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

Support registering inert attributes and attribute tools using crate-level attributes #66070

Merged
merged 5 commits into from
Nov 10, 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
23 changes: 20 additions & 3 deletions src/librustc/hir/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ pub enum NonMacroAttrKind {
Tool,
/// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
DeriveHelper,
/// Single-segment custom attribute registered with `#[register_attr]`.
Registered,
/// Single-segment custom attribute registered by a legacy plugin (`register_attribute`).
LegacyPluginHelper,
/// Single-segment custom attribute not registered in any way (`#[my_attr]`).
Custom,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
Expand Down Expand Up @@ -329,8 +329,24 @@ impl NonMacroAttrKind {
NonMacroAttrKind::Builtin => "built-in attribute",
NonMacroAttrKind::Tool => "tool attribute",
NonMacroAttrKind::DeriveHelper => "derive helper attribute",
NonMacroAttrKind::Registered => "explicitly registered attribute",
NonMacroAttrKind::LegacyPluginHelper => "legacy plugin helper attribute",
NonMacroAttrKind::Custom => "custom attribute",
}
}

pub fn article(self) -> &'static str {
match self {
NonMacroAttrKind::Registered => "an",
_ => "a",
}
}

/// Users of some attributes cannot mark them as used, so they are considered always used.
pub fn is_used(self) -> bool {
match self {
NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true,
NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered |
NonMacroAttrKind::LegacyPluginHelper => false,
}
}
}
Expand Down Expand Up @@ -389,6 +405,7 @@ impl<Id> Res<Id> {
pub fn article(&self) -> &'static str {
match *self {
Res::Def(kind, _) => kind.article(),
Res::NonMacroAttr(kind) => kind.article(),
Res::Err => "an",
_ => "a",
}
Expand Down
1 change: 0 additions & 1 deletion src/librustc_plugin/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ impl<'a> Registry<'a> {

/// Register an attribute with an attribute type.
///
/// Registered attributes will bypass the `custom_attribute` feature gate.
/// `Whitelisted` attributes will additionally not trigger the `unused_attribute`
/// lint. `CrateLevel` attributes will not be allowed on anything other than a crate.
pub fn register_attribute(&mut self, name: Symbol, ty: AttributeType) {
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,7 @@ impl<'a> Resolver<'a> {
crate fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
match res {
Res::Def(DefKind::Macro(..), def_id) => self.get_macro_by_def_id(def_id),
Res::NonMacroAttr(attr_kind) =>
Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
Res::NonMacroAttr(attr_kind) => Some(self.non_macro_attr(attr_kind.is_used())),
_ => None,
}
}
Expand Down
14 changes: 11 additions & 3 deletions src/librustc_resolve/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use syntax_pos::hygiene::MacroKind;
use syntax_pos::{BytePos, Span, MultiSpan};

use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
use crate::{path_names_to_string, KNOWN_TOOLS};
use crate::path_names_to_string;
use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
use crate::{PathResult, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Segment};

Expand Down Expand Up @@ -400,6 +400,14 @@ impl<'a> Resolver<'a> {
Scope::Module(module) => {
this.add_module_candidates(module, &mut suggestions, filter_fn);
}
Scope::RegisteredAttrs => {
let res = Res::NonMacroAttr(NonMacroAttrKind::Registered);
if filter_fn(res) {
suggestions.extend(this.registered_attrs.iter().map(|ident| {
TypoSuggestion::from_res(ident.name, res)
}));
}
}
Scope::MacroUsePrelude => {
suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| {
let res = binding.res();
Expand Down Expand Up @@ -439,8 +447,8 @@ impl<'a> Resolver<'a> {
}
Scope::ToolPrelude => {
let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
suggestions.extend(KNOWN_TOOLS.iter().map(|name| {
TypoSuggestion::from_res(*name, res)
suggestions.extend(this.registered_tools.iter().map(|ident| {
TypoSuggestion::from_res(ident.name, res)
}));
}
Scope::StdLibPrelude => {
Expand Down
27 changes: 16 additions & 11 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ mod check_unused;
mod build_reduced_graph;
mod resolve_imports;

const KNOWN_TOOLS: &[Name] = &[sym::clippy, sym::rustfmt];

enum Weak {
Yes,
No,
Expand All @@ -102,6 +100,7 @@ enum Scope<'a> {
MacroRules(LegacyScope<'a>),
CrateRoot,
Module(Module<'a>),
RegisteredAttrs,
MacroUsePrelude,
BuiltinAttrs,
LegacyPluginHelpers,
Expand Down Expand Up @@ -621,7 +620,6 @@ enum AmbiguityKind {
Import,
BuiltinAttr,
DeriveHelper,
LegacyHelperVsPrelude,
LegacyVsModern,
GlobVsOuter,
GlobVsGlob,
Expand All @@ -638,8 +636,6 @@ impl AmbiguityKind {
"built-in attribute vs any other name",
AmbiguityKind::DeriveHelper =>
"derive helper attribute vs any other name",
AmbiguityKind::LegacyHelperVsPrelude =>
"legacy plugin helper attribute vs name from prelude",
AmbiguityKind::LegacyVsModern =>
"`macro_rules` vs non-`macro_rules` from other module",
AmbiguityKind::GlobVsOuter =>
Expand Down Expand Up @@ -916,6 +912,8 @@ pub struct Resolver<'a> {
crate_loader: CrateLoader<'a>,
macro_names: FxHashSet<Ident>,
builtin_macros: FxHashMap<Name, SyntaxExtension>,
registered_attrs: FxHashSet<Ident>,
registered_tools: FxHashSet<Ident>,
macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
all_macros: FxHashMap<Name, Res>,
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
Expand Down Expand Up @@ -1132,6 +1130,9 @@ impl<'a> Resolver<'a> {
}
}

let (registered_attrs, registered_tools) =
macros::registered_attrs_and_tools(session, &krate.attrs);

let mut invocation_parent_scopes = FxHashMap::default();
invocation_parent_scopes.insert(ExpnId::root(), ParentScope::module(graph_root));

Expand Down Expand Up @@ -1201,6 +1202,8 @@ impl<'a> Resolver<'a> {
crate_loader: CrateLoader::new(session, metadata_loader, crate_name),
macro_names: FxHashSet::default(),
builtin_macros: Default::default(),
registered_attrs,
registered_tools,
macro_use_prelude: FxHashMap::default(),
all_macros: FxHashMap::default(),
macro_map: FxHashMap::default(),
Expand Down Expand Up @@ -1469,6 +1472,7 @@ impl<'a> Resolver<'a> {
Scope::MacroRules(..) => true,
Scope::CrateRoot => true,
Scope::Module(..) => true,
Scope::RegisteredAttrs => use_prelude,
Scope::MacroUsePrelude => use_prelude || rust_2015,
Scope::BuiltinAttrs => true,
Scope::LegacyPluginHelpers => use_prelude || rust_2015,
Expand Down Expand Up @@ -1513,11 +1517,12 @@ impl<'a> Resolver<'a> {
match ns {
TypeNS => Scope::ExternPrelude,
ValueNS => Scope::StdLibPrelude,
MacroNS => Scope::MacroUsePrelude,
MacroNS => Scope::RegisteredAttrs,
}
}
}
}
Scope::RegisteredAttrs => Scope::MacroUsePrelude,
Scope::MacroUsePrelude => Scope::StdLibPrelude,
Scope::BuiltinAttrs => Scope::LegacyPluginHelpers,
Scope::LegacyPluginHelpers => break, // nowhere else to search
Expand Down Expand Up @@ -1673,11 +1678,11 @@ impl<'a> Resolver<'a> {
if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
return Some(LexicalScopeBinding::Item(binding));
}
}
if ns == TypeNS && KNOWN_TOOLS.contains(&ident.name) {
let binding = (Res::ToolMod, ty::Visibility::Public,
DUMMY_SP, ExpnId::root()).to_name_binding(self.arenas);
return Some(LexicalScopeBinding::Item(binding));
if let Some(ident) = self.registered_tools.get(&ident) {
let binding = (Res::ToolMod, ty::Visibility::Public,
ident.span, ExpnId::root()).to_name_binding(self.arenas);
return Some(LexicalScopeBinding::Item(binding));
}
}
if let Some(prelude) = self.prelude {
if let Ok(binding) = self.resolve_ident_in_module_unadjusted(
Expand Down
Loading