Skip to content

Commit 10b3a0d

Browse files
committed
Auto merge of #96885 - petrochenkov:linkstrict2, r=cjgillot,luqmana
rustc: Stricter checking for #[link] attributes A subset of #94962 that doesn't touch library renaming/reordering/deduplication. `#[link]` attributes are checked for all kinds of unexpected arguments inside them. I also tried to make wording for these errors more consistent, that's why some existing errors are changed, including errors for command line `-l` options. Spans are also made more precise where possible.
2 parents e1ec326 + 4fa24bc commit 10b3a0d

File tree

61 files changed

+774
-535
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+774
-535
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

-31
Original file line numberDiff line numberDiff line change
@@ -396,37 +396,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
396396
}
397397
}
398398

399-
// Check for unstable modifiers on `#[link(..)]` attribute
400-
if attr.has_name(sym::link) {
401-
for nested_meta in attr.meta_item_list().unwrap_or_default() {
402-
if nested_meta.has_name(sym::modifiers) {
403-
if let Some(modifiers) = nested_meta.value_str() {
404-
for modifier in modifiers.as_str().split(',') {
405-
if let Some(modifier) = modifier.strip_prefix(&['+', '-']) {
406-
macro_rules! gate_modifier { ($($name:literal => $feature:ident)*) => {
407-
$(if modifier == $name {
408-
let msg = concat!("`#[link(modifiers=\"", $name, "\")]` is unstable");
409-
gate_feature_post!(
410-
self,
411-
$feature,
412-
nested_meta.name_value_literal_span().unwrap(),
413-
msg
414-
);
415-
})*
416-
}}
417-
418-
gate_modifier!(
419-
"bundle" => native_link_modifiers_bundle
420-
"verbatim" => native_link_modifiers_verbatim
421-
"as-needed" => native_link_modifiers_as_needed
422-
);
423-
}
424-
}
425-
}
426-
}
427-
}
428-
}
429-
430399
// Emit errors for non-staged-api crates.
431400
if !self.features.staged_api {
432401
if attr.has_name(sym::rustc_deprecated)

compiler/rustc_error_codes/src/error_codes/E0455.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
Some linking kinds are target-specific and not supported on all platforms.
2+
13
Linking with `kind=framework` is only supported when targeting macOS,
24
as frameworks are specific to that operating system.
35

6+
Similarly, `kind=raw-dylib` is only supported when targeting Windows-like
7+
platforms.
8+
49
Erroneous code example:
510

611
```ignore (should-compile_fail-but-cannot-doctest-conditionally-without-macos)

compiler/rustc_error_codes/src/error_codes/E0458.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ Please specify a valid "kind" value, from one of the following:
1212
* static
1313
* dylib
1414
* framework
15+
* raw-dylib

compiler/rustc_metadata/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
22
#![feature(crate_visibility_modifier)]
3+
#![feature(decl_macro)]
34
#![feature(drain_filter)]
45
#![feature(generators)]
6+
#![feature(let_chains)]
57
#![feature(let_else)]
68
#![feature(nll)]
79
#![feature(once_cell)]

compiler/rustc_metadata/src/native_libs.rs

+274-240
Large diffs are not rendered by default.

compiler/rustc_passes/src/check_attr.rs

+20-14
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use rustc_session::lint::builtin::{
2323
use rustc_session::parse::feature_err;
2424
use rustc_span::symbol::{kw, sym, Symbol};
2525
use rustc_span::{Span, DUMMY_SP};
26+
use rustc_target::spec::abi::Abi;
2627
use std::collections::hash_map::Entry;
2728

2829
pub(crate) fn target_from_impl_item<'tcx>(
@@ -1317,22 +1318,27 @@ impl CheckAttrVisitor<'_> {
13171318

13181319
/// Checks if `#[link]` is applied to an item other than a foreign module.
13191320
fn check_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
1320-
match target {
1321-
Target::ForeignMod => {}
1322-
_ => {
1323-
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
1324-
let mut diag = lint.build("attribute should be applied to an `extern` block");
1325-
diag.warn(
1326-
"this was previously accepted by the compiler but is \
1327-
being phased out; it will become a hard error in \
1328-
a future release!",
1329-
);
1321+
if target == Target::ForeignMod
1322+
&& let hir::Node::Item(item) = self.tcx.hir().get(hir_id)
1323+
&& let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item
1324+
&& !matches!(abi, Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic)
1325+
{
1326+
return;
1327+
}
13301328

1331-
diag.span_label(span, "not an `extern` block");
1332-
diag.emit();
1333-
});
1329+
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
1330+
let mut diag =
1331+
lint.build("attribute should be applied to an `extern` block with non-Rust ABI");
1332+
diag.warn(
1333+
"this was previously accepted by the compiler but is \
1334+
being phased out; it will become a hard error in \
1335+
a future release!",
1336+
);
1337+
if target != Target::ForeignMod {
1338+
diag.span_label(span, "not an `extern` block");
13341339
}
1335-
}
1340+
diag.emit();
1341+
});
13361342
}
13371343

13381344
/// Checks if `#[link_name]` is applied to an item other than a foreign function or static.

compiler/rustc_session/src/config.rs

+45-59
Original file line numberDiff line numberDiff line change
@@ -1937,33 +1937,27 @@ fn parse_native_lib_kind(
19371937
};
19381938

19391939
let kind = match kind {
1940-
"dylib" => NativeLibKind::Dylib { as_needed: None },
1941-
"framework" => NativeLibKind::Framework { as_needed: None },
19421940
"static" => NativeLibKind::Static { bundle: None, whole_archive: None },
19431941
"static-nobundle" => {
19441942
early_warn(
19451943
error_format,
19461944
"library kind `static-nobundle` has been superseded by specifying \
1947-
`-bundle` on library kind `static`. Try `static:-bundle`",
1945+
modifier `-bundle` with library kind `static`. Try `static:-bundle`",
19481946
);
1949-
if modifiers.is_some() {
1950-
early_error(
1951-
error_format,
1952-
"linking modifier can't be used with library kind `static-nobundle`",
1953-
)
1954-
}
19551947
if !nightly_options::match_is_nightly_build(matches) {
19561948
early_error(
19571949
error_format,
1958-
"library kind `static-nobundle` are currently unstable and only accepted on \
1959-
the nightly compiler",
1950+
"library kind `static-nobundle` is unstable \
1951+
and only accepted on the nightly compiler",
19601952
);
19611953
}
19621954
NativeLibKind::Static { bundle: Some(false), whole_archive: None }
19631955
}
1964-
s => early_error(
1956+
"dylib" => NativeLibKind::Dylib { as_needed: None },
1957+
"framework" => NativeLibKind::Framework { as_needed: None },
1958+
_ => early_error(
19651959
error_format,
1966-
&format!("unknown library kind `{s}`, expected one of dylib, framework, or static"),
1960+
&format!("unknown library kind `{kind}`, expected one of: static, dylib, framework"),
19671961
),
19681962
};
19691963
match modifiers {
@@ -1978,94 +1972,83 @@ fn parse_native_lib_modifiers(
19781972
error_format: ErrorOutputType,
19791973
matches: &getopts::Matches,
19801974
) -> (NativeLibKind, Option<bool>) {
1981-
let report_unstable_modifier = |modifier| {
1982-
if !nightly_options::is_unstable_enabled(matches) {
1983-
let why = if nightly_options::match_is_nightly_build(matches) {
1984-
" and only accepted on the nightly compiler"
1985-
} else {
1986-
", the `-Z unstable-options` flag must also be passed to use it"
1987-
};
1988-
early_error(
1989-
error_format,
1990-
&format!("{modifier} linking modifier is currently unstable{why}"),
1991-
)
1992-
}
1993-
};
1994-
1995-
let mut has_duplicate_modifiers = false;
19961975
let mut verbatim = None;
19971976
for modifier in modifiers.split(',') {
19981977
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
19991978
Some(m) => (m, modifier.starts_with('+')),
20001979
None => early_error(
20011980
error_format,
20021981
"invalid linking modifier syntax, expected '+' or '-' prefix \
2003-
before one of: bundle, verbatim, whole-archive, as-needed",
1982+
before one of: bundle, verbatim, whole-archive, as-needed",
20041983
),
20051984
};
20061985

1986+
let report_unstable_modifier = || {
1987+
if !nightly_options::is_unstable_enabled(matches) {
1988+
let why = if nightly_options::match_is_nightly_build(matches) {
1989+
" and only accepted on the nightly compiler"
1990+
} else {
1991+
", the `-Z unstable-options` flag must also be passed to use it"
1992+
};
1993+
early_error(
1994+
error_format,
1995+
&format!("linking modifier `{modifier}` is unstable{why}"),
1996+
)
1997+
}
1998+
};
1999+
let assign_modifier = |dst: &mut Option<bool>| {
2000+
if dst.is_some() {
2001+
let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
2002+
early_error(error_format, &msg)
2003+
} else {
2004+
*dst = Some(value);
2005+
}
2006+
};
20072007
match (modifier, &mut kind) {
20082008
("bundle", NativeLibKind::Static { bundle, .. }) => {
2009-
report_unstable_modifier(modifier);
2010-
if bundle.is_some() {
2011-
has_duplicate_modifiers = true;
2012-
}
2013-
*bundle = Some(value);
2009+
report_unstable_modifier();
2010+
assign_modifier(bundle)
20142011
}
20152012
("bundle", _) => early_error(
20162013
error_format,
2017-
"bundle linking modifier is only compatible with \
2018-
`static` linking kind",
2014+
"linking modifier `bundle` is only compatible with `static` linking kind",
20192015
),
20202016

20212017
("verbatim", _) => {
2022-
report_unstable_modifier(modifier);
2023-
if verbatim.is_some() {
2024-
has_duplicate_modifiers = true;
2025-
}
2026-
verbatim = Some(value);
2018+
report_unstable_modifier();
2019+
assign_modifier(&mut verbatim)
20272020
}
20282021

20292022
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
2030-
if whole_archive.is_some() {
2031-
has_duplicate_modifiers = true;
2032-
}
2033-
*whole_archive = Some(value);
2023+
assign_modifier(whole_archive)
20342024
}
20352025
("whole-archive", _) => early_error(
20362026
error_format,
2037-
"whole-archive linking modifier is only compatible with \
2038-
`static` linking kind",
2027+
"linking modifier `whole-archive` is only compatible with `static` linking kind",
20392028
),
20402029

20412030
("as-needed", NativeLibKind::Dylib { as_needed })
20422031
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
2043-
report_unstable_modifier(modifier);
2044-
if as_needed.is_some() {
2045-
has_duplicate_modifiers = true;
2046-
}
2047-
*as_needed = Some(value);
2032+
report_unstable_modifier();
2033+
assign_modifier(as_needed)
20482034
}
20492035
("as-needed", _) => early_error(
20502036
error_format,
2051-
"as-needed linking modifier is only compatible with \
2052-
`dylib` and `framework` linking kinds",
2037+
"linking modifier `as-needed` is only compatible with \
2038+
`dylib` and `framework` linking kinds",
20532039
),
20542040

20552041
// Note: this error also excludes the case with empty modifier
20562042
// string, like `modifiers = ""`.
20572043
_ => early_error(
20582044
error_format,
20592045
&format!(
2060-
"unrecognized linking modifier `{modifier}`, expected one \
2061-
of: bundle, verbatim, whole-archive, as-needed"
2046+
"unknown linking modifier `{modifier}`, expected one \
2047+
of: bundle, verbatim, whole-archive, as-needed"
20622048
),
20632049
),
20642050
}
20652051
}
2066-
if has_duplicate_modifiers {
2067-
report_unstable_modifier("duplicating")
2068-
}
20692052

20702053
(kind, verbatim)
20712054
}
@@ -2093,6 +2076,9 @@ fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec<
20932076
None => (name, None),
20942077
Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())),
20952078
};
2079+
if name.is_empty() {
2080+
early_error(error_format, "library name must not be empty");
2081+
}
20962082
NativeLib { name, new_name, kind, verbatim }
20972083
})
20982084
.collect()

src/doc/rustc/src/command-line-arguments.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ where `KIND` may be one of:
5252
If the kind is specified, then linking modifiers can be attached to it.
5353
Modifiers are specified as a comma-delimited string with each modifier prefixed with
5454
either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively.
55-
The last boolean value specified for a given modifier wins. \
55+
Specifying multiple `modifiers` arguments in a single `link` attribute,
56+
or multiple identical modifiers in the same `modifiers` argument is not currently supported. \
5657
Example: `-l static:+whole-archive=mylib`.
5758

5859
The kind of library and the modifiers can also be specified in a [`#[link]`

src/test/ui/empty/empty-linkname.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[link(name = "")] //~ ERROR: given with empty name
1+
#[link(name = "")] //~ ERROR: link name must not be empty
22
extern "C" {}
33

44
fn main() {}

src/test/ui/empty/empty-linkname.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0454]: `#[link(name = "")]` given with empty name
2-
--> $DIR/empty-linkname.rs:1:1
1+
error[E0454]: link name must not be empty
2+
--> $DIR/empty-linkname.rs:1:15
33
|
44
LL | #[link(name = "")]
5-
| ^^^^^^^^^^^^^^^^^^ empty name given
5+
| ^^ empty link name
66

77
error: aborting due to previous error
88

src/test/ui/error-codes/E0454.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0454]: `#[link(name = "")]` given with empty name
2-
--> $DIR/E0454.rs:1:1
1+
error[E0454]: link name must not be empty
2+
--> $DIR/E0454.rs:1:15
33
|
44
LL | #[link(name = "")] extern "C" {}
5-
| ^^^^^^^^^^^^^^^^^^ empty name given
5+
| ^^ empty link name
66

77
error: aborting due to previous error
88

src/test/ui/error-codes/E0458.stderr

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
error[E0458]: unknown kind: `wonderful_unicorn`
2-
--> $DIR/E0458.rs:1:8
1+
error[E0458]: unknown link kind `wonderful_unicorn`, expected one of: static, dylib, framework, raw-dylib
2+
--> $DIR/E0458.rs:1:15
33
|
44
LL | #[link(kind = "wonderful_unicorn")] extern "C" {}
5-
| -------^^^^^^^^^^^^^^^^^^^^^^^^^^--
6-
| |
7-
| unknown kind
5+
| ^^^^^^^^^^^^^^^^^^^ unknown link kind
86

9-
error[E0459]: `#[link(...)]` specified without `name = "foo"`
7+
error[E0459]: `#[link]` attribute requires a `name = "string"` argument
108
--> $DIR/E0458.rs:1:1
119
|
1210
LL | #[link(kind = "wonderful_unicorn")] extern "C" {}

src/test/ui/error-codes/E0459.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0459]: `#[link(...)]` specified without `name = "foo"`
1+
error[E0459]: `#[link]` attribute requires a `name = "string"` argument
22
--> $DIR/E0459.rs:1:1
33
|
44
LL | #[link(kind = "dylib")] extern "C" {}

src/test/ui/feature-gates/feature-gate-link_cfg.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0658]: kind="link_cfg" is unstable
2-
--> $DIR/feature-gate-link_cfg.rs:1:1
1+
error[E0658]: link cfg is unstable
2+
--> $DIR/feature-gate-link_cfg.rs:1:22
33
|
44
LL | #[link(name = "foo", cfg(foo))]
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^
66
|
77
= note: see issue #37406 <https://github.com/rust-lang/rust/issues/37406> for more information
88
= help: add `#![feature(link_cfg)]` to the crate attributes to enable
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#[link(name = "foo", modifiers = "+as-needed")]
2-
//~^ ERROR: `#[link(modifiers="as-needed")]` is unstable
1+
#[link(name = "foo", kind = "dylib", modifiers = "+as-needed")]
2+
//~^ ERROR: linking modifier `as-needed` is unstable
33
extern "C" {}
44

55
fn main() {}

src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0658]: `#[link(modifiers="as-needed")]` is unstable
2-
--> $DIR/feature-gate-native_link_modifiers_as_needed.rs:1:34
1+
error[E0658]: linking modifier `as-needed` is unstable
2+
--> $DIR/feature-gate-native_link_modifiers_as_needed.rs:1:50
33
|
4-
LL | #[link(name = "foo", modifiers = "+as-needed")]
5-
| ^^^^^^^^^^^^
4+
LL | #[link(name = "foo", kind = "dylib", modifiers = "+as-needed")]
5+
| ^^^^^^^^^^^^
66
|
77
= note: see issue #81490 <https://github.com/rust-lang/rust/issues/81490> for more information
88
= help: add `#![feature(native_link_modifiers_as_needed)]` to the crate attributes to enable
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
error: bundle linking modifier is currently unstable and only accepted on the nightly compiler
1+
error: linking modifier `bundle` is unstable and only accepted on the nightly compiler
22

0 commit comments

Comments
 (0)