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:
commit
d269d234e0
493 changed files with 5851 additions and 4268 deletions
1
.mailmap
1
.mailmap
|
|
@ -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>
|
||||
|
|
|
|||
237
Cargo.lock
237
Cargo.lock
|
|
@ -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]]
|
||||
|
|
|
|||
27
Cargo.toml
27
Cargo.toml
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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<
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
// @generated
|
||||
impl_any_provider!(BakedDataProvider);
|
||||
71
compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data
Normal file
71
compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -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;
|
||||
|
|
@ -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)) }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -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)) }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ pub(crate) enum AttributeKind {
|
|||
MinSize = 4,
|
||||
Naked = 5,
|
||||
NoAlias = 6,
|
||||
NoCapture = 7,
|
||||
CapturesAddress = 7,
|
||||
NoInline = 8,
|
||||
NonNull = 9,
|
||||
NoRedZone = 10,
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
tempfile = "3.7.1"
|
||||
tempfile.workspace = true
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)| {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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={:?})",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
},
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
libc = "0.2.73"
|
||||
libc.workspace = true
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
|||
|
|
@ -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]) {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue