Skip to content

Commit 804072f

Browse files
authored
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
2 parents cb5ecff + b59e743 commit 804072f

File tree

4 files changed

+350
-163
lines changed

4 files changed

+350
-163
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -352,15 +352,15 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
352352

353353
// Runtime
354354
ungated!(
355-
windows_subsystem, Normal,
355+
windows_subsystem, CrateLevel,
356356
template!(NameValueStr: "windows|console"), FutureWarnFollowing
357357
),
358358
ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070
359359

360360
// Code generation:
361361
ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing),
362362
ungated!(cold, Normal, template!(Word), WarnFollowing),
363-
ungated!(no_builtins, Normal, template!(Word), WarnFollowing),
363+
ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing),
364364
ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk),
365365
ungated!(track_caller, Normal, template!(Word), WarnFollowing),
366366
gated!(

compiler/rustc_passes/src/check_attr.rs

+21
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ impl CheckAttrVisitor<'_> {
126126
// lint-only checks
127127
match attr.name_or_empty() {
128128
sym::cold => self.check_cold(hir_id, attr, span, target),
129+
sym::link => self.check_link(hir_id, attr, span, target),
129130
sym::link_name => self.check_link_name(hir_id, attr, span, target),
130131
sym::link_section => self.check_link_section(hir_id, attr, span, target),
131132
sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target),
@@ -1157,6 +1158,26 @@ impl CheckAttrVisitor<'_> {
11571158
}
11581159
}
11591160

1161+
/// Checks if `#[link]` is applied to an item other than a foreign module.
1162+
fn check_link(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
1163+
match target {
1164+
Target::ForeignMod => {}
1165+
_ => {
1166+
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
1167+
let mut diag = lint.build("attribute should be applied to an `extern` block");
1168+
diag.warn(
1169+
"this was previously accepted by the compiler but is \
1170+
being phased out; it will become a hard error in \
1171+
a future release!",
1172+
);
1173+
1174+
diag.span_label(*span, "not an `extern` block");
1175+
diag.emit();
1176+
});
1177+
}
1178+
}
1179+
}
1180+
11601181
/// Checks if `#[link_name]` is applied to an item other than a foreign function or static.
11611182
fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
11621183
match target {

src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs

+38-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//~ NOTE not a function
2-
//~^ NOTE not a foreign function or static
3-
//~^^ NOTE not a function or static
2+
//~| NOTE not a foreign function or static
3+
//~| NOTE not a function or static
4+
//~| NOTE not an `extern` block
45
// This test enumerates as many compiler-builtin ungated attributes as
56
// possible (that is, all the mutually compatible ones), and checks
67
// that we get "expected" (*) warnings for each in the various weird
@@ -59,9 +60,9 @@
5960
#![proc_macro_derive()] //~ WARN `#[proc_macro_derive]` only has an effect
6061
#![doc = "2400"]
6162
#![cold] //~ WARN attribute should be applied to a function
62-
//~^ WARN
63-
// see issue-43106-gating-of-builtin-attrs-error.rs
64-
#![link()]
63+
//~^ WARN this was previously accepted
64+
#![link()] //~ WARN attribute should be applied to an `extern` block
65+
//~^ WARN this was previously accepted
6566
#![link_name = "1900"]
6667
//~^ WARN attribute should be applied to a foreign function
6768
//~^^ WARN this was previously accepted by the compiler
@@ -547,22 +548,38 @@ mod link_section {
547548
}
548549

549550

550-
// Note that this is a `check-pass` test, so it
551-
// will never invoke the linker. These are here nonetheless to point
552-
// out that we allow them at non-crate-level (though I do not know
553-
// whether they have the same effect here as at crate-level).
551+
// Note that this is a `check-pass` test, so it will never invoke the linker.
554552

555553
#[link()]
554+
//~^ WARN attribute should be applied to an `extern` block
555+
//~| WARN this was previously accepted
556556
mod link {
557+
//~^ NOTE not an `extern` block
558+
557559
mod inner { #![link()] }
560+
//~^ WARN attribute should be applied to an `extern` block
561+
//~| WARN this was previously accepted
562+
//~| NOTE not an `extern` block
558563

559564
#[link()] fn f() { }
565+
//~^ WARN attribute should be applied to an `extern` block
566+
//~| WARN this was previously accepted
567+
//~| NOTE not an `extern` block
560568

561569
#[link()] struct S;
570+
//~^ WARN attribute should be applied to an `extern` block
571+
//~| WARN this was previously accepted
572+
//~| NOTE not an `extern` block
562573

563574
#[link()] type T = S;
575+
//~^ WARN attribute should be applied to an `extern` block
576+
//~| WARN this was previously accepted
577+
//~| NOTE not an `extern` block
564578

565579
#[link()] impl S { }
580+
//~^ WARN attribute should be applied to an `extern` block
581+
//~| WARN this was previously accepted
582+
//~| NOTE not an `extern` block
566583
}
567584

568585
struct StructForDeprecated;
@@ -594,16 +611,22 @@ mod must_use {
594611
}
595612

596613
#[windows_subsystem = "windows"]
614+
//~^ WARN crate-level attribute should be an inner attribute
597615
mod windows_subsystem {
598616
mod inner { #![windows_subsystem="windows"] }
617+
//~^ WARN crate-level attribute should be in the root module
599618

600619
#[windows_subsystem = "windows"] fn f() { }
620+
//~^ WARN crate-level attribute should be an inner attribute
601621

602622
#[windows_subsystem = "windows"] struct S;
623+
//~^ WARN crate-level attribute should be an inner attribute
603624

604625
#[windows_subsystem = "windows"] type T = S;
626+
//~^ WARN crate-level attribute should be an inner attribute
605627

606628
#[windows_subsystem = "windows"] impl S { }
629+
//~^ WARN crate-level attribute should be an inner attribute
607630
}
608631

609632
// BROKEN USES OF CRATE-LEVEL BUILT-IN ATTRIBUTES
@@ -686,16 +709,22 @@ mod no_main_1 {
686709
}
687710

688711
#[no_builtins]
712+
//~^ WARN crate-level attribute should be an inner attribute
689713
mod no_builtins {
690714
mod inner { #![no_builtins] }
715+
//~^ WARN crate-level attribute should be in the root module
691716

692717
#[no_builtins] fn f() { }
718+
//~^ WARN crate-level attribute should be an inner attribute
693719

694720
#[no_builtins] struct S;
721+
//~^ WARN crate-level attribute should be an inner attribute
695722

696723
#[no_builtins] type T = S;
724+
//~^ WARN crate-level attribute should be an inner attribute
697725

698726
#[no_builtins] impl S { }
727+
//~^ WARN crate-level attribute should be an inner attribute
699728
}
700729

701730
#[recursion_limit="0200"]

0 commit comments

Comments
 (0)