emit specific warning to clarify that foreign items can't have no_mangle

remove extra commented code
Deduplicate some diagnostics code
add code symbols, machine applicable suggestion
clarify error message
This commit is contained in:
asquared31415 2021-08-29 20:08:40 -04:00
parent 2f662b1403
commit fc125a52ec
3 changed files with 102 additions and 0 deletions

View file

@ -1331,6 +1331,36 @@ impl CheckAttrVisitor<'tcx> {
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_mangle");
}
// FIXME: #[no_mangle] was previously allowed on non-functions/statics, this should be an error
// The error should specify that the item that is wrong is specifically a *foreign* fn/static
// otherwise the error seems odd
Target::ForeignFn | Target::ForeignStatic => {
let foreign_item_kind = match target {
Target::ForeignFn => "function",
Target::ForeignStatic => "static",
_ => unreachable!(),
};
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
lint.build(&format!(
"`#[no_mangle]` has no effect on a foreign {}",
foreign_item_kind
))
.warn(
"this was previously accepted by the compiler but is \
being phased out; it will become a hard error in \
a future release!",
)
.span_label(*span, format!("foreign {}", foreign_item_kind))
.note("symbol names in extern blocks are not mangled")
.span_suggestion(
attr.span,
"remove this attribute",
String::new(),
Applicability::MachineApplicable,
)
.emit();
});
}
_ => {
// FIXME: #[no_mangle] was previously allowed on non-functions/statics and some
// crates used this, so only emit a warning.

30
src/test/ui/extern/extern-no-mangle.rs vendored Normal file
View file

@ -0,0 +1,30 @@
#![warn(unused_attributes)]
// Tests that placing the #[no_mangle] attribute on a foreign fn or static emits
// a specialized warning.
// The previous warning only talks about a "function or static" but foreign fns/statics
// are also not allowed to have #[no_mangle]
// build-pass
extern "C" {
#[no_mangle]
//~^ WARNING `#[no_mangle]` has no effect on a foreign static
//~^^ WARNING this was previously accepted by the compiler
pub static FOO: u8;
#[no_mangle]
//~^ WARNING `#[no_mangle]` has no effect on a foreign function
//~^^ WARNING this was previously accepted by the compiler
pub fn bar();
}
fn no_new_warn() {
// Should emit the generic "not a function or static" warning
#[no_mangle]
//~^ WARNING attribute should be applied to a free function, impl method or static
//~^^ WARNING this was previously accepted by the compiler
let x = 0_u8;
}
fn main() {}

View file

@ -0,0 +1,42 @@
warning: attribute should be applied to a free function, impl method or static
--> $DIR/extern-no-mangle.rs:24:5
|
LL | #[no_mangle]
| ^^^^^^^^^^^^
...
LL | let x = 0_u8;
| ------------- not a free function, impl method or static
|
note: the lint level is defined here
--> $DIR/extern-no-mangle.rs:1:9
|
LL | #![warn(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: `#[no_mangle]` has no effect on a foreign static
--> $DIR/extern-no-mangle.rs:11:5
|
LL | #[no_mangle]
| ^^^^^^^^^^^^ help: remove this attribute
...
LL | pub static FOO: u8;
| ------------------- foreign static
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: symbol names in extern blocks are not mangled
warning: `#[no_mangle]` has no effect on a foreign function
--> $DIR/extern-no-mangle.rs:16:5
|
LL | #[no_mangle]
| ^^^^^^^^^^^^ help: remove this attribute
...
LL | pub fn bar();
| ------------- foreign function
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: symbol names in extern blocks are not mangled
warning: 3 warnings emitted