Rollup merge of #92701 - ehuss:even-more-attr-validation, r=matthewjasper
Add some more attribute validation This adds some more validation for the position of attributes: * `link` is only valid on an `extern` block * `windows_subsystem` and `no_builtins` are only valid at the crate level
This commit is contained in:
commit
804072fdfc
@ -352,7 +352,7 @@ pub struct BuiltinAttribute {
|
||||
|
||||
// Runtime
|
||||
ungated!(
|
||||
windows_subsystem, Normal,
|
||||
windows_subsystem, CrateLevel,
|
||||
template!(NameValueStr: "windows|console"), FutureWarnFollowing
|
||||
),
|
||||
ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070
|
||||
@ -360,7 +360,7 @@ pub struct BuiltinAttribute {
|
||||
// Code generation:
|
||||
ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing),
|
||||
ungated!(cold, Normal, template!(Word), WarnFollowing),
|
||||
ungated!(no_builtins, Normal, template!(Word), WarnFollowing),
|
||||
ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing),
|
||||
ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk),
|
||||
ungated!(track_caller, Normal, template!(Word), WarnFollowing),
|
||||
gated!(
|
||||
|
@ -126,6 +126,7 @@ fn check_attributes(
|
||||
// lint-only checks
|
||||
match attr.name_or_empty() {
|
||||
sym::cold => self.check_cold(hir_id, attr, span, target),
|
||||
sym::link => self.check_link(hir_id, attr, span, target),
|
||||
sym::link_name => self.check_link_name(hir_id, attr, span, target),
|
||||
sym::link_section => self.check_link_section(hir_id, attr, span, target),
|
||||
sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target),
|
||||
@ -1157,6 +1158,26 @@ fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Targe
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if `#[link]` is applied to an item other than a foreign module.
|
||||
fn check_link(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
|
||||
match target {
|
||||
Target::ForeignMod => {}
|
||||
_ => {
|
||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
||||
let mut diag = lint.build("attribute should be applied to an `extern` block");
|
||||
diag.warn(
|
||||
"this was previously accepted by the compiler but is \
|
||||
being phased out; it will become a hard error in \
|
||||
a future release!",
|
||||
);
|
||||
|
||||
diag.span_label(*span, "not an `extern` block");
|
||||
diag.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if `#[link_name]` is applied to an item other than a foreign function or static.
|
||||
fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
|
||||
match target {
|
||||
|
@ -1,6 +1,7 @@
|
||||
//~ NOTE not a function
|
||||
//~^ NOTE not a foreign function or static
|
||||
//~^^ NOTE not a function or static
|
||||
//~| NOTE not a foreign function or static
|
||||
//~| NOTE not a function or static
|
||||
//~| NOTE not an `extern` block
|
||||
// This test enumerates as many compiler-builtin ungated attributes as
|
||||
// possible (that is, all the mutually compatible ones), and checks
|
||||
// that we get "expected" (*) warnings for each in the various weird
|
||||
@ -59,9 +60,9 @@
|
||||
#![proc_macro_derive()] //~ WARN `#[proc_macro_derive]` only has an effect
|
||||
#![doc = "2400"]
|
||||
#![cold] //~ WARN attribute should be applied to a function
|
||||
//~^ WARN
|
||||
// see issue-43106-gating-of-builtin-attrs-error.rs
|
||||
#![link()]
|
||||
//~^ WARN this was previously accepted
|
||||
#![link()] //~ WARN attribute should be applied to an `extern` block
|
||||
//~^ WARN this was previously accepted
|
||||
#![link_name = "1900"]
|
||||
//~^ WARN attribute should be applied to a foreign function
|
||||
//~^^ WARN this was previously accepted by the compiler
|
||||
@ -547,22 +548,38 @@ mod inner { #![link_section="1800"] }
|
||||
}
|
||||
|
||||
|
||||
// Note that this is a `check-pass` test, so it
|
||||
// will never invoke the linker. These are here nonetheless to point
|
||||
// out that we allow them at non-crate-level (though I do not know
|
||||
// whether they have the same effect here as at crate-level).
|
||||
// Note that this is a `check-pass` test, so it will never invoke the linker.
|
||||
|
||||
#[link()]
|
||||
//~^ WARN attribute should be applied to an `extern` block
|
||||
//~| WARN this was previously accepted
|
||||
mod link {
|
||||
//~^ NOTE not an `extern` block
|
||||
|
||||
mod inner { #![link()] }
|
||||
//~^ WARN attribute should be applied to an `extern` block
|
||||
//~| WARN this was previously accepted
|
||||
//~| NOTE not an `extern` block
|
||||
|
||||
#[link()] fn f() { }
|
||||
//~^ WARN attribute should be applied to an `extern` block
|
||||
//~| WARN this was previously accepted
|
||||
//~| NOTE not an `extern` block
|
||||
|
||||
#[link()] struct S;
|
||||
//~^ WARN attribute should be applied to an `extern` block
|
||||
//~| WARN this was previously accepted
|
||||
//~| NOTE not an `extern` block
|
||||
|
||||
#[link()] type T = S;
|
||||
//~^ WARN attribute should be applied to an `extern` block
|
||||
//~| WARN this was previously accepted
|
||||
//~| NOTE not an `extern` block
|
||||
|
||||
#[link()] impl S { }
|
||||
//~^ WARN attribute should be applied to an `extern` block
|
||||
//~| WARN this was previously accepted
|
||||
//~| NOTE not an `extern` block
|
||||
}
|
||||
|
||||
struct StructForDeprecated;
|
||||
@ -594,16 +611,22 @@ mod inner { #![must_use] }
|
||||
}
|
||||
|
||||
#[windows_subsystem = "windows"]
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
mod windows_subsystem {
|
||||
mod inner { #![windows_subsystem="windows"] }
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[windows_subsystem = "windows"] fn f() { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[windows_subsystem = "windows"] struct S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[windows_subsystem = "windows"] type T = S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[windows_subsystem = "windows"] impl S { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
}
|
||||
|
||||
// BROKEN USES OF CRATE-LEVEL BUILT-IN ATTRIBUTES
|
||||
@ -686,16 +709,22 @@ mod inner { #![no_main] }
|
||||
}
|
||||
|
||||
#[no_builtins]
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
mod no_builtins {
|
||||
mod inner { #![no_builtins] }
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[no_builtins] fn f() { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[no_builtins] struct S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[no_builtins] type T = S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[no_builtins] impl S { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
}
|
||||
|
||||
#[recursion_limit="0200"]
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user