about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2017-03-24 23:03:15 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2017-05-25 05:52:05 +0000
commitbfa2ef62a1d283eea2779ce0a4676a855536bfcd (patch)
tree6f975fa9c0b699448069c165590c113f0a8615cc /src
parent1f175fa35d4263f1d2c4c3433a495a78996305f4 (diff)
downloadrust-bfa2ef62a1d283eea2779ce0a4676a855536bfcd.tar.gz
rust-bfa2ef62a1d283eea2779ce0a4676a855536bfcd.zip
Hygienize `librustc_typeck`.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/lowering.rs47
-rw-r--r--src/librustc/hir/map/def_collector.rs7
-rw-r--r--src/librustc/hir/map/definitions.rs23
-rw-r--r--src/librustc/hir/map/mod.rs7
-rw-r--r--src/librustc/ty/mod.rs48
-rw-r--r--src/librustc_const_eval/check_match.rs6
-rw-r--r--src/librustc_resolve/lib.rs2
-rw-r--r--src/librustc_resolve/macros.rs14
-rw-r--r--src/librustc_typeck/astconv.rs3
-rw-r--r--src/librustc_typeck/check/method/mod.rs3
-rw-r--r--src/librustc_typeck/check/method/probe.rs16
-rw-r--r--src/librustc_typeck/check/method/suggest.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs31
-rw-r--r--src/libsyntax_pos/hygiene.rs20
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<DefIndex>,
     resolver: &'a mut Resolver,
+    name_map: FxHashMap<Ident, Name>,
 
     /// The items being lowered are collected here.
     items: BTreeMap<NodeId, hir::Item>,
@@ -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<Spanned<Ident>>) -> Option<Spanned<Name>> {
         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<DefIndex>,
+    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<F: FnOnce(&mut Self)>(&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<DefIndex>,
     def_index_to_node: [Vec<ast::NodeId>; 2],
     pub(super) node_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
+    macro_def_scopes: FxHashMap<Mark, DefId>,
+    expansions: FxHashMap<DefIndex, Mark>,
 }
 
 // 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<usize> {
-        self.fields.iter().position(|f| f.name == name)
+    pub fn index_of_field_named(&self, name: ast::Name) -> Option<usize> {
+        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<ty::AssociatedItem> {
-        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<ast::NodeId>) {
-        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<ast::NodeId>) {
-        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::<Vec<_>>();
 
             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<MarkData>,
     syntax_contexts: Vec<SyntaxContextData>,
     markings: HashMap<(SyntaxContext, Mark), SyntaxContext>,
+    idents: HashMap<Symbol, Ident>,
 }
 
 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))
+        })
+    }
+}