diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 920635d838738..b338e5471171c 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -803,11 +803,9 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( visitor.visit_lifetime(lifetime); walk_list!(visitor, visit_param_bound, bounds); } - &WherePredicate::EqPredicate(WhereEqPredicate{hir_id, - ref lhs_ty, + &WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty, ref rhs_ty, ..}) => { - visitor.visit_id(hir_id); visitor.visit_ty(lhs_ty); visitor.visit_ty(rhs_ty); } diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index f1b999cdd6f0f..b8da117d73fe3 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -1442,13 +1442,11 @@ impl LoweringContext<'_> { bounds: self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), }), WherePredicate::EqPredicate(WhereEqPredicate { - id, ref lhs_ty, ref rhs_ty, span, }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - hir_id: self.lower_node_id(id), lhs_ty: self.lower_ty(lhs_ty, ImplTraitContext::disallowed()), rhs_ty: self.lower_ty(rhs_ty, ImplTraitContext::disallowed()), span, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index b0fa844c81881..1be9fc077792e 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -433,6 +433,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.with_parent(pat.hir_id, |this| { intravisit::walk_pat(this, pat); }); + self.with_parent(pat.hir_id, |this| match pat.kind { + // FIXME(eddyb) add `visit_field_pat` to `intravisit`. + PatKind::Struct(ref qpath, ref fields, _) => { + this.visit_qpath(qpath, pat.hir_id, pat.span); + for field in fields { + this.insert(field.span, field.hir_id, Node::FieldPat(field)); + this.with_parent(field.hir_id, |this| { + this.visit_pat(&field.pat); + }); + } + } + _ => intravisit::walk_pat(this, pat), + }); } fn visit_arm(&mut self, arm: &'hir Arm) { @@ -456,8 +469,21 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_expr(&mut self, expr: &'hir Expr) { self.insert(expr.span, expr.hir_id, Node::Expr(expr)); - self.with_parent(expr.hir_id, |this| { - intravisit::walk_expr(this, expr); + self.with_parent(expr.hir_id, |this| match expr.kind { + // FIXME(eddyb) add `visit_field` to `intravisit`. + ExprKind::Struct(ref qpath, ref fields, ref optional_base) => { + this.visit_qpath(qpath, expr.hir_id, expr.span); + for field in fields { + this.insert(field.span, field.hir_id, Node::Field(field)); + this.with_parent(field.hir_id, |this| { + this.visit_expr(&field.expr); + }); + } + if let Some(base) = optional_base { + this.visit_expr(base); + } + } + _ => intravisit::walk_expr(this, expr), }); } @@ -484,6 +510,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } + fn visit_assoc_type_binding(&mut self, type_binding: &'hir TypeBinding) { + self.insert(type_binding.span, type_binding.hir_id, Node::TypeBinding(type_binding)); + + self.with_parent(type_binding.hir_id, |this| { + intravisit::walk_assoc_type_binding(this, type_binding); + }); + } + fn visit_trait_ref(&mut self, tr: &'hir TraitRef) { self.insert(tr.path.span, tr.hir_ref_id, Node::TraitRef(tr)); @@ -551,7 +585,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_struct_field(&mut self, field: &'hir StructField) { - self.insert(field.span, field.hir_id, Node::Field(field)); + self.insert(field.span, field.hir_id, Node::StructField(field)); self.with_parent(field.hir_id, |this| { intravisit::walk_struct_field(this, field); }); diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index b66c2ce1178a4..4cefa2dd96241 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -1,170 +1,44 @@ -use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; -use crate::hir::{self, intravisit, HirId, ItemLocalId}; -use crate::hir::itemlikevisit::ItemLikeVisitor; -use rustc_data_structures::fx::FxHashSet; +use crate::hir::def_id::{DefId, DefIndex}; +use crate::hir::{self, HirId}; use rustc_data_structures::sync::{Lock, ParallelIterator, par_iter}; +use std::collections::BTreeMap; pub fn check_crate(hir_map: &hir::map::Map<'_>) { hir_map.dep_graph.assert_ignored(); let errors = Lock::new(Vec::new()); - par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| { - let local_def_id = hir_map.local_def_id(*module_id); - hir_map.visit_item_likes_in_module(local_def_id, &mut OuterVisitor { - hir_map, - errors: &errors, - }); + par_iter(0..hir_map.map.len()).for_each(|owner| { + let owner = DefIndex::from(owner); + let local_map = &hir_map.map[owner]; + + // Collect the missing `ItemLocalId`s. + let missing: Vec<_> = local_map + .iter_enumerated() + .filter(|(_, entry)| entry.is_none()) + .map(|(local_id, _)| local_id) + .collect(); + + if !missing.is_empty() { + let present: BTreeMap<_, _> = local_map + .iter_enumerated() + .filter(|(_, entry)| entry.is_some()) + .map(|(local_id, _)| { + (local_id, hir_map.node_to_string(HirId { owner, local_id })) + }) + .collect(); + + errors.lock().push(format!( + "{}:\n missing IDs = {:?}\n present IDs = {:#?}", + hir_map.def_path(DefId::local(owner)).to_string_no_crate(), + missing, + present, + )); + } }); let errors = errors.into_inner(); - if !errors.is_empty() { - let message = errors - .iter() - .fold(String::new(), |s1, s2| s1 + "\n" + s2); - bug!("{}", message); - } -} - -struct HirIdValidator<'a, 'hir> { - hir_map: &'a hir::map::Map<'hir>, - owner_def_index: Option, - hir_ids_seen: FxHashSet, - errors: &'a Lock>, -} - -struct OuterVisitor<'a, 'hir> { - hir_map: &'a hir::map::Map<'hir>, - errors: &'a Lock>, -} - -impl<'a, 'hir> OuterVisitor<'a, 'hir> { - fn new_inner_visitor(&self, - hir_map: &'a hir::map::Map<'hir>) - -> HirIdValidator<'a, 'hir> { - HirIdValidator { - hir_map, - owner_def_index: None, - hir_ids_seen: Default::default(), - errors: self.errors, - } - } -} - -impl<'a, 'hir> ItemLikeVisitor<'hir> for OuterVisitor<'a, 'hir> { - fn visit_item(&mut self, i: &'hir hir::Item) { - let mut inner_visitor = self.new_inner_visitor(self.hir_map); - inner_visitor.check(i.hir_id, |this| intravisit::walk_item(this, i)); - } - - fn visit_trait_item(&mut self, i: &'hir hir::TraitItem) { - let mut inner_visitor = self.new_inner_visitor(self.hir_map); - inner_visitor.check(i.hir_id, |this| intravisit::walk_trait_item(this, i)); - } - - fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) { - let mut inner_visitor = self.new_inner_visitor(self.hir_map); - inner_visitor.check(i.hir_id, |this| intravisit::walk_impl_item(this, i)); - } -} - -impl<'a, 'hir> HirIdValidator<'a, 'hir> { - #[cold] - #[inline(never)] - fn error(&self, f: impl FnOnce() -> String) { - self.errors.lock().push(f()); - } - - fn check)>(&mut self, - hir_id: HirId, - walk: F) { - assert!(self.owner_def_index.is_none()); - let owner_def_index = self.hir_map.local_def_id(hir_id).index; - self.owner_def_index = Some(owner_def_index); - walk(self); - - if owner_def_index == CRATE_DEF_INDEX { - return; - } - - // There's always at least one entry for the owning item itself - let max = self.hir_ids_seen - .iter() - .map(|local_id| local_id.as_usize()) - .max() - .expect("owning item has no entry"); - - if max != self.hir_ids_seen.len() - 1 { - // Collect the missing ItemLocalIds - let missing: Vec<_> = (0 ..= max as u32) - .filter(|&i| !self.hir_ids_seen.contains(&ItemLocalId::from_u32(i))) - .collect(); - - // Try to map those to something more useful - let mut missing_items = Vec::with_capacity(missing.len()); - - for local_id in missing { - let hir_id = HirId { - owner: owner_def_index, - local_id: ItemLocalId::from_u32(local_id), - }; - - trace!("missing hir id {:#?}", hir_id); - - missing_items.push(format!("[local_id: {}, node:{}]", - local_id, - self.hir_map.node_to_string(hir_id))); - } - self.error(|| format!( - "ItemLocalIds not assigned densely in {}. \ - Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}", - self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(), - max, - missing_items, - self.hir_ids_seen - .iter() - .map(|&local_id| HirId { - owner: owner_def_index, - local_id, - }) - .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h))) - .collect::>())); - } - } -} - -impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { - - fn nested_visit_map<'this>(&'this mut self) - -> intravisit::NestedVisitorMap<'this, 'hir> { - intravisit::NestedVisitorMap::OnlyBodies(self.hir_map) - } - - fn visit_id(&mut self, hir_id: HirId) { - let owner = self.owner_def_index.expect("no owner_def_index"); - - if hir_id == hir::DUMMY_HIR_ID { - self.error(|| format!("HirIdValidator: HirId {:?} is invalid", - self.hir_map.node_to_string(hir_id))); - return; - } - - if owner != hir_id.owner { - self.error(|| format!( - "HirIdValidator: The recorded owner of {} is {} instead of {}", - self.hir_map.node_to_string(hir_id), - self.hir_map.def_path(DefId::local(hir_id.owner)).to_string_no_crate(), - self.hir_map.def_path(DefId::local(owner)).to_string_no_crate())); - } - - self.hir_ids_seen.insert(hir_id.local_id); - } - - fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef) { - // Explicitly do nothing here. ImplItemRefs contain hir::Visibility - // values that actually belong to an ImplItem instead of the ItemKind::Impl - // we are currently in. So for those it's correct that they have a - // different owner. + bug!("`ItemLocalId`s not assigned densely in:\n{}", errors.join("\n")); } } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index acadd77cc36c0..ff7a850ead54e 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -384,13 +384,16 @@ impl<'hir> Map<'hir> { DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data)) } Node::AnonConst(_) | - Node::Field(_) | + Node::StructField(_) | Node::Expr(_) | + Node::Field(_) | Node::Stmt(_) | Node::PathSegment(_) | Node::Ty(_) | + Node::TypeBinding(_) | Node::TraitRef(_) | Node::Pat(_) | + Node::FieldPat(_) | Node::Binding(_) | Node::Local(_) | Node::Param(_) | @@ -990,7 +993,7 @@ impl<'hir> Map<'hir> { Node::ImplItem(ii) => ii.ident.name, Node::TraitItem(ti) => ti.ident.name, Node::Variant(v) => v.ident.name, - Node::Field(f) => f.ident.name, + Node::StructField(f) => f.ident.name, Node::Lifetime(lt) => lt.name.ident().name, Node::GenericParam(param) => param.name.ident().name, Node::Binding(&Pat { kind: PatKind::Binding(_, _, l, _), .. }) => l.name, @@ -1011,7 +1014,7 @@ impl<'hir> Map<'hir> { Some(Node::TraitItem(ref ti)) => Some(&ti.attrs[..]), Some(Node::ImplItem(ref ii)) => Some(&ii.attrs[..]), Some(Node::Variant(ref v)) => Some(&v.attrs[..]), - Some(Node::Field(ref f)) => Some(&f.attrs[..]), + Some(Node::StructField(ref f)) => Some(&f.attrs[..]), Some(Node::Expr(ref e)) => Some(&*e.attrs), Some(Node::Stmt(ref s)) => Some(s.kind.attrs()), Some(Node::Arm(ref a)) => Some(&*a.attrs), @@ -1072,15 +1075,18 @@ impl<'hir> Map<'hir> { Some(Node::TraitItem(trait_method)) => trait_method.span, Some(Node::ImplItem(impl_item)) => impl_item.span, Some(Node::Variant(variant)) => variant.span, - Some(Node::Field(field)) => field.span, + Some(Node::StructField(field)) => field.span, Some(Node::AnonConst(constant)) => self.body(constant.body).value.span, Some(Node::Expr(expr)) => expr.span, + Some(Node::Field(field)) => field.span, Some(Node::Stmt(stmt)) => stmt.span, Some(Node::PathSegment(seg)) => seg.ident.span, Some(Node::Ty(ty)) => ty.span, + Some(Node::TypeBinding(type_binding)) => type_binding.span, Some(Node::TraitRef(tr)) => tr.path.span, Some(Node::Binding(pat)) => pat.span, Some(Node::Pat(pat)) => pat.span, + Some(Node::FieldPat(field)) => field.span, Some(Node::Arm(arm)) => arm.span, Some(Node::Block(block)) => block.span, Some(Node::Ctor(..)) => match self.find( @@ -1195,7 +1201,7 @@ impl<'a> NodesMatchingSuffix<'a> { Some(Node::TraitItem(n)) => n.name(), Some(Node::ImplItem(n)) => n.name(), Some(Node::Variant(n)) => n.name(), - Some(Node::Field(n)) => n.name(), + Some(Node::StructField(n)) => n.name(), _ => return false, }; self.matches_names(self.map.get_parent_item(hir), name) @@ -1287,12 +1293,15 @@ impl<'a> print::State<'a> { Node::Variant(a) => self.print_variant(&a), Node::AnonConst(a) => self.print_anon_const(&a), Node::Expr(a) => self.print_expr(&a), + Node::Field(_) => bug!("cannot print Field"), Node::Stmt(a) => self.print_stmt(&a), Node::PathSegment(a) => self.print_path_segment(&a), Node::Ty(a) => self.print_type(&a), + Node::TypeBinding(_) => bug!("cannot print TypeBinding"), Node::TraitRef(a) => self.print_trait_ref(&a), Node::Binding(a) | Node::Pat(a) => self.print_pat(&a), + Node::FieldPat(_) => bug!("cannot print FieldPat"), Node::Arm(a) => self.print_arm(&a), Node::Block(a) => { // Containing cbox, will be closed by print-block at `}`. @@ -1304,7 +1313,7 @@ impl<'a> print::State<'a> { Node::Lifetime(a) => self.print_lifetime(&a), Node::Visibility(a) => self.print_visibility(&a), Node::GenericParam(_) => bug!("cannot print Node::GenericParam"), - Node::Field(_) => bug!("cannot print StructField"), + Node::StructField(_) => bug!("cannot print StructField"), // These cases do not carry enough information in the // `hir_map` to reconstruct their full structure for pretty // printing. @@ -1392,8 +1401,8 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { variant.ident, path_str(), id_str) } - Some(Node::Field(ref field)) => { - format!("field {} in {}{}", + Some(Node::StructField(ref field)) => { + format!("struct field {} in {}{}", field.ident, path_str(), id_str) } @@ -1403,6 +1412,9 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { Some(Node::Expr(_)) => { format!("expr {}{}", map.hir_to_pretty_string(id), id_str) } + Some(Node::Field(f)) => { + format!("field {}: {}{}", f.ident, map.hir_to_pretty_string(f.expr.hir_id), id_str) + } Some(Node::Stmt(_)) => { format!("stmt {}{}", map.hir_to_pretty_string(id), id_str) } @@ -1412,6 +1424,9 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { Some(Node::Ty(_)) => { format!("type {}{}", map.hir_to_pretty_string(id), id_str) } + Some(Node::TypeBinding(type_binding)) => { + format!("type binding {:?}{}", type_binding, id_str) + } Some(Node::TraitRef(_)) => { format!("trait_ref {}{}", map.hir_to_pretty_string(id), id_str) } @@ -1421,6 +1436,9 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { Some(Node::Pat(_)) => { format!("pat {}{}", map.hir_to_pretty_string(id), id_str) } + Some(Node::FieldPat(f)) => { + format!("field pat {}: {}{}", f.ident, map.hir_to_pretty_string(f.pat.hir_id), id_str) + } Some(Node::Param(_)) => { format!("param {}{}", map.hir_to_pretty_string(id), id_str) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 0edc41e6b4881..19f0ff8b5954d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -721,7 +721,6 @@ pub struct WhereRegionPredicate { /// An equality predicate (e.g., `T = int`); currently unsupported. #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct WhereEqPredicate { - pub hir_id: HirId, pub span: Span, pub lhs_ty: P, pub rhs_ty: P, @@ -2814,15 +2813,18 @@ pub enum Node<'hir> { TraitItem(&'hir TraitItem), ImplItem(&'hir ImplItem), Variant(&'hir Variant), - Field(&'hir StructField), + StructField(&'hir StructField), AnonConst(&'hir AnonConst), Expr(&'hir Expr), + Field(&'hir Field), Stmt(&'hir Stmt), PathSegment(&'hir PathSegment), Ty(&'hir Ty), + TypeBinding(&'hir TypeBinding), TraitRef(&'hir TraitRef), Binding(&'hir Pat), Pat(&'hir Pat), + FieldPat(&'hir FieldPat), Arm(&'hir Arm), Block(&'hir Block), Local(&'hir Local), diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 8be64bf64b5e9..37e1779760800 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -320,7 +320,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { Node::ForeignItem(_) | Node::Variant(_) | Node::Ctor(..) | - Node::Field(_) | + Node::StructField(_) | Node::Ty(_) | Node::MacroDef(_) => {} _ => { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 488d6332f7e39..38fd2691fafa1 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -2206,7 +2206,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } // Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds). - Node::ForeignItem(_) | Node::Ty(_) | Node::TraitRef(_) => None, + Node::ForeignItem(_) | + Node::Ty(_) | + Node::TypeBinding(_) | + Node::TraitRef(_) => None, // Everything else (only closures?) doesn't // actually enjoy elision in return types. _ => { diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index f2ad400d5dd37..e92812d18b165 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -277,14 +277,17 @@ fn lint_int_literal<'a, 'tcx>( return; } - let par_id = cx.tcx.hir().get_parent_node(e.hir_id); - if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) { - if let hir::ExprKind::Struct(..) = par_e.kind { - if is_range_literal(cx.sess(), par_e) - && lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t) - { - // The overflowing literal lint was overridden. - return; + let field_id = cx.tcx.hir().get_parent_node(e.hir_id); + if let Node::Field(field) = cx.tcx.hir().get(field_id) { + let struct_id = cx.tcx.hir().get_parent_node(field.hir_id); + if let Node::Expr(par_e) = cx.tcx.hir().get(struct_id) { + if let hir::ExprKind::Struct(..) = par_e.kind { + if is_range_literal(cx.sess(), par_e) + && lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t) + { + // The overflowing literal lint was overridden. + return; + } } } } @@ -317,9 +320,9 @@ fn lint_uint_literal<'a, 'tcx>( }; if lit_val < min || lit_val > max { let parent_id = cx.tcx.hir().get_parent_node(e.hir_id); - if let Node::Expr(par_e) = cx.tcx.hir().get(parent_id) { - match par_e.kind { - hir::ExprKind::Cast(..) => { + match cx.tcx.hir().get(parent_id) { + Node::Expr(par_e) => { + if let hir::ExprKind::Cast(..) = par_e.kind { if let ty::Char = cx.tables.expr_ty(par_e).kind { let mut err = cx.struct_span_lint( OVERFLOWING_LITERALS, @@ -336,15 +339,21 @@ fn lint_uint_literal<'a, 'tcx>( return; } } - hir::ExprKind::Struct(..) - if is_range_literal(cx.sess(), par_e) => { - if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) { + } + Node::Field(field) => { + let struct_id = cx.tcx.hir().get_parent_node(field.hir_id); + if let Node::Expr(par_e) = cx.tcx.hir().get(struct_id) { + if let hir::ExprKind::Struct(..) = par_e.kind { + if is_range_literal(cx.sess(), par_e) + && lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) + { // The overflowing literal lint was overridden. return; } } - _ => {} + } } + _ => {} } if let Some(repr_str) = get_bin_hex_repr(cx, lit) { report_bin_hex_error(cx, e, attr::IntType::UnsignedInt(t), repr_str, lit_val, false); diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 68b33331a1ffb..f5447686563ea 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -627,7 +627,7 @@ fn annotate_struct_field( let node = tcx.hir().find(hir_id)?; // Now we're dealing with the actual struct that we're going to suggest a change to, // we can expect a field that is an immutable reference to a type. - if let hir::Node::Field(field) = node { + if let hir::Node::StructField(field) = node { if let hir::TyKind::Rptr(lifetime, hir::MutTy { mutbl: hir::Mutability::MutImmutable, ref ty diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 309e73f57c964..7a48f72134cb1 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -294,25 +294,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + // FIXME(eddyb) why does the name say "pattern" when it handles expressions? crate fn is_hir_id_from_struct_pattern_shorthand_field( &self, hir_id: hir::HirId, - sp: Span, ) -> bool { - let cm = self.sess().source_map(); let parent_id = self.tcx.hir().get_parent_node(hir_id); if let Some(parent) = self.tcx.hir().find(parent_id) { // Account for fields - if let Node::Expr(hir::Expr { - kind: hir::ExprKind::Struct(_, fields, ..), .. - }) = parent { - if let Ok(src) = cm.span_to_snippet(sp) { - for field in fields { - if field.ident.as_str() == src && field.is_shorthand { - return true; - } - } - } + if let Node::Field(field) = parent { + return field.is_shorthand; } } false @@ -350,7 +341,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field( expr.hir_id, - sp, ); // 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> { let can_cast = false; let mut prefix = String::new(); - if let Some(hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Struct(_, fields, _), - .. - })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id)) { - // `expr` is a literal field for a struct, only suggest if appropriate - for field in fields { - if field.expr.hir_id == expr.hir_id && field.is_shorthand { - // This is a field literal - prefix = format!("{}: ", field.ident); - break; - } - } - if &prefix == "" { - // Likely a field was meant, but this field wasn't found. Do not suggest anything. - return false; + let parent_id = self.tcx.hir().get_parent_node(expr.hir_id); + if let Some(hir::Node::Field(field)) = self.tcx.hir().find(parent_id) { + if field.is_shorthand { + // This is a field literal + prefix = format!("{}: ", field.ident); } } if let hir::ExprKind::Call(path, args) = &expr.kind { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 26f040810462f..12dddd0831ce6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4408,7 +4408,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if !self.check_for_cast(err, expr, found, expected) { let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field( expr.hir_id, - expr.span, ); let methods = self.get_conversion_methods(expr.span, expected, found); if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index ffe034759a80c..baf1ee3f54cc4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -902,7 +902,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { let node = tcx.hir().get(hir_id); let parent_def_id = match node { Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) | - Node::Ctor(..) | Node::Field(_) => { + Node::Ctor(..) | Node::StructField(_) => { let parent_id = tcx.hir().get_parent_item(hir_id); Some(tcx.hir().local_def_id(parent_id)) } @@ -1358,7 +1358,7 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option icx.to_ty(&field.ty), + Node::StructField(field) => icx.to_ty(&field.ty), Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., gen), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8af38507b48d1..f4a3c93bfec2a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -457,7 +457,6 @@ pub struct WhereRegionPredicate { /// E.g., `T = int`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereEqPredicate { - pub id: NodeId, pub span: Span, pub lhs_ty: P, pub rhs_ty: P, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 60ee17d09b755..d5121250cc458 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -794,8 +794,7 @@ pub fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis)); } WherePredicate::EqPredicate(ep) => { - let WhereEqPredicate { id, span, lhs_ty, rhs_ty } = ep; - vis.visit_id(id); + let WhereEqPredicate { span, lhs_ty, rhs_ty } = ep; vis.visit_span(span); vis.visit_ty(lhs_ty); vis.visit_ty(rhs_ty); diff --git a/src/libsyntax/parse/parser/generics.rs b/src/libsyntax/parse/parser/generics.rs index 51caae69c86a4..60fce266671d1 100644 --- a/src/libsyntax/parse/parser/generics.rs +++ b/src/libsyntax/parse/parser/generics.rs @@ -271,7 +271,6 @@ impl<'a> Parser<'a> { span: lo.to(self.prev_span), lhs_ty: ty, rhs_ty, - id: ast::DUMMY_NODE_ID, } )) } else { diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 2e5ae235893cb..e934d57c6a712 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -581,7 +581,6 @@ impl<'a> TraitDef<'a> { } ast::WherePredicate::EqPredicate(ref we) => { ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - id: ast::DUMMY_NODE_ID, span: self.span, lhs_ty: we.lhs_ty.clone(), rhs_ty: we.rhs_ty.clone(), diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index 0290f4b2cc982..541267986a510 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -26,6 +26,11 @@ error[E0308]: mismatched types | LL | let x = Foo { a: 10isize }; | ^^^^^^^ expected usize, found isize + | +help: change the type of the numeric literal from `isize` to `usize` + | +LL | let x = Foo { a: 10usize }; + | ^^^^^^^ error[E0560]: struct `c::Foo` has no field named `b` --> $DIR/span-preservation.rs:35:26 diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr index bbc2abea51df7..a21c9e9c17f42 100644 --- a/src/test/ui/range/range-1.stderr +++ b/src/test/ui/range/range-1.stderr @@ -3,6 +3,11 @@ error[E0308]: mismatched types | LL | let _ = 0u32..10i32; | ^^^^^ expected u32, found i32 + | +help: change the type of the numeric literal from `i32` to `u32` + | +LL | let _ = 0u32..10u32; + | ^^^^^ error[E0277]: the trait bound `bool: std::iter::Step` is not satisfied --> $DIR/range-1.rs:9:14 diff --git a/src/test/ui/structs/struct-path-self-type-mismatch.stderr b/src/test/ui/structs/struct-path-self-type-mismatch.stderr index 687d610baf8cf..9a003fea0532e 100644 --- a/src/test/ui/structs/struct-path-self-type-mismatch.stderr +++ b/src/test/ui/structs/struct-path-self-type-mismatch.stderr @@ -3,6 +3,11 @@ error[E0308]: mismatched types | LL | Self { inner: 1.5f32 }; | ^^^^^^ expected i32, found f32 + | +help: change the type of the numeric literal from `f32` to `i32` + | +LL | Self { inner: 1i32 }; + | ^^^^ error[E0308]: mismatched types --> $DIR/struct-path-self-type-mismatch.rs:15:20