Merge ref 'e004014d1b' from rust-lang/rust

Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: e004014d1b
Filtered ref: d62798e442c1c6ec461725b87dacc87c285259c8

This merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
The Miri Cronjob Bot 2025-08-30 05:00:00 +00:00
commit d269d234e0
493 changed files with 5851 additions and 4268 deletions

View file

@ -255,6 +255,7 @@ Guillaume Gomez <guillaume1.gomez@gmail.com>
Guillaume Gomez <guillaume1.gomez@gmail.com> ggomez <ggomez@ggo.ifr.lan>
Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <ggomez@ggo.ifr.lan>
Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <guillaume.gomez@huawei.com>
gnzlbg <gonzalobg88@gmail.com> <gnzlbg@users.noreply.github.com>
hamidreza kalbasi <hamidrezakalbasi@protonmail.com>
Hanna Kruppe <hanna.kruppe@gmail.com> <robin.kruppe@gmail.com>
Heather <heather@cynede.net> <Cynede@Gentoo.org>

View file

@ -1674,30 +1674,40 @@ checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
dependencies = [
"displaydoc",
"potential_utf",
"yoke 0.8.0",
"yoke",
"zerofrom",
"zerovec 0.11.4",
"zerovec",
]
[[package]]
name = "icu_list"
version = "1.5.0"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbfeda1d7775b6548edd4e8b7562304a559a91ed56ab56e18961a053f367c365"
checksum = "e26f94ec776bb8b28cedc7dcf91033b822c5cb4c1783cf7a3f796fc168aa0c8b"
dependencies = [
"displaydoc",
"icu_list_data",
"icu_locid_transform",
"icu_provider 1.5.0",
"regex-automata 0.2.0",
"writeable 0.5.5",
"icu_provider",
"regex-automata 0.4.9",
"serde",
"writeable",
"zerovec",
]
[[package]]
name = "icu_list_data"
version = "1.5.1"
name = "icu_locale"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52b1a7fbdbf3958f1be8354cb59ac73f165b7b7082d447ff2090355c9a069120"
checksum = "6ae5921528335e91da1b6c695dbf1ec37df5ac13faa3f91e5640be93aa2fbefd"
dependencies = [
"displaydoc",
"icu_collections",
"icu_locale_core",
"icu_locale_data",
"icu_provider",
"potential_utf",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_locale_core"
@ -1706,44 +1716,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
dependencies = [
"displaydoc",
"litemap 0.8.0",
"tinystr 0.8.1",
"writeable 0.6.1",
"zerovec 0.11.4",
"litemap",
"tinystr",
"writeable",
"zerovec",
]
[[package]]
name = "icu_locid"
version = "1.5.0"
name = "icu_locale_data"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
dependencies = [
"displaydoc",
"litemap 0.7.5",
"tinystr 0.7.6",
"writeable 0.5.5",
"zerovec 0.10.4",
]
[[package]]
name = "icu_locid_transform"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
dependencies = [
"displaydoc",
"icu_locid",
"icu_locid_transform_data",
"icu_provider 1.5.0",
"tinystr 0.7.6",
"zerovec 0.10.4",
]
[[package]]
name = "icu_locid_transform_data"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
checksum = "4fdef0c124749d06a743c69e938350816554eb63ac979166590e2b4ee4252765"
[[package]]
name = "icu_normalizer"
@ -1755,9 +1738,9 @@ dependencies = [
"icu_collections",
"icu_normalizer_data",
"icu_properties",
"icu_provider 2.0.0",
"icu_provider",
"smallvec",
"zerovec 0.11.4",
"zerovec",
]
[[package]]
@ -1776,10 +1759,10 @@ dependencies = [
"icu_collections",
"icu_locale_core",
"icu_properties_data",
"icu_provider 2.0.0",
"icu_provider",
"potential_utf",
"zerotrie",
"zerovec 0.11.4",
"zerovec",
]
[[package]]
@ -1788,23 +1771,6 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"
[[package]]
name = "icu_provider"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
dependencies = [
"displaydoc",
"icu_locid",
"icu_provider_macros",
"stable_deref_trait",
"tinystr 0.7.6",
"writeable 0.5.5",
"yoke 0.7.5",
"zerofrom",
"zerovec 0.10.4",
]
[[package]]
name = "icu_provider"
version = "2.0.0"
@ -1814,36 +1780,12 @@ dependencies = [
"displaydoc",
"icu_locale_core",
"stable_deref_trait",
"tinystr 0.8.1",
"writeable 0.6.1",
"yoke 0.8.0",
"tinystr",
"writeable",
"yoke",
"zerofrom",
"zerotrie",
"zerovec 0.11.4",
]
[[package]]
name = "icu_provider_adapters"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6324dfd08348a8e0374a447ebd334044d766b1839bb8d5ccf2482a99a77c0bc"
dependencies = [
"icu_locid",
"icu_locid_transform",
"icu_provider 1.5.0",
"tinystr 0.7.6",
"zerovec 0.10.4",
]
[[package]]
name = "icu_provider_macros"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
"zerovec",
]
[[package]]
@ -2243,12 +2185,6 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "litemap"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
[[package]]
name = "litemap"
version = "0.8.0"
@ -2959,7 +2895,8 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
dependencies = [
"zerovec 0.11.4",
"serde",
"zerovec",
]
[[package]]
@ -3205,15 +3142,6 @@ dependencies = [
"regex-syntax 0.6.29",
]
[[package]]
name = "regex-automata"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9368763f5a9b804326f3af749e16f9abf378d227bcdee7634b13d8f17793782"
dependencies = [
"memchr",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
@ -3480,6 +3408,7 @@ dependencies = [
"rustc_parse",
"rustc_session",
"rustc_span",
"rustc_target",
"thin-vec",
]
@ -3488,10 +3417,9 @@ name = "rustc_baked_icu_data"
version = "0.0.0"
dependencies = [
"icu_list",
"icu_locid",
"icu_locid_transform",
"icu_provider 1.5.0",
"zerovec 0.10.4",
"icu_locale",
"icu_provider",
"zerovec",
]
[[package]]
@ -3764,8 +3692,7 @@ dependencies = [
"fluent-bundle",
"fluent-syntax",
"icu_list",
"icu_locid",
"icu_provider_adapters",
"icu_locale",
"intl-memoizer",
"rustc_ast",
"rustc_ast_pretty",
@ -5497,16 +5424,6 @@ dependencies = [
"libc",
]
[[package]]
name = "tinystr"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
dependencies = [
"displaydoc",
"zerovec 0.10.4",
]
[[package]]
name = "tinystr"
version = "0.8.1"
@ -5514,7 +5431,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
dependencies = [
"displaydoc",
"zerovec 0.11.4",
"zerovec",
]
[[package]]
@ -5779,7 +5696,7 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658"
dependencies = [
"tinystr 0.8.1",
"tinystr",
]
[[package]]
@ -5789,7 +5706,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5957eb82e346d7add14182a3315a7e298f04e1ba4baac36f7f0dbfedba5fc25"
dependencies = [
"proc-macro-hack",
"tinystr 0.8.1",
"tinystr",
"unic-langid-impl",
"unic-langid-macros-impl",
]
@ -6683,12 +6600,6 @@ dependencies = [
"wasmparser 0.237.0",
]
[[package]]
name = "writeable"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]]
name = "writeable"
version = "0.6.1"
@ -6727,18 +6638,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "yoke"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
dependencies = [
"serde",
"stable_deref_trait",
"yoke-derive 0.7.5",
"zerofrom",
]
[[package]]
name = "yoke"
version = "0.8.0"
@ -6747,22 +6646,10 @@ checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
dependencies = [
"serde",
"stable_deref_trait",
"yoke-derive 0.8.0",
"yoke-derive",
"zerofrom",
]
[[package]]
name = "yoke-derive"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
"synstructure",
]
[[package]]
name = "yoke-derive"
version = "0.8.0"
@ -6823,41 +6710,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
dependencies = [
"displaydoc",
"yoke 0.8.0",
"yoke",
"zerofrom",
]
[[package]]
name = "zerovec"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
dependencies = [
"yoke 0.7.5",
"zerofrom",
"zerovec-derive 0.10.3",
]
[[package]]
name = "zerovec"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
dependencies = [
"yoke 0.8.0",
"yoke",
"zerofrom",
"zerovec-derive 0.11.1",
]
[[package]]
name = "zerovec-derive"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
"zerovec-derive",
]
[[package]]

View file

@ -59,6 +59,33 @@ exclude = [
"obj",
]
[workspace.dependencies]
# tidy-alphabetical-start
bitflags = "2.9.3"
derive-where = "1.6.0"
either = "1.15.0"
indexmap = "2.10.0"
itertools = "0.12.1"
# FIXME: Remove this pin once this rustix issue is resolved
# https://github.com/bytecodealliance/rustix/issues/1496
libc = "=0.2.174"
measureme = "12.0.3"
memchr = "2.7.5"
odht = { version = "0.3.1", features = ["nightly"] }
polonius-engine = "0.13.0"
proc-macro2 = "1.0.101"
quote = "1.0.40"
rustc-demangle = "0.1.26"
rustc-hash = "2.1.1"
rustc-literal-escaper = "0.0.5"
rustc_apfloat = "0.2.3"
scoped-tls = "1.0.1"
serde_json = "1.0.142"
tempfile = "3.20.0"
thin-vec = "0.2.14"
tracing = "0.1.37"
# tidy-alphabetical-end
[profile.release.package.rustc_thread_pool]
# The rustc fork of Rayon has deadlock detection code which intermittently
# causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227)

View file

@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
bitflags.workspace = true
rand = { version = "0.9.0", default-features = false, optional = true }
rand_xoshiro = { version = "0.7.0", optional = true }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
@ -15,7 +15,7 @@ rustc_index = { path = "../rustc_index", default-features = false }
rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true }
rustc_span = { path = "../rustc_span", optional = true }
tracing = "0.1"
tracing.workspace = true
# tidy-alphabetical-end
[features]

View file

@ -594,23 +594,13 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
discriminants: impl Iterator<Item = (VariantIdx, i128)>,
) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
// Until we've decided whether to use the tagged or
// niche filling LayoutData, we don't want to intern the
// variant layouts, so we can't store them in the
// overall LayoutData. Store the overall LayoutData
// and the variant LayoutDatas here until then.
struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> {
layout: LayoutData<FieldIdx, VariantIdx>,
variants: IndexVec<VariantIdx, LayoutData<FieldIdx, VariantIdx>>,
}
let dl = self.cx.data_layout();
// bail if the enum has an incoherent repr that cannot be computed
if repr.packed() {
return Err(LayoutCalculatorError::ReprConflict);
}
let calculate_niche_filling_layout = || -> Option<TmpLayout<FieldIdx, VariantIdx>> {
let calculate_niche_filling_layout = || -> Option<LayoutData<FieldIdx, VariantIdx>> {
if repr.inhibit_enum_layout_opt() {
return None;
}
@ -746,7 +736,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
niche_start,
},
tag_field: FieldIdx::new(0),
variants: IndexVec::new(),
variants: variant_layouts,
},
fields: FieldsShape::Arbitrary {
offsets: [niche_offset].into(),
@ -762,7 +752,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
randomization_seed: combined_seed,
};
Some(TmpLayout { layout, variants: variant_layouts })
Some(layout)
};
let niche_filling_layout = calculate_niche_filling_layout();
@ -1093,7 +1083,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
tag,
tag_encoding: TagEncoding::Direct,
tag_field: FieldIdx::new(0),
variants: IndexVec::new(),
variants: layout_variants,
},
fields: FieldsShape::Arbitrary {
offsets: [Size::ZERO].into(),
@ -1109,18 +1099,16 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
randomization_seed: combined_seed,
};
let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants };
let mut best_layout = match (tagged_layout, niche_filling_layout) {
let best_layout = match (tagged_layout, niche_filling_layout) {
(tl, Some(nl)) => {
// Pick the smaller layout; otherwise,
// pick the layout with the larger niche; otherwise,
// pick tagged as it has simpler codegen.
use cmp::Ordering::*;
let niche_size = |tmp_l: &TmpLayout<FieldIdx, VariantIdx>| {
tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl))
let niche_size = |l: &LayoutData<FieldIdx, VariantIdx>| {
l.largest_niche.map_or(0, |n| n.available(dl))
};
match (tl.layout.size.cmp(&nl.layout.size), niche_size(&tl).cmp(&niche_size(&nl))) {
match (tl.size.cmp(&nl.size), niche_size(&tl).cmp(&niche_size(&nl))) {
(Greater, _) => nl,
(Equal, Less) => nl,
_ => tl,
@ -1129,16 +1117,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
(tl, None) => tl,
};
// Now we can intern the variant layouts and store them in the enum layout.
best_layout.layout.variants = match best_layout.layout.variants {
Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
Variants::Multiple { tag, tag_encoding, tag_field, variants: best_layout.variants }
}
Variants::Single { .. } | Variants::Empty => {
panic!("encountered a single-variant or empty enum during multi-variant layout")
}
};
Ok(best_layout.layout)
Ok(best_layout)
}
fn univariant_biased<

View file

@ -5,9 +5,9 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
memchr = "2.7.4"
rustc-literal-escaper = "0.0.5"
bitflags.workspace = true
memchr.workspace = true
rustc-literal-escaper.workspace = true
rustc_ast_ir = { path = "../rustc_ast_ir" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_index = { path = "../rustc_index" }
@ -15,6 +15,6 @@ rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
thin-vec = "0.2.12"
tracing = "0.1"
thin-vec.workspace = true
tracing.workspace = true
# tidy-alphabetical-end

View file

@ -3,15 +3,6 @@
//! `TokenStream`s represent syntactic objects before they are converted into ASTs.
//! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s,
//! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens.
//!
//! ## Ownership
//!
//! `TokenStream`s are persistent data structures constructed as ropes with reference
//! counted-children. In general, this means that calling an operation on a `TokenStream`
//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
//! the original. This essentially coerces `TokenStream`s into "views" of their subparts,
//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking
//! ownership of the original.
use std::borrow::Cow;
use std::ops::Range;
@ -99,17 +90,6 @@ impl TokenTree {
}
}
impl<CTX> HashStable<CTX> for TokenStream
where
CTX: crate::HashStableContext,
{
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
for sub_tt in self.iter() {
sub_tt.hash_stable(hcx, hasher);
}
}
}
/// A lazy version of [`AttrTokenStream`], which defers creation of an actual
/// `AttrTokenStream` until it is needed.
#[derive(Clone)]
@ -556,10 +536,6 @@ pub struct AttrsTarget {
pub tokens: LazyAttrTokenStream,
}
/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
#[derive(Clone, Debug, Default, Encodable, Decodable)]
pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>);
/// Indicates whether a token can join with the following token to form a
/// compound token. Used for conversions to `proc_macro::Spacing`. Also used to
/// guide pretty-printing, which is where the `JointHidden` value (which isn't
@ -620,58 +596,9 @@ pub enum Spacing {
JointHidden,
}
impl TokenStream {
/// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
/// separating the two arguments with a comma for diagnostic suggestions.
pub fn add_comma(&self) -> Option<(TokenStream, Span)> {
// Used to suggest if a user writes `foo!(a b);`
let mut suggestion = None;
let mut iter = self.0.iter().enumerate().peekable();
while let Some((pos, ts)) = iter.next() {
if let Some((_, next)) = iter.peek() {
let sp = match (&ts, &next) {
(_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue,
(
TokenTree::Token(token_left, Spacing::Alone),
TokenTree::Token(token_right, _),
) if (token_left.is_non_reserved_ident() || token_left.is_lit())
&& (token_right.is_non_reserved_ident() || token_right.is_lit()) =>
{
token_left.span
}
(TokenTree::Delimited(sp, ..), _) => sp.entire(),
_ => continue,
};
let sp = sp.shrink_to_hi();
let comma = TokenTree::token_alone(token::Comma, sp);
suggestion = Some((pos, comma, sp));
}
}
if let Some((pos, comma, sp)) = suggestion {
let mut new_stream = Vec::with_capacity(self.0.len() + 1);
let parts = self.0.split_at(pos + 1);
new_stream.extend_from_slice(parts.0);
new_stream.push(comma);
new_stream.extend_from_slice(parts.1);
return Some((TokenStream::new(new_stream), sp));
}
None
}
}
impl FromIterator<TokenTree> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
}
}
impl Eq for TokenStream {}
impl PartialEq<TokenStream> for TokenStream {
fn eq(&self, other: &TokenStream) -> bool {
self.iter().eq(other.iter())
}
}
/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
#[derive(Clone, Debug, Default, Encodable, Decodable)]
pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>);
impl TokenStream {
pub fn new(tts: Vec<TokenTree>) -> TokenStream {
@ -847,6 +774,68 @@ impl TokenStream {
}
}
}
/// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
/// separating the two arguments with a comma for diagnostic suggestions.
pub fn add_comma(&self) -> Option<(TokenStream, Span)> {
// Used to suggest if a user writes `foo!(a b);`
let mut suggestion = None;
let mut iter = self.0.iter().enumerate().peekable();
while let Some((pos, ts)) = iter.next() {
if let Some((_, next)) = iter.peek() {
let sp = match (&ts, &next) {
(_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue,
(
TokenTree::Token(token_left, Spacing::Alone),
TokenTree::Token(token_right, _),
) if (token_left.is_non_reserved_ident() || token_left.is_lit())
&& (token_right.is_non_reserved_ident() || token_right.is_lit()) =>
{
token_left.span
}
(TokenTree::Delimited(sp, ..), _) => sp.entire(),
_ => continue,
};
let sp = sp.shrink_to_hi();
let comma = TokenTree::token_alone(token::Comma, sp);
suggestion = Some((pos, comma, sp));
}
}
if let Some((pos, comma, sp)) = suggestion {
let mut new_stream = Vec::with_capacity(self.0.len() + 1);
let parts = self.0.split_at(pos + 1);
new_stream.extend_from_slice(parts.0);
new_stream.push(comma);
new_stream.extend_from_slice(parts.1);
return Some((TokenStream::new(new_stream), sp));
}
None
}
}
impl PartialEq<TokenStream> for TokenStream {
fn eq(&self, other: &TokenStream) -> bool {
self.iter().eq(other.iter())
}
}
impl Eq for TokenStream {}
impl FromIterator<TokenTree> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
}
}
impl<CTX> HashStable<CTX> for TokenStream
where
CTX: crate::HashStableContext,
{
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
for sub_tt in self.iter() {
sub_tt.hash_stable(hcx, hasher);
}
}
}
#[derive(Clone)]

View file

@ -24,6 +24,6 @@ rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
thin-vec = "0.2.12"
tracing = "0.1"
thin-vec.workspace = true
tracing.workspace = true
# tidy-alphabetical-end

View file

@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
itertools = "0.12"
itertools.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
@ -18,5 +18,5 @@ rustc_macros = { path = "../rustc_macros" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
thin-vec = "0.2.12"
thin-vec.workspace = true
# tidy-alphabetical-end

View file

@ -188,6 +188,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
notable_trait => doc_notable_trait
}
"meant for internal use only" {
attribute => rustdoc_internals
keyword => rustdoc_internals
fake_variadic => rustdoc_internals
search_unbox => rustdoc_internals

View file

@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
itertools = "0.12"
itertools.workspace = true
rustc_ast = { path = "../rustc_ast" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_span = { path = "../rustc_span" }
@ -13,5 +13,5 @@ rustc_span = { path = "../rustc_span" }
[dev-dependencies]
# tidy-alphabetical-start
thin-vec = "0.2.12"
thin-vec.workspace = true
# tidy-alphabetical-end

View file

@ -17,5 +17,6 @@ rustc_macros = { path = "../rustc_macros" }
rustc_parse = { path = "../rustc_parse" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
thin-vec = "0.2.12"
rustc_target = { path = "../rustc_target" }
thin-vec.workspace = true
# tidy-alphabetical-end

View file

@ -195,3 +195,55 @@ attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`
attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
.help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
attr_parsing_as_needed_compatibility =
linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
attr_parsing_bundle_needs_static =
linking modifier `bundle` is only compatible with `static` linking kind
attr_parsing_empty_link_name =
link name must not be empty
.label = empty link name
attr_parsing_import_name_type_raw =
import name type can only be used with link kind `raw-dylib`
attr_parsing_import_name_type_x86 =
import name type is only supported on x86
attr_parsing_incompatible_wasm_link =
`wasm_import_module` is incompatible with other arguments in `#[link]` attributes
attr_parsing_invalid_link_modifier =
invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
attr_parsing_link_arg_unstable =
link kind `link-arg` is unstable
attr_parsing_link_cfg_unstable =
link cfg is unstable
attr_parsing_link_framework_apple =
link kind `framework` is only supported on Apple targets
attr_parsing_link_requires_name =
`#[link]` attribute requires a `name = "string"` argument
.label = missing `name` argument
attr_parsing_multiple_modifiers =
multiple `{$modifier}` modifiers in a single `modifiers` argument
attr_parsing_multiple_renamings =
multiple renamings were specified for library `{$lib_name}`
attr_parsing_raw_dylib_no_nul =
link name must not contain NUL characters if link kind is `raw-dylib`
attr_parsing_raw_dylib_elf_unstable =
link kind `raw-dylib` is unstable on ELF platforms
attr_parsing_raw_dylib_only_windows =
link kind `raw-dylib` is only supported on Windows targets
attr_parsing_whole_archive_needs_static =
linking modifier `whole-archive` is only compatible with `static` linking kind

View file

@ -36,7 +36,7 @@ pub fn parse_cfg_attr<'c, S: Stage>(
parse_cfg_entry(cx, single)
}
fn parse_cfg_entry<S: Stage>(
pub(crate) fn parse_cfg_entry<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
item: &MetaItemOrLitParser<'_>,
) -> Option<CfgEntry> {

View file

@ -1,9 +1,21 @@
use rustc_feature::Features;
use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
use rustc_hir::attrs::Linkage;
use rustc_hir::attrs::*;
use rustc_session::Session;
use rustc_session::parse::feature_err;
use rustc_span::kw;
use rustc_target::spec::BinaryFormat;
use super::prelude::*;
use super::util::parse_single_integer;
use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection};
use crate::attributes::cfg::parse_cfg_entry;
use crate::fluent_generated;
use crate::session_diagnostics::{
AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ImportNameTypeRaw, ImportNameTypeX86,
IncompatibleWasmLink, InvalidLinkModifier, LinkFrameworkApple, LinkOrdinalOutOfRange,
LinkRequiresName, MultipleModifiers, NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows,
WholeArchiveNeedsStatic,
};
pub(crate) struct LinkNameParser;
@ -34,6 +46,409 @@ impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
}
}
pub(crate) struct LinkParser;
impl<S: Stage> CombineAttributeParser<S> for LinkParser {
type Item = LinkEntry;
const PATH: &[Symbol] = &[sym::link];
const CONVERT: ConvertFn<Self::Item> = AttributeKind::Link;
const TEMPLATE: AttributeTemplate = template!(List: &[
r#"name = "...""#,
r#"name = "...", kind = "dylib|static|...""#,
r#"name = "...", wasm_import_module = "...""#,
r#"name = "...", import_name_type = "decorated|noprefix|undecorated""#,
r#"name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated""#,
], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute");
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
fn extend<'c>(
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 sess = cx.sess();
let features = cx.features();
let mut name = None;
let mut kind = None;
let mut modifiers = None;
let mut cfg = None;
let mut wasm_import_module = None;
let mut import_name_type = None;
for item in items.mixed() {
let Some(item) = item.meta_item() else {
cx.unexpected_literal(item.span());
continue;
};
let cont = match item.path().word().map(|ident| ident.name) {
Some(sym::name) => Self::parse_link_name(item, &mut name, cx),
Some(sym::kind) => Self::parse_link_kind(item, &mut kind, cx, sess, features),
Some(sym::modifiers) => Self::parse_link_modifiers(item, &mut modifiers, cx),
Some(sym::cfg) => Self::parse_link_cfg(item, &mut cfg, cx, sess, features),
Some(sym::wasm_import_module) => {
Self::parse_link_wasm_import_module(item, &mut wasm_import_module, cx)
}
Some(sym::import_name_type) => {
Self::parse_link_import_name_type(item, &mut import_name_type, cx)
}
_ => {
cx.expected_specific_argument_strings(
item.span(),
&[
sym::name,
sym::kind,
sym::modifiers,
sym::cfg,
sym::wasm_import_module,
sym::import_name_type,
],
);
true
}
};
if !cont {
return result;
}
}
// Do this outside the above loop so we don't depend on modifiers coming after kinds
let mut verbatim = None;
if let Some((modifiers, span)) = modifiers {
for modifier in modifiers.as_str().split(',') {
let (modifier, value): (Symbol, bool) = match modifier.strip_prefix(&['+', '-']) {
Some(m) => (Symbol::intern(m), modifier.starts_with('+')),
None => {
cx.emit_err(InvalidLinkModifier { span });
continue;
}
};
macro report_unstable_modifier($feature: ident) {
if !features.$feature() {
// FIXME: make this translatable
#[expect(rustc::untranslatable_diagnostic)]
feature_err(
sess,
sym::$feature,
span,
format!("linking modifier `{modifier}` is unstable"),
)
.emit();
}
}
let assign_modifier = |dst: &mut Option<bool>| {
if dst.is_some() {
cx.emit_err(MultipleModifiers { span, modifier });
} else {
*dst = Some(value);
}
};
match (modifier, &mut kind) {
(sym::bundle, Some(NativeLibKind::Static { bundle, .. })) => {
assign_modifier(bundle)
}
(sym::bundle, _) => {
cx.emit_err(BundleNeedsStatic { span });
}
(sym::verbatim, _) => assign_modifier(&mut verbatim),
(
sym::whole_dash_archive,
Some(NativeLibKind::Static { whole_archive, .. }),
) => assign_modifier(whole_archive),
(sym::whole_dash_archive, _) => {
cx.emit_err(WholeArchiveNeedsStatic { span });
}
(sym::as_dash_needed, Some(NativeLibKind::Dylib { as_needed }))
| (sym::as_dash_needed, Some(NativeLibKind::Framework { as_needed })) => {
report_unstable_modifier!(native_link_modifiers_as_needed);
assign_modifier(as_needed)
}
(sym::as_dash_needed, _) => {
cx.emit_err(AsNeededCompatibility { span });
}
_ => {
cx.expected_specific_argument_strings(
span,
&[
sym::bundle,
sym::verbatim,
sym::whole_dash_archive,
sym::as_dash_needed,
],
);
}
}
}
}
if let Some((_, span)) = wasm_import_module {
if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
cx.emit_err(IncompatibleWasmLink { span });
}
}
if wasm_import_module.is_some() {
(name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule));
}
let Some((name, name_span)) = name else {
cx.emit_err(LinkRequiresName { span: cx.attr_span });
return result;
};
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
if let Some((_, span)) = import_name_type {
if kind != Some(NativeLibKind::RawDylib) {
cx.emit_err(ImportNameTypeRaw { span });
}
}
if let Some(NativeLibKind::RawDylib) = kind
&& name.as_str().contains('\0')
{
cx.emit_err(RawDylibNoNul { span: name_span });
}
result = Some(LinkEntry {
span: cx.attr_span,
kind: kind.unwrap_or(NativeLibKind::Unspecified),
name,
cfg,
verbatim,
import_name_type,
});
result
}
}
impl LinkParser {
fn parse_link_name<S: Stage>(
item: &MetaItemParser<'_>,
name: &mut Option<(Symbol, Span)>,
cx: &mut AcceptContext<'_, '_, S>,
) -> bool {
if name.is_some() {
cx.duplicate_key(item.span(), sym::name);
return true;
}
let Some(nv) = item.args().name_value() else {
cx.expected_name_value(item.span(), Some(sym::name));
return false;
};
let Some(link_name) = nv.value_as_str() else {
cx.expected_name_value(item.span(), Some(sym::name));
return false;
};
if link_name.is_empty() {
cx.emit_err(EmptyLinkName { span: nv.value_span });
}
*name = Some((link_name, nv.value_span));
true
}
fn parse_link_kind<S: Stage>(
item: &MetaItemParser<'_>,
kind: &mut Option<NativeLibKind>,
cx: &mut AcceptContext<'_, '_, S>,
sess: &Session,
features: &Features,
) -> bool {
if kind.is_some() {
cx.duplicate_key(item.span(), sym::kind);
return true;
}
let Some(nv) = item.args().name_value() else {
cx.expected_name_value(item.span(), Some(sym::kind));
return true;
};
let Some(link_kind) = nv.value_as_str() else {
cx.expected_name_value(item.span(), Some(sym::kind));
return true;
};
let link_kind = match link_kind {
kw::Static => NativeLibKind::Static { bundle: None, whole_archive: None },
sym::dylib => NativeLibKind::Dylib { as_needed: None },
sym::framework => {
if !sess.target.is_like_darwin {
cx.emit_err(LinkFrameworkApple { span: nv.value_span });
}
NativeLibKind::Framework { as_needed: None }
}
sym::raw_dash_dylib => {
if sess.target.is_like_windows {
// raw-dylib is stable and working on Windows
} else if sess.target.binary_format == BinaryFormat::Elf && features.raw_dylib_elf()
{
// raw-dylib is unstable on ELF, but the user opted in
} else if sess.target.binary_format == BinaryFormat::Elf && sess.is_nightly_build()
{
feature_err(
sess,
sym::raw_dylib_elf,
nv.value_span,
fluent_generated::attr_parsing_raw_dylib_elf_unstable,
)
.emit();
} else {
cx.emit_err(RawDylibOnlyWindows { span: nv.value_span });
}
NativeLibKind::RawDylib
}
sym::link_dash_arg => {
if !features.link_arg_attribute() {
feature_err(
sess,
sym::link_arg_attribute,
nv.value_span,
fluent_generated::attr_parsing_link_arg_unstable,
)
.emit();
}
NativeLibKind::LinkArg
}
_kind => {
cx.expected_specific_argument_strings(
nv.value_span,
&[
kw::Static,
sym::dylib,
sym::framework,
sym::raw_dash_dylib,
sym::link_dash_arg,
],
);
return true;
}
};
*kind = Some(link_kind);
true
}
fn parse_link_modifiers<S: Stage>(
item: &MetaItemParser<'_>,
modifiers: &mut Option<(Symbol, Span)>,
cx: &mut AcceptContext<'_, '_, S>,
) -> bool {
if modifiers.is_some() {
cx.duplicate_key(item.span(), sym::modifiers);
return true;
}
let Some(nv) = item.args().name_value() else {
cx.expected_name_value(item.span(), Some(sym::modifiers));
return true;
};
let Some(link_modifiers) = nv.value_as_str() else {
cx.expected_name_value(item.span(), Some(sym::modifiers));
return true;
};
*modifiers = Some((link_modifiers, nv.value_span));
true
}
fn parse_link_cfg<S: Stage>(
item: &MetaItemParser<'_>,
cfg: &mut Option<CfgEntry>,
cx: &mut AcceptContext<'_, '_, S>,
sess: &Session,
features: &Features,
) -> bool {
if cfg.is_some() {
cx.duplicate_key(item.span(), sym::cfg);
return true;
}
let Some(link_cfg) = item.args().list() else {
cx.expected_list(item.span());
return true;
};
let Some(link_cfg) = link_cfg.single() else {
cx.expected_single_argument(item.span());
return true;
};
if !features.link_cfg() {
feature_err(
sess,
sym::link_cfg,
item.span(),
fluent_generated::attr_parsing_link_cfg_unstable,
)
.emit();
}
*cfg = parse_cfg_entry(cx, link_cfg);
true
}
fn parse_link_wasm_import_module<S: Stage>(
item: &MetaItemParser<'_>,
wasm_import_module: &mut Option<(Symbol, Span)>,
cx: &mut AcceptContext<'_, '_, S>,
) -> bool {
if wasm_import_module.is_some() {
cx.duplicate_key(item.span(), sym::wasm_import_module);
return true;
}
let Some(nv) = item.args().name_value() else {
cx.expected_name_value(item.span(), Some(sym::wasm_import_module));
return true;
};
let Some(link_wasm_import_module) = nv.value_as_str() else {
cx.expected_name_value(item.span(), Some(sym::wasm_import_module));
return true;
};
*wasm_import_module = Some((link_wasm_import_module, item.span()));
true
}
fn parse_link_import_name_type<S: Stage>(
item: &MetaItemParser<'_>,
import_name_type: &mut Option<(PeImportNameType, Span)>,
cx: &mut AcceptContext<'_, '_, S>,
) -> bool {
if import_name_type.is_some() {
cx.duplicate_key(item.span(), sym::import_name_type);
return true;
}
let Some(nv) = item.args().name_value() else {
cx.expected_name_value(item.span(), Some(sym::import_name_type));
return true;
};
let Some(link_import_name_type) = nv.value_as_str() else {
cx.expected_name_value(item.span(), Some(sym::import_name_type));
return true;
};
if cx.sess().target.arch != "x86" {
cx.emit_err(ImportNameTypeX86 { span: item.span() });
return true;
}
let link_import_name_type = match link_import_name_type {
sym::decorated => PeImportNameType::Decorated,
sym::noprefix => PeImportNameType::NoPrefix,
sym::undecorated => PeImportNameType::Undecorated,
_ => {
cx.expected_specific_argument_strings(
item.span(),
&[sym::decorated, sym::noprefix, sym::undecorated],
);
return true;
}
};
*import_name_type = Some((link_import_name_type, item.span()));
true
}
}
pub(crate) struct LinkSectionParser;
impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {

View file

@ -1,20 +1,30 @@
// parsing
// templates
#[doc(hidden)]
pub(super) use rustc_feature::{AttributeTemplate, template};
// data structures
#[doc(hidden)]
pub(super) use rustc_hir::attrs::AttributeKind;
#[doc(hidden)]
pub(super) use rustc_hir::lints::AttributeLintKind;
#[doc(hidden)]
pub(super) use rustc_hir::{MethodKind, Target};
#[doc(hidden)]
pub(super) use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
#[doc(hidden)]
pub(super) use thin_vec::ThinVec;
#[doc(hidden)]
pub(super) use crate::attributes::{
AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn,
NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
// contexts
#[doc(hidden)]
pub(super) use crate::context::{AcceptContext, FinalizeContext, Stage};
#[doc(hidden)]
pub(super) use crate::parser::*;
// target checking
#[doc(hidden)]
pub(super) use crate::target_checking::Policy::{Allow, Error, Warn};
#[doc(hidden)]
pub(super) use crate::target_checking::{ALL_TARGETS, AllowedTargets};

View file

@ -30,7 +30,7 @@ use crate::attributes::dummy::DummyParser;
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
use crate::attributes::link_attrs::{
ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
LinkSectionParser, LinkageParser, StdInternalSymbolParser,
LinkParser, LinkSectionParser, LinkageParser, StdInternalSymbolParser,
};
use crate::attributes::lint_helpers::{
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
@ -162,6 +162,7 @@ attribute_parsers!(
Combine<AllowConstFnUnstableParser>,
Combine<AllowInternalUnstableParser>,
Combine<ForceTargetFeatureParser>,
Combine<LinkParser>,
Combine<ReprParser>,
Combine<TargetFeatureParser>,
Combine<UnstableFeatureBoundParser>,

View file

@ -273,14 +273,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
(accept.accept_fn)(&mut cx, args);
if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
Self::check_type(accept.attribute_type, target, &mut cx);
self.check_target(
path.get_attribute_path(),
attr.span,
&accept.allowed_targets,
target,
target_id,
&mut emit_lint,
);
Self::check_target(&accept.allowed_targets, target, &mut cx);
}
}
} else {

View file

@ -79,6 +79,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![doc(rust_logo)]
#![feature(decl_macro)]
#![feature(rustdoc_internals)]
#![recursion_limit = "256"]
// tidy-alphabetical-end

View file

@ -10,11 +10,11 @@ use rustc_ast::token::{self, Delimiter, MetaVarKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path};
use rustc_ast_pretty::pprust;
use rustc_errors::PResult;
use rustc_errors::{Diag, PResult};
use rustc_hir::{self as hir, AttrPath};
use rustc_parse::exp;
use rustc_parse::parser::{Parser, PathStyle, token_descr};
use rustc_session::errors::report_lit_error;
use rustc_session::errors::{create_lit_error, report_lit_error};
use rustc_session::parse::ParseSess;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym};
use thin_vec::ThinVec;
@ -379,22 +379,23 @@ struct MetaItemListParserContext<'a, 'sess> {
impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
fn parse_unsuffixed_meta_item_lit(&mut self) -> PResult<'sess, MetaItemLit> {
let uninterpolated_span = self.parser.token_uninterpolated_span();
let Some(token_lit) = self.parser.eat_token_lit() else {
return self.parser.handle_missing_lit(Parser::mk_meta_item_lit_char);
};
let Some(token_lit) = self.parser.eat_token_lit() else { return Err(self.expected_lit()) };
self.unsuffixed_meta_item_from_lit(token_lit)
}
fn unsuffixed_meta_item_from_lit(
&mut self,
token_lit: token::Lit,
) -> PResult<'sess, MetaItemLit> {
let lit = match MetaItemLit::from_token_lit(token_lit, self.parser.prev_token.span) {
Ok(lit) => lit,
Err(err) => {
let guar =
report_lit_error(&self.parser.psess, err, token_lit, uninterpolated_span);
// Pack possible quotes and prefixes from the original literal into
// the error literal's symbol so they can be pretty-printed faithfully.
let suffixless_lit = token::Lit::new(token_lit.kind, token_lit.symbol, None);
let symbol = Symbol::intern(&suffixless_lit.to_string());
let token_lit = token::Lit::new(token::Err(guar), symbol, token_lit.suffix);
MetaItemLit::from_token_lit(token_lit, uninterpolated_span).unwrap()
return Err(create_lit_error(
&self.parser.psess,
err,
token_lit,
self.parser.prev_token_uninterpolated_span(),
));
}
};
@ -448,16 +449,28 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
}
fn parse_meta_item_inner(&mut self) -> PResult<'sess, MetaItemOrLitParser<'static>> {
match self.parse_unsuffixed_meta_item_lit() {
Ok(lit) => return Ok(MetaItemOrLitParser::Lit(lit)),
Err(err) => err.cancel(), // we provide a better error below
}
match self.parse_attr_item() {
Ok(mi) => return Ok(MetaItemOrLitParser::MetaItemParser(mi)),
Err(err) => err.cancel(), // we provide a better error below
if let Some(token_lit) = self.parser.eat_token_lit() {
// If a literal token is parsed, we commit to parsing a MetaItemLit for better errors
Ok(MetaItemOrLitParser::Lit(self.unsuffixed_meta_item_from_lit(token_lit)?))
} else {
let prev_pros = self.parser.approx_token_stream_pos();
match self.parse_attr_item() {
Ok(item) => Ok(MetaItemOrLitParser::MetaItemParser(item)),
Err(err) => {
// If `parse_attr_item` made any progress, it likely has a more precise error we should prefer
// If it didn't make progress we use the `expected_lit` from below
if self.parser.approx_token_stream_pos() != prev_pros {
Err(err)
} else {
err.cancel();
Err(self.expected_lit())
}
}
}
}
}
fn expected_lit(&mut self) -> Diag<'sess> {
let mut err = InvalidMetaItem {
span: self.parser.token.span,
descr: token_descr(&self.parser.token),
@ -492,7 +505,7 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
self.parser.bump();
}
Err(self.parser.dcx().create_err(err))
self.parser.dcx().create_err(err)
}
fn parse(

View file

@ -836,3 +836,97 @@ pub(crate) struct InvalidAttrStyle {
pub target_span: Option<Span>,
pub target: Target,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_empty_link_name, code = E0454)]
pub(crate) struct EmptyLinkName {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_link_framework_apple, code = E0455)]
pub(crate) struct LinkFrameworkApple {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_incompatible_wasm_link)]
pub(crate) struct IncompatibleWasmLink {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_link_requires_name, code = E0459)]
pub(crate) struct LinkRequiresName {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_raw_dylib_no_nul)]
pub(crate) struct RawDylibNoNul {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_raw_dylib_only_windows, code = E0455)]
pub(crate) struct RawDylibOnlyWindows {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_invalid_link_modifier)]
pub(crate) struct InvalidLinkModifier {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_multiple_modifiers)]
pub(crate) struct MultipleModifiers {
#[primary_span]
pub span: Span,
pub modifier: Symbol,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_import_name_type_x86)]
pub(crate) struct ImportNameTypeX86 {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_bundle_needs_static)]
pub(crate) struct BundleNeedsStatic {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_whole_archive_needs_static)]
pub(crate) struct WholeArchiveNeedsStatic {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_as_needed_compatibility)]
pub(crate) struct AsNeededCompatibility {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_import_name_type_raw)]
pub(crate) struct ImportNameTypeRaw {
#[primary_span]
pub span: Span,
}

View file

@ -3,9 +3,8 @@ use std::borrow::Cow;
use rustc_ast::AttrStyle;
use rustc_errors::DiagArgValue;
use rustc_feature::{AttributeType, Features};
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
use rustc_hir::{AttrPath, MethodKind, Target};
use rustc_span::Span;
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{MethodKind, Target};
use crate::AttributeParser;
use crate::context::{AcceptContext, Stage};
@ -71,38 +70,34 @@ pub(crate) enum Policy {
impl<'sess, S: Stage> AttributeParser<'sess, S> {
pub(crate) fn check_target(
&self,
attr_name: AttrPath,
attr_span: Span,
allowed_targets: &AllowedTargets,
target: Target,
target_id: S::Id,
mut emit_lint: impl FnMut(AttributeLint<S::Id>),
cx: &mut AcceptContext<'_, 'sess, S>,
) {
match allowed_targets.is_allowed(target) {
AllowedResult::Allowed => {}
AllowedResult::Warn => {
let allowed_targets = allowed_targets.allowed_targets();
let (applied, only) =
allowed_targets_applied(allowed_targets, target, self.features);
emit_lint(AttributeLint {
id: target_id,
span: attr_span,
kind: AttributeLintKind::InvalidTarget {
name: attr_name,
let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features);
let name = cx.attr_path.clone();
let attr_span = cx.attr_span;
cx.emit_lint(
AttributeLintKind::InvalidTarget {
name,
target,
only: if only { "only " } else { "" },
applied,
},
});
attr_span,
);
}
AllowedResult::Error => {
let allowed_targets = allowed_targets.allowed_targets();
let (applied, only) =
allowed_targets_applied(allowed_targets, target, self.features);
self.dcx().emit_err(InvalidTarget {
span: attr_span,
name: attr_name,
let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features);
let name = cx.attr_path.clone();
cx.dcx().emit_err(InvalidTarget {
span: cx.attr_span.clone(),
name,
target: target.plural_name(),
only: if only { "only " } else { "" },
applied: DiagArgValue::StrListSepByAnd(

View file

@ -5,9 +5,8 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
icu_list = "1.2"
icu_locid = "1.2"
icu_locid_transform = "1.3.2"
icu_provider = { version = "1.2", features = ["sync"] }
zerovec = "0.10.0"
icu_list = { version = "2.0", default-features = false }
icu_locale = { version = "2.0", default-features = false, features = ["compiled_data"] }
icu_provider = { version = "2.0", features = ["baked", "sync"] }
zerovec = "0.11.0"
# tidy-alphabetical-end

View file

@ -1,2 +0,0 @@
// @generated
impl_any_provider!(BakedDataProvider);

File diff suppressed because one or more lines are too long

View file

@ -1,46 +0,0 @@
// @generated
/// Marks a type as a data provider. You can then use macros like
/// `impl_core_helloworld_v1` to add implementations.
///
/// ```ignore
/// struct MyProvider;
/// const _: () = {
/// include!("path/to/generated/macros.rs");
/// make_provider!(MyProvider);
/// impl_core_helloworld_v1!(MyProvider);
/// }
/// ```
#[doc(hidden)]
#[macro_export]
macro_rules! __make_provider {
($ name : ty) => {
#[clippy::msrv = "1.66"]
impl $name {
#[doc(hidden)]
#[allow(dead_code)]
pub const MUST_USE_MAKE_PROVIDER_MACRO: () = ();
}
};
}
#[doc(inline)]
pub use __make_provider as make_provider;
#[macro_use]
#[path = "macros/fallback_likelysubtags_v1.data.rs"]
mod fallback_likelysubtags_v1;
#[doc(inline)]
pub use __impl_fallback_likelysubtags_v1 as impl_fallback_likelysubtags_v1;
#[macro_use]
#[path = "macros/fallback_parents_v1.data.rs"]
mod fallback_parents_v1;
#[doc(inline)]
pub use __impl_fallback_parents_v1 as impl_fallback_parents_v1;
#[macro_use]
#[path = "macros/fallback_supplement_co_v1.data.rs"]
mod fallback_supplement_co_v1;
#[doc(inline)]
pub use __impl_fallback_supplement_co_v1 as impl_fallback_supplement_co_v1;
#[macro_use]
#[path = "macros/list_and_v1.data.rs"]
mod list_and_v1;
#[doc(inline)]
pub use __impl_list_and_v1 as impl_list_and_v1;

View file

@ -1,40 +0,0 @@
// @generated
/// Implement `DataProvider<LocaleFallbackLikelySubtagsV1Marker>` on the given struct using the data
/// hardcoded in this file. This allows the struct to be used with
/// `icu`'s `_unstable` constructors.
#[doc(hidden)]
#[macro_export]
macro_rules! __impl_fallback_likelysubtags_v1 {
($ provider : ty) => {
#[clippy::msrv = "1.66"]
const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
#[clippy::msrv = "1.66"]
impl $provider {
#[doc(hidden)]
pub const SINGLETON_FALLBACK_LIKELYSUBTAGS_V1: &'static <icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1 {
l2s: unsafe {
#[allow(unused_unsafe)]
zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"am\0ar\0as\0be\0bg\0bgcbhobn\0brxchrcv\0doiel\0fa\0gu\0he\0hi\0hy\0ja\0ka\0kk\0km\0kn\0ko\0kokks\0ky\0lo\0maimk\0ml\0mn\0mnimr\0my\0ne\0or\0pa\0ps\0rajru\0sa\0satsd\0si\0sr\0ta\0te\0tg\0th\0ti\0tt\0uk\0ur\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"EthiArabBengCyrlCyrlDevaDevaBengDevaCherCyrlDevaGrekArabGujrHebrDevaArmnJpanGeorCyrlKhmrKndaKoreDevaArabCyrlLaooDevaCyrlMlymCyrlBengDevaMymrDevaOryaGuruArabDevaCyrlDevaOlckArabSinhCyrlTamlTeluCyrlThaiEthiCyrlCyrlArabHantHans") })
},
lr2s: unsafe {
#[allow(unused_unsafe)]
zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0ha\0kk\0ky\0mn\0ms\0pa\0sd\0sr\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x03\0\0\0\x05\0\0\0\t\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x0F\0\0\0\x13\0\0\0\x14\0\0\0\x16\0\0\0\x17\0\0\0&\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IQ\0IR\0RU\0CM\0SD\0AF\0CN\0IR\0MN\0CN\0TR\0CN\0CC\0PK\0IN\0ME\0RO\0RU\0TR\0PK\0AF\0CN\0CN\0AU\0BN\0GB\0GF\0HK\0ID\0MO\0PA\0PF\0PH\0SR\0TH\0TW\0US\0VN\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabArabCyrlArabArabArabArabArabArabArabLatnMongArabArabDevaLatnLatnLatnLatnArabArabCyrlHansHantHantHantHantHantHantHantHantHantHantHantHantHantHantHant") })
},
l2r: unsafe {
#[allow(unused_unsafe)]
zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"af\0am\0ar\0as\0astaz\0be\0bg\0bgcbhobn\0br\0brxbs\0ca\0cebchrcs\0cv\0cy\0da\0de\0doidsbel\0en\0es\0et\0eu\0fa\0ff\0fi\0filfo\0fr\0ga\0gd\0gl\0gu\0ha\0he\0hi\0hr\0hsbhu\0hy\0ia\0id\0ig\0is\0it\0ja\0jv\0ka\0keakgpkk\0km\0kn\0ko\0kokks\0ky\0lo\0lt\0lv\0maimi\0mk\0ml\0mn\0mnimr\0ms\0my\0ne\0nl\0nn\0no\0or\0pa\0pcmpl\0ps\0pt\0qu\0rajrm\0ro\0ru\0sa\0satsc\0sd\0si\0sk\0sl\0so\0sq\0sr\0su\0sv\0sw\0ta\0te\0tg\0th\0ti\0tk\0to\0tr\0tt\0uk\0ur\0uz\0vi\0wo\0xh\0yo\0yrlyuezh\0zu\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ZA\0ET\0EG\0IN\0ES\0AZ\0BY\0BG\0IN\0IN\0BD\0FR\0IN\0BA\0ES\0PH\0US\0CZ\0RU\0GB\0DK\0DE\0IN\0DE\0GR\0US\0ES\0EE\0ES\0IR\0SN\0FI\0PH\0FO\0FR\0IE\0GB\0ES\0IN\0NG\0IL\0IN\0HR\0DE\0HU\0AM\x00001ID\0NG\0IS\0IT\0JP\0ID\0GE\0CV\0BR\0KZ\0KH\0IN\0KR\0IN\0IN\0KG\0LA\0LT\0LV\0IN\0NZ\0MK\0IN\0MN\0IN\0IN\0MY\0MM\0NP\0NL\0NO\0NO\0IN\0IN\0NG\0PL\0AF\0BR\0PE\0IN\0CH\0RO\0RU\0IN\0IN\0IT\0PK\0LK\0SK\0SI\0SO\0AL\0RS\0ID\0SE\0TZ\0IN\0IN\0TJ\0TH\0ET\0TM\0TO\0TR\0RU\0UA\0PK\0UZ\0VN\0SN\0ZA\0NG\0BR\0HK\0CN\0ZA\0") })
},
ls2r: unsafe {
#[allow(unused_unsafe)]
zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0en\0ff\0kk\0ky\0mn\0pa\0sd\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x01\0\0\0\x02\0\0\0\x03\0\0\0\x04\0\0\0\x06\0\0\0\x07\0\0\0\x08\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x11\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabShawAdlmArabArabLatnMongArabDevaKhojSindArabArabHansBopoHanbHant") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IR\0GB\0GN\0CN\0CN\0TR\0CN\0PK\0IN\0IN\0IN\0PK\0AF\0CN\0TW\0TW\0TW\0") })
},
};
}
#[clippy::msrv = "1.66"]
impl icu_provider::DataProvider<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker> for $provider {
fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker>, icu_provider::DataError> {
if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_LIKELYSUBTAGS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) }
}
}
};
}

View file

@ -1,28 +0,0 @@
// @generated
/// Implement `DataProvider<LocaleFallbackParentsV1Marker>` on the given struct using the data
/// hardcoded in this file. This allows the struct to be used with
/// `icu`'s `_unstable` constructors.
#[doc(hidden)]
#[macro_export]
macro_rules! __impl_fallback_parents_v1 {
($ provider : ty) => {
#[clippy::msrv = "1.66"]
const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
#[clippy::msrv = "1.66"]
impl $provider {
#[doc(hidden)]
pub const SINGLETON_FALLBACK_PARENTS_V1: &'static <icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackParentsV1 {
parents: unsafe {
#[allow(unused_unsafe)]
zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x84\0\0\0\0\0\x06\0\x0B\0\x10\0\x15\0\x1A\0\x1F\0$\0)\0.\x003\08\0=\0B\0G\0L\0Q\0V\0[\0`\0e\0j\0o\0t\0y\0~\0\x83\0\x88\0\x8D\0\x92\0\x97\0\x9C\0\xA1\0\xA6\0\xAB\0\xB0\0\xB5\0\xBA\0\xBF\0\xC4\0\xC9\0\xCE\0\xD3\0\xD8\0\xDD\0\xE2\0\xE7\0\xEC\0\xF1\0\xF6\0\xFB\0\0\x01\x05\x01\n\x01\x0F\x01\x14\x01\x19\x01\x1E\x01#\x01(\x01-\x012\x017\x01<\x01A\x01F\x01K\x01P\x01U\x01Z\x01_\x01d\x01i\x01n\x01s\x01x\x01}\x01\x82\x01\x87\x01\x8C\x01\x91\x01\x96\x01\x9B\x01\xA0\x01\xA5\x01\xAA\x01\xAF\x01\xB4\x01\xB9\x01\xBE\x01\xC3\x01\xC8\x01\xCD\x01\xD2\x01\xD7\x01\xDC\x01\xE1\x01\xE6\x01\xEB\x01\xF0\x01\xF5\x01\xFA\x01\xFF\x01\x04\x02\t\x02\x0E\x02\x13\x02\x18\x02\x1D\x02\"\x02'\x02,\x021\x026\x02;\x02@\x02G\x02I\x02K\x02M\x02R\x02W\x02\\\x02a\x02f\x02k\x02p\x02u\x02z\x02\x7F\x02\x84\x02\x89\x02en-150en-AGen-AIen-ATen-AUen-BBen-BEen-BMen-BSen-BWen-BZen-CCen-CHen-CKen-CMen-CXen-CYen-DEen-DGen-DKen-DMen-ERen-FIen-FJen-FKen-FMen-GBen-GDen-GGen-GHen-GIen-GMen-GYen-HKen-IEen-ILen-IMen-INen-IOen-JEen-JMen-KEen-KIen-KNen-KYen-LCen-LRen-LSen-MGen-MOen-MSen-MTen-MUen-MVen-MWen-MYen-NAen-NFen-NGen-NLen-NRen-NUen-NZen-PGen-PKen-PNen-PWen-RWen-SBen-SCen-SDen-SEen-SGen-SHen-SIen-SLen-SSen-SXen-SZen-TCen-TKen-TOen-TTen-TVen-TZen-UGen-VCen-VGen-VUen-WSen-ZAen-ZMen-ZWes-ARes-BOes-BRes-BZes-CLes-COes-CRes-CUes-DOes-ECes-GTes-HNes-MXes-NIes-PAes-PEes-PRes-PYes-SVes-USes-UYes-VEhi-Latnhtnbnnno-NOpt-AOpt-CHpt-CVpt-FRpt-GQpt-GWpt-LUpt-MOpt-MZpt-STpt-TLzh-Hant-MO") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419en\0\0\0\0\0\0\x01IN\0fr\0\0\0\0\0\0\x01HT\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0zh\0\x01Hant\x01HK\0") })
},
};
}
#[clippy::msrv = "1.66"]
impl icu_provider::DataProvider<icu_locid_transform::provider::LocaleFallbackParentsV1Marker> for $provider {
fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::LocaleFallbackParentsV1Marker>, icu_provider::DataError> {
if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_PARENTS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) }
}
}
};
}

View file

@ -1,32 +0,0 @@
// @generated
/// Implement `DataProvider<CollationFallbackSupplementV1Marker>` on the given struct using the data
/// hardcoded in this file. This allows the struct to be used with
/// `icu`'s `_unstable` constructors.
#[doc(hidden)]
#[macro_export]
macro_rules! __impl_fallback_supplement_co_v1 {
($ provider : ty) => {
#[clippy::msrv = "1.66"]
const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
#[clippy::msrv = "1.66"]
impl $provider {
#[doc(hidden)]
pub const SINGLETON_FALLBACK_SUPPLEMENT_CO_V1: &'static <icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackSupplementV1 {
parents: unsafe {
#[allow(unused_unsafe)]
zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x01\0\0\0\0\0yue") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"zh\0\x01Hant\0\0\0\0") })
},
unicode_extension_defaults: unsafe {
#[allow(unused_unsafe)]
zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"co") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x02\0\0\0") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x02\0zhzh-Hant") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x06\0pinyinstroke") })
},
};
}
#[clippy::msrv = "1.66"]
impl icu_provider::DataProvider<icu_locid_transform::provider::CollationFallbackSupplementV1Marker> for $provider {
fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::CollationFallbackSupplementV1Marker>, icu_provider::DataError> {
if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_SUPPLEMENT_CO_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) }
}
}
};
}

File diff suppressed because one or more lines are too long

View file

@ -1,31 +1,40 @@
// @generated
include!("macros.rs");
include!("list_and_v1.rs.data");
/// Marks a type as a data provider. You can then use macros like
/// `impl_core_helloworld_v1` to add implementations.
///
/// ```ignore
/// struct MyProvider;
/// const _: () = {
/// include!("path/to/generated/macros.rs");
/// make_provider!(MyProvider);
/// impl_core_helloworld_v1!(MyProvider);
/// }
/// ```
#[doc(hidden)]
#[macro_export]
macro_rules! __make_provider {
($ name : ty) => {
#[clippy::msrv = "1.82"]
impl $name {
#[allow(dead_code)]
pub(crate) const MUST_USE_MAKE_PROVIDER_MACRO: () = ();
}
icu_provider::marker::impl_data_provider_never_marker!($name);
};
}
#[doc(inline)]
pub use __make_provider as make_provider;
/// This macro requires the following crates:
/// * `icu_list`
/// * `icu_locale/compiled_data`
/// * `icu_provider`
/// * `icu_provider/baked`
/// * `zerovec`
#[allow(unused_macros)]
macro_rules! impl_data_provider {
($ provider : ty) => {
make_provider!($provider);
impl_fallback_likelysubtags_v1!($provider);
impl_fallback_parents_v1!($provider);
impl_fallback_supplement_co_v1!($provider);
impl_list_and_v1!($provider);
};
}
#[allow(unused_macros)]
macro_rules! impl_any_provider {
($ provider : ty) => {
#[clippy::msrv = "1.66"]
impl icu_provider::AnyProvider for $provider {
fn load_any(&self, key: icu_provider::DataKey, req: icu_provider::DataRequest) -> Result<icu_provider::AnyResponse, icu_provider::DataError> {
match key.hashed() {
h if h == <icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
h if h == <icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::LocaleFallbackParentsV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
h if h == <icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::CollationFallbackSupplementV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
h if h == <icu_list::provider::AndListV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_list::provider::AndListV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
_ => Err(icu_provider::DataErrorKind::MissingDataKey.with_req(key, req)),
}
}
}
};
}
#[clippy::msrv = "1.66"]
pub struct BakedDataProvider;
impl_data_provider!(BakedDataProvider);

View file

@ -14,10 +14,9 @@
//! To regenerate the data, run this command:
//!
//! ```text
//! icu4x-datagen -W --pretty --fingerprint --use-separate-crates \
//! --format mod -l en es fr it ja pt ru tr zh zh-Hans zh-Hant \
//! -k list/and@1 fallback/likelysubtags@1 fallback/parents@1 fallback/supplement/co@1 \
//! --cldr-tag latest --icuexport-tag latest -o src/data
//! icu4x-datagen -W --pretty --use-separate-crates \
//! --format baked --locales @en @es @fr @it @ja @pt @ru @tr @zh @zh-Hans @zh-Hant \
//! -m ListAndV1 -o src/data
//! ```
// tidy-alphabetical-start
@ -29,26 +28,26 @@
// #![warn(unreachable_pub)] // don't use because this crate is mostly generated code
// tidy-alphabetical-end
mod data {
include!("data/mod.rs");
include!("data/any.rs");
}
pub struct BakedDataProvider;
pub use data::BakedDataProvider;
include!("data/mod.rs");
const _: () = {
impl_data_provider!(BakedDataProvider);
};
pub const fn baked_data_provider() -> BakedDataProvider {
data::BakedDataProvider
BakedDataProvider
}
pub mod supported_locales {
pub const EN: icu_locid::Locale = icu_locid::locale!("en");
pub const ES: icu_locid::Locale = icu_locid::locale!("es");
pub const FR: icu_locid::Locale = icu_locid::locale!("fr");
pub const IT: icu_locid::Locale = icu_locid::locale!("it");
pub const JA: icu_locid::Locale = icu_locid::locale!("ja");
pub const PT: icu_locid::Locale = icu_locid::locale!("pt");
pub const RU: icu_locid::Locale = icu_locid::locale!("ru");
pub const TR: icu_locid::Locale = icu_locid::locale!("tr");
pub const ZH_HANS: icu_locid::Locale = icu_locid::locale!("zh-Hans");
pub const ZH_HANT: icu_locid::Locale = icu_locid::locale!("zh-Hant");
pub const EN: icu_locale::Locale = icu_locale::locale!("en");
pub const ES: icu_locale::Locale = icu_locale::locale!("es");
pub const FR: icu_locale::Locale = icu_locale::locale!("fr");
pub const IT: icu_locale::Locale = icu_locale::locale!("it");
pub const JA: icu_locale::Locale = icu_locale::locale!("ja");
pub const PT: icu_locale::Locale = icu_locale::locale!("pt");
pub const RU: icu_locale::Locale = icu_locale::locale!("ru");
pub const TR: icu_locale::Locale = icu_locale::locale!("tr");
pub const ZH_HANS: icu_locale::Locale = icu_locale::locale!("zh-Hans");
pub const ZH_HANT: icu_locale::Locale = icu_locale::locale!("zh-Hant");
}

View file

@ -5,9 +5,9 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
either = "1.5.0"
itertools = "0.12"
polonius-engine = "0.13.0"
either.workspace = true
itertools.workspace = true
polonius-engine.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
@ -25,5 +25,5 @@ rustc_span = { path = "../rustc_span" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_traits = { path = "../rustc_traits" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
tracing.workspace = true
# tidy-alphabetical-end

View file

@ -565,7 +565,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
let (blame_constraint, path) = self.regioncx.best_blame_constraint(
borrow_region,
NllRegionVariableOrigin::FreeRegion,
|r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
outlived_region,
);
let BlameConstraint { category, from_closure, cause, .. } = blame_constraint;

View file

@ -243,10 +243,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindOpaqueRegion<'_, 'tcx> {
let opaque_region_vid = self.regioncx.to_region_vid(opaque_region);
// Find a path between the borrow region and our opaque capture.
if let Some((path, _)) =
self.regioncx.find_constraint_path_between_regions(self.borrow_region, |r| {
r == opaque_region_vid
})
if let Some(path) = self
.regioncx
.constraint_path_between_regions(self.borrow_region, opaque_region_vid)
{
for constraint in path {
// If we find a call in this path, then check if it defines the opaque.

View file

@ -61,7 +61,7 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
| ConstraintCategory::Boring
| ConstraintCategory::BoringNoLocation
| ConstraintCategory::Internal
| ConstraintCategory::IllegalUniverse => "",
| ConstraintCategory::OutlivesUnnameablePlaceholder(..) => "",
}
}
}
@ -369,11 +369,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let error_vid = self.regioncx.region_from_element(longer_fr, &error_element);
// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
let (_, cause) = self.regioncx.find_outlives_blame_span(
longer_fr,
NllRegionVariableOrigin::Placeholder(placeholder),
error_vid,
);
let cause = self
.regioncx
.best_blame_constraint(
longer_fr,
NllRegionVariableOrigin::Placeholder(placeholder),
error_vid,
)
.0
.cause;
let universe = placeholder.universe;
let universe_info = self.regioncx.universe_info(universe);
@ -429,9 +433,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
) {
debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
let (blame_constraint, path) = self.regioncx.best_blame_constraint(fr, fr_origin, |r| {
self.regioncx.provides_universal_region(r, fr, outlived_fr)
});
let (blame_constraint, path) =
self.regioncx.best_blame_constraint(fr, fr_origin, outlived_fr);
let BlameConstraint { category, cause, variance_info, .. } = blame_constraint;
debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);

View file

@ -1,7 +1,6 @@
//! Logic for lowering higher-kinded outlives constraints
//! (with placeholders and universes) and turn them into regular
//! outlives constraints.
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::graph::scc;
@ -10,7 +9,7 @@ use rustc_index::IndexVec;
use rustc_infer::infer::RegionVariableOrigin;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{RegionVid, UniverseIndex};
use tracing::debug;
use tracing::{debug, trace};
use crate::constraints::{ConstraintSccIndex, OutlivesConstraintSet};
use crate::consumers::OutlivesConstraint;
@ -62,18 +61,71 @@ impl scc::Annotations<RegionVid> for SccAnnotations<'_, '_, RegionTracker> {
type SccIdx = ConstraintSccIndex;
}
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
enum PlaceholderReachability {
/// This SCC reaches no placeholders.
NoPlaceholders,
/// This SCC reaches at least one placeholder.
Placeholders {
/// The largest-universed placeholder we can reach
max_universe: (UniverseIndex, RegionVid),
/// The placeholder with the smallest ID
min_placeholder: RegionVid,
/// The placeholder with the largest ID
max_placeholder: RegionVid,
},
}
impl PlaceholderReachability {
/// Merge the reachable placeholders of two graph components.
fn merge(self, other: PlaceholderReachability) -> PlaceholderReachability {
use PlaceholderReachability::*;
match (self, other) {
(NoPlaceholders, NoPlaceholders) => NoPlaceholders,
(NoPlaceholders, p @ Placeholders { .. })
| (p @ Placeholders { .. }, NoPlaceholders) => p,
(
Placeholders {
min_placeholder: min_pl,
max_placeholder: max_pl,
max_universe: max_u,
},
Placeholders { min_placeholder, max_placeholder, max_universe },
) => Placeholders {
min_placeholder: min_pl.min(min_placeholder),
max_placeholder: max_pl.max(max_placeholder),
max_universe: max_u.max(max_universe),
},
}
}
fn max_universe(&self) -> Option<(UniverseIndex, RegionVid)> {
match self {
Self::NoPlaceholders => None,
Self::Placeholders { max_universe, .. } => Some(*max_universe),
}
}
/// If we have reached placeholders, determine if they can
/// be named from this universe.
fn can_be_named_by(&self, from: UniverseIndex) -> bool {
self.max_universe()
.is_none_or(|(max_placeholder_universe, _)| from.can_name(max_placeholder_universe))
}
}
/// An annotation for region graph SCCs that tracks
/// the values of its elements. This annotates a single SCC.
#[derive(Copy, Debug, Clone)]
pub(crate) struct RegionTracker {
/// The largest universe of a placeholder reached from this SCC.
/// This includes placeholders within this SCC.
max_placeholder_universe_reached: UniverseIndex,
reachable_placeholders: PlaceholderReachability,
/// The largest universe nameable from this SCC.
/// It is the smallest nameable universes of all
/// existential regions reachable from it.
max_nameable_universe: UniverseIndex,
/// existential regions reachable from it. Small Rvids are preferred.
max_nameable_universe: (UniverseIndex, RegionVid),
/// The representative Region Variable Id for this SCC.
pub(crate) representative: Representative,
@ -81,65 +133,73 @@ pub(crate) struct RegionTracker {
impl RegionTracker {
pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
let placeholder_universe =
let reachable_placeholders =
if matches!(definition.origin, NllRegionVariableOrigin::Placeholder(_)) {
definition.universe
PlaceholderReachability::Placeholders {
max_universe: (definition.universe, rvid),
min_placeholder: rvid,
max_placeholder: rvid,
}
} else {
UniverseIndex::ROOT
PlaceholderReachability::NoPlaceholders
};
Self {
max_placeholder_universe_reached: placeholder_universe,
max_nameable_universe: definition.universe,
reachable_placeholders,
max_nameable_universe: (definition.universe, rvid),
representative: Representative::new(rvid, definition),
}
}
/// The largest universe this SCC can name. It's the smallest
/// largest nameable uninverse of any reachable region.
/// largest nameable universe of any reachable region, or
/// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)`
pub(crate) fn max_nameable_universe(self) -> UniverseIndex {
self.max_nameable_universe
self.max_nameable_universe.0
}
pub(crate) fn max_placeholder_universe_reached(self) -> UniverseIndex {
self.max_placeholder_universe_reached
}
fn merge_min_max_seen(&mut self, other: &Self) {
self.max_placeholder_universe_reached = std::cmp::max(
self.max_placeholder_universe_reached,
other.max_placeholder_universe_reached,
);
self.max_nameable_universe =
std::cmp::min(self.max_nameable_universe, other.max_nameable_universe);
}
/// Returns `true` if during the annotated SCC reaches a placeholder
/// with a universe larger than the smallest nameable universe of any
/// reachable existential region.
pub(crate) fn has_incompatible_universes(&self) -> bool {
self.max_nameable_universe().cannot_name(self.max_placeholder_universe_reached)
if let Some((universe, _)) = self.reachable_placeholders.max_universe() {
universe
} else {
UniverseIndex::ROOT
}
}
/// Determine if the tracked universes of the two SCCs are compatible.
pub(crate) fn universe_compatible_with(&self, other: Self) -> bool {
// HACK: We first check whether we can name the highest existential universe
// of `other`. This only exists to avoid errors in case that scc already
// depends on a placeholder it cannot name itself.
self.max_nameable_universe().can_name(other.max_nameable_universe())
|| self.max_nameable_universe().can_name(other.max_placeholder_universe_reached)
|| other.reachable_placeholders.can_be_named_by(self.max_nameable_universe())
}
/// If this SCC reaches a placeholder it can't name, return it.
fn unnameable_placeholder(&self) -> Option<(UniverseIndex, RegionVid)> {
self.reachable_placeholders.max_universe().filter(|&(placeholder_universe, _)| {
!self.max_nameable_universe().can_name(placeholder_universe)
})
}
}
impl scc::Annotation for RegionTracker {
fn merge_scc(mut self, other: Self) -> Self {
self.representative = self.representative.merge_scc(other.representative);
self.merge_min_max_seen(&other);
self
fn merge_scc(self, other: Self) -> Self {
trace!("{:?} << {:?}", self.representative, other.representative);
Self {
representative: self.representative.min(other.representative),
max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
}
}
fn merge_reached(mut self, other: Self) -> Self {
// No update to in-component values, only add seen values.
self.merge_min_max_seen(&other);
self
fn merge_reached(self, other: Self) -> Self {
Self {
max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
representative: self.representative,
}
}
}
@ -310,28 +370,52 @@ fn rewrite_placeholder_outlives<'tcx>(
let annotation = annotations[scc];
// If this SCC participates in a universe violation,
// e.g. if it reaches a region with a universe smaller than
// the largest region reached, add a requirement that it must
// outlive `'static`.
if annotation.has_incompatible_universes() {
// Optimisation opportunity: this will add more constraints than
// needed for correctness, since an SCC upstream of another with
// a universe violation will "infect" its downstream SCCs to also
// outlive static.
let scc_representative_outlives_static = OutlivesConstraint {
sup: annotation.representative.rvid(),
sub: fr_static,
category: ConstraintCategory::IllegalUniverse,
locations: Locations::All(rustc_span::DUMMY_SP),
span: rustc_span::DUMMY_SP,
variance_info: VarianceDiagInfo::None,
from_closure: false,
};
outlives_constraints.push(scc_representative_outlives_static);
added_constraints = true;
debug!("Added {:?}: 'static!", annotation.representative.rvid());
}
let Some((max_u, max_u_rvid)) = annotation.unnameable_placeholder() else {
continue;
};
debug!(
"Placeholder universe {max_u:?} is too large for its SCC, represented by {:?}",
annotation.representative
);
// We only add one `r: 'static` constraint per SCC, where `r` is the SCC representative.
// That constraint is annotated with some placeholder `unnameable` where
// `unnameable` is unnameable from `r` and there is a path in the constraint graph
// between them.
//
// There is one exception; if some other region in this SCC can't name `'r`, then
// we pick the region with the smallest universe in the SCC, so that a path can
// always start in `'r` to find a motivation that isn't cyclic.
let blame_to = if annotation.representative.rvid() == max_u_rvid {
// Assertion: the region that lowered our universe is an existential one and we are a placeholder!
// The SCC's representative is not nameable from some region
// that ends up in the SCC.
let small_universed_rvid = annotation.max_nameable_universe.1;
debug!(
"{small_universed_rvid:?} lowered our universe to {:?}",
annotation.max_nameable_universe()
);
small_universed_rvid
} else {
// `max_u_rvid` is not nameable by the SCC's representative.
max_u_rvid
};
// FIXME: if we can extract a useful blame span here, future error
// reporting and constraint search can be simplified.
added_constraints = true;
outlives_constraints.push(OutlivesConstraint {
sup: annotation.representative.rvid(),
sub: fr_static,
category: ConstraintCategory::OutlivesUnnameablePlaceholder(blame_to),
locations: Locations::All(rustc_span::DUMMY_SP),
span: rustc_span::DUMMY_SP,
variance_info: VarianceDiagInfo::None,
from_closure: false,
});
}
added_constraints
}

View file

@ -12,9 +12,13 @@ use rustc_middle::ty::UniverseIndex;
use super::*;
fn render_outlives_constraint(constraint: &OutlivesConstraint<'_>) -> String {
match constraint.locations {
Locations::All(_) => "All(...)".to_string(),
Locations::Single(loc) => format!("{loc:?}"),
if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = constraint.category {
format!("{unnameable:?} unnameable")
} else {
match constraint.locations {
Locations::All(_) => "All(...)".to_string(),
Locations::Single(loc) => format!("{loc:?}"),
}
}
}

View file

@ -3,7 +3,7 @@ use std::rc::Rc;
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::graph::scc::{self, Sccs};
use rustc_data_structures::graph::scc::Sccs;
use rustc_errors::Diag;
use rustc_hir::def_id::CRATE_DEF_ID;
use rustc_index::IndexVec;
@ -74,18 +74,6 @@ impl Representative {
}
}
impl scc::Annotation for Representative {
fn merge_scc(self, other: Self) -> Self {
// Just pick the smallest one. Note that we order by tag first!
std::cmp::min(self, other)
}
// For reachability, we do nothing since the representative doesn't change.
fn merge_reached(self, _other: Self) -> Self {
self
}
}
pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex>;
pub struct RegionInferenceContext<'tcx> {
@ -1285,11 +1273,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
{
debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus);
let blame_span_category = self.find_outlives_blame_span(
longer_fr,
NllRegionVariableOrigin::FreeRegion,
shorter_fr,
);
let blame_constraint = self
.best_blame_constraint(longer_fr, NllRegionVariableOrigin::FreeRegion, shorter_fr)
.0;
// Grow `shorter_fr` until we find some non-local regions. (We
// always will.) We'll call them `shorter_fr+` -- they're ever
@ -1302,8 +1288,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
subject: ClosureOutlivesSubject::Region(fr_minus),
outlived_free_region: fr,
blame_span: blame_span_category.1.span,
category: blame_span_category.0,
blame_span: blame_constraint.cause.span,
category: blame_constraint.category,
});
}
return RegionRelationCheckResult::Propagated;
@ -1342,66 +1328,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}
/// We have a constraint `fr1: fr2` that is not satisfied, where
/// `fr2` represents some universal region. Here, `r` is some
/// region where we know that `fr1: r` and this function has the
/// job of determining whether `r` is "to blame" for the fact that
/// `fr1: fr2` is required.
///
/// This is true under two conditions:
///
/// - `r == fr2`
/// - `fr2` is `'static` and `r` is some placeholder in a universe
/// that cannot be named by `fr1`; in that case, we will require
/// that `fr1: 'static` because it is the only way to `fr1: r` to
/// be satisfied. (See `add_incompatible_universe`.)
pub(crate) fn provides_universal_region(
pub(crate) fn constraint_path_between_regions(
&self,
r: RegionVid,
fr1: RegionVid,
fr2: RegionVid,
) -> bool {
debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2);
let result = {
r == fr2 || {
fr2 == self.universal_regions().fr_static && self.cannot_name_placeholder(fr1, r)
}
};
debug!("provides_universal_region: result = {:?}", result);
result
}
/// If `r2` represents a placeholder region, then this returns
/// `true` if `r1` cannot name that placeholder in its
/// value; otherwise, returns `false`.
pub(crate) fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool {
match self.definitions[r2].origin {
NllRegionVariableOrigin::Placeholder(placeholder) => {
let r1_universe = self.definitions[r1].universe;
debug!(
"cannot_name_value_of: universe1={r1_universe:?} placeholder={:?}",
placeholder
);
r1_universe.cannot_name(placeholder.universe)
}
NllRegionVariableOrigin::FreeRegion | NllRegionVariableOrigin::Existential { .. } => {
false
}
from_region: RegionVid,
to_region: RegionVid,
) -> Option<Vec<OutlivesConstraint<'tcx>>> {
if from_region == to_region {
bug!("Tried to find a path between {from_region:?} and itself!");
}
}
/// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
pub(crate) fn find_outlives_blame_span(
&self,
fr1: RegionVid,
fr1_origin: NllRegionVariableOrigin,
fr2: RegionVid,
) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) {
let BlameConstraint { category, cause, .. } = self
.best_blame_constraint(fr1, fr1_origin, |r| self.provides_universal_region(r, fr1, fr2))
.0;
(category, cause)
self.constraint_path_to(from_region, |to| to == to_region, true).map(|o| o.0)
}
/// Walks the graph of constraints (where `'a: 'b` is considered
@ -1410,15 +1345,30 @@ impl<'tcx> RegionInferenceContext<'tcx> {
///
/// Returns: a series of constraints as well as the region `R`
/// that passed the target test.
/// If `include_static_outlives_all` is `true`, then the synthetic
/// outlives constraints `'static -> a` for every region `a` are
/// considered in the search, otherwise they are ignored.
#[instrument(skip(self, target_test), ret)]
pub(crate) fn find_constraint_path_between_regions(
pub(crate) fn constraint_path_to(
&self,
from_region: RegionVid,
target_test: impl Fn(RegionVid) -> bool,
include_placeholder_static: bool,
) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
self.find_constraint_path_between_regions_inner(true, from_region, &target_test).or_else(
|| self.find_constraint_path_between_regions_inner(false, from_region, &target_test),
self.find_constraint_path_between_regions_inner(
true,
from_region,
&target_test,
include_placeholder_static,
)
.or_else(|| {
self.find_constraint_path_between_regions_inner(
false,
from_region,
&target_test,
include_placeholder_static,
)
})
}
/// The constraints we get from equating the hidden type of each use of an opaque
@ -1438,6 +1388,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
ignore_opaque_type_constraints: bool,
from_region: RegionVid,
target_test: impl Fn(RegionVid) -> bool,
include_placeholder_static: bool,
) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
context[from_region] = Trace::StartRegion;
@ -1452,7 +1403,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
while let Some(r) = deque.pop_front() {
debug!(
"find_constraint_path_between_regions: from_region={:?} r={:?} value={}",
"constraint_path_to: from_region={:?} r={:?} value={}",
from_region,
r,
self.region_value_str(r),
@ -1525,8 +1476,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// This loop can be hot.
for constraint in edges {
match constraint.category {
ConstraintCategory::IllegalUniverse => {
debug!("Ignoring illegal universe constraint: {constraint:?}");
ConstraintCategory::OutlivesUnnameablePlaceholder(_)
if !include_placeholder_static =>
{
debug!("Ignoring illegal placeholder constraint: {constraint:?}");
continue;
}
ConstraintCategory::OpaqueType if ignore_opaque_type_constraints => {
@ -1535,6 +1488,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
_ => {}
}
debug_assert_eq!(constraint.sup, r);
handle_trace(constraint.sub, Trace::FromGraph(constraint));
}
@ -1549,33 +1503,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid {
trace!(scc = ?self.constraint_sccs.scc(fr1));
trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1)));
self.find_constraint_path_between_regions(fr1, |r| {
// First look for some `r` such that `fr1: r` and `r` is live at `location`
self.constraint_path_to(fr1, |r| {
trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r));
self.liveness_constraints.is_live_at(r, location)
})
.or_else(|| {
// If we fail to find that, we may find some `r` such that
// `fr1: r` and `r` is a placeholder from some universe
// `fr1` cannot name. This would force `fr1` to be
// `'static`.
self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(fr1, r))
})
.or_else(|| {
// If we fail to find THAT, it may be that `fr1` is a
// placeholder that cannot "fit" into its SCC. In that
// case, there should be some `r` where `fr1: r` and `fr1` is a
// placeholder that `r` cannot name. We can blame that
// edge.
//
// Remember that if `R1: R2`, then the universe of R1
// must be able to name the universe of R2, because R2 will
// be at least `'empty(Universe(R2))`, and `R1` must be at
// larger than that.
self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(r, fr1))
})
.map(|(_path, r)| r)
.unwrap()
}, true).unwrap().1
}
/// Get the region outlived by `longer_fr` and live at `element`.
@ -1619,22 +1550,38 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// creating a constraint path that forces `R` to outlive
/// `from_region`, and then finding the best choices within that
/// path to blame.
#[instrument(level = "debug", skip(self, target_test))]
#[instrument(level = "debug", skip(self))]
pub(crate) fn best_blame_constraint(
&self,
from_region: RegionVid,
from_region_origin: NllRegionVariableOrigin,
target_test: impl Fn(RegionVid) -> bool,
to_region: RegionVid,
) -> (BlameConstraint<'tcx>, Vec<OutlivesConstraint<'tcx>>) {
// Find all paths
let (path, target_region) = self
.find_constraint_path_between_regions(from_region, target_test)
.or_else(|| {
self.find_constraint_path_between_regions(from_region, |r| {
self.cannot_name_placeholder(from_region, r)
})
})
.unwrap();
assert!(from_region != to_region, "Trying to blame a region for itself!");
let path = self.constraint_path_between_regions(from_region, to_region).unwrap();
// If we are passing through a constraint added because we reached an unnameable placeholder `'unnameable`,
// redirect search towards `'unnameable`.
let due_to_placeholder_outlives = path.iter().find_map(|c| {
if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = c.category {
Some(unnameable)
} else {
None
}
});
// Edge case: it's possible that `'from_region` is an unnameable placeholder.
let path = if let Some(unnameable) = due_to_placeholder_outlives
&& unnameable != from_region
{
// We ignore the extra edges due to unnameable placeholders to get
// an explanation that was present in the original constraint graph.
self.constraint_path_to(from_region, |r| r == unnameable, false).unwrap().0
} else {
path
};
debug!(
"path={:#?}",
path.iter()
@ -1742,7 +1689,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
ConstraintCategory::Cast {
unsize_to: Some(unsize_ty),
is_implicit_coercion: true,
} if target_region == self.universal_regions().fr_static
} if to_region == self.universal_regions().fr_static
// Mirror the note's condition, to minimize how often this diverts blame.
&& let ty::Adt(_, args) = unsize_ty.kind()
&& args.iter().any(|arg| arg.as_type().is_some_and(|ty| ty.is_trait()))
@ -1780,7 +1727,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// specific, and are not used for relations that would make sense to blame.
ConstraintCategory::BoringNoLocation => 6,
// Do not blame internal constraints.
ConstraintCategory::IllegalUniverse => 7,
ConstraintCategory::OutlivesUnnameablePlaceholder(_) => 7,
ConstraintCategory::Internal => 8,
};
@ -1817,6 +1764,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
path[best_choice]
};
assert!(
!matches!(
best_constraint.category,
ConstraintCategory::OutlivesUnnameablePlaceholder(_)
),
"Illegal placeholder constraint blamed; should have redirected to other region relation"
);
let blame_constraint = BlameConstraint {
category: best_constraint.category,
from_closure: best_constraint.from_closure,

View file

@ -30,6 +30,6 @@ rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
thin-vec = "0.2.12"
tracing = "0.1"
thin-vec.workspace = true
tracing.workspace = true
# tidy-alphabetical-end

View file

@ -416,7 +416,7 @@ pub(crate) mod printf {
// Yes, this *is* the parameter.
Some(('$', end2)) => {
state = Flags;
parameter = Some(at.slice_between(end).unwrap().parse().unwrap());
parameter = at.slice_between(end).unwrap().parse().ok();
move_to!(end2);
}
// Wait, no, actually, it's the width.

View file

@ -8,15 +8,15 @@ test = false
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
bitflags.workspace = true
# To avoid duplicate dependencies, this should match the version of gimli used
# by `rustc_codegen_ssa` via its `thorin-dwp` dependency.
gimli = "0.31"
itertools = "0.12"
libc = "0.2"
measureme = "12.0.1"
itertools.workspace = true
libc.workspace = true
measureme.workspace = true
object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
rustc-demangle = "0.1.21"
rustc-demangle.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
@ -38,9 +38,9 @@ rustc_span = { path = "../rustc_span" }
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
rustc_target = { path = "../rustc_target" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_json.workspace = true
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
tracing.workspace = true
# tidy-alphabetical-end
[features]

View file

@ -44,7 +44,7 @@ const ABI_AFFECTING_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 1] =
const OPTIMIZATION_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 6] = [
(ArgAttribute::NoAlias, llvm::AttributeKind::NoAlias),
(ArgAttribute::NoCapture, llvm::AttributeKind::NoCapture),
(ArgAttribute::CapturesAddress, llvm::AttributeKind::CapturesAddress),
(ArgAttribute::NonNull, llvm::AttributeKind::NonNull),
(ArgAttribute::ReadOnly, llvm::AttributeKind::ReadOnly),
(ArgAttribute::NoUndef, llvm::AttributeKind::NoUndef),
@ -84,8 +84,10 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
}
for (attr, llattr) in OPTIMIZATION_ATTRIBUTES {
if regular.contains(attr) {
// captures(address, read_provenance) is only available since LLVM 21.
if attr == ArgAttribute::CapturesReadOnly && llvm_util::get_version() < (21, 0, 0) {
// captures(...) is only available since LLVM 21.
if (attr == ArgAttribute::CapturesReadOnly || attr == ArgAttribute::CapturesAddress)
&& llvm_util::get_version() < (21, 0, 0)
{
continue;
}
attrs.push(llattr.create_attr(cx.llcx));

View file

@ -15,6 +15,7 @@ use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::memmap::Mmap;
use rustc_errors::DiagCtxtHandle;
use rustc_hir::attrs::SanitizerSet;
use rustc_middle::bug;
use rustc_middle::dep_graph::WorkProduct;
use rustc_session::config::{self, Lto};
@ -42,6 +43,37 @@ fn prepare_lto(
.map(|symbol| CString::new(symbol.to_owned()).unwrap())
.collect::<Vec<CString>>();
if cgcx.regular_module_config.instrument_coverage
|| cgcx.regular_module_config.pgo_gen.enabled()
{
// These are weak symbols that point to the profile version and the
// profile name, which need to be treated as exported so LTO doesn't nix
// them.
const PROFILER_WEAK_SYMBOLS: [&CStr; 2] =
[c"__llvm_profile_raw_version", c"__llvm_profile_filename"];
symbols_below_threshold.extend(PROFILER_WEAK_SYMBOLS.iter().map(|&sym| sym.to_owned()));
}
if cgcx.regular_module_config.sanitizer.contains(SanitizerSet::MEMORY) {
let mut msan_weak_symbols = Vec::new();
// Similar to profiling, preserve weak msan symbol during LTO.
if cgcx.regular_module_config.sanitizer_recover.contains(SanitizerSet::MEMORY) {
msan_weak_symbols.push(c"__msan_keep_going");
}
if cgcx.regular_module_config.sanitizer_memory_track_origins != 0 {
msan_weak_symbols.push(c"__msan_track_origins");
}
symbols_below_threshold.extend(msan_weak_symbols.into_iter().map(|sym| sym.to_owned()));
}
// Preserve LLVM-injected, ASAN-related symbols.
// See also https://github.com/rust-lang/rust/issues/113404.
symbols_below_threshold.push(c"___asan_globals_registered".to_owned());
// __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
// __llvm_profile_runtime, therefore we won't know until link time if this symbol
// should have default visibility.

View file

@ -19,7 +19,9 @@ use rustc_middle::ty::{
self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
};
use rustc_session::config::{self, DebugInfo, Lto};
use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Symbol, hygiene};
use rustc_span::{
DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Span, Symbol, hygiene,
};
use rustc_symbol_mangling::typeid_for_trait_ref;
use rustc_target::spec::DebuginfoKind;
use smallvec::smallvec;
@ -423,6 +425,14 @@ fn build_slice_type_di_node<'ll, 'tcx>(
/// This function will look up the debuginfo node in the TypeMap. If it can't find it, it
/// will create the node by dispatching to the corresponding `build_*_di_node()` function.
pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
spanned_type_di_node(cx, t, DUMMY_SP)
}
pub(crate) fn spanned_type_di_node<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
t: Ty<'tcx>,
span: Span,
) -> &'ll DIType {
let unique_type_id = UniqueTypeId::for_ty(cx.tcx, t);
if let Some(existing_di_node) = debug_context(cx).type_map.di_node_for_unique_id(unique_type_id)
@ -460,7 +470,7 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) ->
ty::Adt(def, ..) => match def.adt_kind() {
AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id),
AdtKind::Union => build_union_type_di_node(cx, unique_type_id),
AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id),
AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id, span),
},
ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id),
_ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t),

View file

@ -10,7 +10,7 @@ use rustc_middle::bug;
use rustc_middle::mir::CoroutineLayout;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef};
use rustc_span::Symbol;
use rustc_span::{Span, Symbol};
use super::type_map::{DINodeCreationResult, UniqueTypeId};
use super::{SmallVec, size_and_align_of};
@ -30,13 +30,14 @@ mod native;
pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
unique_type_id: UniqueTypeId<'tcx>,
span: Span,
) -> DINodeCreationResult<'ll> {
let enum_type = unique_type_id.expect_ty();
let &ty::Adt(enum_adt_def, _) = enum_type.kind() else {
bug!("build_enum_type_di_node() called with non-enum type: `{:?}`", enum_type)
};
let enum_type_and_layout = cx.layout_of(enum_type);
let enum_type_and_layout = cx.spanned_layout_of(enum_type, span);
if wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout) {
return build_c_style_enum_di_node(cx, enum_adt_def, enum_type_and_layout);

View file

@ -28,7 +28,9 @@ use rustc_target::spec::DebuginfoKind;
use smallvec::SmallVec;
use tracing::debug;
use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, type_di_node};
use self::metadata::{
UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, spanned_type_di_node, type_di_node,
};
use self::namespace::mangled_name_of_instance;
use self::utils::{DIB, create_DIArray, is_node_local_to_unit};
use crate::builder::Builder;
@ -626,7 +628,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let loc = self.lookup_debug_loc(span.lo());
let file_metadata = file_metadata(self, &loc.file);
let type_metadata = type_di_node(self, variable_type);
let type_metadata = spanned_type_di_node(self, variable_type, span);
let (argument_index, dwarf_tag) = match variable_kind {
ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),

View file

@ -263,7 +263,7 @@ pub(crate) enum AttributeKind {
MinSize = 4,
Naked = 5,
NoAlias = 6,
NoCapture = 7,
CapturesAddress = 7,
NoInline = 8,
NonNull = 9,
NoRedZone = 10,

View file

@ -6,12 +6,12 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
ar_archive_writer = "0.4.2"
bitflags = "2.4.1"
bitflags.workspace = true
bstr = "1.11.3"
# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version
# per crate", so if you change this, you need to also change it in `rustc_llvm`.
cc = "=1.2.16"
itertools = "0.12"
itertools.workspace = true
pathdiff = "0.2.0"
regex = "1.4"
rustc_abi = { path = "../rustc_abi" }
@ -37,18 +37,18 @@ rustc_span = { path = "../rustc_span" }
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
serde_json = "1.0.59"
serde_json.workspace = true
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tempfile = "3.2"
thin-vec = "0.2.12"
tempfile.workspace = true
thin-vec.workspace = true
thorin-dwp = "0.9"
tracing = "0.1"
tracing.workspace = true
wasm-encoder = "0.219"
# tidy-alphabetical-end
[target.'cfg(unix)'.dependencies]
# tidy-alphabetical-start
libc = "0.2.50"
libc.workspace = true
# tidy-alphabetical-end
[dependencies.object]

View file

@ -14,11 +14,13 @@ use itertools::Itertools;
use regex::Regex;
use rustc_arena::TypedArena;
use rustc_ast::CRATE_NODE_ID;
use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize};
use rustc_hir::attrs::NativeLibKind;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_macros::LintDiagnostic;
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
@ -38,7 +40,6 @@ use rustc_session::config::{
use rustc_session::lint::builtin::LINKER_MESSAGES;
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
use rustc_session::search_paths::PathKind;
use rustc_session::utils::NativeLibKind;
/// For all the linkers we support, and information they might
/// need out of the shared crate context before we get rid of it.
use rustc_session::{Session, filesearch};
@ -3019,7 +3020,9 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
match lib.cfg {
Some(ref cfg) => rustc_attr_parsing::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
Some(ref cfg) => {
eval_config_entry(sess, cfg, CRATE_NODE_ID, None, ShouldEmit::ErrorsAndLints).as_bool()
}
None => true,
}
}

View file

@ -7,9 +7,9 @@ use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_hashes::Hash128;
use rustc_hir::attrs::NativeLibKind;
use rustc_session::Session;
use rustc_session::cstore::DllImport;
use rustc_session::utils::NativeLibKind;
use rustc_span::Symbol;
use crate::back::archive::ImportLibraryItem;

View file

@ -15,7 +15,7 @@ use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolNam
use rustc_middle::util::Providers;
use rustc_session::config::{CrateType, OomStrategy};
use rustc_symbol_mangling::mangle_internal_symbol;
use rustc_target::spec::{SanitizerSet, TlsModel};
use rustc_target::spec::TlsModel;
use tracing::debug;
use crate::base::allocator_kind_for_codegen;
@ -242,53 +242,6 @@ fn exported_non_generic_symbols_provider_local<'tcx>(
}
}
if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() {
// These are weak symbols that point to the profile version and the
// profile name, which need to be treated as exported so LTO doesn't nix
// them.
const PROFILER_WEAK_SYMBOLS: [&str; 2] =
["__llvm_profile_raw_version", "__llvm_profile_filename"];
symbols.extend(PROFILER_WEAK_SYMBOLS.iter().map(|sym| {
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym));
(
exported_symbol,
SymbolExportInfo {
level: SymbolExportLevel::C,
kind: SymbolExportKind::Data,
used: false,
rustc_std_internal_symbol: false,
},
)
}));
}
if tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) {
let mut msan_weak_symbols = Vec::new();
// Similar to profiling, preserve weak msan symbol during LTO.
if tcx.sess.opts.unstable_opts.sanitizer_recover.contains(SanitizerSet::MEMORY) {
msan_weak_symbols.push("__msan_keep_going");
}
if tcx.sess.opts.unstable_opts.sanitizer_memory_track_origins != 0 {
msan_weak_symbols.push("__msan_track_origins");
}
symbols.extend(msan_weak_symbols.into_iter().map(|sym| {
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym));
(
exported_symbol,
SymbolExportInfo {
level: SymbolExportLevel::C,
kind: SymbolExportKind::Data,
used: false,
rustc_std_internal_symbol: false,
},
)
}));
}
// Sort so we get a stable incr. comp. hash.
symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx));

View file

@ -138,23 +138,12 @@ impl ModuleConfig {
let emit_obj = if !should_emit_obj {
EmitObj::None
} else if sess.target.obj_is_bitcode
|| (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins)
{
} else if sess.target.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() {
// This case is selected if the target uses objects as bitcode, or
// if linker plugin LTO is enabled. In the linker plugin LTO case
// the assumption is that the final link-step will read the bitcode
// and convert it to object code. This may be done by either the
// native linker or rustc itself.
//
// Note, however, that the linker-plugin-lto requested here is
// explicitly ignored for `#![no_builtins]` crates. These crates are
// specifically ignored by rustc's LTO passes and wouldn't work if
// loaded into the linker. These crates define symbols that LLVM
// lowers intrinsics to, and these symbol dependencies aren't known
// until after codegen. As a result any crate marked
// `#![no_builtins]` is assumed to not participate in LTO and
// instead goes on to generate object code.
EmitObj::Bitcode
} else if need_bitcode_in_object(tcx) {
EmitObj::ObjectCode(BitcodeSection::Full)
@ -1957,10 +1946,13 @@ impl<B: ExtraBackendMethods> Drop for Coordinator<B> {
pub struct OngoingCodegen<B: ExtraBackendMethods> {
pub backend: B,
pub crate_info: CrateInfo,
pub output_filenames: Arc<OutputFilenames>,
// Field order below is intended to terminate the coordinator thread before two fields below
// drop and prematurely close channels used by coordinator thread. See `Coordinator`'s
// `Drop` implementation for more info.
pub coordinator: Coordinator<B>,
pub codegen_worker_receive: Receiver<CguMessage>,
pub shared_emitter_main: SharedEmitterMain,
pub output_filenames: Arc<OutputFilenames>,
pub coordinator: Coordinator<B>,
}
impl<B: ExtraBackendMethods> OngoingCodegen<B> {

View file

@ -1,10 +1,11 @@
#![allow(non_camel_case_types)]
use rustc_hir::LangItem;
use rustc_hir::attrs::PeImportNameType;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, Instance, TyCtxt};
use rustc_middle::{bug, mir, span_bug};
use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
use rustc_session::cstore::{DllCallingConvention, DllImport};
use rustc_span::Span;
use rustc_target::spec::Target;

View file

@ -25,10 +25,10 @@ use std::io;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::unord::UnordMap;
use rustc_hir::CRATE_HIR_ID;
use rustc_hir::attrs::{CfgEntry, NativeLibKind};
use rustc_hir::def_id::CrateNum;
use rustc_macros::{Decodable, Encodable, HashStable};
use rustc_metadata::EncodedMetadata;
@ -45,7 +45,6 @@ use rustc_session::Session;
use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
use rustc_session::cstore::{self, CrateSource};
use rustc_session::lint::builtin::LINKER_MESSAGES;
use rustc_session::utils::NativeLibKind;
use rustc_span::Symbol;
pub mod assert_module_sources;
@ -187,7 +186,7 @@ pub struct NativeLib {
pub kind: NativeLibKind,
pub name: Symbol,
pub filename: Option<Symbol>,
pub cfg: Option<ast::MetaItemInner>,
pub cfg: Option<CfgEntry>,
pub verbatim: bool,
pub dll_imports: Vec<cstore::DllImport>,
}

View file

@ -5,9 +5,9 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
either = "1"
either.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_apfloat = "0.2.0"
rustc_apfloat.workspace = true
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
@ -22,5 +22,5 @@ rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
tracing = "0.1"
tracing.workspace = true
# tidy-alphabetical-end

View file

@ -6,14 +6,15 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
arrayvec = { version = "0.7", default-features = false }
bitflags = "2.4.1"
either = "1.0"
bitflags.workspace = true
either.workspace = true
elsa = "1.11.0"
ena = "0.14.3"
indexmap = "2.4.0"
indexmap.workspace = true
jobserver_crate = { version = "0.1.28", package = "jobserver" }
measureme = "12.0.1"
rustc-hash = "2.0.0"
measureme.workspace = true
parking_lot = "0.12"
rustc-hash.workspace = true
rustc-stable-hash = { version = "0.1.0", features = ["nightly"] }
rustc_arena = { path = "../rustc_arena" }
rustc_graphviz = { path = "../rustc_graphviz" }
@ -24,9 +25,9 @@ rustc_serialize = { path = "../rustc_serialize" }
rustc_thread_pool = { path = "../rustc_thread_pool" }
smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] }
stacker = "0.1.17"
tempfile = "3.2"
thin-vec = "0.2.12"
tracing = "0.1"
tempfile.workspace = true
thin-vec.workspace = true
tracing.workspace = true
# tidy-alphabetical-end
[dependencies.hashbrown]
@ -34,9 +35,6 @@ version = "0.15.2"
default-features = false
features = ["nightly"] # for may_dangle
[dependencies.parking_lot]
version = "0.12"
[target.'cfg(windows)'.dependencies.windows]
version = "0.61.0"
features = [
@ -49,7 +47,7 @@ features = [
[target.'cfg(unix)'.dependencies]
# tidy-alphabetical-start
libc = "0.2"
libc.workspace = true
# tidy-alphabetical-end
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]

View file

@ -49,14 +49,14 @@ rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_ty_utils = { path = "../rustc_ty_utils" }
serde_json = "1.0.59"
serde_json.workspace = true
shlex = "1.0"
tracing = { version = "0.1.35" }
tracing.workspace = true
# tidy-alphabetical-end
[target.'cfg(all(unix, any(target_env = "gnu", target_os = "macos")))'.dependencies]
# tidy-alphabetical-start
libc = "0.2"
libc.workspace = true
# tidy-alphabetical-end
[target.'cfg(windows)'.dependencies.windows]

View file

@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.
An unknown "kind" was specified for a link attribute.
Erroneous code example:
```compile_fail,E0458
```ignore (no longer emitted)
#[link(kind = "wonderful_unicorn")] extern "C" {}
// error: unknown kind: `wonderful_unicorn`
```

View file

@ -7,9 +7,8 @@ edition = "2024"
# tidy-alphabetical-start
fluent-bundle = "0.16"
fluent-syntax = "0.12"
icu_list = "1.2"
icu_locid = "1.2"
icu_provider_adapters = "1.2"
icu_list = { version = "2.0", default-features = false, features = ["alloc"] }
icu_locale = { version = "2.0", default-features = false }
intl-memoizer = "0.5.1"
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
@ -18,6 +17,6 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
tracing = "0.1"
tracing.workspace = true
unic-langid = { version = "0.9.0", features = ["macros"] }
# tidy-alphabetical-end

View file

@ -15,7 +15,6 @@ use fluent_bundle::FluentResource;
pub use fluent_bundle::types::FluentType;
pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue};
use fluent_syntax::parser::ParserError;
use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
use intl_memoizer::concurrent::IntlLangMemoizer;
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend};
use rustc_macros::{Decodable, Encodable};
@ -515,8 +514,8 @@ impl From<Vec<Span>> for MultiSpan {
}
}
fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locid::Locale> {
icu_locid::Locale::try_from_bytes(lang.to_string().as_bytes()).ok()
fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locale::Locale> {
icu_locale::Locale::try_from_str(&lang.to_string()).ok()
}
pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValue<'_> {
@ -568,21 +567,15 @@ pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValu
where
Self: Sized,
{
let baked_data_provider = rustc_baked_icu_data::baked_data_provider();
let locale_fallbacker =
LocaleFallbacker::try_new_with_any_provider(&baked_data_provider)
.expect("Failed to create fallback provider");
let data_provider =
LocaleFallbackProvider::new_with_fallbacker(baked_data_provider, locale_fallbacker);
let locale = icu_locale_from_unic_langid(lang)
.unwrap_or_else(|| rustc_baked_icu_data::supported_locales::EN);
let list_formatter =
icu_list::ListFormatter::try_new_and_with_length_with_any_provider(
&data_provider,
&locale.into(),
icu_list::ListLength::Wide,
)
.expect("Failed to create list formatter");
let list_formatter = icu_list::ListFormatter::try_new_and_unstable(
&rustc_baked_icu_data::BakedDataProvider,
locale.into(),
icu_list::options::ListFormatterOptions::default()
.with_length(icu_list::options::ListLength::Wide),
)
.expect("Failed to create list formatter");
Ok(MemoizableListFormatter(list_formatter))
}

View file

@ -21,10 +21,10 @@ rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
serde = { version = "1.0.125", features = ["derive"] }
serde_json = "1.0.59"
serde_json.workspace = true
termcolor = "1.2.0"
termize = "0.2"
tracing = "0.1"
tracing.workspace = true
# tidy-alphabetical-end
[target.'cfg(windows)'.dependencies.windows]

View file

@ -1462,7 +1462,7 @@ impl HumanEmitter {
max_line_num_len: usize,
is_secondary: bool,
is_cont: bool,
) -> io::Result<()> {
) -> io::Result<CodeWindowStatus> {
let mut buffer = StyledBuffer::new();
if !msp.has_primary_spans() && !msp.has_span_labels() && is_secondary && !self.short_message
@ -1575,12 +1575,14 @@ impl HumanEmitter {
}
let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp);
trace!("{annotated_files:#?}");
let mut code_window_status = CodeWindowStatus::Open;
// Make sure our primary file comes first
let primary_span = msp.primary_span().unwrap_or_default();
let (Some(sm), false) = (self.sm.as_ref(), primary_span.is_dummy()) else {
// If we don't have span information, emit and exit
return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message);
return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)
.map(|_| code_window_status);
};
let primary_lo = sm.lookup_char_pos(primary_span.lo());
if let Ok(pos) =
@ -1589,6 +1591,9 @@ impl HumanEmitter {
annotated_files.swap(0, pos);
}
// An end column separator should be emitted when a file with with a
// source, is followed by one without a source
let mut col_sep_before_no_show_source = false;
let annotated_files_len = annotated_files.len();
// Print out the annotate source lines that correspond with the error
for (file_idx, annotated_file) in annotated_files.into_iter().enumerate() {
@ -1599,6 +1604,26 @@ impl HumanEmitter {
&annotated_file.file,
) {
if !self.short_message {
// Add an end column separator when a file without a source
// comes after one with a source
// ╭▸ $DIR/deriving-meta-unknown-trait.rs:1:10
// │
// LL │ #[derive(Eqr)]
// │ ━━━
// ╰╴ (<- It prints *this* line)
// ╭▸ $SRC_DIR/core/src/cmp.rs:356:0
// │
// ╰╴note: similarly named derive macro `Eq` defined here
if col_sep_before_no_show_source {
let buffer_msg_line_offset = buffer.num_lines();
self.draw_col_separator_end(
&mut buffer,
buffer_msg_line_offset,
max_line_num_len + 1,
);
}
col_sep_before_no_show_source = false;
// We'll just print an unannotated message.
for (annotation_id, line) in annotated_file.lines.iter().enumerate() {
let mut annotations = line.annotations.clone();
@ -1639,29 +1664,42 @@ impl HumanEmitter {
}
line_idx += 1;
}
for (label, is_primary) in labels.into_iter() {
if is_cont
&& file_idx == annotated_files_len - 1
&& annotation_id == annotated_file.lines.len() - 1
&& !labels.is_empty()
{
code_window_status = CodeWindowStatus::Closed;
}
let labels_len = labels.len();
for (label_idx, (label, is_primary)) in labels.into_iter().enumerate() {
let style = if is_primary {
Style::LabelPrimary
} else {
Style::LabelSecondary
};
let pipe = self.col_separator();
buffer.prepend(line_idx, &format!(" {pipe}"), Style::LineNumber);
for _ in 0..max_line_num_len {
buffer.prepend(line_idx, " ", Style::NoStyle);
}
self.draw_col_separator_no_space(
&mut buffer,
line_idx,
max_line_num_len + 1,
);
line_idx += 1;
let chr = self.note_separator();
buffer.append(line_idx, &format!(" {chr} note: "), style);
for _ in 0..max_line_num_len {
buffer.prepend(line_idx, " ", Style::NoStyle);
}
self.draw_note_separator(
&mut buffer,
line_idx,
max_line_num_len + 1,
label_idx != labels_len - 1,
);
buffer.append(line_idx, "note", Style::MainHeaderMsg);
buffer.append(line_idx, ": ", Style::NoStyle);
buffer.append(line_idx, label, style);
line_idx += 1;
}
}
}
continue;
} else {
col_sep_before_no_show_source = true;
}
// print out the span location and spacer before we print the annotated source
@ -1976,7 +2014,7 @@ impl HumanEmitter {
// final step: take our styled buffer, render it, then output it
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
Ok(())
Ok(code_window_status)
}
fn column_width(&self, code_offset: usize) -> usize {
@ -2491,7 +2529,7 @@ impl HumanEmitter {
!children.is_empty()
|| suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden),
) {
Ok(()) => {
Ok(code_window_status) => {
if !children.is_empty()
|| suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden)
{
@ -2502,7 +2540,7 @@ impl HumanEmitter {
{
// We'll continue the vertical bar to point into the next note.
self.draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1);
} else {
} else if matches!(code_window_status, CodeWindowStatus::Open) {
// We'll close the vertical bar to visually end the code window.
self.draw_col_separator_end(&mut buffer, 0, max_line_num_len + 1);
}
@ -2829,10 +2867,11 @@ impl HumanEmitter {
}
}
fn note_separator(&self) -> char {
fn note_separator(&self, is_cont: bool) -> &'static str {
match self.theme {
OutputTheme::Ascii => '=',
OutputTheme::Unicode => '╰',
OutputTheme::Ascii => "= ",
OutputTheme::Unicode if is_cont => "",
OutputTheme::Unicode => "",
}
}
@ -2945,11 +2984,7 @@ impl HumanEmitter {
col: usize,
is_cont: bool,
) {
let chr = match self.theme {
OutputTheme::Ascii => "= ",
OutputTheme::Unicode if is_cont => "",
OutputTheme::Unicode => "",
};
let chr = self.note_separator(is_cont);
buffer.puts(line, col, chr, Style::LineNumber);
}
@ -3050,6 +3085,12 @@ enum DisplaySuggestion {
Add,
}
#[derive(Clone, Copy, Debug)]
enum CodeWindowStatus {
Closed,
Open,
}
impl FileWithAnnotatedLines {
/// Preprocess all the annotations so that they are grouped by file and by line number
/// This helps us quickly iterate over the whole message (including secondary file spans)

View file

@ -29,6 +29,6 @@ rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
thin-vec = "0.2.12"
tracing = "0.1"
thin-vec.workspace = true
tracing.workspace = true
# tidy-alphabetical-end

View file

@ -9,5 +9,5 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_hir = { path = "../rustc_hir" }
rustc_span = { path = "../rustc_span" }
serde = { version = "1.0.125", features = ["derive"] }
serde_json = "1.0.59"
serde_json.workspace = true
# tidy-alphabetical-end

View file

@ -11,8 +11,8 @@ proc-macro = true
annotate-snippets = "0.11"
fluent-bundle = "0.16"
fluent-syntax = "0.12"
proc-macro2 = "1"
quote = "1"
proc-macro2.workspace = true
quote.workspace = true
syn = { version = "2", features = ["full"] }
unic-langid = { version = "0.9.0", features = ["macros"] }
# tidy-alphabetical-end

View file

@ -5,5 +5,5 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
tempfile = "3.7.1"
tempfile.workspace = true
# tidy-alphabetical-end

View file

@ -5,8 +5,8 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
bitflags = "2.9.1"
odht = { version = "0.3.1", features = ["nightly"] }
bitflags.workspace = true
odht.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
@ -21,6 +21,6 @@ rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
thin-vec = "0.2.12"
tracing = "0.1"
thin-vec.workspace = true
tracing.workspace = true
# tidy-alphabetical-end

View file

@ -248,6 +248,120 @@ impl IntoDiagArg for MirPhase {
}
}
/// Different ways that the PE Format can decorate a symbol name.
/// From <https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-name-type>
#[derive(
Copy,
Clone,
Debug,
Encodable,
Decodable,
HashStable_Generic,
PartialEq,
Eq,
PrintAttribute
)]
pub enum PeImportNameType {
/// IMPORT_ORDINAL
/// Uses the ordinal (i.e., a number) rather than the name.
Ordinal(u16),
/// Same as IMPORT_NAME
/// Name is decorated with all prefixes and suffixes.
Decorated,
/// Same as IMPORT_NAME_NOPREFIX
/// Prefix (e.g., the leading `_` or `@`) is skipped, but suffix is kept.
NoPrefix,
/// Same as IMPORT_NAME_UNDECORATE
/// Prefix (e.g., the leading `_` or `@`) and suffix (the first `@` and all
/// trailing characters) are skipped.
Undecorated,
}
#[derive(
Copy,
Clone,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Encodable,
Decodable,
PrintAttribute
)]
#[derive(HashStable_Generic)]
pub enum NativeLibKind {
/// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC)
Static {
/// Whether to bundle objects from static library into produced rlib
bundle: Option<bool>,
/// Whether to link static library without throwing any object files away
whole_archive: Option<bool>,
},
/// Dynamic library (e.g. `libfoo.so` on Linux)
/// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC).
Dylib {
/// Whether the dynamic library will be linked only if it satisfies some undefined symbols
as_needed: Option<bool>,
},
/// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
/// On Linux, it refers to a generated shared library stub.
RawDylib,
/// A macOS-specific kind of dynamic libraries.
Framework {
/// Whether the framework will be linked only if it satisfies some undefined symbols
as_needed: Option<bool>,
},
/// Argument which is passed to linker, relative order with libraries and other arguments
/// is preserved
LinkArg,
/// Module imported from WebAssembly
WasmImportModule,
/// The library kind wasn't specified, `Dylib` is currently used as a default.
Unspecified,
}
impl NativeLibKind {
pub fn has_modifiers(&self) -> bool {
match self {
NativeLibKind::Static { bundle, whole_archive } => {
bundle.is_some() || whole_archive.is_some()
}
NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => {
as_needed.is_some()
}
NativeLibKind::RawDylib
| NativeLibKind::Unspecified
| NativeLibKind::LinkArg
| NativeLibKind::WasmImportModule => false,
}
}
pub fn is_statically_included(&self) -> bool {
matches!(self, NativeLibKind::Static { .. })
}
pub fn is_dllimport(&self) -> bool {
matches!(
self,
NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified
)
}
}
#[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
pub struct LinkEntry {
pub span: Span,
pub kind: NativeLibKind,
pub name: Symbol,
pub cfg: Option<CfgEntry>,
pub verbatim: Option<bool>,
pub import_name_type: Option<(PeImportNameType, Span)>,
}
/// Represents parsed *built-in* inert attributes.
///
/// ## Overview
@ -418,6 +532,9 @@ pub enum AttributeKind {
/// Represents `#[inline]` and `#[rustc_force_inline]`.
Inline(InlineAttr, Span),
/// Represents `#[link]`.
Link(ThinVec<LinkEntry>, Span),
/// Represents `#[link_name]`.
LinkName { name: Symbol, span: Span },

View file

@ -50,6 +50,7 @@ impl AttributeKind {
Fundamental { .. } => Yes,
Ignore { .. } => No,
Inline(..) => No,
Link(..) => No,
LinkName { .. } => Yes, // Needed for rustdoc
LinkOrdinal { .. } => No,
LinkSection { .. } => Yes, // Needed for rustdoc

View file

@ -9,7 +9,7 @@ doctest = false
[dependencies]
# tidy-alphabetical-start
itertools = "0.12"
itertools.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
@ -29,5 +29,5 @@ rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
tracing.workspace = true
# tidy-alphabetical-end

View file

@ -202,14 +202,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
Some((normalized_ty, ocx.into_pending_obligations()))
}
/// Returns the final type we ended up with, which may be an inference
/// variable (we will resolve it first, if we want).
pub fn final_ty(&self, resolve: bool) -> Ty<'tcx> {
if resolve {
self.infcx.resolve_vars_if_possible(self.state.cur_ty)
} else {
self.state.cur_ty
}
/// Returns the final type we ended up with, which may be an unresolved
/// inference variable.
pub fn final_ty(&self) -> Ty<'tcx> {
self.state.cur_ty
}
pub fn step_count(&self) -> usize {

View file

@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
itertools = "0.12"
itertools.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
@ -25,5 +25,5 @@ rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
tracing.workspace = true
# tidy-alphabetical-end

View file

@ -42,7 +42,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut obligations = PredicateObligations::new();
let targets =
steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false)));
steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty()));
let steps: Vec<_> = steps
.iter()
.map(|&(source, kind)| {

View file

@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef);
}
match autoderef.final_ty(false).kind() {
match autoderef.final_ty().kind() {
ty::FnDef(def_id, _) => {
let abi = self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi;
self.check_call_abi(abi, call_expr.span);
@ -200,8 +200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs: &'tcx [hir::Expr<'tcx>],
autoderef: &Autoderef<'a, 'tcx>,
) -> Option<CallStep<'tcx>> {
let adjusted_ty =
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty());
// If the callee is a function pointer or a closure, then we're all set.
match *adjusted_ty.kind() {

View file

@ -2918,7 +2918,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Emits an error if we deref an infer variable, like calling `.field` on a base type
// of `&_`. We can also use this to suppress unnecessary "missing field" errors that
// will follow ambiguity errors.
let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty());
if let ty::Error(_) = final_ty.kind() {
return final_ty;
}

View file

@ -629,7 +629,7 @@ pub(crate) fn method_autoderef_steps<'tcx>(
.collect();
(steps, autoderef_via_deref.reached_recursion_limit())
};
let final_ty = autoderef_via_deref.final_ty(true);
let final_ty = autoderef_via_deref.final_ty();
let opt_bad_ty = match final_ty.kind() {
ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
reached_raw_pointer,

View file

@ -109,8 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
index_ty: Ty<'tcx>,
index_expr: &hir::Expr<'_>,
) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> {
let adjusted_ty =
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty());
debug!(
"try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \
index_ty={:?})",

View file

@ -19,6 +19,6 @@ rustc_middle = { path = "../rustc_middle" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
thin-vec = "0.2.12"
tracing = "0.1"
thin-vec.workspace = true
tracing.workspace = true
# tidy-alphabetical-end

View file

@ -8,8 +8,8 @@ proc-macro = true
[dependencies]
# tidy-alphabetical-start
proc-macro2 = "1"
quote = "1"
proc-macro2.workspace = true
quote.workspace = true
syn = { version = "2.0.9", features = ["full", "extra-traits"] }
# tidy-alphabetical-end

View file

@ -18,6 +18,6 @@ rustc_middle = { path = "../rustc_middle" }
rustc_span = { path = "../rustc_span" }
rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
thin-vec = "0.2.12"
tracing = "0.1"
thin-vec.workspace = true
tracing.workspace = true
# tidy-alphabetical-end

View file

@ -46,7 +46,7 @@ rustc_thread_pool = { path = "../rustc_thread_pool" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_traits = { path = "../rustc_traits" }
rustc_ty_utils = { path = "../rustc_ty_utils" }
tracing = "0.1"
tracing.workspace = true
# tidy-alphabetical-end
[dev-dependencies]

View file

@ -8,6 +8,7 @@ use rustc_abi::Align;
use rustc_data_structures::profiling::TimePassesFormat;
use rustc_errors::emitter::HumanReadableErrorType;
use rustc_errors::{ColorConfig, registry};
use rustc_hir::attrs::NativeLibKind;
use rustc_session::config::{
AutoDiff, BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel,
CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation,
@ -20,7 +21,7 @@ use rustc_session::config::{
};
use rustc_session::lint::Level;
use rustc_session::search_paths::SearchPath;
use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
use rustc_session::utils::{CanonicalizedPath, NativeLib};
use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, build_session, getopts};
use rustc_span::edition::{DEFAULT_EDITION, Edition};
use rustc_span::source_map::{RealFileLoader, SourceMapInputs};

View file

@ -14,13 +14,9 @@ Rust lexer used by rustc. No stability guarantees are provided.
# Note that this crate purposefully does not depend on other rustc crates
[dependencies]
memchr = "2.7.4"
memchr.workspace = true
unicode-properties = { version = "0.1.0", default-features = false, features = ["emoji"] }
unicode-xid = "0.2.0"
[dependencies.unicode-properties]
version = "0.1.0"
default-features = false
features = ["emoji"]
[dev-dependencies]
expect-test = "1.4.0"

View file

@ -24,6 +24,6 @@ rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
tracing.workspace = true
unicode-security = "0.1.0"
# tidy-alphabetical-end

View file

@ -1554,7 +1554,7 @@ impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> {
#[help(lint_help_exposed_provenance)]
pub(crate) struct IntegerToPtrTransmutes<'tcx> {
#[subdiagnostic]
pub suggestion: IntegerToPtrTransmutesSuggestion<'tcx>,
pub suggestion: Option<IntegerToPtrTransmutesSuggestion<'tcx>>,
}
#[derive(Subdiagnostic)]

View file

@ -169,19 +169,25 @@ fn check_int_to_ptr_transmute<'tcx>(
expr.hir_id,
expr.span,
IntegerToPtrTransmutes {
suggestion: if dst.is_ref() {
IntegerToPtrTransmutesSuggestion::ToRef {
dst: *inner_ty,
suffix,
ref_mutbl: mutbl.prefix_str(),
start_call: expr.span.shrink_to_lo().until(arg.span),
}
suggestion: if layout_inner_ty.is_sized() {
Some(if dst.is_ref() {
IntegerToPtrTransmutesSuggestion::ToRef {
dst: *inner_ty,
suffix,
ref_mutbl: mutbl.prefix_str(),
start_call: expr.span.shrink_to_lo().until(arg.span),
}
} else {
IntegerToPtrTransmutesSuggestion::ToPtr {
dst: *inner_ty,
suffix,
start_call: expr.span.shrink_to_lo().until(arg.span),
}
})
} else {
IntegerToPtrTransmutesSuggestion::ToPtr {
dst: *inner_ty,
suffix,
start_call: expr.span.shrink_to_lo().until(arg.span),
}
// We can't suggest using `with_exposed_provenance` for unsized type
// so don't suggest anything.
None
},
},
);

View file

@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
libc = "0.2.73"
libc.workspace = true
# tidy-alphabetical-end
[build-dependencies]

View file

@ -1226,12 +1226,6 @@ extern "C" void LLVMRustPrintPasses() {
extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
size_t Len) {
auto PreserveFunctions = [=](const GlobalValue &GV) {
// Preserve LLVM-injected, ASAN-related symbols.
// See also https://github.com/rust-lang/rust/issues/113404.
if (GV.getName() == "___asan_globals_registered") {
return true;
}
// Preserve symbols exported from Rust modules.
for (size_t I = 0; I < Len; I++) {
if (GV.getName() == Symbols[I]) {

View file

@ -242,7 +242,7 @@ enum class LLVMRustAttributeKind {
MinSize = 4,
Naked = 5,
NoAlias = 6,
NoCapture = 7,
CapturesAddress = 7,
NoInline = 8,
NonNull = 9,
NoRedZone = 10,
@ -297,12 +297,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
return Attribute::Naked;
case LLVMRustAttributeKind::NoAlias:
return Attribute::NoAlias;
case LLVMRustAttributeKind::NoCapture:
#if LLVM_VERSION_GE(21, 0)
report_fatal_error("NoCapture doesn't exist in LLVM 21");
#else
return Attribute::NoCapture;
#endif
case LLVMRustAttributeKind::NoCfCheck:
return Attribute::NoCfCheck;
case LLVMRustAttributeKind::NoInline:
@ -377,6 +371,7 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
#else
report_fatal_error("DeadOnReturn attribute requires LLVM 21 or later");
#endif
case LLVMRustAttributeKind::CapturesAddress:
case LLVMRustAttributeKind::CapturesReadOnly:
report_fatal_error("Should be handled separately");
}
@ -429,9 +424,9 @@ extern "C" void LLVMRustEraseInstFromParent(LLVMValueRef Instr) {
extern "C" LLVMAttributeRef
LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) {
#if LLVM_VERSION_GE(21, 0)
// LLVM 21 replaced the NoCapture attribute with Captures(none).
if (RustAttr == LLVMRustAttributeKind::NoCapture) {
return wrap(Attribute::getWithCaptureInfo(*unwrap(C), CaptureInfo::none()));
if (RustAttr == LLVMRustAttributeKind::CapturesAddress) {
return wrap(Attribute::getWithCaptureInfo(
*unwrap(C), CaptureInfo(CaptureComponents::Address)));
}
if (RustAttr == LLVMRustAttributeKind::CapturesReadOnly) {
return wrap(Attribute::getWithCaptureInfo(

View file

@ -5,10 +5,10 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
tracing = "0.1.28"
tracing-core = "=0.1.30" # FIXME(Nilstrieb) tracing has a deadlock: https://github.com/tokio-rs/tracing/issues/2635
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
tracing-tree = "0.3.1"
tracing.workspace = true
# tidy-alphabetical-end
[features]

View file

@ -8,8 +8,8 @@ proc-macro = true
[dependencies]
# tidy-alphabetical-start
proc-macro2 = "1"
quote = "1"
proc-macro2.workspace = true
quote.workspace = true
syn = { version = "2.0.9", features = ["full"] }
synstructure = "0.13.0"
# tidy-alphabetical-end

View file

@ -5,9 +5,9 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
bitflags.workspace = true
libloading = "0.8.0"
odht = { version = "0.3.1", features = ["nightly"] }
odht.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
@ -30,11 +30,11 @@ rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
tempfile = "3.7.1"
tracing = "0.1"
tempfile.workspace = true
tracing.workspace = true
# tidy-alphabetical-end
[target.'cfg(target_os = "aix")'.dependencies]
# tidy-alphabetical-start
libc = "0.2"
libc.workspace = true
# tidy-alphabetical-end

View file

@ -1,6 +1,3 @@
metadata_as_needed_compatibility =
linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
metadata_async_drop_types_in_dependency =
found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}`
.help = if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used
@ -11,9 +8,6 @@ metadata_bad_panic_strategy =
metadata_binary_output_to_tty =
option `-o` or `--emit` is used to write binary output type `metadata` to stdout, but stdout is a tty
metadata_bundle_needs_static =
linking modifier `bundle` is only compatible with `static` linking kind
metadata_cannot_find_crate =
can't find crate for `{$crate_name}`{$add_info}
@ -60,10 +54,6 @@ metadata_crate_not_panic_runtime =
metadata_dl_error =
{$path}{$err}
metadata_empty_link_name =
link name must not be empty
.label = empty link name
metadata_empty_renaming_target =
an empty renaming target was specified for library `{$lib_name}`
@ -108,15 +98,6 @@ metadata_full_metadata_not_found =
metadata_global_alloc_required =
no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
metadata_import_name_type_form =
import name type must be of the form `import_name_type = "string"`
metadata_import_name_type_raw =
import name type can only be used with link kind `raw-dylib`
metadata_import_name_type_x86 =
import name type is only supported on x86
metadata_incompatible_panic_in_drop_strategy =
the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
@ -143,15 +124,10 @@ metadata_incompatible_target_modifiers_r_missed =
mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
.note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}`
.help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
metadata_incompatible_wasm_link =
`wasm_import_module` is incompatible with other arguments in `#[link]` attributes
metadata_install_missing_components =
maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
metadata_invalid_link_modifier =
invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
metadata_invalid_meta_files =
found invalid metadata files for crate `{$crate_name}`{$add_info}
@ -164,67 +140,18 @@ metadata_lib_framework_apple =
metadata_lib_required =
crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
metadata_link_arg_unstable =
link kind `link-arg` is unstable
metadata_link_cfg_form =
link cfg must be of the form `cfg(/* predicate */)`
metadata_link_cfg_single_predicate =
link cfg must have a single predicate argument
metadata_link_cfg_unstable =
link cfg is unstable
metadata_link_framework_apple =
link kind `framework` is only supported on Apple targets
metadata_link_kind_form =
link kind must be of the form `kind = "string"`
metadata_link_modifiers_form =
link modifiers must be of the form `modifiers = "string"`
metadata_link_name_form =
link name must be of the form `name = "string"`
metadata_link_ordinal_raw_dylib =
`#[link_ordinal]` is only supported if link kind is `raw-dylib`
metadata_link_requires_name =
`#[link]` attribute requires a `name = "string"` argument
.label = missing `name` argument
metadata_missing_native_library =
could not find native static library `{$libname}`, perhaps an -L flag is missing?
metadata_multiple_candidates =
multiple candidates for `{$flavor}` dependency `{$crate_name}` found
metadata_multiple_cfgs =
multiple `cfg` arguments in a single `#[link]` attribute
metadata_multiple_import_name_type =
multiple `import_name_type` arguments in a single `#[link]` attribute
metadata_multiple_kinds_in_link =
multiple `kind` arguments in a single `#[link]` attribute
metadata_multiple_link_modifiers =
multiple `modifiers` arguments in a single `#[link]` attribute
metadata_multiple_modifiers =
multiple `{$modifier}` modifiers in a single `modifiers` argument
metadata_multiple_names_in_link =
multiple `name` arguments in a single `#[link]` attribute
metadata_multiple_renamings =
multiple renamings were specified for library `{$lib_name}`
metadata_multiple_wasm_import =
multiple `wasm_import_module` arguments in a single `#[link]` attribute
metadata_newer_crate_version =
found possibly newer version of crate `{$crate_name}`{$add_info}
.note = perhaps that crate needs to be recompiled?
@ -263,15 +190,6 @@ metadata_prev_alloc_error_handler =
metadata_prev_global_alloc =
previous global allocator defined here
metadata_raw_dylib_elf_unstable =
link kind `raw-dylib` is unstable on ELF platforms
metadata_raw_dylib_no_nul =
link name must not contain NUL characters if link kind is `raw-dylib`
metadata_raw_dylib_only_windows =
link kind `raw-dylib` is only supported on Windows targets
metadata_raw_dylib_unsupported_abi =
ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
@ -307,19 +225,6 @@ metadata_target_not_installed =
metadata_two_panic_runtimes =
cannot link together two panic runtimes: {$prev_name} and {$cur_name}
metadata_unexpected_link_arg =
unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
metadata_unknown_import_name_type =
unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated
metadata_unknown_link_kind =
unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib, link-arg
.label = unknown link kind
metadata_unknown_link_modifier =
unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
metadata_unknown_target_modifier_unsafe_allowed = unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}`
metadata_wasm_c_abi =

View file

@ -83,187 +83,6 @@ pub struct IncompatiblePanicInDropStrategy {
pub desired_strategy: PanicStrategy,
}
#[derive(Diagnostic)]
#[diag(metadata_multiple_names_in_link)]
pub struct MultipleNamesInLink {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_multiple_kinds_in_link)]
pub struct MultipleKindsInLink {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_link_name_form)]
pub struct LinkNameForm {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_link_kind_form)]
pub struct LinkKindForm {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_link_modifiers_form)]
pub struct LinkModifiersForm {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_link_cfg_form)]
pub struct LinkCfgForm {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_wasm_import_form)]
pub struct WasmImportForm {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_empty_link_name, code = E0454)]
pub struct EmptyLinkName {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_link_framework_apple, code = E0455)]
pub struct LinkFrameworkApple {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_raw_dylib_only_windows, code = E0455)]
pub struct RawDylibOnlyWindows {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_unknown_link_kind, code = E0458)]
pub struct UnknownLinkKind<'a> {
#[primary_span]
#[label]
pub span: Span,
pub kind: &'a str,
}
#[derive(Diagnostic)]
#[diag(metadata_multiple_link_modifiers)]
pub struct MultipleLinkModifiers {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_multiple_cfgs)]
pub struct MultipleCfgs {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_link_cfg_single_predicate)]
pub struct LinkCfgSinglePredicate {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_multiple_wasm_import)]
pub struct MultipleWasmImport {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_unexpected_link_arg)]
pub struct UnexpectedLinkArg {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_invalid_link_modifier)]
pub struct InvalidLinkModifier {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_multiple_modifiers)]
pub struct MultipleModifiers<'a> {
#[primary_span]
pub span: Span,
pub modifier: &'a str,
}
#[derive(Diagnostic)]
#[diag(metadata_bundle_needs_static)]
pub struct BundleNeedsStatic {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_whole_archive_needs_static)]
pub struct WholeArchiveNeedsStatic {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_as_needed_compatibility)]
pub struct AsNeededCompatibility {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_unknown_link_modifier)]
pub struct UnknownLinkModifier<'a> {
#[primary_span]
pub span: Span,
pub modifier: &'a str,
}
#[derive(Diagnostic)]
#[diag(metadata_incompatible_wasm_link)]
pub struct IncompatibleWasmLink {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_link_requires_name, code = E0459)]
pub struct LinkRequiresName {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_raw_dylib_no_nul)]
pub struct RawDylibNoNul {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_link_ordinal_raw_dylib)]
pub struct LinkOrdinalRawDylib {
@ -706,42 +525,6 @@ pub struct LibFilenameForm<'a> {
pub dll_suffix: &'a str,
}
#[derive(Diagnostic)]
#[diag(metadata_multiple_import_name_type)]
pub struct MultipleImportNameType {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_import_name_type_form)]
pub struct ImportNameTypeForm {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_import_name_type_x86)]
pub struct ImportNameTypeX86 {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_unknown_import_name_type)]
pub struct UnknownImportNameType<'a> {
#[primary_span]
pub span: Span,
pub import_name_type: &'a str,
}
#[derive(Diagnostic)]
#[diag(metadata_import_name_type_raw)]
pub struct ImportNameTypeRaw {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(metadata_wasm_c_abi)]
pub(crate) struct WasmCAbi {

View file

@ -3,25 +3,21 @@ use std::path::{Path, PathBuf};
use rustc_abi::ExternAbi;
use rustc_ast::CRATE_NODE_ID;
use rustc_attr_parsing as attr;
use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::attrs::{AttributeKind, NativeLibKind, PeImportNameType};
use rustc_hir::find_attr;
use rustc_middle::query::LocalCrate;
use rustc_middle::ty::{self, List, Ty, TyCtxt};
use rustc_session::Session;
use rustc_session::config::CrateType;
use rustc_session::cstore::{
DllCallingConvention, DllImport, ForeignModule, NativeLib, PeImportNameType,
};
use rustc_session::parse::feature_err;
use rustc_session::cstore::{DllCallingConvention, DllImport, ForeignModule, NativeLib};
use rustc_session::search_paths::PathKind;
use rustc_session::utils::NativeLibKind;
use rustc_span::Symbol;
use rustc_span::def_id::{DefId, LOCAL_CRATE};
use rustc_span::{Symbol, sym};
use rustc_target::spec::{BinaryFormat, LinkSelfContainedComponents};
use crate::{errors, fluent_generated};
use crate::errors;
/// The fallback directories are passed to linker, but not used when rustc does the search,
/// because in the latter case the set of fallback directories cannot always be determined
@ -192,7 +188,9 @@ pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib>
pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
match lib.cfg {
Some(ref cfg) => attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
Some(ref cfg) => {
eval_config_entry(sess, cfg, CRATE_NODE_ID, None, ShouldEmit::ErrorsAndLints).as_bool()
}
None => true,
}
}
@ -213,289 +211,23 @@ impl<'tcx> Collector<'tcx> {
return;
}
// Process all of the #[link(..)]-style arguments
let features = self.tcx.features();
for m in self.tcx.get_attrs(def_id, sym::link) {
let Some(items) = m.meta_item_list() else {
continue;
};
let mut name = None;
let mut kind = None;
let mut modifiers = None;
let mut cfg = None;
let mut wasm_import_module = None;
let mut import_name_type = None;
for item in items.iter() {
match item.name() {
Some(sym::name) => {
if name.is_some() {
sess.dcx().emit_err(errors::MultipleNamesInLink { span: item.span() });
continue;
}
let Some(link_name) = item.value_str() else {
sess.dcx().emit_err(errors::LinkNameForm { span: item.span() });
continue;
};
let span = item.name_value_literal_span().unwrap();
if link_name.is_empty() {
sess.dcx().emit_err(errors::EmptyLinkName { span });
}
name = Some((link_name, span));
}
Some(sym::kind) => {
if kind.is_some() {
sess.dcx().emit_err(errors::MultipleKindsInLink { span: item.span() });
continue;
}
let Some(link_kind) = item.value_str() else {
sess.dcx().emit_err(errors::LinkKindForm { span: item.span() });
continue;
};
let span = item.name_value_literal_span().unwrap();
let link_kind = match link_kind.as_str() {
"static" => NativeLibKind::Static { bundle: None, whole_archive: None },
"dylib" => NativeLibKind::Dylib { as_needed: None },
"framework" => {
if !sess.target.is_like_darwin {
sess.dcx().emit_err(errors::LinkFrameworkApple { span });
}
NativeLibKind::Framework { as_needed: None }
}
"raw-dylib" => {
if sess.target.is_like_windows {
// raw-dylib is stable and working on Windows
} else if sess.target.binary_format == BinaryFormat::Elf
&& features.raw_dylib_elf()
{
// raw-dylib is unstable on ELF, but the user opted in
} else if sess.target.binary_format == BinaryFormat::Elf
&& sess.is_nightly_build()
{
feature_err(
sess,
sym::raw_dylib_elf,
span,
fluent_generated::metadata_raw_dylib_elf_unstable,
)
.emit();
} else {
sess.dcx().emit_err(errors::RawDylibOnlyWindows { span });
}
NativeLibKind::RawDylib
}
"link-arg" => {
if !features.link_arg_attribute() {
feature_err(
sess,
sym::link_arg_attribute,
span,
fluent_generated::metadata_link_arg_unstable,
)
.emit();
}
NativeLibKind::LinkArg
}
kind => {
sess.dcx().emit_err(errors::UnknownLinkKind { span, kind });
continue;
}
};
kind = Some(link_kind);
}
Some(sym::modifiers) => {
if modifiers.is_some() {
sess.dcx()
.emit_err(errors::MultipleLinkModifiers { span: item.span() });
continue;
}
let Some(link_modifiers) = item.value_str() else {
sess.dcx().emit_err(errors::LinkModifiersForm { span: item.span() });
continue;
};
modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
}
Some(sym::cfg) => {
if cfg.is_some() {
sess.dcx().emit_err(errors::MultipleCfgs { span: item.span() });
continue;
}
let Some(link_cfg) = item.meta_item_list() else {
sess.dcx().emit_err(errors::LinkCfgForm { span: item.span() });
continue;
};
let [link_cfg] = link_cfg else {
sess.dcx()
.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
continue;
};
let Some(link_cfg) = link_cfg.meta_item_or_bool() else {
sess.dcx()
.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
continue;
};
if !features.link_cfg() {
feature_err(
sess,
sym::link_cfg,
item.span(),
fluent_generated::metadata_link_cfg_unstable,
)
.emit();
}
cfg = Some(link_cfg.clone());
}
Some(sym::wasm_import_module) => {
if wasm_import_module.is_some() {
sess.dcx().emit_err(errors::MultipleWasmImport { span: item.span() });
continue;
}
let Some(link_wasm_import_module) = item.value_str() else {
sess.dcx().emit_err(errors::WasmImportForm { span: item.span() });
continue;
};
wasm_import_module = Some((link_wasm_import_module, item.span()));
}
Some(sym::import_name_type) => {
if import_name_type.is_some() {
sess.dcx()
.emit_err(errors::MultipleImportNameType { span: item.span() });
continue;
}
let Some(link_import_name_type) = item.value_str() else {
sess.dcx().emit_err(errors::ImportNameTypeForm { span: item.span() });
continue;
};
if self.tcx.sess.target.arch != "x86" {
sess.dcx().emit_err(errors::ImportNameTypeX86 { span: item.span() });
continue;
}
let link_import_name_type = match link_import_name_type.as_str() {
"decorated" => PeImportNameType::Decorated,
"noprefix" => PeImportNameType::NoPrefix,
"undecorated" => PeImportNameType::Undecorated,
import_name_type => {
sess.dcx().emit_err(errors::UnknownImportNameType {
span: item.span(),
import_name_type,
});
continue;
}
};
import_name_type = Some((link_import_name_type, item.span()));
}
_ => {
sess.dcx().emit_err(errors::UnexpectedLinkArg { span: item.span() });
}
}
}
// Do this outside the above loop so we don't depend on modifiers coming after kinds
let mut verbatim = None;
if let Some((modifiers, span)) = modifiers {
for modifier in modifiers.as_str().split(',') {
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
Some(m) => (m, modifier.starts_with('+')),
None => {
sess.dcx().emit_err(errors::InvalidLinkModifier { span });
continue;
}
};
macro report_unstable_modifier($feature: ident) {
if !features.$feature() {
// FIXME: make this translatable
#[expect(rustc::untranslatable_diagnostic)]
feature_err(
sess,
sym::$feature,
span,
format!("linking modifier `{modifier}` is unstable"),
)
.emit();
}
}
let assign_modifier = |dst: &mut Option<bool>| {
if dst.is_some() {
sess.dcx().emit_err(errors::MultipleModifiers { span, modifier });
} else {
*dst = Some(value);
}
};
match (modifier, &mut kind) {
("bundle", Some(NativeLibKind::Static { bundle, .. })) => {
assign_modifier(bundle)
}
("bundle", _) => {
sess.dcx().emit_err(errors::BundleNeedsStatic { span });
}
("verbatim", _) => assign_modifier(&mut verbatim),
("whole-archive", Some(NativeLibKind::Static { whole_archive, .. })) => {
assign_modifier(whole_archive)
}
("whole-archive", _) => {
sess.dcx().emit_err(errors::WholeArchiveNeedsStatic { span });
}
("as-needed", Some(NativeLibKind::Dylib { as_needed }))
| ("as-needed", Some(NativeLibKind::Framework { as_needed })) => {
report_unstable_modifier!(native_link_modifiers_as_needed);
assign_modifier(as_needed)
}
("as-needed", _) => {
sess.dcx().emit_err(errors::AsNeededCompatibility { span });
}
_ => {
sess.dcx().emit_err(errors::UnknownLinkModifier { span, modifier });
}
}
}
}
if let Some((_, span)) = wasm_import_module {
if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
sess.dcx().emit_err(errors::IncompatibleWasmLink { span });
}
}
if wasm_import_module.is_some() {
(name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule));
}
let Some((name, name_span)) = name else {
sess.dcx().emit_err(errors::LinkRequiresName { span: m.span() });
continue;
};
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
if let Some((_, span)) = import_name_type {
if kind != Some(NativeLibKind::RawDylib) {
sess.dcx().emit_err(errors::ImportNameTypeRaw { span });
}
}
let dll_imports = match kind {
Some(NativeLibKind::RawDylib) => {
if name.as_str().contains('\0') {
sess.dcx().emit_err(errors::RawDylibNoNul { span: name_span });
}
foreign_items
.iter()
.map(|&child_item| {
self.build_dll_import(
abi,
import_name_type.map(|(import_name_type, _)| import_name_type),
child_item,
)
})
.collect()
}
for attr in
find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::Link(links, _) => links)
.iter()
.map(|v| v.iter())
.flatten()
{
let dll_imports = match attr.kind {
NativeLibKind::RawDylib => foreign_items
.iter()
.map(|&child_item| {
self.build_dll_import(
abi,
attr.import_name_type.map(|(import_name_type, _)| import_name_type),
child_item,
)
})
.collect(),
_ => {
for &child_item in foreign_items {
if let Some(span) = find_attr!(self.tcx.get_all_attrs(child_item), AttributeKind::LinkOrdinal {span, ..} => *span)
@ -508,15 +240,20 @@ impl<'tcx> Collector<'tcx> {
}
};
let kind = kind.unwrap_or(NativeLibKind::Unspecified);
let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), self.tcx);
let filename = find_bundled_library(
attr.name,
attr.verbatim,
attr.kind,
attr.cfg.is_some(),
self.tcx,
);
self.libs.push(NativeLib {
name,
name: attr.name,
filename,
kind,
cfg,
kind: attr.kind,
cfg: attr.cfg.clone(),
foreign_module: Some(def_id.to_def_id()),
verbatim,
verbatim: attr.verbatim,
dll_imports,
});
}

View file

@ -5,12 +5,12 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
either = "1.5.0"
bitflags.workspace = true
either.workspace = true
gsgdt = "0.1.2"
polonius-engine = "0.13.0"
polonius-engine.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_apfloat = "0.2.0"
rustc_apfloat.workspace = true
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_ir = { path = "../rustc_ast_ir" }
@ -34,8 +34,8 @@ rustc_target = { path = "../rustc_target" }
rustc_thread_pool = { path = "../rustc_thread_pool" }
rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
thin-vec = "0.2.12"
tracing = "0.1"
thin-vec.workspace = true
tracing.workspace = true
# tidy-alphabetical-end
[features]

View file

@ -29,6 +29,7 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::direct_use_of_rustc_type_ir)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(round_char_boundary))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(allocator_api)]
@ -51,7 +52,6 @@
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(ptr_alignment_type)]
#![feature(round_char_boundary)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
#![feature(sized_hierarchy)]

View file

@ -149,8 +149,15 @@ pub enum ConstraintCategory<'tcx> {
/// A constraint that doesn't correspond to anything the user sees.
Internal,
/// An internal constraint derived from an illegal universe relation.
IllegalUniverse,
/// An internal constraint added when a region outlives a placeholder
/// it cannot name and therefore has to outlive `'static`. The argument
/// is the unnameable placeholder and the constraint is always between
/// an SCC representative and `'static`.
OutlivesUnnameablePlaceholder(
#[type_foldable(identity)]
#[type_visitable(ignore)]
ty::RegionVid,
),
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]

View file

@ -5,9 +5,9 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
itertools = "0.12"
itertools.workspace = true
rustc_abi = { path = "../rustc_abi" }
rustc_apfloat = "0.2.0"
rustc_apfloat.workspace = true
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
@ -23,5 +23,5 @@ rustc_pattern_analysis = { path = "../rustc_pattern_analysis" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
tracing = "0.1"
tracing.workspace = true
# tidy-alphabetical-end

Some files were not shown because too many files have changed in this diff Show more