about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2018-02-08 15:48:16 -0800
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2018-02-17 21:48:35 -0800
commit4294528b5da1dabd777aa88f621f222f0b0df8f4 (patch)
tree0a3f060468e7a2c29e25fc4bde2e1220cc24dc44
parentba8d6d18d0378a515ed692f7e7fdb0c5a068c7ea (diff)
downloadrust-4294528b5da1dabd777aa88f621f222f0b0df8f4.tar.gz
rust-4294528b5da1dabd777aa88f621f222f0b0df8f4.zip
Improve hygiene when privacy-checking struct expression or struct constructor fields.
-rw-r--r--src/librustc_privacy/lib.rs26
1 files changed, 19 insertions, 7 deletions
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index b46882f054d..f8221698231 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -34,6 +34,7 @@ use rustc::util::nodemap::NodeSet;
 use syntax::ast::{self, CRATE_NODE_ID, Ident};
 use syntax::symbol::keywords;
 use syntax_pos::Span;
+use syntax_pos::hygiene::SyntaxContext;
 
 use std::cmp;
 use std::mem::replace;
@@ -491,9 +492,13 @@ struct NamePrivacyVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
-    // Checks that a field is accessible.
-    fn check_field(&mut self, span: Span, def: &'tcx ty::AdtDef, field: &'tcx ty::FieldDef) {
-        let ident = Ident { ctxt: span.ctxt().modern(), ..keywords::Invalid.ident() };
+    // Checks that a field in a struct constructor (expression or pattern) is accessible.
+    fn check_field(&mut self,
+                   use_ctxt: SyntaxContext, // Syntax context of the field name at the use site
+                   span: Span, // Span of the field pattern, e.g. `x: 0`
+                   def: &'tcx ty::AdtDef, // Definition of the struct or enum
+                   field: &'tcx ty::FieldDef) { // Definition of the field
+        let ident = Ident { ctxt: use_ctxt.modern(), ..keywords::Invalid.ident() };
         let def_id = self.tcx.adjust_ident(ident, def.did, self.current_item).1;
         if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
             struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
@@ -566,12 +571,17 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
                     // unmentioned fields, just check them all.
                     for variant_field in &variant.fields {
                         let field = fields.iter().find(|f| f.name.node == variant_field.name);
-                        let span = if let Some(f) = field { f.span } else { base.span };
-                        self.check_field(span, adt, variant_field);
+                        let (use_ctxt, span) = match field {
+                            Some(field) => (field.name.node.to_ident().ctxt, field.span),
+                            None => (base.span.ctxt(), base.span),
+                        };
+                        self.check_field(use_ctxt, span, adt, variant_field);
                     }
                 } else {
                     for field in fields {
-                        self.check_field(field.span, adt, variant.field_named(field.name.node));
+                        let use_ctxt = field.name.node.to_ident().ctxt;
+                        let field_def = variant.field_named(field.name.node);
+                        self.check_field(use_ctxt, field.span, adt, field_def);
                     }
                 }
             }
@@ -588,7 +598,9 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
                 let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap();
                 let variant = adt.variant_of_def(def);
                 for field in fields {
-                    self.check_field(field.span, adt, variant.field_named(field.node.name));
+                    let use_ctxt = field.node.name.to_ident().ctxt;
+                    let field_def = variant.field_named(field.node.name);
+                    self.check_field(use_ctxt, field.span, adt, field_def);
                 }
             }
             _ => {}