Skip to content

Commit 4294528

Browse files
committed
Improve hygiene when privacy-checking struct expression or struct constructor fields.
1 parent ba8d6d1 commit 4294528

File tree

1 file changed

+19
-7
lines changed

1 file changed

+19
-7
lines changed

src/librustc_privacy/lib.rs

+19-7
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use rustc::util::nodemap::NodeSet;
3434
use syntax::ast::{self, CRATE_NODE_ID, Ident};
3535
use syntax::symbol::keywords;
3636
use syntax_pos::Span;
37+
use syntax_pos::hygiene::SyntaxContext;
3738

3839
use std::cmp;
3940
use std::mem::replace;
@@ -491,9 +492,13 @@ struct NamePrivacyVisitor<'a, 'tcx: 'a> {
491492
}
492493

493494
impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
494-
// Checks that a field is accessible.
495-
fn check_field(&mut self, span: Span, def: &'tcx ty::AdtDef, field: &'tcx ty::FieldDef) {
496-
let ident = Ident { ctxt: span.ctxt().modern(), ..keywords::Invalid.ident() };
495+
// Checks that a field in a struct constructor (expression or pattern) is accessible.
496+
fn check_field(&mut self,
497+
use_ctxt: SyntaxContext, // Syntax context of the field name at the use site
498+
span: Span, // Span of the field pattern, e.g. `x: 0`
499+
def: &'tcx ty::AdtDef, // Definition of the struct or enum
500+
field: &'tcx ty::FieldDef) { // Definition of the field
501+
let ident = Ident { ctxt: use_ctxt.modern(), ..keywords::Invalid.ident() };
497502
let def_id = self.tcx.adjust_ident(ident, def.did, self.current_item).1;
498503
if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
499504
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> {
566571
// unmentioned fields, just check them all.
567572
for variant_field in &variant.fields {
568573
let field = fields.iter().find(|f| f.name.node == variant_field.name);
569-
let span = if let Some(f) = field { f.span } else { base.span };
570-
self.check_field(span, adt, variant_field);
574+
let (use_ctxt, span) = match field {
575+
Some(field) => (field.name.node.to_ident().ctxt, field.span),
576+
None => (base.span.ctxt(), base.span),
577+
};
578+
self.check_field(use_ctxt, span, adt, variant_field);
571579
}
572580
} else {
573581
for field in fields {
574-
self.check_field(field.span, adt, variant.field_named(field.name.node));
582+
let use_ctxt = field.name.node.to_ident().ctxt;
583+
let field_def = variant.field_named(field.name.node);
584+
self.check_field(use_ctxt, field.span, adt, field_def);
575585
}
576586
}
577587
}
@@ -588,7 +598,9 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
588598
let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap();
589599
let variant = adt.variant_of_def(def);
590600
for field in fields {
591-
self.check_field(field.span, adt, variant.field_named(field.node.name));
601+
let use_ctxt = field.node.name.to_ident().ctxt;
602+
let field_def = variant.field_named(field.node.name);
603+
self.check_field(use_ctxt, field.span, adt, field_def);
592604
}
593605
}
594606
_ => {}

0 commit comments

Comments
 (0)