Skip to content

Commit 772924e

Browse files
committed
rustc: add Field, FieldPat and TypeBinding to the HIR map.
1 parent b35ea5f commit 772924e

File tree

10 files changed

+108
-47
lines changed

10 files changed

+108
-47
lines changed

src/librustc/hir/map/collector.rs

+36-2
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
433433
self.with_parent(pat.hir_id, |this| {
434434
intravisit::walk_pat(this, pat);
435435
});
436+
self.with_parent(pat.hir_id, |this| match pat.kind {
437+
// FIXME(eddyb) add `visit_field_pat` to `intravisit`.
438+
PatKind::Struct(ref qpath, ref fields, _) => {
439+
this.visit_qpath(qpath, pat.hir_id, pat.span);
440+
for field in fields {
441+
this.insert(field.span, field.hir_id, Node::FieldPat(field));
442+
this.with_parent(field.hir_id, |this| {
443+
this.visit_pat(&field.pat);
444+
});
445+
}
446+
}
447+
_ => intravisit::walk_pat(this, pat),
448+
});
436449
}
437450

438451
fn visit_arm(&mut self, arm: &'hir Arm) {
@@ -456,8 +469,21 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
456469
fn visit_expr(&mut self, expr: &'hir Expr) {
457470
self.insert(expr.span, expr.hir_id, Node::Expr(expr));
458471

459-
self.with_parent(expr.hir_id, |this| {
460-
intravisit::walk_expr(this, expr);
472+
self.with_parent(expr.hir_id, |this| match expr.kind {
473+
// FIXME(eddyb) add `visit_field` to `intravisit`.
474+
ExprKind::Struct(ref qpath, ref fields, ref optional_base) => {
475+
this.visit_qpath(qpath, expr.hir_id, expr.span);
476+
for field in fields {
477+
this.insert(field.span, field.hir_id, Node::Field(field));
478+
this.with_parent(field.hir_id, |this| {
479+
this.visit_expr(&field.expr);
480+
});
481+
}
482+
if let Some(base) = optional_base {
483+
this.visit_expr(base);
484+
}
485+
}
486+
_ => intravisit::walk_expr(this, expr),
461487
});
462488
}
463489

@@ -484,6 +510,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
484510
});
485511
}
486512

513+
fn visit_assoc_type_binding(&mut self, type_binding: &'hir TypeBinding) {
514+
self.insert(type_binding.span, type_binding.hir_id, Node::TypeBinding(type_binding));
515+
516+
self.with_parent(type_binding.hir_id, |this| {
517+
intravisit::walk_assoc_type_binding(this, type_binding);
518+
});
519+
}
520+
487521
fn visit_trait_ref(&mut self, tr: &'hir TraitRef) {
488522
self.insert(tr.path.span, tr.hir_ref_id, Node::TraitRef(tr));
489523

src/librustc/hir/map/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -386,11 +386,14 @@ impl<'hir> Map<'hir> {
386386
Node::AnonConst(_) |
387387
Node::StructField(_) |
388388
Node::Expr(_) |
389+
Node::Field(_) |
389390
Node::Stmt(_) |
390391
Node::PathSegment(_) |
391392
Node::Ty(_) |
393+
Node::TypeBinding(_) |
392394
Node::TraitRef(_) |
393395
Node::Pat(_) |
396+
Node::FieldPat(_) |
394397
Node::Binding(_) |
395398
Node::Local(_) |
396399
Node::Param(_) |
@@ -1075,12 +1078,15 @@ impl<'hir> Map<'hir> {
10751078
Some(Node::StructField(field)) => field.span,
10761079
Some(Node::AnonConst(constant)) => self.body(constant.body).value.span,
10771080
Some(Node::Expr(expr)) => expr.span,
1081+
Some(Node::Field(field)) => field.span,
10781082
Some(Node::Stmt(stmt)) => stmt.span,
10791083
Some(Node::PathSegment(seg)) => seg.ident.span,
10801084
Some(Node::Ty(ty)) => ty.span,
1085+
Some(Node::TypeBinding(type_binding)) => type_binding.span,
10811086
Some(Node::TraitRef(tr)) => tr.path.span,
10821087
Some(Node::Binding(pat)) => pat.span,
10831088
Some(Node::Pat(pat)) => pat.span,
1089+
Some(Node::FieldPat(field)) => field.span,
10841090
Some(Node::Arm(arm)) => arm.span,
10851091
Some(Node::Block(block)) => block.span,
10861092
Some(Node::Ctor(..)) => match self.find(
@@ -1287,12 +1293,15 @@ impl<'a> print::State<'a> {
12871293
Node::Variant(a) => self.print_variant(&a),
12881294
Node::AnonConst(a) => self.print_anon_const(&a),
12891295
Node::Expr(a) => self.print_expr(&a),
1296+
Node::Field(_) => bug!("cannot print Field"),
12901297
Node::Stmt(a) => self.print_stmt(&a),
12911298
Node::PathSegment(a) => self.print_path_segment(&a),
12921299
Node::Ty(a) => self.print_type(&a),
1300+
Node::TypeBinding(_) => bug!("cannot print TypeBinding"),
12931301
Node::TraitRef(a) => self.print_trait_ref(&a),
12941302
Node::Binding(a) |
12951303
Node::Pat(a) => self.print_pat(&a),
1304+
Node::FieldPat(_) => bug!("cannot print FieldPat"),
12961305
Node::Arm(a) => self.print_arm(&a),
12971306
Node::Block(a) => {
12981307
// Containing cbox, will be closed by print-block at `}`.
@@ -1403,6 +1412,9 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
14031412
Some(Node::Expr(_)) => {
14041413
format!("expr {}{}", map.hir_to_pretty_string(id), id_str)
14051414
}
1415+
Some(Node::Field(f)) => {
1416+
format!("field {}: {}{}", f.ident, map.hir_to_pretty_string(f.expr.hir_id), id_str)
1417+
}
14061418
Some(Node::Stmt(_)) => {
14071419
format!("stmt {}{}", map.hir_to_pretty_string(id), id_str)
14081420
}
@@ -1412,6 +1424,9 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
14121424
Some(Node::Ty(_)) => {
14131425
format!("type {}{}", map.hir_to_pretty_string(id), id_str)
14141426
}
1427+
Some(Node::TypeBinding(type_binding)) => {
1428+
format!("type binding {:?}{}", type_binding, id_str)
1429+
}
14151430
Some(Node::TraitRef(_)) => {
14161431
format!("trait_ref {}{}", map.hir_to_pretty_string(id), id_str)
14171432
}
@@ -1421,6 +1436,9 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
14211436
Some(Node::Pat(_)) => {
14221437
format!("pat {}{}", map.hir_to_pretty_string(id), id_str)
14231438
}
1439+
Some(Node::FieldPat(f)) => {
1440+
format!("field pat {}: {}{}", f.ident, map.hir_to_pretty_string(f.pat.hir_id), id_str)
1441+
}
14241442
Some(Node::Param(_)) => {
14251443
format!("param {}{}", map.hir_to_pretty_string(id), id_str)
14261444
}

src/librustc/hir/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2817,12 +2817,15 @@ pub enum Node<'hir> {
28172817
StructField(&'hir StructField),
28182818
AnonConst(&'hir AnonConst),
28192819
Expr(&'hir Expr),
2820+
Field(&'hir Field),
28202821
Stmt(&'hir Stmt),
28212822
PathSegment(&'hir PathSegment),
28222823
Ty(&'hir Ty),
2824+
TypeBinding(&'hir TypeBinding),
28232825
TraitRef(&'hir TraitRef),
28242826
Binding(&'hir Pat),
28252827
Pat(&'hir Pat),
2828+
FieldPat(&'hir FieldPat),
28262829
Arm(&'hir Arm),
28272830
Block(&'hir Block),
28282831
Local(&'hir Local),

src/librustc/middle/resolve_lifetime.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2206,7 +2206,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
22062206
}
22072207

22082208
// Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds).
2209-
Node::ForeignItem(_) | Node::Ty(_) | Node::TraitRef(_) => None,
2209+
Node::ForeignItem(_) |
2210+
Node::Ty(_) |
2211+
Node::TypeBinding(_) |
2212+
Node::TraitRef(_) => None,
22102213
// Everything else (only closures?) doesn't
22112214
// actually enjoy elision in return types.
22122215
_ => {

src/librustc_lint/types.rs

+24-15
Original file line numberDiff line numberDiff line change
@@ -277,14 +277,17 @@ fn lint_int_literal<'a, 'tcx>(
277277
return;
278278
}
279279

280-
let par_id = cx.tcx.hir().get_parent_node(e.hir_id);
281-
if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) {
282-
if let hir::ExprKind::Struct(..) = par_e.kind {
283-
if is_range_literal(cx.sess(), par_e)
284-
&& lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t)
285-
{
286-
// The overflowing literal lint was overridden.
287-
return;
280+
let field_id = cx.tcx.hir().get_parent_node(e.hir_id);
281+
if let Node::Field(field) = cx.tcx.hir().get(field_id) {
282+
let struct_id = cx.tcx.hir().get_parent_node(field.hir_id);
283+
if let Node::Expr(par_e) = cx.tcx.hir().get(struct_id) {
284+
if let hir::ExprKind::Struct(..) = par_e.kind {
285+
if is_range_literal(cx.sess(), par_e)
286+
&& lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t)
287+
{
288+
// The overflowing literal lint was overridden.
289+
return;
290+
}
288291
}
289292
}
290293
}
@@ -317,9 +320,9 @@ fn lint_uint_literal<'a, 'tcx>(
317320
};
318321
if lit_val < min || lit_val > max {
319322
let parent_id = cx.tcx.hir().get_parent_node(e.hir_id);
320-
if let Node::Expr(par_e) = cx.tcx.hir().get(parent_id) {
321-
match par_e.kind {
322-
hir::ExprKind::Cast(..) => {
323+
match cx.tcx.hir().get(parent_id) {
324+
Node::Expr(par_e) => {
325+
if let hir::ExprKind::Cast(..) = par_e.kind {
323326
if let ty::Char = cx.tables.expr_ty(par_e).kind {
324327
let mut err = cx.struct_span_lint(
325328
OVERFLOWING_LITERALS,
@@ -336,15 +339,21 @@ fn lint_uint_literal<'a, 'tcx>(
336339
return;
337340
}
338341
}
339-
hir::ExprKind::Struct(..)
340-
if is_range_literal(cx.sess(), par_e) => {
341-
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
342+
}
343+
Node::Field(field) => {
344+
let struct_id = cx.tcx.hir().get_parent_node(field.hir_id);
345+
if let Node::Expr(par_e) = cx.tcx.hir().get(struct_id) {
346+
if let hir::ExprKind::Struct(..) = par_e.kind {
347+
if is_range_literal(cx.sess(), par_e)
348+
&& lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t)
349+
{
342350
// The overflowing literal lint was overridden.
343351
return;
344352
}
345353
}
346-
_ => {}
354+
}
347355
}
356+
_ => {}
348357
}
349358
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
350359
report_bin_hex_error(cx, e, attr::IntType::UnsignedInt(t), repr_str, lit_val, false);

src/librustc_typeck/check/demand.rs

+8-28
Original file line numberDiff line numberDiff line change
@@ -294,25 +294,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
294294
}
295295
}
296296

297+
// FIXME(eddyb) why does the name say "pattern" when it handles expressions?
297298
crate fn is_hir_id_from_struct_pattern_shorthand_field(
298299
&self,
299300
hir_id: hir::HirId,
300-
sp: Span,
301301
) -> bool {
302-
let cm = self.sess().source_map();
303302
let parent_id = self.tcx.hir().get_parent_node(hir_id);
304303
if let Some(parent) = self.tcx.hir().find(parent_id) {
305304
// Account for fields
306-
if let Node::Expr(hir::Expr {
307-
kind: hir::ExprKind::Struct(_, fields, ..), ..
308-
}) = parent {
309-
if let Ok(src) = cm.span_to_snippet(sp) {
310-
for field in fields {
311-
if field.ident.as_str() == src && field.is_shorthand {
312-
return true;
313-
}
314-
}
315-
}
305+
if let Node::Field(field) = parent {
306+
return field.is_shorthand;
316307
}
317308
}
318309
false
@@ -350,7 +341,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
350341

351342
let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field(
352343
expr.hir_id,
353-
sp,
354344
);
355345

356346
// If the span is from a macro, then it's hard to extract the text
@@ -579,21 +569,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
579569
let can_cast = false;
580570

581571
let mut prefix = String::new();
582-
if let Some(hir::Node::Expr(hir::Expr {
583-
kind: hir::ExprKind::Struct(_, fields, _),
584-
..
585-
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id)) {
586-
// `expr` is a literal field for a struct, only suggest if appropriate
587-
for field in fields {
588-
if field.expr.hir_id == expr.hir_id && field.is_shorthand {
589-
// This is a field literal
590-
prefix = format!("{}: ", field.ident);
591-
break;
592-
}
593-
}
594-
if &prefix == "" {
595-
// Likely a field was meant, but this field wasn't found. Do not suggest anything.
596-
return false;
572+
let parent_id = self.tcx.hir().get_parent_node(expr.hir_id);
573+
if let Some(hir::Node::Field(field)) = self.tcx.hir().find(parent_id) {
574+
if field.is_shorthand {
575+
// This is a field literal
576+
prefix = format!("{}: ", field.ident);
597577
}
598578
}
599579
if let hir::ExprKind::Call(path, args) = &expr.kind {

src/librustc_typeck/check/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4408,7 +4408,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
44084408
} else if !self.check_for_cast(err, expr, found, expected) {
44094409
let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field(
44104410
expr.hir_id,
4411-
expr.span,
44124411
);
44134412
let methods = self.get_conversion_methods(expr.span, expected, found);
44144413
if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {

src/test/ui/proc-macro/span-preservation.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ error[E0308]: mismatched types
2626
|
2727
LL | let x = Foo { a: 10isize };
2828
| ^^^^^^^ expected usize, found isize
29+
|
30+
help: change the type of the numeric literal from `isize` to `usize`
31+
|
32+
LL | let x = Foo { a: 10usize };
33+
| ^^^^^^^
2934

3035
error[E0560]: struct `c::Foo` has no field named `b`
3136
--> $DIR/span-preservation.rs:35:26

src/test/ui/range/range-1.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error[E0308]: mismatched types
33
|
44
LL | let _ = 0u32..10i32;
55
| ^^^^^ expected u32, found i32
6+
|
7+
help: change the type of the numeric literal from `i32` to `u32`
8+
|
9+
LL | let _ = 0u32..10u32;
10+
| ^^^^^
611

712
error[E0277]: the trait bound `bool: std::iter::Step` is not satisfied
813
--> $DIR/range-1.rs:9:14

src/test/ui/structs/struct-path-self-type-mismatch.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error[E0308]: mismatched types
33
|
44
LL | Self { inner: 1.5f32 };
55
| ^^^^^^ expected i32, found f32
6+
|
7+
help: change the type of the numeric literal from `f32` to `i32`
8+
|
9+
LL | Self { inner: 1i32 };
10+
| ^^^^
611

712
error[E0308]: mismatched types
813
--> $DIR/struct-path-self-type-mismatch.rs:15:20

0 commit comments

Comments
 (0)