Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve attributes in several places #63468

Merged
merged 1 commit into from
Sep 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>,
petrochenkov marked this conversation as resolved.
Show resolved Hide resolved
}

/// 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