Skip to content

Commit

Permalink
Rollup merge of rust-lang#63468 - c410-f3r:attrs, r=petrochenkov
Browse files Browse the repository at this point in the history
Resolve attributes in several places

Resolve attributes for Arm, Field, FieldPat, GenericParam, Param, StructField and Variant.

This PR is based on @petrochenkov work located at petrochenkov@83fdb8d.
  • Loading branch information
Centril committed Sep 9, 2019
2 parents 824383d + 63a5f39 commit 457a23f
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 457a23f

Please sign in to comment.