Rollup merge of #71205 - NeoRaider:check_attr, r=jonas-schievink
rustc: fix check_attr() for methods, closures and foreign functions This fixes an issue that previously turned up for methods in https://github.com/rust-lang/rust/pull/69274, but also exists for closures and foreign function: `check_attr` does not call `codegen_fn_attrs()` for these types when it should, meaning that incorrectly used function attributes are not diagnosed without codegen. The issue affects our UI tests, as they run with `--emit=metadata` by default, but as it turns out, this is not the only case: Function attributes are not checked on any dead code without this fix! This makes the fix a **breaking change**. The following very silly Rust programs compiles fine on stable Rust when it should not, which is fixed by this PR. ```rust fn main() { #[target_feature(enable = "sse2")] || {}; } ``` I assume any real-world program which may trigger this issue would at least emit a dead code warning, but of course that is no guarantee that such code does not exist... Fixes #70307
This commit is contained in:
commit
4e6772b52b
@ -76,7 +76,7 @@ impl CheckAttrVisitor<'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
if target == Target::Fn {
|
||||
if matches!(target, Target::Fn | Target::Method(_) | Target::ForeignFn) {
|
||||
self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id(hir_id));
|
||||
}
|
||||
|
||||
@ -389,6 +389,9 @@ impl CheckAttrVisitor<'tcx> {
|
||||
);
|
||||
}
|
||||
}
|
||||
if target == Target::Closure {
|
||||
self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id(expr.hir_id));
|
||||
}
|
||||
}
|
||||
|
||||
fn check_used(&self, attrs: &'hir [Attribute], target: Target) {
|
||||
|
@ -8,24 +8,28 @@
|
||||
struct Foo;
|
||||
impl Fn<()> for Foo {
|
||||
//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change
|
||||
//~| ERROR manual implementations of `Fn` are experimental
|
||||
extern "rust-call" fn call(self, args: ()) -> () {}
|
||||
//~^ ERROR rust-call ABI is subject to change
|
||||
}
|
||||
struct Foo1;
|
||||
impl FnOnce() for Foo1 {
|
||||
//~^ ERROR associated type bindings are not allowed here
|
||||
//~| ERROR manual implementations of `FnOnce` are experimental
|
||||
extern "rust-call" fn call_once(self, args: ()) -> () {}
|
||||
//~^ ERROR rust-call ABI is subject to change
|
||||
}
|
||||
struct Bar;
|
||||
impl FnMut<()> for Bar {
|
||||
//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change
|
||||
//~| ERROR manual implementations of `FnMut` are experimental
|
||||
extern "rust-call" fn call_mut(&self, args: ()) -> () {}
|
||||
//~^ ERROR rust-call ABI is subject to change
|
||||
}
|
||||
struct Baz;
|
||||
impl FnOnce<()> for Baz {
|
||||
//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change
|
||||
//~| ERROR manual implementations of `FnOnce` are experimental
|
||||
extern "rust-call" fn call_once(&self, args: ()) -> () {}
|
||||
//~^ ERROR rust-call ABI is subject to change
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:11:12
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:12:12
|
||||
|
|
||||
LL | extern "rust-call" fn call(self, args: ()) -> () {}
|
||||
| ^^^^^^^^^^^
|
||||
@ -8,7 +8,7 @@ LL | extern "rust-call" fn call(self, args: ()) -> () {}
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:17:12
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:19:12
|
||||
|
|
||||
LL | extern "rust-call" fn call_once(self, args: ()) -> () {}
|
||||
| ^^^^^^^^^^^
|
||||
@ -17,7 +17,7 @@ LL | extern "rust-call" fn call_once(self, args: ()) -> () {}
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:12
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:26:12
|
||||
|
|
||||
LL | extern "rust-call" fn call_mut(&self, args: ()) -> () {}
|
||||
| ^^^^^^^^^^^
|
||||
@ -26,7 +26,7 @@ LL | extern "rust-call" fn call_mut(&self, args: ()) -> () {}
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:29:12
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:33:12
|
||||
|
|
||||
LL | extern "rust-call" fn call_once(&self, args: ()) -> () {}
|
||||
| ^^^^^^^^^^^
|
||||
@ -44,13 +44,13 @@ LL | impl Fn<()> for Foo {
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0229]: associated type bindings are not allowed here
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:15:6
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:16:6
|
||||
|
|
||||
LL | impl FnOnce() for Foo1 {
|
||||
| ^^^^^^^^ associated type not allowed here
|
||||
|
||||
error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:21:6
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:6
|
||||
|
|
||||
LL | impl FnMut<()> for Bar {
|
||||
| ^^^^^^^^^ help: use parenthetical notation instead: `FnMut() -> ()`
|
||||
@ -59,7 +59,7 @@ LL | impl FnMut<()> for Bar {
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:27:6
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:6
|
||||
|
|
||||
LL | impl FnOnce<()> for Baz {
|
||||
| ^^^^^^^^^^ help: use parenthetical notation instead: `FnOnce() -> ()`
|
||||
@ -67,7 +67,39 @@ LL | impl FnOnce<()> for Baz {
|
||||
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error[E0183]: manual implementations of `Fn` are experimental
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:1
|
||||
|
|
||||
LL | impl Fn<()> for Foo {
|
||||
| ^^^^^^^^^^^^^^^^^^^ manual implementations of `Fn` are experimental
|
||||
|
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0183]: manual implementations of `FnMut` are experimental
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:1
|
||||
|
|
||||
LL | impl FnMut<()> for Bar {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ manual implementations of `FnMut` are experimental
|
||||
|
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0183]: manual implementations of `FnOnce` are experimental
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:16:1
|
||||
|
|
||||
LL | impl FnOnce() for Foo1 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ manual implementations of `FnOnce` are experimental
|
||||
|
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0183]: manual implementations of `FnOnce` are experimental
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:1
|
||||
|
|
||||
LL | impl FnOnce<()> for Baz {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ manual implementations of `FnOnce` are experimental
|
||||
|
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0229, E0658.
|
||||
For more information about an error, try `rustc --explain E0229`.
|
||||
|
@ -4,6 +4,7 @@ struct Test;
|
||||
|
||||
impl FnOnce<(u32, u32)> for Test {
|
||||
//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change
|
||||
//~| ERROR manual implementations of `FnOnce` are experimental
|
||||
type Output = u32;
|
||||
|
||||
extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-unboxed-closures.rs:9:12
|
||||
--> $DIR/feature-gate-unboxed-closures.rs:10:12
|
||||
|
|
||||
LL | extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
|
||||
| ^^^^^^^^^^^
|
||||
@ -16,6 +16,14 @@ LL | impl FnOnce<(u32, u32)> for Test {
|
||||
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0183]: manual implementations of `FnOnce` are experimental
|
||||
--> $DIR/feature-gate-unboxed-closures.rs:5:1
|
||||
|
|
||||
LL | impl FnOnce<(u32, u32)> for Test {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ manual implementations of `FnOnce` are experimental
|
||||
|
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -1,3 +1,5 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
fn foo<T>() {
|
||||
struct Foo {
|
||||
x: T, //~ ERROR can't use generic parameters from outer function
|
||||
@ -5,6 +7,7 @@ fn foo<T>() {
|
||||
|
||||
impl<T> Drop for Foo<T> {
|
||||
//~^ ERROR wrong number of type arguments
|
||||
//~| ERROR the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0401]: can't use generic parameters from outer function
|
||||
--> $DIR/issue-3214.rs:3:12
|
||||
--> $DIR/issue-3214.rs:5:12
|
||||
|
|
||||
LL | fn foo<T>() {
|
||||
| --- - type parameter from outer function
|
||||
@ -10,12 +10,18 @@ LL | x: T,
|
||||
| ^ use of generic parameter from outer function
|
||||
|
||||
error[E0107]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/issue-3214.rs:6:26
|
||||
--> $DIR/issue-3214.rs:8:26
|
||||
|
|
||||
LL | impl<T> Drop for Foo<T> {
|
||||
| ^ unexpected type argument
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/issue-3214.rs:8:10
|
||||
|
|
||||
LL | impl<T> Drop for Foo<T> {
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
Some errors have detailed explanations: E0107, E0401.
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0207, E0401.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
||||
|
@ -1,5 +1,3 @@
|
||||
// build-fail
|
||||
|
||||
#![feature(track_caller)]
|
||||
|
||||
fn main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: `#[target_feature(..)]` can only be applied to `unsafe` functions
|
||||
--> $DIR/issue-68060.rs:8:13
|
||||
--> $DIR/issue-68060.rs:6:13
|
||||
|
|
||||
LL | #[target_feature(enable = "")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only be applied to `unsafe` functions
|
||||
@ -8,13 +8,13 @@ LL | |_| (),
|
||||
| ------ not an `unsafe` function
|
||||
|
||||
error: the feature named `` is not valid for this target
|
||||
--> $DIR/issue-68060.rs:8:30
|
||||
--> $DIR/issue-68060.rs:6:30
|
||||
|
|
||||
LL | #[target_feature(enable = "")]
|
||||
| ^^^^^^^^^^^ `` is not valid for this target
|
||||
|
||||
error[E0737]: `#[track_caller]` requires Rust ABI
|
||||
--> $DIR/issue-68060.rs:11:13
|
||||
--> $DIR/issue-68060.rs:9:13
|
||||
|
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
@ -4,4 +4,10 @@
|
||||
extern "C" fn f() {}
|
||||
//~^^ ERROR `#[track_caller]` requires Rust ABI
|
||||
|
||||
extern "C" {
|
||||
#[track_caller]
|
||||
fn g();
|
||||
//~^^ ERROR `#[track_caller]` requires Rust ABI
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -4,6 +4,12 @@ error[E0737]: `#[track_caller]` requires Rust ABI
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0737]: `#[track_caller]` requires Rust ABI
|
||||
--> $DIR/error-with-invalid-abi.rs:8:5
|
||||
|
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0737`.
|
||||
|
@ -65,9 +65,26 @@ trait Baz { }
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test() {}
|
||||
|
||||
trait Quux {
|
||||
fn foo();
|
||||
}
|
||||
|
||||
impl Quux for Foo {
|
||||
#[target_feature(enable = "sse2")]
|
||||
//~^ ERROR `#[target_feature(..)]` can only be applied to `unsafe` functions
|
||||
//~| NOTE can only be applied to `unsafe` functions
|
||||
fn foo() {}
|
||||
//~^ NOTE not an `unsafe` function
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
foo();
|
||||
bar();
|
||||
}
|
||||
#[target_feature(enable = "sse2")]
|
||||
//~^ ERROR `#[target_feature(..)]` can only be applied to `unsafe` functions
|
||||
//~| NOTE can only be applied to `unsafe` functions
|
||||
|| {};
|
||||
//~^ NOTE not an `unsafe` function
|
||||
}
|
||||
|
@ -91,5 +91,23 @@ error: cannot use `#[inline(always)]` with `#[target_feature]`
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
error: `#[target_feature(..)]` can only be applied to `unsafe` functions
|
||||
--> $DIR/invalid-attribute.rs:85:5
|
||||
|
|
||||
LL | #[target_feature(enable = "sse2")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only be applied to `unsafe` functions
|
||||
...
|
||||
LL | || {};
|
||||
| ----- not an `unsafe` function
|
||||
|
||||
error: `#[target_feature(..)]` can only be applied to `unsafe` functions
|
||||
--> $DIR/invalid-attribute.rs:73:5
|
||||
|
|
||||
LL | #[target_feature(enable = "sse2")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only be applied to `unsafe` functions
|
||||
...
|
||||
LL | fn foo() {}
|
||||
| ----------- not an `unsafe` function
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user