Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c602e9a

Browse files
committedNov 18, 2024
Auto merge of #133160 - jhpratt:rollup-wzj9q15, r=jhpratt
Rollup of 4 pull requests Successful merges: - #132934 (Overhaul the `-l` option parser (for linking to native libs)) - #133142 (rename rustc_const_stable_intrinsic -> rustc_intrinsic_const_stable_indirect) - #133145 (Document alternatives to `static mut`) - #133158 (Subtree update of `rust-analyzer`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents e83c45a + 194c76e commit c602e9a

25 files changed

+378
-217
lines changed
 

‎compiler/rustc_const_eval/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ const_eval_uninhabited_enum_variant_written =
403403
const_eval_unmarked_const_fn_exposed = `{$def_path}` cannot be (indirectly) exposed to stable
404404
.help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
405405
const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable
406-
.help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
406+
.help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_intrinsic_const_stable_indirect]` (but this requires team approval)
407407
408408
const_eval_unreachable = entering unreachable code
409409
const_eval_unreachable_unwind =

‎compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
760760
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
761761
// All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it
762762
// can be *directly* invoked from stable const code) does not always
763-
// have the `#[rustc_const_stable_intrinsic]` attribute (which controls
763+
// have the `#[rustc_intrinsic_const_stable_indirect]` attribute (which controls
764764
// exposing an intrinsic indirectly); we accept this call anyway.
765765
}
766766
}

‎compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
838838
template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
839839
),
840840
rustc_attr!(
841-
rustc_const_stable_intrinsic, Normal,
841+
rustc_intrinsic_const_stable_indirect, Normal,
842842
template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
843843
),
844844
gated!(

‎compiler/rustc_middle/src/ty/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1793,7 +1793,7 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Intrinsi
17931793
Some(ty::IntrinsicDef {
17941794
name: tcx.item_name(def_id.into()),
17951795
must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
1796-
const_stable: tcx.has_attr(def_id, sym::rustc_const_stable_intrinsic),
1796+
const_stable: tcx.has_attr(def_id, sym::rustc_intrinsic_const_stable_indirect),
17971797
})
17981798
} else {
17991799
None

‎compiler/rustc_session/src/config.rs

Lines changed: 9 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,18 @@ use rustc_target::spec::{
3030
};
3131
use tracing::debug;
3232

33+
pub use crate::config::cfg::{Cfg, CheckCfg, ExpectedValues};
34+
use crate::config::native_libs::parse_native_libs;
3335
use crate::errors::FileWriteFail;
3436
pub use crate::options::*;
3537
use crate::search_paths::SearchPath;
36-
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
38+
use crate::utils::CanonicalizedPath;
3739
use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint};
3840

3941
mod cfg;
42+
mod native_libs;
4043
pub mod sigpipe;
4144

42-
pub use cfg::{Cfg, CheckCfg, ExpectedValues};
43-
4445
/// The different settings that the `-C strip` flag can have.
4546
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
4647
pub enum Strip {
@@ -2134,143 +2135,6 @@ fn parse_assert_incr_state(
21342135
}
21352136
}
21362137

2137-
fn parse_native_lib_kind(
2138-
early_dcx: &EarlyDiagCtxt,
2139-
matches: &getopts::Matches,
2140-
kind: &str,
2141-
) -> (NativeLibKind, Option<bool>) {
2142-
let (kind, modifiers) = match kind.split_once(':') {
2143-
None => (kind, None),
2144-
Some((kind, modifiers)) => (kind, Some(modifiers)),
2145-
};
2146-
2147-
let kind = match kind {
2148-
"static" => NativeLibKind::Static { bundle: None, whole_archive: None },
2149-
"dylib" => NativeLibKind::Dylib { as_needed: None },
2150-
"framework" => NativeLibKind::Framework { as_needed: None },
2151-
"link-arg" => {
2152-
if !nightly_options::is_unstable_enabled(matches) {
2153-
let why = if nightly_options::match_is_nightly_build(matches) {
2154-
" and only accepted on the nightly compiler"
2155-
} else {
2156-
", the `-Z unstable-options` flag must also be passed to use it"
2157-
};
2158-
early_dcx.early_fatal(format!("library kind `link-arg` is unstable{why}"))
2159-
}
2160-
NativeLibKind::LinkArg
2161-
}
2162-
_ => early_dcx.early_fatal(format!(
2163-
"unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
2164-
)),
2165-
};
2166-
match modifiers {
2167-
None => (kind, None),
2168-
Some(modifiers) => parse_native_lib_modifiers(early_dcx, kind, modifiers, matches),
2169-
}
2170-
}
2171-
2172-
fn parse_native_lib_modifiers(
2173-
early_dcx: &EarlyDiagCtxt,
2174-
mut kind: NativeLibKind,
2175-
modifiers: &str,
2176-
matches: &getopts::Matches,
2177-
) -> (NativeLibKind, Option<bool>) {
2178-
let mut verbatim = None;
2179-
for modifier in modifiers.split(',') {
2180-
let (modifier, value) = match modifier.strip_prefix(['+', '-']) {
2181-
Some(m) => (m, modifier.starts_with('+')),
2182-
None => early_dcx.early_fatal(
2183-
"invalid linking modifier syntax, expected '+' or '-' prefix \
2184-
before one of: bundle, verbatim, whole-archive, as-needed",
2185-
),
2186-
};
2187-
2188-
let report_unstable_modifier = || {
2189-
if !nightly_options::is_unstable_enabled(matches) {
2190-
let why = if nightly_options::match_is_nightly_build(matches) {
2191-
" and only accepted on the nightly compiler"
2192-
} else {
2193-
", the `-Z unstable-options` flag must also be passed to use it"
2194-
};
2195-
early_dcx.early_fatal(format!("linking modifier `{modifier}` is unstable{why}"))
2196-
}
2197-
};
2198-
let assign_modifier = |dst: &mut Option<bool>| {
2199-
if dst.is_some() {
2200-
let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
2201-
early_dcx.early_fatal(msg)
2202-
} else {
2203-
*dst = Some(value);
2204-
}
2205-
};
2206-
match (modifier, &mut kind) {
2207-
("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle),
2208-
("bundle", _) => early_dcx.early_fatal(
2209-
"linking modifier `bundle` is only compatible with `static` linking kind",
2210-
),
2211-
2212-
("verbatim", _) => assign_modifier(&mut verbatim),
2213-
2214-
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
2215-
assign_modifier(whole_archive)
2216-
}
2217-
("whole-archive", _) => early_dcx.early_fatal(
2218-
"linking modifier `whole-archive` is only compatible with `static` linking kind",
2219-
),
2220-
2221-
("as-needed", NativeLibKind::Dylib { as_needed })
2222-
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
2223-
report_unstable_modifier();
2224-
assign_modifier(as_needed)
2225-
}
2226-
("as-needed", _) => early_dcx.early_fatal(
2227-
"linking modifier `as-needed` is only compatible with \
2228-
`dylib` and `framework` linking kinds",
2229-
),
2230-
2231-
// Note: this error also excludes the case with empty modifier
2232-
// string, like `modifiers = ""`.
2233-
_ => early_dcx.early_fatal(format!(
2234-
"unknown linking modifier `{modifier}`, expected one \
2235-
of: bundle, verbatim, whole-archive, as-needed"
2236-
)),
2237-
}
2238-
}
2239-
2240-
(kind, verbatim)
2241-
}
2242-
2243-
fn parse_libs(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Vec<NativeLib> {
2244-
matches
2245-
.opt_strs("l")
2246-
.into_iter()
2247-
.map(|s| {
2248-
// Parse string of the form "[KIND[:MODIFIERS]=]lib[:new_name]",
2249-
// where KIND is one of "dylib", "framework", "static", "link-arg" and
2250-
// where MODIFIERS are a comma separated list of supported modifiers
2251-
// (bundle, verbatim, whole-archive, as-needed). Each modifier is prefixed
2252-
// with either + or - to indicate whether it is enabled or disabled.
2253-
// The last value specified for a given modifier wins.
2254-
let (name, kind, verbatim) = match s.split_once('=') {
2255-
None => (s, NativeLibKind::Unspecified, None),
2256-
Some((kind, name)) => {
2257-
let (kind, verbatim) = parse_native_lib_kind(early_dcx, matches, kind);
2258-
(name.to_string(), kind, verbatim)
2259-
}
2260-
};
2261-
2262-
let (name, new_name) = match name.split_once(':') {
2263-
None => (name, None),
2264-
Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())),
2265-
};
2266-
if name.is_empty() {
2267-
early_dcx.early_fatal("library name must not be empty");
2268-
}
2269-
NativeLib { name, new_name, kind, verbatim }
2270-
})
2271-
.collect()
2272-
}
2273-
22742138
pub fn parse_externs(
22752139
early_dcx: &EarlyDiagCtxt,
22762140
matches: &getopts::Matches,
@@ -2644,7 +2508,10 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
26442508
let debuginfo = select_debuginfo(matches, &cg);
26452509
let debuginfo_compression = unstable_opts.debuginfo_compression;
26462510

2647-
let libs = parse_libs(early_dcx, matches);
2511+
let crate_name = matches.opt_str("crate-name");
2512+
let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref());
2513+
// Parse any `-l` flags, which link to native libraries.
2514+
let libs = parse_native_libs(early_dcx, &unstable_opts, unstable_features, matches);
26482515

26492516
let test = matches.opt_present("test");
26502517

@@ -2659,8 +2526,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
26592526

26602527
let externs = parse_externs(early_dcx, matches, &unstable_opts);
26612528

2662-
let crate_name = matches.opt_str("crate-name");
2663-
26642529
let remap_path_prefix = parse_remap_path_prefix(early_dcx, matches, &unstable_opts);
26652530

26662531
let pretty = parse_pretty(early_dcx, &unstable_opts);
@@ -2734,7 +2599,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
27342599
error_format,
27352600
diagnostic_width,
27362601
externs,
2737-
unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()),
2602+
unstable_features,
27382603
crate_name,
27392604
libs,
27402605
debug_assertions,
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
//! Parser for the `-l` command-line option, which links the generated crate to
2+
//! a native library.
3+
//!
4+
//! (There is also a similar but separate syntax for `#[link]` attributes,
5+
//! which have their own parser in `rustc_metadata`.)
6+
7+
use rustc_feature::UnstableFeatures;
8+
9+
use crate::EarlyDiagCtxt;
10+
use crate::config::UnstableOptions;
11+
use crate::utils::{NativeLib, NativeLibKind};
12+
13+
#[cfg(test)]
14+
mod tests;
15+
16+
/// Parses all `-l` options.
17+
pub(crate) fn parse_native_libs(
18+
early_dcx: &EarlyDiagCtxt,
19+
unstable_opts: &UnstableOptions,
20+
unstable_features: UnstableFeatures,
21+
matches: &getopts::Matches,
22+
) -> Vec<NativeLib> {
23+
let cx = ParseNativeLibCx {
24+
early_dcx,
25+
unstable_options_enabled: unstable_opts.unstable_options,
26+
is_nightly: unstable_features.is_nightly_build(),
27+
};
28+
matches.opt_strs("l").into_iter().map(|value| parse_native_lib(&cx, &value)).collect()
29+
}
30+
31+
struct ParseNativeLibCx<'a> {
32+
early_dcx: &'a EarlyDiagCtxt,
33+
unstable_options_enabled: bool,
34+
is_nightly: bool,
35+
}
36+
37+
impl ParseNativeLibCx<'_> {
38+
/// If unstable values are not permitted, exits with a fatal error made by
39+
/// combining the given strings.
40+
fn on_unstable_value(&self, message: &str, if_nightly: &str, if_stable: &str) {
41+
if self.unstable_options_enabled {
42+
return;
43+
}
44+
45+
let suffix = if self.is_nightly { if_nightly } else { if_stable };
46+
self.early_dcx.early_fatal(format!("{message}{suffix}"));
47+
}
48+
}
49+
50+
/// Parses the value of a single `-l` option.
51+
fn parse_native_lib(cx: &ParseNativeLibCx<'_>, value: &str) -> NativeLib {
52+
let NativeLibParts { kind, modifiers, name, new_name } = split_native_lib_value(value);
53+
54+
let kind = kind.map_or(NativeLibKind::Unspecified, |kind| match kind {
55+
"static" => NativeLibKind::Static { bundle: None, whole_archive: None },
56+
"dylib" => NativeLibKind::Dylib { as_needed: None },
57+
"framework" => NativeLibKind::Framework { as_needed: None },
58+
"link-arg" => {
59+
cx.on_unstable_value(
60+
"library kind `link-arg` is unstable",
61+
", the `-Z unstable-options` flag must also be passed to use it",
62+
" and only accepted on the nightly compiler",
63+
);
64+
NativeLibKind::LinkArg
65+
}
66+
_ => cx.early_dcx.early_fatal(format!(
67+
"unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
68+
)),
69+
});
70+
71+
// Provisionally create the result, so that modifiers can modify it.
72+
let mut native_lib = NativeLib {
73+
name: name.to_owned(),
74+
new_name: new_name.map(str::to_owned),
75+
kind,
76+
verbatim: None,
77+
};
78+
79+
if let Some(modifiers) = modifiers {
80+
// If multiple modifiers are present, they are separated by commas.
81+
for modifier in modifiers.split(',') {
82+
parse_and_apply_modifier(cx, modifier, &mut native_lib);
83+
}
84+
}
85+
86+
if native_lib.name.is_empty() {
87+
cx.early_dcx.early_fatal("library name must not be empty");
88+
}
89+
90+
native_lib
91+
}
92+
93+
/// Parses one of the comma-separated modifiers (prefixed by `+` or `-`), and
94+
/// modifies `native_lib` appropriately.
95+
///
96+
/// Exits with a fatal error if a malformed/unknown/inappropriate modifier is
97+
/// found.
98+
fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_lib: &mut NativeLib) {
99+
let early_dcx = cx.early_dcx;
100+
101+
// Split off the leading `+` or `-` into a boolean value.
102+
let (modifier, value) = match modifier.split_at_checked(1) {
103+
Some(("+", m)) => (m, true),
104+
Some(("-", m)) => (m, false),
105+
_ => cx.early_dcx.early_fatal(
106+
"invalid linking modifier syntax, expected '+' or '-' prefix \
107+
before one of: bundle, verbatim, whole-archive, as-needed",
108+
),
109+
};
110+
111+
// Assigns the value (from `+` or `-`) to an empty `Option<bool>`, or emits
112+
// a fatal error if the option has already been set.
113+
let assign_modifier = |opt_bool: &mut Option<bool>| {
114+
if opt_bool.is_some() {
115+
let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
116+
early_dcx.early_fatal(msg)
117+
}
118+
*opt_bool = Some(value);
119+
};
120+
121+
// Check that the modifier is applicable to the native lib kind, and apply it.
122+
match (modifier, &mut native_lib.kind) {
123+
("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle),
124+
("bundle", _) => early_dcx
125+
.early_fatal("linking modifier `bundle` is only compatible with `static` linking kind"),
126+
127+
("verbatim", _) => assign_modifier(&mut native_lib.verbatim),
128+
129+
("whole-archive", NativeLibKind::Static { whole_archive, .. }) => {
130+
assign_modifier(whole_archive)
131+
}
132+
("whole-archive", _) => early_dcx.early_fatal(
133+
"linking modifier `whole-archive` is only compatible with `static` linking kind",
134+
),
135+
136+
("as-needed", NativeLibKind::Dylib { as_needed })
137+
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
138+
cx.on_unstable_value(
139+
"linking modifier `as-needed` is unstable",
140+
", the `-Z unstable-options` flag must also be passed to use it",
141+
" and only accepted on the nightly compiler",
142+
);
143+
assign_modifier(as_needed)
144+
}
145+
("as-needed", _) => early_dcx.early_fatal(
146+
"linking modifier `as-needed` is only compatible with \
147+
`dylib` and `framework` linking kinds",
148+
),
149+
150+
_ => early_dcx.early_fatal(format!(
151+
"unknown linking modifier `{modifier}`, expected one \
152+
of: bundle, verbatim, whole-archive, as-needed"
153+
)),
154+
}
155+
}
156+
157+
#[derive(Debug, PartialEq, Eq)]
158+
struct NativeLibParts<'a> {
159+
kind: Option<&'a str>,
160+
modifiers: Option<&'a str>,
161+
name: &'a str,
162+
new_name: Option<&'a str>,
163+
}
164+
165+
/// Splits a string of the form `[KIND[:MODIFIERS]=]NAME[:NEW_NAME]` into those
166+
/// individual parts. This cannot fail, but the resulting strings require
167+
/// further validation.
168+
fn split_native_lib_value(value: &str) -> NativeLibParts<'_> {
169+
// Split the initial value into `[KIND=]NAME`.
170+
let name = value;
171+
let (kind, name) = match name.split_once('=') {
172+
Some((prefix, name)) => (Some(prefix), name),
173+
None => (None, name),
174+
};
175+
176+
// Split the kind part, if present, into `KIND[:MODIFIERS]`.
177+
let (kind, modifiers) = match kind {
178+
Some(kind) => match kind.split_once(':') {
179+
Some((kind, modifiers)) => (Some(kind), Some(modifiers)),
180+
None => (Some(kind), None),
181+
},
182+
None => (None, None),
183+
};
184+
185+
// Split the name part into `NAME[:NEW_NAME]`.
186+
let (name, new_name) = match name.split_once(':') {
187+
Some((name, new_name)) => (name, Some(new_name)),
188+
None => (name, None),
189+
};
190+
191+
NativeLibParts { kind, modifiers, name, new_name }
192+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use crate::config::native_libs::{NativeLibParts, split_native_lib_value};
2+
3+
#[test]
4+
fn split() {
5+
// This is a unit test for some implementation details, so consider deleting
6+
// it if it gets in the way.
7+
use NativeLibParts as P;
8+
9+
let examples = &[
10+
("", P { kind: None, modifiers: None, name: "", new_name: None }),
11+
("foo", P { kind: None, modifiers: None, name: "foo", new_name: None }),
12+
("foo:", P { kind: None, modifiers: None, name: "foo", new_name: Some("") }),
13+
("foo:bar", P { kind: None, modifiers: None, name: "foo", new_name: Some("bar") }),
14+
(":bar", P { kind: None, modifiers: None, name: "", new_name: Some("bar") }),
15+
("kind=foo", P { kind: Some("kind"), modifiers: None, name: "foo", new_name: None }),
16+
(":mods=foo", P { kind: Some(""), modifiers: Some("mods"), name: "foo", new_name: None }),
17+
(":mods=:bar", P {
18+
kind: Some(""),
19+
modifiers: Some("mods"),
20+
name: "",
21+
new_name: Some("bar"),
22+
}),
23+
("kind=foo:bar", P {
24+
kind: Some("kind"),
25+
modifiers: None,
26+
name: "foo",
27+
new_name: Some("bar"),
28+
}),
29+
("kind:mods=foo", P {
30+
kind: Some("kind"),
31+
modifiers: Some("mods"),
32+
name: "foo",
33+
new_name: None,
34+
}),
35+
("kind:mods=foo:bar", P {
36+
kind: Some("kind"),
37+
modifiers: Some("mods"),
38+
name: "foo",
39+
new_name: Some("bar"),
40+
}),
41+
("::==::", P { kind: Some(""), modifiers: Some(":"), name: "=", new_name: Some(":") }),
42+
("==::==", P { kind: Some(""), modifiers: None, name: "=", new_name: Some(":==") }),
43+
];
44+
45+
for &(value, ref expected) in examples {
46+
println!("{value:?}");
47+
let actual = split_native_lib_value(value);
48+
assert_eq!(&actual, expected);
49+
}
50+
}

‎compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1666,7 +1666,6 @@ symbols! {
16661666
rustc_const_panic_str,
16671667
rustc_const_stable,
16681668
rustc_const_stable_indirect,
1669-
rustc_const_stable_intrinsic,
16701669
rustc_const_unstable,
16711670
rustc_conversion_suggestion,
16721671
rustc_deallocator,
@@ -1696,6 +1695,7 @@ symbols! {
16961695
rustc_inherit_overflow_checks,
16971696
rustc_insignificant_dtor,
16981697
rustc_intrinsic,
1698+
rustc_intrinsic_const_stable_indirect,
16991699
rustc_intrinsic_must_be_overridden,
17001700
rustc_layout,
17011701
rustc_layout_scalar_valid_range_end,

‎library/core/src/intrinsics/mod.rs

Lines changed: 48 additions & 48 deletions
Large diffs are not rendered by default.

‎library/std/src/keyword_docs.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,9 @@ mod self_upper_keyword {}
14481448
/// in a multithreaded context. As such, all accesses to mutable `static`s
14491449
/// require an [`unsafe`] block.
14501450
///
1451+
/// When possible, it's often better to use a non-mutable `static` with an
1452+
/// interior mutable type such as [`Mutex`], [`OnceLock`], or an [atomic].
1453+
///
14511454
/// Despite their unsafety, mutable `static`s are necessary in many contexts:
14521455
/// they can be used to represent global state shared by the whole program or in
14531456
/// [`extern`] blocks to bind to variables from C libraries.
@@ -1468,7 +1471,10 @@ mod self_upper_keyword {}
14681471
/// [`extern`]: keyword.extern.html
14691472
/// [`mut`]: keyword.mut.html
14701473
/// [`unsafe`]: keyword.unsafe.html
1474+
/// [`Mutex`]: sync::Mutex
1475+
/// [`OnceLock`]: sync::OnceLock
14711476
/// [`RefCell`]: cell::RefCell
1477+
/// [atomic]: sync::atomic
14721478
/// [Reference]: ../reference/items/static-items.html
14731479
mod static_keyword {}
14741480

‎src/tools/rust-analyzer/Cargo.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change

‎src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use either::Either;
22
use ide_db::FxHashMap;
33
use itertools::Itertools;
4-
use syntax::{ast, ted, AstNode, SmolStr, ToSmolStr};
4+
use syntax::{ast, syntax_editor::SyntaxEditor, AstNode, SmolStr, SyntaxElement, ToSmolStr};
55

66
use crate::{AssistContext, AssistId, AssistKind, Assists};
77

@@ -24,6 +24,11 @@ pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
2424
let record =
2525
path.syntax().parent().and_then(<Either<ast::RecordExpr, ast::RecordPat>>::cast)?;
2626

27+
let parent_node = match ctx.covering_element() {
28+
SyntaxElement::Node(n) => n,
29+
SyntaxElement::Token(t) => t.parent()?,
30+
};
31+
2732
let ranks = compute_fields_ranks(&path, ctx)?;
2833
let get_rank_of_field = |of: Option<SmolStr>| {
2934
*ranks.get(of.unwrap_or_default().trim_start_matches("r#")).unwrap_or(&usize::MAX)
@@ -65,23 +70,31 @@ pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
6570
AssistId("reorder_fields", AssistKind::RefactorRewrite),
6671
"Reorder record fields",
6772
target,
68-
|builder| match fields {
69-
Either::Left((sorted, field_list)) => {
70-
replace(builder.make_mut(field_list).fields(), sorted)
71-
}
72-
Either::Right((sorted, field_list)) => {
73-
replace(builder.make_mut(field_list).fields(), sorted)
73+
|builder| {
74+
let mut editor = builder.make_editor(&parent_node);
75+
76+
match fields {
77+
Either::Left((sorted, field_list)) => {
78+
replace(&mut editor, field_list.fields(), sorted)
79+
}
80+
Either::Right((sorted, field_list)) => {
81+
replace(&mut editor, field_list.fields(), sorted)
82+
}
7483
}
84+
85+
builder.add_file_edits(ctx.file_id(), editor);
7586
},
7687
)
7788
}
7889

7990
fn replace<T: AstNode + PartialEq>(
91+
editor: &mut SyntaxEditor,
8092
fields: impl Iterator<Item = T>,
8193
sorted_fields: impl IntoIterator<Item = T>,
8294
) {
8395
fields.zip(sorted_fields).for_each(|(field, sorted_field)| {
84-
ted::replace(field.syntax(), sorted_field.syntax().clone_for_update())
96+
// FIXME: remove `clone_for_update` when `SyntaxEditor` handles it for us
97+
editor.replace(field.syntax(), sorted_field.syntax().clone_for_update())
8598
});
8699
}
87100

‎src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -511,12 +511,16 @@ pub(crate) fn handle_document_diagnostics(
511511
.into_iter()
512512
.filter_map(|d| {
513513
let file = d.range.file_id;
514-
let diagnostic = convert_diagnostic(&line_index, d);
515514
if file == file_id {
515+
let diagnostic = convert_diagnostic(&line_index, d);
516516
return Some(diagnostic);
517517
}
518518
if supports_related {
519-
related_documents.entry(file).or_insert_with(Vec::new).push(diagnostic);
519+
let (diagnostics, line_index) = related_documents
520+
.entry(file)
521+
.or_insert_with(|| (Vec::new(), snap.file_line_index(file).ok()));
522+
let diagnostic = convert_diagnostic(line_index.as_mut()?, d);
523+
diagnostics.push(diagnostic);
520524
}
521525
None
522526
});
@@ -529,7 +533,7 @@ pub(crate) fn handle_document_diagnostics(
529533
related_documents: related_documents.is_empty().not().then(|| {
530534
related_documents
531535
.into_iter()
532-
.map(|(id, items)| {
536+
.map(|(id, (items, _))| {
533537
(
534538
to_proto::url(&snap, id),
535539
lsp_types::DocumentDiagnosticReportKind::Full(

‎tests/ui/consts/const-unstable-intrinsic.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ error: intrinsic `copy::copy` cannot be (indirectly) exposed to stable
7474
LL | unsafe { copy(src, dst, count) }
7575
| ^^^^^^^^^^^^^^^^^^^^^
7676
|
77-
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
77+
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_intrinsic_const_stable_indirect]` (but this requires team approval)
7878

7979
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
8080
--> $DIR/const-unstable-intrinsic.rs:61:9

‎tests/ui/feature-gates/feature-gate-link-arg-attribute.stderr renamed to ‎tests/ui/feature-gates/feature-gate-link-arg-attribute.in_attr.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0658]: link kind `link-arg` is unstable
2-
--> $DIR/feature-gate-link-arg-attribute.rs:1:15
2+
--> $DIR/feature-gate-link-arg-attribute.rs:5:15
33
|
44
LL | #[link(kind = "link-arg", name = "foo")]
55
| ^^^^^^^^^^
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: unknown linking modifier `link-arg`, expected one of: bundle, verbatim, whole-archive, as-needed
2+
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
//@ revisions: in_attr in_flag
2+
//@[in_flag] compile-flags: -l dylib:+link-arg=foo
3+
4+
#[cfg(in_attr)]
15
#[link(kind = "link-arg", name = "foo")]
2-
//~^ ERROR link kind `link-arg` is unstable
6+
//[in_attr]~^ ERROR link kind `link-arg` is unstable
37
extern "C" {}
48

59
fn main() {}

‎tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr renamed to ‎tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.in_attr.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0658]: linking modifier `as-needed` is unstable
2-
--> $DIR/feature-gate-native_link_modifiers_as_needed.rs:1:50
2+
--> $DIR/feature-gate-native_link_modifiers_as_needed.rs:5:50
33
|
44
LL | #[link(name = "foo", kind = "dylib", modifiers = "+as-needed")]
55
| ^^^^^^^^^^^^
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: linking modifier `as-needed` is unstable, the `-Z unstable-options` flag must also be passed to use it
2+
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
//@ revisions: in_attr in_flag
2+
//@[in_flag] compile-flags: -l dylib:+as-needed=foo
3+
4+
#[cfg(in_attr)]
15
#[link(name = "foo", kind = "dylib", modifiers = "+as-needed")]
2-
//~^ ERROR: linking modifier `as-needed` is unstable
6+
//[in_attr]~^ ERROR: linking modifier `as-needed` is unstable
37
extern "C" {}
48

59
fn main() {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: unknown linking modifier ``, expected one of: bundle, verbatim, whole-archive, as-needed
2+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//@ edition: 2021
2+
//@ revisions: blank no-prefix prefix-only unknown
3+
4+
//@[blank] compile-flags: -l static:=foo
5+
//@[no-prefix] compile-flags: -l static:bundle=foo
6+
//@[prefix-only] compile-flags: -l static:+=foo
7+
//@[unknown] compile-flags: -l static:+ferris=foo
8+
9+
// Tests various illegal values for the "modifier" part of an `-l` flag.
10+
11+
fn main() {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: unknown linking modifier `ferris`, expected one of: bundle, verbatim, whole-archive, as-needed
2+

0 commit comments

Comments
 (0)
Please sign in to comment.