From bfa2ef62a1d283eea2779ce0a4676a855536bfcd Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 24 Mar 2017 23:03:15 +0000 Subject: [PATCH] Hygienize `librustc_typeck`. --- src/librustc/hir/lowering.rs | 47 ++++++++++++-------- src/librustc/hir/map/def_collector.rs | 7 ++- src/librustc/hir/map/definitions.rs | 23 +++++++++- src/librustc/hir/map/mod.rs | 7 +-- src/librustc/ty/mod.rs | 48 ++++++++++++++------- src/librustc_const_eval/check_match.rs | 6 +-- src/librustc_resolve/lib.rs | 2 +- src/librustc_resolve/macros.rs | 14 ++++-- src/librustc_typeck/astconv.rs | 3 +- src/librustc_typeck/check/method/mod.rs | 3 +- src/librustc_typeck/check/method/probe.rs | 16 ++++++- src/librustc_typeck/check/method/suggest.rs | 4 +- src/librustc_typeck/check/mod.rs | 31 +++++++++---- src/libsyntax_pos/hygiene.rs | 20 ++++++++- 14 files changed, 170 insertions(+), 61 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 1e4114add81..7ff7ad6a90e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -47,7 +47,7 @@ use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX}; use hir::def::{Def, PathResolution}; use rustc_data_structures::indexed_vec::IndexVec; use session::Session; -use util::nodemap::{DefIdMap, NodeMap}; +use util::nodemap::{DefIdMap, FxHashMap, NodeMap}; use std::collections::BTreeMap; use std::fmt::Debug; @@ -77,6 +77,7 @@ pub struct LoweringContext<'a> { // a definition, then we can properly create the def id. parent_def: Option, resolver: &'a mut Resolver, + name_map: FxHashMap, /// The items being lowered are collected here. items: BTreeMap, @@ -126,6 +127,7 @@ pub fn lower_crate(sess: &Session, sess: sess, parent_def: None, resolver: resolver, + name_map: FxHashMap(), items: BTreeMap::new(), trait_items: BTreeMap::new(), impl_items: BTreeMap::new(), @@ -495,6 +497,14 @@ impl<'a> LoweringContext<'a> { } } + fn lower_ident(&mut self, ident: Ident) -> Name { + let ident = ident.modern(); + if ident.ctxt == SyntaxContext::empty() { + return ident.name; + } + *self.name_map.entry(ident).or_insert_with(|| Symbol::from_ident(ident)) + } + fn lower_opt_sp_ident(&mut self, o_id: Option>) -> Option> { o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name)) } @@ -546,7 +556,7 @@ impl<'a> LoweringContext<'a> { fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding { hir::TypeBinding { id: self.lower_node_id(b.id), - name: b.ident.name, + name: self.lower_ident(b.ident), ty: self.lower_ty(&b.ty), span: b.span, } @@ -844,7 +854,7 @@ impl<'a> LoweringContext<'a> { } hir::PathSegment { - name: segment.identifier.name, + name: self.lower_ident(segment.identifier), parameters: parameters, } } @@ -941,7 +951,7 @@ impl<'a> LoweringContext<'a> { } fn lower_ty_param(&mut self, tp: &TyParam, add_bounds: &[TyParamBound]) -> hir::TyParam { - let mut name = tp.ident.name; + let mut name = self.lower_ident(tp.ident); // Don't expose `Self` (recovered "keyword used as ident" parse error). // `rustc::ty` expects `Self` to be only used for a trait's `Self`. @@ -1137,7 +1147,11 @@ impl<'a> LoweringContext<'a> { hir::StructField { span: f.span, id: self.lower_node_id(f.id), - name: f.ident.map(|ident| ident.name).unwrap_or(Symbol::intern(&index.to_string())), + name: self.lower_ident(match f.ident { + Some(ident) => ident, + // FIXME(jseyfried) positional field hygiene + None => Ident { name: Symbol::intern(&index.to_string()), ctxt: f.span.ctxt }, + }), vis: self.lower_visibility(&f.vis, None), ty: self.lower_ty(&f.ty), attrs: self.lower_attrs(&f.attrs), @@ -1146,7 +1160,7 @@ impl<'a> LoweringContext<'a> { fn lower_field(&mut self, f: &Field) -> hir::Field { hir::Field { - name: respan(f.ident.span, f.ident.node.name), + name: respan(f.ident.span, self.lower_ident(f.ident.node)), expr: P(self.lower_expr(&f.expr)), span: f.span, is_shorthand: f.is_shorthand, @@ -1371,7 +1385,7 @@ impl<'a> LoweringContext<'a> { self.with_parent_def(i.id, |this| { hir::TraitItem { id: this.lower_node_id(i.id), - name: i.ident.name, + name: this.lower_ident(i.ident), attrs: this.lower_attrs(&i.attrs), node: match i.node { TraitItemKind::Const(ref ty, ref default) => { @@ -1421,7 +1435,7 @@ impl<'a> LoweringContext<'a> { }; hir::TraitItemRef { id: hir::TraitItemId { node_id: i.id }, - name: i.ident.name, + name: self.lower_ident(i.ident), span: i.span, defaultness: self.lower_defaultness(Defaultness::Default, has_default), kind: kind, @@ -1432,7 +1446,7 @@ impl<'a> LoweringContext<'a> { self.with_parent_def(i.id, |this| { hir::ImplItem { id: this.lower_node_id(i.id), - name: i.ident.name, + name: this.lower_ident(i.ident), attrs: this.lower_attrs(&i.attrs), vis: this.lower_visibility(&i.vis, None), defaultness: this.lower_defaultness(i.defaultness, true /* [1] */), @@ -1461,7 +1475,7 @@ impl<'a> LoweringContext<'a> { fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef { hir::ImplItemRef { id: hir::ImplItemId { node_id: i.id }, - name: i.ident.name, + name: self.lower_ident(i.ident), span: i.span, vis: self.lower_visibility(&i.vis, Some(i.id)), defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), @@ -1655,7 +1669,7 @@ impl<'a> LoweringContext<'a> { Spanned { span: f.span, node: hir::FieldPat { - name: f.node.ident.name, + name: self.lower_ident(f.node.ident), pat: self.lower_pat(&f.node.pat), is_shorthand: f.node.is_shorthand, }, @@ -1825,7 +1839,7 @@ impl<'a> LoweringContext<'a> { ExprKind::MethodCall(i, ref tps, ref args) => { let tps = tps.iter().map(|x| self.lower_ty(x)).collect(); let args = args.iter().map(|x| self.lower_expr(x)).collect(); - hir::ExprMethodCall(respan(i.span, i.node.name), tps, args) + hir::ExprMethodCall(respan(i.span, self.lower_ident(i.node)), tps, args) } ExprKind::Binary(binop, ref lhs, ref rhs) => { let binop = self.lower_binop(binop); @@ -1924,7 +1938,8 @@ impl<'a> LoweringContext<'a> { P(self.lower_expr(er))) } ExprKind::Field(ref el, ident) => { - hir::ExprField(P(self.lower_expr(el)), respan(ident.span, ident.node.name)) + hir::ExprField(P(self.lower_expr(el)), + respan(ident.span, self.lower_ident(ident.node))) } ExprKind::TupField(ref el, ident) => { hir::ExprTupField(P(self.lower_expr(el)), ident) @@ -2643,10 +2658,8 @@ impl<'a> LoweringContext<'a> { let def_id = { let defs = self.resolver.definitions(); let def_path_data = DefPathData::Binding(name.as_str()); - let def_index = defs.create_def_with_parent(parent_def, - id, - def_path_data, - REGULAR_SPACE); + let def_index = defs + .create_def_with_parent(parent_def, id, def_path_data, REGULAR_SPACE, Mark::root()); DefId::local(def_index) }; diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 7ff5152c71a..88750ce3acd 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -22,6 +22,7 @@ use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE}; pub struct DefCollector<'a> { definitions: &'a mut Definitions, parent_def: Option, + expansion: Mark, pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>, } @@ -32,9 +33,10 @@ pub struct MacroInvocationData { } impl<'a> DefCollector<'a> { - pub fn new(definitions: &'a mut Definitions) -> Self { + pub fn new(definitions: &'a mut Definitions, expansion: Mark) -> Self { DefCollector { definitions: definitions, + expansion: expansion, parent_def: None, visit_macro_invoc: None, } @@ -54,7 +56,8 @@ impl<'a> DefCollector<'a> { -> DefIndex { let parent_def = self.parent_def.unwrap(); debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); - self.definitions.create_def_with_parent(parent_def, node_id, data, address_space) + self.definitions + .create_def_with_parent(parent_def, node_id, data, address_space, self.expansion) } pub fn with_parent(&mut self, parent_def: DefIndex, f: F) { diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 9537b40b28a..7d9f92e17b9 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -24,6 +24,7 @@ use serialize::{Encodable, Decodable, Encoder, Decoder}; use std::fmt::Write; use std::hash::Hash; use syntax::ast; +use syntax::ext::hygiene::Mark; use syntax::symbol::{Symbol, InternedString}; use ty::TyCtxt; use util::nodemap::NodeMap; @@ -180,6 +181,8 @@ pub struct Definitions { node_to_def_index: NodeMap, def_index_to_node: [Vec; 2], pub(super) node_to_hir_id: IndexVec, + macro_def_scopes: FxHashMap, + expansions: FxHashMap, } // Unfortunately we have to provide a manual impl of Clone because of the @@ -194,6 +197,8 @@ impl Clone for Definitions { self.def_index_to_node[1].clone(), ], node_to_hir_id: self.node_to_hir_id.clone(), + macro_def_scopes: self.macro_def_scopes.clone(), + expansions: self.expansions.clone(), } } } @@ -379,6 +384,8 @@ impl Definitions { node_to_def_index: NodeMap(), def_index_to_node: [vec![], vec![]], node_to_hir_id: IndexVec::new(), + macro_def_scopes: FxHashMap(), + expansions: FxHashMap(), } } @@ -472,7 +479,8 @@ impl Definitions { parent: DefIndex, node_id: ast::NodeId, data: DefPathData, - address_space: DefIndexAddressSpace) + address_space: DefIndexAddressSpace, + expansion: Mark) -> DefIndex { debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})", parent, node_id, data); @@ -510,6 +518,7 @@ impl Definitions { assert_eq!(index.as_array_index(), self.def_index_to_node[address_space.index()].len()); self.def_index_to_node[address_space.index()].push(node_id); + self.expansions.insert(index, expansion); debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id); self.node_to_def_index.insert(node_id, index); @@ -525,6 +534,18 @@ impl Definitions { "Trying initialize NodeId -> HirId mapping twice"); self.node_to_hir_id = mapping; } + + pub fn expansion(&self, index: DefIndex) -> Mark { + self.expansions[&index] + } + + pub fn macro_def_scope(&self, mark: Mark) -> DefId { + self.macro_def_scopes[&mark] + } + + pub fn add_macro_def_scope(&mut self, mark: Mark, scope: DefId) { + self.macro_def_scopes.insert(mark, scope); + } } impl DefPathData { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 868730edfed..09e9d7c5b2f 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -637,14 +637,15 @@ impl<'hir> Map<'hir> { /// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no /// module parent is in this map. - pub fn get_module_parent(&self, id: NodeId) -> NodeId { - match self.walk_parent_nodes(id, |node| match *node { + pub fn get_module_parent(&self, id: NodeId) -> DefId { + let id = match self.walk_parent_nodes(id, |node| match *node { NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true, _ => false, }) { Ok(id) => id, Err(id) => id, - } + }; + self.local_def_id(id) } /// Returns the nearest enclosing scope. A scope is an item or block. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index fa731f6dde6..963ee9b7165 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -45,8 +45,9 @@ use std::rc::Rc; use std::slice; use std::vec::IntoIter; use std::mem; -use syntax::ast::{self, DUMMY_NODE_ID, Name, NodeId}; +use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId}; use syntax::attr; +use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::symbol::{Symbol, InternedString}; use syntax_pos::{DUMMY_SP, Span}; use rustc_const_math::ConstInt; @@ -268,7 +269,7 @@ impl Visibility { def => Visibility::Restricted(def.def_id()), }, hir::Inherited => { - Visibility::Restricted(tcx.hir.local_def_id(tcx.hir.get_module_parent(id))) + Visibility::Restricted(tcx.hir.get_module_parent(id)) } } } @@ -1823,17 +1824,22 @@ impl<'a, 'gcx, 'tcx> AdtDef { impl<'a, 'gcx, 'tcx> VariantDef { #[inline] - pub fn find_field_named(&self, - name: ast::Name) - -> Option<&FieldDef> { - self.fields.iter().find(|f| f.name == name) + pub fn find_field_named(&self, name: ast::Name) -> Option<&FieldDef> { + self.index_of_field_named(name).map(|index| &self.fields[index]) } - #[inline] - pub fn index_of_field_named(&self, - name: ast::Name) - -> Option { - self.fields.iter().position(|f| f.name == name) + pub fn index_of_field_named(&self, name: ast::Name) -> Option { + if let Some(index) = self.fields.iter().position(|f| f.name == name) { + return Some(index); + } + let mut ident = name.to_ident(); + while ident.ctxt != SyntaxContext::empty() { + ident.ctxt.remove_mark(); + if let Some(field) = self.fields.iter().position(|f| f.name.to_ident() == ident) { + return Some(field); + } + } + None } #[inline] @@ -2257,10 +2263,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn vis_is_accessible_from(self, vis: Visibility, block: NodeId) -> bool { - vis.is_accessible_from(self.hir.local_def_id(self.hir.get_module_parent(block)), self) - } - pub fn item_name(self, id: DefId) -> ast::Name { if let Some(id) = self.hir.as_local_node_id(id) { self.hir.name(id) @@ -2372,6 +2374,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Err(self.sess.cstore.crate_name(impl_did.krate)) } } + + pub fn adjust(self, name: Name, scope: DefId, block: NodeId) -> (Ident, DefId) { + self.adjust_ident(name.to_ident(), scope, block) + } + + pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) { + let expansion = match scope.krate { + LOCAL_CRATE => self.hir.definitions().expansion(scope.index), + _ => Mark::root(), + }; + let scope = match ident.ctxt.adjust(expansion) { + Some(macro_def) => self.hir.definitions().macro_def_scope(macro_def), + None => self.hir.get_module_parent(block), + }; + (ident, scope) + } } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 7ed5f620816..b35b0865991 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -154,7 +154,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { } } - let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(scrut.id)); + let module = self.tcx.hir.get_module_parent(scrut.id); MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| { let mut have_errors = false; @@ -182,7 +182,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { // Then, if the match has no arms, check whether the scrutinee // is uninhabited. let pat_ty = self.tables.node_id_to_type(scrut.id); - let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(scrut.id)); + let module = self.tcx.hir.get_module_parent(scrut.id); if inlined_arms.is_empty() { let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type { pat_ty.is_uninhabited_from(module, self.tcx) @@ -231,7 +231,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { "local binding" }; - let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(pat.id)); + let module = self.tcx.hir.get_module_parent(pat.id); MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| { let mut patcx = PatternContext::new(self.tcx, self.tables); let pattern = patcx.lower_pattern(pat); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 180a608e631..552023d022f 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1320,7 +1320,7 @@ impl<'a> Resolver<'a> { module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root); let mut definitions = Definitions::new(); - DefCollector::new(&mut definitions) + DefCollector::new(&mut definitions, Mark::root()) .collect_root(crate_name, &session.local_crate_disambiguator().as_str()); let mut invocations = FxHashMap(); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 9aba892e0ff..8957312e152 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -158,7 +158,7 @@ impl<'a> base::Resolver for Resolver<'a> { fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]) { let invocation = self.invocations[&mark]; - self.collect_def_ids(invocation, expansion); + self.collect_def_ids(mark, invocation, expansion); self.current_module = invocation.module.get(); self.current_module.unresolved_invocations.borrow_mut().remove(&mark); @@ -290,7 +290,12 @@ impl<'a> base::Resolver for Resolver<'a> { Err(determinacy) => return Err(determinacy), }, }; + self.macro_defs.insert(invoc.expansion_data.mark, def.def_id()); + let normal_module_def_id = + self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id; + self.definitions.add_macro_def_scope(invoc.expansion_data.mark, normal_module_def_id); + self.unused_macros.remove(&def.def_id()); let ext = self.get_macro(def); if ext.is_modern() { @@ -665,7 +670,10 @@ impl<'a> Resolver<'a> { } } - fn collect_def_ids(&mut self, invocation: &'a InvocationData<'a>, expansion: &Expansion) { + fn collect_def_ids(&mut self, + mark: Mark, + invocation: &'a InvocationData<'a>, + expansion: &Expansion) { let Resolver { ref mut invocations, arenas, graph_root, .. } = *self; let InvocationData { def_index, const_expr, .. } = *invocation; @@ -681,7 +689,7 @@ impl<'a> Resolver<'a> { }); }; - let mut def_collector = DefCollector::new(&mut self.definitions); + let mut def_collector = DefCollector::new(&mut self.definitions, mark); def_collector.visit_macro_invoc = Some(visit_macro_invoc); def_collector.with_parent(def_index, |def_collector| { if const_expr { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 9e8352fde80..d1ff3ed4f49 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -891,7 +891,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name) .expect("missing associated type"); let def = Def::AssociatedTy(item.def_id); - if !tcx.vis_is_accessible_from(item.vis, ref_id) { + let def_scope = tcx.adjust(assoc_name, item.container.id(), ref_id).1; + if !item.vis.is_accessible_from(def_scope, tcx) { let msg = format!("{} `{}` is private", def.kind_name(), assoc_name); tcx.sess.span_err(span, &msg); } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 4d5f67004a7..43bf702935a 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -338,6 +338,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// and return it, or `None`, if no such item was defined there. pub fn associated_item(&self, def_id: DefId, item_name: ast::Name) -> Option { - self.tcx.associated_items(def_id).find(|item| item.name == item_name) + let ident = self.tcx.adjust(item_name, def_id, self.body_id).0; + self.tcx.associated_items(def_id).find(|item| item.name.to_ident() == ident) } } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 9ad72b2a137..b32eb9ac5fb 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -371,7 +371,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn push_inherent_candidate(&mut self, xform_self_ty: Ty<'tcx>, item: ty::AssociatedItem, kind: CandidateKind<'tcx>, import_id: Option) { - if self.tcx.vis_is_accessible_from(item.vis, self.body_id) { + let is_accessible = if let LookingFor::MethodName(name) = self.looking_for { + let def_scope = self.tcx.adjust(name, item.container.id(), self.body_id).1; + item.vis.is_accessible_from(def_scope, self.tcx) + } else { + true + }; + if is_accessible { self.inherent_candidates.push(Candidate { xform_self_ty, item, kind, import_id }); } else if self.private_candidate.is_none() { self.private_candidate = Some(item.def()); @@ -380,7 +386,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn push_extension_candidate(&mut self, xform_self_ty: Ty<'tcx>, item: ty::AssociatedItem, kind: CandidateKind<'tcx>, import_id: Option) { - if self.tcx.vis_is_accessible_from(item.vis, self.body_id) { + let is_accessible = if let LookingFor::MethodName(name) = self.looking_for { + let def_scope = self.tcx.adjust(name, item.container.id(), self.body_id).1; + item.vis.is_accessible_from(def_scope, self.tcx) + } else { + true + }; + if is_accessible { self.extension_candidates.push(Candidate { xform_self_ty, item, kind, import_id }); } else if self.private_candidate.is_none() { self.private_candidate = Some(item.def()); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 7e70bb92cd6..edaaa863ecc 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -195,8 +195,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; let field_ty = field.ty(tcx, substs); - - if tcx.vis_is_accessible_from(field.vis, self.body_id) { + let scope = self.tcx.hir.get_module_parent(self.body_id); + if field.vis.is_accessible_from(scope, self.tcx) { if self.is_fn_ty(&field_ty, span) { err.help(&format!("use `({0}.{1})(...)` if you \ meant to call the function \ diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 24a88140cf0..1ad3914854d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2916,9 +2916,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match base_t.sty { ty::TyAdt(base_def, substs) if !base_def.is_enum() => { debug!("struct named {:?}", base_t); - if let Some(field) = base_def.struct_variant().find_field_named(field.node) { + let (ident, def_scope) = + self.tcx.adjust(field.node, base_def.did, self.body_id); + let fields = &base_def.struct_variant().fields; + if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) { let field_ty = self.field_ty(expr.span, field, substs); - if self.tcx.vis_is_accessible_from(field.vis, self.body_id) { + if field.vis.is_accessible_from(def_scope, self.tcx) { autoderef.finalize(lvalue_pref, base); self.apply_autoderef_adjustment(base.id, autoderefs, base_t); @@ -3024,16 +3027,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !tuple_like { continue } debug!("tuple struct named {:?}", base_t); - base_def.struct_variant().fields.get(idx.node).and_then(|field| { + let ident = ast::Ident { + name: Symbol::intern(&idx.node.to_string()), + ctxt: idx.span.ctxt.modern(), + }; + let (ident, def_scope) = + self.tcx.adjust_ident(ident, base_def.did, self.body_id); + let fields = &base_def.struct_variant().fields; + if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) { let field_ty = self.field_ty(expr.span, field, substs); - private_candidate = Some((base_def.did, field_ty)); - if self.tcx.vis_is_accessible_from(field.vis, self.body_id) { + if field.vis.is_accessible_from(def_scope, self.tcx) { self.tcx.check_stability(field.did, expr.id, expr.span); Some(field_ty) } else { + private_candidate = Some((base_def.did, field_ty)); None } - }) + } else { + None + } } ty::TyTuple(ref v, _) => { tuple_like = true; @@ -3142,7 +3154,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut remaining_fields = FxHashMap(); for field in &variant.fields { - remaining_fields.insert(field.name, field); + remaining_fields.insert(field.name.to_ident(), field); } let mut seen_fields = FxHashMap(); @@ -3154,7 +3166,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let final_field_type; let field_type_hint; - if let Some(v_field) = remaining_fields.remove(&field.name.node) { + let ident = tcx.adjust(field.name.node, variant.did, self.body_id).0; + if let Some(v_field) = remaining_fields.remove(&ident) { final_field_type = self.field_ty(field.span, v_field, substs); field_type_hint = self.field_ty(field.span, v_field, hint_substs); @@ -3205,7 +3218,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut displayable_field_names = remaining_fields .keys() - .map(|x| x.as_str()) + .map(|ident| ident.name.as_str()) .collect::>(); displayable_field_names.sort(); diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 24a21faa7eb..f23398bda6b 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -16,7 +16,7 @@ //! DOI=10.1017/S0956796812000093 http://dx.doi.org/10.1017/S0956796812000093 use Span; -use symbol::Symbol; +use symbol::{Ident, Symbol}; use serialize::{Encodable, Decodable, Encoder, Decoder}; use std::cell::RefCell; @@ -106,6 +106,7 @@ struct HygieneData { marks: Vec, syntax_contexts: Vec, markings: HashMap<(SyntaxContext, Mark), SyntaxContext>, + idents: HashMap, } impl HygieneData { @@ -114,6 +115,7 @@ impl HygieneData { marks: vec![MarkData::default()], syntax_contexts: vec![SyntaxContextData::default()], markings: HashMap::new(), + idents: HashMap::new(), } } @@ -348,3 +350,19 @@ impl Decodable for SyntaxContext { Ok(SyntaxContext::empty()) // FIXME(jseyfried) intercrate hygiene } } + +impl Symbol { + pub fn from_ident(ident: Ident) -> Symbol { + HygieneData::with(|data| { + let symbol = Symbol::gensym(&ident.name.as_str()); + data.idents.insert(symbol, ident); + symbol + }) + } + + pub fn to_ident(self) -> Ident { + HygieneData::with(|data| { + data.idents.get(&self).cloned().unwrap_or(Ident::with_empty_ctxt(self)) + }) + } +}