From 67a5b193c113b56cc885006a675280add09a14e3 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 5 Sep 2021 16:30:37 -0700 Subject: [PATCH 1/3] Check for duplicate attributes. --- compiler/rustc_feature/src/builtin_attrs.rs | 427 +++++++++++------- compiler/rustc_feature/src/lib.rs | 2 + compiler/rustc_passes/src/check_attr.rs | 118 ++++- .../ui/lint/unused/unused-attr-duplicate.rs | 108 +++++ .../lint/unused/unused-attr-duplicate.stderr | 306 +++++++++++++ .../ui/macros/macro-use-all-and-none.stderr | 3 +- 6 files changed, 791 insertions(+), 173 deletions(-) create mode 100644 src/test/ui/lint/unused/unused-attr-duplicate.rs create mode 100644 src/test/ui/lint/unused/unused-attr-duplicate.stderr diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 74a637fde33fc..f25b2d8f566c0 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1,5 +1,6 @@ //! Built-in attributes and `cfg` flag gating. +use AttributeDuplicates::*; use AttributeGate::*; use AttributeType::*; @@ -88,11 +89,66 @@ impl AttributeGate { /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now. #[derive(Clone, Copy, Default)] pub struct AttributeTemplate { + /// If `true`, the attribute is allowed to be a bare word like `#[test]`. pub word: bool, + /// If `Some`, the attribute is allowed to take a list of items like `#[allow(..)]`. pub list: Option<&'static str>, + /// If `Some`, the attribute is allowed to be a name/value pair where the + /// value is a string, like `#[must_use = "reason"]`. pub name_value_str: Option<&'static str>, } +/// How to handle multiple duplicate attributes on the same item. +#[derive(Clone, Copy, Default)] +pub enum AttributeDuplicates { + /// Duplicates of this attribute are allowed. + /// + /// This should only be used with attributes where duplicates have semantic + /// meaning, or some kind of "additive" behavior. For example, `#[warn(..)]` + /// can be specified multiple times, and it combines all the entries. Or use + /// this if there is validation done elsewhere. + #[default] + DuplicatesOk, + /// Duplicates after the first attribute will be an unused_attribute warning. + /// + /// This is usually used for "word" attributes, where they are used as a + /// boolean marker, like `#[used]`. It is not necessarily wrong that there + /// are duplicates, but the others should probably be removed. + WarnFollowing, + /// Same as `WarnFollowing`, but only issues warnings for word-style attributes. + /// + /// This is only for special cases, for example multiple `#[macro_use]` can + /// be warned, but multiple `#[macro_use(...)]` should not because the list + /// form has different meaning from the word form. + WarnFollowingWordOnly, + /// Duplicates after the first attribute will be an error. + /// + /// This should be used where duplicates would be ignored, but carry extra + /// meaning that could cause confusion. For example, `#[stable(since="1.0")] + /// #[stable(since="2.0")]`, which version should be used for `stable`? + ErrorFollowing, + /// Duplicates preceding the last instance of the attribute will be an error. + /// + /// This is the same as `ErrorFollowing`, except the last attribute is the + /// one that is "used". This is typically used in cases like codegen + /// attributes which usually only honor the last attribute. + ErrorPreceding, + /// Duplicates after the first attribute will be an unused_attribute warning + /// with a note that this will be an error in the future. + /// + /// This should be used for attributes that should be `ErrorFollowing`, but + /// because older versions of rustc silently accepted (and ignored) the + /// attributes, this is used to transition. + FutureWarnFollowing, + /// Duplicates preceding the last instance of the attribute will be a + /// warning, with a note that this will be an error in the future. + /// + /// This is the same as `FutureWarnFollowing`, except the last attribute is + /// the one that is "used". Ideally these can eventually migrate to + /// `ErrorPreceding`. + FutureWarnPreceding, +} + /// A convenience macro for constructing attribute templates. /// E.g., `template!(Word, List: "description")` means that the attribute /// supports forms `#[attr]` and `#[attr(description)]`. @@ -114,36 +170,45 @@ macro_rules! template { } macro_rules! ungated { - ($attr:ident, $typ:expr, $tpl:expr $(,)?) => { - BuiltinAttribute { name: sym::$attr, type_: $typ, template: $tpl, gate: Ungated } + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(,)?) => { + BuiltinAttribute { + name: sym::$attr, + type_: $typ, + template: $tpl, + gate: Ungated, + duplicates: $duplicates, + } }; } macro_rules! gated { - ($attr:ident, $typ:expr, $tpl:expr, $gate:ident, $msg:expr $(,)?) => { + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $gate:ident, $msg:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, type_: $typ, template: $tpl, + duplicates: $duplicates, gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)), } }; - ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $msg:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, type_: $typ, template: $tpl, + duplicates: $duplicates, gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)), } }; } macro_rules! rustc_attr { - (TEST, $attr:ident, $typ:expr, $tpl:expr $(,)?) => { + (TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr $(,)?) => { rustc_attr!( $attr, $typ, $tpl, + $duplicate, concat!( "the `#[", stringify!($attr), @@ -152,11 +217,12 @@ macro_rules! rustc_attr { ), ) }; - ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $msg:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, type_: $typ, template: $tpl, + duplicates: $duplicates, gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)), } }; @@ -175,6 +241,7 @@ pub struct BuiltinAttribute { pub name: Symbol, pub type_: AttributeType, pub template: AttributeTemplate, + pub duplicates: AttributeDuplicates, pub gate: AttributeGate, } @@ -186,42 +253,48 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== // Conditional compilation: - ungated!(cfg, Normal, template!(List: "predicate")), - ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ...")), + ungated!(cfg, Normal, template!(List: "predicate"), DuplicatesOk), + ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), DuplicatesOk), // Testing: - ungated!(ignore, Normal, template!(Word, NameValueStr: "reason")), + ungated!(ignore, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing), ungated!( should_panic, Normal, - template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), + template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), FutureWarnFollowing, ), // FIXME(Centril): This can be used on stable but shouldn't. - ungated!(reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name")), + ungated!(reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name"), ErrorFollowing), // Macros: - ungated!(automatically_derived, Normal, template!(Word)), - // FIXME(#14407) - ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ...")), - ungated!(macro_escape, Normal, template!(Word)), // Deprecated synonym for `macro_use`. - ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros")), - ungated!(proc_macro, Normal, template!(Word)), + ungated!(automatically_derived, Normal, template!(Word), WarnFollowing), + ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ..."), WarnFollowingWordOnly), + ungated!(macro_escape, Normal, template!(Word), WarnFollowing), // Deprecated synonym for `macro_use`. + ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros"), WarnFollowing), + ungated!(proc_macro, Normal, template!(Word), ErrorFollowing), ungated!( proc_macro_derive, Normal, - template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), + template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing, ), - ungated!(proc_macro_attribute, Normal, template!(Word)), + ungated!(proc_macro_attribute, Normal, template!(Word), ErrorFollowing), // Lints: - ungated!(warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), - ungated!(allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), - ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), - ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), - ungated!(must_use, Normal, template!(Word, NameValueStr: "reason")), + ungated!( + warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk + ), + ungated!( + allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk + ), + ungated!( + forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk + ), + ungated!( + deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk + ), + ungated!(must_use, Normal, template!(Word, NameValueStr: "reason"), FutureWarnFollowing), gated!( - must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), must_not_suspend, - experimental!(must_not_suspend) + must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, + must_not_suspend, experimental!(must_not_suspend) ), - // FIXME(#14407) ungated!( deprecated, Normal, template!( @@ -229,78 +302,86 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, NameValueStr: "reason" ), + // This has special duplicate handling in E0550 to handle duplicates with rustc_deprecated + DuplicatesOk ), // Crate properties: - ungated!(crate_name, CrateLevel, template!(NameValueStr: "name")), - ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|...")), - ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored")), + ungated!(crate_name, CrateLevel, template!(NameValueStr: "name"), FutureWarnFollowing), + ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), FutureWarnFollowing), + // crate_id is deprecated + ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored"), FutureWarnFollowing), // ABI, linking, symbols, and FFI ungated!( link, Normal, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#), + DuplicatesOk, ), - ungated!(link_name, Normal, template!(NameValueStr: "name")), - ungated!(no_link, Normal, template!(Word)), - ungated!(repr, Normal, template!(List: "C")), - ungated!(export_name, Normal, template!(NameValueStr: "name")), - ungated!(link_section, Normal, template!(NameValueStr: "name")), - ungated!(no_mangle, Normal, template!(Word)), - ungated!(used, Normal, template!(Word)), + ungated!(link_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), + ungated!(no_link, Normal, template!(Word), WarnFollowing), + ungated!(repr, Normal, template!(List: "C"), DuplicatesOk), + ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), + ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), + ungated!(no_mangle, Normal, template!(Word), WarnFollowing), + ungated!(used, Normal, template!(Word), WarnFollowing), // Limits: - ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")), - ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N")), + ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing), + ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing), gated!( - const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit, - experimental!(const_eval_limit) + const_eval_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing, + const_eval_limit, experimental!(const_eval_limit) ), gated!( - move_size_limit, CrateLevel, template!(NameValueStr: "N"), large_assignments, - experimental!(move_size_limit) + move_size_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing, + large_assignments, experimental!(move_size_limit) ), // Entry point: - ungated!(main, Normal, template!(Word)), - ungated!(start, Normal, template!(Word)), - ungated!(no_start, CrateLevel, template!(Word)), - ungated!(no_main, CrateLevel, template!(Word)), + ungated!(main, Normal, template!(Word), WarnFollowing), + ungated!(start, Normal, template!(Word), WarnFollowing), + ungated!(no_start, CrateLevel, template!(Word), WarnFollowing), + ungated!(no_main, CrateLevel, template!(Word), WarnFollowing), // Modules, prelude, and resolution: - ungated!(path, Normal, template!(NameValueStr: "file")), - ungated!(no_std, CrateLevel, template!(Word)), - ungated!(no_implicit_prelude, Normal, template!(Word)), - ungated!(non_exhaustive, Normal, template!(Word)), + ungated!(path, Normal, template!(NameValueStr: "file"), FutureWarnFollowing), + ungated!(no_std, CrateLevel, template!(Word), WarnFollowing), + ungated!(no_implicit_prelude, Normal, template!(Word), WarnFollowing), + ungated!(non_exhaustive, Normal, template!(Word), WarnFollowing), // Runtime - ungated!(windows_subsystem, Normal, template!(NameValueStr: "windows|console")), - ungated!(panic_handler, Normal, template!(Word)), // RFC 2070 + ungated!( + windows_subsystem, Normal, + template!(NameValueStr: "windows|console"), FutureWarnFollowing + ), + ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070 // Code generation: - ungated!(inline, Normal, template!(Word, List: "always|never")), - ungated!(cold, Normal, template!(Word)), - ungated!(no_builtins, Normal, template!(Word)), - ungated!(target_feature, Normal, template!(List: r#"enable = "name""#)), - ungated!(track_caller, Normal, template!(Word)), + ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing), + ungated!(cold, Normal, template!(Word), WarnFollowing), + ungated!(no_builtins, Normal, template!(Word), WarnFollowing), + ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk), + ungated!(track_caller, Normal, template!(Word), WarnFollowing), gated!( no_sanitize, Normal, - template!(List: "address, memory, thread"), + template!(List: "address, memory, thread"), DuplicatesOk, experimental!(no_sanitize) ), - gated!(no_coverage, Normal, template!(Word), experimental!(no_coverage)), + gated!(no_coverage, Normal, template!(Word), WarnFollowing, experimental!(no_coverage)), - // FIXME: #14408 assume docs are used since rustdoc looks at them. - ungated!(doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string")), + ungated!( + doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk + ), // ========================================================================== // Unstable attributes: // ========================================================================== // Linking: - gated!(naked, Normal, template!(Word), naked_functions, experimental!(naked)), + gated!(naked, Normal, template!(Word), WarnFollowing, naked_functions, experimental!(naked)), gated!( - link_ordinal, Normal, template!(List: "ordinal"), raw_dylib, + link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, raw_dylib, experimental!(link_ordinal) ), @@ -309,6 +390,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ name: sym::plugin, type_: CrateLevel, template: template!(List: "name"), + duplicates: DuplicatesOk, gate: Gated( Stability::Deprecated( "https://github.com/rust-lang/rust/pull/64675", @@ -321,42 +403,52 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ }, // Testing: - gated!(allow_fail, Normal, template!(Word), experimental!(allow_fail)), + gated!(allow_fail, Normal, template!(Word), WarnFollowing, experimental!(allow_fail)), gated!( - test_runner, CrateLevel, template!(List: "path"), custom_test_frameworks, + test_runner, CrateLevel, template!(List: "path"), ErrorFollowing, custom_test_frameworks, "custom test frameworks are an unstable feature", ), // RFC #1268 - gated!(marker, Normal, template!(Word), marker_trait_attr, experimental!(marker)), gated!( - thread_local, Normal, template!(Word), + marker, Normal, template!(Word), WarnFollowing, marker_trait_attr, experimental!(marker) + ), + gated!( + thread_local, Normal, template!(Word), WarnFollowing, "`#[thread_local]` is an experimental feature, and does not currently handle destructors", ), - gated!(no_core, CrateLevel, template!(Word), experimental!(no_core)), + gated!(no_core, CrateLevel, template!(Word), WarnFollowing, experimental!(no_core)), // RFC 2412 gated!( - optimize, Normal, template!(List: "size|speed"), optimize_attribute, + optimize, Normal, template!(List: "size|speed"), ErrorPreceding, optimize_attribute, experimental!(optimize), ), // RFC 2867 - gated!(instruction_set, Normal, template!(List: "set"), isa_attribute, experimental!(instruction_set)), + gated!( + instruction_set, Normal, template!(List: "set"), ErrorPreceding, + isa_attribute, experimental!(instruction_set) + ), - gated!(ffi_returns_twice, Normal, template!(Word), experimental!(ffi_returns_twice)), - gated!(ffi_pure, Normal, template!(Word), experimental!(ffi_pure)), - gated!(ffi_const, Normal, template!(Word), experimental!(ffi_const)), gated!( - register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), + ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice) + ), + gated!(ffi_pure, Normal, template!(Word), WarnFollowing, experimental!(ffi_pure)), + gated!(ffi_const, Normal, template!(Word), WarnFollowing, experimental!(ffi_const)), + gated!( + register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), DuplicatesOk, experimental!(register_attr), ), gated!( - register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), + register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), DuplicatesOk, experimental!(register_tool), ), - gated!(cmse_nonsecure_entry, Normal, template!(Word), experimental!(cmse_nonsecure_entry)), + gated!( + cmse_nonsecure_entry, Normal, template!(Word), WarnFollowing, + experimental!(cmse_nonsecure_entry) + ), // RFC 2632 gated!( - default_method_body_is_const, Normal, template!(Word), const_trait_impl, + default_method_body_is_const, Normal, template!(Word), WarnFollowing, const_trait_impl, "`default_method_body_is_const` is a temporary placeholder for declaring default bodies \ as `const`, which may be removed or renamed in the future." ), @@ -365,34 +457,33 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes: Stability, deprecation, and unsafe: // ========================================================================== - ungated!(feature, CrateLevel, template!(List: "name1, name1, ...")), - // FIXME(#14407) -- only looked at on-demand so we can't - // guarantee they'll have already been checked. + ungated!(feature, CrateLevel, template!(List: "name1, name1, ..."), DuplicatesOk), + // DuplicatesOk since it has its own validation ungated!( rustc_deprecated, Normal, - template!(List: r#"since = "version", reason = "...""#) + template!(List: r#"since = "version", reason = "...""#), DuplicatesOk // See E0550 + ), + // DuplicatesOk since it has its own validation + ungated!( + stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk ), - // FIXME(#14407) - ungated!(stable, Normal, template!(List: r#"feature = "name", since = "version""#)), - // FIXME(#14407) ungated!( unstable, Normal, - template!(List: r#"feature = "name", reason = "...", issue = "N""#), + template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk, ), - // FIXME(#14407) - ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#)), - // FIXME(#14407) - ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#)), + ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk), + ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk), gated!( - allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), + allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, "allow_internal_unstable side-steps feature gating and stability checks", ), gated!( - rustc_allow_const_fn_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), + rustc_allow_const_fn_unstable, Normal, + template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" ), gated!( - allow_internal_unsafe, Normal, template!(Word), + allow_internal_unsafe, Normal, template!(Word), WarnFollowing, "allow_internal_unsafe side-steps the unsafe_code lint", ), @@ -400,9 +491,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes: Type system related: // ========================================================================== - gated!(fundamental, Normal, template!(Word), experimental!(fundamental)), + gated!(fundamental, Normal, template!(Word), WarnFollowing, experimental!(fundamental)), gated!( - may_dangle, Normal, template!(Word), dropck_eyepatch, + may_dangle, Normal, template!(Word), WarnFollowing, dropck_eyepatch, "`may_dangle` has unstable semantics and may be removed in the future", ), @@ -410,26 +501,32 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes: Runtime related: // ========================================================================== - rustc_attr!(rustc_allocator, Normal, template!(Word), IMPL_DETAIL), - rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), IMPL_DETAIL), - gated!(alloc_error_handler, Normal, template!(Word), experimental!(alloc_error_handler)), + rustc_attr!(rustc_allocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), + rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), + gated!( + alloc_error_handler, Normal, template!(Word), WarnFollowing, + experimental!(alloc_error_handler) + ), gated!( - default_lib_allocator, Normal, template!(Word), allocator_internals, + default_lib_allocator, Normal, template!(Word), WarnFollowing, allocator_internals, experimental!(default_lib_allocator), ), gated!( - needs_allocator, Normal, template!(Word), allocator_internals, + needs_allocator, Normal, template!(Word), WarnFollowing, allocator_internals, experimental!(needs_allocator), ), - gated!(panic_runtime, Normal, template!(Word), experimental!(panic_runtime)), - gated!(needs_panic_runtime, Normal, template!(Word), experimental!(needs_panic_runtime)), + gated!(panic_runtime, Normal, template!(Word), WarnFollowing, experimental!(panic_runtime)), gated!( - compiler_builtins, Normal, template!(Word), + needs_panic_runtime, Normal, template!(Word), WarnFollowing, + experimental!(needs_panic_runtime) + ), + gated!( + compiler_builtins, Normal, template!(Word), WarnFollowing, "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ which contains compiler-rt intrinsics and will never be stable", ), gated!( - profiler_runtime, Normal, template!(Word), + profiler_runtime, Normal, template!(Word), WarnFollowing, "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ which contains the profiler runtime and will never be stable", ), @@ -439,10 +536,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== gated!( - linkage, Normal, template!(NameValueStr: "external|internal|..."), + linkage, Normal, template!(NameValueStr: "external|internal|..."), ErrorPreceding, "the `linkage` attribute is experimental and not portable across platforms", ), - rustc_attr!(rustc_std_internal_symbol, Normal, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!( + rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE + ), // ========================================================================== // Internal attributes, Macro related: @@ -450,13 +549,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!( rustc_builtin_macro, Normal, - template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), + template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing, IMPL_DETAIL, ), - rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), rustc_attr!( rustc_macro_transparency, Normal, - template!(NameValueStr: "transparent|semitransparent|opaque"), + template!(NameValueStr: "transparent|semitransparent|opaque"), ErrorFollowing, "used internally for testing macro hygiene", ), @@ -470,39 +569,49 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, NameValueStr: "message" ), + ErrorFollowing, INTERNAL_UNSTABLE ), // Enumerates "identity-like" conversion methods to suggest on type mismatch. - rustc_attr!(rustc_conversion_suggestion, Normal, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!( + rustc_conversion_suggestion, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE + ), // Prevents field reads in the marked trait or method to be considered // during dead code analysis. - rustc_attr!(rustc_trivial_field_reads, Normal, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!( + rustc_trivial_field_reads, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE + ), // ========================================================================== // Internal attributes, Const related: // ========================================================================== - rustc_attr!(rustc_promotable, Normal, template!(Word), IMPL_DETAIL), - rustc_attr!(rustc_legacy_const_generics, Normal, template!(List: "N"), INTERNAL_UNSTABLE), + rustc_attr!(rustc_promotable, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), + rustc_attr!( + rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing, + INTERNAL_UNSTABLE + ), // Do not const-check this function's body. It will always get replaced during CTFE. - rustc_attr!(rustc_do_not_const_check, Normal, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!( + rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE + ), // ========================================================================== // Internal attributes, Layout related: // ========================================================================== rustc_attr!( - rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), + rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), ErrorFollowing, "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ niche optimizations in libcore and will never be stable", ), rustc_attr!( - rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), + rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), ErrorFollowing, "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ niche optimizations in libcore and will never be stable", ), rustc_attr!( - rustc_nonnull_optimization_guaranteed, Normal, template!(Word), + rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing, "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \ niche optimizations in libcore and will never be stable", ), @@ -511,13 +620,14 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Misc: // ========================================================================== gated!( - lang, Normal, template!(NameValueStr: "name"), lang_items, + lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, lang_items, "language items are subject to change", ), BuiltinAttribute { name: sym::rustc_diagnostic_item, type_: Normal, template: template!(NameValueStr: "name"), + duplicates: ErrorFollowing, gate: Gated( Stability::Unstable, sym::rustc_attrs, @@ -527,41 +637,43 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ }, gated!( // Used in resolve: - prelude_import, Normal, template!(Word), + prelude_import, Normal, template!(Word), WarnFollowing, "`#[prelude_import]` is for use by rustc only", ), gated!( - rustc_paren_sugar, Normal, template!(Word), unboxed_closures, + rustc_paren_sugar, Normal, template!(Word), WarnFollowing, unboxed_closures, "unboxed_closures are still evolving", ), rustc_attr!( - rustc_inherit_overflow_checks, Normal, template!(Word), + rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ overflow checking behavior of several libcore functions that are inlined \ across crates and will never be stable", ), - rustc_attr!(rustc_reservation_impl, Normal, template!(NameValueStr: "reservation message"), - "the `#[rustc_reservation_impl]` attribute is internally used \ - for reserving for `for From for T` impl" + rustc_attr!( + rustc_reservation_impl, Normal, + template!(NameValueStr: "reservation message"), ErrorFollowing, + "the `#[rustc_reservation_impl]` attribute is internally used \ + for reserving for `for From for T` impl" ), rustc_attr!( - rustc_test_marker, Normal, template!(Word), + rustc_test_marker, Normal, template!(Word), WarnFollowing, "the `#[rustc_test_marker]` attribute is used internally to track tests", ), rustc_attr!( - rustc_unsafe_specialization_marker, Normal, template!(Word), + rustc_unsafe_specialization_marker, Normal, template!(Word), WarnFollowing, "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" ), rustc_attr!( - rustc_specialization_trait, Normal, template!(Word), + rustc_specialization_trait, Normal, template!(Word), WarnFollowing, "the `#[rustc_specialization_trait]` attribute is used to check specializations" ), rustc_attr!( - rustc_main, Normal, template!(Word), + rustc_main, Normal, template!(Word), WarnFollowing, "the `#[rustc_main]` attribute is used internally to specify test entry point function", ), rustc_attr!( - rustc_skip_array_during_method_dispatch, Normal, template!(Word), + rustc_skip_array_during_method_dispatch, Normal, template!(Word), WarnFollowing, "the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \ from method dispatch when the receiver is an array, for compatibility in editions < 2021." ), @@ -570,48 +682,53 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Testing: // ========================================================================== - rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), - rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word)), - rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word)), - rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word)), - rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), - rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), - rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), + rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_variance, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing), + rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing), rustc_attr!( TEST, rustc_error, Normal, - template!(Word, List: "delay_span_bug_from_inside_query") + template!(Word, List: "delay_span_bug_from_inside_query"), WarnFollowingWordOnly + ), + rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing), + rustc_attr!( + TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode"), DuplicatesOk + ), + rustc_attr!( + TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode"), DuplicatesOk ), - rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word)), - rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word)), - rustc_attr!(TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode")), - rustc_attr!(TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode")), rustc_attr!( TEST, rustc_clean, Normal, template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), + DuplicatesOk, ), rustc_attr!( TEST, rustc_partition_reused, Normal, - template!(List: r#"cfg = "...", module = "...""#), + template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, ), rustc_attr!( TEST, rustc_partition_codegened, Normal, - template!(List: r#"cfg = "...", module = "...""#), + template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, ), rustc_attr!( TEST, rustc_expected_cgu_reuse, Normal, - template!(List: r#"cfg = "...", module = "...", kind = "...""#), - ), - rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word)), - rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word)), - rustc_attr!(TEST, rustc_def_path, Normal, template!(Word)), - rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ...")), - rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word)), - rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word)), - rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word)), - rustc_attr!(TEST, rustc_dump_vtable, Normal, template!(Word)), - rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/)), + template!(List: r#"cfg = "...", module = "...", kind = "...""#), DuplicatesOk, + ), + rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk), + rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_dump_vtable, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/), DuplicatesOk), gated!( - omit_gdb_pretty_printer_section, Normal, template!(Word), + omit_gdb_pretty_printer_section, Normal, template!(Word), WarnFollowing, "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite", ), ]; diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index b25aab21e491a..bfc537cfae2cb 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -11,6 +11,7 @@ //! even if it is stabilized or removed, *do not remove it*. Instead, move the //! symbol to the `accepted` or `removed` modules respectively. +#![feature(derive_default_enum)] #![feature(once_cell)] mod accepted; @@ -146,6 +147,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option( tcx: TyCtxt<'tcx>, @@ -69,7 +70,7 @@ impl CheckAttrVisitor<'tcx> { let mut doc_aliases = FxHashMap::default(); let mut is_valid = true; let mut specified_inline = None; - let mut seen = FxHashSet::default(); + let mut seen = FxHashMap::default(); let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { let attr_is_valid = match attr.name_or_empty() { @@ -148,6 +149,8 @@ impl CheckAttrVisitor<'tcx> { _ => {} } + let builtin = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); + if hir_id != CRATE_HIR_ID { if let Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)) @@ -165,21 +168,28 @@ impl CheckAttrVisitor<'tcx> { } } - // Duplicate attributes - match attr.name_or_empty() { - name @ sym::macro_use => { - let args = attr.meta_item_list().unwrap_or_else(Vec::new); - let args: Vec<_> = args.iter().map(|arg| arg.name_or_empty()).collect(); - if !seen.insert((name, args)) { - self.tcx.struct_span_lint_hir( - UNUSED_ATTRIBUTES, - hir_id, + if let Some(BuiltinAttribute { duplicates, .. }) = builtin { + check_duplicates(self.tcx, attr, hir_id, *duplicates, &mut seen); + } + + // Warn on useless empty attributes. + if matches!(attr.name_or_empty(), sym::macro_use) + && attr.meta_item_list().map_or(false, |list| list.is_empty()) + { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build("unused attribute") + .span_suggestion( attr.span, - |lint| lint.build("unused attribute").emit(), - ); - } - } - _ => {} + "remove this attribute", + String::new(), + Applicability::MachineApplicable, + ) + .note(&format!( + "attribute `{}` with an empty list has no effect", + attr.name_or_empty() + )) + .emit(); + }); } } @@ -1990,3 +2000,77 @@ fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { check_mod_attrs, ..*providers }; } + +fn check_duplicates( + tcx: TyCtxt<'_>, + attr: &Attribute, + hir_id: HirId, + duplicates: AttributeDuplicates, + seen: &mut FxHashMap, +) { + use AttributeDuplicates::*; + if matches!(duplicates, WarnFollowingWordOnly) && !attr.is_word() { + return; + } + match duplicates { + DuplicatesOk => {} + WarnFollowing | FutureWarnFollowing | WarnFollowingWordOnly | FutureWarnPreceding => { + match seen.entry(attr.name_or_empty()) { + Entry::Occupied(mut entry) => { + let (this, other) = if matches!(duplicates, FutureWarnPreceding) { + let to_remove = entry.insert(attr.span); + (to_remove, attr.span) + } else { + (attr.span, *entry.get()) + }; + tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, this, |lint| { + let mut db = lint.build("unused attribute"); + db.span_note(other, "attribute also specified here").span_suggestion( + this, + "remove this attribute", + String::new(), + Applicability::MachineApplicable, + ); + if matches!(duplicates, FutureWarnFollowing | FutureWarnPreceding) { + db.warn( + "this was previously accepted by the compiler but is \ + being phased out; it will become a hard error in \ + a future release!", + ); + } + db.emit(); + }); + } + Entry::Vacant(entry) => { + entry.insert(attr.span); + } + } + } + ErrorFollowing | ErrorPreceding => match seen.entry(attr.name_or_empty()) { + Entry::Occupied(mut entry) => { + let (this, other) = if matches!(duplicates, ErrorPreceding) { + let to_remove = entry.insert(attr.span); + (to_remove, attr.span) + } else { + (attr.span, *entry.get()) + }; + tcx.sess + .struct_span_err( + this, + &format!("multiple `{}` attributes", attr.name_or_empty()), + ) + .span_note(other, "attribute also specified here") + .span_suggestion( + this, + "remove this attribute", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + } + Entry::Vacant(entry) => { + entry.insert(attr.span); + } + }, + } +} diff --git a/src/test/ui/lint/unused/unused-attr-duplicate.rs b/src/test/ui/lint/unused/unused-attr-duplicate.rs new file mode 100644 index 0000000000000..074d5a92ad620 --- /dev/null +++ b/src/test/ui/lint/unused/unused-attr-duplicate.rs @@ -0,0 +1,108 @@ +// Tests for repeating attribute warnings. +// aux-build:lint_unused_extern_crate.rs +// compile-flags:--test +// Not tested due to extra requirements: +// - panic_handler: needs extra setup +// - target_feature: platform-specific +// - link_section: platform-specific +// - proc_macro, proc_macro_derive, proc_macro_attribute: needs to be a +// proc-macro, and have special handling for mixing. +// - unstable attributes (not going to bother) +// - no_main: extra setup +#![deny(unused_attributes)] +#![crate_name = "unused_attr_duplicate"] +#![crate_name = "unused_attr_duplicate2"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![crate_type = "bin"] +#![crate_type = "rlib"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![recursion_limit = "128"] +#![recursion_limit = "256"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![type_length_limit = "1048576"] +#![type_length_limit = "1"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![no_std] +#![no_std] //~ ERROR unused attribute +#![no_implicit_prelude] +#![no_implicit_prelude] //~ ERROR unused attribute +#![windows_subsystem = "console"] +#![windows_subsystem = "windows"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![no_builtins] +#![no_builtins] //~ ERROR unused attribute + +#[no_link] +#[no_link] //~ ERROR unused attribute +extern crate lint_unused_extern_crate; + +#[macro_use] +#[macro_use] //~ ERROR unused attribute +pub mod m { + #[macro_export] + #[macro_export] //~ ERROR unused attribute + macro_rules! foo { + () => {}; + } +} + +#[path = "auxiliary/lint_unused_extern_crate.rs"] +#[path = "bar.rs"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +pub mod from_path; + +#[test] +#[ignore] +#[ignore = "some text"] //~ ERROR unused attribute +#[should_panic] +#[should_panic(expected = "values don't match")] //~ ERROR unused attribute +//~^ WARN this was previously accepted +fn t1() {} + +#[must_use] +#[must_use = "some message"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +// No warnings for #[repr], would require more logic. +#[repr(C)] +#[repr(C)] +#[non_exhaustive] +#[non_exhaustive] //~ ERROR unused attribute +pub struct X; + +#[automatically_derived] +#[automatically_derived] //~ ERROR unused attribute +impl X {} + +#[inline(always)] +#[inline(never)] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#[cold] +#[cold] //~ ERROR unused attribute +#[track_caller] +#[track_caller] //~ ERROR unused attribute +pub fn xyz() {} + +// No warnings for #[link], would require more logic. +#[link(name = "rust_test_helpers", kind = "static")] +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + #[link_name = "this_does_not_exist"] //~ ERROR unused attribute + //~^ WARN this was previously accepted + #[link_name = "rust_dbg_extern_identity_u32"] + pub fn name_in_rust(v: u32) -> u32; +} + +#[export_name = "exported_symbol_name"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#[export_name = "exported_symbol_name2"] +pub fn export_test() {} + +#[no_mangle] +#[no_mangle] //~ ERROR unused attribute +pub fn no_mangle_test() {} + +#[used] +#[used] //~ ERROR unused attribute +static FOO: u32 = 0; + +fn main() {} diff --git a/src/test/ui/lint/unused/unused-attr-duplicate.stderr b/src/test/ui/lint/unused/unused-attr-duplicate.stderr new file mode 100644 index 0000000000000..d4305add0aa4f --- /dev/null +++ b/src/test/ui/lint/unused/unused-attr-duplicate.stderr @@ -0,0 +1,306 @@ +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:36:1 + | +LL | #[no_link] + | ^^^^^^^^^^ help: remove this attribute + | +note: the lint level is defined here + --> $DIR/unused-attr-duplicate.rs:12:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:35:1 + | +LL | #[no_link] + | ^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:40:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:39:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:50:1 + | +LL | #[path = "bar.rs"] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:49:1 + | +LL | #[path = "auxiliary/lint_unused_extern_crate.rs"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:56:1 + | +LL | #[ignore = "some text"] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:55:1 + | +LL | #[ignore] + | ^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:58:1 + | +LL | #[should_panic(expected = "values don't match")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:57:1 + | +LL | #[should_panic] + | ^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:63:1 + | +LL | #[must_use = "some message"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:62:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:69:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:68:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:73:1 + | +LL | #[automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:72:1 + | +LL | #[automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:77:1 + | +LL | #[inline(never)] + | ^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:76:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:80:1 + | +LL | #[cold] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:79:1 + | +LL | #[cold] + | ^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:82:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:81:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:95:1 + | +LL | #[export_name = "exported_symbol_name"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:97:1 + | +LL | #[export_name = "exported_symbol_name2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:101:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:100:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:105:1 + | +LL | #[used] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:104:1 + | +LL | #[used] + | ^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:89:5 + | +LL | #[link_name = "this_does_not_exist"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:91:5 + | +LL | #[link_name = "rust_dbg_extern_identity_u32"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:14:1 + | +LL | #![crate_name = "unused_attr_duplicate2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:13:1 + | +LL | #![crate_name = "unused_attr_duplicate"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:17:1 + | +LL | #![crate_type = "rlib"] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:16:1 + | +LL | #![crate_type = "bin"] + | ^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:20:1 + | +LL | #![recursion_limit = "256"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:19:1 + | +LL | #![recursion_limit = "128"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:23:1 + | +LL | #![type_length_limit = "1"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:22:1 + | +LL | #![type_length_limit = "1048576"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:26:1 + | +LL | #![no_std] + | ^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:25:1 + | +LL | #![no_std] + | ^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:28:1 + | +LL | #![no_implicit_prelude] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:27:1 + | +LL | #![no_implicit_prelude] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:30:1 + | +LL | #![windows_subsystem = "windows"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:29:1 + | +LL | #![windows_subsystem = "console"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:33:1 + | +LL | #![no_builtins] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:32:1 + | +LL | #![no_builtins] + | ^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:43:5 + | +LL | #[macro_export] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:42:5 + | +LL | #[macro_export] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 24 previous errors + diff --git a/src/test/ui/macros/macro-use-all-and-none.stderr b/src/test/ui/macros/macro-use-all-and-none.stderr index bdee5f4d872a8..6de7ffb2f635b 100644 --- a/src/test/ui/macros/macro-use-all-and-none.stderr +++ b/src/test/ui/macros/macro-use-all-and-none.stderr @@ -2,13 +2,14 @@ warning: unused attribute --> $DIR/macro-use-all-and-none.rs:7:1 | LL | #[macro_use()] - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ help: remove this attribute | note: the lint level is defined here --> $DIR/macro-use-all-and-none.rs:4:9 | LL | #![warn(unused_attributes)] | ^^^^^^^^^^^^^^^^^ + = note: attribute `macro_use` with an empty list has no effect warning: 1 warning emitted From 4c60ea8228993a11d46f2dfb110128325441c77b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 5 Sep 2021 17:16:28 -0700 Subject: [PATCH 2/3] Add checks for more empty attributes. --- compiler/rustc_passes/src/check_attr.rs | 13 +- src/test/ui/empty/empty-attributes.rs | 14 ++ src/test/ui/empty/empty-attributes.stderr | 63 ++++++ ...sue-43106-gating-of-builtin-attrs-error.rs | 23 ++ ...43106-gating-of-builtin-attrs-error.stderr | 45 +++- .../issue-43106-gating-of-builtin-attrs.rs | 13 -- ...issue-43106-gating-of-builtin-attrs.stderr | 204 +++++++++--------- 7 files changed, 255 insertions(+), 120 deletions(-) create mode 100644 src/test/ui/empty/empty-attributes.rs create mode 100644 src/test/ui/empty/empty-attributes.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 270d6504b01d3..2def57cf02a61 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -173,8 +173,17 @@ impl CheckAttrVisitor<'tcx> { } // Warn on useless empty attributes. - if matches!(attr.name_or_empty(), sym::macro_use) - && attr.meta_item_list().map_or(false, |list| list.is_empty()) + if matches!( + attr.name_or_empty(), + sym::macro_use + | sym::allow + | sym::warn + | sym::deny + | sym::forbid + | sym::feature + | sym::repr + | sym::target_feature + ) && attr.meta_item_list().map_or(false, |list| list.is_empty()) { self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { lint.build("unused attribute") diff --git a/src/test/ui/empty/empty-attributes.rs b/src/test/ui/empty/empty-attributes.rs new file mode 100644 index 0000000000000..7e9b05587b075 --- /dev/null +++ b/src/test/ui/empty/empty-attributes.rs @@ -0,0 +1,14 @@ +#![deny(unused_attributes)] +#![allow()] //~ ERROR unused attribute +#![warn()] //~ ERROR unused attribute +#![deny()] //~ ERROR unused attribute +#![forbid()] //~ ERROR unused attribute +#![feature()] //~ ERROR unused attribute + +#[repr()] //~ ERROR unused attribute +pub struct S; + +#[target_feature()] //~ ERROR unused attribute +pub unsafe fn foo() {} + +fn main() {} diff --git a/src/test/ui/empty/empty-attributes.stderr b/src/test/ui/empty/empty-attributes.stderr new file mode 100644 index 0000000000000..e0798e4f0c69f --- /dev/null +++ b/src/test/ui/empty/empty-attributes.stderr @@ -0,0 +1,63 @@ +error: unused attribute + --> $DIR/empty-attributes.rs:8:1 + | +LL | #[repr()] + | ^^^^^^^^^ help: remove this attribute + | +note: the lint level is defined here + --> $DIR/empty-attributes.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + = note: attribute `repr` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:11:1 + | +LL | #[target_feature()] + | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `target_feature` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:2:1 + | +LL | #![allow()] + | ^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `allow` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:3:1 + | +LL | #![warn()] + | ^^^^^^^^^^ help: remove this attribute + | + = note: attribute `warn` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:4:1 + | +LL | #![deny()] + | ^^^^^^^^^^ help: remove this attribute + | + = note: attribute `deny` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:5:1 + | +LL | #![forbid()] + | ^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `forbid` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:6:1 + | +LL | #![feature()] + | ^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `feature` with an empty list has no effect + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs index 44abe160f8716..1fe133ac2bc98 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs @@ -134,4 +134,27 @@ mod start { //~^ ERROR: `start` attribute can only be used on functions } +#[repr(C)] +//~^ ERROR: attribute should be applied to a struct, enum, or union +mod repr { +//~^ NOTE not a struct, enum, or union + mod inner { #![repr(C)] } + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union + + #[repr(C)] fn f() { } + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union + + struct S; + + #[repr(C)] type T = S; + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union + + #[repr(C)] impl S { } + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union +} + fn main() {} diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index aed1312155db5..9e2e2d4137d25 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -91,6 +91,21 @@ LL | | } LL | | } | |_- not a free function, impl method or static +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:137:8 + | +LL | #[repr(C)] + | ^ +LL | +LL | / mod repr { +LL | | +LL | | mod inner { #![repr(C)] } +LL | | +... | +LL | | +LL | | } + | |_- not a struct, enum, or union + error: attribute should be applied to an `extern crate` item --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1 | @@ -235,7 +250,31 @@ error: attribute should be applied to a free function, impl method or static LL | #[export_name = "2200"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static -error: aborting due to 34 previous errors +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:141:25 + | +LL | mod inner { #![repr(C)] } + | --------------------^---- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:145:12 + | +LL | #[repr(C)] fn f() { } + | ^ ---------- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:151:12 + | +LL | #[repr(C)] type T = S; + | ^ ----------- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:155:12 + | +LL | #[repr(C)] impl S { } + | ^ ---------- not a struct, enum, or union + +error: aborting due to 39 previous errors -Some errors have detailed explanations: E0518, E0658. -For more information about an error, try `rustc --explain E0518`. +Some errors have detailed explanations: E0517, E0518, E0658. +For more information about an error, try `rustc --explain E0517`. diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index 97fa775967da4..1ddf8508cc8cc 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -245,19 +245,6 @@ mod bench { impl S { } } -#[repr()] -mod repr { - mod inner { #![repr()] } - - #[repr()] fn f() { } - - struct S; - - #[repr()] type T = S; - - #[repr()] impl S { } -} - #[path = "3800"] mod path { mod inner { #![path="3800"] } diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 214584f47e9ba..b98374bfa80cc 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -173,7 +173,7 @@ LL | #[deny(x5100)] impl S { } | ^^^^^ warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:17 | LL | mod inner { #![macro_escape] } | ^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL | mod inner { #![macro_escape] } = help: try an outer attribute: `#[macro_use]` warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:396:1 | LL | #[macro_escape] | ^^^^^^^^^^^^^^^ @@ -213,13 +213,13 @@ LL | #![warn(unused_attributes, unknown_lints)] | ^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on items - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:278:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:265:1 | LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:296:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:283:1 | LL | #[no_mangle] | ^^^^^^^^^^^^ @@ -236,31 +236,31 @@ LL | | } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:323:1 | LL | #[should_panic] | ^^^^^^^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:354:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:1 | LL | #[ignore] | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:1 | LL | #[reexport_test_harness_main = "2900"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:416:1 | LL | #[no_std] | ^^^^^^^^^ warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:465:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:452:1 | LL | #[cold] | ^^^^^^^ @@ -277,7 +277,7 @@ LL | | } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:494:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:481:1 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ @@ -294,7 +294,7 @@ LL | | } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:533:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:520:1 | LL | #[link_section = "1800"] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -311,37 +311,37 @@ LL | | } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:624:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:643:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:630:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:662:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:649:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:1 | LL | #[no_main] | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:714:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -443,55 +443,55 @@ LL | #[macro_export] impl S { } | ^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:265:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:252:5 | LL | #[path = "3800"] fn f() { } | ^^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:268:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:255:5 | LL | #[path = "3800"] struct S; | ^^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:258:5 | LL | #[path = "3800"] type T = S; | ^^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:261:5 | LL | #[path = "3800"] impl S { } | ^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on items - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:281:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:268:17 | LL | mod inner { #![automatically_derived] } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on items - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:284:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5 | LL | #[automatically_derived] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on items - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:287:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5 | LL | #[automatically_derived] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on items - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:290:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:277:5 | LL | #[automatically_derived] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:301:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:288:17 | LL | mod inner { #![no_mangle] } | ------------^^^^^^^^^^^^^-- not a free function, impl method or static @@ -499,7 +499,7 @@ LL | mod inner { #![no_mangle] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:308:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:295:5 | LL | #[no_mangle] struct S; | ^^^^^^^^^^^^ --------- not a free function, impl method or static @@ -507,7 +507,7 @@ LL | #[no_mangle] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:313:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:300:5 | LL | #[no_mangle] type T = S; | ^^^^^^^^^^^^ ----------- not a free function, impl method or static @@ -515,7 +515,7 @@ LL | #[no_mangle] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:318:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:305:5 | LL | #[no_mangle] impl S { } | ^^^^^^^^^^^^ ---------- not a free function, impl method or static @@ -523,7 +523,7 @@ LL | #[no_mangle] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:324:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:311:9 | LL | #[no_mangle] fn foo(); | ^^^^^^^^^^^^ --------- not a free function, impl method or static @@ -531,7 +531,7 @@ LL | #[no_mangle] fn foo(); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:329:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:316:9 | LL | #[no_mangle] fn bar() {} | ^^^^^^^^^^^^ ----------- not a free function, impl method or static @@ -539,163 +539,163 @@ LL | #[no_mangle] fn bar() {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:339:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:326:17 | LL | mod inner { #![should_panic] } | ^^^^^^^^^^^^^^^^ warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:331:5 | LL | #[should_panic] struct S; | ^^^^^^^^^^^^^^^ warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:334:5 | LL | #[should_panic] type T = S; | ^^^^^^^^^^^^^^^ warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:350:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:337:5 | LL | #[should_panic] impl S { } | ^^^^^^^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:357:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:17 | LL | mod inner { #![ignore] } | ^^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:362:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:349:5 | LL | #[ignore] struct S; | ^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:365:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:5 | LL | #[ignore] type T = S; | ^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5 | LL | #[ignore] impl S { } | ^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:363:5 | LL | #[no_implicit_prelude] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:379:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:366:5 | LL | #[no_implicit_prelude] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:382:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:369:5 | LL | #[no_implicit_prelude] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:385:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:372:5 | LL | #[no_implicit_prelude] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:379:17 | LL | mod inner { #![reexport_test_harness_main="2900"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:382:5 | LL | #[reexport_test_harness_main = "2900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:385:5 | LL | #[reexport_test_harness_main = "2900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:388:5 | LL | #[reexport_test_harness_main = "2900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:391:5 | LL | #[reexport_test_harness_main = "2900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:416:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:5 | LL | #[macro_escape] fn f() { } | ^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:419:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:406:5 | LL | #[macro_escape] struct S; | ^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:422:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:5 | LL | #[macro_escape] type T = S; | ^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:425:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:5 | LL | #[macro_escape] impl S { } | ^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:419:17 | LL | mod inner { #![no_std] } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:435:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:422:5 | LL | #[no_std] fn f() { } | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:425:5 | LL | #[no_std] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:441:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:428:5 | LL | #[no_std] type T = S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:444:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:431:5 | LL | #[no_std] impl S { } | ^^^^^^^^^ warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:471:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:17 | LL | mod inner { #![cold] } | ------------^^^^^^^^-- not a function @@ -703,7 +703,7 @@ LL | mod inner { #![cold] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:478:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:465:5 | LL | #[cold] struct S; | ^^^^^^^ --------- not a function @@ -711,7 +711,7 @@ LL | #[cold] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5 | LL | #[cold] type T = S; | ^^^^^^^ ----------- not a function @@ -719,7 +719,7 @@ LL | #[cold] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:475:5 | LL | #[cold] impl S { } | ^^^^^^^ ---------- not a function @@ -727,7 +727,7 @@ LL | #[cold] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ @@ -737,13 +737,13 @@ LL | extern "C" { } | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! help: try `#[link(name = "1900")]` instead - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:507:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:494:17 | LL | mod inner { #![link_name="1900"] } | ------------^^^^^^^^^^^^^^^^^^^^-- not a foreign function or static @@ -751,7 +751,7 @@ LL | mod inner { #![link_name="1900"] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5 | LL | #[link_name = "1900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static @@ -759,7 +759,7 @@ LL | #[link_name = "1900"] fn f() { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:517:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:504:5 | LL | #[link_name = "1900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^ --------- not a foreign function or static @@ -767,7 +767,7 @@ LL | #[link_name = "1900"] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:509:5 | LL | #[link_name = "1900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^ ----------- not a foreign function or static @@ -775,7 +775,7 @@ LL | #[link_name = "1900"] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:514:5 | LL | #[link_name = "1900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static @@ -783,7 +783,7 @@ LL | #[link_name = "1900"] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:539:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:526:17 | LL | mod inner { #![link_section="1800"] } | ------------^^^^^^^^^^^^^^^^^^^^^^^-- not a function or static @@ -791,7 +791,7 @@ LL | mod inner { #![link_section="1800"] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:546:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:533:5 | LL | #[link_section = "1800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static @@ -799,7 +799,7 @@ LL | #[link_section = "1800"] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:538:5 | LL | #[link_section = "1800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static @@ -807,7 +807,7 @@ LL | #[link_section = "1800"] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:556:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:543:5 | LL | #[link_section = "1800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static @@ -815,181 +815,181 @@ LL | #[link_section = "1800"] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:627:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:614:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:630:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:617:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:633:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:636:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:623:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:626:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:633:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:649:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:636:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:652:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:655:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:658:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:645:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:665:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:652:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:655:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:658:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:674:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:661:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:677:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:664:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:17 | LL | mod inner { #![no_main] } | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5 | LL | #[no_main] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:678:5 | LL | #[no_main] struct S; | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:694:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:681:5 | LL | #[no_main] type T = S; | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:5 | LL | #[no_main] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:710:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:739:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:735:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 36dcd4cbd9a455707f2b790e01fbdc38a86d5e9b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 21 Nov 2021 08:02:00 -0800 Subject: [PATCH 3/3] Update link_ordinal duplicate attribute handling. This removes the duplicate check, as this is now handled in a centralized location. --- compiler/rustc_typeck/src/collect.rs | 8 -------- src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs | 3 +-- .../ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr | 8 +++++++- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 209690ec5fc9a..de1606a7ed5f0 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2865,14 +2865,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } else if attr.has_name(sym::link_name) { codegen_fn_attrs.link_name = attr.value_str(); } else if attr.has_name(sym::link_ordinal) { - if link_ordinal_span.is_some() { - tcx.sess - .struct_span_err( - attr.span, - "multiple `link_ordinal` attributes on a single definition", - ) - .emit(); - } link_ordinal_span = Some(attr.span); if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) { codegen_fn_attrs.link_ordinal = ordinal; diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs index 9874121267717..0ab994ecd45be 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs @@ -4,9 +4,8 @@ #[link(name = "foo", kind = "raw-dylib")] extern "C" { - #[link_ordinal(1)] + #[link_ordinal(1)] //~ ERROR multiple `link_ordinal` attributes #[link_ordinal(2)] - //~^ ERROR multiple `link_ordinal` attributes on a single definition fn foo(); } diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr index a79fb2de94402..4772533ab2f07 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr @@ -7,7 +7,13 @@ LL | #![feature(raw_dylib)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #58713 for more information -error: multiple `link_ordinal` attributes on a single definition +error: multiple `link_ordinal` attributes + --> $DIR/link-ordinal-multiple.rs:7:5 + | +LL | #[link_ordinal(1)] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here --> $DIR/link-ordinal-multiple.rs:8:5 | LL | #[link_ordinal(2)]