diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index d4d7af92fe3..025494e3fd7 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -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)] @@ -329,8 +329,24 @@ pub fn descr(self) -> &'static str { 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, } } } @@ -389,6 +405,7 @@ pub fn descr(&self) -> &'static str { pub fn article(&self) -> &'static str { match *self { Res::Def(kind, _) => kind.article(), + Res::NonMacroAttr(kind) => kind.article(), Res::Err => "an", _ => "a", } diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 2e23b8c870c..3f4b87a97c7 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -101,7 +101,6 @@ pub fn register_llvm_pass(&mut self, name: &str) { /// 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) { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 1ce356d4891..0fcac5aab62 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -141,8 +141,7 @@ impl<'a> Resolver<'a> { crate fn get_macro(&mut self, res: Res) -> Option> { 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, } } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 3d68b72a655..771519b86c1 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -19,7 +19,7 @@ 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}; @@ -400,6 +400,14 @@ fn early_lookup_typo_candidate( 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(); @@ -439,8 +447,8 @@ fn early_lookup_typo_candidate( } 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 => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e94b544582e..88c675a6ce5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -74,8 +74,6 @@ mod build_reduced_graph; mod resolve_imports; -const KNOWN_TOOLS: &[Name] = &[sym::clippy, sym::rustfmt]; - enum Weak { Yes, No, @@ -102,6 +100,7 @@ enum Scope<'a> { MacroRules(LegacyScope<'a>), CrateRoot, Module(Module<'a>), + RegisteredAttrs, MacroUsePrelude, BuiltinAttrs, LegacyPluginHelpers, @@ -621,7 +620,6 @@ enum AmbiguityKind { Import, BuiltinAttr, DeriveHelper, - LegacyHelperVsPrelude, LegacyVsModern, GlobVsOuter, GlobVsGlob, @@ -638,8 +636,6 @@ fn descr(self) -> &'static str { "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 => @@ -916,6 +912,8 @@ pub struct Resolver<'a> { crate_loader: CrateLoader<'a>, macro_names: FxHashSet, builtin_macros: FxHashMap, + registered_attrs: FxHashSet, + registered_tools: FxHashSet, macro_use_prelude: FxHashMap>, all_macros: FxHashMap, macro_map: FxHashMap>, @@ -1138,6 +1136,9 @@ pub fn new(session: &'a Session, } } + 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)); @@ -1207,6 +1208,8 @@ pub fn new(session: &'a Session, 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(), @@ -1484,6 +1487,7 @@ fn visit_scopes( 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, @@ -1528,11 +1532,12 @@ fn visit_scopes( 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 @@ -1688,11 +1693,11 @@ fn resolve_ident_in_lexical_scope(&mut self, 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( diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index cc811d3b59a..2d125a459c8 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -3,16 +3,17 @@ use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy}; use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope, Weak}; -use crate::{ModuleKind, NameBinding, PathResult, Segment, ToNameBinding}; -use crate::{ModuleOrUniformRoot, KNOWN_TOOLS}; +use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding}; use crate::Namespace::*; use crate::resolve_imports::ImportResolver; use rustc::hir::def::{self, DefKind, NonMacroAttrKind}; use rustc::hir::def_id; use rustc::middle::stability; +use rustc::session::Session; +use rustc::util::nodemap::FxHashSet; use rustc::{ty, lint, span_bug}; use syntax::ast::{self, NodeId, Ident}; -use syntax::attr::StabilityLevel; +use syntax::attr::{self, StabilityLevel}; use syntax::edition::Edition; use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name}; use syntax::feature_gate::GateIssue; @@ -93,6 +94,46 @@ fn fast_print_path(path: &ast::Path) -> Symbol { } } +/// The code common between processing `#![register_tool]` and `#![register_attr]`. +fn registered_idents( + sess: &Session, + attrs: &[ast::Attribute], + attr_name: Symbol, + descr: &str, +) -> FxHashSet { + let mut registered = FxHashSet::default(); + for attr in attr::filter_by_name(attrs, attr_name) { + for nested_meta in attr.meta_item_list().unwrap_or_default() { + match nested_meta.ident() { + Some(ident) => if let Some(old_ident) = registered.replace(ident) { + let msg = format!("{} `{}` was already registered", descr, ident); + sess.struct_span_err(ident.span, &msg) + .span_label(old_ident.span, "already registered here").emit(); + } + None => { + let msg = format!("`{}` only accepts identifiers", attr_name); + let span = nested_meta.span(); + sess.struct_span_err(span, &msg).span_label(span, "not an identifier").emit(); + } + } + } + } + registered +} + +crate fn registered_attrs_and_tools( + sess: &Session, + attrs: &[ast::Attribute], +) -> (FxHashSet, FxHashSet) { + let registered_attrs = registered_idents(sess, attrs, sym::register_attr, "attribute"); + let mut registered_tools = registered_idents(sess, attrs, sym::register_tool, "tool"); + // We implicitly add `rustfmt` and `clippy` to known tools, + // but it's not an error to register them explicitly. + let predefined_tools = [sym::clippy, sym::rustfmt]; + registered_tools.extend(predefined_tools.iter().cloned().map(Ident::with_dummy_span)); + (registered_attrs, registered_tools) +} + impl<'a> base::Resolver for Resolver<'a> { fn next_node_id(&mut self) -> NodeId { self.next_node_id() @@ -416,10 +457,9 @@ pub fn resolve_macro_path( struct Flags: u8 { const MACRO_RULES = 1 << 0; const MODULE = 1 << 1; - const PRELUDE = 1 << 2; - const MISC_SUGGEST_CRATE = 1 << 3; - const MISC_SUGGEST_SELF = 1 << 4; - const MISC_FROM_PRELUDE = 1 << 5; + const MISC_SUGGEST_CRATE = 1 << 2; + const MISC_SUGGEST_SELF = 1 << 3; + const MISC_FROM_PRELUDE = 1 << 4; } } @@ -453,6 +493,10 @@ struct Flags: u8 { // Go through all the scopes and try to resolve the name. let break_result = self.visit_scopes(scope_set, parent_scope, orig_ident, |this, scope, use_prelude, ident| { + let ok = |res, span, arenas| Ok(( + (res, ty::Visibility::Public, span, ExpnId::root()).to_name_binding(arenas), + Flags::empty(), + )); let result = match scope { Scope::DeriveHelpers => { let mut result = Err(Determinacy::Determined); @@ -461,10 +505,8 @@ struct Flags: u8 { match this.resolve_macro_path(derive, Some(MacroKind::Derive), parent_scope, true, force) { Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) { - let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), - ty::Visibility::Public, derive.span, ExpnId::root()) - .to_name_binding(this.arenas); - result = Ok((binding, Flags::empty())); + let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); + result = ok(res, derive.span, this.arenas); break; } Ok(_) | Err(Determinacy::Determined) => {} @@ -531,41 +573,39 @@ struct Flags: u8 { Err((Determinacy::Determined, _)) => Err(Determinacy::Determined), } } + Scope::RegisteredAttrs => match this.registered_attrs.get(&ident).cloned() { + Some(ident) => ok( + Res::NonMacroAttr(NonMacroAttrKind::Registered), ident.span, this.arenas + ), + None => Err(Determinacy::Determined) + } Scope::MacroUsePrelude => match this.macro_use_prelude.get(&ident.name).cloned() { - Some(binding) => Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)), + Some(binding) => Ok((binding, Flags::MISC_FROM_PRELUDE)), None => Err(Determinacy::determined( this.graph_root.unexpanded_invocations.borrow().is_empty() )) } Scope::BuiltinAttrs => if is_builtin_attr_name(ident.name) { - let binding = (Res::NonMacroAttr(NonMacroAttrKind::Builtin), - ty::Visibility::Public, DUMMY_SP, ExpnId::root()) - .to_name_binding(this.arenas); - Ok((binding, Flags::PRELUDE)) + ok(Res::NonMacroAttr(NonMacroAttrKind::Builtin), DUMMY_SP, this.arenas) } else { Err(Determinacy::Determined) } Scope::LegacyPluginHelpers => if this.session.plugin_attributes.borrow().iter() .any(|(name, _)| ident.name == *name) { - let binding = (Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper), - ty::Visibility::Public, DUMMY_SP, ExpnId::root()) - .to_name_binding(this.arenas); - Ok((binding, Flags::PRELUDE)) + let res = Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper); + ok(res, DUMMY_SP, this.arenas) } else { Err(Determinacy::Determined) } Scope::ExternPrelude => match this.extern_prelude_get(ident, !record_used) { - Some(binding) => Ok((binding, Flags::PRELUDE)), + Some(binding) => Ok((binding, Flags::empty())), None => Err(Determinacy::determined( this.graph_root.unexpanded_invocations.borrow().is_empty() )), } - Scope::ToolPrelude => if KNOWN_TOOLS.contains(&ident.name) { - let binding = (Res::ToolMod, ty::Visibility::Public, DUMMY_SP, ExpnId::root()) - .to_name_binding(this.arenas); - Ok((binding, Flags::PRELUDE)) - } else { - Err(Determinacy::Determined) + Scope::ToolPrelude => match this.registered_tools.get(&ident).cloned() { + Some(ident) => ok(Res::ToolMod, ident.span, this.arenas), + None => Err(Determinacy::Determined) } Scope::StdLibPrelude => { let mut result = Err(Determinacy::Determined); @@ -579,7 +619,7 @@ struct Flags: u8 { path_span, ) { if use_prelude || this.is_builtin_macro(binding.res()) { - result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)); + result = Ok((binding, Flags::MISC_FROM_PRELUDE)); } } } @@ -587,11 +627,7 @@ struct Flags: u8 { } Scope::BuiltinTypes => match this.primitive_type_table.primitive_types .get(&ident.name).cloned() { - Some(prim_ty) => { - let binding = (Res::PrimTy(prim_ty), ty::Visibility::Public, - DUMMY_SP, ExpnId::root()).to_name_binding(this.arenas); - Ok((binding, Flags::PRELUDE)) - } + Some(prim_ty) => ok(Res::PrimTy(prim_ty), DUMMY_SP, this.arenas), None => Err(Determinacy::Determined) } }; @@ -608,8 +644,6 @@ struct Flags: u8 { if res != innermost_res { let builtin = Res::NonMacroAttr(NonMacroAttrKind::Builtin); let derive_helper = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); - let legacy_helper = - Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper); let ambiguity_error_kind = if is_import { Some(AmbiguityKind::Import) @@ -617,11 +651,6 @@ struct Flags: u8 { Some(AmbiguityKind::BuiltinAttr) } else if innermost_res == derive_helper || res == derive_helper { Some(AmbiguityKind::DeriveHelper) - } else if innermost_res == legacy_helper && - flags.contains(Flags::PRELUDE) || - res == legacy_helper && - innermost_flags.contains(Flags::PRELUDE) { - Some(AmbiguityKind::LegacyHelperVsPrelude) } else if innermost_flags.contains(Flags::MACRO_RULES) && flags.contains(Flags::MODULE) && !this.disambiguate_legacy_vs_modern(innermost_binding, @@ -681,20 +710,7 @@ struct Flags: u8 { return Ok(binding); } - let determinacy = Determinacy::determined(determinacy == Determinacy::Determined || force); - if determinacy == Determinacy::Determined && macro_kind == Some(MacroKind::Attr) && - self.session.features_untracked().custom_attribute { - // For single-segment attributes interpret determinate "no resolution" as a custom - // attribute. (Lexical resolution implies the first segment and attr kind should imply - // the last segment, so we are certainly working with a single-segment attribute here.) - assert!(ns == MacroNS); - let binding = (Res::NonMacroAttr(NonMacroAttrKind::Custom), - ty::Visibility::Public, orig_ident.span, ExpnId::root()) - .to_name_binding(self.arenas); - Ok(binding) - } else { - Err(determinacy) - } + Err(Determinacy::determined(determinacy == Determinacy::Determined || force)) } crate fn finalize_macro_resolutions(&mut self) { @@ -705,16 +721,7 @@ struct Flags: u8 { // Make sure compilation does not succeed if preferred macro resolution // has changed after the macro had been expanded. In theory all such // situations should be reported as ambiguity errors, so this is a bug. - if initial_res == Res::NonMacroAttr(NonMacroAttrKind::Custom) { - // Yeah, legacy custom attributes are implemented using forced resolution - // (which is a best effort error recovery tool, basically), so we can't - // promise their resolution won't change later. - let msg = format!("inconsistent resolution for a macro: first {}, then {}", - initial_res.descr(), res.descr()); - this.session.span_err(span, &msg); - } else { - span_bug!(span, "inconsistent resolution for a macro"); - } + span_bug!(span, "inconsistent resolution for a macro"); } } else { // It's possible that the macro was unresolved (indeterminate) and silently @@ -826,7 +833,8 @@ fn prohibit_imported_non_macro_attrs(&self, binding: Option<&'a NameBinding<'a>> res: Option, span: Span) { if let Some(Res::NonMacroAttr(kind)) = res { if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) { - let msg = format!("cannot use a {} through an import", kind.descr()); + let msg = + format!("cannot use {} {} through an import", kind.article(), kind.descr()); let mut err = self.session.struct_span_err(span, &msg); if let Some(binding) = binding { err.span_note(binding.span, &format!("the {} imported here", kind.descr())); diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 1d198fca56b..d59d0f0e28e 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -265,9 +265,6 @@ pub fn set(&self, features: &mut Features, span: Span) { /// Allows the use of SIMD types in functions declared in `extern` blocks. (active, simd_ffi, "1.0.0", Some(27731), None), - /// Allows using custom attributes (RFC 572). - (active, custom_attribute, "1.0.0", Some(29642), None), - /// Allows using non lexical lifetimes (RFC 2094). (active, nll, "1.0.0", Some(43234), None), @@ -526,6 +523,12 @@ pub fn set(&self, features: &mut Features, span: Span) { /// Allows using the `efiapi` ABI. (active, abi_efiapi, "1.40.0", Some(65815), None), + /// Allows using the `#[register_attr]` attribute. + (active, register_attr, "1.41.0", Some(66080), None), + + /// Allows using the `#[register_attr]` attribute. + (active, register_tool, "1.41.0", Some(66079), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index b32a887c6b2..608cc2a09cb 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -329,6 +329,14 @@ macro_rules! experimental { gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)), gated!(track_caller, Whitelisted, template!(Word), experimental!(track_caller)), + gated!( + register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), + experimental!(register_attr), + ), + gated!( + register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), + experimental!(register_tool), + ), // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: diff --git a/src/libsyntax/feature_gate/removed.rs b/src/libsyntax/feature_gate/removed.rs index c7b931a6f70..f0aa74c65df 100644 --- a/src/libsyntax/feature_gate/removed.rs +++ b/src/libsyntax/feature_gate/removed.rs @@ -67,6 +67,9 @@ macro_rules! declare_features { Some("merged into `#![feature(slice_patterns)]`")), (removed, macro_reexport, "1.0.0", Some(29638), None, Some("subsumed by `pub use`")), + /// Allows using custom attributes (RFC 572). + (removed, custom_attribute, "1.0.0", Some(29642), None, + Some("removed in favor of `#![register_tool]` and `#![register_attr]`")), (removed, pushpop_unsafe, "1.2.0", None, None, None), (removed, needs_allocator, "1.4.0", Some(27389), None, Some("subsumed by `#![feature(allocator_internals)]`")), diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index f07d56e7ea2..c41f413970f 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -546,6 +546,8 @@ recursion_limit, reexport_test_harness_main, reflect, + register_attr, + register_tool, relaxed_adts, repr, repr128, diff --git a/src/test/ui-fulldeps/issue-15778-pass.rs b/src/test/ui-fulldeps/issue-15778-pass.rs index b93630d56b0..55f19ab4ee3 100644 --- a/src/test/ui-fulldeps/issue-15778-pass.rs +++ b/src/test/ui-fulldeps/issue-15778-pass.rs @@ -3,7 +3,15 @@ // ignore-stage1 // compile-flags: -D crate-not-okay -#![feature(plugin, custom_attribute, custom_inner_attributes, rustc_attrs)] +#![feature(plugin, register_attr, custom_inner_attributes, rustc_attrs)] + +#![register_attr( + rustc_crate_okay, + rustc_crate_blue, + rustc_crate_red, + rustc_crate_grey, + rustc_crate_green, +)] #![plugin(lint_for_crate_rpass)] #![rustc_crate_okay] diff --git a/src/test/ui-fulldeps/issue-15778-pass.stderr b/src/test/ui-fulldeps/issue-15778-pass.stderr index 0c30d2cdcbf..48b42958489 100644 --- a/src/test/ui-fulldeps/issue-15778-pass.stderr +++ b/src/test/ui-fulldeps/issue-15778-pass.stderr @@ -1,5 +1,5 @@ warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/issue-15778-pass.rs:8:1 + --> $DIR/issue-15778-pass.rs:16:1 | LL | #![plugin(lint_for_crate_rpass)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version diff --git a/src/test/ui/attributes/register-attr-tool-fail.rs b/src/test/ui/attributes/register-attr-tool-fail.rs new file mode 100644 index 00000000000..84736be844b --- /dev/null +++ b/src/test/ui/attributes/register-attr-tool-fail.rs @@ -0,0 +1,13 @@ +#![feature(register_attr)] +#![feature(register_tool)] + +#![register_attr] //~ ERROR malformed `register_attr` attribute input +#![register_tool] //~ ERROR malformed `register_tool` attribute input + +#![register_attr(a::b)] //~ ERROR `register_attr` only accepts identifiers +#![register_tool(a::b)] //~ ERROR `register_tool` only accepts identifiers + +#![register_attr(attr, attr)] //~ ERROR attribute `attr` was already registered +#![register_tool(tool, tool)] //~ ERROR tool `tool` was already registered + +fn main() {} diff --git a/src/test/ui/attributes/register-attr-tool-fail.stderr b/src/test/ui/attributes/register-attr-tool-fail.stderr new file mode 100644 index 00000000000..77acfcd87cf --- /dev/null +++ b/src/test/ui/attributes/register-attr-tool-fail.stderr @@ -0,0 +1,42 @@ +error: `register_attr` only accepts identifiers + --> $DIR/register-attr-tool-fail.rs:7:18 + | +LL | #![register_attr(a::b)] + | ^^^^ not an identifier + +error: attribute `attr` was already registered + --> $DIR/register-attr-tool-fail.rs:10:24 + | +LL | #![register_attr(attr, attr)] + | ---- ^^^^ + | | + | already registered here + +error: `register_tool` only accepts identifiers + --> $DIR/register-attr-tool-fail.rs:8:18 + | +LL | #![register_tool(a::b)] + | ^^^^ not an identifier + +error: tool `tool` was already registered + --> $DIR/register-attr-tool-fail.rs:11:24 + | +LL | #![register_tool(tool, tool)] + | ---- ^^^^ + | | + | already registered here + +error: malformed `register_attr` attribute input + --> $DIR/register-attr-tool-fail.rs:4:1 + | +LL | #![register_attr] + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[register_attr(attr1, attr2, ...)]` + +error: malformed `register_tool` attribute input + --> $DIR/register-attr-tool-fail.rs:5:1 + | +LL | #![register_tool] + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[register_tool(tool1, tool2, ...)]` + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/attributes/register-attr-tool-import.rs b/src/test/ui/attributes/register-attr-tool-import.rs new file mode 100644 index 00000000000..3d0cf9154fb --- /dev/null +++ b/src/test/ui/attributes/register-attr-tool-import.rs @@ -0,0 +1,14 @@ +// edition:2018 + +#![feature(register_attr)] +#![feature(register_tool)] + +#![register_attr(attr)] +#![register_tool(tool)] + +use attr as renamed_attr; // OK +use tool as renamed_tool; // OK + +#[renamed_attr] //~ ERROR cannot use an explicitly registered attribute through an import +#[renamed_tool::attr] //~ ERROR cannot use a tool module through an import +fn main() {} diff --git a/src/test/ui/attributes/register-attr-tool-import.stderr b/src/test/ui/attributes/register-attr-tool-import.stderr new file mode 100644 index 00000000000..6f280c8e0d9 --- /dev/null +++ b/src/test/ui/attributes/register-attr-tool-import.stderr @@ -0,0 +1,26 @@ +error: cannot use an explicitly registered attribute through an import + --> $DIR/register-attr-tool-import.rs:12:3 + | +LL | #[renamed_attr] + | ^^^^^^^^^^^^ + | +note: the explicitly registered attribute imported here + --> $DIR/register-attr-tool-import.rs:9:5 + | +LL | use attr as renamed_attr; // OK + | ^^^^^^^^^^^^^^^^^^^^ + +error: cannot use a tool module through an import + --> $DIR/register-attr-tool-import.rs:13:3 + | +LL | #[renamed_tool::attr] + | ^^^^^^^^^^^^ + | +note: the tool module imported here + --> $DIR/register-attr-tool-import.rs:10:5 + | +LL | use tool as renamed_tool; // OK + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/attributes/register-attr-tool-prelude.rs b/src/test/ui/attributes/register-attr-tool-prelude.rs new file mode 100644 index 00000000000..a491773f5eb --- /dev/null +++ b/src/test/ui/attributes/register-attr-tool-prelude.rs @@ -0,0 +1,14 @@ +#![feature(register_attr)] +#![feature(register_tool)] + +#![register_attr(attr)] +#![register_tool(tool)] + +#[no_implicit_prelude] +mod m { + #[attr] //~ ERROR cannot find attribute `attr` in this scope + #[tool::attr] //~ ERROR failed to resolve: use of undeclared type or module `tool` + fn check() {} +} + +fn main() {} diff --git a/src/test/ui/attributes/register-attr-tool-prelude.stderr b/src/test/ui/attributes/register-attr-tool-prelude.stderr new file mode 100644 index 00000000000..66a4eeb6aa4 --- /dev/null +++ b/src/test/ui/attributes/register-attr-tool-prelude.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: use of undeclared type or module `tool` + --> $DIR/register-attr-tool-prelude.rs:10:7 + | +LL | #[tool::attr] + | ^^^^ use of undeclared type or module `tool` + +error: cannot find attribute `attr` in this scope + --> $DIR/register-attr-tool-prelude.rs:9:7 + | +LL | #[attr] + | ^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/attributes/register-attr-tool-unused.rs b/src/test/ui/attributes/register-attr-tool-unused.rs new file mode 100644 index 00000000000..546e372f5e3 --- /dev/null +++ b/src/test/ui/attributes/register-attr-tool-unused.rs @@ -0,0 +1,10 @@ +#![deny(unused)] + +#![feature(register_attr)] +#![feature(register_tool)] + +#[register_attr(attr)] //~ ERROR crate-level attribute should be an inner attribute + //~| ERROR unused attribute +#[register_tool(tool)] //~ ERROR crate-level attribute should be an inner attribute + //~| ERROR unused attribute +fn main() {} diff --git a/src/test/ui/attributes/register-attr-tool-unused.stderr b/src/test/ui/attributes/register-attr-tool-unused.stderr new file mode 100644 index 00000000000..0756c572c35 --- /dev/null +++ b/src/test/ui/attributes/register-attr-tool-unused.stderr @@ -0,0 +1,33 @@ +error: unused attribute + --> $DIR/register-attr-tool-unused.rs:6:1 + | +LL | #[register_attr(attr)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/register-attr-tool-unused.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]` + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/register-attr-tool-unused.rs:6:1 + | +LL | #[register_attr(attr)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/register-attr-tool-unused.rs:8:1 + | +LL | #[register_tool(tool)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/register-attr-tool-unused.rs:8:1 + | +LL | #[register_tool(tool)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/attributes/register-attr-tool.rs b/src/test/ui/attributes/register-attr-tool.rs new file mode 100644 index 00000000000..ee9da74d4fb --- /dev/null +++ b/src/test/ui/attributes/register-attr-tool.rs @@ -0,0 +1,19 @@ +// check-pass +// compile-flags: --cfg foo + +#![feature(register_attr)] +#![feature(register_tool)] + +#![register_attr(attr)] +#![register_tool(tool)] +#![register_tool(rustfmt, clippy)] // OK +#![cfg_attr(foo, register_attr(conditional_attr))] +#![cfg_attr(foo, register_tool(conditional_tool))] + +#[attr] +#[tool::attr] +#[rustfmt::attr] +#[clippy::attr] +#[conditional_attr] +#[conditional_tool::attr] +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs index e4c80141aa2..724e53debeb 100644 --- a/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs +++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs @@ -1,8 +1,6 @@ // This test ensures that attributes on formals in generic parameter // lists are included when we are checking for unstable attributes. -// gate-test-custom_attribute - struct StLt<#[lt_struct] 'a>(&'a u32); //~^ ERROR cannot find attribute `lt_struct` in this scope struct StTy<#[ty_struct] I>(I); diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr index bc89caddb44..b33710ce049 100644 --- a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr +++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr @@ -1,101 +1,101 @@ error: cannot find attribute `lt_hof` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:53:21 + --> $DIR/feature-gate-custom_attribute2.rs:51:21 | LL | where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 | ^^^^^^ error: cannot find attribute `ty_meth` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:48:15 + --> $DIR/feature-gate-custom_attribute2.rs:46:15 | LL | fn m_ty<#[ty_meth] P>(_: P) { } | ^^^^^^^ error: cannot find attribute `lt_meth` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:46:15 + --> $DIR/feature-gate-custom_attribute2.rs:44:15 | LL | fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } | ^^^^^^^ error: cannot find attribute `ty_fn` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:42:11 + --> $DIR/feature-gate-custom_attribute2.rs:40:11 | LL | fn f_ty<#[ty_fn] O>(_: O) { } | ^^^^^ error: cannot find attribute `lt_fn` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:40:11 + --> $DIR/feature-gate-custom_attribute2.rs:38:11 | LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } | ^^^^^ error: cannot find attribute `ty_impl_for` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:35:8 + --> $DIR/feature-gate-custom_attribute2.rs:33:8 | LL | impl<#[ty_impl_for] N> TrTy for StTy { | ^^^^^^^^^^^ error: cannot find attribute `lt_impl_for` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:31:8 + --> $DIR/feature-gate-custom_attribute2.rs:29:8 | LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> { | ^^^^^^^^^^^ error: cannot find attribute `ty_inherent` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:28:8 + --> $DIR/feature-gate-custom_attribute2.rs:26:8 | LL | impl<#[ty_inherent] M> StTy { } | ^^^^^^^^^^^ error: cannot find attribute `lt_inherent` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:26:8 + --> $DIR/feature-gate-custom_attribute2.rs:24:8 | LL | impl<#[lt_inherent] 'e> StLt<'e> { } | ^^^^^^^^^^^ error: cannot find attribute `ty_type` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:23:13 + --> $DIR/feature-gate-custom_attribute2.rs:21:13 | LL | type TyTy<#[ty_type] L> = (L, ); | ^^^^^^^ error: cannot find attribute `lt_type` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:21:13 + --> $DIR/feature-gate-custom_attribute2.rs:19:13 | LL | type TyLt<#[lt_type] 'd> = &'d u32; | ^^^^^^^ error: cannot find attribute `ty_trait` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:18:14 + --> $DIR/feature-gate-custom_attribute2.rs:16:14 | LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); } | ^^^^^^^^ error: cannot find attribute `lt_trait` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:16:14 + --> $DIR/feature-gate-custom_attribute2.rs:14:14 | LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } | ^^^^^^^^ error: cannot find attribute `ty_enum` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:13:13 + --> $DIR/feature-gate-custom_attribute2.rs:11:13 | LL | enum EnTy<#[ty_enum] J> { A(J), B } | ^^^^^^^ error: cannot find attribute `lt_enum` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:11:13 + --> $DIR/feature-gate-custom_attribute2.rs:9:13 | LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B } | ^^^^^^^ error: cannot find attribute `ty_struct` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:8:15 + --> $DIR/feature-gate-custom_attribute2.rs:6:15 | LL | struct StTy<#[ty_struct] I>(I); | ^^^^^^^^^ error: cannot find attribute `lt_struct` in this scope - --> $DIR/feature-gate-custom_attribute2.rs:6:15 + --> $DIR/feature-gate-custom_attribute2.rs:4:15 | LL | struct StLt<#[lt_struct] 'a>(&'a u32); | ^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-register_attr.rs b/src/test/ui/feature-gates/feature-gate-register_attr.rs new file mode 100644 index 00000000000..36dce2aa7b9 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-register_attr.rs @@ -0,0 +1,3 @@ +#![register_attr(attr)] //~ ERROR the `#[register_attr]` attribute is an experimental feature + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-register_attr.stderr b/src/test/ui/feature-gates/feature-gate-register_attr.stderr new file mode 100644 index 00000000000..3965d481d9b --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-register_attr.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[register_attr]` attribute is an experimental feature + --> $DIR/feature-gate-register_attr.rs:1:1 + | +LL | #![register_attr(attr)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/66080 + = help: add `#![feature(register_attr)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-register_tool.rs b/src/test/ui/feature-gates/feature-gate-register_tool.rs new file mode 100644 index 00000000000..e599593283b --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-register_tool.rs @@ -0,0 +1,3 @@ +#![register_tool(tool)] //~ ERROR the `#[register_tool]` attribute is an experimental feature + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-register_tool.stderr b/src/test/ui/feature-gates/feature-gate-register_tool.stderr new file mode 100644 index 00000000000..177342aed90 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-register_tool.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[register_tool]` attribute is an experimental feature + --> $DIR/feature-gate-register_tool.rs:1:1 + | +LL | #![register_tool(tool)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/66079 + = help: add `#![feature(register_tool)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.rs b/src/test/ui/proc-macro/expand-to-unstable-2.rs index da7c89fdd46..4160e5418b7 100644 --- a/src/test/ui/proc-macro/expand-to-unstable-2.rs +++ b/src/test/ui/proc-macro/expand-to-unstable-2.rs @@ -1,6 +1,8 @@ // aux-build:derive-unstable-2.rs -#![feature(custom_attribute)] +#![feature(register_attr)] + +#![register_attr(rustc_foo)] #[macro_use] extern crate derive_unstable_2; diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.stderr b/src/test/ui/proc-macro/expand-to-unstable-2.stderr index 01e6a4a8ab9..5b6184afacd 100644 --- a/src/test/ui/proc-macro/expand-to-unstable-2.stderr +++ b/src/test/ui/proc-macro/expand-to-unstable-2.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler - --> $DIR/expand-to-unstable-2.rs:8:10 + --> $DIR/expand-to-unstable-2.rs:10:10 | LL | #[derive(Unstable)] | ^^^^^^^^ diff --git a/src/test/ui/proc-macro/issue-41211.rs b/src/test/ui/proc-macro/issue-41211.rs index 491b89b2f55..072a63baf3a 100644 --- a/src/test/ui/proc-macro/issue-41211.rs +++ b/src/test/ui/proc-macro/issue-41211.rs @@ -3,11 +3,13 @@ // FIXME: https://github.com/rust-lang/rust/issues/41430 // This is a temporary regression test for the ICE reported in #41211 -#![feature(custom_attribute)] #![feature(custom_inner_attributes)] +#![feature(register_attr)] + +#![register_attr(identity_attr)] #![identity_attr] -//~^ ERROR inconsistent resolution for a macro: first custom attribute, then attribute macro +//~^ ERROR `identity_attr` is ambiguous extern crate test_macros; use test_macros::identity_attr; diff --git a/src/test/ui/proc-macro/issue-41211.stderr b/src/test/ui/proc-macro/issue-41211.stderr index f01cba0c930..22ad4aa147b 100644 --- a/src/test/ui/proc-macro/issue-41211.stderr +++ b/src/test/ui/proc-macro/issue-41211.stderr @@ -1,8 +1,21 @@ -error: inconsistent resolution for a macro: first custom attribute, then attribute macro - --> $DIR/issue-41211.rs:9:4 +error[E0659]: `identity_attr` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) + --> $DIR/issue-41211.rs:11:4 | LL | #![identity_attr] - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ ambiguous name + | +note: `identity_attr` could refer to the attribute macro imported here + --> $DIR/issue-41211.rs:14:5 + | +LL | use test_macros::identity_attr; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::identity_attr` to refer to this attribute macro unambiguously +note: `identity_attr` could also refer to the explicitly registered attribute defined here + --> $DIR/issue-41211.rs:9:18 + | +LL | #![register_attr(identity_attr)] + | ^^^^^^^^^^^^^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/span/issue-36530.rs b/src/test/ui/span/issue-36530.rs index 14b2c8644e0..4776740d8de 100644 --- a/src/test/ui/span/issue-36530.rs +++ b/src/test/ui/span/issue-36530.rs @@ -1,6 +1,8 @@ // gate-test-custom_inner_attributes -#![feature(custom_attribute)] +#![feature(register_attr)] + +#![register_attr(foo)] #[foo] mod foo { diff --git a/src/test/ui/span/issue-36530.stderr b/src/test/ui/span/issue-36530.stderr index c6b7895e65a..2d3972917df 100644 --- a/src/test/ui/span/issue-36530.stderr +++ b/src/test/ui/span/issue-36530.stderr @@ -1,5 +1,5 @@ error[E0658]: non-builtin inner attributes are unstable - --> $DIR/issue-36530.rs:7:5 + --> $DIR/issue-36530.rs:9:5 | LL | #![foo] | ^^^^^^^