Skip to content

Commit

Permalink
Resolve attributes in several places
Browse files Browse the repository at this point in the history
Arm, Field, FieldPat, GenericParam, Param, StructField and Variant
  • Loading branch information
c410-f3r committed Sep 9, 2019
1 parent 2c0931e commit 63a5f39
Show file tree
Hide file tree
Showing 37 changed files with 1,097 additions and 489 deletions.
58 changes: 57 additions & 1 deletion src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
}

fn visit_variant(&mut self, v: &'a Variant) {
if v.is_placeholder {
return self.visit_macro_invoc(v.id);
}
let def = self.create_def(v.id,
DefPathData::TypeNs(v.ident.as_interned_str()),
v.span);
Expand All @@ -168,16 +171,24 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {

fn visit_variant_data(&mut self, data: &'a VariantData) {
for (index, field) in data.fields().iter().enumerate() {
if field.is_placeholder {
self.visit_macro_invoc(field.id);
continue;
}
let name = field.ident.map(|ident| ident.name)
.unwrap_or_else(|| sym::integer(index));
let def = self.create_def(field.id,
DefPathData::ValueNs(name.as_interned_str()),
field.span);
self.with_parent(def, |this| this.visit_struct_field(field));
self.with_parent(def, |this| visit::walk_struct_field(this, field));
}
}

fn visit_generic_param(&mut self, param: &'a GenericParam) {
if param.is_placeholder {
self.visit_macro_invoc(param.id);
return;
}
let name = param.ident.as_interned_str();
let def_path_data = match param.kind {
GenericParamKind::Lifetime { .. } => DefPathData::LifetimeNs(name),
Expand Down Expand Up @@ -294,4 +305,49 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
}
}
}

fn visit_arm(&mut self, arm: &'a Arm) {
if arm.is_placeholder {
self.visit_macro_invoc(arm.id)
} else {
visit::walk_arm(self, arm)
}
}

fn visit_field(&mut self, f: &'a Field) {
if f.is_placeholder {
self.visit_macro_invoc(f.id)
} else {
visit::walk_field(self, f)
}
}

fn visit_field_pattern(&mut self, fp: &'a FieldPat) {
if fp.is_placeholder {
self.visit_macro_invoc(fp.id)
} else {
visit::walk_field_pattern(self, fp)
}
}

fn visit_param(&mut self, p: &'a Param) {
if p.is_placeholder {
self.visit_macro_invoc(p.id)
} else {
visit::walk_param(self, p)
}
}

fn visit_struct_field(&mut self, sf: &'a StructField) {
if sf.is_placeholder {
self.visit_macro_invoc(sf.id)
} else {
let name = sf.ident.map(|ident| ident.name)
.unwrap_or_else(|| panic!("don't know the field number in this context"));
let def = self.create_def(sf.id,
DefPathData::ValueNs(name.as_interned_str()),
sf.span);
self.with_parent(def, |this| visit::walk_struct_field(this, sf));
}
}
}
139 changes: 94 additions & 45 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use syntax::ast::{Name, Ident};
use syntax::attr;

use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant};
use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind};
use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax::ext::expand::AstFragment;
use syntax::ext::hygiene::ExpnId;
Expand Down Expand Up @@ -580,7 +580,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}

/// Constructs the reduced graph for one item.
fn build_reduced_graph_for_item(&mut self, item: &Item) {
fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
let parent_scope = &self.parent_scope;
let parent = parent_scope.module;
let expansion = parent_scope.expansion;
Expand Down Expand Up @@ -716,23 +716,17 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
}

ItemKind::Enum(ref enum_definition, _) => {
let module_kind = ModuleKind::Def(
DefKind::Enum,
self.r.definitions.local_def_id(item.id),
ident.name,
);
ItemKind::Enum(_, _) => {
let def_id = self.r.definitions.local_def_id(item.id);
self.r.variant_vis.insert(def_id, vis);
let module_kind = ModuleKind::Def(DefKind::Enum, def_id, ident.name);
let module = self.r.new_module(parent,
module_kind,
parent.normal_ancestor_id,
expansion,
item.span);
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
self.parent_scope.module = module;

for variant in &(*enum_definition).variants {
self.build_reduced_graph_for_variant(variant, vis);
}
}

ItemKind::TraitAlias(..) => {
Expand Down Expand Up @@ -817,38 +811,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}
}

// Constructs the reduced graph for one variant. Variants exist in the
// type and value namespaces.
fn build_reduced_graph_for_variant(&mut self, variant: &Variant, vis: ty::Visibility) {
let parent = self.parent_scope.module;
let expn_id = self.parent_scope.expansion;
let ident = variant.ident;

// Define a name in the type namespace.
let def_id = self.r.definitions.local_def_id(variant.id);
let res = Res::Def(DefKind::Variant, def_id);
self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id));

// If the variant is marked as non_exhaustive then lower the visibility to within the
// crate.
let mut ctor_vis = vis;
let has_non_exhaustive = attr::contains_name(&variant.attrs, sym::non_exhaustive);
if has_non_exhaustive && vis == ty::Visibility::Public {
ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
}

// Define a constructor name in the value namespace.
// Braced variants, unlike structs, generate unusable names in
// value namespace, they are reserved for possible future use.
// It's ok to use the variant's id as a ctor id since an
// error will be reported on any use of such resolution anyway.
let ctor_node_id = variant.data.ctor_id().unwrap_or(variant.id);
let ctor_def_id = self.r.definitions.local_def_id(ctor_node_id);
let ctor_kind = CtorKind::from_ast(&variant.data);
let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
}

/// Constructs the reduced graph for one foreign item.
fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
let (res, ns) = match item.node {
Expand Down Expand Up @@ -1188,7 +1150,6 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
_ => false,
};

let orig_current_module = self.parent_scope.module;
let orig_current_legacy_scope = self.parent_scope.legacy;
self.build_reduced_graph_for_item(item);
Expand Down Expand Up @@ -1271,4 +1232,92 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
}
visit::walk_attribute(self, attr);
}

fn visit_arm(&mut self, arm: &'b ast::Arm) {
if arm.is_placeholder {
self.visit_invoc(arm.id);
} else {
visit::walk_arm(self, arm);
}
}

fn visit_field(&mut self, f: &'b ast::Field) {
if f.is_placeholder {
self.visit_invoc(f.id);
} else {
visit::walk_field(self, f);
}
}

fn visit_field_pattern(&mut self, fp: &'b ast::FieldPat) {
if fp.is_placeholder {
self.visit_invoc(fp.id);
} else {
visit::walk_field_pattern(self, fp);
}
}

fn visit_generic_param(&mut self, param: &'b ast::GenericParam) {
if param.is_placeholder {
self.visit_invoc(param.id);
} else {
visit::walk_generic_param(self, param);
}
}

fn visit_param(&mut self, p: &'b ast::Param) {
if p.is_placeholder {
self.visit_invoc(p.id);
} else {
visit::walk_param(self, p);
}
}

fn visit_struct_field(&mut self, sf: &'b ast::StructField) {
if sf.is_placeholder {
self.visit_invoc(sf.id);
} else {
visit::walk_struct_field(self, sf);
}
}

// Constructs the reduced graph for one variant. Variants exist in the
// type and value namespaces.
fn visit_variant(&mut self, variant: &'b ast::Variant) {
if variant.is_placeholder {
self.visit_invoc(variant.id);
return;
}

let parent = self.parent_scope.module;
let vis = self.r.variant_vis[&parent.def_id().expect("enum without def-id")];
let expn_id = self.parent_scope.expansion;
let ident = variant.ident;

// Define a name in the type namespace.
let def_id = self.r.definitions.local_def_id(variant.id);
let res = Res::Def(DefKind::Variant, def_id);
self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id));

// If the variant is marked as non_exhaustive then lower the visibility to within the
// crate.
let mut ctor_vis = vis;
let has_non_exhaustive = attr::contains_name(&variant.attrs, sym::non_exhaustive);
if has_non_exhaustive && vis == ty::Visibility::Public {
ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
}

// Define a constructor name in the value namespace.
// Braced variants, unlike structs, generate unusable names in
// value namespace, they are reserved for possible future use.
// It's ok to use the variant's id as a ctor id since an
// error will be reported on any use of such resolution anyway.
let ctor_node_id = variant.data.ctor_id().unwrap_or(variant.id);
let ctor_def_id = self.r.definitions.local_def_id(ctor_node_id);
let ctor_kind = CtorKind::from_ast(&variant.data);
let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));

visit::walk_variant(self, variant);
}
}
5 changes: 5 additions & 0 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,10 @@ pub struct Resolver<'a> {

/// Features enabled for this crate.
active_features: FxHashSet<Symbol>,

/// Stores enum visibilities to properly build a reduced graph
/// when visiting the correspondent variants.
variant_vis: DefIdMap<ty::Visibility>,
}

/// Nothing really interesting here; it just provides memory for the rest of the crate.
Expand Down Expand Up @@ -1214,6 +1218,7 @@ impl<'a> Resolver<'a> {
features.declared_lib_features.iter().map(|(feat, ..)| *feat)
.chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat))
.collect(),
variant_vis: Default::default()
}
}

Expand Down
22 changes: 21 additions & 1 deletion src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use syntax::attr::StabilityLevel;
use syntax::edition::Edition;
use syntax::ext::base::{self, InvocationRes, Indeterminate, SpecialDerives};
use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
use syntax::ext::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind};
use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind};
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name};
Expand Down Expand Up @@ -225,6 +225,26 @@ impl<'a> base::Resolver for Resolver<'a> {
self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
}

match invoc.fragment_kind {
AstFragmentKind::Arms
| AstFragmentKind::Fields
| AstFragmentKind::FieldPats
| AstFragmentKind::GenericParams
| AstFragmentKind::Params
| AstFragmentKind::StructFields
| AstFragmentKind::Variants =>
{
if let Res::Def(..) = res {
self.session.span_err(
span,
"expected an inert attribute, found an attribute macro"
);
return Ok(InvocationRes::Single(self.dummy_ext(kind)));
}
},
_ => {}
}

Ok(InvocationRes::Single(ext))
}

Expand Down
6 changes: 3 additions & 3 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,15 +519,15 @@ fn convert_variant_ctor(tcx: TyCtxt<'_>, ctor_id: hir::HirId) {
tcx.predicates_of(def_id);
}

fn convert_enum_variant_types<'tcx>(
tcx: TyCtxt<'tcx>,
fn convert_enum_variant_types(
tcx: TyCtxt<'_>,
def_id: DefId,
variants: &[hir::Variant]
) {
let def = tcx.adt_def(def_id);
let repr_type = def.repr.discr_type();
let initial = repr_type.initial_discriminant(tcx);
let mut prev_discr = None::<Discr<'tcx>>;
let mut prev_discr = None::<Discr<'_>>;

// fill the discriminant values and field types
for variant in variants {
Expand Down
Loading

0 comments on commit 63a5f39

Please sign in to comment.