Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Improve hygiene when privacy-checking struct expression or struct con…
…structor fields.
  • Loading branch information
jseyfried committed Feb 18, 2018
1 parent ba8d6d1 commit 4294528
Showing 1 changed file with 19 additions and 7 deletions.
26 changes: 19 additions & 7 deletions src/librustc_privacy/lib.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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);
}
}
}
Expand All @@ -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);
}
}
_ => {}
Expand Down

0 comments on commit 4294528

Please sign in to comment.