Skip to content

Commit 3fc30d8

Browse files
committed
Auto merge of #66070 - petrochenkov:regattr, r=matthewjasper
Support registering inert attributes and attribute tools using crate-level attributes And remove `#[feature(custom_attribute)]`. (`rustc_plugin::Registry::register_attribute` is not removed yet, I'll do it in a follow up PR.) ```rust #![register_attr(my_attr)] #![register_tool(my_tool)] #[my_attr] // OK #[my_tool::anything] // OK fn main() {} ``` --- Some tools (`rustfmt` and `clippy`) used in tool attributes are hardcoded in the compiler. We need some way to introduce them without hardcoding as well. This PR introduces a way to do it with a crate level attribute. The previous attempt to introduce them through command line (#57921) met some resistance. This probably needs to go through an RFC before stabilization. However, I'd prefer to land *this* PR without an RFC to able to remove `#[feature(custom_attribute)]` and `Registry::register_attribute` while also providing a replacement. --- `register_attr` is a direct replacement for `#![feature(custom_attribute)]` (#29642), except it doesn't rely on implicit fallback from unresolved attributes to custom attributes (which was always hacky and is the primary reason for the removal of `custom_attribute`) and requires registering the attribute explicitly. It's not clear whether it should go through stabilization or not. It's quite possible that all the uses should migrate to `#![register_tool]` (#66079) instead. --- Details: - The naming is `register_attr`/`register_tool` rather than some `register_attributes` (plural, no abbreviation) for consistency with already existing attributes like `cfg_attr`, or `feature`, etc. --- Previous attempt: #57921 cc #44690 Tracking issues: #66079 (`register_tool`), #66080 (`register_attr`) Closes #29642
2 parents a3b6e57 + 83f553c commit 3fc30d8

33 files changed

+411
-118
lines changed

src/librustc/hir/def.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ pub enum NonMacroAttrKind {
4040
Tool,
4141
/// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
4242
DeriveHelper,
43+
/// Single-segment custom attribute registered with `#[register_attr]`.
44+
Registered,
4345
/// Single-segment custom attribute registered by a legacy plugin (`register_attribute`).
4446
LegacyPluginHelper,
45-
/// Single-segment custom attribute not registered in any way (`#[my_attr]`).
46-
Custom,
4747
}
4848

4949
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
@@ -329,8 +329,24 @@ impl NonMacroAttrKind {
329329
NonMacroAttrKind::Builtin => "built-in attribute",
330330
NonMacroAttrKind::Tool => "tool attribute",
331331
NonMacroAttrKind::DeriveHelper => "derive helper attribute",
332+
NonMacroAttrKind::Registered => "explicitly registered attribute",
332333
NonMacroAttrKind::LegacyPluginHelper => "legacy plugin helper attribute",
333-
NonMacroAttrKind::Custom => "custom attribute",
334+
}
335+
}
336+
337+
pub fn article(self) -> &'static str {
338+
match self {
339+
NonMacroAttrKind::Registered => "an",
340+
_ => "a",
341+
}
342+
}
343+
344+
/// Users of some attributes cannot mark them as used, so they are considered always used.
345+
pub fn is_used(self) -> bool {
346+
match self {
347+
NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true,
348+
NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered |
349+
NonMacroAttrKind::LegacyPluginHelper => false,
334350
}
335351
}
336352
}
@@ -389,6 +405,7 @@ impl<Id> Res<Id> {
389405
pub fn article(&self) -> &'static str {
390406
match *self {
391407
Res::Def(kind, _) => kind.article(),
408+
Res::NonMacroAttr(kind) => kind.article(),
392409
Res::Err => "an",
393410
_ => "a",
394411
}

src/librustc_plugin/registry.rs

-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ impl<'a> Registry<'a> {
101101

102102
/// Register an attribute with an attribute type.
103103
///
104-
/// Registered attributes will bypass the `custom_attribute` feature gate.
105104
/// `Whitelisted` attributes will additionally not trigger the `unused_attribute`
106105
/// lint. `CrateLevel` attributes will not be allowed on anything other than a crate.
107106
pub fn register_attribute(&mut self, name: Symbol, ty: AttributeType) {

src/librustc_resolve/build_reduced_graph.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,7 @@ impl<'a> Resolver<'a> {
141141
crate fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
142142
match res {
143143
Res::Def(DefKind::Macro(..), def_id) => self.get_macro_by_def_id(def_id),
144-
Res::NonMacroAttr(attr_kind) =>
145-
Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
144+
Res::NonMacroAttr(attr_kind) => Some(self.non_macro_attr(attr_kind.is_used())),
146145
_ => None,
147146
}
148147
}

src/librustc_resolve/diagnostics.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use syntax_pos::hygiene::MacroKind;
1919
use syntax_pos::{BytePos, Span, MultiSpan};
2020

2121
use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
22-
use crate::{path_names_to_string, KNOWN_TOOLS};
22+
use crate::path_names_to_string;
2323
use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
2424
use crate::{PathResult, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Segment};
2525

@@ -400,6 +400,14 @@ impl<'a> Resolver<'a> {
400400
Scope::Module(module) => {
401401
this.add_module_candidates(module, &mut suggestions, filter_fn);
402402
}
403+
Scope::RegisteredAttrs => {
404+
let res = Res::NonMacroAttr(NonMacroAttrKind::Registered);
405+
if filter_fn(res) {
406+
suggestions.extend(this.registered_attrs.iter().map(|ident| {
407+
TypoSuggestion::from_res(ident.name, res)
408+
}));
409+
}
410+
}
403411
Scope::MacroUsePrelude => {
404412
suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| {
405413
let res = binding.res();
@@ -439,8 +447,8 @@ impl<'a> Resolver<'a> {
439447
}
440448
Scope::ToolPrelude => {
441449
let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
442-
suggestions.extend(KNOWN_TOOLS.iter().map(|name| {
443-
TypoSuggestion::from_res(*name, res)
450+
suggestions.extend(this.registered_tools.iter().map(|ident| {
451+
TypoSuggestion::from_res(ident.name, res)
444452
}));
445453
}
446454
Scope::StdLibPrelude => {

src/librustc_resolve/lib.rs

+16-11
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,6 @@ mod check_unused;
7474
mod build_reduced_graph;
7575
mod resolve_imports;
7676

77-
const KNOWN_TOOLS: &[Name] = &[sym::clippy, sym::rustfmt];
78-
7977
enum Weak {
8078
Yes,
8179
No,
@@ -102,6 +100,7 @@ enum Scope<'a> {
102100
MacroRules(LegacyScope<'a>),
103101
CrateRoot,
104102
Module(Module<'a>),
103+
RegisteredAttrs,
105104
MacroUsePrelude,
106105
BuiltinAttrs,
107106
LegacyPluginHelpers,
@@ -621,7 +620,6 @@ enum AmbiguityKind {
621620
Import,
622621
BuiltinAttr,
623622
DeriveHelper,
624-
LegacyHelperVsPrelude,
625623
LegacyVsModern,
626624
GlobVsOuter,
627625
GlobVsGlob,
@@ -638,8 +636,6 @@ impl AmbiguityKind {
638636
"built-in attribute vs any other name",
639637
AmbiguityKind::DeriveHelper =>
640638
"derive helper attribute vs any other name",
641-
AmbiguityKind::LegacyHelperVsPrelude =>
642-
"legacy plugin helper attribute vs name from prelude",
643639
AmbiguityKind::LegacyVsModern =>
644640
"`macro_rules` vs non-`macro_rules` from other module",
645641
AmbiguityKind::GlobVsOuter =>
@@ -916,6 +912,8 @@ pub struct Resolver<'a> {
916912
crate_loader: CrateLoader<'a>,
917913
macro_names: FxHashSet<Ident>,
918914
builtin_macros: FxHashMap<Name, SyntaxExtension>,
915+
registered_attrs: FxHashSet<Ident>,
916+
registered_tools: FxHashSet<Ident>,
919917
macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
920918
all_macros: FxHashMap<Name, Res>,
921919
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
@@ -1138,6 +1136,9 @@ impl<'a> Resolver<'a> {
11381136
}
11391137
}
11401138

1139+
let (registered_attrs, registered_tools) =
1140+
macros::registered_attrs_and_tools(session, &krate.attrs);
1141+
11411142
let mut invocation_parent_scopes = FxHashMap::default();
11421143
invocation_parent_scopes.insert(ExpnId::root(), ParentScope::module(graph_root));
11431144

@@ -1207,6 +1208,8 @@ impl<'a> Resolver<'a> {
12071208
crate_loader: CrateLoader::new(session, metadata_loader, crate_name),
12081209
macro_names: FxHashSet::default(),
12091210
builtin_macros: Default::default(),
1211+
registered_attrs,
1212+
registered_tools,
12101213
macro_use_prelude: FxHashMap::default(),
12111214
all_macros: FxHashMap::default(),
12121215
macro_map: FxHashMap::default(),
@@ -1484,6 +1487,7 @@ impl<'a> Resolver<'a> {
14841487
Scope::MacroRules(..) => true,
14851488
Scope::CrateRoot => true,
14861489
Scope::Module(..) => true,
1490+
Scope::RegisteredAttrs => use_prelude,
14871491
Scope::MacroUsePrelude => use_prelude || rust_2015,
14881492
Scope::BuiltinAttrs => true,
14891493
Scope::LegacyPluginHelpers => use_prelude || rust_2015,
@@ -1528,11 +1532,12 @@ impl<'a> Resolver<'a> {
15281532
match ns {
15291533
TypeNS => Scope::ExternPrelude,
15301534
ValueNS => Scope::StdLibPrelude,
1531-
MacroNS => Scope::MacroUsePrelude,
1535+
MacroNS => Scope::RegisteredAttrs,
15321536
}
15331537
}
15341538
}
15351539
}
1540+
Scope::RegisteredAttrs => Scope::MacroUsePrelude,
15361541
Scope::MacroUsePrelude => Scope::StdLibPrelude,
15371542
Scope::BuiltinAttrs => Scope::LegacyPluginHelpers,
15381543
Scope::LegacyPluginHelpers => break, // nowhere else to search
@@ -1688,11 +1693,11 @@ impl<'a> Resolver<'a> {
16881693
if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
16891694
return Some(LexicalScopeBinding::Item(binding));
16901695
}
1691-
}
1692-
if ns == TypeNS && KNOWN_TOOLS.contains(&ident.name) {
1693-
let binding = (Res::ToolMod, ty::Visibility::Public,
1694-
DUMMY_SP, ExpnId::root()).to_name_binding(self.arenas);
1695-
return Some(LexicalScopeBinding::Item(binding));
1696+
if let Some(ident) = self.registered_tools.get(&ident) {
1697+
let binding = (Res::ToolMod, ty::Visibility::Public,
1698+
ident.span, ExpnId::root()).to_name_binding(self.arenas);
1699+
return Some(LexicalScopeBinding::Item(binding));
1700+
}
16961701
}
16971702
if let Some(prelude) = self.prelude {
16981703
if let Ok(binding) = self.resolve_ident_in_module_unadjusted(

0 commit comments

Comments
 (0)