commit
391a2ea868
2078 changed files with 77161 additions and 38957 deletions
1
.mailmap
1
.mailmap
|
|
@ -609,6 +609,7 @@ Shohei Wada <pc@wada314.jp>
|
|||
Shotaro Yamada <sinkuu@sinkuu.xyz>
|
||||
Shotaro Yamada <sinkuu@sinkuu.xyz> <sinkuu@users.noreply.github.com>
|
||||
Shyam Sundar B <shyambaskaran@outlook.com>
|
||||
Sidney Cammeresi <sac@cheesecake.org> <sac@readyset.io>
|
||||
Simon Barber-Dueck <sbarberdueck@gmail.com> Simon BD <simon@server>
|
||||
Simon Sapin <simon@exyr.org> <simon.sapin@exyr.org>
|
||||
Simonas Kazlauskas <git@kazlauskas.me> Simonas Kazlauskas <github@kazlauskas.me>
|
||||
|
|
|
|||
262
Cargo.lock
262
Cargo.lock
|
|
@ -568,7 +568,7 @@ checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
|||
|
||||
[[package]]
|
||||
name = "clippy"
|
||||
version = "0.1.91"
|
||||
version = "0.1.92"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"askama",
|
||||
|
|
@ -595,7 +595,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clippy_config"
|
||||
version = "0.1.91"
|
||||
version = "0.1.92"
|
||||
dependencies = [
|
||||
"clippy_utils",
|
||||
"itertools",
|
||||
|
|
@ -618,7 +618,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clippy_lints"
|
||||
version = "0.1.91"
|
||||
version = "0.1.92"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"cargo_metadata 0.18.1",
|
||||
|
|
@ -649,7 +649,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clippy_utils"
|
||||
version = "0.1.91"
|
||||
version = "0.1.92"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"itertools",
|
||||
|
|
@ -937,23 +937,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.168"
|
||||
version = "1.0.185"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7aa144b12f11741f0dab5b4182896afad46faa0598b6a061f7b9d17a21837ba7"
|
||||
checksum = "2f81de88da10862f22b5b3a60f18f6f42bbe7cb8faa24845dd7b1e4e22190e77"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxx-build",
|
||||
"cxxbridge-cmd",
|
||||
"cxxbridge-flags",
|
||||
"cxxbridge-macro",
|
||||
"foldhash",
|
||||
"foldhash 0.2.0",
|
||||
"link-cplusplus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.168"
|
||||
version = "1.0.185"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12d3cbb84fb003242941c231b45ca9417e786e66e94baa39584bd99df3a270b6"
|
||||
checksum = "5edd58bf75c3fdfc80d79806403af626570662f7b6cc782a7fabe156166bd6d6"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
|
|
@ -966,9 +967,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cxxbridge-cmd"
|
||||
version = "1.0.168"
|
||||
version = "1.0.185"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fa36b7b249d43f67a3f54bd65788e35e7afe64bbc671396387a48b3e8aaea94"
|
||||
checksum = "fd46bf2b541a4e0c2d5abba76607379ee05d68e714868e3cb406dc8d591ce2d2"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"codespan-reporting",
|
||||
|
|
@ -980,15 +981,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.168"
|
||||
version = "1.0.185"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77707c70f6563edc5429618ca34a07241b75ebab35bd01d46697c75d58f8ddfe"
|
||||
checksum = "2c79b68f6a3a8f809d39b38ae8af61305a6113819b19b262643b9c21353b92d9"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.168"
|
||||
version = "1.0.185"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ede6c0fb7e318f0a11799b86ee29dcf17b9be2960bd379a6c38e1a96a6010fff"
|
||||
checksum = "862b7fdb048ff9ef0779a0d0a03affd09746c4c875543746b640756be9cff2af"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"proc-macro2",
|
||||
|
|
@ -1051,7 +1052,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "declare_clippy_lint"
|
||||
version = "0.1.91"
|
||||
version = "0.1.92"
|
||||
|
||||
[[package]]
|
||||
name = "derive-where"
|
||||
|
|
@ -1191,6 +1192,12 @@ version = "1.0.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921"
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
|
|
@ -1382,6 +1389,12 @@ version = "0.1.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.1"
|
||||
|
|
@ -1458,9 +1471,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.23"
|
||||
version = "0.2.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1"
|
||||
checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df"
|
||||
dependencies = [
|
||||
"unicode-width 0.2.1",
|
||||
]
|
||||
|
|
@ -1561,7 +1574,7 @@ checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
|||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
"foldhash",
|
||||
"foldhash 0.1.5",
|
||||
"serde",
|
||||
]
|
||||
|
||||
|
|
@ -2154,9 +2167,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.10"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a6f6da007f968f9def0d65a05b187e2960183de70c160204ecfccf0ee330212"
|
||||
checksum = "7f78c730aaa7d0b9336a299029ea49f9ee53b0ed06e9202e8cb7db9bae7b8c82"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
|
@ -2167,6 +2180,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"html5ever",
|
||||
"regex",
|
||||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2346,11 +2360,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "359f76430b20a79f9e20e115b3428614e654f04fab314482fc0fda0ebd3c6044"
|
||||
checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3121,6 +3135,26 @@ dependencies = [
|
|||
"thiserror 2.0.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ref-cast"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf"
|
||||
dependencies = [
|
||||
"ref-cast-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ref-cast-impl"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
|
|
@ -3248,6 +3282,7 @@ dependencies = [
|
|||
"rustc_driver_impl",
|
||||
"rustc_public",
|
||||
"rustc_public_bridge",
|
||||
"rustc_windows_rc",
|
||||
"tikv-jemalloc-sys",
|
||||
]
|
||||
|
||||
|
|
@ -3623,6 +3658,7 @@ name = "rustc_driver"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_driver_impl",
|
||||
"rustc_windows_rc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4206,6 +4242,7 @@ name = "rustc_mir_transform"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"either",
|
||||
"hashbrown",
|
||||
"itertools",
|
||||
"rustc_abi",
|
||||
"rustc_arena",
|
||||
|
|
@ -4409,7 +4446,6 @@ dependencies = [
|
|||
"rustc_middle",
|
||||
"rustc_query_system",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"tracing",
|
||||
]
|
||||
|
|
@ -4575,6 +4611,7 @@ dependencies = [
|
|||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
"rustc_span",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
|
|
@ -4681,6 +4718,7 @@ dependencies = [
|
|||
name = "rustc_type_ir"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"derive-where",
|
||||
"ena",
|
||||
|
|
@ -4718,6 +4756,13 @@ dependencies = [
|
|||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_windows_rc"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustdoc"
|
||||
version = "0.0.0"
|
||||
|
|
@ -4780,9 +4825,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustfix"
|
||||
version = "0.8.1"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81864b097046da5df3758fdc6e4822bbb70afa06317e8ca45ea1b51cb8c5e5a4"
|
||||
checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -4890,6 +4935,31 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schemars"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0"
|
||||
dependencies = [
|
||||
"dyn-clone",
|
||||
"ref-cast",
|
||||
"schemars_derive",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schemars_derive"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33d020396d1d138dc19f1165df7545479dcd58d93810dc5d646a16e55abefa80"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_derive_internals",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
|
|
@ -4964,6 +5034,17 @@ dependencies = [
|
|||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.29.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.142"
|
||||
|
|
@ -5518,11 +5599,10 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
|
|||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.37"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
|
|
@ -5825,6 +5905,12 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urlencoding"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
version = "0.7.6"
|
||||
|
|
@ -5969,9 +6055,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-component-ld"
|
||||
version = "0.5.16"
|
||||
version = "0.5.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14cd35d6cae91109a0ffd207b573cf3c741cab7e921dd376ea7aaf2c52a3408c"
|
||||
checksum = "1c9208f87cac2332fd80dcf36d54e9163d3446e28301e0c6e424984425738984"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
|
|
@ -5979,9 +6065,9 @@ dependencies = [
|
|||
"libc",
|
||||
"tempfile",
|
||||
"wasi-preview1-component-adapter-provider",
|
||||
"wasmparser 0.237.0",
|
||||
"wasmparser 0.239.0",
|
||||
"wat",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
"winsplit",
|
||||
"wit-component",
|
||||
"wit-parser",
|
||||
|
|
@ -6006,24 +6092,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-encoder"
|
||||
version = "0.237.0"
|
||||
version = "0.239.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efe92d1321afa53ffc88a57c497bb7330c3cf84c98ffdba4a4caf6a0684fad3c"
|
||||
checksum = "5be00faa2b4950c76fe618c409d2c3ea5a3c9422013e079482d78544bb2d184c"
|
||||
dependencies = [
|
||||
"leb128fmt",
|
||||
"wasmparser 0.237.0",
|
||||
"wasmparser 0.239.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-metadata"
|
||||
version = "0.237.0"
|
||||
version = "0.239.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cc0b0a0c4f35ca6efa7a797671372915d4e9659dba2d59edc6fafc931d19997"
|
||||
checksum = "20b3ec880a9ac69ccd92fbdbcf46ee833071cf09f82bb005b2327c7ae6025ae2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indexmap",
|
||||
"wasm-encoder 0.237.0",
|
||||
"wasmparser 0.237.0",
|
||||
"wasm-encoder 0.239.0",
|
||||
"wasmparser 0.239.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6048,9 +6134,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.237.0"
|
||||
version = "0.239.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d2a40ca0d2bdf4b0bf36c13a737d0b2c58e4c8aaefe1c57f336dd75369ca250"
|
||||
checksum = "8c9d90bb93e764f6beabf1d02028c70a2156a6583e63ac4218dd07ef733368b0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"hashbrown",
|
||||
|
|
@ -6061,22 +6147,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wast"
|
||||
version = "237.0.0"
|
||||
version = "239.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcf66f545acbd55082485cb9a6daab54579cb8628a027162253e8e9f5963c767"
|
||||
checksum = "9139176fe8a2590e0fb174cdcaf373b224cb93c3dde08e4297c1361d2ba1ea5d"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"leb128fmt",
|
||||
"memchr",
|
||||
"unicode-width 0.2.1",
|
||||
"wasm-encoder 0.237.0",
|
||||
"wasm-encoder 0.239.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wat"
|
||||
version = "1.237.0"
|
||||
version = "1.239.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27975186f549e4b8d6878b627be732863883c72f7bf4dcf8f96e5f8242f73da9"
|
||||
checksum = "3e1c941927d34709f255558166f8901a2005f8ab4a9650432e9281b7cc6f3b75"
|
||||
dependencies = [
|
||||
"wast",
|
||||
]
|
||||
|
|
@ -6299,15 +6385,6 @@ dependencies = [
|
|||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
|
|
@ -6335,21 +6412,6 @@ dependencies = [
|
|||
"windows-targets 0.53.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
|
|
@ -6392,12 +6454,6 @@ dependencies = [
|
|||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
|
|
@ -6410,12 +6466,6 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
|
|
@ -6428,12 +6478,6 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
|
|
@ -6458,12 +6502,6 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
|
|
@ -6476,12 +6514,6 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
|
|
@ -6494,12 +6526,6 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
|
|
@ -6512,12 +6538,6 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
|
|
@ -6565,9 +6585,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wit-component"
|
||||
version = "0.237.0"
|
||||
version = "0.239.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfb7674f76c10e82fe00b256a9d4ffb2b8d037d42ab8e9a83ebb3be35c9d0bf6"
|
||||
checksum = "88a866b19dba2c94d706ec58c92a4c62ab63e482b4c935d2a085ac94caecb136"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
|
|
@ -6576,17 +6596,17 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"wasm-encoder 0.237.0",
|
||||
"wasm-encoder 0.239.0",
|
||||
"wasm-metadata",
|
||||
"wasmparser 0.237.0",
|
||||
"wasmparser 0.239.0",
|
||||
"wit-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-parser"
|
||||
version = "0.237.0"
|
||||
version = "0.239.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce2596a5bc7c24cc965b56ad6ff9e32394c4e401764f89620a888519c6e849ab"
|
||||
checksum = "55c92c939d667b7bf0c6bf2d1f67196529758f99a2a45a3355cc56964fd5315d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"id-arena",
|
||||
|
|
@ -6597,7 +6617,7 @@ dependencies = [
|
|||
"serde_derive",
|
||||
"serde_json",
|
||||
"unicode-xid",
|
||||
"wasmparser 0.237.0",
|
||||
"wasmparser 0.239.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
126
RELEASES.md
126
RELEASES.md
|
|
@ -1,3 +1,129 @@
|
|||
Version 1.90.0 (2025-09-18)
|
||||
===========================
|
||||
|
||||
<a id="1.90-Language"></a>
|
||||
|
||||
Language
|
||||
--------
|
||||
- [Split up the `unknown_or_malformed_diagnostic_attributes` lint](https://github.com/rust-lang/rust/pull/140717). This lint has been split up into four finer-grained lints, with `unknown_or_malformed_diagnostic_attributes` now being the lint group that contains these lints:
|
||||
1. `unknown_diagnostic_attributes`: unknown to the current compiler
|
||||
2. `misplaced_diagnostic_attributes`: placed on the wrong item
|
||||
3. `malformed_diagnostic_attributes`: malformed attribute syntax or options
|
||||
4. `malformed_diagnostic_format_literals`: malformed format string literal
|
||||
- [Allow constants whose final value has references to mutable/external memory, but reject such constants as patterns](https://github.com/rust-lang/rust/pull/140942)
|
||||
- [Allow volatile access to non-Rust memory, including address 0](https://github.com/rust-lang/rust/pull/141260)
|
||||
|
||||
|
||||
<a id="1.90-Compiler"></a>
|
||||
|
||||
Compiler
|
||||
--------
|
||||
- [Use `lld` by default on `x86_64-unknown-linux-gnu`](https://github.com/rust-lang/rust/pull/140525).
|
||||
- [Tier 3 `musl` targets now link dynamically by default](https://github.com/rust-lang/rust/pull/144410). Affected targets:
|
||||
- `mips64-unknown-linux-muslabi64`
|
||||
- `powerpc64-unknown-linux-musl`
|
||||
- `powerpc-unknown-linux-musl`
|
||||
- `powerpc-unknown-linux-muslspe`
|
||||
- `riscv32gc-unknown-linux-musl`
|
||||
- `s390x-unknown-linux-musl`
|
||||
- `thumbv7neon-unknown-linux-musleabihf`
|
||||
|
||||
|
||||
<a id="1.90-Platform-Support"></a>
|
||||
|
||||
Platform Support
|
||||
----------------
|
||||
- [Demote `x86_64-apple-darwin` to Tier 2 with host tools](https://github.com/rust-lang/rust/pull/145252)
|
||||
|
||||
|
||||
Refer to Rust's [platform support page][platform-support-doc]
|
||||
for more information on Rust's tiered platform support.
|
||||
|
||||
[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html
|
||||
|
||||
<a id="1.90-Libraries"></a>
|
||||
|
||||
Libraries
|
||||
---------
|
||||
- [Stabilize `u*::{checked,overflowing,saturating,wrapping}_sub_signed`](https://github.com/rust-lang/rust/issues/126043)
|
||||
- [Allow comparisons between `CStr`, `CString`, and `Cow<CStr>`](https://github.com/rust-lang/rust/pull/137268)
|
||||
- [Remove some unsized tuple impls since unsized tuples can't be constructed](https://github.com/rust-lang/rust/pull/138340)
|
||||
- [Set `MSG_NOSIGNAL` for `UnixStream`](https://github.com/rust-lang/rust/pull/140005)
|
||||
- [`proc_macro::Ident::new` now supports `$crate`.](https://github.com/rust-lang/rust/pull/141996)
|
||||
- [Guarantee the pointer returned from `Thread::into_raw` has at least 8 bytes of alignment](https://github.com/rust-lang/rust/pull/143859)
|
||||
|
||||
|
||||
<a id="1.90-Stabilized-APIs"></a>
|
||||
|
||||
Stabilized APIs
|
||||
---------------
|
||||
|
||||
- [`u{n}::checked_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.checked_sub_signed)
|
||||
- [`u{n}::overflowing_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.overflowing_sub_signed)
|
||||
- [`u{n}::saturating_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.saturating_sub_signed)
|
||||
- [`u{n}::wrapping_sub_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.wrapping_sub_signed)
|
||||
- [`impl Copy for IntErrorKind`](https://doc.rust-lang.org/stable/std/num/enum.IntErrorKind.html#impl-Copy-for-IntErrorKind)
|
||||
- [`impl Hash for IntErrorKind`](https://doc.rust-lang.org/stable/std/num/enum.IntErrorKind.html#impl-Hash-for-IntErrorKind)
|
||||
- [`impl PartialEq<&CStr> for CStr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#impl-PartialEq%3C%26CStr%3E-for-CStr)
|
||||
- [`impl PartialEq<CString> for CStr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#impl-PartialEq%3CCString%3E-for-CStr)
|
||||
- [`impl PartialEq<Cow<CStr>> for CStr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#impl-PartialEq%3CCow%3C'_,+CStr%3E%3E-for-CStr)
|
||||
- [`impl PartialEq<&CStr> for CString`](https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#impl-PartialEq%3C%26CStr%3E-for-CString)
|
||||
- [`impl PartialEq<CStr> for CString`](https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#impl-PartialEq%3CCStr%3E-for-CString)
|
||||
- [`impl PartialEq<Cow<CStr>> for CString`](https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#impl-PartialEq%3CCow%3C'_,+CStr%3E%3E-for-CString)
|
||||
- [`impl PartialEq<&CStr> for Cow<CStr>`](https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html#impl-PartialEq%3C%26CStr%3E-for-Cow%3C'_,+CStr%3E)
|
||||
- [`impl PartialEq<CStr> for Cow<CStr>`](https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html#impl-PartialEq%3CCStr%3E-for-Cow%3C'_,+CStr%3E)
|
||||
- [`impl PartialEq<CString> for Cow<CStr>`](https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html#impl-PartialEq%3CCString%3E-for-Cow%3C'_,+CStr%3E)
|
||||
|
||||
|
||||
These previously stable APIs are now stable in const contexts:
|
||||
|
||||
- [`<[T]>::reverse`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.reverse)
|
||||
- [`f32::floor`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.floor)
|
||||
- [`f32::ceil`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.ceil)
|
||||
- [`f32::trunc`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.trunc)
|
||||
- [`f32::fract`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.fract)
|
||||
- [`f32::round`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.round)
|
||||
- [`f32::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.round_ties_even)
|
||||
- [`f64::floor`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.floor)
|
||||
- [`f64::ceil`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.ceil)
|
||||
- [`f64::trunc`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.trunc)
|
||||
- [`f64::fract`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.fract)
|
||||
- [`f64::round`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.round)
|
||||
- [`f64::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.round_ties_even)
|
||||
|
||||
|
||||
<a id="1.90-Cargo"></a>
|
||||
|
||||
Cargo
|
||||
-----
|
||||
- [Add `http.proxy-cainfo` config for proxy certs](https://github.com/rust-lang/cargo/pull/15374/)
|
||||
- [Use `gix` for `cargo package`](https://github.com/rust-lang/cargo/pull/15534/)
|
||||
- [feat(publish): Stabilize multi-package publishing](https://github.com/rust-lang/cargo/pull/15636/)
|
||||
|
||||
<a id="1.90-Rustdoc"></a>
|
||||
|
||||
Rustdoc
|
||||
-----
|
||||
- [Add ways to collapse all impl blocks](https://github.com/rust-lang/rust/pull/141663). Previously the "Summary" button and "-" keyboard shortcut would never collapse `impl` blocks, now they do when shift is held
|
||||
- [Display unsafe attributes with `unsafe()` wrappers](https://github.com/rust-lang/rust/pull/143662)
|
||||
|
||||
|
||||
<a id="1.90-Compatibility-Notes"></a>
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
- [Use `lld` by default on `x86_64-unknown-linux-gnu`](https://github.com/rust-lang/rust/pull/140525).
|
||||
See also <https://blog.rust-lang.org/2025/09/01/rust-lld-on-1.90.0-stable/>.
|
||||
- [Make `core::iter::Fuse`'s `Default` impl construct `I::default()` internally as promised in the docs instead of always being empty](https://github.com/rust-lang/rust/pull/140985)
|
||||
- [Set `MSG_NOSIGNAL` for `UnixStream`](https://github.com/rust-lang/rust/pull/140005)
|
||||
This may change program behavior but results in the same behavior as other primitives (e.g., stdout, network sockets).
|
||||
Programs relying on signals to terminate them should update handling of sockets to handle errors on write by exiting.
|
||||
- [On Unix `std::env::home_dir` will use the fallback if the `HOME` environment variable is empty](https://github.com/rust-lang/rust/pull/141840)
|
||||
- We now [reject unsupported `extern "{abi}"`s consistently in all positions](https://github.com/rust-lang/rust/pull/142134). This primarily affects the use of implementing traits on an `extern "{abi}"` function pointer, like `extern "stdcall" fn()`, on a platform that doesn't support that, like aarch64-unknown-linux-gnu. Direct usage of these unsupported ABI strings by declaring or defining functions was already rejected, so this is only a change for consistency.
|
||||
- [const-eval: error when initializing a static writes to that static](https://github.com/rust-lang/rust/pull/143084)
|
||||
- [Check that the `proc_macro_derive` macro has correct arguments when applied to the crate root](https://github.com/rust-lang/rust/pull/143607)
|
||||
|
||||
|
||||
Version 1.89.0 (2025-08-07)
|
||||
==========================
|
||||
|
||||
|
|
|
|||
|
|
@ -325,6 +325,9 @@
|
|||
# Defaults to the Python interpreter used to execute x.py.
|
||||
#build.python = "python"
|
||||
|
||||
# The path to (or name of) the resource compiler executable to use on Windows.
|
||||
#build.windows-rc = "rc.exe"
|
||||
|
||||
# The path to the REUSE executable to use. Note that REUSE is not required in
|
||||
# most cases, as our tooling relies on a cached (and shrunk) copy of the
|
||||
# REUSE output present in the git repository and in our source tarballs.
|
||||
|
|
@ -859,6 +862,14 @@
|
|||
# Trigger a `DebugBreak` after an internal compiler error during bootstrap on Windows
|
||||
#rust.break-on-ice = true
|
||||
|
||||
# Set the number of threads for the compiler frontend used during compilation of Rust code (passed to `-Zthreads`).
|
||||
# The valid options are:
|
||||
# 0 - Set the number of threads according to the detected number of threads of the host system
|
||||
# 1 - Use a single thread for compilation of Rust code (the default)
|
||||
# N - Number of threads used for compilation of Rust code
|
||||
#
|
||||
#rust.parallel-frontend-threads = 1
|
||||
|
||||
# =============================================================================
|
||||
# Distribution options
|
||||
#
|
||||
|
|
|
|||
|
|
@ -30,6 +30,12 @@ features = ['unprefixed_malloc_on_supported_platforms']
|
|||
check_only = ['rustc_driver_impl/check_only']
|
||||
jemalloc = ['dep:tikv-jemalloc-sys']
|
||||
llvm = ['rustc_driver_impl/llvm']
|
||||
llvm_enzyme = ['rustc_driver_impl/llvm_enzyme']
|
||||
max_level_info = ['rustc_driver_impl/max_level_info']
|
||||
rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts']
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[build-dependencies]
|
||||
# tidy-alphabetical-start
|
||||
rustc_windows_rc = { path = "../rustc_windows_rc" }
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use std::env;
|
||||
use std::{env, path};
|
||||
|
||||
use rustc_windows_rc::{VersionInfoFileType, compile_windows_resource_file};
|
||||
|
||||
fn main() {
|
||||
let target_os = env::var("CARGO_CFG_TARGET_OS");
|
||||
|
|
@ -13,6 +15,18 @@ fn main() {
|
|||
|
||||
// Add a manifest file to rustc.exe.
|
||||
fn set_windows_exe_options() {
|
||||
set_windows_resource();
|
||||
set_windows_manifest();
|
||||
}
|
||||
|
||||
fn set_windows_resource() {
|
||||
let stem = path::PathBuf::from("rustc_main_resource");
|
||||
let file_description = "rustc";
|
||||
let res_file = compile_windows_resource_file(&stem, file_description, VersionInfoFileType::App);
|
||||
println!("cargo:rustc-link-arg={}", res_file.display());
|
||||
}
|
||||
|
||||
fn set_windows_manifest() {
|
||||
static WINDOWS_MANIFEST_FILE: &str = "Windows Manifest.xml";
|
||||
|
||||
let mut manifest = env::current_dir().unwrap();
|
||||
|
|
|
|||
|
|
@ -2284,6 +2284,54 @@ pub struct FnSig {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
impl FnSig {
|
||||
/// Return a span encompassing the header, or where to insert it if empty.
|
||||
pub fn header_span(&self) -> Span {
|
||||
match self.header.ext {
|
||||
Extern::Implicit(span) | Extern::Explicit(_, span) => {
|
||||
return self.span.with_hi(span.hi());
|
||||
}
|
||||
Extern::None => {}
|
||||
}
|
||||
|
||||
match self.header.safety {
|
||||
Safety::Unsafe(span) | Safety::Safe(span) => return self.span.with_hi(span.hi()),
|
||||
Safety::Default => {}
|
||||
};
|
||||
|
||||
if let Some(coroutine_kind) = self.header.coroutine_kind {
|
||||
return self.span.with_hi(coroutine_kind.span().hi());
|
||||
}
|
||||
|
||||
if let Const::Yes(span) = self.header.constness {
|
||||
return self.span.with_hi(span.hi());
|
||||
}
|
||||
|
||||
self.span.shrink_to_lo()
|
||||
}
|
||||
|
||||
/// The span of the header's safety, or where to insert it if empty.
|
||||
pub fn safety_span(&self) -> Span {
|
||||
match self.header.safety {
|
||||
Safety::Unsafe(span) | Safety::Safe(span) => span,
|
||||
Safety::Default => {
|
||||
// Insert after the `coroutine_kind` if available.
|
||||
if let Some(extern_span) = self.header.ext.span() {
|
||||
return extern_span.shrink_to_lo();
|
||||
}
|
||||
|
||||
// Insert right at the front of the signature.
|
||||
self.header_span().shrink_to_hi()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The span of the header's extern, or where to insert it if empty.
|
||||
pub fn extern_span(&self) -> Span {
|
||||
self.header.ext.span().unwrap_or(self.safety_span().shrink_to_hi())
|
||||
}
|
||||
}
|
||||
|
||||
/// A constraint on an associated item.
|
||||
///
|
||||
/// ### Examples
|
||||
|
|
@ -3526,6 +3574,13 @@ impl Extern {
|
|||
None => Extern::Implicit(span),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(self) -> Option<Span> {
|
||||
match self {
|
||||
Extern::None => None,
|
||||
Extern::Implicit(span) | Extern::Explicit(_, span) => Some(span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A function header.
|
||||
|
|
@ -3534,12 +3589,12 @@ impl Extern {
|
|||
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
|
||||
#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]
|
||||
pub struct FnHeader {
|
||||
/// Whether this is `unsafe`, or has a default safety.
|
||||
pub safety: Safety,
|
||||
/// Whether this is `async`, `gen`, or nothing.
|
||||
pub coroutine_kind: Option<CoroutineKind>,
|
||||
/// The `const` keyword, if any
|
||||
pub constness: Const,
|
||||
/// Whether this is `async`, `gen`, or nothing.
|
||||
pub coroutine_kind: Option<CoroutineKind>,
|
||||
/// Whether this is `unsafe`, or has a default safety.
|
||||
pub safety: Safety,
|
||||
/// The `extern` keyword and corresponding ABI string, if any.
|
||||
pub ext: Extern,
|
||||
}
|
||||
|
|
@ -3553,38 +3608,6 @@ impl FnHeader {
|
|||
|| matches!(constness, Const::Yes(_))
|
||||
|| !matches!(ext, Extern::None)
|
||||
}
|
||||
|
||||
/// Return a span encompassing the header, or none if all options are default.
|
||||
pub fn span(&self) -> Option<Span> {
|
||||
fn append(a: &mut Option<Span>, b: Span) {
|
||||
*a = match a {
|
||||
None => Some(b),
|
||||
Some(x) => Some(x.to(b)),
|
||||
}
|
||||
}
|
||||
|
||||
let mut full_span = None;
|
||||
|
||||
match self.safety {
|
||||
Safety::Unsafe(span) | Safety::Safe(span) => append(&mut full_span, span),
|
||||
Safety::Default => {}
|
||||
};
|
||||
|
||||
if let Some(coroutine_kind) = self.coroutine_kind {
|
||||
append(&mut full_span, coroutine_kind.span());
|
||||
}
|
||||
|
||||
if let Const::Yes(span) = self.constness {
|
||||
append(&mut full_span, span);
|
||||
}
|
||||
|
||||
match self.ext {
|
||||
Extern::Implicit(span) | Extern::Explicit(_, span) => append(&mut full_span, span),
|
||||
Extern::None => {}
|
||||
}
|
||||
|
||||
full_span
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FnHeader {
|
||||
|
|
|
|||
|
|
@ -1536,7 +1536,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
hir::LangItem::Range
|
||||
}
|
||||
}
|
||||
(None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
|
||||
(None, Some(..), Closed) => {
|
||||
if self.tcx.features().new_range() {
|
||||
hir::LangItem::RangeToInclusiveCopy
|
||||
} else {
|
||||
hir::LangItem::RangeToInclusive
|
||||
}
|
||||
}
|
||||
(Some(e1), Some(e2), Closed) => {
|
||||
if self.tcx.features().new_range() {
|
||||
hir::LangItem::RangeInclusiveCopy
|
||||
|
|
@ -1560,13 +1566,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
};
|
||||
|
||||
let fields = self.arena.alloc_from_iter(
|
||||
e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map(
|
||||
|(s, e)| {
|
||||
e1.iter()
|
||||
.map(|e| (sym::start, e))
|
||||
.chain(e2.iter().map(|e| {
|
||||
(
|
||||
if matches!(
|
||||
lang_item,
|
||||
hir::LangItem::RangeInclusiveCopy | hir::LangItem::RangeToInclusiveCopy
|
||||
) {
|
||||
sym::last
|
||||
} else {
|
||||
sym::end
|
||||
},
|
||||
e,
|
||||
)
|
||||
}))
|
||||
.map(|(s, e)| {
|
||||
let expr = self.lower_expr(e);
|
||||
let ident = Ident::new(s, self.lower_span(e.span));
|
||||
self.expr_field(ident, expr, e.span)
|
||||
},
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
hir::ExprKind::Struct(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
|
|||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::{DefKind, PerNS, Res};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
|
||||
use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin, Target, find_attr};
|
||||
use rustc_hir::{
|
||||
self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, find_attr,
|
||||
};
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
|
||||
|
|
@ -1117,20 +1119,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
};
|
||||
|
||||
let span = self.lower_span(i.span);
|
||||
let item = hir::ImplItem {
|
||||
owner_id: hir_id.expect_owner(),
|
||||
ident: self.lower_ident(ident),
|
||||
generics,
|
||||
impl_kind: if is_in_trait_impl {
|
||||
ImplItemImplKind::Trait {
|
||||
defaultness,
|
||||
trait_item_def_id: self
|
||||
.resolver
|
||||
.get_partial_res(i.id)
|
||||
.and_then(|r| r.expect_full_res().opt_def_id())
|
||||
.ok_or_else(|| {
|
||||
self.dcx().span_delayed_bug(
|
||||
span,
|
||||
"could not resolve trait item being implemented",
|
||||
)
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) }
|
||||
},
|
||||
kind,
|
||||
vis_span: self.lower_span(i.vis.span),
|
||||
span: self.lower_span(i.span),
|
||||
defaultness,
|
||||
span,
|
||||
has_delayed_lints: !self.delayed_lints.is_empty(),
|
||||
trait_item_def_id: self
|
||||
.resolver
|
||||
.get_partial_res(i.id)
|
||||
.map(|r| r.expect_full_res().opt_def_id())
|
||||
.unwrap_or(None),
|
||||
};
|
||||
self.arena.alloc(item)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2101,17 +2101,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
{
|
||||
return;
|
||||
}
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
RelaxedBoundPolicy::Forbidden(reason) => {
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
|
||||
match reason {
|
||||
RelaxedBoundForbiddenReason::TraitObjectTy => {
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.dcx().span_err(
|
||||
span,
|
||||
"relaxed bounds are not permitted in trait object types",
|
||||
|
|
@ -2119,6 +2116,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::SuperTrait => {
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut diag = self.dcx().struct_span_err(
|
||||
span,
|
||||
"relaxed bounds are not permitted in supertrait bounds",
|
||||
|
|
|
|||
|
|
@ -57,8 +57,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim
|
|||
.label = {ast_passes_auto_super_lifetime}
|
||||
.suggestion = remove the super traits or lifetime bounds
|
||||
|
||||
ast_passes_bad_c_variadic = defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention
|
||||
|
||||
ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
|
||||
.cannot_have = cannot have a body
|
||||
.invalid = the invalid body
|
||||
|
|
@ -66,6 +64,17 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
|
|||
|
||||
ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
|
||||
|
||||
ast_passes_c_variadic_bad_extern = `...` is not supported for `extern "{$abi}"` functions
|
||||
.label = `extern "{$abi}"` because of this
|
||||
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||
|
||||
ast_passes_c_variadic_must_be_unsafe =
|
||||
functions with a C variable argument list must be unsafe
|
||||
.suggestion = add the `unsafe` keyword to this definition
|
||||
|
||||
ast_passes_c_variadic_no_extern = `...` is not supported for non-extern functions
|
||||
.help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
|
||||
|
||||
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
|
||||
.const = `const` because of this
|
||||
.variadic = C-variadic because of this
|
||||
|
|
@ -84,6 +93,10 @@ ast_passes_const_without_body =
|
|||
ast_passes_constraint_on_negative_bound =
|
||||
associated type constraints not allowed on negative bounds
|
||||
|
||||
ast_passes_coroutine_and_c_variadic = functions cannot be both `{$coroutine_kind}` and C-variadic
|
||||
.const = `{$coroutine_kind}` because of this
|
||||
.variadic = C-variadic because of this
|
||||
|
||||
ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
|
||||
.label = not supported
|
||||
.suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
|
||||
|
|
@ -201,6 +214,10 @@ ast_passes_match_arm_with_no_body =
|
|||
.suggestion = add a body after the pattern
|
||||
|
||||
ast_passes_missing_unsafe_on_extern = extern blocks must be unsafe
|
||||
.suggestion = needs `unsafe` before the extern keyword
|
||||
|
||||
ast_passes_missing_unsafe_on_extern_lint = extern blocks should be unsafe
|
||||
.suggestion = needs `unsafe` before the extern keyword
|
||||
|
||||
ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
|
||||
.help = consider using the `#[path]` attribute to specify filesystem path
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
|
||||
if !spans.is_empty() {
|
||||
let header_span = sig.header.span().unwrap_or(sig.span.shrink_to_lo());
|
||||
let header_span = sig.header_span();
|
||||
let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span());
|
||||
let padding = if header_span.is_empty() { "" } else { " " };
|
||||
|
||||
|
|
@ -665,46 +665,68 @@ impl<'a> AstValidator<'a> {
|
|||
/// - Non-const
|
||||
/// - Either foreign, or free and `unsafe extern "C"` semantically
|
||||
fn check_c_variadic_type(&self, fk: FnKind<'a>) {
|
||||
let variadic_spans: Vec<_> = fk
|
||||
.decl()
|
||||
.inputs
|
||||
.iter()
|
||||
.filter(|arg| matches!(arg.ty.kind, TyKind::CVarArgs))
|
||||
.map(|arg| arg.span)
|
||||
.collect();
|
||||
// `...` is already rejected when it is not the final parameter.
|
||||
let variadic_param = match fk.decl().inputs.last() {
|
||||
Some(param) if matches!(param.ty.kind, TyKind::CVarArgs) => param,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
if variadic_spans.is_empty() {
|
||||
return;
|
||||
}
|
||||
let FnKind::Fn(fn_ctxt, _, Fn { sig, .. }) = fk else {
|
||||
// Unreachable because the parser already rejects `...` in closures.
|
||||
unreachable!("C variable argument list cannot be used in closures")
|
||||
};
|
||||
|
||||
if let Some(header) = fk.header()
|
||||
&& let Const::Yes(const_span) = header.constness
|
||||
{
|
||||
let mut spans = variadic_spans.clone();
|
||||
spans.push(const_span);
|
||||
// C-variadics are not yet implemented in const evaluation.
|
||||
if let Const::Yes(const_span) = sig.header.constness {
|
||||
self.dcx().emit_err(errors::ConstAndCVariadic {
|
||||
spans,
|
||||
spans: vec![const_span, variadic_param.span],
|
||||
const_span,
|
||||
variadic_spans: variadic_spans.clone(),
|
||||
variadic_span: variadic_param.span,
|
||||
});
|
||||
}
|
||||
|
||||
match (fk.ctxt(), fk.header()) {
|
||||
(Some(FnCtxt::Foreign), _) => return,
|
||||
(Some(FnCtxt::Free), Some(header)) => match header.ext {
|
||||
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _)
|
||||
| Extern::Explicit(StrLit { symbol_unescaped: sym::C_dash_unwind, .. }, _)
|
||||
| Extern::Implicit(_)
|
||||
if matches!(header.safety, Safety::Unsafe(_)) =>
|
||||
{
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
if let Some(coroutine_kind) = sig.header.coroutine_kind {
|
||||
self.dcx().emit_err(errors::CoroutineAndCVariadic {
|
||||
spans: vec![coroutine_kind.span(), variadic_param.span],
|
||||
coroutine_kind: coroutine_kind.as_str(),
|
||||
coroutine_span: coroutine_kind.span(),
|
||||
variadic_span: variadic_param.span,
|
||||
});
|
||||
}
|
||||
|
||||
self.dcx().emit_err(errors::BadCVariadic { span: variadic_spans });
|
||||
match fn_ctxt {
|
||||
FnCtxt::Foreign => return,
|
||||
FnCtxt::Free | FnCtxt::Assoc(_) => match sig.header.ext {
|
||||
Extern::Implicit(_) => {
|
||||
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
|
||||
span: variadic_param.span,
|
||||
unsafe_span: sig.safety_span(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Extern::Explicit(StrLit { symbol_unescaped, .. }, _) => {
|
||||
if !matches!(symbol_unescaped, sym::C | sym::C_dash_unwind) {
|
||||
self.dcx().emit_err(errors::CVariadicBadExtern {
|
||||
span: variadic_param.span,
|
||||
abi: symbol_unescaped,
|
||||
extern_span: sig.extern_span(),
|
||||
});
|
||||
}
|
||||
|
||||
if !matches!(sig.header.safety, Safety::Unsafe(_)) {
|
||||
self.dcx().emit_err(errors::CVariadicMustBeUnsafe {
|
||||
span: variadic_param.span,
|
||||
unsafe_span: sig.safety_span(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Extern::None => {
|
||||
let err = errors::CVariadicNoExtern { span: variadic_param.span };
|
||||
self.dcx().emit_err(err);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item_named(&self, ident: Ident, kind: &str) {
|
||||
|
|
@ -1104,7 +1126,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
MISSING_UNSAFE_ON_EXTERN,
|
||||
item.id,
|
||||
item.span,
|
||||
BuiltinLintDiag::MissingUnsafeOnExtern {
|
||||
errors::MissingUnsafeOnExternLint {
|
||||
suggestion: item.span.shrink_to_lo(),
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -319,10 +319,37 @@ pub(crate) struct ExternItemAscii {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_bad_c_variadic)]
|
||||
pub(crate) struct BadCVariadic {
|
||||
#[diag(ast_passes_c_variadic_no_extern)]
|
||||
#[help]
|
||||
pub(crate) struct CVariadicNoExtern {
|
||||
#[primary_span]
|
||||
pub span: Vec<Span>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_c_variadic_must_be_unsafe)]
|
||||
pub(crate) struct CVariadicMustBeUnsafe {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
#[suggestion(
|
||||
ast_passes_suggestion,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "unsafe ",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub unsafe_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_c_variadic_bad_extern)]
|
||||
#[help]
|
||||
pub(crate) struct CVariadicBadExtern {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub abi: Symbol,
|
||||
#[label]
|
||||
pub extern_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
@ -489,6 +516,13 @@ pub(crate) struct MissingUnsafeOnExtern {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(ast_passes_missing_unsafe_on_extern_lint)]
|
||||
pub(crate) struct MissingUnsafeOnExternLint {
|
||||
#[suggestion(code = "unsafe ", applicability = "machine-applicable")]
|
||||
pub suggestion: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_fieldless_union)]
|
||||
pub(crate) struct FieldlessUnion {
|
||||
|
|
@ -656,7 +690,19 @@ pub(crate) struct ConstAndCVariadic {
|
|||
#[label(ast_passes_const)]
|
||||
pub const_span: Span,
|
||||
#[label(ast_passes_variadic)]
|
||||
pub variadic_spans: Vec<Span>,
|
||||
pub variadic_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_coroutine_and_c_variadic)]
|
||||
pub(crate) struct CoroutineAndCVariadic {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
pub coroutine_kind: &'static str,
|
||||
#[label(ast_passes_const)]
|
||||
pub coroutine_span: Span,
|
||||
#[label(ast_passes_variadic)]
|
||||
pub variadic_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
|||
|
|
@ -122,6 +122,14 @@ attr_parsing_null_on_export = `export_name` may not contain null characters
|
|||
|
||||
attr_parsing_null_on_link_section = `link_section` may not contain null characters
|
||||
|
||||
attr_parsing_null_on_objc_class = `objc::class!` may not contain null characters
|
||||
|
||||
attr_parsing_null_on_objc_selector = `objc::selector!` may not contain null characters
|
||||
|
||||
attr_parsing_objc_class_expected_string_literal = `objc::class!` expected a string literal
|
||||
|
||||
attr_parsing_objc_selector_expected_string_literal = `objc::selector!` expected a string literal
|
||||
|
||||
attr_parsing_repr_ident =
|
||||
meta item in `repr` must be an identifier
|
||||
|
||||
|
|
@ -247,3 +255,7 @@ attr_parsing_raw_dylib_only_windows =
|
|||
|
||||
attr_parsing_whole_archive_needs_static =
|
||||
linking modifier `whole-archive` is only compatible with `static` linking kind
|
||||
|
||||
attr_parsing_limit_invalid =
|
||||
`limit` must be a non-negative integer
|
||||
.label = {$error_str}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy};
|
|||
use rustc_session::parse::feature_err;
|
||||
|
||||
use super::prelude::*;
|
||||
use crate::session_diagnostics::{NakedFunctionIncompatibleAttribute, NullOnExport};
|
||||
use crate::session_diagnostics::{
|
||||
NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, NullOnObjcSelector,
|
||||
ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral,
|
||||
};
|
||||
|
||||
pub(crate) struct OptimizeParser;
|
||||
|
||||
|
|
@ -150,6 +153,70 @@ impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ObjcClassParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for ObjcClassParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_class];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]);
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "ClassName");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(nv) = args.name_value() else {
|
||||
cx.expected_name_value(cx.attr_span, None);
|
||||
return None;
|
||||
};
|
||||
let Some(classname) = nv.value_as_str() else {
|
||||
// `#[rustc_objc_class = ...]` is expected to be used as an implementatioin detail
|
||||
// inside a standard library macro, but `cx.expected_string_literal` exposes too much.
|
||||
// Use a custom error message instead.
|
||||
cx.emit_err(ObjcClassExpectedStringLiteral { span: nv.value_span });
|
||||
return None;
|
||||
};
|
||||
if classname.as_str().contains('\0') {
|
||||
// `#[rustc_objc_class = ...]` will be converted to a null-terminated string,
|
||||
// so it may not contain any null characters.
|
||||
cx.emit_err(NullOnObjcClass { span: nv.value_span });
|
||||
return None;
|
||||
}
|
||||
Some(AttributeKind::ObjcClass { classname, span: cx.attr_span })
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ObjcSelectorParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for ObjcSelectorParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_selector];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]);
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "methodName");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(nv) = args.name_value() else {
|
||||
cx.expected_name_value(cx.attr_span, None);
|
||||
return None;
|
||||
};
|
||||
let Some(methname) = nv.value_as_str() else {
|
||||
// `#[rustc_objc_selector = ...]` is expected to be used as an implementatioin detail
|
||||
// inside a standard library macro, but `cx.expected_string_literal` exposes too much.
|
||||
// Use a custom error message instead.
|
||||
cx.emit_err(ObjcSelectorExpectedStringLiteral { span: nv.value_span });
|
||||
return None;
|
||||
};
|
||||
if methname.as_str().contains('\0') {
|
||||
// `#[rustc_objc_selector = ...]` will be converted to a null-terminated string,
|
||||
// so it may not contain any null characters.
|
||||
cx.emit_err(NullOnObjcSelector { span: nv.value_span });
|
||||
return None;
|
||||
}
|
||||
Some(AttributeKind::ObjcSelector { methname, span: cx.attr_span })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct NakedParser {
|
||||
span: Option<Span>,
|
||||
|
|
@ -218,6 +285,7 @@ impl<S: Stage> AttributeParser<S> for NakedParser {
|
|||
sym::rustc_std_internal_symbol,
|
||||
// FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
|
||||
sym::rustc_align,
|
||||
sym::rustc_align_static,
|
||||
// obviously compatible with self
|
||||
sym::naked,
|
||||
// documentation
|
||||
|
|
|
|||
|
|
@ -1,6 +1,40 @@
|
|||
use rustc_feature::AttributeType;
|
||||
use std::num::IntErrorKind;
|
||||
|
||||
use rustc_hir::limit::Limit;
|
||||
|
||||
use super::prelude::*;
|
||||
use crate::session_diagnostics::LimitInvalid;
|
||||
|
||||
impl<S: Stage> AcceptContext<'_, '_, S> {
|
||||
fn parse_limit_int(&self, nv: &NameValueParser) -> Option<Limit> {
|
||||
let Some(limit) = nv.value_as_str() else {
|
||||
self.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
|
||||
return None;
|
||||
};
|
||||
|
||||
let error_str = match limit.as_str().parse() {
|
||||
Ok(i) => return Some(Limit::new(i)),
|
||||
Err(e) => match e.kind() {
|
||||
IntErrorKind::PosOverflow => "`limit` is too large",
|
||||
IntErrorKind::Empty => "`limit` must be a non-negative integer",
|
||||
IntErrorKind::InvalidDigit => "not a valid integer",
|
||||
IntErrorKind::NegOverflow => {
|
||||
panic!(
|
||||
"`limit` should never negatively overflow since we're parsing into a usize and we'd get Empty instead"
|
||||
)
|
||||
}
|
||||
IntErrorKind::Zero => {
|
||||
panic!("zero is a valid `limit` so should have returned Ok() when parsing")
|
||||
}
|
||||
kind => panic!("unimplemented IntErrorKind variant: {:?}", kind),
|
||||
},
|
||||
};
|
||||
|
||||
self.emit_err(LimitInvalid { span: self.attr_span, value_span: nv.value_span, error_str });
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct CrateNameParser;
|
||||
|
||||
|
|
@ -9,11 +43,7 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
|
|||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
|
||||
const TYPE: AttributeType = AttributeType::CrateLevel;
|
||||
|
||||
// FIXME: crate name is allowed on all targets and ignored,
|
||||
// even though it should only be valid on crates of course
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let ArgParser::NameValue(n) = args else {
|
||||
|
|
@ -34,3 +64,122 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RecursionLimitParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
|
||||
const PATH: &[Symbol] = &[sym::recursion_limit];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let ArgParser::NameValue(nv) = args else {
|
||||
cx.expected_name_value(cx.attr_span, None);
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(AttributeKind::RecursionLimit {
|
||||
limit: cx.parse_limit_int(nv)?,
|
||||
attr_span: cx.attr_span,
|
||||
limit_span: nv.value_span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct MoveSizeLimitParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
|
||||
const PATH: &[Symbol] = &[sym::move_size_limit];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let ArgParser::NameValue(nv) = args else {
|
||||
cx.expected_name_value(cx.attr_span, None);
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(AttributeKind::MoveSizeLimit {
|
||||
limit: cx.parse_limit_int(nv)?,
|
||||
attr_span: cx.attr_span,
|
||||
limit_span: nv.value_span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct TypeLengthLimitParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
|
||||
const PATH: &[Symbol] = &[sym::type_length_limit];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let ArgParser::NameValue(nv) = args else {
|
||||
cx.expected_name_value(cx.attr_span, None);
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(AttributeKind::TypeLengthLimit {
|
||||
limit: cx.parse_limit_int(nv)?,
|
||||
attr_span: cx.attr_span,
|
||||
limit_span: nv.value_span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct PatternComplexityLimitParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
|
||||
const PATH: &[Symbol] = &[sym::pattern_complexity_limit];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let ArgParser::NameValue(nv) = args else {
|
||||
cx.expected_name_value(cx.attr_span, None);
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(AttributeKind::PatternComplexityLimit {
|
||||
limit: cx.parse_limit_int(nv)?,
|
||||
attr_span: cx.attr_span,
|
||||
limit_span: nv.value_span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct NoCoreParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for NoCoreParser {
|
||||
const PATH: &[Symbol] = &[sym::no_core];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoCore;
|
||||
}
|
||||
|
||||
pub(crate) struct NoStdParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for NoStdParser {
|
||||
const PATH: &[Symbol] = &[sym::no_std];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcCoherenceIsCoreParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcCoherenceIsCoreParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoherenceIsCore;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use rustc_ast::AttrStyle;
|
||||
use rustc_errors::DiagArgValue;
|
||||
use rustc_hir::attrs::MacroUseArgs;
|
||||
|
||||
|
|
@ -133,3 +134,65 @@ impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
|
|||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);
|
||||
}
|
||||
|
||||
pub(crate) struct MacroExportParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for MacroExportParser {
|
||||
const PATH: &[Symbol] = &[sym::macro_export];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: &["local_inner_macros"]);
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
|
||||
Allow(Target::MacroDef),
|
||||
Error(Target::WherePredicate),
|
||||
Error(Target::Crate),
|
||||
]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let suggestions = || {
|
||||
<Self as SingleAttributeParser<S>>::TEMPLATE
|
||||
.suggestions(AttrStyle::Inner, "macro_export")
|
||||
};
|
||||
let local_inner_macros = match args {
|
||||
ArgParser::NoArgs => false,
|
||||
ArgParser::List(list) => {
|
||||
let Some(l) = list.single() else {
|
||||
let span = cx.attr_span;
|
||||
cx.emit_lint(
|
||||
AttributeLintKind::InvalidMacroExportArguments {
|
||||
suggestions: suggestions(),
|
||||
},
|
||||
span,
|
||||
);
|
||||
return None;
|
||||
};
|
||||
match l.meta_item().and_then(|i| i.path().word_sym()) {
|
||||
Some(sym::local_inner_macros) => true,
|
||||
_ => {
|
||||
let span = cx.attr_span;
|
||||
cx.emit_lint(
|
||||
AttributeLintKind::InvalidMacroExportArguments {
|
||||
suggestions: suggestions(),
|
||||
},
|
||||
span,
|
||||
);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
ArgParser::NameValue(_) => {
|
||||
let span = cx.attr_span;
|
||||
let suggestions = suggestions();
|
||||
cx.emit_err(IllFormedAttributeInputLint {
|
||||
num_suggestions: suggestions.len(),
|
||||
suggestions: DiagArgValue::StrListSepByAnd(
|
||||
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
|
||||
),
|
||||
span,
|
||||
});
|
||||
return None;
|
||||
}
|
||||
};
|
||||
Some(AttributeKind::MacroExport { span: cx.attr_span, local_inner_macros })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,15 +12,11 @@
|
|||
//! - [`CombineAttributeParser`](crate::attributes::CombineAttributeParser): makes it easy to implement an attribute which should combine the
|
||||
//! contents of attributes, if an attribute appear multiple times in a list
|
||||
//!
|
||||
//! By default, attributes are allowed anywhere. When adding an attribute that should only be used
|
||||
//! at the crate root, consider setting the `TYPE` in the parser trait to
|
||||
//! [`AttributeType::CrateLevel`](rustc_feature::AttributeType::CrateLevel).
|
||||
//!
|
||||
//! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use rustc_feature::{AttributeTemplate, AttributeType, template};
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use thin_vec::ThinVec;
|
||||
|
|
@ -89,11 +85,8 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
|
|||
///
|
||||
/// If an attribute has this symbol, the `accept` function will be called on it.
|
||||
const ATTRIBUTES: AcceptMapping<Self, S>;
|
||||
|
||||
const ALLOWED_TARGETS: AllowedTargets;
|
||||
|
||||
const TYPE: AttributeType = AttributeType::Normal;
|
||||
|
||||
/// The parser has gotten a chance to accept the attributes on an item,
|
||||
/// here it can produce an attribute.
|
||||
///
|
||||
|
|
@ -135,8 +128,6 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
|
|||
/// The template this attribute parser should implement. Used for diagnostics.
|
||||
const TEMPLATE: AttributeTemplate;
|
||||
|
||||
const TYPE: AttributeType = AttributeType::Normal;
|
||||
|
||||
/// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
|
||||
}
|
||||
|
|
@ -183,8 +174,6 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
|
|||
)];
|
||||
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
|
||||
|
||||
const TYPE: AttributeType = T::TYPE;
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
Some(self.1?.0)
|
||||
}
|
||||
|
|
@ -269,7 +258,6 @@ pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
|
|||
const PATH: &[Symbol];
|
||||
const ON_DUPLICATE: OnDuplicate<S>;
|
||||
const ALLOWED_TARGETS: AllowedTargets;
|
||||
const TYPE: AttributeType = AttributeType::Normal;
|
||||
|
||||
/// Create the [`AttributeKind`] given attribute's [`Span`].
|
||||
const CREATE: fn(Span) -> AttributeKind;
|
||||
|
|
@ -289,7 +277,6 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
|
|||
const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
|
||||
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
const TYPE: AttributeType = T::TYPE;
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
if let Err(span) = args.no_args() {
|
||||
|
|
@ -323,8 +310,6 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
|
|||
/// The template this attribute parser should implement. Used for diagnostics.
|
||||
const TEMPLATE: AttributeTemplate;
|
||||
|
||||
const TYPE: AttributeType = AttributeType::Normal;
|
||||
|
||||
/// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
@ -360,7 +345,6 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
|
|||
group.items.extend(T::extend(cx, args))
|
||||
})];
|
||||
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
|
||||
const TYPE: AttributeType = T::TYPE;
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
if let Some(first_span) = self.first_span {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// templates
|
||||
// data structures
|
||||
#[doc(hidden)]
|
||||
pub(super) use rustc_feature::{AttributeTemplate, template};
|
||||
// data structures
|
||||
#[doc(hidden)]
|
||||
pub(super) use rustc_hir::attrs::AttributeKind;
|
||||
#[doc(hidden)]
|
||||
|
|
|
|||
|
|
@ -331,3 +331,30 @@ impl<S: Stage> AttributeParser<S> for AlignParser {
|
|||
Some(AttributeKind::Align { align, span })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct AlignStaticParser(AlignParser);
|
||||
|
||||
impl AlignStaticParser {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_align_static];
|
||||
const TEMPLATE: AttributeTemplate = AlignParser::TEMPLATE;
|
||||
|
||||
fn parse<'c, S: Stage>(
|
||||
&mut self,
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
args: &'c ArgParser<'_>,
|
||||
) {
|
||||
self.0.parse(cx, args)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Stage> AttributeParser<S> for AlignStaticParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(Self::PATH, Self::TEMPLATE, Self::parse)];
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]);
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
let (align, span) = self.0.0?;
|
||||
Some(AttributeKind::Align { align, span })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
use std::mem;
|
||||
|
||||
use rustc_feature::AttributeType;
|
||||
|
||||
use super::prelude::*;
|
||||
use crate::attributes::{
|
||||
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
|
||||
|
|
@ -151,15 +149,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for AllowIncoherentImplParser {
|
|||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::AllowIncoherentImpl;
|
||||
}
|
||||
|
||||
pub(crate) struct CoherenceIsCoreParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const TYPE: AttributeType = AttributeType::CrateLevel;
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
|
||||
}
|
||||
|
||||
pub(crate) struct FundamentalParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
|
||||
const PATH: &[Symbol] = &[sym::fundamental];
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::sync::LazyLock;
|
|||
use private::Sealed;
|
||||
use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
|
||||
use rustc_errors::{Diag, Diagnostic, Level};
|
||||
use rustc_feature::{AttributeTemplate, AttributeType};
|
||||
use rustc_feature::AttributeTemplate;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
|
||||
use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
|
||||
|
|
@ -20,11 +20,14 @@ use crate::attributes::allow_unstable::{
|
|||
use crate::attributes::body::CoroutineParser;
|
||||
use crate::attributes::codegen_attrs::{
|
||||
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
|
||||
NoMangleParser, OptimizeParser, SanitizeParser, TargetFeatureParser, TrackCallerParser,
|
||||
UsedParser,
|
||||
NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser, SanitizeParser,
|
||||
TargetFeatureParser, TrackCallerParser, UsedParser,
|
||||
};
|
||||
use crate::attributes::confusables::ConfusablesParser;
|
||||
use crate::attributes::crate_level::CrateNameParser;
|
||||
use crate::attributes::crate_level::{
|
||||
CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoStdParser, PatternComplexityLimitParser,
|
||||
RecursionLimitParser, RustcCoherenceIsCoreParser, TypeLengthLimitParser,
|
||||
};
|
||||
use crate::attributes::deprecation::DeprecationParser;
|
||||
use crate::attributes::dummy::DummyParser;
|
||||
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
|
||||
|
|
@ -37,7 +40,7 @@ use crate::attributes::lint_helpers::{
|
|||
};
|
||||
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
|
||||
use crate::attributes::macro_attrs::{
|
||||
AllowInternalUnsafeParser, MacroEscapeParser, MacroUseParser,
|
||||
AllowInternalUnsafeParser, MacroEscapeParser, MacroExportParser, MacroUseParser,
|
||||
};
|
||||
use crate::attributes::must_use::MustUseParser;
|
||||
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
|
||||
|
|
@ -47,7 +50,7 @@ use crate::attributes::proc_macro_attrs::{
|
|||
ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
|
||||
};
|
||||
use crate::attributes::prototype::CustomMirParser;
|
||||
use crate::attributes::repr::{AlignParser, ReprParser};
|
||||
use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
|
||||
use crate::attributes::rustc_internal::{
|
||||
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
|
||||
RustcObjectLifetimeDefaultParser,
|
||||
|
|
@ -58,10 +61,10 @@ use crate::attributes::stability::{
|
|||
};
|
||||
use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser};
|
||||
use crate::attributes::traits::{
|
||||
AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
|
||||
DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
|
||||
ParenSugarParser, PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser,
|
||||
TypeConstParser, UnsafeSpecializationMarkerParser,
|
||||
AllowIncoherentImplParser, CoinductiveParser, ConstTraitParser, DenyExplicitImplParser,
|
||||
DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, ParenSugarParser,
|
||||
PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
|
||||
UnsafeSpecializationMarkerParser,
|
||||
};
|
||||
use crate::attributes::transparency::TransparencyParser;
|
||||
use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
|
||||
|
|
@ -80,7 +83,6 @@ pub(super) struct GroupTypeInnerAccept<S: Stage> {
|
|||
pub(super) template: AttributeTemplate,
|
||||
pub(super) accept_fn: AcceptFn<S>,
|
||||
pub(super) allowed_targets: AllowedTargets,
|
||||
pub(super) attribute_type: AttributeType,
|
||||
}
|
||||
|
||||
type AcceptFn<S> =
|
||||
|
|
@ -130,7 +132,6 @@ macro_rules! attribute_parsers {
|
|||
})
|
||||
}),
|
||||
allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
|
||||
attribute_type: <$names as crate::attributes::AttributeParser<$stage>>::TYPE,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -149,6 +150,7 @@ attribute_parsers!(
|
|||
pub(crate) static ATTRIBUTE_PARSERS = [
|
||||
// tidy-alphabetical-start
|
||||
AlignParser,
|
||||
AlignStaticParser,
|
||||
BodyStabilityParser,
|
||||
ConfusablesParser,
|
||||
ConstStabilityParser,
|
||||
|
|
@ -181,10 +183,16 @@ attribute_parsers!(
|
|||
Single<LinkOrdinalParser>,
|
||||
Single<LinkSectionParser>,
|
||||
Single<LinkageParser>,
|
||||
Single<MacroExportParser>,
|
||||
Single<MoveSizeLimitParser>,
|
||||
Single<MustUseParser>,
|
||||
Single<ObjcClassParser>,
|
||||
Single<ObjcSelectorParser>,
|
||||
Single<OptimizeParser>,
|
||||
Single<PathAttributeParser>,
|
||||
Single<PatternComplexityLimitParser>,
|
||||
Single<ProcMacroDeriveParser>,
|
||||
Single<RecursionLimitParser>,
|
||||
Single<RustcBuiltinMacroParser>,
|
||||
Single<RustcForceInlineParser>,
|
||||
Single<RustcLayoutScalarValidRangeEnd>,
|
||||
|
|
@ -194,11 +202,11 @@ attribute_parsers!(
|
|||
Single<ShouldPanicParser>,
|
||||
Single<SkipDuringMethodDispatchParser>,
|
||||
Single<TransparencyParser>,
|
||||
Single<TypeLengthLimitParser>,
|
||||
Single<WithoutArgs<AllowIncoherentImplParser>>,
|
||||
Single<WithoutArgs<AllowInternalUnsafeParser>>,
|
||||
Single<WithoutArgs<AsPtrParser>>,
|
||||
Single<WithoutArgs<AutomaticallyDerivedParser>>,
|
||||
Single<WithoutArgs<CoherenceIsCoreParser>>,
|
||||
Single<WithoutArgs<CoinductiveParser>>,
|
||||
Single<WithoutArgs<ColdParser>>,
|
||||
Single<WithoutArgs<ConstContinueParser>>,
|
||||
|
|
@ -215,8 +223,10 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<MacroEscapeParser>>,
|
||||
Single<WithoutArgs<MarkerParser>>,
|
||||
Single<WithoutArgs<MayDangleParser>>,
|
||||
Single<WithoutArgs<NoCoreParser>>,
|
||||
Single<WithoutArgs<NoImplicitPreludeParser>>,
|
||||
Single<WithoutArgs<NoMangleParser>>,
|
||||
Single<WithoutArgs<NoStdParser>>,
|
||||
Single<WithoutArgs<NonExhaustiveParser>>,
|
||||
Single<WithoutArgs<ParenSugarParser>>,
|
||||
Single<WithoutArgs<PassByValueParser>>,
|
||||
|
|
@ -224,6 +234,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<ProcMacroAttributeParser>>,
|
||||
Single<WithoutArgs<ProcMacroParser>>,
|
||||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
|
||||
Single<WithoutArgs<SpecializationTraitParser>>,
|
||||
Single<WithoutArgs<StdInternalSymbolParser>>,
|
||||
Single<WithoutArgs<TrackCallerParser>>,
|
||||
|
|
@ -346,7 +357,10 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
|
|||
/// must be delayed until after HIR is built. This method will take care of the details of
|
||||
/// that.
|
||||
pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
|
||||
if matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
|
||||
if !matches!(
|
||||
self.stage.should_emit(),
|
||||
ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true }
|
||||
) {
|
||||
return;
|
||||
}
|
||||
let id = self.target_id;
|
||||
|
|
@ -670,20 +684,20 @@ pub enum ShouldEmit {
|
|||
///
|
||||
/// Only relevant when early parsing, in late parsing equivalent to `ErrorsAndLints`.
|
||||
/// Late parsing is never fatal, and instead tries to emit as many diagnostics as possible.
|
||||
EarlyFatal,
|
||||
EarlyFatal { also_emit_lints: bool },
|
||||
/// The operation will emit errors and lints.
|
||||
/// This is usually what you need.
|
||||
ErrorsAndLints,
|
||||
/// The operation will emit *not* errors and lints.
|
||||
/// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::Emit`.
|
||||
/// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::ErrorsAndLints`.
|
||||
Nothing,
|
||||
}
|
||||
|
||||
impl ShouldEmit {
|
||||
pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {
|
||||
match self {
|
||||
ShouldEmit::EarlyFatal if diag.level() == Level::DelayedBug => diag.emit(),
|
||||
ShouldEmit::EarlyFatal => diag.upgrade_to_fatal().emit(),
|
||||
ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(),
|
||||
ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(),
|
||||
ShouldEmit::ErrorsAndLints => diag.emit(),
|
||||
ShouldEmit::Nothing => diag.delay_as_bug(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -272,7 +272,6 @@ 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(&accept.allowed_targets, target, &mut cx);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,18 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<L::Id>, lint_emi
|
|||
},
|
||||
);
|
||||
}
|
||||
AttributeLintKind::InvalidMacroExportArguments { suggestions } => lint_emitter
|
||||
.emit_node_span_lint(
|
||||
rustc_session::lint::builtin::INVALID_MACRO_EXPORT_ARGUMENTS,
|
||||
*id,
|
||||
*span,
|
||||
session_diagnostics::IllFormedAttributeInput {
|
||||
num_suggestions: suggestions.len(),
|
||||
suggestions: DiagArgValue::StrListSepByAnd(
|
||||
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
|
||||
),
|
||||
},
|
||||
),
|
||||
AttributeLintKind::EmptyAttribute { first_span } => lint_emitter.emit_node_span_lint(
|
||||
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
|
||||
*id,
|
||||
|
|
|
|||
|
|
@ -459,6 +459,34 @@ pub(crate) struct NullOnLinkSection {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_null_on_objc_class)]
|
||||
pub(crate) struct NullOnObjcClass {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_null_on_objc_selector)]
|
||||
pub(crate) struct NullOnObjcSelector {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_objc_class_expected_string_literal)]
|
||||
pub(crate) struct ObjcClassExpectedStringLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_objc_selector_expected_string_literal)]
|
||||
pub(crate) struct ObjcSelectorExpectedStringLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_stability_outside_std, code = E0734)]
|
||||
pub(crate) struct StabilityOutsideStd {
|
||||
|
|
@ -930,3 +958,13 @@ pub(crate) struct ImportNameTypeRaw {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_limit_invalid)]
|
||||
pub(crate) struct LimitInvalid<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label]
|
||||
pub value_span: Span,
|
||||
pub error_str: &'a str,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
|||
|
||||
use rustc_ast::AttrStyle;
|
||||
use rustc_errors::DiagArgValue;
|
||||
use rustc_feature::{AttributeType, Features};
|
||||
use rustc_feature::Features;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_hir::{MethodKind, Target};
|
||||
|
||||
|
|
@ -14,6 +14,11 @@ use crate::session_diagnostics::InvalidTarget;
|
|||
pub(crate) enum AllowedTargets {
|
||||
AllowList(&'static [Policy]),
|
||||
AllowListWarnRest(&'static [Policy]),
|
||||
/// Special, and not the same as `AllowList(&[Allow(Target::Crate)])`.
|
||||
/// For crate-level attributes we emit a specific set of lints to warn
|
||||
/// people about accidentally not using them on the crate.
|
||||
/// Only use this for attributes that are *exclusively* valid at the crate level.
|
||||
CrateLevel,
|
||||
}
|
||||
|
||||
pub(crate) enum AllowedResult {
|
||||
|
|
@ -43,6 +48,7 @@ impl AllowedTargets {
|
|||
AllowedResult::Warn
|
||||
}
|
||||
}
|
||||
AllowedTargets::CrateLevel => AllowedResult::Allowed,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,6 +56,7 @@ impl AllowedTargets {
|
|||
match self {
|
||||
AllowedTargets::AllowList(list) => list,
|
||||
AllowedTargets::AllowListWarnRest(list) => list,
|
||||
AllowedTargets::CrateLevel => ALL_TARGETS,
|
||||
}
|
||||
.iter()
|
||||
.filter_map(|target| match target {
|
||||
|
|
@ -74,6 +81,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
target: Target,
|
||||
cx: &mut AcceptContext<'_, 'sess, S>,
|
||||
) {
|
||||
Self::check_type(matches!(allowed_targets, AllowedTargets::CrateLevel), target, cx);
|
||||
|
||||
match allowed_targets.is_allowed(target) {
|
||||
AllowedResult::Allowed => {}
|
||||
AllowedResult::Warn => {
|
||||
|
|
@ -109,7 +118,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
}
|
||||
|
||||
pub(crate) fn check_type(
|
||||
attribute_type: AttributeType,
|
||||
crate_level: bool,
|
||||
target: Target,
|
||||
cx: &mut AcceptContext<'_, 'sess, S>,
|
||||
) {
|
||||
|
|
@ -119,7 +128,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
return;
|
||||
}
|
||||
|
||||
if attribute_type != AttributeType::CrateLevel {
|
||||
if !crate_level {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -438,7 +438,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
|
||||
let elaborated_args =
|
||||
std::iter::zip(*args, &generics.own_params).map(|(arg, param)| {
|
||||
if let Some(ty::Dynamic(obj, _, ty::Dyn)) = arg.as_type().map(Ty::kind) {
|
||||
if let Some(ty::Dynamic(obj, _)) = arg.as_type().map(Ty::kind) {
|
||||
let default = tcx.object_lifetime_default(param.def_id);
|
||||
|
||||
let re_static = tcx.lifetimes.re_static;
|
||||
|
|
@ -464,7 +464,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
|
||||
has_dyn = true;
|
||||
|
||||
Ty::new_dynamic(tcx, obj, implied_region, ty::Dyn).into()
|
||||
Ty::new_dynamic(tcx, obj, implied_region).into()
|
||||
} else {
|
||||
arg
|
||||
}
|
||||
|
|
|
|||
|
|
@ -716,7 +716,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
return (false, false, None);
|
||||
};
|
||||
|
||||
let implemented_trait_item = self.infcx.tcx.associated_item(my_def).trait_item_def_id;
|
||||
let implemented_trait_item = self.infcx.tcx.trait_item_of(my_def);
|
||||
|
||||
(
|
||||
true,
|
||||
|
|
|
|||
|
|
@ -166,13 +166,9 @@ impl RegionTracker {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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())
|
||||
|| other.reachable_placeholders.can_be_named_by(self.max_nameable_universe())
|
||||
/// Determine if we can name all the placeholders in `other`.
|
||||
pub(crate) fn can_name_all_placeholders(&self, other: Self) -> bool {
|
||||
other.reachable_placeholders.can_be_named_by(self.max_nameable_universe.0)
|
||||
}
|
||||
|
||||
/// If this SCC reaches a placeholder it can't name, return it.
|
||||
|
|
|
|||
|
|
@ -1557,9 +1557,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
&(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
|
||||
&Rvalue::Discriminant(place) => {
|
||||
let af = match *rvalue {
|
||||
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
|
||||
Rvalue::Discriminant(..) => None,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
|
@ -1904,7 +1903,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
|
|||
| ty::Slice(_)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Dynamic(_, _, _)
|
||||
| ty::Dynamic(_, _)
|
||||
| ty::Closure(_, _)
|
||||
| ty::CoroutineClosure(_, _)
|
||||
| ty::Coroutine(_, _)
|
||||
|
|
@ -1950,7 +1949,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
|
|||
| ty::Ref(_, _, _)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Dynamic(_, _, _)
|
||||
| ty::Dynamic(_, _)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Never
|
||||
| ty::UnsafeBinder(_)
|
||||
|
|
|
|||
|
|
@ -306,16 +306,11 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
|
|||
self.consume_operand(location, op);
|
||||
}
|
||||
|
||||
&(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
|
||||
let af = match rvalue {
|
||||
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
|
||||
Rvalue::Discriminant(..) => None,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
&Rvalue::Discriminant(place) => {
|
||||
self.access_place(
|
||||
location,
|
||||
place,
|
||||
(Shallow(af), Read(ReadKind::Copy)),
|
||||
(Shallow(None), Read(ReadKind::Copy)),
|
||||
LocalMutationIsAllowed::No,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -571,11 +571,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if all the elements in the value of `scc_b` are nameable
|
||||
/// Returns `true` if all the placeholders in the value of `scc_b` are nameable
|
||||
/// in `scc_a`. Used during constraint propagation, and only once
|
||||
/// the value of `scc_b` has been computed.
|
||||
fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccIndex) -> bool {
|
||||
self.scc_annotations[scc_a].universe_compatible_with(self.scc_annotations[scc_b])
|
||||
fn can_name_all_placeholders(
|
||||
&self,
|
||||
scc_a: ConstraintSccIndex,
|
||||
scc_b: ConstraintSccIndex,
|
||||
) -> bool {
|
||||
self.scc_annotations[scc_a].can_name_all_placeholders(self.scc_annotations[scc_b])
|
||||
}
|
||||
|
||||
/// Once regions have been propagated, this method is used to see
|
||||
|
|
@ -615,7 +619,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
}
|
||||
|
||||
// Type-test failed. Report the error.
|
||||
let erased_generic_kind = infcx.tcx.erase_regions(type_test.generic_kind);
|
||||
let erased_generic_kind = infcx.tcx.erase_and_anonymize_regions(type_test.generic_kind);
|
||||
|
||||
// Skip duplicate-ish errors.
|
||||
if deduplicate_errors.insert((
|
||||
|
|
@ -964,16 +968,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
return true;
|
||||
}
|
||||
|
||||
let fr_static = self.universal_regions().fr_static;
|
||||
|
||||
// If we are checking that `'sup: 'sub`, and `'sub` contains
|
||||
// some placeholder that `'sup` cannot name, then this is only
|
||||
// true if `'sup` outlives static.
|
||||
if !self.universe_compatible(sub_region_scc, sup_region_scc) {
|
||||
//
|
||||
// Avoid infinite recursion if `sub_region` is already `'static`
|
||||
if sub_region != fr_static
|
||||
&& !self.can_name_all_placeholders(sup_region_scc, sub_region_scc)
|
||||
{
|
||||
debug!(
|
||||
"sub universe `{sub_region_scc:?}` is not nameable \
|
||||
by super `{sup_region_scc:?}`, promoting to static",
|
||||
);
|
||||
|
||||
return self.eval_outlives(sup_region, self.universal_regions().fr_static);
|
||||
return self.eval_outlives(sup_region, fr_static);
|
||||
}
|
||||
|
||||
// Both the `sub_region` and `sup_region` consist of the union
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ fn compute_concrete_types_from_defining_uses<'tcx>(
|
|||
//
|
||||
// FIXME(-Znext-solver): This isn't necessary after all. We can remove this check again.
|
||||
if let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
|
||||
rcx.infcx.tcx.erase_regions(opaque_type_key),
|
||||
rcx.infcx.tcx.erase_and_anonymize_regions(opaque_type_key),
|
||||
(opaque_type_key, hidden_type.span),
|
||||
) && let Some((arg1, arg2)) = std::iter::zip(
|
||||
prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
|
||||
|
|
|
|||
|
|
@ -230,8 +230,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
location: impl NormalizeLocation,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
let body = self.body;
|
||||
|
||||
let cause = ObligationCause::misc(
|
||||
location.to_locations().span(body),
|
||||
body.source.def_id().expect_local(),
|
||||
);
|
||||
|
||||
if self.infcx.next_trait_solver() {
|
||||
let body = self.body;
|
||||
let param_env = self.infcx.param_env;
|
||||
// FIXME: Make this into a real type op?
|
||||
self.fully_perform_op(
|
||||
|
|
@ -241,10 +247,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
|ocx| {
|
||||
let structurally_normalize = |ty| {
|
||||
ocx.structurally_normalize_ty(
|
||||
&ObligationCause::misc(
|
||||
location.to_locations().span(body),
|
||||
body.source.def_id().expect_local(),
|
||||
),
|
||||
&cause,
|
||||
param_env,
|
||||
ty,
|
||||
)
|
||||
|
|
@ -253,6 +256,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
|
||||
let tail = tcx.struct_tail_raw(
|
||||
ty,
|
||||
&cause,
|
||||
structurally_normalize,
|
||||
|| {},
|
||||
);
|
||||
|
|
@ -265,7 +269,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
.unwrap_or_else(|guar| Ty::new_error(tcx, guar))
|
||||
} else {
|
||||
let mut normalize = |ty| self.normalize(ty, location);
|
||||
let tail = tcx.struct_tail_raw(ty, &mut normalize, || {});
|
||||
let tail = tcx.struct_tail_raw(ty, &cause, &mut normalize, || {});
|
||||
normalize(tail)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1487,9 +1487,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
unsize_to: None,
|
||||
},
|
||||
);
|
||||
} else if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) =
|
||||
} else if let ty::Dynamic(src_tty, _src_lt) =
|
||||
*self.struct_tail(src.ty, location).kind()
|
||||
&& let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) =
|
||||
&& let ty::Dynamic(dst_tty, dst_lt) =
|
||||
*self.struct_tail(dst.ty, location).kind()
|
||||
&& src_tty.principal().is_some()
|
||||
&& dst_tty.principal().is_some()
|
||||
|
|
@ -1511,7 +1511,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
// FIXME: Once we disallow casting `*const dyn Trait + 'short`
|
||||
// to `*const dyn Trait + 'long`, then this can just be `src_lt`.
|
||||
dst_lt,
|
||||
ty::Dyn,
|
||||
);
|
||||
let dst_obj = Ty::new_dynamic(
|
||||
tcx,
|
||||
|
|
@ -1519,7 +1518,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
&dst_tty.without_auto_traits().collect::<Vec<_>>(),
|
||||
),
|
||||
dst_lt,
|
||||
ty::Dyn,
|
||||
);
|
||||
|
||||
debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
|
||||
|
|
@ -1631,7 +1629,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
| Rvalue::BinaryOp(..)
|
||||
| Rvalue::RawPtr(..)
|
||||
| Rvalue::ThreadLocalRef(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::Discriminant(..)
|
||||
| Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
|
||||
}
|
||||
|
|
@ -1892,7 +1889,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
if is_diverging {
|
||||
// The signature in this call can reference region variables,
|
||||
// so erase them before calling a query.
|
||||
let output_ty = self.tcx().erase_regions(sig.output());
|
||||
let output_ty = self.tcx().erase_and_anonymize_regions(sig.output());
|
||||
if !output_ty
|
||||
.is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.infcx.param_env))
|
||||
{
|
||||
|
|
@ -1986,7 +1983,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
|
||||
let op_arg_ty = self.normalize(op_arg_ty, term_location);
|
||||
let category = if call_source.from_hir_call() {
|
||||
ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty)))
|
||||
ConstraintCategory::CallArgument(Some(
|
||||
self.infcx.tcx.erase_and_anonymize_regions(func_ty),
|
||||
))
|
||||
} else {
|
||||
ConstraintCategory::Boring
|
||||
};
|
||||
|
|
@ -2120,7 +2119,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
// Erase the regions from `ty` to get a global type. The
|
||||
// `Sized` bound in no way depends on precise regions, so this
|
||||
// shouldn't affect `is_sized`.
|
||||
let erased_ty = tcx.erase_regions(ty);
|
||||
let erased_ty = tcx.erase_and_anonymize_regions(ty);
|
||||
// FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here.
|
||||
if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
|
||||
// in current MIR construction, all non-control-flow rvalue
|
||||
|
|
@ -2199,7 +2198,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
| Rvalue::Repeat(..)
|
||||
| Rvalue::Ref(..)
|
||||
| Rvalue::RawPtr(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::Cast(..)
|
||||
| Rvalue::ShallowInitBox(..)
|
||||
| Rvalue::BinaryOp(..)
|
||||
|
|
|
|||
|
|
@ -33,3 +33,8 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
|||
thin-vec = "0.2.12"
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[features]
|
||||
# tidy-alphabetical-start
|
||||
llvm_enzyme = []
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -64,6 +64,11 @@ builtin_macros_autodiff_ty_activity = {$act} can not be used for this type
|
|||
builtin_macros_autodiff_unknown_activity = did not recognize Activity: `{$act}`
|
||||
|
||||
builtin_macros_autodiff_width = autodiff width must fit u32, but is {$width}
|
||||
|
||||
builtin_macros_avoid_att_syntax = avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
|
||||
|
||||
builtin_macros_avoid_intel_syntax = avoid using `.intel_syntax`, Intel syntax is the default
|
||||
|
||||
builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
|
||||
.label = not applicable here
|
||||
.label2 = not a `struct`, `enum` or `union`
|
||||
|
|
@ -138,6 +143,8 @@ builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept a
|
|||
builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
|
||||
.suggestion = remove the value
|
||||
|
||||
builtin_macros_duplicate_macro_attribute = duplicated attribute
|
||||
|
||||
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
|
||||
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
|
||||
.custom = use `std::env::var({$var_expr})` to read the variable at run time
|
||||
|
|
@ -231,6 +238,8 @@ builtin_macros_derive_from_wrong_field_count = `#[derive(From)]` used on a struc
|
|||
|
||||
builtin_macros_derive_from_usage_note = `#[derive(From)]` can only be used on structs with exactly one field
|
||||
|
||||
builtin_macros_incomplete_include = include macro expected single expression in source
|
||||
|
||||
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
|
||||
.note = only one `#[default]` attribute is needed
|
||||
.label = `#[default]` used here
|
||||
|
|
@ -294,3 +303,5 @@ builtin_macros_unexpected_lit = expected path to a trait, found literal
|
|||
.label = not a trait
|
||||
.str_lit = try using `#[derive({$sym})]`
|
||||
.other = for example, write `#[derive(Debug)]` for `Debug`
|
||||
|
||||
builtin_macros_unnameable_test_items = cannot test inner items
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use lint::BuiltinLintDiag;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{AsmMacro, token};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
|
|
@ -352,7 +351,7 @@ fn expand_preparsed_asm(
|
|||
lint::builtin::BAD_ASM_STYLE,
|
||||
find_span(".intel_syntax"),
|
||||
ecx.current_expansion.lint_node_id,
|
||||
BuiltinLintDiag::AvoidUsingIntelSyntax,
|
||||
errors::AvoidIntelSyntax,
|
||||
);
|
||||
}
|
||||
if template_str.contains(".att_syntax") {
|
||||
|
|
@ -360,7 +359,7 @@ fn expand_preparsed_asm(
|
|||
lint::builtin::BAD_ASM_STYLE,
|
||||
find_span(".att_syntax"),
|
||||
ecx.current_expansion.lint_node_id,
|
||||
BuiltinLintDiag::AvoidUsingAttSyntax,
|
||||
errors::AvoidAttSyntax,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
mod context;
|
||||
|
||||
use rustc_ast::token::{self, Delimiter};
|
||||
use rustc_ast::token::Delimiter;
|
||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
|
||||
use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment};
|
||||
use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp, token};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::PResult;
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
|
|
@ -29,7 +29,7 @@ pub(crate) fn expand_assert<'cx>(
|
|||
|
||||
// `core::panic` and `std::panic` are different macros, so we use call-site
|
||||
// context to pick up whichever is currently in scope.
|
||||
let call_site_span = cx.with_call_site_ctxt(cond_expr.span);
|
||||
let call_site_span = cx.with_call_site_ctxt(span);
|
||||
|
||||
let panic_path = || {
|
||||
if use_panic_2021(span) {
|
||||
|
|
@ -63,7 +63,7 @@ pub(crate) fn expand_assert<'cx>(
|
|||
}),
|
||||
})),
|
||||
);
|
||||
assert_cond_check(cx, call_site_span, cond_expr, then)
|
||||
expr_if_not(cx, call_site_span, cond_expr, then, None)
|
||||
}
|
||||
// If `generic_assert` is enabled, generates rich captured outputs
|
||||
//
|
||||
|
|
@ -88,33 +88,26 @@ pub(crate) fn expand_assert<'cx>(
|
|||
)),
|
||||
)],
|
||||
);
|
||||
assert_cond_check(cx, call_site_span, cond_expr, then)
|
||||
expr_if_not(cx, call_site_span, cond_expr, then, None)
|
||||
};
|
||||
|
||||
ExpandResult::Ready(MacEager::expr(expr))
|
||||
}
|
||||
|
||||
/// `assert!($cond_expr, $custom_message)`
|
||||
struct Assert {
|
||||
cond_expr: Box<Expr>,
|
||||
custom_message: Option<TokenStream>,
|
||||
}
|
||||
|
||||
/// `match <cond> { true => {} _ => <then> }`
|
||||
fn assert_cond_check(cx: &ExtCtxt<'_>, span: Span, cond: Box<Expr>, then: Box<Expr>) -> Box<Expr> {
|
||||
// Instead of expanding to `if !<cond> { <then> }`, we expand to
|
||||
// `match <cond> { true => {} _ => <then> }`.
|
||||
// This allows us to always complain about mismatched types instead of "cannot apply unary
|
||||
// operator `!` to type `X`" when passing an invalid `<cond>`, while also allowing `<cond>` to
|
||||
// be `&true`.
|
||||
let els = cx.expr_block(cx.block(span, thin_vec![]));
|
||||
let mut arms = thin_vec![];
|
||||
arms.push(cx.arm(span, cx.pat_lit(span, cx.expr_bool(span, true)), els));
|
||||
arms.push(cx.arm(span, cx.pat_wild(span), then));
|
||||
|
||||
// We wrap the `match` in a statement to limit the length of any borrows introduced in the
|
||||
// condition.
|
||||
cx.expr_block(cx.block(span, [cx.stmt_expr(cx.expr_match(span, cond, arms))].into()))
|
||||
// if !{ ... } { ... } else { ... }
|
||||
fn expr_if_not(
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
cond: Box<Expr>,
|
||||
then: Box<Expr>,
|
||||
els: Option<Box<Expr>>,
|
||||
) -> Box<Expr> {
|
||||
cx.expr_if(span, cx.expr(span, ExprKind::Unary(UnOp::Not, cond)), then, els)
|
||||
}
|
||||
|
||||
fn parse_assert<'a>(cx: &ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> {
|
||||
|
|
|
|||
|
|
@ -209,7 +209,8 @@ mod llvm_enzyme {
|
|||
mut item: Annotatable,
|
||||
mode: DiffMode,
|
||||
) -> Vec<Annotatable> {
|
||||
if cfg!(not(llvm_enzyme)) {
|
||||
// FIXME(bjorn3) maybe have the backend directly tell if autodiff is supported?
|
||||
if cfg!(not(feature = "llvm_enzyme")) {
|
||||
ecx.sess.dcx().emit_err(errors::AutoDiffSupportNotBuild { span: meta_item.span });
|
||||
return vec![item];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,43 +51,4 @@ pub(crate) fn expand_deriving_const_param_ty(
|
|||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: path_std!(marker::UnsizedConstParamTy),
|
||||
skip_path_as_bound: false,
|
||||
needs_copy_as_bound_if_packed: false,
|
||||
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
|
||||
supports_unions: false,
|
||||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
}
|
||||
|
||||
pub(crate) fn expand_deriving_unsized_const_param_ty(
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: path_std!(marker::UnsizedConstParamTy),
|
||||
skip_path_as_bound: false,
|
||||
needs_copy_as_bound_if_packed: false,
|
||||
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
|
||||
supports_unions: false,
|
||||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,29 @@ use rustc_errors::{
|
|||
Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans,
|
||||
Subdiagnostic,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(builtin_macros_avoid_intel_syntax)]
|
||||
pub(crate) struct AvoidIntelSyntax;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(builtin_macros_avoid_att_syntax)]
|
||||
pub(crate) struct AvoidAttSyntax;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(builtin_macros_incomplete_include)]
|
||||
pub(crate) struct IncompleteInclude;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(builtin_macros_unnameable_test_items)]
|
||||
pub(crate) struct UnnameableTestItems;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(builtin_macros_duplicate_macro_attribute)]
|
||||
pub(crate) struct DuplicateMacroAttribute;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_requires_cfg_pattern)]
|
||||
pub(crate) struct RequiresCfgPattern {
|
||||
|
|
|
|||
|
|
@ -565,9 +565,11 @@ fn make_format_args(
|
|||
&used,
|
||||
&args,
|
||||
&pieces,
|
||||
&invalid_refs,
|
||||
detect_foreign_fmt,
|
||||
str_style,
|
||||
fmt_str,
|
||||
uncooked_fmt_str.1.as_str(),
|
||||
fmt_span,
|
||||
);
|
||||
}
|
||||
|
|
@ -645,9 +647,11 @@ fn report_missing_placeholders(
|
|||
used: &[bool],
|
||||
args: &FormatArguments,
|
||||
pieces: &[parse::Piece<'_>],
|
||||
invalid_refs: &[(usize, Option<Span>, PositionUsedAs, FormatArgPositionKind)],
|
||||
detect_foreign_fmt: bool,
|
||||
str_style: Option<usize>,
|
||||
fmt_str: &str,
|
||||
uncooked_fmt_str: &str,
|
||||
fmt_span: Span,
|
||||
) {
|
||||
let mut diag = if let &[(span, named)] = &unused[..] {
|
||||
|
|
@ -762,6 +766,35 @@ fn report_missing_placeholders(
|
|||
diag.span_label(fmt_span, "formatting specifier missing");
|
||||
}
|
||||
|
||||
if !found_foreign && invalid_refs.is_empty() {
|
||||
// Show example if user didn't use any format specifiers
|
||||
let show_example = used.iter().all(|used| !used);
|
||||
|
||||
if !show_example {
|
||||
if unused.len() > 1 {
|
||||
diag.note(format!("consider adding {} format specifiers", unused.len()));
|
||||
}
|
||||
} else {
|
||||
let msg = if unused.len() == 1 {
|
||||
"a format specifier".to_string()
|
||||
} else {
|
||||
format!("{} format specifiers", unused.len())
|
||||
};
|
||||
|
||||
let sugg = match str_style {
|
||||
None => format!("\"{}{}\"", uncooked_fmt_str, "{}".repeat(unused.len())),
|
||||
Some(n_hashes) => format!(
|
||||
"r{hashes}\"{uncooked_fmt_str}{fmt_specifiers}\"{hashes}",
|
||||
hashes = "#".repeat(n_hashes),
|
||||
fmt_specifiers = "{}".repeat(unused.len())
|
||||
),
|
||||
};
|
||||
let msg = format!("format specifiers use curly braces, consider adding {msg}");
|
||||
|
||||
diag.span_suggestion_verbose(fmt_span, msg, sugg, Applicability::MaybeIncorrect);
|
||||
}
|
||||
}
|
||||
|
||||
diag.emit();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,6 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
|||
Clone: clone::expand_deriving_clone,
|
||||
Copy: bounds::expand_deriving_copy,
|
||||
ConstParamTy: bounds::expand_deriving_const_param_ty,
|
||||
UnsizedConstParamTy: bounds::expand_deriving_unsized_const_param_ty,
|
||||
Debug: debug::expand_deriving_debug,
|
||||
Default: default::expand_deriving_default,
|
||||
Eq: eq::expand_deriving_eq,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
//! The implementation of built-in macros which relate to the file system.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
|
@ -10,10 +12,11 @@ use rustc_expand::base::{
|
|||
DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, resolve_path,
|
||||
};
|
||||
use rustc_expand::module::DirOwnership;
|
||||
use rustc_lint_defs::BuiltinLintDiag;
|
||||
use rustc_parse::parser::{ForceCollect, Parser};
|
||||
use rustc_parse::lexer::StripTokens;
|
||||
use rustc_parse::parser::ForceCollect;
|
||||
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error};
|
||||
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{ByteSymbol, Pos, Span, Symbol};
|
||||
use smallvec::SmallVec;
|
||||
|
|
@ -23,11 +26,7 @@ use crate::util::{
|
|||
check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
|
||||
};
|
||||
|
||||
// These macros all relate to the file system; they either return
|
||||
// the column/row/filename of the expression, or they include
|
||||
// a given file into the current one.
|
||||
|
||||
/// line!(): expands to the current line number
|
||||
/// Expand `line!()` to the current line number.
|
||||
pub(crate) fn expand_line(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -42,7 +41,7 @@ pub(crate) fn expand_line(
|
|||
ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.line as u32)))
|
||||
}
|
||||
|
||||
/* column!(): expands to the current column number */
|
||||
/// Expand `column!()` to the current column number.
|
||||
pub(crate) fn expand_column(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -57,9 +56,7 @@ pub(crate) fn expand_column(
|
|||
ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1)))
|
||||
}
|
||||
|
||||
/// file!(): expands to the current filename */
|
||||
/// The source_file (`loc.file`) contains a bunch more information we could spit
|
||||
/// out if we wanted.
|
||||
/// Expand `file!()` to the current filename.
|
||||
pub(crate) fn expand_file(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -81,6 +78,7 @@ pub(crate) fn expand_file(
|
|||
)))
|
||||
}
|
||||
|
||||
/// Expand `stringify!($input)`.
|
||||
pub(crate) fn expand_stringify(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -91,6 +89,7 @@ pub(crate) fn expand_stringify(
|
|||
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))))
|
||||
}
|
||||
|
||||
/// Expand `module_path!()` to (a textual representation of) the current module path.
|
||||
pub(crate) fn expand_mod(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -104,9 +103,9 @@ pub(crate) fn expand_mod(
|
|||
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))))
|
||||
}
|
||||
|
||||
/// include! : parse the given file as an expr
|
||||
/// This is generally a bad idea because it's going to behave
|
||||
/// unhygienically.
|
||||
/// Expand `include!($input)`.
|
||||
///
|
||||
/// This works in item and expression position. Notably, it doesn't work in pattern position.
|
||||
pub(crate) fn expand_include<'cx>(
|
||||
cx: &'cx mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -116,64 +115,76 @@ pub(crate) fn expand_include<'cx>(
|
|||
let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include!") else {
|
||||
return ExpandResult::Retry(());
|
||||
};
|
||||
let file = match mac {
|
||||
Ok(file) => file,
|
||||
let path = match mac {
|
||||
Ok(path) => path,
|
||||
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
|
||||
};
|
||||
// The file will be added to the code map by the parser
|
||||
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
|
||||
Ok(f) => f,
|
||||
let path = match resolve_path(&cx.sess, path.as_str(), sp) {
|
||||
Ok(path) => path,
|
||||
Err(err) => {
|
||||
let guar = err.emit();
|
||||
return ExpandResult::Ready(DummyResult::any(sp, guar));
|
||||
}
|
||||
};
|
||||
let p = unwrap_or_emit_fatal(new_parser_from_file(cx.psess(), &file, Some(sp)));
|
||||
|
||||
// If in the included file we have e.g., `mod bar;`,
|
||||
// then the path of `bar.rs` should be relative to the directory of `file`.
|
||||
// then the path of `bar.rs` should be relative to the directory of `path`.
|
||||
// See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion.
|
||||
// `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained.
|
||||
let dir_path = file.parent().unwrap_or(&file).to_owned();
|
||||
let dir_path = path.parent().unwrap_or(&path).to_owned();
|
||||
cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path));
|
||||
cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None };
|
||||
|
||||
struct ExpandInclude<'a> {
|
||||
p: Parser<'a>,
|
||||
psess: &'a ParseSess,
|
||||
path: PathBuf,
|
||||
node_id: ast::NodeId,
|
||||
span: Span,
|
||||
}
|
||||
impl<'a> MacResult for ExpandInclude<'a> {
|
||||
fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> {
|
||||
let expr = parse_expr(&mut self.p).ok()?;
|
||||
if self.p.token != token::Eof {
|
||||
self.p.psess.buffer_lint(
|
||||
fn make_expr(self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> {
|
||||
let mut p = unwrap_or_emit_fatal(new_parser_from_file(
|
||||
self.psess,
|
||||
&self.path,
|
||||
// Don't strip frontmatter for backward compatibility, `---` may be the start of a
|
||||
// manifold negation. FIXME: Ideally, we wouldn't strip shebangs here either.
|
||||
StripTokens::Shebang,
|
||||
Some(self.span),
|
||||
));
|
||||
let expr = parse_expr(&mut p).ok()?;
|
||||
if p.token != token::Eof {
|
||||
p.psess.buffer_lint(
|
||||
INCOMPLETE_INCLUDE,
|
||||
self.p.token.span,
|
||||
p.token.span,
|
||||
self.node_id,
|
||||
BuiltinLintDiag::IncompleteInclude,
|
||||
errors::IncompleteInclude,
|
||||
);
|
||||
}
|
||||
Some(expr)
|
||||
}
|
||||
|
||||
fn make_items(mut self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
|
||||
fn make_items(self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
|
||||
let mut p = unwrap_or_emit_fatal(new_parser_from_file(
|
||||
self.psess,
|
||||
&self.path,
|
||||
StripTokens::ShebangAndFrontmatter,
|
||||
Some(self.span),
|
||||
));
|
||||
let mut ret = SmallVec::new();
|
||||
loop {
|
||||
match self.p.parse_item(ForceCollect::No) {
|
||||
match p.parse_item(ForceCollect::No) {
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
break;
|
||||
}
|
||||
Ok(Some(item)) => ret.push(item),
|
||||
Ok(None) => {
|
||||
if self.p.token != token::Eof {
|
||||
self.p
|
||||
.dcx()
|
||||
.create_err(errors::ExpectedItem {
|
||||
span: self.p.token.span,
|
||||
token: &pprust::token_to_string(&self.p.token),
|
||||
})
|
||||
.emit();
|
||||
if p.token != token::Eof {
|
||||
p.dcx().emit_err(errors::ExpectedItem {
|
||||
span: p.token.span,
|
||||
token: &pprust::token_to_string(&p.token),
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -184,10 +195,17 @@ pub(crate) fn expand_include<'cx>(
|
|||
}
|
||||
}
|
||||
|
||||
ExpandResult::Ready(Box::new(ExpandInclude { p, node_id: cx.current_expansion.lint_node_id }))
|
||||
ExpandResult::Ready(Box::new(ExpandInclude {
|
||||
psess: cx.psess(),
|
||||
path,
|
||||
node_id: cx.current_expansion.lint_node_id,
|
||||
span: sp,
|
||||
}))
|
||||
}
|
||||
|
||||
/// `include_str!`: read the given file, insert it as a literal string expr
|
||||
/// Expand `include_str!($input)` to the content of the UTF-8-encoded file given by path `$input` as a string literal.
|
||||
///
|
||||
/// This works in expression, pattern and statement position.
|
||||
pub(crate) fn expand_include_str(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -206,6 +224,7 @@ pub(crate) fn expand_include_str(
|
|||
Ok((bytes, bsp)) => match std::str::from_utf8(&bytes) {
|
||||
Ok(src) => {
|
||||
let interned_src = Symbol::intern(src);
|
||||
// MacEager converts the expr into a pat if need be.
|
||||
MacEager::expr(cx.expr_str(cx.with_def_site_ctxt(bsp), interned_src))
|
||||
}
|
||||
Err(utf8err) => {
|
||||
|
|
@ -218,6 +237,9 @@ pub(crate) fn expand_include_str(
|
|||
})
|
||||
}
|
||||
|
||||
/// Expand `include_bytes!($input)` to the content of the file given by path `$input`.
|
||||
///
|
||||
/// This works in expression, pattern and statement position.
|
||||
pub(crate) fn expand_include_bytes(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
|
|
@ -237,6 +259,7 @@ pub(crate) fn expand_include_bytes(
|
|||
// Don't care about getting the span for the raw bytes,
|
||||
// because the console can't really show them anyway.
|
||||
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(ByteSymbol::intern(&bytes)));
|
||||
// MacEager converts the expr into a pat if need be.
|
||||
MacEager::expr(expr)
|
||||
}
|
||||
Err(dummy) => dummy,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ use rustc_errors::DiagCtxtHandle;
|
|||
use rustc_expand::base::{ExtCtxt, ResolverExpand};
|
||||
use rustc_expand::expand::{AstFragment, ExpansionConfig};
|
||||
use rustc_feature::Features;
|
||||
use rustc_lint_defs::BuiltinLintDiag;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::builtin::UNNAMEABLE_TEST_ITEMS;
|
||||
use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency};
|
||||
|
|
@ -165,7 +164,7 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> {
|
|||
UNNAMEABLE_TEST_ITEMS,
|
||||
attr.span,
|
||||
i.id,
|
||||
BuiltinLintDiag::UnnameableTestItems,
|
||||
errors::UnnameableTestItems,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
|
|||
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt};
|
||||
use rustc_expand::expand::AstFragment;
|
||||
use rustc_feature::AttributeTemplate;
|
||||
use rustc_lint_defs::BuiltinLintDiag;
|
||||
use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
|
||||
use rustc_parse::{exp, parser};
|
||||
use rustc_session::errors::report_lit_error;
|
||||
|
|
@ -49,7 +48,7 @@ pub(crate) fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable,
|
|||
DUPLICATE_MACRO_ATTRIBUTES,
|
||||
attr.span,
|
||||
ecx.current_expansion.lint_node_id,
|
||||
BuiltinLintDiag::DuplicateMacroAttribute,
|
||||
errors::DuplicateMacroAttribute,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -715,7 +715,7 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
fx.bcx.ins().jump(ret_block, &[]);
|
||||
} else {
|
||||
match ty.kind() {
|
||||
ty::Dynamic(_, _, ty::Dyn) => {
|
||||
ty::Dynamic(_, _) => {
|
||||
// IN THIS ARM, WE HAVE:
|
||||
// ty = *mut (dyn Trait)
|
||||
// which is: exists<T> ( *mut T, Vtable<T: Trait> )
|
||||
|
|
|
|||
|
|
@ -834,12 +834,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
|
|||
fx.bcx.ins().nop();
|
||||
}
|
||||
}
|
||||
Rvalue::Len(place) => {
|
||||
let place = codegen_place(fx, place);
|
||||
let usize_layout = fx.layout_of(fx.tcx.types.usize);
|
||||
let len = codegen_array_len(fx, place);
|
||||
lval.write_cvalue(fx, CValue::by_val(len, usize_layout));
|
||||
}
|
||||
Rvalue::ShallowInitBox(ref operand, content_ty) => {
|
||||
let content_ty = fx.monomorphize(content_ty);
|
||||
let box_layout = fx.layout_of(Ty::new_box(fx.tcx, content_ty));
|
||||
|
|
|
|||
|
|
@ -30,9 +30,7 @@ pub(crate) fn unsized_info<'tcx>(
|
|||
fx.pointer_type,
|
||||
len.try_to_target_usize(fx.tcx).expect("expected monomorphic const in codegen") as i64,
|
||||
),
|
||||
(&ty::Dynamic(data_a, _, src_dyn_kind), &ty::Dynamic(data_b, _, target_dyn_kind))
|
||||
if src_dyn_kind == target_dyn_kind =>
|
||||
{
|
||||
(&ty::Dynamic(data_a, _), &ty::Dynamic(data_b, _)) => {
|
||||
let old_info =
|
||||
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
|
||||
let b_principal_def_id = data_b.principal_def_id();
|
||||
|
|
|
|||
|
|
@ -909,8 +909,7 @@ pub(crate) fn assert_assignable<'tcx>(
|
|||
);
|
||||
// fn(&T) -> for<'l> fn(&'l T) is allowed
|
||||
}
|
||||
(&ty::Dynamic(from_traits, _, _from_kind), &ty::Dynamic(to_traits, _, _to_kind)) => {
|
||||
// FIXME(dyn-star): Do the right thing with DynKinds
|
||||
(&ty::Dynamic(from_traits, _), &ty::Dynamic(to_traits, _)) => {
|
||||
for (from, to) in from_traits.iter().zip(to_traits) {
|
||||
let from = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), from);
|
||||
let to = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
|
|||
if global.to_rvalue().get_type() != val_llty {
|
||||
global.to_rvalue().set_type(val_llty);
|
||||
}
|
||||
|
||||
// NOTE: Alignment from attributes has already been applied to the allocation.
|
||||
set_global_alignment(self, global, alloc.align);
|
||||
|
||||
global.global_set_initializer_rvalue(value);
|
||||
|
|
|
|||
|
|
@ -730,7 +730,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
|||
if self.is_sized_indirect() {
|
||||
OperandValue::Ref(PlaceValue::new_sized(val, self.layout.align.abi)).store(bx, dst)
|
||||
} else if self.is_unsized_indirect() {
|
||||
bug!("unsized `ArgAbi` must be handled through `store_fn_arg`");
|
||||
bug!("unsized `ArgAbi` cannot be stored");
|
||||
} else if let PassMode::Cast { ref cast, .. } = self.mode {
|
||||
// FIXME(eddyb): Figure out when the simpler Store is safe, clang
|
||||
// uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
|
||||
|
|
@ -797,12 +797,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
|||
OperandValue::Pair(next(), next()).store(bx, dst);
|
||||
}
|
||||
PassMode::Indirect { meta_attrs: Some(_), .. } => {
|
||||
let place_val = PlaceValue {
|
||||
llval: next(),
|
||||
llextra: Some(next()),
|
||||
align: self.layout.align.abi,
|
||||
};
|
||||
OperandValue::Ref(place_val).store(bx, dst);
|
||||
bug!("unsized `ArgAbi` cannot be stored");
|
||||
}
|
||||
PassMode::Direct(_)
|
||||
| PassMode::Indirect { meta_attrs: None, .. }
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
|||
|
||||
// Make sure lifetimes are erased, to avoid generating distinct LLVM
|
||||
// types for Rust types that only differ in the choice of lifetimes.
|
||||
let normal_ty = cx.tcx.erase_regions(self.ty);
|
||||
let normal_ty = cx.tcx.erase_and_anonymize_regions(self.ty);
|
||||
|
||||
let mut defer = None;
|
||||
let ty = if self.ty != normal_ty {
|
||||
|
|
|
|||
|
|
@ -46,5 +46,6 @@ tracing = "0.1"
|
|||
[features]
|
||||
# tidy-alphabetical-start
|
||||
check_only = ["rustc_llvm/check_only"]
|
||||
llvm_enzyme = []
|
||||
# tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -215,9 +215,9 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
|||
let align = attrs.pointee_align.unwrap_or(self.layout.align.abi);
|
||||
OperandValue::Ref(PlaceValue::new_sized(val, align)).store(bx, dst);
|
||||
}
|
||||
// Unsized indirect qrguments
|
||||
// Unsized indirect arguments cannot be stored
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||
bug!("unsized `ArgAbi` must be handled through `store_fn_arg`");
|
||||
bug!("unsized `ArgAbi` cannot be stored");
|
||||
}
|
||||
PassMode::Cast { cast, pad_i32: _ } => {
|
||||
// The ABI mandates that the value is passed as a different struct representation.
|
||||
|
|
@ -272,12 +272,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
|||
OperandValue::Pair(next(), next()).store(bx, dst);
|
||||
}
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||
let place_val = PlaceValue {
|
||||
llval: next(),
|
||||
llextra: Some(next()),
|
||||
align: self.layout.align.abi,
|
||||
};
|
||||
OperandValue::Ref(place_val).store(bx, dst);
|
||||
bug!("unsized `ArgAbi` cannot be stored");
|
||||
}
|
||||
PassMode::Direct(_)
|
||||
| PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ }
|
||||
|
|
|
|||
|
|
@ -240,6 +240,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
}
|
||||
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
|
||||
constraints.extend_from_slice(&[
|
||||
"~{fflags}".to_string(),
|
||||
"~{vtype}".to_string(),
|
||||
"~{vl}".to_string(),
|
||||
"~{vxsat}".to_string(),
|
||||
|
|
|
|||
37
compiler/rustc_codegen_llvm/src/back/command_line_args.rs
Normal file
37
compiler/rustc_codegen_llvm/src/back/command_line_args.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Joins command-line arguments into a single space-separated string, quoting
|
||||
/// and escaping individual arguments as necessary.
|
||||
///
|
||||
/// The result is intended to be informational, for embedding in debug metadata,
|
||||
/// and might not be properly quoted/escaped for actual command-line use.
|
||||
pub(crate) fn quote_command_line_args(args: &[String]) -> String {
|
||||
// Start with a decent-sized buffer, since rustc invocations tend to be long.
|
||||
let mut buf = String::with_capacity(128);
|
||||
|
||||
for arg in args {
|
||||
if !buf.is_empty() {
|
||||
buf.push(' ');
|
||||
}
|
||||
|
||||
print_arg_quoted(&mut buf, arg);
|
||||
}
|
||||
|
||||
buf
|
||||
}
|
||||
|
||||
/// Equivalent to LLVM's `sys::printArg` with quoting always enabled
|
||||
/// (see llvm/lib/Support/Program.cpp).
|
||||
fn print_arg_quoted(buf: &mut String, arg: &str) {
|
||||
buf.reserve(arg.len() + 2);
|
||||
|
||||
buf.push('"');
|
||||
for ch in arg.chars() {
|
||||
if matches!(ch, '"' | '\\' | '$') {
|
||||
buf.push('\\');
|
||||
}
|
||||
buf.push(ch);
|
||||
}
|
||||
buf.push('"');
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#[test]
|
||||
fn quote_command_line_args() {
|
||||
use super::quote_command_line_args;
|
||||
|
||||
struct Case<'a> {
|
||||
args: &'a [&'a str],
|
||||
expected: &'a str,
|
||||
}
|
||||
|
||||
let cases = &[
|
||||
Case { args: &[], expected: "" },
|
||||
Case { args: &["--hello", "world"], expected: r#""--hello" "world""# },
|
||||
Case { args: &["--hello world"], expected: r#""--hello world""# },
|
||||
Case {
|
||||
args: &["plain", "$dollar", "spa ce", r"back\slash", r#""quote""#, "plain"],
|
||||
expected: r#""plain" "\$dollar" "spa ce" "back\\slash" "\"quote\"" "plain""#,
|
||||
},
|
||||
];
|
||||
|
||||
for &Case { args, expected } in cases {
|
||||
let args = args.iter().copied().map(str::to_owned).collect::<Vec<_>>();
|
||||
let actual = quote_command_line_args(&args);
|
||||
assert_eq!(actual, expected, "args {args:?}");
|
||||
}
|
||||
}
|
||||
|
|
@ -617,7 +617,7 @@ pub(crate) fn run_pass_manager(
|
|||
crate::builder::gpu_offload::handle_gpu_code(cgcx, &cx);
|
||||
}
|
||||
|
||||
if cfg!(llvm_enzyme) && enable_ad && !thin {
|
||||
if cfg!(feature = "llvm_enzyme") && enable_ad && !thin {
|
||||
let opt_stage = llvm::OptStage::FatLTO;
|
||||
let stage = write::AutodiffStage::PostAD;
|
||||
if !config.autodiff.contains(&config::AutoDiff::NoPostopt) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
pub(crate) mod archive;
|
||||
mod command_line_args;
|
||||
pub(crate) mod lto;
|
||||
pub(crate) mod owned_target_machine;
|
||||
mod profiling;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::ffi::CStr;
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr::NonNull;
|
||||
|
|
@ -39,13 +38,10 @@ impl OwnedTargetMachine {
|
|||
output_obj_file: &CStr,
|
||||
debug_info_compression: &CStr,
|
||||
use_emulated_tls: bool,
|
||||
args_cstr_buff: &[u8],
|
||||
argv0: &str,
|
||||
command_line_args: &str,
|
||||
use_wasm_eh: bool,
|
||||
) -> Result<Self, LlvmError<'static>> {
|
||||
// The argument list is passed as the concatenation of one or more C strings.
|
||||
// This implies that there must be a last byte, and it must be 0.
|
||||
assert_matches!(args_cstr_buff, [.., b'\0'], "the last byte must be a NUL terminator");
|
||||
|
||||
// SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed to data
|
||||
let tm_ptr = unsafe {
|
||||
llvm::LLVMRustCreateTargetMachine(
|
||||
|
|
@ -70,8 +66,10 @@ impl OwnedTargetMachine {
|
|||
output_obj_file.as_ptr(),
|
||||
debug_info_compression.as_ptr(),
|
||||
use_emulated_tls,
|
||||
args_cstr_buff.as_ptr(),
|
||||
args_cstr_buff.len(),
|
||||
argv0.as_ptr(),
|
||||
argv0.len(),
|
||||
command_line_args.as_ptr(),
|
||||
command_line_args.len(),
|
||||
use_wasm_eh,
|
||||
)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ use rustc_span::{BytePos, InnerSpan, Pos, SpanData, SyntaxContext, sym};
|
|||
use rustc_target::spec::{CodeModel, FloatAbi, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
|
||||
use tracing::{debug, trace};
|
||||
|
||||
use crate::back::command_line_args::quote_command_line_args;
|
||||
use crate::back::lto::ThinBuffer;
|
||||
use crate::back::owned_target_machine::OwnedTargetMachine;
|
||||
use crate::back::profiling::{
|
||||
|
|
@ -249,23 +250,15 @@ pub(crate) fn target_machine_factory(
|
|||
|
||||
let use_emulated_tls = matches!(sess.tls_model(), TlsModel::Emulated);
|
||||
|
||||
// copy the exe path, followed by path all into one buffer
|
||||
// null terminating them so we can use them as null terminated strings
|
||||
let args_cstr_buff = {
|
||||
let mut args_cstr_buff: Vec<u8> = Vec::new();
|
||||
let exe_path = std::env::current_exe().unwrap_or_default();
|
||||
let exe_path_str = exe_path.into_os_string().into_string().unwrap_or_default();
|
||||
|
||||
args_cstr_buff.extend_from_slice(exe_path_str.as_bytes());
|
||||
args_cstr_buff.push(0);
|
||||
|
||||
for arg in sess.expanded_args.iter() {
|
||||
args_cstr_buff.extend_from_slice(arg.as_bytes());
|
||||
args_cstr_buff.push(0);
|
||||
}
|
||||
|
||||
args_cstr_buff
|
||||
};
|
||||
// Command-line information to be included in the target machine.
|
||||
// This seems to only be used for embedding in PDB debuginfo files.
|
||||
// FIXME(Zalathar): Maybe skip this for non-PDB targets?
|
||||
let argv0 = std::env::current_exe()
|
||||
.unwrap_or_default()
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.unwrap_or_default();
|
||||
let command_line_args = quote_command_line_args(&sess.expanded_args);
|
||||
|
||||
let debuginfo_compression = sess.opts.debuginfo_compression.to_string();
|
||||
match sess.opts.debuginfo_compression {
|
||||
|
|
@ -323,7 +316,8 @@ pub(crate) fn target_machine_factory(
|
|||
&output_obj_file,
|
||||
&debuginfo_compression,
|
||||
use_emulated_tls,
|
||||
&args_cstr_buff,
|
||||
&argv0,
|
||||
&command_line_args,
|
||||
use_wasm_eh,
|
||||
)
|
||||
})
|
||||
|
|
@ -574,7 +568,8 @@ pub(crate) unsafe fn llvm_optimize(
|
|||
// FIXME(ZuseZ4): In a future update we could figure out how to only optimize individual functions getting
|
||||
// differentiated.
|
||||
|
||||
let consider_ad = cfg!(llvm_enzyme) && config.autodiff.contains(&config::AutoDiff::Enable);
|
||||
let consider_ad =
|
||||
cfg!(feature = "llvm_enzyme") && config.autodiff.contains(&config::AutoDiff::Enable);
|
||||
let run_enzyme = autodiff_stage == AutodiffStage::DuringAD;
|
||||
let print_before_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModBefore);
|
||||
let print_after_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModAfter);
|
||||
|
|
@ -740,7 +735,8 @@ pub(crate) fn optimize(
|
|||
|
||||
// If we know that we will later run AD, then we disable vectorization and loop unrolling.
|
||||
// Otherwise we pretend AD is already done and run the normal opt pipeline (=PostAD).
|
||||
let consider_ad = cfg!(llvm_enzyme) && config.autodiff.contains(&config::AutoDiff::Enable);
|
||||
let consider_ad =
|
||||
cfg!(feature = "llvm_enzyme") && config.autodiff.contains(&config::AutoDiff::Enable);
|
||||
let autodiff_stage = if consider_ad { AutodiffStage::PreAD } else { AutodiffStage::PostAD };
|
||||
// The embedded bitcode is used to run LTO/ThinLTO.
|
||||
// The bitcode obtained during the `codegen` phase is no longer suitable for performing LTO.
|
||||
|
|
|
|||
|
|
@ -109,18 +109,36 @@ pub(crate) fn compile_codegen_unit(
|
|||
attributes::apply_to_llfn(entry, llvm::AttributePlace::Function, &attrs);
|
||||
}
|
||||
|
||||
// Define Objective-C module info and module flags. Note, the module info will
|
||||
// also be added to the `llvm.compiler.used` variable, created later.
|
||||
//
|
||||
// These are only necessary when we need the linker to do its Objective-C-specific
|
||||
// magic. We could theoretically do it unconditionally, but at a slight cost to linker
|
||||
// performance in the common case where it's unnecessary.
|
||||
if !cx.objc_classrefs.borrow().is_empty() || !cx.objc_selrefs.borrow().is_empty() {
|
||||
if cx.objc_abi_version() == 1 {
|
||||
cx.define_objc_module_info();
|
||||
}
|
||||
cx.add_objc_module_flags();
|
||||
}
|
||||
|
||||
// Finalize code coverage by injecting the coverage map. Note, the coverage map will
|
||||
// also be added to the `llvm.compiler.used` variable, created next.
|
||||
if cx.sess().instrument_coverage() {
|
||||
cx.coverageinfo_finalize();
|
||||
}
|
||||
|
||||
// Create the llvm.used and llvm.compiler.used variables.
|
||||
// Create the llvm.used variable.
|
||||
if !cx.used_statics.is_empty() {
|
||||
cx.create_used_variable_impl(c"llvm.used", &cx.used_statics);
|
||||
}
|
||||
if !cx.compiler_used_statics.is_empty() {
|
||||
cx.create_used_variable_impl(c"llvm.compiler.used", &cx.compiler_used_statics);
|
||||
|
||||
// Create the llvm.compiler.used variable.
|
||||
{
|
||||
let compiler_used_statics = cx.compiler_used_statics.borrow();
|
||||
if !compiler_used_statics.is_empty() {
|
||||
cx.create_used_variable_impl(c"llvm.compiler.used", &compiler_used_statics);
|
||||
}
|
||||
}
|
||||
|
||||
// Run replace-all-uses-with for statics that need it. This must
|
||||
|
|
|
|||
|
|
@ -1091,16 +1091,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
ty: Ty<'tcx>,
|
||||
lhs: Self::Value,
|
||||
rhs: Self::Value,
|
||||
) -> Option<Self::Value> {
|
||||
// FIXME: See comment on the definition of `three_way_compare`.
|
||||
if crate::llvm_util::get_version() < (20, 0, 0) {
|
||||
return None;
|
||||
}
|
||||
|
||||
) -> Self::Value {
|
||||
let size = ty.primitive_size(self.tcx);
|
||||
let name = if ty.is_signed() { "llvm.scmp" } else { "llvm.ucmp" };
|
||||
|
||||
Some(self.call_intrinsic(name, &[self.type_i8(), self.type_ix(size.bits())], &[lhs, rhs]))
|
||||
self.call_intrinsic(name, &[self.type_i8(), self.type_ix(size.bits())], &[lhs, rhs])
|
||||
}
|
||||
|
||||
/* Miscellaneous instructions */
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ use std::ptr;
|
|||
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
|
||||
use rustc_codegen_ssa::common::TypeKind;
|
||||
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods};
|
||||
use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt, TypingEnv};
|
||||
use rustc_middle::ty::{Instance, PseudoCanonicalInput, TyCtxt, TypingEnv};
|
||||
use rustc_middle::{bug, ty};
|
||||
use rustc_target::callconv::PassMode;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::builder::{Builder, PlaceRef, UNNAMED};
|
||||
|
|
@ -16,9 +17,12 @@ use crate::value::Value;
|
|||
|
||||
pub(crate) fn adjust_activity_to_abi<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
fn_ty: Ty<'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
typing_env: TypingEnv<'tcx>,
|
||||
da: &mut Vec<DiffActivity>,
|
||||
) {
|
||||
let fn_ty = instance.ty(tcx, typing_env);
|
||||
|
||||
if !matches!(fn_ty.kind(), ty::FnDef(..)) {
|
||||
bug!("expected fn def for autodiff, got {:?}", fn_ty);
|
||||
}
|
||||
|
|
@ -27,8 +31,16 @@ pub(crate) fn adjust_activity_to_abi<'tcx>(
|
|||
// All we do is decide how to handle the arguments.
|
||||
let sig = fn_ty.fn_sig(tcx).skip_binder();
|
||||
|
||||
// FIXME(Sa4dUs): pass proper varargs once we have support for differentiating variadic functions
|
||||
let Ok(fn_abi) =
|
||||
tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty())))
|
||||
else {
|
||||
bug!("failed to get fn_abi of instance with empty varargs");
|
||||
};
|
||||
|
||||
let mut new_activities = vec![];
|
||||
let mut new_positions = vec![];
|
||||
let mut del_activities = 0;
|
||||
for (i, ty) in sig.inputs().iter().enumerate() {
|
||||
if let Some(inner_ty) = ty.builtin_deref(true) {
|
||||
if inner_ty.is_slice() {
|
||||
|
|
@ -80,6 +92,34 @@ pub(crate) fn adjust_activity_to_abi<'tcx>(
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let pci = PseudoCanonicalInput { typing_env: TypingEnv::fully_monomorphized(), value: *ty };
|
||||
|
||||
let layout = match tcx.layout_of(pci) {
|
||||
Ok(layout) => layout.layout,
|
||||
Err(_) => {
|
||||
bug!("failed to compute layout for type {:?}", ty);
|
||||
}
|
||||
};
|
||||
|
||||
let pass_mode = &fn_abi.args[i].mode;
|
||||
|
||||
// For ZST, just ignore and don't add its activity, as this arg won't be present
|
||||
// in the LLVM passed to Enzyme.
|
||||
// Some targets pass ZST indirectly in the C ABI, in that case, handle it as a normal arg
|
||||
// FIXME(Sa4dUs): Enforce ZST corresponding diff activity be `Const`
|
||||
if *pass_mode == PassMode::Ignore {
|
||||
del_activities += 1;
|
||||
da.remove(i);
|
||||
}
|
||||
|
||||
// If the argument is lowered as a `ScalarPair`, we need to duplicate its activity.
|
||||
// Otherwise, the number of activities won't match the number of LLVM arguments and
|
||||
// this will lead to errors when verifying the Enzyme call.
|
||||
if let rustc_abi::BackendRepr::ScalarPair(_, _) = layout.backend_repr() {
|
||||
new_activities.push(da[i].clone());
|
||||
new_positions.push(i + 1 - del_activities);
|
||||
}
|
||||
}
|
||||
// now add the extra activities coming from slices
|
||||
// Reverse order to not invalidate the indices
|
||||
|
|
|
|||
|
|
@ -108,6 +108,10 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
|
|||
bytes_in_context(self.llcx(), bytes)
|
||||
}
|
||||
|
||||
pub(crate) fn null_terminate_const_bytes(&self, bytes: &[u8]) -> &'ll Value {
|
||||
null_terminate_bytes_in_context(self.llcx(), bytes)
|
||||
}
|
||||
|
||||
pub(crate) fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
|
||||
unsafe {
|
||||
let idx = c_uint::try_from(idx).expect("LLVMGetAggregateElement index overflow");
|
||||
|
|
@ -381,6 +385,16 @@ pub(crate) fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn null_terminate_bytes_in_context<'ll>(
|
||||
llcx: &'ll llvm::Context,
|
||||
bytes: &[u8],
|
||||
) -> &'ll Value {
|
||||
unsafe {
|
||||
let ptr = bytes.as_ptr() as *const c_char;
|
||||
llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), FALSE)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn named_struct<'ll>(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
|
||||
let len = c_uint::try_from(elts.len()).expect("LLVMConstStructInContext elements len overflow");
|
||||
unsafe { llvm::LLVMConstNamedStruct(ty, elts.as_ptr(), len) }
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use rustc_middle::mir::mono::MonoItem;
|
|||
use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
|
||||
use rustc_middle::ty::{self, Instance};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::Symbol;
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
use crate::common::CodegenCx;
|
||||
|
|
@ -331,6 +332,10 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
}
|
||||
|
||||
g
|
||||
} else if let Some(classname) = fn_attrs.objc_class {
|
||||
self.get_objc_classref(classname)
|
||||
} else if let Some(methname) = fn_attrs.objc_selector {
|
||||
self.get_objc_selref(methname)
|
||||
} else {
|
||||
check_and_apply_linkage(self, fn_attrs, llty, sym, def_id)
|
||||
};
|
||||
|
|
@ -452,6 +457,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
self.statics_to_rauw.borrow_mut().push((g, new_g));
|
||||
new_g
|
||||
};
|
||||
|
||||
// NOTE: Alignment from attributes has already been applied to the allocation.
|
||||
set_global_alignment(self, g, alloc.align);
|
||||
llvm::set_initializer(g, v);
|
||||
|
||||
|
|
@ -541,8 +548,225 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
|
||||
/// Add a global value to a list to be stored in the `llvm.compiler.used` variable,
|
||||
/// an array of ptr.
|
||||
pub(crate) fn add_compiler_used_global(&mut self, global: &'ll Value) {
|
||||
self.compiler_used_statics.push(global);
|
||||
pub(crate) fn add_compiler_used_global(&self, global: &'ll Value) {
|
||||
self.compiler_used_statics.borrow_mut().push(global);
|
||||
}
|
||||
|
||||
// We do our best here to match what Clang does when compiling Objective-C natively.
|
||||
// See Clang's `CGObjCCommonMac::CreateCStringLiteral`:
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L4134
|
||||
fn define_objc_classname(&self, classname: &str) -> &'ll Value {
|
||||
assert_eq!(self.objc_abi_version(), 1);
|
||||
|
||||
let llval = self.null_terminate_const_bytes(classname.as_bytes());
|
||||
let llty = self.val_ty(llval);
|
||||
let sym = self.generate_local_symbol_name("OBJC_CLASS_NAME_");
|
||||
let g = self.define_global(&sym, llty).unwrap_or_else(|| {
|
||||
bug!("symbol `{}` is already defined", sym);
|
||||
});
|
||||
set_global_alignment(self, g, self.tcx.data_layout.i8_align.abi);
|
||||
llvm::set_initializer(g, llval);
|
||||
llvm::set_linkage(g, llvm::Linkage::PrivateLinkage);
|
||||
llvm::set_section(g, c"__TEXT,__cstring,cstring_literals");
|
||||
llvm::LLVMSetGlobalConstant(g, llvm::TRUE);
|
||||
llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
|
||||
self.add_compiler_used_global(g);
|
||||
|
||||
g
|
||||
}
|
||||
|
||||
// We do our best here to match what Clang does when compiling Objective-C natively.
|
||||
// See Clang's `ObjCNonFragileABITypesHelper`:
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L6052
|
||||
fn get_objc_class_t(&self) -> &'ll Type {
|
||||
if let Some(class_t) = self.objc_class_t.get() {
|
||||
return class_t;
|
||||
}
|
||||
|
||||
assert_eq!(self.objc_abi_version(), 2);
|
||||
|
||||
// struct _class_t {
|
||||
// struct _class_t* isa;
|
||||
// struct _class_t* const superclass;
|
||||
// void* cache;
|
||||
// IMP* vtable;
|
||||
// struct class_ro_t* ro;
|
||||
// }
|
||||
|
||||
let class_t = self.type_named_struct("struct._class_t");
|
||||
let els = [self.type_ptr(); 5];
|
||||
let packed = false;
|
||||
self.set_struct_body(class_t, &els, packed);
|
||||
|
||||
self.objc_class_t.set(Some(class_t));
|
||||
class_t
|
||||
}
|
||||
|
||||
// We do our best here to match what Clang does when compiling Objective-C natively. We
|
||||
// deduplicate references within a CGU, but we need a reference definition in each referencing
|
||||
// CGU. All attempts at using external references to a single reference definition result in
|
||||
// linker errors.
|
||||
fn get_objc_classref(&self, classname: Symbol) -> &'ll Value {
|
||||
let mut classrefs = self.objc_classrefs.borrow_mut();
|
||||
if let Some(classref) = classrefs.get(&classname).copied() {
|
||||
return classref;
|
||||
}
|
||||
|
||||
let g = match self.objc_abi_version() {
|
||||
1 => {
|
||||
// See Clang's `CGObjCMac::EmitClassRefFromId`:
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5205
|
||||
let llval = self.define_objc_classname(classname.as_str());
|
||||
let llty = self.type_ptr();
|
||||
let sym = self.generate_local_symbol_name("OBJC_CLASS_REFERENCES_");
|
||||
let g = self.define_global(&sym, llty).unwrap_or_else(|| {
|
||||
bug!("symbol `{}` is already defined", sym);
|
||||
});
|
||||
set_global_alignment(self, g, self.tcx.data_layout.pointer_align().abi);
|
||||
llvm::set_initializer(g, llval);
|
||||
llvm::set_linkage(g, llvm::Linkage::PrivateLinkage);
|
||||
llvm::set_section(g, c"__OBJC,__cls_refs,literal_pointers,no_dead_strip");
|
||||
self.add_compiler_used_global(g);
|
||||
g
|
||||
}
|
||||
2 => {
|
||||
// See Clang's `CGObjCNonFragileABIMac::EmitClassRefFromId`:
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L7423
|
||||
let llval = {
|
||||
let extern_sym = format!("OBJC_CLASS_$_{}", classname.as_str());
|
||||
let extern_llty = self.get_objc_class_t();
|
||||
self.declare_global(&extern_sym, extern_llty)
|
||||
};
|
||||
let llty = self.type_ptr();
|
||||
let sym = self.generate_local_symbol_name("OBJC_CLASSLIST_REFERENCES_$_");
|
||||
let g = self.define_global(&sym, llty).unwrap_or_else(|| {
|
||||
bug!("symbol `{}` is already defined", sym);
|
||||
});
|
||||
set_global_alignment(self, g, self.tcx.data_layout.pointer_align().abi);
|
||||
llvm::set_initializer(g, llval);
|
||||
llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
|
||||
llvm::set_section(g, c"__DATA,__objc_classrefs,regular,no_dead_strip");
|
||||
self.add_compiler_used_global(g);
|
||||
g
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
classrefs.insert(classname, g);
|
||||
g
|
||||
}
|
||||
|
||||
// We do our best here to match what Clang does when compiling Objective-C natively. We
|
||||
// deduplicate references within a CGU, but we need a reference definition in each referencing
|
||||
// CGU. All attempts at using external references to a single reference definition result in
|
||||
// linker errors.
|
||||
//
|
||||
// Newer versions of Apple Clang generate calls to `@"objc_msgSend$methname"` selector stub
|
||||
// functions. We don't currently do that. The code we generate is closer to what Apple Clang
|
||||
// generates with the `-fno-objc-msgsend-selector-stubs` option.
|
||||
fn get_objc_selref(&self, methname: Symbol) -> &'ll Value {
|
||||
let mut selrefs = self.objc_selrefs.borrow_mut();
|
||||
if let Some(selref) = selrefs.get(&methname).copied() {
|
||||
return selref;
|
||||
}
|
||||
|
||||
let abi_version = self.objc_abi_version();
|
||||
|
||||
// See Clang's `CGObjCCommonMac::CreateCStringLiteral`:
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L4134
|
||||
let methname_llval = self.null_terminate_const_bytes(methname.as_str().as_bytes());
|
||||
let methname_llty = self.val_ty(methname_llval);
|
||||
let methname_sym = self.generate_local_symbol_name("OBJC_METH_VAR_NAME_");
|
||||
let methname_g = self.define_global(&methname_sym, methname_llty).unwrap_or_else(|| {
|
||||
bug!("symbol `{}` is already defined", methname_sym);
|
||||
});
|
||||
set_global_alignment(self, methname_g, self.tcx.data_layout.i8_align.abi);
|
||||
llvm::set_initializer(methname_g, methname_llval);
|
||||
llvm::set_linkage(methname_g, llvm::Linkage::PrivateLinkage);
|
||||
llvm::set_section(
|
||||
methname_g,
|
||||
match abi_version {
|
||||
1 => c"__TEXT,__cstring,cstring_literals",
|
||||
2 => c"__TEXT,__objc_methname,cstring_literals",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
);
|
||||
llvm::LLVMSetGlobalConstant(methname_g, llvm::TRUE);
|
||||
llvm::LLVMSetUnnamedAddress(methname_g, llvm::UnnamedAddr::Global);
|
||||
self.add_compiler_used_global(methname_g);
|
||||
|
||||
// See Clang's `CGObjCMac::EmitSelectorAddr`:
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5243
|
||||
// And Clang's `CGObjCNonFragileABIMac::EmitSelectorAddr`:
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L7586
|
||||
let selref_llval = methname_g;
|
||||
let selref_llty = self.type_ptr();
|
||||
let selref_sym = self.generate_local_symbol_name("OBJC_SELECTOR_REFERENCES_");
|
||||
let selref_g = self.define_global(&selref_sym, selref_llty).unwrap_or_else(|| {
|
||||
bug!("symbol `{}` is already defined", selref_sym);
|
||||
});
|
||||
set_global_alignment(self, selref_g, self.tcx.data_layout.pointer_align().abi);
|
||||
llvm::set_initializer(selref_g, selref_llval);
|
||||
llvm::set_externally_initialized(selref_g, true);
|
||||
llvm::set_linkage(
|
||||
selref_g,
|
||||
match abi_version {
|
||||
1 => llvm::Linkage::PrivateLinkage,
|
||||
2 => llvm::Linkage::InternalLinkage,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
);
|
||||
llvm::set_section(
|
||||
selref_g,
|
||||
match abi_version {
|
||||
1 => c"__OBJC,__message_refs,literal_pointers,no_dead_strip",
|
||||
2 => c"__DATA,__objc_selrefs,literal_pointers,no_dead_strip",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
);
|
||||
self.add_compiler_used_global(selref_g);
|
||||
|
||||
selrefs.insert(methname, selref_g);
|
||||
selref_g
|
||||
}
|
||||
|
||||
// We do our best here to match what Clang does when compiling Objective-C natively.
|
||||
// See Clang's `ObjCTypesHelper`:
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5936
|
||||
// And Clang's `CGObjCMac::EmitModuleInfo`:
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5151
|
||||
pub(crate) fn define_objc_module_info(&mut self) {
|
||||
assert_eq!(self.objc_abi_version(), 1);
|
||||
|
||||
// struct _objc_module {
|
||||
// long version; // Hardcoded to 7 in Clang.
|
||||
// long size; // sizeof(struct _objc_module)
|
||||
// char* name; // Hardcoded to classname "" in Clang.
|
||||
// struct _objc_symtab* symtab; // Null without class or category definitions.
|
||||
// }
|
||||
|
||||
let llty = self.type_named_struct("struct._objc_module");
|
||||
let i32_llty = self.type_i32();
|
||||
let ptr_llty = self.type_ptr();
|
||||
let packed = false;
|
||||
self.set_struct_body(llty, &[i32_llty, i32_llty, ptr_llty, ptr_llty], packed);
|
||||
|
||||
let version = self.const_uint(i32_llty, 7);
|
||||
let size = self.const_uint(i32_llty, 16);
|
||||
let name = self.define_objc_classname("");
|
||||
let symtab = self.const_null(ptr_llty);
|
||||
let llval = crate::common::named_struct(llty, &[version, size, name, symtab]);
|
||||
|
||||
let sym = "OBJC_MODULES";
|
||||
let g = self.define_global(&sym, llty).unwrap_or_else(|| {
|
||||
bug!("symbol `{}` is already defined", sym);
|
||||
});
|
||||
set_global_alignment(self, g, self.tcx.data_layout.pointer_align().abi);
|
||||
llvm::set_initializer(g, llval);
|
||||
llvm::set_linkage(g, llvm::Linkage::PrivateLinkage);
|
||||
llvm::set_section(g, c"__OBJC,__module_info,regular,no_dead_strip");
|
||||
|
||||
self.add_compiler_used_global(g);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ use rustc_session::config::{
|
|||
BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, FunctionReturn, PAuthKey, PacRet,
|
||||
};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol};
|
||||
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||
use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel};
|
||||
use smallvec::SmallVec;
|
||||
|
|
@ -119,7 +119,7 @@ pub(crate) struct FullCx<'ll, 'tcx> {
|
|||
|
||||
/// Statics that will be placed in the llvm.compiler.used variable
|
||||
/// See <https://llvm.org/docs/LangRef.html#the-llvm-compiler-used-global-variable> for details
|
||||
pub compiler_used_statics: Vec<&'ll Value>,
|
||||
pub compiler_used_statics: RefCell<Vec<&'ll Value>>,
|
||||
|
||||
/// Mapping of non-scalar types to llvm types.
|
||||
pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'ll Type>>,
|
||||
|
|
@ -146,6 +146,15 @@ pub(crate) struct FullCx<'ll, 'tcx> {
|
|||
/// `global_asm!` needs to be able to find this new global so that it can
|
||||
/// compute the correct mangled symbol name to insert into the asm.
|
||||
pub renamed_statics: RefCell<FxHashMap<DefId, &'ll Value>>,
|
||||
|
||||
/// Cached Objective-C class type
|
||||
pub objc_class_t: Cell<Option<&'ll Type>>,
|
||||
|
||||
/// Cache of Objective-C class references
|
||||
pub objc_classrefs: RefCell<FxHashMap<Symbol, &'ll Value>>,
|
||||
|
||||
/// Cache of Objective-C selector references
|
||||
pub objc_selrefs: RefCell<FxHashMap<Symbol, &'ll Value>>,
|
||||
}
|
||||
|
||||
fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
|
||||
|
|
@ -172,35 +181,6 @@ pub(crate) unsafe fn create_module<'ll>(
|
|||
let mut target_data_layout = sess.target.data_layout.to_string();
|
||||
let llvm_version = llvm_util::get_version();
|
||||
|
||||
if llvm_version < (20, 0, 0) {
|
||||
if sess.target.arch == "aarch64" || sess.target.arch.starts_with("arm64") {
|
||||
// LLVM 20 defines three additional address spaces for alternate
|
||||
// pointer kinds used in Windows.
|
||||
// See https://github.com/llvm/llvm-project/pull/111879
|
||||
target_data_layout =
|
||||
target_data_layout.replace("-p270:32:32-p271:32:32-p272:64:64", "");
|
||||
}
|
||||
if sess.target.arch.starts_with("sparc") {
|
||||
// LLVM 20 updates the sparc layout to correctly align 128 bit integers to 128 bit.
|
||||
// See https://github.com/llvm/llvm-project/pull/106951
|
||||
target_data_layout = target_data_layout.replace("-i128:128", "");
|
||||
}
|
||||
if sess.target.arch.starts_with("mips64") {
|
||||
// LLVM 20 updates the mips64 layout to correctly align 128 bit integers to 128 bit.
|
||||
// See https://github.com/llvm/llvm-project/pull/112084
|
||||
target_data_layout = target_data_layout.replace("-i128:128", "");
|
||||
}
|
||||
if sess.target.arch.starts_with("powerpc64") {
|
||||
// LLVM 20 updates the powerpc64 layout to correctly align 128 bit integers to 128 bit.
|
||||
// See https://github.com/llvm/llvm-project/pull/118004
|
||||
target_data_layout = target_data_layout.replace("-i128:128", "");
|
||||
}
|
||||
if sess.target.arch.starts_with("wasm32") || sess.target.arch.starts_with("wasm64") {
|
||||
// LLVM 20 updates the wasm(32|64) layout to correctly align 128 bit integers to 128 bit.
|
||||
// See https://github.com/llvm/llvm-project/pull/119204
|
||||
target_data_layout = target_data_layout.replace("-i128:128", "");
|
||||
}
|
||||
}
|
||||
if llvm_version < (21, 0, 0) {
|
||||
if sess.target.arch == "nvptx64" {
|
||||
// LLVM 21 updated the default layout on nvptx: https://github.com/llvm/llvm-project/pull/124961
|
||||
|
|
@ -644,7 +624,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
const_globals: Default::default(),
|
||||
statics_to_rauw: RefCell::new(Vec::new()),
|
||||
used_statics: Vec::new(),
|
||||
compiler_used_statics: Vec::new(),
|
||||
compiler_used_statics: Default::default(),
|
||||
type_lowering: Default::default(),
|
||||
scalar_lltypes: Default::default(),
|
||||
coverage_cx,
|
||||
|
|
@ -655,6 +635,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
intrinsics: Default::default(),
|
||||
local_gen_sym_counter: Cell::new(0),
|
||||
renamed_statics: Default::default(),
|
||||
objc_class_t: Cell::new(None),
|
||||
objc_classrefs: Default::default(),
|
||||
objc_selrefs: Default::default(),
|
||||
},
|
||||
PhantomData,
|
||||
)
|
||||
|
|
@ -679,6 +662,69 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
|
||||
llvm::set_section(g, c"llvm.metadata");
|
||||
}
|
||||
|
||||
/// The Objective-C ABI that is used.
|
||||
///
|
||||
/// This corresponds to the `-fobjc-abi-version=` flag in Clang / GCC.
|
||||
pub(crate) fn objc_abi_version(&self) -> u32 {
|
||||
assert!(self.tcx.sess.target.is_like_darwin);
|
||||
if self.tcx.sess.target.arch == "x86" && self.tcx.sess.target.os == "macos" {
|
||||
// 32-bit x86 macOS uses ABI version 1 (a.k.a. the "fragile ABI").
|
||||
1
|
||||
} else {
|
||||
// All other Darwin-like targets we support use ABI version 2
|
||||
// (a.k.a the "non-fragile ABI").
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
// We do our best here to match what Clang does when compiling Objective-C natively.
|
||||
// See Clang's `CGObjCCommonMac::EmitImageInfo`:
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5085
|
||||
pub(crate) fn add_objc_module_flags(&self) {
|
||||
let abi_version = self.objc_abi_version();
|
||||
|
||||
llvm::add_module_flag_u32(
|
||||
self.llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Error,
|
||||
"Objective-C Version",
|
||||
abi_version,
|
||||
);
|
||||
|
||||
llvm::add_module_flag_u32(
|
||||
self.llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Error,
|
||||
"Objective-C Image Info Version",
|
||||
0,
|
||||
);
|
||||
|
||||
llvm::add_module_flag_str(
|
||||
self.llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Error,
|
||||
"Objective-C Image Info Section",
|
||||
match abi_version {
|
||||
1 => "__OBJC,__image_info,regular",
|
||||
2 => "__DATA,__objc_imageinfo,regular,no_dead_strip",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
);
|
||||
|
||||
if self.tcx.sess.target.env == "sim" {
|
||||
llvm::add_module_flag_u32(
|
||||
self.llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Error,
|
||||
"Objective-C Is Simulated",
|
||||
1 << 5,
|
||||
);
|
||||
}
|
||||
|
||||
llvm::add_module_flag_u32(
|
||||
self.llmod,
|
||||
llvm::ModuleFlagMergeBehavior::Error,
|
||||
"Objective-C Class Properties",
|
||||
1 << 6,
|
||||
);
|
||||
}
|
||||
}
|
||||
impl<'ll> SimpleCx<'ll> {
|
||||
pub(crate) fn get_type_of_global(&self, val: &'ll Value) -> &'ll Type {
|
||||
|
|
|
|||
|
|
@ -32,9 +32,7 @@ use self::type_map::{DINodeCreationResult, Stub, UniqueTypeId};
|
|||
use super::CodegenUnitDebugContext;
|
||||
use super::namespace::mangled_name_of_instance;
|
||||
use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_name};
|
||||
use super::utils::{
|
||||
DIB, create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit,
|
||||
};
|
||||
use super::utils::{DIB, debug_context, get_namespace_for_item, is_node_local_to_unit};
|
||||
use crate::common::{AsCCharPtr, CodegenCx};
|
||||
use crate::debuginfo::dwarf_const;
|
||||
use crate::debuginfo::metadata::type_map::build_type_with_children;
|
||||
|
|
@ -103,32 +101,33 @@ fn build_fixed_size_array_di_node<'ll, 'tcx>(
|
|||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
unique_type_id: UniqueTypeId<'tcx>,
|
||||
array_type: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> DINodeCreationResult<'ll> {
|
||||
let ty::Array(element_type, len) = array_type.kind() else {
|
||||
bug!("build_fixed_size_array_di_node() called with non-ty::Array type `{:?}`", array_type)
|
||||
};
|
||||
|
||||
let element_type_di_node = type_di_node(cx, *element_type);
|
||||
let element_type_di_node = spanned_type_di_node(cx, *element_type, span);
|
||||
|
||||
return_if_di_node_created_in_meantime!(cx, unique_type_id);
|
||||
|
||||
let (size, align) = cx.size_and_align_of(array_type);
|
||||
let (size, align) = cx.spanned_size_and_align_of(array_type, span);
|
||||
|
||||
let upper_bound = len
|
||||
.try_to_target_usize(cx.tcx)
|
||||
.expect("expected monomorphic const in codegen") as c_longlong;
|
||||
|
||||
let subrange =
|
||||
unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) };
|
||||
let subrange = unsafe { llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound) };
|
||||
let subscripts = &[subrange];
|
||||
|
||||
let subscripts = create_DIArray(DIB(cx), &[subrange]);
|
||||
let di_node = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateArrayType(
|
||||
llvm::LLVMDIBuilderCreateArrayType(
|
||||
DIB(cx),
|
||||
size.bits(),
|
||||
align.bits() as u32,
|
||||
element_type_di_node,
|
||||
subscripts,
|
||||
subscripts.as_ptr(),
|
||||
subscripts.len() as c_uint,
|
||||
)
|
||||
};
|
||||
|
||||
|
|
@ -174,17 +173,13 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
"ptr_type={ptr_type}, pointee_type={pointee_type}",
|
||||
);
|
||||
|
||||
let di_node = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreatePointerType(
|
||||
DIB(cx),
|
||||
pointee_type_di_node,
|
||||
pointer_size.bits(),
|
||||
pointer_align.abi.bits() as u32,
|
||||
0, // Ignore DWARF address space.
|
||||
ptr_type_debuginfo_name.as_c_char_ptr(),
|
||||
ptr_type_debuginfo_name.len(),
|
||||
)
|
||||
};
|
||||
let di_node = create_pointer_type(
|
||||
cx,
|
||||
pointee_type_di_node,
|
||||
pointer_size,
|
||||
pointer_align.abi,
|
||||
&ptr_type_debuginfo_name,
|
||||
);
|
||||
|
||||
DINodeCreationResult { di_node, already_stored_in_typemap: false }
|
||||
}
|
||||
|
|
@ -232,17 +227,13 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
|
||||
// The data pointer type is a regular, thin pointer, regardless of whether this
|
||||
// is a slice or a trait object.
|
||||
let data_ptr_type_di_node = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreatePointerType(
|
||||
DIB(cx),
|
||||
pointee_type_di_node,
|
||||
addr_field.size.bits(),
|
||||
addr_field.align.abi.bits() as u32,
|
||||
0, // Ignore DWARF address space.
|
||||
std::ptr::null(),
|
||||
0,
|
||||
)
|
||||
};
|
||||
let data_ptr_type_di_node = create_pointer_type(
|
||||
cx,
|
||||
pointee_type_di_node,
|
||||
addr_field.size,
|
||||
addr_field.align.abi,
|
||||
"",
|
||||
);
|
||||
|
||||
smallvec![
|
||||
build_field_di_node(
|
||||
|
|
@ -317,7 +308,7 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
|
|||
|
||||
debug_context(cx).type_map.unique_id_to_di_node.borrow_mut().remove(&unique_type_id);
|
||||
|
||||
let fn_di_node = create_subroutine_type(cx, create_DIArray(DIB(cx), &signature_di_nodes[..]));
|
||||
let fn_di_node = create_subroutine_type(cx, &signature_di_nodes[..]);
|
||||
|
||||
// This is actually a function pointer, so wrap it in pointer DI.
|
||||
let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false);
|
||||
|
|
@ -328,26 +319,44 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
|
|||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let di_node = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreatePointerType(
|
||||
DIB(cx),
|
||||
fn_di_node,
|
||||
size.bits(),
|
||||
align.bits() as u32,
|
||||
0, // Ignore DWARF address space.
|
||||
name.as_c_char_ptr(),
|
||||
name.len(),
|
||||
)
|
||||
};
|
||||
let di_node = create_pointer_type(cx, fn_di_node, size, align, &name);
|
||||
|
||||
DINodeCreationResult::new(di_node, false)
|
||||
}
|
||||
|
||||
pub(super) fn create_subroutine_type<'ll>(
|
||||
cx: &CodegenCx<'ll, '_>,
|
||||
signature: &'ll DICompositeType,
|
||||
signature: &[Option<&'ll llvm::Metadata>],
|
||||
) -> &'ll DICompositeType {
|
||||
unsafe { llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(cx), signature) }
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateSubroutineType(
|
||||
DIB(cx),
|
||||
None, // ("File" is ignored and has no effect)
|
||||
signature.as_ptr(),
|
||||
signature.len() as c_uint,
|
||||
DIFlags::FlagZero, // (default value)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn create_pointer_type<'ll>(
|
||||
cx: &CodegenCx<'ll, '_>,
|
||||
pointee_ty: &'ll llvm::Metadata,
|
||||
size: Size,
|
||||
align: Align,
|
||||
name: &str,
|
||||
) -> &'ll llvm::Metadata {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreatePointerType(
|
||||
DIB(cx),
|
||||
pointee_ty,
|
||||
size.bits(),
|
||||
align.bits() as u32,
|
||||
0, // Ignore DWARF address space.
|
||||
name.as_ptr(),
|
||||
name.len(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create debuginfo for `dyn SomeTrait` types. Currently these are empty structs
|
||||
|
|
@ -447,7 +456,7 @@ pub(crate) fn spanned_type_di_node<'ll, 'tcx>(
|
|||
build_basic_type_di_node(cx, t)
|
||||
}
|
||||
ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t),
|
||||
ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t),
|
||||
ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t, span),
|
||||
ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id),
|
||||
ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id),
|
||||
ty::Foreign(..) => build_foreign_type_di_node(cx, t, unique_type_id),
|
||||
|
|
@ -812,14 +821,15 @@ fn build_basic_type_di_node<'ll, 'tcx>(
|
|||
};
|
||||
|
||||
let typedef_di_node = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateTypedef(
|
||||
llvm::LLVMDIBuilderCreateTypedef(
|
||||
DIB(cx),
|
||||
ty_di_node,
|
||||
typedef_name.as_c_char_ptr(),
|
||||
typedef_name.as_ptr(),
|
||||
typedef_name.len(),
|
||||
unknown_file_metadata(cx),
|
||||
0,
|
||||
None,
|
||||
0, // (no line number)
|
||||
None, // (no scope)
|
||||
0u32, // (no alignment specified)
|
||||
)
|
||||
};
|
||||
|
||||
|
|
@ -833,12 +843,13 @@ fn create_basic_type<'ll, 'tcx>(
|
|||
encoding: u32,
|
||||
) -> &'ll DIBasicType {
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateBasicType(
|
||||
llvm::LLVMDIBuilderCreateBasicType(
|
||||
DIB(cx),
|
||||
name.as_c_char_ptr(),
|
||||
name.as_ptr(),
|
||||
name.len(),
|
||||
size.bits(),
|
||||
encoding,
|
||||
DIFlags::FlagZero,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1024,10 +1035,10 @@ fn create_member_type<'ll, 'tcx>(
|
|||
type_di_node: &'ll DIType,
|
||||
) -> &'ll DIType {
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateMemberType(
|
||||
llvm::LLVMDIBuilderCreateMemberType(
|
||||
DIB(cx),
|
||||
owner,
|
||||
name.as_c_char_ptr(),
|
||||
name.as_ptr(),
|
||||
name.len(),
|
||||
file_metadata,
|
||||
line_number,
|
||||
|
|
@ -1435,7 +1446,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
|
|||
|
||||
let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
|
||||
let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
|
||||
let trait_ref = tcx.erase_regions(trait_ref);
|
||||
let trait_ref = tcx.erase_and_anonymize_regions(trait_ref);
|
||||
|
||||
tcx.vtable_entries(trait_ref)
|
||||
} else {
|
||||
|
|
@ -1562,7 +1573,7 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
|
|||
// Unwrap potential addrspacecast
|
||||
let vtable = find_vtable_behind_cast(vtable);
|
||||
let trait_ref_self = trait_ref.with_self_ty(cx.tcx, ty);
|
||||
let trait_ref_self = cx.tcx.erase_regions(trait_ref_self);
|
||||
let trait_ref_self = cx.tcx.erase_and_anonymize_regions(trait_ref_self);
|
||||
let trait_def_id = trait_ref_self.def_id;
|
||||
let trait_vis = cx.tcx.visibility(trait_def_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
|||
use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty};
|
||||
use smallvec::smallvec;
|
||||
|
||||
use crate::common::{AsCCharPtr, CodegenCx};
|
||||
use crate::common::CodegenCx;
|
||||
use crate::debuginfo::dwarf_const::DW_TAG_const_type;
|
||||
use crate::debuginfo::metadata::enums::DiscrResult;
|
||||
use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId};
|
||||
|
|
@ -378,20 +378,17 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
|
|||
variant_struct_type_wrapper_di_node,
|
||||
None,
|
||||
),
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateStaticMemberType(
|
||||
DIB(cx),
|
||||
enum_type_di_node,
|
||||
TAG_FIELD_NAME.as_c_char_ptr(),
|
||||
TAG_FIELD_NAME.len(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
variant_names_type_di_node,
|
||||
visibility_flags,
|
||||
Some(cx.const_u64(SINGLE_VARIANT_VIRTUAL_DISR)),
|
||||
tag_base_type_align.bits() as u32,
|
||||
)
|
||||
}
|
||||
create_static_member_type(
|
||||
cx,
|
||||
enum_type_di_node,
|
||||
TAG_FIELD_NAME,
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
variant_names_type_di_node,
|
||||
visibility_flags,
|
||||
Some(cx.const_u64(SINGLE_VARIANT_VIRTUAL_DISR)),
|
||||
tag_base_type_align,
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -570,27 +567,28 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
|
|||
let build_assoc_const = |name: &str,
|
||||
type_di_node_: &'ll DIType,
|
||||
value: u64,
|
||||
align: Align| unsafe {
|
||||
align: Align|
|
||||
-> &'ll llvm::Metadata {
|
||||
// FIXME: Currently we force all DISCR_* values to be u64's as LLDB seems to have
|
||||
// problems inspecting other value types. Since DISCR_* is typically only going to be
|
||||
// directly inspected via the debugger visualizer - which compares it to the `tag` value
|
||||
// (whose type is not modified at all) it shouldn't cause any real problems.
|
||||
let (t_di, align) = if name == ASSOC_CONST_DISCR_NAME {
|
||||
(type_di_node_, align.bits() as u32)
|
||||
(type_di_node_, align)
|
||||
} else {
|
||||
let ty_u64 = Ty::new_uint(cx.tcx, ty::UintTy::U64);
|
||||
(type_di_node(cx, ty_u64), Align::EIGHT.bits() as u32)
|
||||
(type_di_node(cx, ty_u64), Align::EIGHT)
|
||||
};
|
||||
|
||||
// must wrap type in a `const` modifier for LLDB to be able to inspect the value of the member
|
||||
let field_type =
|
||||
llvm::LLVMRustDIBuilderCreateQualifiedType(DIB(cx), DW_TAG_const_type, t_di);
|
||||
let field_type = unsafe {
|
||||
llvm::LLVMDIBuilderCreateQualifiedType(DIB(cx), DW_TAG_const_type, t_di)
|
||||
};
|
||||
|
||||
llvm::LLVMRustDIBuilderCreateStaticMemberType(
|
||||
DIB(cx),
|
||||
create_static_member_type(
|
||||
cx,
|
||||
wrapper_struct_type_di_node,
|
||||
name.as_c_char_ptr(),
|
||||
name.len(),
|
||||
name,
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
field_type,
|
||||
|
|
@ -975,3 +973,30 @@ fn variant_struct_wrapper_type_name(variant_index: VariantIdx) -> Cow<'static, s
|
|||
.map(|&s| Cow::from(s))
|
||||
.unwrap_or_else(|| format!("Variant{}", variant_index.as_usize()).into())
|
||||
}
|
||||
|
||||
fn create_static_member_type<'ll>(
|
||||
cx: &CodegenCx<'ll, '_>,
|
||||
scope: &'ll llvm::Metadata,
|
||||
name: &str,
|
||||
file: &'ll llvm::Metadata,
|
||||
line_number: c_uint,
|
||||
ty: &'ll llvm::Metadata,
|
||||
flags: DIFlags,
|
||||
value: Option<&'ll llvm::Value>,
|
||||
align: Align,
|
||||
) -> &'ll llvm::Metadata {
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateStaticMemberType(
|
||||
DIB(cx),
|
||||
scope,
|
||||
name.as_ptr(),
|
||||
name.len(),
|
||||
file,
|
||||
line_number,
|
||||
ty,
|
||||
flags,
|
||||
value,
|
||||
align.bits() as c_uint,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::cell::RefCell;
|
||||
|
||||
use libc::c_uint;
|
||||
use rustc_abi::{Align, Size, VariantIdx};
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
|
@ -9,7 +10,7 @@ use rustc_middle::bug;
|
|||
use rustc_middle::ty::{self, ExistentialTraitRef, Ty, TyCtxt};
|
||||
|
||||
use super::{DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata};
|
||||
use crate::common::{AsCCharPtr, CodegenCx};
|
||||
use crate::common::CodegenCx;
|
||||
use crate::debuginfo::utils::{DIB, create_DIArray, debug_context};
|
||||
use crate::llvm::debuginfo::{DIFlags, DIScope, DIType};
|
||||
use crate::llvm::{self};
|
||||
|
|
@ -191,7 +192,7 @@ pub(super) fn stub<'ll, 'tcx>(
|
|||
containing_scope: Option<&'ll DIScope>,
|
||||
flags: DIFlags,
|
||||
) -> StubInfo<'ll, 'tcx> {
|
||||
let empty_array = create_DIArray(DIB(cx), &[]);
|
||||
let no_elements: &[Option<&llvm::Metadata>] = &[];
|
||||
let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx);
|
||||
|
||||
let (file_metadata, line_number) = if let Some(def_location) = def_location {
|
||||
|
|
@ -207,10 +208,10 @@ pub(super) fn stub<'ll, 'tcx>(
|
|||
_ => None,
|
||||
};
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateStructType(
|
||||
llvm::LLVMDIBuilderCreateStructType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
name.as_c_char_ptr(),
|
||||
name.as_ptr(),
|
||||
name.len(),
|
||||
file_metadata,
|
||||
line_number,
|
||||
|
|
@ -218,28 +219,30 @@ pub(super) fn stub<'ll, 'tcx>(
|
|||
align.bits() as u32,
|
||||
flags,
|
||||
None,
|
||||
empty_array,
|
||||
0,
|
||||
no_elements.as_ptr(),
|
||||
no_elements.len() as c_uint,
|
||||
0u32, // (Objective-C runtime version; default is 0)
|
||||
vtable_holder,
|
||||
unique_type_id_str.as_c_char_ptr(),
|
||||
unique_type_id_str.as_ptr(),
|
||||
unique_type_id_str.len(),
|
||||
)
|
||||
}
|
||||
}
|
||||
Stub::Union => unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateUnionType(
|
||||
llvm::LLVMDIBuilderCreateUnionType(
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
name.as_c_char_ptr(),
|
||||
name.as_ptr(),
|
||||
name.len(),
|
||||
file_metadata,
|
||||
line_number,
|
||||
size.bits(),
|
||||
align.bits() as u32,
|
||||
flags,
|
||||
Some(empty_array),
|
||||
0,
|
||||
unique_type_id_str.as_c_char_ptr(),
|
||||
no_elements.as_ptr(),
|
||||
no_elements.len() as c_uint,
|
||||
0u32, // (Objective-C runtime version; default is 0)
|
||||
unique_type_id_str.as_ptr(),
|
||||
unique_type_id_str.len(),
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
let file_metadata = file_metadata(self, &loc.file);
|
||||
|
||||
let function_type_metadata =
|
||||
create_subroutine_type(self, get_function_signature(self, fn_abi));
|
||||
create_subroutine_type(self, &get_function_signature(self, fn_abi));
|
||||
|
||||
let mut name = String::with_capacity(64);
|
||||
type_names::push_item_name(tcx, def_id, false, &mut name);
|
||||
|
|
@ -441,9 +441,9 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
fn get_function_signature<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
) -> &'ll DIArray {
|
||||
) -> Vec<Option<&'ll llvm::Metadata>> {
|
||||
if cx.sess().opts.debuginfo != DebugInfo::Full {
|
||||
return create_DIArray(DIB(cx), &[]);
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let mut signature = Vec::with_capacity(fn_abi.args.len() + 1);
|
||||
|
|
@ -484,7 +484,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
.extend(fn_abi.args.iter().map(|arg| Some(type_di_node(cx, arg.layout.ty))));
|
||||
}
|
||||
|
||||
create_DIArray(DIB(cx), &signature[..])
|
||||
signature
|
||||
}
|
||||
|
||||
fn get_template_parameters<'ll, 'tcx>(
|
||||
|
|
|
|||
|
|
@ -1208,7 +1208,8 @@ fn codegen_autodiff<'ll, 'tcx>(
|
|||
|
||||
adjust_activity_to_abi(
|
||||
tcx,
|
||||
fn_source.ty(tcx, TypingEnv::fully_monomorphized()),
|
||||
fn_source,
|
||||
TypingEnv::fully_monomorphized(),
|
||||
&mut diff_attrs.input_activity,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ use rustc_middle::util::Providers;
|
|||
use rustc_session::Session;
|
||||
use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::spec::{RelocModel, TlsModel};
|
||||
|
||||
mod abi;
|
||||
mod allocator;
|
||||
|
|
@ -244,16 +245,7 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
match req.kind {
|
||||
PrintKind::RelocationModels => {
|
||||
writeln!(out, "Available relocation models:").unwrap();
|
||||
for name in &[
|
||||
"static",
|
||||
"pic",
|
||||
"pie",
|
||||
"dynamic-no-pic",
|
||||
"ropi",
|
||||
"rwpi",
|
||||
"ropi-rwpi",
|
||||
"default",
|
||||
] {
|
||||
for name in RelocModel::ALL.iter().map(RelocModel::desc).chain(["default"]) {
|
||||
writeln!(out, " {name}").unwrap();
|
||||
}
|
||||
writeln!(out).unwrap();
|
||||
|
|
@ -267,9 +259,7 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
}
|
||||
PrintKind::TlsModels => {
|
||||
writeln!(out, "Available TLS models:").unwrap();
|
||||
for name in
|
||||
&["global-dynamic", "local-dynamic", "initial-exec", "local-exec", "emulated"]
|
||||
{
|
||||
for name in TlsModel::ALL.iter().map(TlsModel::desc) {
|
||||
writeln!(out, " {name}").unwrap();
|
||||
}
|
||||
writeln!(out).unwrap();
|
||||
|
|
|
|||
|
|
@ -59,10 +59,10 @@ pub(crate) enum LLVMRustVerifierFailureAction {
|
|||
LLVMReturnStatusAction = 2,
|
||||
}
|
||||
|
||||
#[cfg(llvm_enzyme)]
|
||||
#[cfg(feature = "llvm_enzyme")]
|
||||
pub(crate) use self::Enzyme_AD::*;
|
||||
|
||||
#[cfg(llvm_enzyme)]
|
||||
#[cfg(feature = "llvm_enzyme")]
|
||||
pub(crate) mod Enzyme_AD {
|
||||
use std::ffi::{CString, c_char};
|
||||
|
||||
|
|
@ -134,10 +134,10 @@ pub(crate) mod Enzyme_AD {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(llvm_enzyme))]
|
||||
#[cfg(not(feature = "llvm_enzyme"))]
|
||||
pub(crate) use self::Fallback_AD::*;
|
||||
|
||||
#[cfg(not(llvm_enzyme))]
|
||||
#[cfg(not(feature = "llvm_enzyme"))]
|
||||
pub(crate) mod Fallback_AD {
|
||||
#![allow(unused_variables)]
|
||||
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ use rustc_target::spec::SymbolVisibility;
|
|||
|
||||
use super::RustString;
|
||||
use super::debuginfo::{
|
||||
DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator,
|
||||
DIFile, DIFlags, DIGlobalVariableExpression, DILocation, DISPFlags, DIScope, DISubprogram,
|
||||
DISubrange, DITemplateTypeParameter, DIType, DIVariable, DebugEmissionKind, DebugNameTableKind,
|
||||
DIArray, DIBuilder, DIDerivedType, DIDescriptor, DIEnumerator, DIFile, DIFlags,
|
||||
DIGlobalVariableExpression, DILocation, DISPFlags, DIScope, DISubprogram, DISubrange,
|
||||
DITemplateTypeParameter, DIType, DIVariable, DebugEmissionKind, DebugNameTableKind,
|
||||
};
|
||||
use crate::llvm;
|
||||
|
||||
|
|
@ -1237,6 +1237,7 @@ unsafe extern "C" {
|
|||
pub(crate) safe fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
|
||||
pub(crate) safe fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
|
||||
pub(crate) safe fn LLVMSetTailCallKind(CallInst: &Value, kind: TailCallKind);
|
||||
pub(crate) safe fn LLVMSetExternallyInitialized(GlobalVar: &Value, IsExtInit: Bool);
|
||||
|
||||
// Operations on attributes
|
||||
pub(crate) fn LLVMCreateStringAttribute(
|
||||
|
|
@ -1870,6 +1871,124 @@ unsafe extern "C" {
|
|||
Scope: &'ll Metadata,
|
||||
InlinedAt: Option<&'ll Metadata>,
|
||||
) -> &'ll Metadata;
|
||||
|
||||
pub(crate) fn LLVMDIBuilderCreateSubroutineType<'ll>(
|
||||
Builder: &DIBuilder<'ll>,
|
||||
File: Option<&'ll Metadata>, // (ignored and has no effect)
|
||||
ParameterTypes: *const Option<&'ll Metadata>,
|
||||
NumParameterTypes: c_uint,
|
||||
Flags: DIFlags, // (default is `DIFlags::DIFlagZero`)
|
||||
) -> &'ll Metadata;
|
||||
|
||||
pub(crate) fn LLVMDIBuilderCreateUnionType<'ll>(
|
||||
Builder: &DIBuilder<'ll>,
|
||||
Scope: Option<&'ll Metadata>,
|
||||
Name: *const c_uchar, // See "PTR_LEN_STR".
|
||||
NameLen: size_t,
|
||||
File: &'ll Metadata,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Flags: DIFlags,
|
||||
Elements: *const Option<&'ll Metadata>,
|
||||
NumElements: c_uint,
|
||||
RunTimeLang: c_uint, // (optional Objective-C runtime version; default is 0)
|
||||
UniqueId: *const c_uchar, // See "PTR_LEN_STR".
|
||||
UniqueIdLen: size_t,
|
||||
) -> &'ll Metadata;
|
||||
|
||||
pub(crate) fn LLVMDIBuilderCreateArrayType<'ll>(
|
||||
Builder: &DIBuilder<'ll>,
|
||||
Size: u64,
|
||||
Align: u32,
|
||||
Ty: &'ll Metadata,
|
||||
Subscripts: *const &'ll Metadata,
|
||||
NumSubscripts: c_uint,
|
||||
) -> &'ll Metadata;
|
||||
|
||||
pub(crate) fn LLVMDIBuilderCreateBasicType<'ll>(
|
||||
Builder: &DIBuilder<'ll>,
|
||||
Name: *const c_uchar, // See "PTR_LEN_STR".
|
||||
NameLen: size_t,
|
||||
SizeInBits: u64,
|
||||
Encoding: c_uint, // (`LLVMDWARFTypeEncoding`)
|
||||
Flags: DIFlags, // (default is `DIFlags::DIFlagZero`)
|
||||
) -> &'ll Metadata;
|
||||
|
||||
pub(crate) fn LLVMDIBuilderCreatePointerType<'ll>(
|
||||
Builder: &DIBuilder<'ll>,
|
||||
PointeeTy: &'ll Metadata,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u32,
|
||||
AddressSpace: c_uint, // (optional DWARF address space; default is 0)
|
||||
Name: *const c_uchar, // See "PTR_LEN_STR".
|
||||
NameLen: size_t,
|
||||
) -> &'ll Metadata;
|
||||
|
||||
pub(crate) fn LLVMDIBuilderCreateStructType<'ll>(
|
||||
Builder: &DIBuilder<'ll>,
|
||||
Scope: Option<&'ll Metadata>,
|
||||
Name: *const c_uchar, // See "PTR_LEN_STR".
|
||||
NameLen: size_t,
|
||||
File: &'ll Metadata,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Flags: DIFlags,
|
||||
DerivedFrom: Option<&'ll Metadata>,
|
||||
Elements: *const Option<&'ll Metadata>,
|
||||
NumElements: c_uint,
|
||||
RunTimeLang: c_uint, // (optional Objective-C runtime version; default is 0)
|
||||
VTableHolder: Option<&'ll Metadata>,
|
||||
UniqueId: *const c_uchar, // See "PTR_LEN_STR".
|
||||
UniqueIdLen: size_t,
|
||||
) -> &'ll Metadata;
|
||||
|
||||
pub(crate) fn LLVMDIBuilderCreateMemberType<'ll>(
|
||||
Builder: &DIBuilder<'ll>,
|
||||
Scope: &'ll Metadata,
|
||||
Name: *const c_uchar, // See "PTR_LEN_STR".
|
||||
NameLen: size_t,
|
||||
File: &'ll Metadata,
|
||||
LineNo: c_uint,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u32,
|
||||
OffsetInBits: u64,
|
||||
Flags: DIFlags,
|
||||
Ty: &'ll Metadata,
|
||||
) -> &'ll Metadata;
|
||||
|
||||
pub(crate) fn LLVMDIBuilderCreateStaticMemberType<'ll>(
|
||||
Builder: &DIBuilder<'ll>,
|
||||
Scope: &'ll Metadata,
|
||||
Name: *const c_uchar, // See "PTR_LEN_STR".
|
||||
NameLen: size_t,
|
||||
File: &'ll Metadata,
|
||||
LineNumber: c_uint,
|
||||
Type: &'ll Metadata,
|
||||
Flags: DIFlags,
|
||||
ConstantVal: Option<&'ll Value>,
|
||||
AlignInBits: u32,
|
||||
) -> &'ll Metadata;
|
||||
|
||||
/// Creates a "qualified type" in the C/C++ sense, by adding modifiers
|
||||
/// like `const` or `volatile`.
|
||||
pub(crate) fn LLVMDIBuilderCreateQualifiedType<'ll>(
|
||||
Builder: &DIBuilder<'ll>,
|
||||
Tag: c_uint, // (DWARF tag, e.g. `DW_TAG_const_type`)
|
||||
Type: &'ll Metadata,
|
||||
) -> &'ll Metadata;
|
||||
|
||||
pub(crate) fn LLVMDIBuilderCreateTypedef<'ll>(
|
||||
Builder: &DIBuilder<'ll>,
|
||||
Type: &'ll Metadata,
|
||||
Name: *const c_uchar, // See "PTR_LEN_STR".
|
||||
NameLen: size_t,
|
||||
File: &'ll Metadata,
|
||||
LineNo: c_uint,
|
||||
Scope: Option<&'ll Metadata>,
|
||||
AlignInBits: u32, // (optional; default is 0)
|
||||
) -> &'ll Metadata;
|
||||
}
|
||||
|
||||
#[link(name = "llvm-wrapper", kind = "static")]
|
||||
|
|
@ -2172,11 +2291,6 @@ unsafe extern "C" {
|
|||
SourceLen: size_t,
|
||||
) -> &'a DIFile;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateSubroutineType<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
ParameterTypes: &'a DIArray,
|
||||
) -> &'a DICompositeType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateFunction<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: &'a DIDescriptor,
|
||||
|
|
@ -2210,66 +2324,6 @@ unsafe extern "C" {
|
|||
TParam: &'a DIArray,
|
||||
) -> &'a DISubprogram;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateBasicType<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
SizeInBits: u64,
|
||||
Encoding: c_uint,
|
||||
) -> &'a DIBasicType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateTypedef<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Type: &'a DIBasicType,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNo: c_uint,
|
||||
Scope: Option<&'a DIScope>,
|
||||
) -> &'a DIDerivedType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreatePointerType<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
PointeeTy: &'a DIType,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u32,
|
||||
AddressSpace: c_uint,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
) -> &'a DIDerivedType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateStructType<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: Option<&'a DIDescriptor>,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Flags: DIFlags,
|
||||
DerivedFrom: Option<&'a DIType>,
|
||||
Elements: &'a DIArray,
|
||||
RunTimeLang: c_uint,
|
||||
VTableHolder: Option<&'a DIType>,
|
||||
UniqueId: *const c_char,
|
||||
UniqueIdLen: size_t,
|
||||
) -> &'a DICompositeType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateMemberType<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: &'a DIDescriptor,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNo: c_uint,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u32,
|
||||
OffsetInBits: u64,
|
||||
Flags: DIFlags,
|
||||
Ty: &'a DIType,
|
||||
) -> &'a DIDerivedType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateVariantMemberType<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: &'a DIScope,
|
||||
|
|
@ -2285,25 +2339,6 @@ unsafe extern "C" {
|
|||
Ty: &'a DIType,
|
||||
) -> &'a DIType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateStaticMemberType<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: &'a DIDescriptor,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNo: c_uint,
|
||||
Ty: &'a DIType,
|
||||
Flags: DIFlags,
|
||||
val: Option<&'a Value>,
|
||||
AlignInBits: u32,
|
||||
) -> &'a DIDerivedType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateQualifiedType<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Tag: c_uint,
|
||||
Type: &'a DIType,
|
||||
) -> &'a DIDerivedType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateStaticVariable<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Context: Option<&'a DIScope>,
|
||||
|
|
@ -2335,14 +2370,6 @@ unsafe extern "C" {
|
|||
AlignInBits: u32,
|
||||
) -> &'a DIVariable;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateArrayType<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Size: u64,
|
||||
AlignInBits: u32,
|
||||
Ty: &'a DIType,
|
||||
Subscripts: &'a DIArray,
|
||||
) -> &'a DIType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderGetOrCreateSubrange<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Lo: i64,
|
||||
|
|
@ -2388,22 +2415,6 @@ unsafe extern "C" {
|
|||
IsScoped: bool,
|
||||
) -> &'a DIType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateUnionType<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: Option<&'a DIScope>,
|
||||
Name: *const c_char,
|
||||
NameLen: size_t,
|
||||
File: &'a DIFile,
|
||||
LineNumber: c_uint,
|
||||
SizeInBits: u64,
|
||||
AlignInBits: u32,
|
||||
Flags: DIFlags,
|
||||
Elements: Option<&'a DIArray>,
|
||||
RunTimeLang: c_uint,
|
||||
UniqueId: *const c_char,
|
||||
UniqueIdLen: size_t,
|
||||
) -> &'a DIType;
|
||||
|
||||
pub(crate) fn LLVMRustDIBuilderCreateVariantPart<'a>(
|
||||
Builder: &DIBuilder<'a>,
|
||||
Scope: &'a DIScope,
|
||||
|
|
@ -2480,8 +2491,10 @@ unsafe extern "C" {
|
|||
OutputObjFile: *const c_char,
|
||||
DebugInfoCompression: *const c_char,
|
||||
UseEmulatedTls: bool,
|
||||
ArgsCstrBuff: *const c_uchar, // See "PTR_LEN_STR".
|
||||
ArgsCstrBuffLen: usize,
|
||||
Argv0: *const c_uchar, // See "PTR_LEN_STR".
|
||||
Argv0Len: size_t,
|
||||
CommandLineArgs: *const c_uchar, // See "PTR_LEN_STR".
|
||||
CommandLineArgsLen: size_t,
|
||||
UseWasmEH: bool,
|
||||
) -> *mut TargetMachine;
|
||||
|
||||
|
|
|
|||
|
|
@ -258,6 +258,10 @@ pub(crate) fn set_alignment(llglobal: &Value, align: Align) {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_externally_initialized(llglobal: &Value, is_ext_init: bool) {
|
||||
LLVMSetExternallyInitialized(llglobal, is_ext_init.to_llvm_bool());
|
||||
}
|
||||
|
||||
/// Get the `name`d comdat from `llmod` and assign it to `llglobal`.
|
||||
///
|
||||
/// Inserts the comdat into `llmod` if it does not exist.
|
||||
|
|
|
|||
|
|
@ -217,27 +217,16 @@ impl<'a> IntoIterator for LLVMFeature<'a> {
|
|||
/// Rust can also be build with an external precompiled version of LLVM which might lead to failures
|
||||
/// if the oldest tested / supported LLVM version doesn't yet support the relevant intrinsics.
|
||||
pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFeature<'a>> {
|
||||
let arch = if sess.target.arch == "x86_64" {
|
||||
"x86"
|
||||
} else if sess.target.arch == "arm64ec" {
|
||||
"aarch64"
|
||||
} else if sess.target.arch == "sparc64" {
|
||||
"sparc"
|
||||
} else if sess.target.arch == "powerpc64" {
|
||||
"powerpc"
|
||||
} else {
|
||||
&*sess.target.arch
|
||||
let raw_arch = &*sess.target.arch;
|
||||
let arch = match raw_arch {
|
||||
"x86_64" => "x86",
|
||||
"arm64ec" => "aarch64",
|
||||
"sparc64" => "sparc",
|
||||
"powerpc64" => "powerpc",
|
||||
_ => raw_arch,
|
||||
};
|
||||
let (major, _, _) = get_version();
|
||||
match (arch, s) {
|
||||
("x86", "sse4.2") => Some(LLVMFeature::with_dependencies(
|
||||
"sse4.2",
|
||||
smallvec![TargetFeatureFoldStrength::EnableOnly("crc32")],
|
||||
)),
|
||||
("x86", "pclmulqdq") => Some(LLVMFeature::new("pclmul")),
|
||||
("x86", "rdrand") => Some(LLVMFeature::new("rdrnd")),
|
||||
("x86", "bmi1") => Some(LLVMFeature::new("bmi")),
|
||||
("x86", "cmpxchg16b") => Some(LLVMFeature::new("cx16")),
|
||||
("x86", "lahfsahf") => Some(LLVMFeature::new("sahf")),
|
||||
("aarch64", "rcpc2") => Some(LLVMFeature::new("rcpc-immo")),
|
||||
("aarch64", "dpb") => Some(LLVMFeature::new("ccpp")),
|
||||
("aarch64", "dpb2") => Some(LLVMFeature::new("ccdp")),
|
||||
|
|
@ -246,9 +235,6 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
|
|||
("aarch64", "pmuv3") => Some(LLVMFeature::new("perfmon")),
|
||||
("aarch64", "paca") => Some(LLVMFeature::new("pauth")),
|
||||
("aarch64", "pacg") => Some(LLVMFeature::new("pauth")),
|
||||
// Before LLVM 20 those two features were packaged together as b16b16
|
||||
("aarch64", "sve-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")),
|
||||
("aarch64", "sme-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")),
|
||||
("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")),
|
||||
// Rust ties fp and neon together.
|
||||
("aarch64", "neon") => Some(LLVMFeature::with_dependencies(
|
||||
|
|
@ -262,57 +248,26 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
|
|||
// Filter out features that are not supported by the current LLVM version
|
||||
("aarch64", "fpmr") => None, // only existed in 18
|
||||
("arm", "fp16") => Some(LLVMFeature::new("fullfp16")),
|
||||
// NVPTX targets added in LLVM 20
|
||||
("nvptx64", "sm_100") if get_version().0 < 20 => None,
|
||||
("nvptx64", "sm_100a") if get_version().0 < 20 => None,
|
||||
("nvptx64", "sm_101") if get_version().0 < 20 => None,
|
||||
("nvptx64", "sm_101a") if get_version().0 < 20 => None,
|
||||
("nvptx64", "sm_120") if get_version().0 < 20 => None,
|
||||
("nvptx64", "sm_120a") if get_version().0 < 20 => None,
|
||||
("nvptx64", "ptx86") if get_version().0 < 20 => None,
|
||||
("nvptx64", "ptx87") if get_version().0 < 20 => None,
|
||||
// Filter out features that are not supported by the current LLVM version
|
||||
("loongarch64", "div32" | "lam-bh" | "lamcas" | "ld-seq-sa" | "scq")
|
||||
if get_version().0 < 20 =>
|
||||
{
|
||||
None
|
||||
}
|
||||
("loongarch32" | "loongarch64", "32s") if get_version().0 < 21 => None,
|
||||
// Filter out features that are not supported by the current LLVM version
|
||||
("riscv32" | "riscv64", "zacas" | "rva23u64" | "supm") if get_version().0 < 20 => None,
|
||||
(
|
||||
"s390x",
|
||||
"message-security-assist-extension12"
|
||||
| "concurrent-functions"
|
||||
| "miscellaneous-extensions-4"
|
||||
| "vector-enhancements-3"
|
||||
| "vector-packed-decimal-enhancement-3",
|
||||
) if get_version().0 < 20 => None,
|
||||
("loongarch32" | "loongarch64", "32s") if major < 21 => None,
|
||||
("powerpc", "power8-crypto") => Some(LLVMFeature::new("crypto")),
|
||||
("sparc", "leoncasa") => Some(LLVMFeature::new("hasleoncasa")),
|
||||
("x86", "sse4.2") => Some(LLVMFeature::with_dependencies(
|
||||
"sse4.2",
|
||||
smallvec![TargetFeatureFoldStrength::EnableOnly("crc32")],
|
||||
)),
|
||||
("x86", "pclmulqdq") => Some(LLVMFeature::new("pclmul")),
|
||||
("x86", "rdrand") => Some(LLVMFeature::new("rdrnd")),
|
||||
("x86", "bmi1") => Some(LLVMFeature::new("bmi")),
|
||||
("x86", "cmpxchg16b") => Some(LLVMFeature::new("cx16")),
|
||||
("x86", "lahfsahf") => Some(LLVMFeature::new("sahf")),
|
||||
// Enable the evex512 target feature if an avx512 target feature is enabled.
|
||||
("x86", s) if s.starts_with("avx512") => Some(LLVMFeature::with_dependencies(
|
||||
s,
|
||||
smallvec![TargetFeatureFoldStrength::EnableOnly("evex512")],
|
||||
)),
|
||||
// Support for `wide-arithmetic` will first land in LLVM 20 as part of
|
||||
// llvm/llvm-project#111598
|
||||
("wasm32" | "wasm64", "wide-arithmetic") if get_version() < (20, 0, 0) => None,
|
||||
("sparc", "leoncasa") => Some(LLVMFeature::new("hasleoncasa")),
|
||||
// In LLVM 19, there is no `v8plus` feature and `v9` means "SPARC-V9 instruction available and SPARC-V8+ ABI used".
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L27-L28
|
||||
// Before LLVM 19, there was no `v8plus` feature and `v9` means "SPARC-V9 instruction available".
|
||||
// https://github.com/llvm/llvm-project/blob/llvmorg-18.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L26
|
||||
("sparc", "v8plus") if get_version().0 == 19 => Some(LLVMFeature::new("v9")),
|
||||
("powerpc", "power8-crypto") => Some(LLVMFeature::new("crypto")),
|
||||
// These new `amx` variants and `movrs` were introduced in LLVM20
|
||||
("x86", "amx-avx512" | "amx-fp8" | "amx-movrs" | "amx-tf32" | "amx-transpose")
|
||||
if get_version().0 < 20 =>
|
||||
{
|
||||
None
|
||||
}
|
||||
("x86", "movrs") if get_version().0 < 20 => None,
|
||||
("x86", "avx10.1") => Some(LLVMFeature::new("avx10.1-512")),
|
||||
("x86", "avx10.2") if get_version().0 < 20 => None,
|
||||
("x86", "avx10.2") if get_version().0 >= 20 => Some(LLVMFeature::new("avx10.2-512")),
|
||||
("x86", "avx10.2") => Some(LLVMFeature::new("avx10.2-512")),
|
||||
("x86", "apxf") => Some(LLVMFeature::with_dependencies(
|
||||
"egpr",
|
||||
smallvec![
|
||||
|
|
@ -716,17 +671,7 @@ pub(crate) fn global_llvm_features(
|
|||
};
|
||||
|
||||
// Features implied by an implicit or explicit `--target`.
|
||||
features.extend(
|
||||
sess.target
|
||||
.features
|
||||
.split(',')
|
||||
.filter(|v| !v.is_empty())
|
||||
// Drop +v8plus feature introduced in LLVM 20.
|
||||
// (Hard-coded target features do not go through `to_llvm_feature` since they already
|
||||
// are LLVM feature names, hence we need a special case here.)
|
||||
.filter(|v| *v != "+v8plus" || get_version() >= (20, 0, 0))
|
||||
.map(String::from),
|
||||
);
|
||||
features.extend(sess.target.features.split(',').filter(|v| !v.is_empty()).map(String::from));
|
||||
|
||||
if wants_wasm_eh(sess) && sess.panic_strategy() == PanicStrategy::Unwind {
|
||||
features.push("+exception-handling".into());
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use rustc_middle::bug;
|
|||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||
use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::common::*;
|
||||
|
|
@ -149,7 +150,11 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub(crate) fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) {
|
||||
let layout = self.layout_of(ty);
|
||||
self.spanned_size_and_align_of(ty, DUMMY_SP)
|
||||
}
|
||||
|
||||
pub(crate) fn spanned_size_and_align_of(&self, ty: Ty<'tcx>, span: Span) -> (Size, Align) {
|
||||
let layout = self.spanned_layout_of(ty, span);
|
||||
(layout.size, layout.align.abi)
|
||||
}
|
||||
}
|
||||
|
|
@ -226,7 +231,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||
|
||||
// Make sure lifetimes are erased, to avoid generating distinct LLVM
|
||||
// types for Rust types that only differ in the choice of lifetimes.
|
||||
let normal_ty = cx.tcx.erase_regions(self.ty);
|
||||
let normal_ty = cx.tcx.erase_and_anonymize_regions(self.ty);
|
||||
|
||||
let mut defer = None;
|
||||
let llty = if self.ty != normal_ty {
|
||||
|
|
|
|||
|
|
@ -908,6 +908,21 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
|
|||
)
|
||||
}
|
||||
"aarch64" => emit_aapcs_va_arg(bx, addr, target_ty),
|
||||
"arm" => {
|
||||
// Types wider than 16 bytes are not currently supported. Clang has special logic for
|
||||
// such types, but `VaArgSafe` is not implemented for any type that is this large.
|
||||
assert!(bx.cx.size_of(target_ty).bytes() <= 16);
|
||||
|
||||
emit_ptr_va_arg(
|
||||
bx,
|
||||
addr,
|
||||
target_ty,
|
||||
PassMode::Direct,
|
||||
SlotSize::Bytes4,
|
||||
AllowHigherAlign::Yes,
|
||||
ForceRightAdjust::No,
|
||||
)
|
||||
}
|
||||
"s390x" => emit_s390x_va_arg(bx, addr, target_ty),
|
||||
"powerpc" => emit_powerpc_va_arg(bx, addr, target_ty),
|
||||
"powerpc64" | "powerpc64le" => emit_ptr_va_arg(
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ ar_archive_writer = "0.5"
|
|||
bitflags = "2.4.1"
|
||||
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`.
|
||||
# per crate", so if you change this, you need to also change it in `rustc_llvm` and `rustc_windows_rc`.
|
||||
cc = "=1.2.16"
|
||||
itertools = "0.12"
|
||||
pathdiff = "0.2.0"
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ codegen_ssa_aix_strip_not_used = using host's `strip` binary to cross-compile to
|
|||
|
||||
codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error}
|
||||
|
||||
codegen_ssa_autodiff_without_lto = using the autodiff feature requires using fat-lto
|
||||
|
||||
codegen_ssa_bare_instruction_set = `#[instruction_set]` requires an argument
|
||||
|
||||
codegen_ssa_binary_output_to_tty = option `-o` or `--emit` is used to write binary output type `{$shorthand}` to stdout, but stdout is a tty
|
||||
|
|
@ -31,7 +29,7 @@ codegen_ssa_cpu_required = target requires explicitly specifying a cpu with `-C
|
|||
codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
|
||||
|
||||
codegen_ssa_dlltool_fail_import_library =
|
||||
Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
|
||||
dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
|
||||
{$stdout}
|
||||
{$stderr}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ impl Command {
|
|||
}
|
||||
Program::Lld(ref p, flavor) => {
|
||||
let mut c = process::Command::new(p);
|
||||
c.arg("-flavor").arg(flavor.as_str());
|
||||
c.arg("-flavor").arg(flavor.desc());
|
||||
c
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -168,9 +168,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
(&ty::Array(_, len), &ty::Slice(_)) => cx.const_usize(
|
||||
len.try_to_target_usize(cx.tcx()).expect("expected monomorphic const in codegen"),
|
||||
),
|
||||
(&ty::Dynamic(data_a, _, src_dyn_kind), &ty::Dynamic(data_b, _, target_dyn_kind))
|
||||
if src_dyn_kind == target_dyn_kind =>
|
||||
{
|
||||
(&ty::Dynamic(data_a, _), &ty::Dynamic(data_b, _)) => {
|
||||
let old_info =
|
||||
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
|
||||
let b_principal_def_id = data_b.principal_def_id();
|
||||
|
|
@ -208,7 +206,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
old_info
|
||||
}
|
||||
}
|
||||
(_, ty::Dynamic(data, _, _)) => meth::get_vtable(
|
||||
(_, ty::Dynamic(data, _)) => meth::get_vtable(
|
||||
cx,
|
||||
source,
|
||||
data.principal()
|
||||
|
|
|
|||
|
|
@ -296,6 +296,12 @@ fn process_builtin_attrs(
|
|||
AttributeKind::Sanitize { span, .. } => {
|
||||
interesting_spans.sanitize = Some(*span);
|
||||
}
|
||||
AttributeKind::ObjcClass { classname, .. } => {
|
||||
codegen_fn_attrs.objc_class = Some(*classname);
|
||||
}
|
||||
AttributeKind::ObjcSelector { methname, .. } => {
|
||||
codegen_fn_attrs.objc_selector = Some(*methname);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -562,15 +568,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
codegen_fn_attrs
|
||||
}
|
||||
|
||||
/// If the provided DefId is a method in a trait impl, return the DefId of the method prototype.
|
||||
fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
|
||||
let impl_item = tcx.opt_associated_item(def_id)?;
|
||||
match impl_item.container {
|
||||
ty::AssocItemContainer::Impl => impl_item.trait_item_def_id,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
|
||||
// Backtrack to the crate root.
|
||||
let mut disabled = match tcx.opt_local_parent(did) {
|
||||
|
|
@ -600,14 +597,15 @@ fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
|
|||
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
|
||||
/// applied to the method prototype.
|
||||
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
let Some(trait_item) = opt_trait_item(tcx, def_id) else { return false };
|
||||
tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
|
||||
tcx.trait_item_of(def_id).is_some_and(|id| {
|
||||
tcx.codegen_fn_attrs(id).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
|
||||
})
|
||||
}
|
||||
|
||||
/// If the provided DefId is a method in a trait impl, return the value of the `#[align]`
|
||||
/// attribute on the method prototype (if any).
|
||||
fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Align> {
|
||||
tcx.codegen_fn_attrs(opt_trait_item(tcx, def_id)?).alignment
|
||||
tcx.codegen_fn_attrs(tcx.trait_item_of(def_id)?).alignment
|
||||
}
|
||||
|
||||
/// We now check the #\[rustc_autodiff\] attributes which we generated from the #[autodiff(...)]
|
||||
|
|
|
|||
|
|
@ -37,10 +37,6 @@ pub(crate) struct CguNotRecorded<'a> {
|
|||
pub cgu_name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_autodiff_without_lto)]
|
||||
pub struct AutodiffWithoutLto;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_unknown_reuse_kind)]
|
||||
pub(crate) struct UnknownReuseKind {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ fn dyn_trait_in_self<'tcx>(
|
|||
) -> Option<ty::ExistentialTraitRef<'tcx>> {
|
||||
for arg in ty.peel_refs().walk() {
|
||||
if let GenericArgKind::Type(ty) = arg.kind()
|
||||
&& let ty::Dynamic(data, _, _) = ty.kind()
|
||||
&& let ty::Dynamic(data, _) = ty.kind()
|
||||
{
|
||||
// FIXME(arbitrary_self_types): This is likely broken for receivers which
|
||||
// have a "non-self" trait objects as a generic argument.
|
||||
|
|
|
|||
|
|
@ -520,7 +520,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
LocalRef::Place(va_list) => {
|
||||
bx.va_end(va_list.val.llval);
|
||||
|
||||
// Explicitly end the lifetime of the `va_list`, this matters for LLVM.
|
||||
// Explicitly end the lifetime of the `va_list`, improves LLVM codegen.
|
||||
bx.lifetime_end(va_list.val.llval, va_list.layout.size);
|
||||
}
|
||||
_ => bug!("C-variadic function must have a `VaList` place"),
|
||||
|
|
@ -614,7 +614,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let (maybe_null, drop_fn, fn_abi, drop_instance) = match ty.kind() {
|
||||
// FIXME(eddyb) perhaps move some of this logic into
|
||||
// `Instance::resolve_drop_in_place`?
|
||||
ty::Dynamic(_, _, ty::Dyn) => {
|
||||
ty::Dynamic(_, _) => {
|
||||
// IN THIS ARM, WE HAVE:
|
||||
// ty = *mut (dyn Trait)
|
||||
// which is: exists<T> ( *mut T, Vtable<T: Trait> )
|
||||
|
|
|
|||
|
|
@ -438,6 +438,10 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
if fx.fn_abi.c_variadic && arg_index == fx.fn_abi.args.len() {
|
||||
let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty));
|
||||
|
||||
// Explicitly start the lifetime of the `va_list`, improves LLVM codegen.
|
||||
bx.lifetime_start(va_list.val.llval, va_list.layout.size);
|
||||
|
||||
bx.va_start(va_list.val.llval);
|
||||
|
||||
return LocalRef::Place(va_list);
|
||||
|
|
|
|||
|
|
@ -228,6 +228,9 @@ fn prefix_and_suffix<'tcx>(
|
|||
writeln!(begin, "{asm_name}:").unwrap();
|
||||
|
||||
writeln!(end).unwrap();
|
||||
// emit a label starting with `func_end` for `cargo asm` and other tooling that might
|
||||
// pattern match on assembly generated by LLVM.
|
||||
writeln!(end, ".Lfunc_end_{asm_name}:").unwrap();
|
||||
writeln!(end, ".size {asm_name}, . - {asm_name}").unwrap();
|
||||
writeln!(end, ".popsection").unwrap();
|
||||
if !arch_suffix.is_empty() {
|
||||
|
|
@ -246,6 +249,7 @@ fn prefix_and_suffix<'tcx>(
|
|||
writeln!(begin, "{asm_name}:").unwrap();
|
||||
|
||||
writeln!(end).unwrap();
|
||||
writeln!(end, ".Lfunc_end_{asm_name}:").unwrap();
|
||||
writeln!(end, ".popsection").unwrap();
|
||||
if !arch_suffix.is_empty() {
|
||||
writeln!(end, "{}", arch_suffix).unwrap();
|
||||
|
|
@ -263,6 +267,7 @@ fn prefix_and_suffix<'tcx>(
|
|||
writeln!(begin, "{asm_name}:").unwrap();
|
||||
|
||||
writeln!(end).unwrap();
|
||||
writeln!(end, ".Lfunc_end_{asm_name}:").unwrap();
|
||||
writeln!(end, ".popsection").unwrap();
|
||||
if !arch_suffix.is_empty() {
|
||||
writeln!(end, "{}", arch_suffix).unwrap();
|
||||
|
|
@ -287,6 +292,7 @@ fn prefix_and_suffix<'tcx>(
|
|||
writeln!(end).unwrap();
|
||||
// .size is ignored for function symbols, so we can skip it
|
||||
writeln!(end, "end_function").unwrap();
|
||||
writeln!(end, ".Lfunc_end_{asm_name}:").unwrap();
|
||||
}
|
||||
BinaryFormat::Xcoff => {
|
||||
// the LLVM XCOFFAsmParser is extremely incomplete and does not implement many of the
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use itertools::Itertools as _;
|
||||
use rustc_abi::{self as abi, FIRST_VARIANT};
|
||||
use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT};
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||
|
|
@ -7,9 +7,9 @@ use rustc_middle::{bug, mir, span_bug};
|
|||
use rustc_session::config::OptLevel;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use super::FunctionCx;
|
||||
use super::operand::{OperandRef, OperandRefBuilder, OperandValue};
|
||||
use super::place::{PlaceRef, PlaceValue, codegen_tag_value};
|
||||
use super::{FunctionCx, LocalRef};
|
||||
use crate::common::{IntPredicate, TypeKind};
|
||||
use crate::traits::*;
|
||||
use crate::{MemFlags, base};
|
||||
|
|
@ -25,6 +25,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
match *rvalue {
|
||||
mir::Rvalue::Use(ref operand) => {
|
||||
let cg_operand = self.codegen_operand(bx, operand);
|
||||
// Crucially, we do *not* use `OperandValue::Ref` for types with
|
||||
// `BackendRepr::Scalar | BackendRepr::ScalarPair`. This ensures we match the MIR
|
||||
// semantics regarding when assignment operators allow overlap of LHS and RHS.
|
||||
if matches!(
|
||||
cg_operand.layout.backend_repr,
|
||||
BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..),
|
||||
) {
|
||||
debug_assert!(!matches!(cg_operand.val, OperandValue::Ref(..)));
|
||||
}
|
||||
// FIXME: consider not copying constants through stack. (Fixable by codegen'ing
|
||||
// constants into `OperandValue::Ref`; why don’t we do that yet if we don’t?)
|
||||
cg_operand.val.store(bx, dest);
|
||||
|
|
@ -501,14 +510,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
self.codegen_place_to_pointer(bx, place, mk_ptr)
|
||||
}
|
||||
|
||||
mir::Rvalue::Len(place) => {
|
||||
let size = self.evaluate_array_len(bx, place);
|
||||
OperandRef {
|
||||
val: OperandValue::Immediate(size),
|
||||
layout: bx.cx().layout_of(bx.tcx().types.usize),
|
||||
}
|
||||
}
|
||||
|
||||
mir::Rvalue::BinaryOp(op_with_overflow, box (ref lhs, ref rhs))
|
||||
if let Some(op) = op_with_overflow.overflowing_to_wrapping() =>
|
||||
{
|
||||
|
|
@ -740,21 +741,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn evaluate_array_len(&mut self, bx: &mut Bx, place: mir::Place<'tcx>) -> Bx::Value {
|
||||
// ZST are passed as operands and require special handling
|
||||
// because codegen_place() panics if Local is operand.
|
||||
if let Some(index) = place.as_local()
|
||||
&& let LocalRef::Operand(op) = self.locals[index]
|
||||
&& let ty::Array(_, n) = op.layout.ty.kind()
|
||||
{
|
||||
let n = n.try_to_target_usize(bx.tcx()).expect("expected monomorphic const in codegen");
|
||||
return bx.cx().const_usize(n);
|
||||
}
|
||||
// use common size calculation for non zero-sized types
|
||||
let cg_value = self.codegen_place(bx, place.as_ref());
|
||||
cg_value.len(bx.cx())
|
||||
}
|
||||
|
||||
/// Codegen an `Rvalue::RawPtr` or `Rvalue::Ref`
|
||||
fn codegen_place_to_pointer(
|
||||
&mut self,
|
||||
|
|
@ -892,36 +878,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
mir::BinOp::Cmp => {
|
||||
use std::cmp::Ordering;
|
||||
assert!(!is_float);
|
||||
if let Some(value) = bx.three_way_compare(lhs_ty, lhs, rhs) {
|
||||
return value;
|
||||
}
|
||||
let pred = |op| base::bin_op_to_icmp_predicate(op, is_signed);
|
||||
if bx.cx().tcx().sess.opts.optimize == OptLevel::No {
|
||||
// FIXME: This actually generates tighter assembly, and is a classic trick
|
||||
// <https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign>
|
||||
// However, as of 2023-11 it optimizes worse in things like derived
|
||||
// `PartialOrd`, so only use it in debug for now. Once LLVM can handle it
|
||||
// better (see <https://github.com/llvm/llvm-project/issues/73417>), it'll
|
||||
// be worth trying it in optimized builds as well.
|
||||
let is_gt = bx.icmp(pred(mir::BinOp::Gt), lhs, rhs);
|
||||
let gtext = bx.zext(is_gt, bx.type_i8());
|
||||
let is_lt = bx.icmp(pred(mir::BinOp::Lt), lhs, rhs);
|
||||
let ltext = bx.zext(is_lt, bx.type_i8());
|
||||
bx.unchecked_ssub(gtext, ltext)
|
||||
} else {
|
||||
// These operations are those expected by `tests/codegen-llvm/integer-cmp.rs`,
|
||||
// from <https://github.com/rust-lang/rust/pull/63767>.
|
||||
let is_lt = bx.icmp(pred(mir::BinOp::Lt), lhs, rhs);
|
||||
let is_ne = bx.icmp(pred(mir::BinOp::Ne), lhs, rhs);
|
||||
let ge = bx.select(
|
||||
is_ne,
|
||||
bx.cx().const_i8(Ordering::Greater as i8),
|
||||
bx.cx().const_i8(Ordering::Equal as i8),
|
||||
);
|
||||
bx.select(is_lt, bx.cx().const_i8(Ordering::Less as i8), ge)
|
||||
}
|
||||
bx.three_way_compare(lhs_ty, lhs, rhs)
|
||||
}
|
||||
mir::BinOp::AddWithOverflow
|
||||
| mir::BinOp::SubWithOverflow
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::ops::Deref;
|
|||
|
||||
use rustc_abi::{Align, Scalar, Size, WrappingRange};
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::{AtomicOrdering, Instance, Ty};
|
||||
use rustc_session::config::OptLevel;
|
||||
|
|
@ -405,15 +406,41 @@ pub trait BuilderMethods<'a, 'tcx>:
|
|||
fn fcmp(&mut self, op: RealPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
|
||||
|
||||
/// Returns `-1` if `lhs < rhs`, `0` if `lhs == rhs`, and `1` if `lhs > rhs`.
|
||||
// FIXME: Move the default implementation from `codegen_scalar_binop` into this method and
|
||||
// remove the `Option` return once LLVM 20 is the minimum version.
|
||||
fn three_way_compare(
|
||||
&mut self,
|
||||
_ty: Ty<'tcx>,
|
||||
_lhs: Self::Value,
|
||||
_rhs: Self::Value,
|
||||
) -> Option<Self::Value> {
|
||||
None
|
||||
ty: Ty<'tcx>,
|
||||
lhs: Self::Value,
|
||||
rhs: Self::Value,
|
||||
) -> Self::Value {
|
||||
// FIXME: This implementation was designed around LLVM's ability to optimize, but `cg_llvm`
|
||||
// overrides this to just use `@llvm.scmp`/`ucmp` since LLVM 20. This default impl should be
|
||||
// reevaluated with respect to the remaining backends like cg_gcc, whether they might use
|
||||
// specialized implementations as well, or continue to use a generic implementation here.
|
||||
use std::cmp::Ordering;
|
||||
let pred = |op| crate::base::bin_op_to_icmp_predicate(op, ty.is_signed());
|
||||
if self.cx().sess().opts.optimize == OptLevel::No {
|
||||
// This actually generates tighter assembly, and is a classic trick:
|
||||
// <https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign>.
|
||||
// However, as of 2023-11 it optimized worse in LLVM in things like derived
|
||||
// `PartialOrd`, so we were only using it in debug. Since LLVM now uses its own
|
||||
// intrinsics, it may be be worth trying it in optimized builds for other backends.
|
||||
let is_gt = self.icmp(pred(mir::BinOp::Gt), lhs, rhs);
|
||||
let gtext = self.zext(is_gt, self.type_i8());
|
||||
let is_lt = self.icmp(pred(mir::BinOp::Lt), lhs, rhs);
|
||||
let ltext = self.zext(is_lt, self.type_i8());
|
||||
self.unchecked_ssub(gtext, ltext)
|
||||
} else {
|
||||
// These operations were better optimized by LLVM, before `@llvm.scmp`/`ucmp` in 20.
|
||||
// See <https://github.com/rust-lang/rust/pull/63767>.
|
||||
let is_lt = self.icmp(pred(mir::BinOp::Lt), lhs, rhs);
|
||||
let is_ne = self.icmp(pred(mir::BinOp::Ne), lhs, rhs);
|
||||
let ge = self.select(
|
||||
is_ne,
|
||||
self.cx().const_i8(Ordering::Greater as i8),
|
||||
self.cx().const_i8(Ordering::Equal as i8),
|
||||
);
|
||||
self.select(is_lt, self.cx().const_i8(Ordering::Less as i8), ge)
|
||||
}
|
||||
}
|
||||
|
||||
fn memcpy(
|
||||
|
|
|
|||
|
|
@ -573,8 +573,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
Rvalue::Use(_)
|
||||
| Rvalue::CopyForDeref(..)
|
||||
| Rvalue::Repeat(..)
|
||||
| Rvalue::Discriminant(..)
|
||||
| Rvalue::Len(_) => {}
|
||||
| Rvalue::Discriminant(..) => {}
|
||||
|
||||
Rvalue::Aggregate(kind, ..) => {
|
||||
if let AggregateKind::Coroutine(def_id, ..) = kind.as_ref()
|
||||
|
|
|
|||
|
|
@ -232,9 +232,7 @@ where
|
|||
Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx))
|
||||
}
|
||||
|
||||
Rvalue::Discriminant(place) | Rvalue::Len(place) => {
|
||||
in_place::<Q, _>(cx, in_local, place.as_ref())
|
||||
}
|
||||
Rvalue::Discriminant(place) => in_place::<Q, _>(cx, in_local, place.as_ref()),
|
||||
|
||||
Rvalue::CopyForDeref(place) => in_place::<Q, _>(cx, in_local, place.as_ref()),
|
||||
|
||||
|
|
|
|||
|
|
@ -197,7 +197,6 @@ where
|
|||
| mir::Rvalue::CopyForDeref(..)
|
||||
| mir::Rvalue::ThreadLocalRef(..)
|
||||
| mir::Rvalue::Repeat(..)
|
||||
| mir::Rvalue::Len(..)
|
||||
| mir::Rvalue::BinaryOp(..)
|
||||
| mir::Rvalue::NullaryOp(..)
|
||||
| mir::Rvalue::UnaryOp(..)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use rustc_abi::{BackendRepr, FieldIdx, VariantIdx};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError};
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::layout::{LayoutCx, TyAndLayout};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, mir};
|
||||
|
|
@ -196,6 +197,7 @@ fn reconstruct_place_meta<'tcx>(
|
|||
// Traverse the type, and update `last_valtree` as we go.
|
||||
let tail = tcx.struct_tail_raw(
|
||||
layout.ty,
|
||||
&ObligationCause::dummy(),
|
||||
|ty| ty,
|
||||
|| {
|
||||
let branches = last_valtree.unwrap_branch();
|
||||
|
|
|
|||
|
|
@ -658,7 +658,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
let val = self.read_immediate(&receiver)?;
|
||||
break self.ref_to_mplace(&val)?;
|
||||
}
|
||||
ty::Dynamic(.., ty::Dyn) => break receiver.assert_mem_place(), // no immediate unsized values
|
||||
ty::Dynamic(..) => break receiver.assert_mem_place(), // no immediate unsized values
|
||||
_ => {
|
||||
// Not there yet, search for the only non-ZST field.
|
||||
// (The rules for `DispatchFromDyn` ensure there's exactly one such field.)
|
||||
|
|
@ -675,7 +675,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
// (For that reason we also cannot use `unpack_dyn_trait`.)
|
||||
let receiver_tail =
|
||||
self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env);
|
||||
let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
|
||||
let ty::Dynamic(receiver_trait, _) = receiver_tail.kind() else {
|
||||
span_bug!(self.cur_span(), "dynamic call on non-`dyn` type {}", receiver_tail)
|
||||
};
|
||||
assert!(receiver_place.layout.is_unsized());
|
||||
|
|
@ -822,7 +822,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
// instead we do the virtual call stuff ourselves. It's easier here than in `eval_fn_call`
|
||||
// since we can just get a place of the underlying type and use `mplace_to_ref`.
|
||||
let place = match place.layout.ty.kind() {
|
||||
ty::Dynamic(data, _, ty::Dyn) => {
|
||||
ty::Dynamic(data, _) => {
|
||||
// Dropping a trait object. Need to find actual drop fn.
|
||||
self.unpack_dyn_trait(&place, data)?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -386,7 +386,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
);
|
||||
self.write_immediate(val, dest)
|
||||
}
|
||||
(ty::Dynamic(data_a, _, ty::Dyn), ty::Dynamic(data_b, _, ty::Dyn)) => {
|
||||
(ty::Dynamic(data_a, _), ty::Dynamic(data_b, _)) => {
|
||||
let val = self.read_immediate(src)?;
|
||||
// MIR building generates odd NOP casts, prevent them from causing unexpected trouble.
|
||||
// See <https://github.com/rust-lang/rust/issues/128880>.
|
||||
|
|
@ -436,7 +436,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
let new_vptr = self.get_vtable_ptr(ty, data_b)?;
|
||||
self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
|
||||
}
|
||||
(_, &ty::Dynamic(data, _, ty::Dyn)) => {
|
||||
(_, &ty::Dynamic(data, _)) => {
|
||||
// Initial cast from sized to dyn trait
|
||||
let vtable = self.get_vtable_ptr(src_pointee_ty, data)?;
|
||||
let ptr = self.read_pointer(src)?;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use either::{Left, Right};
|
|||
use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout};
|
||||
use rustc_errors::DiagCtxtHandle;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::limit::Limit;
|
||||
use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
use rustc_middle::ty::layout::{
|
||||
|
|
@ -12,7 +13,6 @@ use rustc_middle::ty::layout::{
|
|||
};
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypingEnv, Variance};
|
||||
use rustc_middle::{mir, span_bug};
|
||||
use rustc_session::Limit;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::callconv::FnAbi;
|
||||
use tracing::{debug, trace};
|
||||
|
|
@ -469,7 +469,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
}
|
||||
interp_ok(Some((full_size, full_align)))
|
||||
}
|
||||
ty::Dynamic(expected_trait, _, ty::Dyn) => {
|
||||
ty::Dynamic(expected_trait, _) => {
|
||||
let vtable = metadata.unwrap_meta().to_pointer(self)?;
|
||||
// Read size and align from vtable (already checks size).
|
||||
interp_ok(Some(self.get_vtable_size_and_align(vtable, Some(expected_trait))?))
|
||||
|
|
|
|||
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