Rollup merge of #147262 - JonathanBrouwer:fix-link, r=jieyouxu

Make #[link="dl"] an FCW rather than an error

Fixes https://github.com/rust-lang/rust/issues/147254
I forgot to implement the T-lang decision in https://github.com/rust-lang/rust/pull/143193#issuecomment-3138479942, this implements that decision

r? ``@jdonszelmann``
Can be reviewed commit-by-commit
This needs a beta backport
This commit is contained in:
Stuart Cook 2025-10-05 22:15:06 +11:00 committed by GitHub
commit d97e346ac7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 73 additions and 9 deletions

View file

@ -65,10 +65,22 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
cx: &'c mut AcceptContext<'_, '_, S>,
args: &'c ArgParser<'_>,
) -> impl IntoIterator<Item = Self::Item> + 'c {
let mut result = None;
let Some(items) = args.list() else {
cx.expected_list(cx.attr_span);
return result;
let items = match args {
ArgParser::List(list) => list,
// This is an edgecase added because making this a hard error would break too many crates
// Specifically `#[link = "dl"]` is accepted with a FCW
// For more information, see https://github.com/rust-lang/rust/pull/143193
ArgParser::NameValue(nv) if nv.value_as_str().is_some_and(|v| v == sym::dl) => {
let suggestions = <Self as CombineAttributeParser<S>>::TEMPLATE
.suggestions(cx.attr_style, "link");
let span = cx.attr_span;
cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span);
return None;
}
_ => {
cx.expected_list(cx.attr_span);
return None;
}
};
let sess = cx.sess();
@ -113,7 +125,7 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
}
};
if !cont {
return result;
return None;
}
}
@ -202,7 +214,7 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
}
let Some((name, name_span)) = name else {
cx.emit_err(LinkRequiresName { span: cx.attr_span });
return result;
return None;
};
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
@ -218,15 +230,14 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
cx.emit_err(RawDylibNoNul { span: name_span });
}
result = Some(LinkEntry {
Some(LinkEntry {
span: cx.attr_span,
kind: kind.unwrap_or(NativeLibKind::Unspecified),
name,
cfg,
verbatim,
import_name_type,
});
result
})
}
}

View file

@ -874,6 +874,7 @@ symbols! {
div,
div_assign,
diverging_block_default,
dl,
do_not_recommend,
doc,
doc_alias,

View file

@ -0,0 +1,10 @@
Future incompatibility report: Future breakage diagnostic:
warning: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", wasm_import_module = "...")]`
--> $DIR/link-dl.rs:14:1
|
LL | #[link="dl"]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>

View file

@ -0,0 +1,23 @@
error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", wasm_import_module = "...")]`
--> $DIR/link-dl.rs:14:1
|
LL | #[link="dl"]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
= note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
error: aborting due to 1 previous error
Future incompatibility report: Future breakage diagnostic:
error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", wasm_import_module = "...")]`
--> $DIR/link-dl.rs:14:1
|
LL | #[link="dl"]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
= note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default

View file

@ -0,0 +1,19 @@
// Regression test for an issue discovered in https://github.com/rust-lang/rust/pull/143193/files and rediscovered in https://github.com/rust-lang/rust/issues/147254#event-20049906781
// Malformed #[link] attribute was supposed to be deny-by-default report-in-deps FCW,
// but accidentally was landed as a hard error.
//
// revision `default_fcw` tests that with `ill_formed_attribute_input` (the default) denied,
// the attribute produces an FCW
// revision `allowed` tests that with `ill_formed_attribute_input` allowed the test passes
//@ revisions: default_fcw allowed
//@[allowed] check-pass
#[cfg_attr(allowed, allow(ill_formed_attribute_input))]
#[link="dl"]
//[default_fcw]~^ ERROR valid forms for the attribute are
//[default_fcw]~| WARN previously accepted
extern "C" { }
fn main() {}