commit
0231fa9adf
3305 changed files with 48166 additions and 27855 deletions
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
|
@ -152,6 +152,9 @@ jobs:
|
|||
- name: show the current environment
|
||||
run: src/ci/scripts/dump-environment.sh
|
||||
|
||||
- name: install rust
|
||||
run: src/ci/scripts/install-rust.sh
|
||||
|
||||
- name: install awscli
|
||||
run: src/ci/scripts/install-awscli.sh
|
||||
|
||||
|
|
|
|||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -85,8 +85,6 @@ __pycache__/
|
|||
|
||||
## Node
|
||||
node_modules
|
||||
package-lock.json
|
||||
package.json
|
||||
/src/doc/rustc-dev-guide/mermaid.min.js
|
||||
|
||||
## Rustdoc GUI tests
|
||||
|
|
|
|||
2
.gitmodules
vendored
2
.gitmodules
vendored
|
|
@ -25,7 +25,7 @@
|
|||
[submodule "src/llvm-project"]
|
||||
path = src/llvm-project
|
||||
url = https://github.com/rust-lang/llvm-project.git
|
||||
branch = rustc/20.1-2025-02-13
|
||||
branch = rustc/20.1-2025-07-13
|
||||
shallow = true
|
||||
[submodule "src/doc/embedded-book"]
|
||||
path = src/doc/embedded-book
|
||||
|
|
|
|||
478
Cargo.lock
478
Cargo.lock
|
|
@ -216,7 +216,7 @@ dependencies = [
|
|||
"memchr",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"winnow 0.7.11",
|
||||
"winnow 0.7.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -351,12 +351,6 @@ version = "0.6.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||
|
||||
[[package]]
|
||||
name = "camino"
|
||||
version = "1.1.10"
|
||||
|
|
@ -390,7 +384,7 @@ dependencies = [
|
|||
name = "cargo-miri"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cargo_metadata 0.19.2",
|
||||
"cargo_metadata 0.21.0",
|
||||
"directories",
|
||||
"rustc-build-sysroot",
|
||||
"rustc_tools_util 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -408,6 +402,31 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo-platform"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84982c6c0ae343635a3a4ee6dedef965513735c8b183caa7289fa6e27399ebd4"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo-util-schemas"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dc1a6f7b5651af85774ae5a34b4e8be397d9cf4bc063b7e6dbd99a841837830"
|
||||
dependencies = [
|
||||
"semver",
|
||||
"serde",
|
||||
"serde-untagged",
|
||||
"serde-value",
|
||||
"thiserror 2.0.12",
|
||||
"toml 0.8.23",
|
||||
"unicode-xid",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.18.1"
|
||||
|
|
@ -415,7 +434,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"cargo-platform",
|
||||
"cargo-platform 0.1.9",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -429,7 +448,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"cargo-platform",
|
||||
"cargo-platform 0.1.9",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cfca2aaa699835ba88faf58a06342a314a950d2b9686165e038286c30316868"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"cargo-platform 0.2.0",
|
||||
"cargo-util-schemas",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -476,23 +510,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chrono-tz"
|
||||
version = "0.10.3"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3"
|
||||
checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-tz-build",
|
||||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono-tz-build"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402"
|
||||
dependencies = [
|
||||
"parse-zoneinfo",
|
||||
"phf_codegen",
|
||||
"phf 0.12.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -507,9 +530,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.40"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
|
||||
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
|
@ -527,9 +550,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.40"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
|
||||
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
|
@ -539,9 +562,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.40"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
|
||||
checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
|
|
@ -569,20 +592,14 @@ dependencies = [
|
|||
"color-print",
|
||||
"declare_clippy_lint",
|
||||
"filetime",
|
||||
"futures",
|
||||
"if_chain",
|
||||
"itertools",
|
||||
"parking_lot",
|
||||
"pulldown-cmark",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc_tools_util 0.4.2",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.104",
|
||||
"tempfile",
|
||||
"termize 0.1.1",
|
||||
"tokio",
|
||||
"termize",
|
||||
"toml 0.7.8",
|
||||
"ui_test",
|
||||
"walkdir",
|
||||
|
|
@ -726,6 +743,15 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "comma"
|
||||
version = "1.0.0"
|
||||
|
|
@ -739,7 +765,7 @@ dependencies = [
|
|||
"anstyle-svg",
|
||||
"build_helper",
|
||||
"camino",
|
||||
"colored",
|
||||
"colored 2.2.0",
|
||||
"diff",
|
||||
"getopts",
|
||||
"glob",
|
||||
|
|
@ -810,9 +836,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
|
@ -1001,9 +1027,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "derive_setters"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c848e86c87e5cc305313041c5677d4d95d60baa71cf95e5f6ea2554bb629ff"
|
||||
checksum = "ae5c625eda104c228c06ecaf988d1c60e542176bd7a490e60eeda3493244c0c9"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
|
|
@ -1166,6 +1192,16 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "erased-serde"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"typeid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.13"
|
||||
|
|
@ -1322,95 +1358,6 @@ dependencies = [
|
|||
"new_debug_unreachable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generate-copyright"
|
||||
version = "0.1.0"
|
||||
|
|
@ -1848,12 +1795,6 @@ dependencies = [
|
|||
"icu_properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "if_chain"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
||||
|
||||
[[package]]
|
||||
name = "ignore"
|
||||
version = "0.4.23"
|
||||
|
|
@ -1947,30 +1888,18 @@ dependencies = [
|
|||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipc-channel"
|
||||
version = "0.19.0"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fb8251fb7bcd9ccd3725ed8deae9fe7db8e586495c9eb5b0c52e6233e5e75ea"
|
||||
checksum = "5b1c98b70019c830a1fc39cecfe1f60ff99c4122f0a189697c810c90ec545c14"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"crossbeam-channel",
|
||||
"fnv",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"mio",
|
||||
"rand 0.8.5",
|
||||
"rand 0.9.1",
|
||||
"serde",
|
||||
"tempfile",
|
||||
"uuid",
|
||||
|
|
@ -2163,9 +2092,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
|||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.4"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638"
|
||||
checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
|
|
@ -2275,7 +2204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
|
||||
dependencies = [
|
||||
"log",
|
||||
"phf",
|
||||
"phf 0.11.3",
|
||||
"phf_codegen",
|
||||
"string_cache",
|
||||
"string_cache_codegen",
|
||||
|
|
@ -2314,9 +2243,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "measureme"
|
||||
version = "12.0.1"
|
||||
version = "12.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "570a507d8948a66a97f42cbbaf8a6bb9516a51017d4ee949502ad7a10a864395"
|
||||
checksum = "6ebd1ebda747ae161a4a377bf93f87e18d46faad2331cc0c7d25b84b1d445f49"
|
||||
dependencies = [
|
||||
"log",
|
||||
"memmap2",
|
||||
|
|
@ -2369,7 +2298,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
|
@ -2392,7 +2320,7 @@ dependencies = [
|
|||
"capstone",
|
||||
"chrono",
|
||||
"chrono-tz",
|
||||
"colored",
|
||||
"colored 3.0.0",
|
||||
"directories",
|
||||
"getrandom 0.3.3",
|
||||
"ipc-channel",
|
||||
|
|
@ -2689,6 +2617,15 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "2.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
|
|
@ -2750,15 +2687,6 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-zoneinfo"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathdiff"
|
||||
version = "0.2.3"
|
||||
|
|
@ -2830,7 +2758,16 @@ version = "0.11.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
|
||||
dependencies = [
|
||||
"phf_shared 0.12.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2840,7 +2777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2849,7 +2786,7 @@ version = "0.11.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
|
|
@ -2862,18 +2799,21 @@ dependencies = [
|
|||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.32"
|
||||
|
|
@ -3214,7 +3154,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "run_make_support"
|
||||
version = "0.2.0"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"build_helper",
|
||||
|
|
@ -3260,9 +3200,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
|||
|
||||
[[package]]
|
||||
name = "rustc-literal-escaper"
|
||||
version = "0.0.4"
|
||||
version = "0.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab03008eb631b703dd16978282ae36c73282e7922fe101a4bd072a40ecea7b8b"
|
||||
checksum = "e4ee29da77c5a54f42697493cd4c9b9f31b74df666a6c04dfc4fde77abe0438b"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-main"
|
||||
|
|
@ -3271,8 +3211,8 @@ dependencies = [
|
|||
"rustc_codegen_ssa",
|
||||
"rustc_driver",
|
||||
"rustc_driver_impl",
|
||||
"rustc_smir",
|
||||
"stable_mir",
|
||||
"rustc_public",
|
||||
"rustc_public_bridge",
|
||||
"tikv-jemalloc-sys",
|
||||
]
|
||||
|
||||
|
|
@ -3709,6 +3649,7 @@ dependencies = [
|
|||
"rustc_passes",
|
||||
"rustc_pattern_analysis",
|
||||
"rustc_privacy",
|
||||
"rustc_public",
|
||||
"rustc_query_system",
|
||||
"rustc_resolve",
|
||||
"rustc_session",
|
||||
|
|
@ -3718,7 +3659,6 @@ dependencies = [
|
|||
"rustc_ty_utils",
|
||||
"serde_json",
|
||||
"shlex",
|
||||
"stable_mir",
|
||||
"tracing",
|
||||
"windows 0.61.3",
|
||||
]
|
||||
|
|
@ -3773,7 +3713,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"termcolor",
|
||||
"termize 0.2.0",
|
||||
"termize",
|
||||
"tracing",
|
||||
"windows 0.61.3",
|
||||
]
|
||||
|
|
@ -4349,6 +4289,7 @@ dependencies = [
|
|||
"rustc_ast_lowering",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_expand",
|
||||
|
|
@ -4414,6 +4355,36 @@ dependencies = [
|
|||
"rustc-literal-escaper",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_public"
|
||||
version = "0.1.0-preview"
|
||||
dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_hir",
|
||||
"rustc_middle",
|
||||
"rustc_public_bridge",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"scoped-tls",
|
||||
"serde",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_public_bridge"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_data_structures",
|
||||
"rustc_hir",
|
||||
"rustc_hir_pretty",
|
||||
"rustc_middle",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_query_impl"
|
||||
version = "0.0.0"
|
||||
|
|
@ -4536,25 +4507,11 @@ dependencies = [
|
|||
"rustc_serialize",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"termize 0.2.0",
|
||||
"termize",
|
||||
"tracing",
|
||||
"windows 0.61.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_smir"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_data_structures",
|
||||
"rustc_hir",
|
||||
"rustc_hir_pretty",
|
||||
"rustc_middle",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_span"
|
||||
version = "0.0.0"
|
||||
|
|
@ -4859,15 +4816,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
|
||||
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4954,6 +4911,27 @@ dependencies = [
|
|||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-untagged"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "299d9c19d7d466db4ab10addd5703e4c615dec2a5a16dbbafe191045e87ee66e"
|
||||
dependencies = [
|
||||
"erased-serde",
|
||||
"serde",
|
||||
"typeid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-value"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
|
||||
dependencies = [
|
||||
"ordered-float",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
|
|
@ -4967,9 +4945,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.140"
|
||||
version = "1.0.141"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
|
|
@ -5035,12 +5013,6 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.1"
|
||||
|
|
@ -5059,10 +5031,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "spanned"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86af297923fbcfd107c20a189a6e9c872160df71a7190ae4a7a6c5dce4b2feb6"
|
||||
checksum = "c92d4b0c055fde758f086eb4a6e73410247df8a3837fd606d2caeeaf72aa566d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bstr",
|
||||
"color-eyre",
|
||||
]
|
||||
|
|
@ -5102,22 +5075,6 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "stable_mir"
|
||||
version = "0.1.0-preview"
|
||||
dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_hir",
|
||||
"rustc_middle",
|
||||
"rustc_session",
|
||||
"rustc_smir",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"scoped-tls",
|
||||
"serde",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stacker"
|
||||
version = "0.1.21"
|
||||
|
|
@ -5145,7 +5102,7 @@ checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
|
|||
dependencies = [
|
||||
"new_debug_unreachable",
|
||||
"parking_lot",
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
"precomputed-hash",
|
||||
"serde",
|
||||
]
|
||||
|
|
@ -5157,7 +5114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
|
@ -5187,14 +5144,6 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "suggest-tests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"build_helper",
|
||||
"glob",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
|
|
@ -5230,9 +5179,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.35.2"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3ffa3e4ff2b324a57f7aeb3c349656c7b127c3c189520251a648102a92496e"
|
||||
checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"objc2-core-foundation",
|
||||
|
|
@ -5305,16 +5254,6 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termize"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1706be6b564323ce7092f5f7e6b118a14c8ef7ed0e69c8c5329c914a9f101295"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termize"
|
||||
version = "0.2.0"
|
||||
|
|
@ -5480,21 +5419,6 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.46.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"io-uring",
|
||||
"libc",
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
|
|
@ -5562,7 +5486,7 @@ dependencies = [
|
|||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_write",
|
||||
"winnow 0.7.11",
|
||||
"winnow 0.7.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5682,6 +5606,12 @@ dependencies = [
|
|||
"rustc-hash 2.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeid"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.18.0"
|
||||
|
|
@ -5705,17 +5635,17 @@ checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
|||
|
||||
[[package]]
|
||||
name = "ui_test"
|
||||
version = "0.29.2"
|
||||
version = "0.30.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1211b1111c752c73b33073d2958072be08825fd97c9ab4d83444da361a06634b"
|
||||
checksum = "b56a6897cc4bb6f8daf1939b0b39cd9645856997f46f4d0b3e3cb7122dfe9251"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.11.5",
|
||||
"anyhow",
|
||||
"bstr",
|
||||
"cargo-platform",
|
||||
"cargo-platform 0.1.9",
|
||||
"cargo_metadata 0.18.1",
|
||||
"color-eyre",
|
||||
"colored",
|
||||
"colored 2.2.0",
|
||||
"comma",
|
||||
"crossbeam-channel",
|
||||
"indicatif",
|
||||
|
|
@ -5954,9 +5884,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasi-preview1-component-adapter-provider"
|
||||
version = "34.0.1"
|
||||
version = "34.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aafa1e6af9a954a4bcf6ef420c33355d0ce84ddc6afbcba7bb6f05126f9120ae"
|
||||
checksum = "33696c5f1ff1e083de9f36c3da471abd736362bc173e093f8b0b1ed5a387e39b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
|
|
@ -6600,9 +6530,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.11"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
|
||||
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ members = [
|
|||
"src/tools/rustdoc-gui-test",
|
||||
"src/tools/rustdoc-themes",
|
||||
"src/tools/rustfmt",
|
||||
"src/tools/suggest-tests",
|
||||
"src/tools/test-float-parse",
|
||||
"src/tools/tidy",
|
||||
"src/tools/tier-check",
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ path = [
|
|||
"rust-bors.toml",
|
||||
"triagebot.toml",
|
||||
"typos.toml",
|
||||
"package.json",
|
||||
"package-lock.json",
|
||||
"x",
|
||||
"x.ps1",
|
||||
"x.py",
|
||||
|
|
|
|||
|
|
@ -392,7 +392,8 @@
|
|||
# For example, to build Miri with tracing support, use `tool.miri.features = ["tracing"]`
|
||||
#
|
||||
# The default value for the `features` array is `[]`. However, please note that other flags in
|
||||
# `bootstrap.toml` might influence the features enabled for some tools.
|
||||
# `bootstrap.toml` might influence the features enabled for some tools. Also, enabling features
|
||||
# in tools which are not part of the internal "extra-features" preset might not always work.
|
||||
#build.tool.TOOL_NAME.features = [FEATURE1, FEATURE2]
|
||||
|
||||
# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
|
|||
rustc_driver = { path = "../rustc_driver" }
|
||||
rustc_driver_impl = { path = "../rustc_driver_impl" }
|
||||
|
||||
# Make sure rustc_smir ends up in the sysroot, because this
|
||||
# crate is intended to be used by stable MIR consumers, which are not in-tree.
|
||||
rustc_smir = { path = "../rustc_smir" }
|
||||
rustc_public = { path = "../rustc_public" }
|
||||
|
||||
stable_mir = { path = "../stable_mir" }
|
||||
# Make sure rustc_public_bridge ends up in the sysroot, because this
|
||||
# crate is intended to be used by stable MIR consumers, which are not in-tree.
|
||||
rustc_public_bridge = { path = "../rustc_public_bridge" }
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[dependencies.tikv-jemalloc-sys]
|
||||
|
|
@ -27,6 +27,7 @@ features = ['unprefixed_malloc_on_supported_platforms']
|
|||
|
||||
[features]
|
||||
# tidy-alphabetical-start
|
||||
check_only = ['rustc_driver_impl/check_only']
|
||||
jemalloc = ['dep:tikv-jemalloc-sys']
|
||||
llvm = ['rustc_driver_impl/llvm']
|
||||
max_level_info = ['rustc_driver_impl/max_level_info']
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ use std::fmt;
|
|||
#[cfg(feature = "nightly")]
|
||||
use std::iter::Step;
|
||||
use std::num::{NonZeroUsize, ParseIntError};
|
||||
use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
|
||||
use std::ops::{Add, AddAssign, Deref, Mul, RangeFull, RangeInclusive, Sub};
|
||||
use std::str::FromStr;
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
|
@ -1391,12 +1391,45 @@ impl WrappingRange {
|
|||
}
|
||||
|
||||
/// Returns `true` if `size` completely fills the range.
|
||||
///
|
||||
/// Note that this is *not* the same as `self == WrappingRange::full(size)`.
|
||||
/// Niche calculations can produce full ranges which are not the canonical one;
|
||||
/// for example `Option<NonZero<u16>>` gets `valid_range: (..=0) | (1..)`.
|
||||
#[inline]
|
||||
fn is_full_for(&self, size: Size) -> bool {
|
||||
let max_value = size.unsigned_int_max();
|
||||
debug_assert!(self.start <= max_value && self.end <= max_value);
|
||||
self.start == (self.end.wrapping_add(1) & max_value)
|
||||
}
|
||||
|
||||
/// Checks whether this range is considered non-wrapping when the values are
|
||||
/// interpreted as *unsigned* numbers of width `size`.
|
||||
///
|
||||
/// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
|
||||
/// and `Err(..)` if the range is full so it depends how you think about it.
|
||||
#[inline]
|
||||
pub fn no_unsigned_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
|
||||
if self.is_full_for(size) { Err(..) } else { Ok(self.start <= self.end) }
|
||||
}
|
||||
|
||||
/// Checks whether this range is considered non-wrapping when the values are
|
||||
/// interpreted as *signed* numbers of width `size`.
|
||||
///
|
||||
/// This is heavily dependent on the `size`, as `100..=200` does wrap when
|
||||
/// interpreted as `i8`, but doesn't when interpreted as `i16`.
|
||||
///
|
||||
/// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
|
||||
/// and `Err(..)` if the range is full so it depends how you think about it.
|
||||
#[inline]
|
||||
pub fn no_signed_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
|
||||
if self.is_full_for(size) {
|
||||
Err(..)
|
||||
} else {
|
||||
let start: i128 = size.sign_extend(self.start);
|
||||
let end: i128 = size.sign_extend(self.end);
|
||||
Ok(start <= end)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for WrappingRange {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ edition = "2024"
|
|||
# tidy-alphabetical-start
|
||||
bitflags = "2.4.1"
|
||||
memchr = "2.7.4"
|
||||
rustc-literal-escaper = "0.0.4"
|
||||
rustc-literal-escaper = "0.0.5"
|
||||
rustc_ast_ir = { path = "../rustc_ast_ir" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -217,6 +217,10 @@ impl AttributeExt for Attribute {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_automatically_derived_attr(&self) -> bool {
|
||||
self.has_name(sym::automatically_derived)
|
||||
}
|
||||
}
|
||||
|
||||
impl Attribute {
|
||||
|
|
@ -810,6 +814,7 @@ pub trait AttributeExt: Debug {
|
|||
.iter()
|
||||
.any(|kind| self.has_name(*kind))
|
||||
}
|
||||
fn is_automatically_derived_attr(&self) -> bool;
|
||||
|
||||
/// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.
|
||||
/// * `///doc` returns `Some(("doc", CommentKind::Line))`.
|
||||
|
|
|
|||
|
|
@ -1,24 +1,7 @@
|
|||
//! Definitions shared by macros / syntax extensions and e.g. `rustc_middle`.
|
||||
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::Ident;
|
||||
use rustc_span::def_id::DefId;
|
||||
|
||||
use crate::MetaItem;
|
||||
|
||||
pub mod allocator;
|
||||
pub mod autodiff_attrs;
|
||||
pub mod typetree;
|
||||
|
||||
#[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct StrippedCfgItem<ModId = DefId> {
|
||||
pub parent_module: ModId,
|
||||
pub ident: Ident,
|
||||
pub cfg: MetaItem,
|
||||
}
|
||||
|
||||
impl<ModId> StrippedCfgItem<ModId> {
|
||||
pub fn map_mod_id<New>(self, f: impl FnOnce(ModId) -> New) -> StrippedCfgItem<New> {
|
||||
StrippedCfgItem { parent_module: f(self.parent_module), ident: self.ident, cfg: self.cfg }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
use rustc_macros::{Decodable, Encodable, Walkable};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
use crate::Expr;
|
||||
|
|
@ -41,7 +41,7 @@ use crate::token::LitKind;
|
|||
/// Basically the "AST" for a complete `format_args!()`.
|
||||
///
|
||||
/// E.g., `format_args!("hello {name}");`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub struct FormatArgs {
|
||||
pub span: Span,
|
||||
pub template: Vec<FormatArgsPiece>,
|
||||
|
|
@ -63,7 +63,7 @@ pub struct FormatArgs {
|
|||
/// A piece of a format template string.
|
||||
///
|
||||
/// E.g. "hello" or "{name}".
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub enum FormatArgsPiece {
|
||||
Literal(Symbol),
|
||||
Placeholder(FormatPlaceholder),
|
||||
|
|
@ -73,7 +73,7 @@ pub enum FormatArgsPiece {
|
|||
///
|
||||
/// E.g. `1, 2, name="ferris", n=3`,
|
||||
/// but also implicit captured arguments like `x` in `format_args!("{x}")`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub struct FormatArguments {
|
||||
arguments: Vec<FormatArgument>,
|
||||
num_unnamed_args: usize,
|
||||
|
|
@ -144,13 +144,13 @@ impl FormatArguments {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub struct FormatArgument {
|
||||
pub kind: FormatArgumentKind,
|
||||
pub expr: P<Expr>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub enum FormatArgumentKind {
|
||||
/// `format_args(…, arg)`
|
||||
Normal,
|
||||
|
|
@ -170,24 +170,28 @@ impl FormatArgumentKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]
|
||||
pub struct FormatPlaceholder {
|
||||
/// Index into [`FormatArgs::arguments`].
|
||||
pub argument: FormatArgPosition,
|
||||
/// The span inside the format string for the full `{…}` placeholder.
|
||||
pub span: Option<Span>,
|
||||
/// `{}`, `{:?}`, or `{:x}`, etc.
|
||||
#[visitable(ignore)]
|
||||
pub format_trait: FormatTrait,
|
||||
/// `{}` or `{:.5}` or `{:-^20}`, etc.
|
||||
#[visitable(ignore)]
|
||||
pub format_options: FormatOptions,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]
|
||||
pub struct FormatArgPosition {
|
||||
/// Which argument this position refers to (Ok),
|
||||
/// or would've referred to if it existed (Err).
|
||||
#[visitable(ignore)]
|
||||
pub index: Result<usize, usize>,
|
||||
/// What kind of position this is. See [`FormatArgPositionKind`].
|
||||
#[visitable(ignore)]
|
||||
pub kind: FormatArgPositionKind,
|
||||
/// The span of the name or number.
|
||||
pub span: Option<Span>,
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@ use std::panic;
|
|||
|
||||
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{Ident, Span};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::ast::*;
|
||||
use crate::ptr::P;
|
||||
use crate::tokenstream::*;
|
||||
use crate::visit::{AssocCtxt, BoundKind, FnCtxt, VisitorResult, try_visit, visit_opt, walk_list};
|
||||
use crate::visit::{AssocCtxt, BoundKind, FnCtxt, LifetimeCtxt, VisitorResult, try_visit};
|
||||
|
||||
mod sealed {
|
||||
use rustc_ast_ir::visit::VisitorResult;
|
||||
|
|
@ -36,11 +36,249 @@ mod sealed {
|
|||
|
||||
use sealed::MutVisitorResult;
|
||||
|
||||
pub(crate) trait MutVisitable<V: MutVisitor> {
|
||||
type Extra: Copy;
|
||||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra);
|
||||
}
|
||||
|
||||
impl<V: MutVisitor, T: ?Sized> MutVisitable<V> for P<T>
|
||||
where
|
||||
T: MutVisitable<V>,
|
||||
{
|
||||
type Extra = T::Extra;
|
||||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
|
||||
(**self).visit_mut(visitor, extra)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: MutVisitor, T> MutVisitable<V> for Option<T>
|
||||
where
|
||||
T: MutVisitable<V>,
|
||||
{
|
||||
type Extra = T::Extra;
|
||||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
|
||||
if let Some(this) = self {
|
||||
this.visit_mut(visitor, extra)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: MutVisitor, T> MutVisitable<V> for Spanned<T>
|
||||
where
|
||||
T: MutVisitable<V>,
|
||||
{
|
||||
type Extra = T::Extra;
|
||||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
|
||||
let Spanned { span, node } = self;
|
||||
span.visit_mut(visitor, ());
|
||||
node.visit_mut(visitor, extra);
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: MutVisitor, T> MutVisitable<V> for [T]
|
||||
where
|
||||
T: MutVisitable<V>,
|
||||
{
|
||||
type Extra = T::Extra;
|
||||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
|
||||
for item in self {
|
||||
item.visit_mut(visitor, extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: MutVisitor, T> MutVisitable<V> for Vec<T>
|
||||
where
|
||||
T: MutVisitable<V>,
|
||||
{
|
||||
type Extra = T::Extra;
|
||||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
|
||||
for item in self {
|
||||
item.visit_mut(visitor, extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: MutVisitor, T> MutVisitable<V> for (T,)
|
||||
where
|
||||
T: MutVisitable<V>,
|
||||
{
|
||||
type Extra = T::Extra;
|
||||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
|
||||
self.0.visit_mut(visitor, extra);
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: MutVisitor, T1, T2> MutVisitable<V> for (T1, T2)
|
||||
where
|
||||
T1: MutVisitable<V, Extra = ()>,
|
||||
T2: MutVisitable<V, Extra = ()>,
|
||||
{
|
||||
type Extra = ();
|
||||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
|
||||
self.0.visit_mut(visitor, extra);
|
||||
self.1.visit_mut(visitor, extra);
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: MutVisitor, T1, T2, T3> MutVisitable<V> for (T1, T2, T3)
|
||||
where
|
||||
T1: MutVisitable<V, Extra = ()>,
|
||||
T2: MutVisitable<V, Extra = ()>,
|
||||
T3: MutVisitable<V, Extra = ()>,
|
||||
{
|
||||
type Extra = ();
|
||||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
|
||||
self.0.visit_mut(visitor, extra);
|
||||
self.1.visit_mut(visitor, extra);
|
||||
self.2.visit_mut(visitor, extra);
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: MutVisitor, T1, T2, T3, T4> MutVisitable<V> for (T1, T2, T3, T4)
|
||||
where
|
||||
T1: MutVisitable<V, Extra = ()>,
|
||||
T2: MutVisitable<V, Extra = ()>,
|
||||
T3: MutVisitable<V, Extra = ()>,
|
||||
T4: MutVisitable<V, Extra = ()>,
|
||||
{
|
||||
type Extra = ();
|
||||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
|
||||
self.0.visit_mut(visitor, extra);
|
||||
self.1.visit_mut(visitor, extra);
|
||||
self.2.visit_mut(visitor, extra);
|
||||
self.3.visit_mut(visitor, extra);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MutWalkable<V: MutVisitor> {
|
||||
fn walk_mut(&mut self, visitor: &mut V);
|
||||
}
|
||||
|
||||
macro_rules! visit_visitable {
|
||||
(mut $visitor:expr, $($expr:expr),* $(,)?) => {{
|
||||
$(MutVisitable::visit_mut($expr, $visitor, ());)*
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! visit_visitable_with {
|
||||
(mut $visitor:expr, $expr:expr, $extra:expr $(,)?) => {
|
||||
MutVisitable::visit_mut($expr, $visitor, $extra)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! walk_walkable {
|
||||
($visitor:expr, $expr:expr, mut) => {
|
||||
MutWalkable::walk_mut($expr, $visitor)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_visitable {
|
||||
(|&mut $self:ident: $self_ty:ty,
|
||||
$vis:ident: &mut $vis_ty:ident,
|
||||
$extra:ident: $extra_ty:ty| $block:block) => {
|
||||
#[allow(unused_parens, non_local_definitions)]
|
||||
impl<$vis_ty: MutVisitor> MutVisitable<$vis_ty> for $self_ty {
|
||||
type Extra = $extra_ty;
|
||||
fn visit_mut(&mut $self, $vis: &mut $vis_ty, $extra: Self::Extra) -> V::Result {
|
||||
$block
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_walkable {
|
||||
($(<$K:ident: $Kb:ident>)? |&mut $self:ident: $self_ty:ty,
|
||||
$vis:ident: &mut $vis_ty:ident| $block:block) => {
|
||||
#[allow(unused_parens, non_local_definitions)]
|
||||
impl<$($K: $Kb,)? $vis_ty: MutVisitor> MutWalkable<$vis_ty> for $self_ty {
|
||||
fn walk_mut(&mut $self, $vis: &mut $vis_ty) -> V::Result {
|
||||
$block
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_visitable_noop {
|
||||
(<mut> $($ty:ty,)*) => {
|
||||
$(
|
||||
impl_visitable!(|&mut self: $ty, _vis: &mut V, _extra: ()| {});
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_visitable_list {
|
||||
(<mut> $($ty:ty,)*) => {
|
||||
$(impl<V: MutVisitor, T> MutVisitable<V> for $ty
|
||||
where
|
||||
for<'a> &'a mut $ty: IntoIterator<Item = &'a mut T>,
|
||||
T: MutVisitable<V>,
|
||||
{
|
||||
type Extra = <T as MutVisitable<V>>::Extra;
|
||||
|
||||
#[inline]
|
||||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
|
||||
for i in self {
|
||||
i.visit_mut(visitor, extra);
|
||||
}
|
||||
}
|
||||
})*
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_visitable_direct {
|
||||
(<mut> $($ty:ty,)*) => {
|
||||
$(impl_visitable!(
|
||||
|&mut self: $ty, visitor: &mut V, _extra: ()| {
|
||||
MutWalkable::walk_mut(self, visitor)
|
||||
}
|
||||
);)*
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_visitable_calling_walkable {
|
||||
(<mut>
|
||||
$( fn $method:ident($ty:ty $(, $extra_name:ident: $extra_ty:ty)?); )*
|
||||
) => {
|
||||
$(fn $method(&mut self, node: &mut $ty $(, $extra_name:$extra_ty)?) {
|
||||
impl_visitable!(|&mut self: $ty, visitor: &mut V, extra: ($($extra_ty)?)| {
|
||||
let ($($extra_name)?) = extra;
|
||||
visitor.$method(self $(, $extra_name)?);
|
||||
});
|
||||
walk_walkable!(self, node, mut)
|
||||
})*
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_named_walk {
|
||||
((mut) $Visitor:ident
|
||||
$( pub fn $method:ident($ty:ty); )*
|
||||
) => {
|
||||
$(pub fn $method<V: $Visitor>(visitor: &mut V, node: &mut $ty) {
|
||||
walk_walkable!(visitor, node, mut)
|
||||
})*
|
||||
};
|
||||
}
|
||||
|
||||
super::common_visitor_and_walkers!((mut) MutVisitor);
|
||||
|
||||
macro_rules! generate_flat_map_visitor_fns {
|
||||
($($name:ident, $Ty:ty, $flat_map_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => {
|
||||
$(
|
||||
#[allow(unused_parens)]
|
||||
impl<V: MutVisitor> MutVisitable<V> for ThinVec<$Ty> {
|
||||
type Extra = ($($ParamTy),*);
|
||||
|
||||
#[inline]
|
||||
fn visit_mut(
|
||||
&mut self,
|
||||
visitor: &mut V,
|
||||
($($param),*): Self::Extra,
|
||||
) -> V::Result {
|
||||
$name(visitor, self $(, $param)*)
|
||||
}
|
||||
}
|
||||
|
||||
fn $name<V: MutVisitor>(
|
||||
vis: &mut V,
|
||||
values: &mut ThinVec<$Ty>,
|
||||
|
|
@ -78,15 +316,6 @@ pub fn walk_flat_map_pat_field<T: MutVisitor>(
|
|||
smallvec![fp]
|
||||
}
|
||||
|
||||
fn visit_nested_use_tree<V: MutVisitor>(
|
||||
vis: &mut V,
|
||||
nested_tree: &mut UseTree,
|
||||
nested_id: &mut NodeId,
|
||||
) {
|
||||
vis.visit_id(nested_id);
|
||||
vis.visit_use_tree(nested_tree);
|
||||
}
|
||||
|
||||
macro_rules! generate_walk_flat_map_fns {
|
||||
($($fn_name:ident($Ty:ty$(,$extra_name:ident: $ExtraTy:ty)*) => $visit_fn_name:ident;)+) => {$(
|
||||
pub fn $fn_name<V: MutVisitor>(vis: &mut V, mut value: $Ty$(,$extra_name: $ExtraTy)*) -> SmallVec<[$Ty; 1]> {
|
||||
|
|
@ -109,14 +338,6 @@ generate_walk_flat_map_fns! {
|
|||
walk_flat_map_assoc_item(P<AssocItem>, ctxt: AssocCtxt) => visit_assoc_item;
|
||||
}
|
||||
|
||||
fn walk_ty_alias_where_clauses<T: MutVisitor>(vis: &mut T, tawcs: &mut TyAliasWhereClauses) {
|
||||
let TyAliasWhereClauses { before, after, split: _ } = tawcs;
|
||||
let TyAliasWhereClause { has_where_token: _, span: span_before } = before;
|
||||
let TyAliasWhereClause { has_where_token: _, span: span_after } = after;
|
||||
vis.visit_span(span_before);
|
||||
vis.visit_span(span_after);
|
||||
}
|
||||
|
||||
pub fn walk_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: P<Expr>) -> Option<P<Expr>> {
|
||||
vis.visit_expr(&mut e);
|
||||
Some(e)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use std::{cmp, fmt, iter, mem};
|
|||
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic, Walkable};
|
||||
use rustc_serialize::{Decodable, Encodable};
|
||||
use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym};
|
||||
use thin_vec::ThinVec;
|
||||
|
|
@ -977,7 +977,7 @@ impl TokenCursor {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic, Walkable)]
|
||||
pub struct DelimSpan {
|
||||
pub open: Span,
|
||||
pub close: Span,
|
||||
|
|
|
|||
|
|
@ -126,11 +126,11 @@ impl LitKind {
|
|||
token::CStr => {
|
||||
let s = symbol.as_str();
|
||||
let mut buf = Vec::with_capacity(s.len());
|
||||
unescape_c_str(s, |_span, c| match c {
|
||||
unescape_c_str(s, |_span, res| match res {
|
||||
Ok(MixedUnit::Char(c)) => {
|
||||
buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
|
||||
buf.extend_from_slice(c.get().encode_utf8(&mut [0; 4]).as_bytes())
|
||||
}
|
||||
Ok(MixedUnit::HighByte(b)) => buf.push(b),
|
||||
Ok(MixedUnit::HighByte(b)) => buf.push(b.get()),
|
||||
Err(err) => {
|
||||
assert!(!err.is_fatal(), "failed to unescape C string literal")
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -127,9 +127,6 @@ ast_lowering_misplaced_impl_trait =
|
|||
`impl Trait` is not allowed in {$position}
|
||||
.note = `impl Trait` is only allowed in arguments and return types of functions and methods
|
||||
|
||||
ast_lowering_misplaced_relax_trait_bound =
|
||||
`?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||
|
||||
ast_lowering_never_pattern_with_body =
|
||||
a never pattern is always unreachable
|
||||
.label = this will never be executed
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ use rustc_errors::ErrorGuaranteed;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
|
|
@ -61,21 +62,6 @@ pub(crate) struct DelegationResults<'hir> {
|
|||
}
|
||||
|
||||
impl<'hir> LoweringContext<'_, 'hir> {
|
||||
/// Defines whether the delegatee is an associated function whose first parameter is `self`.
|
||||
pub(crate) fn delegatee_is_method(
|
||||
&self,
|
||||
item_id: NodeId,
|
||||
path_id: NodeId,
|
||||
span: Span,
|
||||
is_in_trait_impl: bool,
|
||||
) -> bool {
|
||||
let sig_id = self.get_delegation_sig_id(item_id, path_id, span, is_in_trait_impl);
|
||||
let Ok(sig_id) = sig_id else {
|
||||
return false;
|
||||
};
|
||||
self.is_method(sig_id, span)
|
||||
}
|
||||
|
||||
fn is_method(&self, def_id: DefId, span: Span) -> bool {
|
||||
match self.tcx.def_kind(def_id) {
|
||||
DefKind::Fn => false,
|
||||
|
|
@ -101,10 +87,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl);
|
||||
match sig_id {
|
||||
Ok(sig_id) => {
|
||||
let is_method = self.is_method(sig_id, span);
|
||||
let (param_count, c_variadic) = self.param_count(sig_id);
|
||||
let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
|
||||
let sig = self.lower_delegation_sig(sig_id, decl, span);
|
||||
let body_id = self.lower_delegation_body(delegation, param_count, span);
|
||||
let body_id = self.lower_delegation_body(delegation, is_method, param_count, span);
|
||||
let ident = self.lower_ident(delegation.ident);
|
||||
let generics = self.lower_delegation_generics(span);
|
||||
DelegationResults { body_id, sig, ident, generics }
|
||||
|
|
@ -234,10 +221,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
hir::FnSig { decl, header, span }
|
||||
}
|
||||
|
||||
fn generate_param(&mut self, idx: usize, span: Span) -> (hir::Param<'hir>, NodeId) {
|
||||
fn generate_param(
|
||||
&mut self,
|
||||
is_method: bool,
|
||||
idx: usize,
|
||||
span: Span,
|
||||
) -> (hir::Param<'hir>, NodeId) {
|
||||
let pat_node_id = self.next_node_id();
|
||||
let pat_id = self.lower_node_id(pat_node_id);
|
||||
let ident = Ident::with_dummy_span(Symbol::intern(&format!("arg{idx}")));
|
||||
// FIXME(cjgillot) AssocItem currently relies on self parameter being exactly named `self`.
|
||||
let name = if is_method && idx == 0 {
|
||||
kw::SelfLower
|
||||
} else {
|
||||
Symbol::intern(&format!("arg{idx}"))
|
||||
};
|
||||
let ident = Ident::with_dummy_span(name);
|
||||
let pat = self.arena.alloc(hir::Pat {
|
||||
hir_id: pat_id,
|
||||
kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, ident, None),
|
||||
|
|
@ -248,9 +246,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
(hir::Param { hir_id: self.next_id(), pat, ty_span: span, span }, pat_node_id)
|
||||
}
|
||||
|
||||
fn generate_arg(&mut self, idx: usize, param_id: HirId, span: Span) -> hir::Expr<'hir> {
|
||||
fn generate_arg(
|
||||
&mut self,
|
||||
is_method: bool,
|
||||
idx: usize,
|
||||
param_id: HirId,
|
||||
span: Span,
|
||||
) -> hir::Expr<'hir> {
|
||||
// FIXME(cjgillot) AssocItem currently relies on self parameter being exactly named `self`.
|
||||
let name = if is_method && idx == 0 {
|
||||
kw::SelfLower
|
||||
} else {
|
||||
Symbol::intern(&format!("arg{idx}"))
|
||||
};
|
||||
let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
|
||||
ident: Ident::with_dummy_span(Symbol::intern(&format!("arg{idx}"))),
|
||||
ident: Ident::with_dummy_span(name),
|
||||
hir_id: self.next_id(),
|
||||
res: Res::Local(param_id),
|
||||
args: None,
|
||||
|
|
@ -264,6 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
fn lower_delegation_body(
|
||||
&mut self,
|
||||
delegation: &Delegation,
|
||||
is_method: bool,
|
||||
param_count: usize,
|
||||
span: Span,
|
||||
) -> BodyId {
|
||||
|
|
@ -274,7 +285,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let mut args: Vec<hir::Expr<'_>> = Vec::with_capacity(param_count);
|
||||
|
||||
for idx in 0..param_count {
|
||||
let (param, pat_node_id) = this.generate_param(idx, span);
|
||||
let (param, pat_node_id) = this.generate_param(is_method, idx, span);
|
||||
parameters.push(param);
|
||||
|
||||
let arg = if let Some(block) = block
|
||||
|
|
@ -290,7 +301,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
this.ident_and_label_to_local_id.insert(pat_node_id, param.pat.hir_id.local_id);
|
||||
this.lower_target_expr(&block)
|
||||
} else {
|
||||
this.generate_arg(idx, param.pat.hir_id, span)
|
||||
this.generate_arg(is_method, idx, param.pat.hir_id, span)
|
||||
};
|
||||
args.push(arg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -324,13 +324,6 @@ pub(crate) struct MisplacedDoubleDot {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering_misplaced_relax_trait_bound)]
|
||||
pub(crate) struct MisplacedRelaxTraitBound {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering_match_arm_with_no_body)]
|
||||
pub(crate) struct MatchArmWithNoBody {
|
||||
|
|
|
|||
|
|
@ -528,7 +528,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
then: &Block,
|
||||
else_opt: Option<&Expr>,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let lowered_cond = self.lower_cond(cond);
|
||||
let lowered_cond = self.lower_expr(cond);
|
||||
let then_expr = self.lower_block_expr(then);
|
||||
if let Some(rslt) = else_opt {
|
||||
hir::ExprKind::If(
|
||||
|
|
@ -541,44 +541,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
// Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope
|
||||
// so that temporaries created in the condition don't live beyond it.
|
||||
fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> {
|
||||
fn has_let_expr(expr: &Expr) -> bool {
|
||||
match &expr.kind {
|
||||
ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
|
||||
ExprKind::Let(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// We have to take special care for `let` exprs in the condition, e.g. in
|
||||
// `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
|
||||
// condition in this case.
|
||||
//
|
||||
// In order to maintain the drop behavior for the non `let` parts of the condition,
|
||||
// we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
|
||||
// gets transformed into `if { let _t = foo; _t } && let pat = val`
|
||||
match &cond.kind {
|
||||
ExprKind::Binary(op @ Spanned { node: ast::BinOpKind::And, .. }, lhs, rhs)
|
||||
if has_let_expr(cond) =>
|
||||
{
|
||||
let op = self.lower_binop(*op);
|
||||
let lhs = self.lower_cond(lhs);
|
||||
let rhs = self.lower_cond(rhs);
|
||||
|
||||
self.arena.alloc(self.expr(cond.span, hir::ExprKind::Binary(op, lhs, rhs)))
|
||||
}
|
||||
ExprKind::Let(..) => self.lower_expr(cond),
|
||||
_ => {
|
||||
let cond = self.lower_expr(cond);
|
||||
let reason = DesugaringKind::CondTemporary;
|
||||
let span_block = self.mark_span_with_reason(reason, cond.span, None);
|
||||
self.expr_drop_temps(span_block, cond)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We desugar: `'label: while $cond $body` into:
|
||||
//
|
||||
// ```
|
||||
|
|
@ -602,7 +564,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
body: &Block,
|
||||
opt_label: Option<Label>,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
|
||||
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
|
||||
let then = self.lower_block_expr(body);
|
||||
let expr_break = self.expr_break(span);
|
||||
let stmt_break = self.stmt_expr(span, expr_break);
|
||||
|
|
@ -2091,7 +2053,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
/// In terms of drop order, it has the same effect as wrapping `expr` in
|
||||
/// `{ let _t = $expr; _t }` but should provide better compile-time performance.
|
||||
///
|
||||
/// The drop order can be important in e.g. `if expr { .. }`.
|
||||
/// The drop order can be important, e.g. to drop temporaries from an `async fn`
|
||||
/// body before its parameters.
|
||||
pub(super) fn expr_drop_temps(
|
||||
&mut self,
|
||||
span: Span,
|
||||
|
|
|
|||
|
|
@ -381,28 +381,16 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
})
|
||||
}
|
||||
|
||||
fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) {
|
||||
// Do not visit the duplicate information in TraitItemRef. We want to
|
||||
// map the actual nodes, not the duplicate ones in the *Ref.
|
||||
let TraitItemRef { id, ident: _, kind: _, span: _ } = *ii;
|
||||
|
||||
self.visit_nested_trait_item(id);
|
||||
fn visit_trait_item_ref(&mut self, id: &'hir TraitItemId) {
|
||||
self.visit_nested_trait_item(*id);
|
||||
}
|
||||
|
||||
fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) {
|
||||
// Do not visit the duplicate information in ImplItemRef. We want to
|
||||
// map the actual nodes, not the duplicate ones in the *Ref.
|
||||
let ImplItemRef { id, ident: _, kind: _, span: _, trait_item_def_id: _ } = *ii;
|
||||
|
||||
self.visit_nested_impl_item(id);
|
||||
fn visit_impl_item_ref(&mut self, id: &'hir ImplItemId) {
|
||||
self.visit_nested_impl_item(*id);
|
||||
}
|
||||
|
||||
fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef) {
|
||||
// Do not visit the duplicate information in ForeignItemRef. We want to
|
||||
// map the actual nodes, not the duplicate ones in the *Ref.
|
||||
let ForeignItemRef { id, ident: _, span: _ } = *fi;
|
||||
|
||||
self.visit_nested_foreign_item(id);
|
||||
fn visit_foreign_item_ref(&mut self, id: &'hir ForeignItemId) {
|
||||
self.visit_nested_foreign_item(*id);
|
||||
}
|
||||
|
||||
fn visit_where_predicate(&mut self, predicate: &'hir WherePredicate<'hir>) {
|
||||
|
|
|
|||
|
|
@ -16,14 +16,11 @@ use smallvec::{SmallVec, smallvec};
|
|||
use thin_vec::ThinVec;
|
||||
use tracing::instrument;
|
||||
|
||||
use super::errors::{
|
||||
InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound, TupleStructWithDefault,
|
||||
UnionWithDefault,
|
||||
};
|
||||
use super::errors::{InvalidAbi, InvalidAbiSuggestion, TupleStructWithDefault, UnionWithDefault};
|
||||
use super::stability::{enabled_names, gate_unstable_abi};
|
||||
use super::{
|
||||
AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
|
||||
ResolverAstLoweringExt,
|
||||
RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,
|
||||
};
|
||||
|
||||
pub(super) struct ItemLowerer<'a, 'hir> {
|
||||
|
|
@ -393,11 +390,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
(trait_ref, lowered_ty)
|
||||
});
|
||||
|
||||
let new_impl_items = self.arena.alloc_from_iter(
|
||||
impl_items
|
||||
.iter()
|
||||
.map(|item| self.lower_impl_item_ref(item, trait_ref.is_some())),
|
||||
);
|
||||
let new_impl_items = self
|
||||
.arena
|
||||
.alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
|
||||
|
||||
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
|
||||
// to not cause an assertion failure inside the `lower_defaultness` function.
|
||||
|
|
@ -419,7 +414,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
items: new_impl_items,
|
||||
}))
|
||||
}
|
||||
ItemKind::Trait(box Trait { is_auto, safety, ident, generics, bounds, items }) => {
|
||||
ItemKind::Trait(box Trait {
|
||||
constness,
|
||||
is_auto,
|
||||
safety,
|
||||
ident,
|
||||
generics,
|
||||
bounds,
|
||||
items,
|
||||
}) => {
|
||||
let constness = self.lower_constness(*constness);
|
||||
let ident = self.lower_ident(*ident);
|
||||
let (generics, (safety, items, bounds)) = self.lower_generics(
|
||||
generics,
|
||||
|
|
@ -428,6 +432,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|this| {
|
||||
let bounds = this.lower_param_bounds(
|
||||
bounds,
|
||||
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::SuperTrait),
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
);
|
||||
let items = this.arena.alloc_from_iter(
|
||||
|
|
@ -437,7 +442,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
(safety, items, bounds)
|
||||
},
|
||||
);
|
||||
hir::ItemKind::Trait(*is_auto, safety, ident, generics, bounds, items)
|
||||
hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items)
|
||||
}
|
||||
ItemKind::TraitAlias(ident, generics, bounds) => {
|
||||
let ident = self.lower_ident(*ident);
|
||||
|
|
@ -448,6 +453,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|this| {
|
||||
this.lower_param_bounds(
|
||||
bounds,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
)
|
||||
},
|
||||
|
|
@ -706,14 +712,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.arena.alloc(item)
|
||||
}
|
||||
|
||||
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
|
||||
hir::ForeignItemRef {
|
||||
id: hir::ForeignItemId { owner_id: self.owner_id(i.id) },
|
||||
// `unwrap` is safe because `ForeignItemKind::MacCall` is the only foreign item kind
|
||||
// without an identifier and it cannot reach here.
|
||||
ident: self.lower_ident(i.kind.ident().unwrap()),
|
||||
span: self.lower_span(i.span),
|
||||
}
|
||||
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemId {
|
||||
hir::ForeignItemId { owner_id: self.owner_id(i.id) }
|
||||
}
|
||||
|
||||
fn lower_variant(&mut self, item_kind: &ItemKind, v: &Variant) -> hir::Variant<'hir> {
|
||||
|
|
@ -939,6 +939,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
hir::TraitItemKind::Type(
|
||||
this.lower_param_bounds(
|
||||
bounds,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
),
|
||||
ty,
|
||||
|
|
@ -972,32 +973,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.arena.alloc(item)
|
||||
}
|
||||
|
||||
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
|
||||
let (ident, kind) = match &i.kind {
|
||||
AssocItemKind::Const(box ConstItem { ident, .. }) => {
|
||||
(*ident, hir::AssocItemKind::Const)
|
||||
}
|
||||
AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, hir::AssocItemKind::Type),
|
||||
AssocItemKind::Fn(box Fn { ident, sig, .. }) => {
|
||||
(*ident, hir::AssocItemKind::Fn { has_self: sig.decl.has_self() })
|
||||
}
|
||||
AssocItemKind::Delegation(box delegation) => (
|
||||
delegation.ident,
|
||||
hir::AssocItemKind::Fn {
|
||||
has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false),
|
||||
},
|
||||
),
|
||||
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
||||
panic!("macros should have been expanded by now")
|
||||
}
|
||||
};
|
||||
let id = hir::TraitItemId { owner_id: self.owner_id(i.id) };
|
||||
hir::TraitItemRef {
|
||||
id,
|
||||
ident: self.lower_ident(ident),
|
||||
span: self.lower_span(i.span),
|
||||
kind,
|
||||
}
|
||||
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemId {
|
||||
hir::TraitItemId { owner_id: self.owner_id(i.id) }
|
||||
}
|
||||
|
||||
/// Construct `ExprKind::Err` for the given `span`.
|
||||
|
|
@ -1128,41 +1105,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
span: self.lower_span(i.span),
|
||||
defaultness,
|
||||
has_delayed_lints: !self.delayed_lints.is_empty(),
|
||||
};
|
||||
self.arena.alloc(item)
|
||||
}
|
||||
|
||||
fn lower_impl_item_ref(&mut self, i: &AssocItem, is_in_trait_impl: bool) -> hir::ImplItemRef {
|
||||
hir::ImplItemRef {
|
||||
id: hir::ImplItemId { owner_id: self.owner_id(i.id) },
|
||||
// `unwrap` is safe because `AssocItemKind::{MacCall,DelegationMac}` are the only
|
||||
// assoc item kinds without an identifier and they cannot reach here.
|
||||
ident: self.lower_ident(i.kind.ident().unwrap()),
|
||||
span: self.lower_span(i.span),
|
||||
kind: match &i.kind {
|
||||
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
|
||||
AssocItemKind::Type(..) => hir::AssocItemKind::Type,
|
||||
AssocItemKind::Fn(box Fn { sig, .. }) => {
|
||||
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
|
||||
}
|
||||
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
|
||||
has_self: self.delegatee_is_method(
|
||||
i.id,
|
||||
delegation.id,
|
||||
i.span,
|
||||
is_in_trait_impl,
|
||||
),
|
||||
},
|
||||
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
||||
panic!("macros should have been expanded by now")
|
||||
}
|
||||
},
|
||||
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)
|
||||
}
|
||||
|
||||
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemId {
|
||||
hir::ImplItemId { owner_id: self.owner_id(i.id) }
|
||||
}
|
||||
|
||||
fn lower_defaultness(
|
||||
|
|
@ -1724,61 +1677,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
assert!(self.impl_trait_defs.is_empty());
|
||||
assert!(self.impl_trait_bounds.is_empty());
|
||||
|
||||
// Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
|
||||
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
|
||||
// these into hir when we lower thee where clauses), but this makes it quite difficult to
|
||||
// keep track of the Span info. Now, `<dyn HirTyLowerer>::add_implicit_sized_bound`
|
||||
// checks both param bounds and where clauses for `?Sized`.
|
||||
for pred in &generics.where_clause.predicates {
|
||||
let WherePredicateKind::BoundPredicate(bound_pred) = &pred.kind else {
|
||||
continue;
|
||||
};
|
||||
let compute_is_param = || {
|
||||
// Check if the where clause type is a plain type parameter.
|
||||
match self
|
||||
.resolver
|
||||
.get_partial_res(bound_pred.bounded_ty.id)
|
||||
.and_then(|r| r.full_res())
|
||||
{
|
||||
Some(Res::Def(DefKind::TyParam, def_id))
|
||||
if bound_pred.bound_generic_params.is_empty() =>
|
||||
{
|
||||
generics
|
||||
.params
|
||||
.iter()
|
||||
.any(|p| def_id == self.local_def_id(p.id).to_def_id())
|
||||
}
|
||||
// Either the `bounded_ty` is not a plain type parameter, or
|
||||
// it's not found in the generic type parameters list.
|
||||
_ => false,
|
||||
}
|
||||
};
|
||||
// We only need to compute this once per `WherePredicate`, but don't
|
||||
// need to compute this at all unless there is a Maybe bound.
|
||||
let mut is_param: Option<bool> = None;
|
||||
for bound in &bound_pred.bounds {
|
||||
if !matches!(
|
||||
*bound,
|
||||
GenericBound::Trait(PolyTraitRef {
|
||||
modifiers: TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. },
|
||||
..
|
||||
})
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
||||
if !is_param && !self.tcx.features().more_maybe_bounds() {
|
||||
self.tcx
|
||||
.sess
|
||||
.create_feature_err(
|
||||
MisplacedRelaxTraitBound { span: bound.span() },
|
||||
sym::more_maybe_bounds,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
|
||||
predicates.extend(generics.params.iter().filter_map(|param| {
|
||||
self.lower_generic_bound_predicate(
|
||||
|
|
@ -1788,6 +1686,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
¶m.bounds,
|
||||
param.colon_span,
|
||||
generics.span,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
itctx,
|
||||
PredicateOrigin::GenericParam,
|
||||
)
|
||||
|
|
@ -1797,7 +1696,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
.where_clause
|
||||
.predicates
|
||||
.iter()
|
||||
.map(|predicate| self.lower_where_predicate(predicate)),
|
||||
.map(|predicate| self.lower_where_predicate(predicate, &generics.params)),
|
||||
);
|
||||
|
||||
let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
|
||||
|
|
@ -1874,6 +1773,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
bounds: &[GenericBound],
|
||||
colon_span: Option<Span>,
|
||||
parent_span: Span,
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
itctx: ImplTraitContext,
|
||||
origin: PredicateOrigin,
|
||||
) -> Option<hir::WherePredicate<'hir>> {
|
||||
|
|
@ -1882,7 +1782,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let bounds = self.lower_param_bounds(bounds, itctx);
|
||||
let bounds = self.lower_param_bounds(bounds, rbp, itctx);
|
||||
|
||||
let param_span = ident.span;
|
||||
|
||||
|
|
@ -1934,7 +1834,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
Some(hir::WherePredicate { hir_id, span, kind })
|
||||
}
|
||||
|
||||
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
|
||||
fn lower_where_predicate(
|
||||
&mut self,
|
||||
pred: &WherePredicate,
|
||||
params: &[ast::GenericParam],
|
||||
) -> hir::WherePredicate<'hir> {
|
||||
let hir_id = self.lower_node_id(pred.id);
|
||||
let span = self.lower_span(pred.span);
|
||||
self.lower_attrs(hir_id, &pred.attrs, span);
|
||||
|
|
@ -1943,17 +1847,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
bound_generic_params,
|
||||
bounded_ty,
|
||||
bounds,
|
||||
}) => hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
|
||||
bound_generic_params: self
|
||||
.lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
|
||||
bounded_ty: self
|
||||
.lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
|
||||
bounds: self.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
),
|
||||
origin: PredicateOrigin::WhereClause,
|
||||
}),
|
||||
}) => {
|
||||
let rbp = if bound_generic_params.is_empty() {
|
||||
RelaxedBoundPolicy::AllowedIfOnTyParam(bounded_ty.id, params)
|
||||
} else {
|
||||
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::LateBoundVarsInScope)
|
||||
};
|
||||
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
|
||||
bound_generic_params: self.lower_generic_params(
|
||||
bound_generic_params,
|
||||
hir::GenericParamSource::Binder,
|
||||
),
|
||||
bounded_ty: self.lower_ty(
|
||||
bounded_ty,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
),
|
||||
bounds: self.lower_param_bounds(
|
||||
bounds,
|
||||
rbp,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
),
|
||||
origin: PredicateOrigin::WhereClause,
|
||||
})
|
||||
}
|
||||
WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
|
||||
hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
|
||||
lifetime: self.lower_lifetime(
|
||||
|
|
@ -1963,6 +1879,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
),
|
||||
bounds: self.lower_param_bounds(
|
||||
bounds,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
),
|
||||
in_where_clause: true,
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ use std::sync::Arc;
|
|||
|
||||
use rustc_ast::node_id::NodeMap;
|
||||
use rustc_ast::{self as ast, *};
|
||||
use rustc_attr_parsing::{AttributeParser, OmitDoc};
|
||||
use rustc_attr_parsing::{AttributeParser, Late, OmitDoc};
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
|
|
@ -53,8 +53,8 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
|||
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::lints::DelayedLint;
|
||||
use rustc_hir::{
|
||||
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem,
|
||||
LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate,
|
||||
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
|
||||
LifetimeSyntax, ParamName, TraitCandidate,
|
||||
};
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_macros::extension;
|
||||
|
|
@ -192,7 +192,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// interact with `gen`/`async gen` blocks
|
||||
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
|
||||
|
||||
attribute_parser: AttributeParser::new(tcx.sess, tcx.features(), registered_tools),
|
||||
attribute_parser: AttributeParser::new(
|
||||
tcx.sess,
|
||||
tcx.features(),
|
||||
registered_tools,
|
||||
Late,
|
||||
),
|
||||
delayed_lints: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
|
@ -276,6 +281,24 @@ impl ResolverAstLowering {
|
|||
}
|
||||
}
|
||||
|
||||
/// How relaxed bounds `?Trait` should be treated.
|
||||
///
|
||||
/// Relaxed bounds should only be allowed in places where we later
|
||||
/// (namely during HIR ty lowering) perform *sized elaboration*.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum RelaxedBoundPolicy<'a> {
|
||||
Allowed,
|
||||
AllowedIfOnTyParam(NodeId, &'a [ast::GenericParam]),
|
||||
Forbidden(RelaxedBoundForbiddenReason),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum RelaxedBoundForbiddenReason {
|
||||
TraitObjectTy,
|
||||
SuperTrait,
|
||||
LateBoundVarsInScope,
|
||||
}
|
||||
|
||||
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
|
||||
/// and if so, what meaning it has.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
|
|
@ -851,25 +874,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
/// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id
|
||||
/// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime
|
||||
/// parameters will be successful.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
#[inline]
|
||||
fn lower_lifetime_binder(
|
||||
&mut self,
|
||||
binder: NodeId,
|
||||
generic_params: &[GenericParam],
|
||||
) -> &'hir [hir::GenericParam<'hir>] {
|
||||
let mut generic_params: Vec<_> = self
|
||||
.lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder)
|
||||
.collect();
|
||||
// Start by creating params for extra lifetimes params, as this creates the definitions
|
||||
// that may be referred to by the AST inside `generic_params`.
|
||||
let extra_lifetimes = self.resolver.extra_lifetime_params(binder);
|
||||
debug!(?extra_lifetimes);
|
||||
generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
|
||||
self.lifetime_res_to_generic_param(ident, node_id, res, hir::GenericParamSource::Binder)
|
||||
}));
|
||||
let generic_params = self.arena.alloc_from_iter(generic_params);
|
||||
debug!(?generic_params);
|
||||
|
||||
generic_params
|
||||
let extra_lifetimes: Vec<_> = extra_lifetimes
|
||||
.into_iter()
|
||||
.filter_map(|(ident, node_id, res)| {
|
||||
self.lifetime_res_to_generic_param(
|
||||
ident,
|
||||
node_id,
|
||||
res,
|
||||
hir::GenericParamSource::Binder,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let arena = self.arena;
|
||||
let explicit_generic_params =
|
||||
self.lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder);
|
||||
arena.alloc_from_iter(explicit_generic_params.chain(extra_lifetimes.into_iter()))
|
||||
}
|
||||
|
||||
fn with_dyn_type_scope<T>(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T {
|
||||
|
|
@ -1079,10 +1109,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
|
||||
hir::AssocItemConstraintKind::Equality { term: err_ty.into() }
|
||||
} else {
|
||||
// Desugar `AssocTy: Bounds` into an assoc type binding where the
|
||||
// later desugars into a trait predicate.
|
||||
let bounds = self.lower_param_bounds(bounds, itctx);
|
||||
|
||||
// FIXME(#135229): These should be forbidden!
|
||||
let bounds =
|
||||
self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx);
|
||||
hir::AssocItemConstraintKind::Bound { bounds }
|
||||
}
|
||||
}
|
||||
|
|
@ -1211,6 +1240,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
span: t.span,
|
||||
parens: ast::Parens::No,
|
||||
},
|
||||
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitObjectTy),
|
||||
itctx,
|
||||
);
|
||||
let bounds = this.arena.alloc_from_iter([bound]);
|
||||
|
|
@ -1266,7 +1296,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
parenthesized: hir::GenericArgsParentheses::No,
|
||||
span_ext: span,
|
||||
});
|
||||
let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args));
|
||||
let path = self.make_lang_item_qpath(hir::LangItem::Pin, span, Some(args));
|
||||
hir::TyKind::Path(path)
|
||||
}
|
||||
TyKind::FnPtr(f) => {
|
||||
|
|
@ -1327,7 +1357,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// takes care of rejecting invalid modifier combinations and
|
||||
// const trait bounds in trait object types.
|
||||
GenericBound::Trait(ty) => {
|
||||
let trait_ref = this.lower_poly_trait_ref(ty, itctx);
|
||||
let trait_ref = this.lower_poly_trait_ref(
|
||||
ty,
|
||||
RelaxedBoundPolicy::Forbidden(
|
||||
RelaxedBoundForbiddenReason::TraitObjectTy,
|
||||
),
|
||||
itctx,
|
||||
);
|
||||
Some(trait_ref)
|
||||
}
|
||||
GenericBound::Outlives(lifetime) => {
|
||||
|
|
@ -1382,9 +1418,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
path
|
||||
}
|
||||
ImplTraitContext::InBinding => {
|
||||
hir::TyKind::TraitAscription(self.lower_param_bounds(bounds, itctx))
|
||||
}
|
||||
ImplTraitContext::InBinding => hir::TyKind::TraitAscription(
|
||||
self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx),
|
||||
),
|
||||
ImplTraitContext::FeatureGated(position, feature) => {
|
||||
let guar = self
|
||||
.tcx
|
||||
|
|
@ -1500,7 +1536,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
|
||||
|
||||
self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| {
|
||||
this.lower_param_bounds(bounds, itctx)
|
||||
this.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1794,10 +1830,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_param_bound(
|
||||
&mut self,
|
||||
tpb: &GenericBound,
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::GenericBound<'hir> {
|
||||
match tpb {
|
||||
GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)),
|
||||
GenericBound::Trait(p) => {
|
||||
hir::GenericBound::Trait(self.lower_poly_trait_ref(p, rbp, itctx))
|
||||
}
|
||||
GenericBound::Outlives(lifetime) => hir::GenericBound::Outlives(self.lower_lifetime(
|
||||
lifetime,
|
||||
LifetimeSource::OutlivesBound,
|
||||
|
|
@ -2012,21 +2051,93 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_poly_trait_ref(
|
||||
&mut self,
|
||||
p: &PolyTraitRef,
|
||||
PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, parens: _ }: &PolyTraitRef,
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::PolyTraitRef<'hir> {
|
||||
let bound_generic_params =
|
||||
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
|
||||
let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx);
|
||||
let modifiers = self.lower_trait_bound_modifiers(p.modifiers);
|
||||
self.lower_lifetime_binder(trait_ref.ref_id, bound_generic_params);
|
||||
let trait_ref = self.lower_trait_ref(*modifiers, trait_ref, itctx);
|
||||
let modifiers = self.lower_trait_bound_modifiers(*modifiers);
|
||||
|
||||
if let ast::BoundPolarity::Maybe(_) = modifiers.polarity {
|
||||
self.validate_relaxed_bound(trait_ref, *span, rbp);
|
||||
}
|
||||
|
||||
hir::PolyTraitRef {
|
||||
bound_generic_params,
|
||||
modifiers,
|
||||
trait_ref,
|
||||
span: self.lower_span(p.span),
|
||||
span: self.lower_span(*span),
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_relaxed_bound(
|
||||
&self,
|
||||
trait_ref: hir::TraitRef<'_>,
|
||||
span: Span,
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
) {
|
||||
// Even though feature `more_maybe_bounds` bypasses the given policy and (currently) enables
|
||||
// relaxed bounds in every conceivable position[^1], we don't want to advertise it to the user
|
||||
// (via a feature gate) since it's super internal. Besides this, it'd be quite distracting.
|
||||
//
|
||||
// [^1]: Strictly speaking, this is incorrect (at the very least for `Sized`) because it's
|
||||
// no longer fully consistent with default trait elaboration in HIR ty lowering.
|
||||
|
||||
match rbp {
|
||||
RelaxedBoundPolicy::Allowed => return,
|
||||
RelaxedBoundPolicy::AllowedIfOnTyParam(id, params) => {
|
||||
if let Some(res) = self.resolver.get_partial_res(id).and_then(|r| r.full_res())
|
||||
&& let Res::Def(DefKind::TyParam, def_id) = res
|
||||
&& params.iter().any(|p| def_id == self.local_def_id(p.id).to_def_id())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
RelaxedBoundPolicy::Forbidden(reason) => {
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
|
||||
match reason {
|
||||
RelaxedBoundForbiddenReason::TraitObjectTy => {
|
||||
self.dcx().span_err(
|
||||
span,
|
||||
"relaxed bounds are not permitted in trait object types",
|
||||
);
|
||||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::SuperTrait => {
|
||||
let mut diag = self.dcx().struct_span_err(
|
||||
span,
|
||||
"relaxed bounds are not permitted in supertrait bounds",
|
||||
);
|
||||
if let Some(def_id) = trait_ref.trait_def_id()
|
||||
&& self.tcx.is_lang_item(def_id, hir::LangItem::Sized)
|
||||
{
|
||||
diag.note("traits are `?Sized` by default");
|
||||
}
|
||||
diag.emit();
|
||||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::LateBoundVarsInScope => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
self.dcx()
|
||||
.struct_span_err(span, "this relaxed bound is not permitted here")
|
||||
.with_note(
|
||||
"in this context, relaxed bounds are only allowed on \
|
||||
type parameters defined by the closest item",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
|
||||
hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl }
|
||||
}
|
||||
|
|
@ -2035,17 +2146,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_param_bounds(
|
||||
&mut self,
|
||||
bounds: &[GenericBound],
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::GenericBounds<'hir> {
|
||||
self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
|
||||
self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, rbp, itctx))
|
||||
}
|
||||
|
||||
fn lower_param_bounds_mut(
|
||||
&mut self,
|
||||
bounds: &[GenericBound],
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> impl Iterator<Item = hir::GenericBound<'hir>> {
|
||||
bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx))
|
||||
bounds.iter().map(move |bound| self.lower_param_bound(bound, rbp, itctx))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
|
|
@ -2079,6 +2192,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
bounds,
|
||||
/* colon_span */ None,
|
||||
span,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
ImplTraitContext::Universal,
|
||||
hir::PredicateOrigin::ImplTrait,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -212,11 +212,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
|
|||
ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
|
||||
.help = use `auto trait Trait {"{}"}` instead
|
||||
|
||||
ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
|
||||
|
||||
ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
|
||||
.note = traits are `?{$path_str}` by default
|
||||
|
||||
ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
|
||||
.suggestion = reorder the parameters: lifetimes, then consts and types
|
||||
|
||||
|
|
@ -240,10 +235,10 @@ ast_passes_static_without_body =
|
|||
ast_passes_tilde_const_disallowed = `[const]` is not allowed here
|
||||
.closure = closures cannot have `[const]` trait bounds
|
||||
.function = this function is not `const`, so it cannot have `[const]` trait bounds
|
||||
.trait = this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds
|
||||
.trait = this trait is not `const`, so it cannot have `[const]` trait bounds
|
||||
.trait_impl = this impl is not `const`, so it cannot have `[const]` trait bounds
|
||||
.impl = inherent impls cannot have `[const]` trait bounds
|
||||
.trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `[const]` trait bounds
|
||||
.trait_assoc_ty = associated types in non-`const` traits cannot have `[const]` trait bounds
|
||||
.trait_impl_assoc_ty = associated types in non-const impls cannot have `[const]` trait bounds
|
||||
.inherent_assoc_ty = inherent associated types cannot have `[const]` trait bounds
|
||||
.object = trait objects cannot have `[const]` trait bounds
|
||||
|
|
|
|||
|
|
@ -49,14 +49,14 @@ enum SelfSemantic {
|
|||
}
|
||||
|
||||
enum TraitOrTraitImpl {
|
||||
Trait { span: Span, constness_span: Option<Span> },
|
||||
Trait { span: Span, constness: Const },
|
||||
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span },
|
||||
}
|
||||
|
||||
impl TraitOrTraitImpl {
|
||||
fn constness(&self) -> Option<Span> {
|
||||
match self {
|
||||
Self::Trait { constness_span: Some(span), .. }
|
||||
Self::Trait { constness: Const::Yes(span), .. }
|
||||
| Self::TraitImpl { constness: Const::Yes(span), .. } => Some(*span),
|
||||
_ => None,
|
||||
}
|
||||
|
|
@ -110,15 +110,10 @@ impl<'a> AstValidator<'a> {
|
|||
self.outer_trait_or_trait_impl = old;
|
||||
}
|
||||
|
||||
fn with_in_trait(
|
||||
&mut self,
|
||||
span: Span,
|
||||
constness_span: Option<Span>,
|
||||
f: impl FnOnce(&mut Self),
|
||||
) {
|
||||
fn with_in_trait(&mut self, span: Span, constness: Const, f: impl FnOnce(&mut Self)) {
|
||||
let old = mem::replace(
|
||||
&mut self.outer_trait_or_trait_impl,
|
||||
Some(TraitOrTraitImpl::Trait { span, constness_span }),
|
||||
Some(TraitOrTraitImpl::Trait { span, constness }),
|
||||
);
|
||||
f(self);
|
||||
self.outer_trait_or_trait_impl = old;
|
||||
|
|
@ -273,7 +268,7 @@ impl<'a> AstValidator<'a> {
|
|||
};
|
||||
|
||||
let make_trait_const_sugg = if const_trait_impl
|
||||
&& let TraitOrTraitImpl::Trait { span, constness_span: None } = parent
|
||||
&& let TraitOrTraitImpl::Trait { span, constness: ast::Const::No } = parent
|
||||
{
|
||||
Some(span.shrink_to_lo())
|
||||
} else {
|
||||
|
|
@ -1131,10 +1126,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
visit::walk_item(self, item)
|
||||
}
|
||||
ItemKind::Trait(box Trait { is_auto, generics, ident, bounds, items, .. }) => {
|
||||
ItemKind::Trait(box Trait {
|
||||
constness,
|
||||
is_auto,
|
||||
generics,
|
||||
ident,
|
||||
bounds,
|
||||
items,
|
||||
..
|
||||
}) => {
|
||||
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
|
||||
let is_const_trait =
|
||||
// FIXME(const_trait_impl) remove this
|
||||
let alt_const_trait_span =
|
||||
attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
|
||||
let constness = match (*constness, alt_const_trait_span) {
|
||||
(Const::Yes(span), _) | (Const::No, Some(span)) => Const::Yes(span),
|
||||
(Const::No, None) => Const::No,
|
||||
};
|
||||
if *is_auto == IsAuto::Yes {
|
||||
// Auto traits cannot have generics, super traits nor contain items.
|
||||
self.deny_generic_params(generics, ident.span);
|
||||
|
|
@ -1145,13 +1153,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
|
||||
// Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
|
||||
// context for the supertraits.
|
||||
let disallowed =
|
||||
is_const_trait.is_none().then(|| TildeConstReason::Trait { span: item.span });
|
||||
let disallowed = matches!(constness, ast::Const::No)
|
||||
.then(|| TildeConstReason::Trait { span: item.span });
|
||||
self.with_tilde_const(disallowed, |this| {
|
||||
this.visit_generics(generics);
|
||||
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
|
||||
});
|
||||
self.with_in_trait(item.span, is_const_trait, |this| {
|
||||
self.with_in_trait(item.span, constness, |this| {
|
||||
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
|
||||
});
|
||||
}
|
||||
|
|
@ -1373,29 +1381,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
match bound {
|
||||
GenericBound::Trait(trait_ref) => {
|
||||
match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) {
|
||||
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||
if !self.features.more_maybe_bounds() =>
|
||||
{
|
||||
self.sess
|
||||
.create_feature_err(
|
||||
errors::OptionalTraitSupertrait {
|
||||
span: trait_ref.span,
|
||||
path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
|
||||
},
|
||||
sym::more_maybe_bounds,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||
if !self.features.more_maybe_bounds() =>
|
||||
{
|
||||
self.sess
|
||||
.create_feature_err(
|
||||
errors::OptionalTraitObject { span: trait_ref.span },
|
||||
sym::more_maybe_bounds,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
(
|
||||
BoundKind::TraitObject,
|
||||
BoundConstness::Always(_),
|
||||
|
|
|
|||
|
|
@ -566,22 +566,6 @@ pub(crate) struct NestedLifetimes {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_optional_trait_supertrait)]
|
||||
#[note]
|
||||
pub(crate) struct OptionalTraitSupertrait {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub path_str: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_optional_trait_object)]
|
||||
pub(crate) struct OptionalTraitObject {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_const_bound_trait_object)]
|
||||
pub(crate) struct ConstBoundTraitObject {
|
||||
|
|
@ -590,7 +574,7 @@ pub(crate) struct ConstBoundTraitObject {
|
|||
}
|
||||
|
||||
// FIXME(const_trait_impl): Consider making the note/reason the message of the diagnostic.
|
||||
// FIXME(const_trait_impl): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here).
|
||||
// FIXME(const_trait_impl): Provide structured suggestions (e.g., add `const` here).
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_tilde_const_disallowed)]
|
||||
pub(crate) struct TildeConstDisallowed {
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comment>
|
|||
pos += shebang_len;
|
||||
}
|
||||
|
||||
for token in rustc_lexer::tokenize(&text[pos..]) {
|
||||
for token in rustc_lexer::tokenize(&text[pos..], rustc_lexer::FrontmatterAllowed::Yes) {
|
||||
let token_text = &text[pos..pos + token.len as usize];
|
||||
match token.kind {
|
||||
rustc_lexer::TokenKind::Whitespace => {
|
||||
|
|
@ -171,6 +171,14 @@ fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comment>
|
|||
})
|
||||
}
|
||||
}
|
||||
rustc_lexer::TokenKind::Frontmatter { .. } => {
|
||||
code_to_the_left = false;
|
||||
comments.push(Comment {
|
||||
style: CommentStyle::Isolated,
|
||||
lines: vec![token_text.to_string()],
|
||||
pos: start_bpos + BytePos(pos as u32),
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
code_to_the_left = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -357,6 +357,7 @@ impl<'a> State<'a> {
|
|||
self.bclose(item.span, empty, cb);
|
||||
}
|
||||
ast::ItemKind::Trait(box ast::Trait {
|
||||
constness,
|
||||
safety,
|
||||
is_auto,
|
||||
ident,
|
||||
|
|
@ -366,6 +367,7 @@ impl<'a> State<'a> {
|
|||
}) => {
|
||||
let (cb, ib) = self.head("");
|
||||
self.print_visibility(&item.vis);
|
||||
self.print_constness(*constness);
|
||||
self.print_safety(*safety);
|
||||
self.print_is_auto(*is_auto);
|
||||
self.word_nbsp("trait");
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use rustc_ast::token::CommentKind;
|
|||
use rustc_ast::{self as ast, AttrStyle};
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::{DefaultBodyStability, PartialConstStability, PrintAttribute, RustcVersion, Stability};
|
||||
|
|
@ -69,6 +69,7 @@ pub enum ReprAttr {
|
|||
ReprAlign(Align),
|
||||
}
|
||||
pub use ReprAttr::*;
|
||||
use rustc_span::def_id::DefId;
|
||||
|
||||
pub enum TransparencyError {
|
||||
UnknownTransparency(Symbol, Span),
|
||||
|
|
@ -109,6 +110,22 @@ pub enum DeprecatedSince {
|
|||
Err,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Encodable,
|
||||
Decodable,
|
||||
Clone,
|
||||
HashStable_Generic,
|
||||
PrintAttribute
|
||||
)]
|
||||
pub enum CoverageStatus {
|
||||
On,
|
||||
Off,
|
||||
}
|
||||
|
||||
impl Deprecation {
|
||||
/// Whether an item marked with #[deprecated(since = "X")] is currently
|
||||
/// deprecated (i.e., whether X is not greater than the current rustc
|
||||
|
|
@ -140,6 +157,30 @@ pub enum UsedBy {
|
|||
Linker,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct StrippedCfgItem<ModId = DefId> {
|
||||
pub parent_module: ModId,
|
||||
pub ident: Ident,
|
||||
pub cfg: (CfgEntry, Span),
|
||||
}
|
||||
|
||||
impl<ModId> StrippedCfgItem<ModId> {
|
||||
pub fn map_mod_id<New>(self, f: impl FnOnce(ModId) -> New) -> StrippedCfgItem<New> {
|
||||
StrippedCfgItem { parent_module: f(self.parent_module), ident: self.ident, cfg: self.cfg }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Encodable, Decodable, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(HashStable_Generic, PrintAttribute)]
|
||||
pub enum CfgEntry {
|
||||
All(ThinVec<CfgEntry>, Span),
|
||||
Any(ThinVec<CfgEntry>, Span),
|
||||
Not(Box<CfgEntry>, Span),
|
||||
Bool(bool, Span),
|
||||
NameValue { name: Symbol, name_span: Span, value: Option<(Symbol, Span)>, span: Span },
|
||||
Version(Option<RustcVersion>, Span),
|
||||
}
|
||||
|
||||
/// Represents parsed *built-in* inert attributes.
|
||||
///
|
||||
/// ## Overview
|
||||
|
|
@ -193,17 +234,24 @@ pub enum UsedBy {
|
|||
pub enum AttributeKind {
|
||||
// tidy-alphabetical-start
|
||||
/// Represents `#[align(N)]`.
|
||||
// FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
|
||||
Align { align: Align, span: Span },
|
||||
|
||||
/// Represents `#[rustc_allow_const_fn_unstable]`.
|
||||
AllowConstFnUnstable(ThinVec<Symbol>, Span),
|
||||
|
||||
/// Represents `#[rustc_allow_incoherent_impl]`.
|
||||
AllowIncoherentImpl(Span),
|
||||
|
||||
/// Represents `#[allow_internal_unstable]`.
|
||||
AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span),
|
||||
|
||||
/// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint).
|
||||
AsPtr(Span),
|
||||
|
||||
/// Represents `#[automatically_derived]`
|
||||
AutomaticallyDerived(Span),
|
||||
|
||||
/// Represents `#[rustc_default_body_unstable]`.
|
||||
BodyStability {
|
||||
stability: DefaultBodyStability,
|
||||
|
|
@ -211,6 +259,12 @@ pub enum AttributeKind {
|
|||
span: Span,
|
||||
},
|
||||
|
||||
/// Represents `#[rustc_coherence_is_core]`.
|
||||
CoherenceIsCore,
|
||||
|
||||
/// Represents `#[rustc_coinductive]`.
|
||||
Coinductive(Span),
|
||||
|
||||
/// Represents `#[cold]`.
|
||||
Cold(Span),
|
||||
|
||||
|
|
@ -234,12 +288,27 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_const_stable_indirect]`.
|
||||
ConstStabilityIndirect,
|
||||
|
||||
/// Represents `#[const_trait]`.
|
||||
ConstTrait(Span),
|
||||
|
||||
/// Represents `#[coverage]`.
|
||||
Coverage(Span, CoverageStatus),
|
||||
|
||||
///Represents `#[rustc_deny_explicit_impl]`.
|
||||
DenyExplicitImpl(Span),
|
||||
|
||||
/// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
|
||||
Deprecation { deprecation: Deprecation, span: Span },
|
||||
|
||||
/// Represents `#[rustc_do_not_implement_via_object]`.
|
||||
DoNotImplementViaObject(Span),
|
||||
|
||||
/// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html).
|
||||
DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol },
|
||||
|
||||
/// Represents `#[rustc_dummy]`.
|
||||
Dummy,
|
||||
|
||||
/// Represents [`#[export_name]`](https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute).
|
||||
ExportName {
|
||||
/// The name to export this item with.
|
||||
|
|
@ -248,6 +317,18 @@ pub enum AttributeKind {
|
|||
span: Span,
|
||||
},
|
||||
|
||||
/// Represents `#[export_stable]`.
|
||||
ExportStable,
|
||||
|
||||
/// Represents `#[ffi_const]`.
|
||||
FfiConst(Span),
|
||||
|
||||
/// Represents `#[ffi_pure]`.
|
||||
FfiPure(Span),
|
||||
|
||||
/// Represents `#[fundamental]`.
|
||||
Fundamental,
|
||||
|
||||
/// Represents `#[ignore]`
|
||||
Ignore {
|
||||
span: Span,
|
||||
|
|
@ -261,6 +342,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[link_name]`.
|
||||
LinkName { name: Symbol, span: Span },
|
||||
|
||||
/// Represents `#[link_ordinal]`.
|
||||
LinkOrdinal { ordinal: u16, span: Span },
|
||||
|
||||
/// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
|
||||
LinkSection { name: Symbol, span: Span },
|
||||
|
||||
|
|
@ -270,6 +354,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_macro_transparency]`.
|
||||
MacroTransparency(Transparency),
|
||||
|
||||
/// Represents `#[marker]`.
|
||||
Marker(Span),
|
||||
|
||||
/// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html).
|
||||
MayDangle(Span),
|
||||
|
||||
|
|
@ -292,15 +379,24 @@ pub enum AttributeKind {
|
|||
/// Represents `#[non_exhaustive]`
|
||||
NonExhaustive(Span),
|
||||
|
||||
/// Represents `#[omit_gdb_pretty_printer_section]`
|
||||
OmitGdbPrettyPrinterSection,
|
||||
|
||||
/// Represents `#[optimize(size|speed)]`
|
||||
Optimize(OptimizeAttr, Span),
|
||||
|
||||
/// Represents `#[rustc_paren_sugar]`.
|
||||
ParenSugar(Span),
|
||||
|
||||
/// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
|
||||
PassByValue(Span),
|
||||
|
||||
/// Represents `#[path]`
|
||||
Path(Symbol, Span),
|
||||
|
||||
/// Represents `#[pointee]`
|
||||
Pointee(Span),
|
||||
|
||||
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
|
||||
PubTransparent(Span),
|
||||
|
||||
|
|
@ -319,6 +415,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_skip_during_method_dispatch]`.
|
||||
SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
|
||||
|
||||
/// Represents `#[rustc_specialization_trait]`.
|
||||
SpecializationTrait(Span),
|
||||
|
||||
/// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
|
||||
Stability {
|
||||
stability: Stability,
|
||||
|
|
@ -326,12 +425,24 @@ pub enum AttributeKind {
|
|||
span: Span,
|
||||
},
|
||||
|
||||
/// Represents `#[rustc_std_internal_symbol]`.
|
||||
StdInternalSymbol(Span),
|
||||
|
||||
/// Represents `#[target_feature(enable = "...")]`
|
||||
TargetFeature(ThinVec<(Symbol, Span)>, Span),
|
||||
|
||||
/// Represents `#[track_caller]`
|
||||
TrackCaller(Span),
|
||||
|
||||
/// Represents `#[type_const]`.
|
||||
TypeConst(Span),
|
||||
|
||||
/// Represents `#[rustc_unsafe_specialization_marker]`.
|
||||
UnsafeSpecializationMarker(Span),
|
||||
|
||||
/// Represents `#[unstable_feature_bound]`.
|
||||
UnstableFeatureBound(ThinVec<(Symbol, Span)>),
|
||||
|
||||
/// Represents `#[used]`
|
||||
Used { used_by: UsedBy, span: Span },
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -15,41 +15,64 @@ impl AttributeKind {
|
|||
// tidy-alphabetical-start
|
||||
Align { .. } => No,
|
||||
AllowConstFnUnstable(..) => No,
|
||||
AllowIncoherentImpl(..) => No,
|
||||
AllowInternalUnstable(..) => Yes,
|
||||
AsPtr(..) => Yes,
|
||||
AutomaticallyDerived(..) => Yes,
|
||||
BodyStability { .. } => No,
|
||||
CoherenceIsCore => No,
|
||||
Coinductive(..) => No,
|
||||
Cold(..) => No,
|
||||
Confusables { .. } => Yes,
|
||||
ConstContinue(..) => No,
|
||||
ConstStability { .. } => Yes,
|
||||
ConstStabilityIndirect => No,
|
||||
ConstTrait(..) => No,
|
||||
Coverage(..) => No,
|
||||
DenyExplicitImpl(..) => No,
|
||||
Deprecation { .. } => Yes,
|
||||
DoNotImplementViaObject(..) => No,
|
||||
DocComment { .. } => Yes,
|
||||
Dummy => No,
|
||||
ExportName { .. } => Yes,
|
||||
ExportStable => No,
|
||||
FfiConst(..) => No,
|
||||
FfiPure(..) => No,
|
||||
Fundamental { .. } => Yes,
|
||||
Ignore { .. } => No,
|
||||
Inline(..) => No,
|
||||
LinkName { .. } => Yes,
|
||||
LinkSection { .. } => No,
|
||||
LinkName { .. } => Yes, // Needed for rustdoc
|
||||
LinkOrdinal { .. } => No,
|
||||
LinkSection { .. } => Yes, // Needed for rustdoc
|
||||
LoopMatch(..) => No,
|
||||
MacroTransparency(..) => Yes,
|
||||
Marker(..) => No,
|
||||
MayDangle(..) => No,
|
||||
MustUse { .. } => Yes,
|
||||
Naked(..) => No,
|
||||
NoImplicitPrelude(..) => No,
|
||||
NoMangle(..) => No,
|
||||
NonExhaustive(..) => Yes,
|
||||
NoMangle(..) => Yes, // Needed for rustdoc
|
||||
NonExhaustive(..) => Yes, // Needed for rustdoc
|
||||
OmitGdbPrettyPrinterSection => No,
|
||||
Optimize(..) => No,
|
||||
ParenSugar(..) => No,
|
||||
PassByValue(..) => Yes,
|
||||
Path(..) => No,
|
||||
Pointee(..) => No,
|
||||
PubTransparent(..) => Yes,
|
||||
Repr { .. } => No,
|
||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
RustcLayoutScalarValidRangeStart(..) => Yes,
|
||||
RustcObjectLifetimeDefault => No,
|
||||
SkipDuringMethodDispatch { .. } => No,
|
||||
SpecializationTrait(..) => No,
|
||||
Stability { .. } => Yes,
|
||||
StdInternalSymbol(..) => No,
|
||||
TargetFeature(..) => No,
|
||||
TrackCaller(..) => Yes,
|
||||
TypeConst(..) => Yes,
|
||||
UnsafeSpecializationMarker(..) => No,
|
||||
UnstableFeatureBound(..) => No,
|
||||
Used { .. } => No,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use rustc_ast::token::CommentKind;
|
|||
use rustc_ast::{AttrStyle, IntTy, UintTy};
|
||||
use rustc_ast_pretty::pp::Printer;
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
pub use stability::*;
|
||||
use thin_vec::ThinVec;
|
||||
pub use version::*;
|
||||
|
|
@ -170,7 +170,7 @@ macro_rules! print_tup {
|
|||
}
|
||||
|
||||
print_tup!(A B C D E F G H);
|
||||
print_skip!(Span, ());
|
||||
print_skip!(Span, (), ErrorGuaranteed);
|
||||
print_disp!(u16, bool, NonZero<u32>);
|
||||
print_debug!(Symbol, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::num::NonZero;
|
||||
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_span::{ErrorGuaranteed, Symbol, sym};
|
||||
|
||||
use crate::{PrintAttribute, RustcVersion};
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ pub enum StableSince {
|
|||
/// Stabilized in the upcoming version, whatever number that is.
|
||||
Current,
|
||||
/// Failed to parse a stabilization version.
|
||||
Err,
|
||||
Err(ErrorGuaranteed),
|
||||
}
|
||||
|
||||
impl StabilityLevel {
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ attr_parsing_invalid_repr_hint_no_value =
|
|||
attr_parsing_invalid_since =
|
||||
'since' must be a Rust version number, such as "1.31.0"
|
||||
|
||||
attr_parsing_link_ordinal_out_of_range = ordinal value in `link_ordinal` is too large: `{$ordinal}`
|
||||
.note = the value may not exceed `u16::MAX`
|
||||
|
||||
attr_parsing_missing_feature =
|
||||
missing 'feature'
|
||||
|
||||
|
|
@ -133,6 +136,9 @@ attr_parsing_unrecognized_repr_hint =
|
|||
attr_parsing_unstable_cfg_target_compact =
|
||||
compact `cfg(target(..))` is experimental and subject to change
|
||||
|
||||
attr_parsing_unstable_feature_bound_incompatible_stability = Item annotated with `#[unstable_feature_bound]` should not be stable
|
||||
.help = If this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`
|
||||
|
||||
attr_parsing_unsupported_literal_cfg_boolean =
|
||||
literal in `cfg` predicate value must be a boolean
|
||||
attr_parsing_unsupported_literal_cfg_string =
|
||||
|
|
@ -146,12 +152,12 @@ attr_parsing_unused_duplicate =
|
|||
unused attribute
|
||||
.suggestion = remove this attribute
|
||||
.note = attribute also specified here
|
||||
.warn = {-passes_previously_accepted}
|
||||
.warn = {-attr_parsing_previously_accepted}
|
||||
|
||||
attr_parsing_unused_multiple =
|
||||
multiple `{$name}` attributes
|
||||
.suggestion = remove this attribute
|
||||
.note = attribute also specified here
|
||||
|
||||
-attr_parsing_perviously_accepted =
|
||||
-attr_parsing_previously_accepted =
|
||||
this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
|
|
|||
|
|
@ -27,6 +27,26 @@ impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct UnstableFeatureBoundParser;
|
||||
impl<S: Stage> CombineAttributeParser<S> for UnstableFeatureBoundParser {
|
||||
const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound];
|
||||
type Item = (Symbol, Span);
|
||||
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableFeatureBound(items);
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");
|
||||
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
args: &'c ArgParser<'_>,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
if !cx.features().staged_api() {
|
||||
cx.emit_err(session_diagnostics::StabilityOutsideStd { span: cx.attr_span });
|
||||
}
|
||||
parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
|
||||
.into_iter()
|
||||
.zip(iter::repeat(cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct AllowConstFnUnstableParser;
|
||||
impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable];
|
||||
|
|
|
|||
|
|
@ -1,247 +1,298 @@
|
|||
use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr_data_structures::RustcVersion;
|
||||
use rustc_feature::{Features, GatedCfg, find_gated_cfg};
|
||||
use rustc_ast::{LitKind, NodeId};
|
||||
use rustc_attr_data_structures::{CfgEntry, RustcVersion};
|
||||
use rustc_feature::{AttributeTemplate, Features, template};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::ExpectedValues;
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||
use rustc_session::lint::{BuiltinLintDiag, Lint};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::session_diagnostics::{self, UnsupportedLiteralReason};
|
||||
use crate::{fluent_generated, parse_version};
|
||||
use crate::context::{AcceptContext, ShouldEmit, Stage};
|
||||
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser};
|
||||
use crate::{
|
||||
CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, try_gate_cfg,
|
||||
};
|
||||
|
||||
/// Emitter of a builtin lint from `cfg_matches`.
|
||||
///
|
||||
/// Used to support emitting a lint (currently on check-cfg), either:
|
||||
/// - as an early buffered lint (in `rustc`)
|
||||
/// - or has a "normal" lint from HIR (in `rustdoc`)
|
||||
pub trait CfgMatchesLintEmitter {
|
||||
fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag);
|
||||
pub const CFG_TEMPLATE: AttributeTemplate = template!(List: "predicate");
|
||||
|
||||
pub fn parse_cfg_attr<'c, S: Stage>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
args: &'c ArgParser<'_>,
|
||||
) -> Option<CfgEntry> {
|
||||
let ArgParser::List(list) = args else {
|
||||
cx.expected_list(cx.attr_span);
|
||||
return None;
|
||||
};
|
||||
let Some(single) = list.single() else {
|
||||
cx.expected_single_argument(list.span);
|
||||
return None;
|
||||
};
|
||||
parse_cfg_entry(cx, single)
|
||||
}
|
||||
|
||||
impl CfgMatchesLintEmitter for NodeId {
|
||||
fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag) {
|
||||
sess.psess.buffer_lint(lint, sp, *self, diag);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Condition {
|
||||
pub name: Symbol,
|
||||
pub name_span: Span,
|
||||
pub value: Option<Symbol>,
|
||||
pub value_span: Option<Span>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// Tests if a cfg-pattern matches the cfg set
|
||||
pub fn cfg_matches(
|
||||
cfg: &MetaItemInner,
|
||||
sess: &Session,
|
||||
lint_emitter: impl CfgMatchesLintEmitter,
|
||||
features: Option<&Features>,
|
||||
) -> bool {
|
||||
eval_condition(cfg, sess, features, &mut |cfg| {
|
||||
try_gate_cfg(cfg.name, cfg.span, sess, features);
|
||||
match sess.psess.check_config.expecteds.get(&cfg.name) {
|
||||
Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
|
||||
lint_emitter.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
BuiltinLintDiag::UnexpectedCfgValue(
|
||||
(cfg.name, cfg.name_span),
|
||||
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
|
||||
),
|
||||
);
|
||||
fn parse_cfg_entry<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
item: &MetaItemOrLitParser<'_>,
|
||||
) -> Option<CfgEntry> {
|
||||
Some(match item {
|
||||
MetaItemOrLitParser::MetaItemParser(meta) => match meta.args() {
|
||||
ArgParser::List(list) => match meta.path().word_sym() {
|
||||
Some(sym::not) => {
|
||||
let Some(single) = list.single() else {
|
||||
cx.expected_single_argument(list.span);
|
||||
return None;
|
||||
};
|
||||
CfgEntry::Not(Box::new(parse_cfg_entry(cx, single)?), list.span)
|
||||
}
|
||||
Some(sym::any) => CfgEntry::Any(
|
||||
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
|
||||
list.span,
|
||||
),
|
||||
Some(sym::all) => CfgEntry::All(
|
||||
list.mixed().flat_map(|sub_item| parse_cfg_entry(cx, sub_item)).collect(),
|
||||
list.span,
|
||||
),
|
||||
Some(sym::target) => parse_cfg_entry_target(cx, list, meta.span())?,
|
||||
Some(sym::version) => parse_cfg_entry_version(cx, list, meta.span())?,
|
||||
_ => {
|
||||
cx.emit_err(session_diagnostics::InvalidPredicate {
|
||||
span: meta.span(),
|
||||
predicate: meta.path().to_string(),
|
||||
});
|
||||
return None;
|
||||
}
|
||||
},
|
||||
a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
|
||||
let Some(name) = meta.path().word_sym() else {
|
||||
cx.emit_err(session_diagnostics::CfgPredicateIdentifier {
|
||||
span: meta.path().span(),
|
||||
});
|
||||
return None;
|
||||
};
|
||||
parse_name_value(name, meta.path().span(), a.name_value(), meta.span(), cx)?
|
||||
}
|
||||
None if sess.psess.check_config.exhaustive_names => {
|
||||
lint_emitter.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
BuiltinLintDiag::UnexpectedCfgName(
|
||||
(cfg.name, cfg.name_span),
|
||||
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
|
||||
),
|
||||
);
|
||||
},
|
||||
MetaItemOrLitParser::Lit(lit) => match lit.kind {
|
||||
LitKind::Bool(b) => CfgEntry::Bool(b, lit.span),
|
||||
_ => {
|
||||
cx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: lit.span });
|
||||
return None;
|
||||
}
|
||||
_ => { /* not unexpected */ }
|
||||
}
|
||||
sess.psess.config.contains(&(cfg.name, cfg.value))
|
||||
},
|
||||
MetaItemOrLitParser::Err(_, _) => return None,
|
||||
})
|
||||
}
|
||||
|
||||
fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
|
||||
let gate = find_gated_cfg(|sym| sym == name);
|
||||
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
|
||||
gate_cfg(gated_cfg, span, sess, feats);
|
||||
}
|
||||
fn parse_cfg_entry_version<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
list: &MetaItemListParser<'_>,
|
||||
meta_span: Span,
|
||||
) -> Option<CfgEntry> {
|
||||
try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option());
|
||||
let Some(version) = list.single() else {
|
||||
cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span });
|
||||
return None;
|
||||
};
|
||||
let Some(version_lit) = version.lit() else {
|
||||
cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version.span() });
|
||||
return None;
|
||||
};
|
||||
let Some(version_str) = version_lit.value_str() else {
|
||||
cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version_lit.span });
|
||||
return None;
|
||||
};
|
||||
|
||||
let min_version = parse_version(version_str).or_else(|| {
|
||||
cx.sess()
|
||||
.dcx()
|
||||
.emit_warn(session_diagnostics::UnknownVersionLiteral { span: version_lit.span });
|
||||
None
|
||||
});
|
||||
|
||||
Some(CfgEntry::Version(min_version, list.span))
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
|
||||
let (cfg, feature, has_feature) = gated_cfg;
|
||||
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
|
||||
let explain = format!("`cfg({cfg})` is experimental and subject to change");
|
||||
feature_err(sess, *feature, cfg_span, explain).emit();
|
||||
fn parse_cfg_entry_target<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
list: &MetaItemListParser<'_>,
|
||||
meta_span: Span,
|
||||
) -> Option<CfgEntry> {
|
||||
if let Some(features) = cx.features_option()
|
||||
&& !features.cfg_target_compact()
|
||||
{
|
||||
feature_err(
|
||||
cx.sess(),
|
||||
sym::cfg_target_compact,
|
||||
meta_span,
|
||||
fluent_generated::attr_parsing_unstable_cfg_target_compact,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
|
||||
/// evaluate individual items.
|
||||
pub fn eval_condition(
|
||||
cfg: &MetaItemInner,
|
||||
sess: &Session,
|
||||
features: Option<&Features>,
|
||||
eval: &mut impl FnMut(Condition) -> bool,
|
||||
) -> bool {
|
||||
let dcx = sess.dcx();
|
||||
let mut result = ThinVec::new();
|
||||
for sub_item in list.mixed() {
|
||||
// First, validate that this is a NameValue item
|
||||
let Some(sub_item) = sub_item.meta_item() else {
|
||||
cx.expected_name_value(sub_item.span(), None);
|
||||
continue;
|
||||
};
|
||||
let Some(nv) = sub_item.args().name_value() else {
|
||||
cx.expected_name_value(sub_item.span(), None);
|
||||
continue;
|
||||
};
|
||||
|
||||
let cfg = match cfg {
|
||||
MetaItemInner::MetaItem(meta_item) => meta_item,
|
||||
MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => {
|
||||
return *b;
|
||||
}
|
||||
_ => {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: cfg.span(),
|
||||
reason: UnsupportedLiteralReason::CfgBoolean,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(cfg.span()),
|
||||
// Then, parse it as a name-value item
|
||||
let Some(name) = sub_item.path().word_sym() else {
|
||||
cx.emit_err(session_diagnostics::CfgPredicateIdentifier {
|
||||
span: sub_item.path().span(),
|
||||
});
|
||||
return false;
|
||||
return None;
|
||||
};
|
||||
let name = Symbol::intern(&format!("target_{name}"));
|
||||
if let Some(cfg) =
|
||||
parse_name_value(name, sub_item.path().span(), Some(nv), sub_item.span(), cx)
|
||||
{
|
||||
result.push(cfg);
|
||||
}
|
||||
}
|
||||
Some(CfgEntry::All(result, list.span))
|
||||
}
|
||||
|
||||
fn parse_name_value<S: Stage>(
|
||||
name: Symbol,
|
||||
name_span: Span,
|
||||
value: Option<&NameValueParser>,
|
||||
span: Span,
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
) -> Option<CfgEntry> {
|
||||
try_gate_cfg(name, span, cx.sess(), cx.features_option());
|
||||
|
||||
let value = match value {
|
||||
None => None,
|
||||
Some(value) => {
|
||||
let Some(value_str) = value.value_as_str() else {
|
||||
cx.expected_string_literal(value.value_span, Some(value.value_as_lit()));
|
||||
return None;
|
||||
};
|
||||
Some((value_str, value.value_span))
|
||||
}
|
||||
};
|
||||
|
||||
match &cfg.kind {
|
||||
MetaItemKind::List(mis) if cfg.has_name(sym::version) => {
|
||||
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||
let (min_version, span) = match &mis[..] {
|
||||
[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
|
||||
(sym, span)
|
||||
}
|
||||
[
|
||||
MetaItemInner::Lit(MetaItemLit { span, .. })
|
||||
| MetaItemInner::MetaItem(MetaItem { span, .. }),
|
||||
] => {
|
||||
dcx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span });
|
||||
return false;
|
||||
}
|
||||
[..] => {
|
||||
dcx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral {
|
||||
span: cfg.span,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let Some(min_version) = parse_version(*min_version) else {
|
||||
dcx.emit_warn(session_diagnostics::UnknownVersionLiteral { span: *span });
|
||||
return false;
|
||||
};
|
||||
Some(CfgEntry::NameValue { name, name_span, value, span })
|
||||
}
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
|
||||
if sess.psess.assume_incomplete_release {
|
||||
RustcVersion::current_overridable() > min_version
|
||||
} else {
|
||||
RustcVersion::current_overridable() >= min_version
|
||||
}
|
||||
}
|
||||
MetaItemKind::List(mis) => {
|
||||
for mi in mis.iter() {
|
||||
if mi.meta_item_or_bool().is_none() {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: mi.span(),
|
||||
reason: UnsupportedLiteralReason::Generic,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(mi.span()),
|
||||
});
|
||||
return false;
|
||||
pub fn eval_config_entry(
|
||||
sess: &Session,
|
||||
cfg_entry: &CfgEntry,
|
||||
id: NodeId,
|
||||
features: Option<&Features>,
|
||||
emit_lints: ShouldEmit,
|
||||
) -> EvalConfigResult {
|
||||
match cfg_entry {
|
||||
CfgEntry::All(subs, ..) => {
|
||||
let mut all = None;
|
||||
for sub in subs {
|
||||
let res = eval_config_entry(sess, sub, id, features, emit_lints);
|
||||
// We cannot short-circuit because `eval_config_entry` emits some lints
|
||||
if !res.as_bool() {
|
||||
all.get_or_insert(res);
|
||||
}
|
||||
}
|
||||
|
||||
// The unwraps below may look dangerous, but we've already asserted
|
||||
// that they won't fail with the loop above.
|
||||
match cfg.name() {
|
||||
Some(sym::any) => mis
|
||||
.iter()
|
||||
// We don't use any() here, because we want to evaluate all cfg condition
|
||||
// as eval_condition can (and does) extra checks
|
||||
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
|
||||
Some(sym::all) => mis
|
||||
.iter()
|
||||
// We don't use all() here, because we want to evaluate all cfg condition
|
||||
// as eval_condition can (and does) extra checks
|
||||
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
|
||||
Some(sym::not) => {
|
||||
let [mi] = mis.as_slice() else {
|
||||
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
|
||||
return false;
|
||||
};
|
||||
|
||||
!eval_condition(mi, sess, features, eval)
|
||||
}
|
||||
Some(sym::target) => {
|
||||
if let Some(features) = features
|
||||
&& !features.cfg_target_compact()
|
||||
{
|
||||
feature_err(
|
||||
sess,
|
||||
sym::cfg_target_compact,
|
||||
cfg.span,
|
||||
fluent_generated::attr_parsing_unstable_cfg_target_compact,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
mis.iter().fold(true, |res, mi| {
|
||||
let Some(mut mi) = mi.meta_item().cloned() else {
|
||||
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier {
|
||||
span: mi.span(),
|
||||
});
|
||||
return false;
|
||||
};
|
||||
|
||||
if let [seg, ..] = &mut mi.path.segments[..] {
|
||||
seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
|
||||
}
|
||||
|
||||
res & eval_condition(&MetaItemInner::MetaItem(mi), sess, features, eval)
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
dcx.emit_err(session_diagnostics::InvalidPredicate {
|
||||
span: cfg.span,
|
||||
predicate: pprust::path_to_string(&cfg.path),
|
||||
});
|
||||
false
|
||||
all.unwrap_or_else(|| EvalConfigResult::True)
|
||||
}
|
||||
CfgEntry::Any(subs, span) => {
|
||||
let mut any = None;
|
||||
for sub in subs {
|
||||
let res = eval_config_entry(sess, sub, id, features, emit_lints);
|
||||
// We cannot short-circuit because `eval_config_entry` emits some lints
|
||||
if res.as_bool() {
|
||||
any.get_or_insert(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
|
||||
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
|
||||
true
|
||||
}
|
||||
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: lit.span,
|
||||
reason: UnsupportedLiteralReason::CfgString,
|
||||
is_bytestr: lit.kind.is_bytestr(),
|
||||
start_point_span: sess.source_map().start_point(lit.span),
|
||||
});
|
||||
true
|
||||
}
|
||||
MetaItemKind::Word | MetaItemKind::NameValue(..) => {
|
||||
let ident = cfg.ident().expect("multi-segment cfg predicate");
|
||||
eval(Condition {
|
||||
name: ident.name,
|
||||
name_span: ident.span,
|
||||
value: cfg.value_str(),
|
||||
value_span: cfg.name_value_literal_span(),
|
||||
span: cfg.span,
|
||||
any.unwrap_or_else(|| EvalConfigResult::False {
|
||||
reason: cfg_entry.clone(),
|
||||
reason_span: *span,
|
||||
})
|
||||
}
|
||||
CfgEntry::Not(sub, span) => {
|
||||
if eval_config_entry(sess, sub, id, features, emit_lints).as_bool() {
|
||||
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
|
||||
} else {
|
||||
EvalConfigResult::True
|
||||
}
|
||||
}
|
||||
CfgEntry::Bool(b, span) => {
|
||||
if *b {
|
||||
EvalConfigResult::True
|
||||
} else {
|
||||
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
|
||||
}
|
||||
}
|
||||
CfgEntry::NameValue { name, name_span, value, span } => {
|
||||
if let ShouldEmit::ErrorsAndLints = emit_lints {
|
||||
match sess.psess.check_config.expecteds.get(name) {
|
||||
Some(ExpectedValues::Some(values))
|
||||
if !values.contains(&value.map(|(v, _)| v)) =>
|
||||
{
|
||||
id.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
*span,
|
||||
BuiltinLintDiag::UnexpectedCfgValue((*name, *name_span), *value),
|
||||
);
|
||||
}
|
||||
None if sess.psess.check_config.exhaustive_names => {
|
||||
id.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
*span,
|
||||
BuiltinLintDiag::UnexpectedCfgName((*name, *name_span), *value),
|
||||
);
|
||||
}
|
||||
_ => { /* not unexpected */ }
|
||||
}
|
||||
}
|
||||
|
||||
if sess.psess.config.contains(&(*name, value.map(|(v, _)| v))) {
|
||||
EvalConfigResult::True
|
||||
} else {
|
||||
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
|
||||
}
|
||||
}
|
||||
CfgEntry::Version(min_version, version_span) => {
|
||||
let Some(min_version) = min_version else {
|
||||
return EvalConfigResult::False {
|
||||
reason: cfg_entry.clone(),
|
||||
reason_span: *version_span,
|
||||
};
|
||||
};
|
||||
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
|
||||
let min_version_ok = if sess.psess.assume_incomplete_release {
|
||||
RustcVersion::current_overridable() > *min_version
|
||||
} else {
|
||||
RustcVersion::current_overridable() >= *min_version
|
||||
};
|
||||
if min_version_ok {
|
||||
EvalConfigResult::True
|
||||
} else {
|
||||
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *version_span }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum EvalConfigResult {
|
||||
True,
|
||||
False { reason: CfgEntry, reason_span: Span },
|
||||
}
|
||||
|
||||
impl EvalConfigResult {
|
||||
pub fn as_bool(&self) -> bool {
|
||||
match self {
|
||||
EvalConfigResult::True => true,
|
||||
EvalConfigResult::False { .. } => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
247
compiler/rustc_attr_parsing/src/attributes/cfg_old.rs
Normal file
247
compiler/rustc_attr_parsing/src/attributes/cfg_old.rs
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr_data_structures::RustcVersion;
|
||||
use rustc_feature::{Features, GatedCfg, find_gated_cfg};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::ExpectedValues;
|
||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||
use rustc_session::lint::{BuiltinLintDiag, Lint};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use crate::session_diagnostics::{self, UnsupportedLiteralReason};
|
||||
use crate::{fluent_generated, parse_version};
|
||||
|
||||
/// Emitter of a builtin lint from `cfg_matches`.
|
||||
///
|
||||
/// Used to support emitting a lint (currently on check-cfg), either:
|
||||
/// - as an early buffered lint (in `rustc`)
|
||||
/// - or has a "normal" lint from HIR (in `rustdoc`)
|
||||
pub trait CfgMatchesLintEmitter {
|
||||
fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag);
|
||||
}
|
||||
|
||||
impl CfgMatchesLintEmitter for NodeId {
|
||||
fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag) {
|
||||
sess.psess.buffer_lint(lint, sp, *self, diag);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Condition {
|
||||
pub name: Symbol,
|
||||
pub name_span: Span,
|
||||
pub value: Option<Symbol>,
|
||||
pub value_span: Option<Span>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// Tests if a cfg-pattern matches the cfg set
|
||||
pub fn cfg_matches(
|
||||
cfg: &MetaItemInner,
|
||||
sess: &Session,
|
||||
lint_emitter: impl CfgMatchesLintEmitter,
|
||||
features: Option<&Features>,
|
||||
) -> bool {
|
||||
eval_condition(cfg, sess, features, &mut |cfg| {
|
||||
try_gate_cfg(cfg.name, cfg.span, sess, features);
|
||||
match sess.psess.check_config.expecteds.get(&cfg.name) {
|
||||
Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
|
||||
lint_emitter.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
BuiltinLintDiag::UnexpectedCfgValue(
|
||||
(cfg.name, cfg.name_span),
|
||||
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
|
||||
),
|
||||
);
|
||||
}
|
||||
None if sess.psess.check_config.exhaustive_names => {
|
||||
lint_emitter.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
BuiltinLintDiag::UnexpectedCfgName(
|
||||
(cfg.name, cfg.name_span),
|
||||
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
|
||||
),
|
||||
);
|
||||
}
|
||||
_ => { /* not unexpected */ }
|
||||
}
|
||||
sess.psess.config.contains(&(cfg.name, cfg.value))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
|
||||
let gate = find_gated_cfg(|sym| sym == name);
|
||||
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
|
||||
gate_cfg(gated_cfg, span, sess, feats);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
|
||||
let (cfg, feature, has_feature) = gated_cfg;
|
||||
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
|
||||
let explain = format!("`cfg({cfg})` is experimental and subject to change");
|
||||
feature_err(sess, *feature, cfg_span, explain).emit();
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
|
||||
/// evaluate individual items.
|
||||
pub fn eval_condition(
|
||||
cfg: &MetaItemInner,
|
||||
sess: &Session,
|
||||
features: Option<&Features>,
|
||||
eval: &mut impl FnMut(Condition) -> bool,
|
||||
) -> bool {
|
||||
let dcx = sess.dcx();
|
||||
|
||||
let cfg = match cfg {
|
||||
MetaItemInner::MetaItem(meta_item) => meta_item,
|
||||
MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => {
|
||||
return *b;
|
||||
}
|
||||
_ => {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: cfg.span(),
|
||||
reason: UnsupportedLiteralReason::CfgBoolean,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(cfg.span()),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
match &cfg.kind {
|
||||
MetaItemKind::List(mis) if cfg.has_name(sym::version) => {
|
||||
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||
let (min_version, span) = match &mis[..] {
|
||||
[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
|
||||
(sym, span)
|
||||
}
|
||||
[
|
||||
MetaItemInner::Lit(MetaItemLit { span, .. })
|
||||
| MetaItemInner::MetaItem(MetaItem { span, .. }),
|
||||
] => {
|
||||
dcx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span });
|
||||
return false;
|
||||
}
|
||||
[..] => {
|
||||
dcx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral {
|
||||
span: cfg.span,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let Some(min_version) = parse_version(*min_version) else {
|
||||
dcx.emit_warn(session_diagnostics::UnknownVersionLiteral { span: *span });
|
||||
return false;
|
||||
};
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
|
||||
if sess.psess.assume_incomplete_release {
|
||||
RustcVersion::current_overridable() > min_version
|
||||
} else {
|
||||
RustcVersion::current_overridable() >= min_version
|
||||
}
|
||||
}
|
||||
MetaItemKind::List(mis) => {
|
||||
for mi in mis.iter() {
|
||||
if mi.meta_item_or_bool().is_none() {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: mi.span(),
|
||||
reason: UnsupportedLiteralReason::Generic,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(mi.span()),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The unwraps below may look dangerous, but we've already asserted
|
||||
// that they won't fail with the loop above.
|
||||
match cfg.name() {
|
||||
Some(sym::any) => mis
|
||||
.iter()
|
||||
// We don't use any() here, because we want to evaluate all cfg condition
|
||||
// as eval_condition can (and does) extra checks
|
||||
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
|
||||
Some(sym::all) => mis
|
||||
.iter()
|
||||
// We don't use all() here, because we want to evaluate all cfg condition
|
||||
// as eval_condition can (and does) extra checks
|
||||
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
|
||||
Some(sym::not) => {
|
||||
let [mi] = mis.as_slice() else {
|
||||
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
|
||||
return false;
|
||||
};
|
||||
|
||||
!eval_condition(mi, sess, features, eval)
|
||||
}
|
||||
Some(sym::target) => {
|
||||
if let Some(features) = features
|
||||
&& !features.cfg_target_compact()
|
||||
{
|
||||
feature_err(
|
||||
sess,
|
||||
sym::cfg_target_compact,
|
||||
cfg.span,
|
||||
fluent_generated::attr_parsing_unstable_cfg_target_compact,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
mis.iter().fold(true, |res, mi| {
|
||||
let Some(mut mi) = mi.meta_item().cloned() else {
|
||||
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier {
|
||||
span: mi.span(),
|
||||
});
|
||||
return false;
|
||||
};
|
||||
|
||||
if let [seg, ..] = &mut mi.path.segments[..] {
|
||||
seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
|
||||
}
|
||||
|
||||
res & eval_condition(&MetaItemInner::MetaItem(mi), sess, features, eval)
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
dcx.emit_err(session_diagnostics::InvalidPredicate {
|
||||
span: cfg.span,
|
||||
predicate: pprust::path_to_string(&cfg.path),
|
||||
});
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
|
||||
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
|
||||
true
|
||||
}
|
||||
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: lit.span,
|
||||
reason: UnsupportedLiteralReason::CfgString,
|
||||
is_bytestr: lit.kind.is_bytestr(),
|
||||
start_point_span: sess.source_map().start_point(lit.span),
|
||||
});
|
||||
true
|
||||
}
|
||||
MetaItemKind::Word | MetaItemKind::NameValue(..) => {
|
||||
let ident = cfg.ident().expect("multi-segment cfg predicate");
|
||||
eval(Condition {
|
||||
name: ident.name,
|
||||
name_span: ident.span,
|
||||
value: cfg.value_str(),
|
||||
value_span: cfg.name_value_literal_span(),
|
||||
span: cfg.span,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_attr_data_structures::{AttributeKind, OptimizeAttr, UsedBy};
|
||||
use rustc_attr_data_structures::{AttributeKind, CoverageStatus, OptimizeAttr, UsedBy};
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
|
@ -15,7 +15,7 @@ pub(crate) struct OptimizeParser;
|
|||
|
||||
impl<S: Stage> SingleAttributeParser<S> for OptimizeParser {
|
||||
const PATH: &[Symbol] = &[sym::optimize];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "size|speed|none");
|
||||
|
||||
|
|
@ -52,11 +52,50 @@ impl<S: Stage> NoArgsAttributeParser<S> for ColdParser {
|
|||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Cold;
|
||||
}
|
||||
|
||||
pub(crate) struct CoverageParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
|
||||
const PATH: &[Symbol] = &[sym::coverage];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::off, sym::on]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(args) = args.list() else {
|
||||
cx.expected_specific_argument_and_list(cx.attr_span, vec!["on", "off"]);
|
||||
return None;
|
||||
};
|
||||
|
||||
let Some(arg) = args.single() else {
|
||||
cx.expected_single_argument(args.span);
|
||||
return None;
|
||||
};
|
||||
|
||||
let fail_incorrect_argument = |span| cx.expected_specific_argument(span, vec!["on", "off"]);
|
||||
|
||||
let Some(arg) = arg.meta_item() else {
|
||||
fail_incorrect_argument(args.span);
|
||||
return None;
|
||||
};
|
||||
|
||||
let status = match arg.path().word_sym() {
|
||||
Some(sym::off) => CoverageStatus::Off,
|
||||
Some(sym::on) => CoverageStatus::On,
|
||||
None | Some(_) => {
|
||||
fail_incorrect_argument(arg.span());
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
Some(AttributeKind::Coverage(cx.attr_span, status))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ExportNameParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::export_name];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
|
||||
|
||||
|
|
@ -138,7 +177,8 @@ impl<S: Stage> AttributeParser<S> for NakedParser {
|
|||
sym::instruction_set,
|
||||
sym::repr,
|
||||
sym::rustc_std_internal_symbol,
|
||||
sym::align,
|
||||
// FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
|
||||
sym::rustc_align,
|
||||
// obviously compatible with self
|
||||
sym::naked,
|
||||
// documentation
|
||||
|
|
@ -334,3 +374,11 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
|
|||
features
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct OmitGdbPrettyPrinterSectionParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for OmitGdbPrettyPrinterSectionParser {
|
||||
const PATH: &[Symbol] = &[sym::omit_gdb_pretty_printer_section];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::OmitGdbPrettyPrinterSection;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ fn get<S: Stage>(
|
|||
|
||||
impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
|
||||
const PATH: &[Symbol] = &[sym::deprecated];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
Word,
|
||||
|
|
|
|||
19
compiler/rustc_attr_parsing/src/attributes/dummy.rs
Normal file
19
compiler/rustc_attr_parsing/src/attributes/dummy.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::parser::ArgParser;
|
||||
|
||||
pub(crate) struct DummyParser;
|
||||
impl<S: Stage> SingleAttributeParser<S> for DummyParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dummy];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really
|
||||
|
||||
fn convert(_: &mut AcceptContext<'_, '_, S>, _: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
Some(AttributeKind::Dummy)
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ pub(crate) struct InlineParser;
|
|||
|
||||
impl<S: Stage> SingleAttributeParser<S> for InlineParser {
|
||||
const PATH: &'static [Symbol] = &[sym::inline];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: "always|never");
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ pub(crate) struct RustcForceInlineParser;
|
|||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_force_inline];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: "reason", NameValueStr: "reason");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_attr_data_structures::AttributeKind::{LinkName, LinkSection};
|
||||
use rustc_attr_data_structures::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::attributes::{
|
||||
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
|
||||
};
|
||||
use crate::context::{AcceptContext, Stage, parse_single_integer};
|
||||
use crate::parser::ArgParser;
|
||||
use crate::session_diagnostics::NullOnLinkSection;
|
||||
use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection};
|
||||
|
||||
pub(crate) struct LinkNameParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
|
||||
const PATH: &[Symbol] = &[sym::link_name];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
|
||||
|
||||
|
|
@ -34,7 +36,7 @@ pub(crate) struct LinkSectionParser;
|
|||
|
||||
impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
|
||||
const PATH: &[Symbol] = &[sym::link_section];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
|
||||
|
||||
|
|
@ -57,3 +59,64 @@ impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
|
|||
Some(LinkSection { name, span: cx.attr_span })
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ExportStableParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for ExportStableParser {
|
||||
const PATH: &[Symbol] = &[sym::export_stable];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ExportStable;
|
||||
}
|
||||
|
||||
pub(crate) struct FfiConstParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for FfiConstParser {
|
||||
const PATH: &[Symbol] = &[sym::ffi_const];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiConst;
|
||||
}
|
||||
|
||||
pub(crate) struct FfiPureParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for FfiPureParser {
|
||||
const PATH: &[Symbol] = &[sym::ffi_pure];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;
|
||||
}
|
||||
|
||||
pub(crate) struct StdInternalSymbolParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for StdInternalSymbolParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_std_internal_symbol];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::StdInternalSymbol;
|
||||
}
|
||||
|
||||
pub(crate) struct LinkOrdinalParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
|
||||
const PATH: &[Symbol] = &[sym::link_ordinal];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "ordinal");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let ordinal = parse_single_integer(cx, args)?;
|
||||
|
||||
// According to the table at
|
||||
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header, the
|
||||
// ordinal must fit into 16 bits. Similarly, the Ordinal field in COFFShortExport (defined
|
||||
// in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import
|
||||
// information to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t.
|
||||
//
|
||||
// FIXME: should we allow an ordinal of 0? The MSVC toolchain has inconsistent support for
|
||||
// this: both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that
|
||||
// specifies a zero ordinal. However, llvm-dlltool is perfectly happy to generate an import
|
||||
// library for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an
|
||||
// import library produced by LLVM with an ordinal of 0, and it generates an .EXE. (I
|
||||
// don't know yet if the resulting EXE runs, as I haven't yet built the necessary DLL --
|
||||
// see earlier comment about LINK.EXE failing.)
|
||||
let Ok(ordinal) = ordinal.try_into() else {
|
||||
cx.emit_err(LinkOrdinalOutOfRange { span: cx.attr_span, ordinal });
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(LinkOrdinal { ordinal, span: cx.attr_span })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,3 +24,10 @@ impl<S: Stage> NoArgsAttributeParser<S> for PassByValueParser {
|
|||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::PassByValue;
|
||||
}
|
||||
|
||||
pub(crate) struct AutomaticallyDerivedParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for AutomaticallyDerivedParser {
|
||||
const PATH: &[Symbol] = &[sym::automatically_derived];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::AutomaticallyDerived;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@ use crate::session_diagnostics::UnusedMultiple;
|
|||
|
||||
pub(crate) mod allow_unstable;
|
||||
pub(crate) mod cfg;
|
||||
pub(crate) mod cfg_old;
|
||||
pub(crate) mod codegen_attrs;
|
||||
pub(crate) mod confusables;
|
||||
pub(crate) mod deprecation;
|
||||
pub(crate) mod dummy;
|
||||
pub(crate) mod inline;
|
||||
pub(crate) mod link_attrs;
|
||||
pub(crate) mod lint_helpers;
|
||||
|
|
@ -139,7 +141,7 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
|
|||
if let Some(pa) = T::convert(cx, args) {
|
||||
match T::ATTRIBUTE_ORDER {
|
||||
// keep the first and report immediately. ignore this attribute
|
||||
AttributeOrder::KeepFirst => {
|
||||
AttributeOrder::KeepInnermost => {
|
||||
if let Some((_, unused)) = group.1 {
|
||||
T::ON_DUPLICATE.exec::<T>(cx, cx.attr_span, unused);
|
||||
return;
|
||||
|
|
@ -147,7 +149,7 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
|
|||
}
|
||||
// keep the new one and warn about the previous,
|
||||
// then replace
|
||||
AttributeOrder::KeepLast => {
|
||||
AttributeOrder::KeepOutermost => {
|
||||
if let Some((_, used)) = group.1 {
|
||||
T::ON_DUPLICATE.exec::<T>(cx, used, cx.attr_span);
|
||||
}
|
||||
|
|
@ -164,9 +166,6 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(jdonszelmann): logic is implemented but the attribute parsers needing
|
||||
// them will be merged in another PR
|
||||
#[allow(unused)]
|
||||
pub(crate) enum OnDuplicate<S: Stage> {
|
||||
/// Give a default warning
|
||||
Warn,
|
||||
|
|
@ -212,25 +211,29 @@ impl<S: Stage> OnDuplicate<S> {
|
|||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// FIXME(jdonszelmann): logic is implemented but the attribute parsers needing
|
||||
// them will be merged in another PR
|
||||
#[allow(unused)]
|
||||
pub(crate) enum AttributeOrder {
|
||||
/// Duplicates after the first attribute will be an error.
|
||||
///
|
||||
/// This should be used where duplicates would be ignored, but carry extra
|
||||
/// meaning that could cause confusion. For example, `#[stable(since="1.0")]
|
||||
/// #[stable(since="2.0")]`, which version should be used for `stable`?
|
||||
KeepFirst,
|
||||
|
||||
/// Duplicates preceding the last instance of the attribute will be a
|
||||
/// warning, with a note that this will be an error in the future.
|
||||
pub(crate) enum AttributeOrder {
|
||||
/// Duplicates after the innermost instance of the attribute will be an error/warning.
|
||||
/// Only keep the lowest attribute.
|
||||
///
|
||||
/// This is the same as `FutureWarnFollowing`, except the last attribute is
|
||||
/// the one that is "used". Ideally these can eventually migrate to
|
||||
/// `ErrorPreceding`.
|
||||
KeepLast,
|
||||
/// Attributes are processed from bottom to top, so this raises a warning/error on all the attributes
|
||||
/// further above the lowest one:
|
||||
/// ```
|
||||
/// #[stable(since="1.0")] //~ WARNING duplicated attribute
|
||||
/// #[stable(since="2.0")]
|
||||
/// ```
|
||||
KeepInnermost,
|
||||
|
||||
/// Duplicates before the outermost instance of the attribute will be an error/warning.
|
||||
/// Only keep the highest attribute.
|
||||
///
|
||||
/// Attributes are processed from bottom to top, so this raises a warning/error on all the attributes
|
||||
/// below the highest one:
|
||||
/// ```
|
||||
/// #[path="foo.rs"]
|
||||
/// #[path="bar.rs"] //~ WARNING duplicated attribute
|
||||
/// ```
|
||||
KeepOutermost,
|
||||
}
|
||||
|
||||
/// An even simpler version of [`SingleAttributeParser`]:
|
||||
|
|
@ -256,7 +259,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> Default for WithoutArgs<T, S> {
|
|||
|
||||
impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for WithoutArgs<T, S> {
|
||||
const PATH: &[Symbol] = T::PATH;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub(crate) struct MustUseParser;
|
|||
|
||||
impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
|
||||
const PATH: &[Symbol] = &[sym::must_use];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason");
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ pub(crate) struct PathParser;
|
|||
|
||||
impl<S: Stage> SingleAttributeParser<S> for PathParser {
|
||||
const PATH: &[Symbol] = &[sym::path];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "file");
|
||||
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ fn parse_alignment(node: &LitKind) -> Result<Align, &'static str> {
|
|||
pub(crate) struct AlignParser(Option<(Align, Span)>);
|
||||
|
||||
impl AlignParser {
|
||||
const PATH: &'static [Symbol] = &[sym::align];
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_align];
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "<alignment in bytes>");
|
||||
|
||||
fn parse<'c, S: Stage>(
|
||||
|
|
|
|||
|
|
@ -1,23 +1,22 @@
|
|||
use rustc_ast::LitKind;
|
||||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::context::{AcceptContext, Stage, parse_single_integer};
|
||||
use crate::parser::ArgParser;
|
||||
|
||||
pub(crate) struct RustcLayoutScalarValidRangeStart;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStart {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_start];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "start");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
parse_rustc_layout_scalar_valid_range(cx, args)
|
||||
.map(|n| AttributeKind::RustcLayoutScalarValidRangeStart(n, cx.attr_span))
|
||||
parse_single_integer(cx, args)
|
||||
.map(|n| AttributeKind::RustcLayoutScalarValidRangeStart(Box::new(n), cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -25,44 +24,21 @@ pub(crate) struct RustcLayoutScalarValidRangeEnd;
|
|||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEnd {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_end];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "end");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
parse_rustc_layout_scalar_valid_range(cx, args)
|
||||
.map(|n| AttributeKind::RustcLayoutScalarValidRangeEnd(n, cx.attr_span))
|
||||
parse_single_integer(cx, args)
|
||||
.map(|n| AttributeKind::RustcLayoutScalarValidRangeEnd(Box::new(n), cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_rustc_layout_scalar_valid_range<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser<'_>,
|
||||
) -> Option<Box<u128>> {
|
||||
let Some(list) = args.list() else {
|
||||
cx.expected_list(cx.attr_span);
|
||||
return None;
|
||||
};
|
||||
let Some(single) = list.single() else {
|
||||
cx.expected_single_argument(list.span);
|
||||
return None;
|
||||
};
|
||||
let Some(lit) = single.lit() else {
|
||||
cx.expected_integer_literal(single.span());
|
||||
return None;
|
||||
};
|
||||
let LitKind::Int(num, _ty) = lit.kind else {
|
||||
cx.expected_integer_literal(single.span());
|
||||
return None;
|
||||
};
|
||||
Some(Box::new(num.0))
|
||||
}
|
||||
|
||||
pub(crate) struct RustcObjectLifetimeDefaultParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcObjectLifetimeDefaultParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::rustc_object_lifetime_default];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,16 @@ impl<S: Stage> AttributeParser<S> for StabilityParser {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some((Stability { level: StabilityLevel::Stable { .. }, .. }, _)) = self.stability {
|
||||
for other_attr in cx.all_attrs {
|
||||
if other_attr.word_is(sym::unstable_feature_bound) {
|
||||
cx.emit_err(session_diagnostics::UnstableFeatureBoundIncompatibleStability {
|
||||
span: cx.target_span,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (stability, span) = self.stability?;
|
||||
|
||||
Some(AttributeKind::Stability { stability, span })
|
||||
|
|
@ -282,12 +292,12 @@ pub(crate) fn parse_stability<S: Stage>(
|
|||
} else if let Some(version) = parse_version(since) {
|
||||
StableSince::Version(version)
|
||||
} else {
|
||||
cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
|
||||
StableSince::Err
|
||||
let err = cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
|
||||
StableSince::Err(err)
|
||||
}
|
||||
} else {
|
||||
cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
|
||||
StableSince::Err
|
||||
let err = cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
|
||||
StableSince::Err(err)
|
||||
};
|
||||
|
||||
match feature {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ pub(crate) struct IgnoreParser;
|
|||
|
||||
impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
|
||||
const PATH: &[Symbol] = &[sym::ignore];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason");
|
||||
|
||||
|
|
|
|||
|
|
@ -2,17 +2,18 @@ use core::mem;
|
|||
|
||||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
|
||||
use crate::attributes::{
|
||||
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
|
||||
};
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::parser::ArgParser;
|
||||
|
||||
pub(crate) struct SkipDuringMethodDispatchParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "array, boxed_slice");
|
||||
|
|
@ -52,3 +53,103 @@ impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
|
|||
Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span })
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ParenSugarParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for ParenSugarParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_paren_sugar];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ParenSugar;
|
||||
}
|
||||
|
||||
pub(crate) struct TypeConstParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for TypeConstParser {
|
||||
const PATH: &[Symbol] = &[sym::type_const];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst;
|
||||
}
|
||||
|
||||
// Markers
|
||||
|
||||
pub(crate) struct MarkerParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for MarkerParser {
|
||||
const PATH: &[Symbol] = &[sym::marker];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Marker;
|
||||
}
|
||||
|
||||
pub(crate) struct DenyExplicitImplParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for DenyExplicitImplParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DenyExplicitImpl;
|
||||
}
|
||||
|
||||
pub(crate) struct DoNotImplementViaObjectParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_do_not_implement_via_object];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject;
|
||||
}
|
||||
|
||||
// FIXME(const_trait_impl): remove this
|
||||
// Const traits
|
||||
|
||||
pub(crate) struct ConstTraitParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for ConstTraitParser {
|
||||
const PATH: &[Symbol] = &[sym::const_trait];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstTrait;
|
||||
}
|
||||
|
||||
// Specialization
|
||||
|
||||
pub(crate) struct SpecializationTraitParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for SpecializationTraitParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_specialization_trait];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::SpecializationTrait;
|
||||
}
|
||||
|
||||
pub(crate) struct UnsafeSpecializationMarkerParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for UnsafeSpecializationMarkerParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::UnsafeSpecializationMarker;
|
||||
}
|
||||
|
||||
// Coherence
|
||||
|
||||
pub(crate) struct CoinductiveParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for CoinductiveParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_coinductive];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Coinductive;
|
||||
}
|
||||
|
||||
pub(crate) struct AllowIncoherentImplParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for AllowIncoherentImplParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
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 CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
|
||||
}
|
||||
|
||||
pub(crate) struct FundamentalParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
|
||||
const PATH: &[Symbol] = &[sym::fundamental];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental;
|
||||
}
|
||||
|
||||
pub(crate) struct PointeeParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for PointeeParser {
|
||||
const PATH: &[Symbol] = &[sym::pointee];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Pointee;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ pub(crate) struct TransparencyParser;
|
|||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
impl<S: Stage> SingleAttributeParser<S> for TransparencyParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_macro_transparency];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Custom(|cx, used, unused| {
|
||||
cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use private::Sealed;
|
||||
use rustc_ast::{self as ast, MetaItemLit, NodeId};
|
||||
use rustc_ast::{self as ast, LitKind, MetaItemLit, NodeId};
|
||||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_attr_data_structures::lints::{AttributeLint, AttributeLintKind};
|
||||
use rustc_errors::{DiagCtxtHandle, Diagnostic};
|
||||
|
|
@ -14,16 +13,25 @@ use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirI
|
|||
use rustc_session::Session;
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
|
||||
|
||||
use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser};
|
||||
use crate::attributes::allow_unstable::{
|
||||
AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
|
||||
};
|
||||
use crate::attributes::codegen_attrs::{
|
||||
ColdParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser, TargetFeatureParser,
|
||||
TrackCallerParser, UsedParser,
|
||||
ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser,
|
||||
OmitGdbPrettyPrinterSectionParser, OptimizeParser, TargetFeatureParser, TrackCallerParser,
|
||||
UsedParser,
|
||||
};
|
||||
use crate::attributes::confusables::ConfusablesParser;
|
||||
use crate::attributes::deprecation::DeprecationParser;
|
||||
use crate::attributes::dummy::DummyParser;
|
||||
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
|
||||
use crate::attributes::link_attrs::{LinkNameParser, LinkSectionParser};
|
||||
use crate::attributes::lint_helpers::{AsPtrParser, PassByValueParser, PubTransparentParser};
|
||||
use crate::attributes::link_attrs::{
|
||||
ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
|
||||
LinkSectionParser, StdInternalSymbolParser,
|
||||
};
|
||||
use crate::attributes::lint_helpers::{
|
||||
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
|
||||
};
|
||||
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
|
||||
use crate::attributes::must_use::MustUseParser;
|
||||
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
|
||||
|
|
@ -39,7 +47,12 @@ use crate::attributes::stability::{
|
|||
BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
|
||||
};
|
||||
use crate::attributes::test_attrs::IgnoreParser;
|
||||
use crate::attributes::traits::SkipDuringMethodDispatchParser;
|
||||
use crate::attributes::traits::{
|
||||
AllowIncoherentImplParser, CoherenceIsCoreParser, 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};
|
||||
use crate::parser::{ArgParser, MetaItemParser, PathParser};
|
||||
|
|
@ -123,14 +136,18 @@ attribute_parsers!(
|
|||
Combine<AllowInternalUnstableParser>,
|
||||
Combine<ReprParser>,
|
||||
Combine<TargetFeatureParser>,
|
||||
Combine<UnstableFeatureBoundParser>,
|
||||
// tidy-alphabetical-end
|
||||
|
||||
// tidy-alphabetical-start
|
||||
Single<CoverageParser>,
|
||||
Single<DeprecationParser>,
|
||||
Single<DummyParser>,
|
||||
Single<ExportNameParser>,
|
||||
Single<IgnoreParser>,
|
||||
Single<InlineParser>,
|
||||
Single<LinkNameParser>,
|
||||
Single<LinkOrdinalParser>,
|
||||
Single<LinkSectionParser>,
|
||||
Single<MustUseParser>,
|
||||
Single<OptimizeParser>,
|
||||
|
|
@ -141,18 +158,37 @@ attribute_parsers!(
|
|||
Single<RustcObjectLifetimeDefaultParser>,
|
||||
Single<SkipDuringMethodDispatchParser>,
|
||||
Single<TransparencyParser>,
|
||||
Single<WithoutArgs<AllowIncoherentImplParser>>,
|
||||
Single<WithoutArgs<AsPtrParser>>,
|
||||
Single<WithoutArgs<AutomaticallyDerivedParser>>,
|
||||
Single<WithoutArgs<CoherenceIsCoreParser>>,
|
||||
Single<WithoutArgs<CoinductiveParser>>,
|
||||
Single<WithoutArgs<ColdParser>>,
|
||||
Single<WithoutArgs<ConstContinueParser>>,
|
||||
Single<WithoutArgs<ConstStabilityIndirectParser>>,
|
||||
Single<WithoutArgs<ConstTraitParser>>,
|
||||
Single<WithoutArgs<DenyExplicitImplParser>>,
|
||||
Single<WithoutArgs<DoNotImplementViaObjectParser>>,
|
||||
Single<WithoutArgs<ExportStableParser>>,
|
||||
Single<WithoutArgs<FfiConstParser>>,
|
||||
Single<WithoutArgs<FfiPureParser>>,
|
||||
Single<WithoutArgs<FundamentalParser>>,
|
||||
Single<WithoutArgs<LoopMatchParser>>,
|
||||
Single<WithoutArgs<MarkerParser>>,
|
||||
Single<WithoutArgs<MayDangleParser>>,
|
||||
Single<WithoutArgs<NoImplicitPreludeParser>>,
|
||||
Single<WithoutArgs<NoMangleParser>>,
|
||||
Single<WithoutArgs<NonExhaustiveParser>>,
|
||||
Single<WithoutArgs<OmitGdbPrettyPrinterSectionParser>>,
|
||||
Single<WithoutArgs<ParenSugarParser>>,
|
||||
Single<WithoutArgs<PassByValueParser>>,
|
||||
Single<WithoutArgs<PointeeParser>>,
|
||||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<SpecializationTraitParser>>,
|
||||
Single<WithoutArgs<StdInternalSymbolParser>>,
|
||||
Single<WithoutArgs<TrackCallerParser>>,
|
||||
Single<WithoutArgs<TypeConstParser>>,
|
||||
Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
|
||||
// tidy-alphabetical-end
|
||||
];
|
||||
);
|
||||
|
|
@ -171,7 +207,11 @@ pub trait Stage: Sized + 'static + Sealed {
|
|||
|
||||
fn parsers() -> &'static group_type!(Self);
|
||||
|
||||
fn emit_err<'sess>(sess: &'sess Session, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed;
|
||||
fn emit_err<'sess>(
|
||||
&self,
|
||||
sess: &'sess Session,
|
||||
diag: impl for<'x> Diagnostic<'x>,
|
||||
) -> ErrorGuaranteed;
|
||||
}
|
||||
|
||||
// allow because it's a sealed trait
|
||||
|
|
@ -183,8 +223,16 @@ impl Stage for Early {
|
|||
fn parsers() -> &'static group_type!(Self) {
|
||||
&early::ATTRIBUTE_PARSERS
|
||||
}
|
||||
fn emit_err<'sess>(sess: &'sess Session, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
|
||||
sess.dcx().create_err(diag).delay_as_bug()
|
||||
fn emit_err<'sess>(
|
||||
&self,
|
||||
sess: &'sess Session,
|
||||
diag: impl for<'x> Diagnostic<'x>,
|
||||
) -> ErrorGuaranteed {
|
||||
if self.emit_errors.should_emit() {
|
||||
sess.dcx().emit_err(diag)
|
||||
} else {
|
||||
sess.dcx().create_err(diag).delay_as_bug()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -197,20 +245,29 @@ impl Stage for Late {
|
|||
fn parsers() -> &'static group_type!(Self) {
|
||||
&late::ATTRIBUTE_PARSERS
|
||||
}
|
||||
fn emit_err<'sess>(tcx: &'sess Session, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
|
||||
fn emit_err<'sess>(
|
||||
&self,
|
||||
tcx: &'sess Session,
|
||||
diag: impl for<'x> Diagnostic<'x>,
|
||||
) -> ErrorGuaranteed {
|
||||
tcx.dcx().emit_err(diag)
|
||||
}
|
||||
}
|
||||
|
||||
/// used when parsing attributes for miscellaneous things *before* ast lowering
|
||||
pub struct Early;
|
||||
pub struct Early {
|
||||
/// Whether to emit errors or delay them as a bug
|
||||
/// For most attributes, the attribute will be parsed again in the `Late` stage and in this case the errors should be delayed
|
||||
/// But for some, such as `cfg`, the attribute will be removed before the `Late` stage so errors must be emitted
|
||||
pub emit_errors: ShouldEmit,
|
||||
}
|
||||
/// used when parsing attributes during ast lowering
|
||||
pub struct Late;
|
||||
|
||||
/// Context given to every attribute parser when accepting
|
||||
///
|
||||
/// Gives [`AttributeParser`]s enough information to create errors, for example.
|
||||
pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
|
||||
pub struct AcceptContext<'f, 'sess, S: Stage> {
|
||||
pub(crate) shared: SharedContext<'f, 'sess, S>,
|
||||
/// The span of the attribute currently being parsed
|
||||
pub(crate) attr_span: Span,
|
||||
|
|
@ -226,7 +283,7 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
|
|||
|
||||
impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
|
||||
pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
|
||||
S::emit_err(&self.sess, diag)
|
||||
self.stage.emit_err(&self.sess, diag)
|
||||
}
|
||||
|
||||
/// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing
|
||||
|
|
@ -397,6 +454,25 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: false,
|
||||
list: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn expected_specific_argument_and_list(
|
||||
&self,
|
||||
span: Span,
|
||||
possibilities: Vec<&'static str>,
|
||||
) -> ErrorGuaranteed {
|
||||
self.emit_err(AttributeParseError {
|
||||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: false,
|
||||
list: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -414,6 +490,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: true,
|
||||
list: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -441,7 +518,7 @@ impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
|
|||
///
|
||||
/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
|
||||
/// errors, for example.
|
||||
pub(crate) struct SharedContext<'p, 'sess, S: Stage> {
|
||||
pub struct SharedContext<'p, 'sess, S: Stage> {
|
||||
/// The parse context, gives access to the session and the
|
||||
/// diagnostics context.
|
||||
pub(crate) cx: &'p mut AttributeParser<'sess, S>,
|
||||
|
|
@ -503,13 +580,32 @@ pub enum OmitDoc {
|
|||
Skip,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum ShouldEmit {
|
||||
/// 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`.
|
||||
Nothing,
|
||||
}
|
||||
|
||||
impl ShouldEmit {
|
||||
pub fn should_emit(&self) -> bool {
|
||||
match self {
|
||||
ShouldEmit::ErrorsAndLints => true,
|
||||
ShouldEmit::Nothing => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Context created once, for example as part of the ast lowering
|
||||
/// context, through which all attributes can be lowered.
|
||||
pub struct AttributeParser<'sess, S: Stage = Late> {
|
||||
pub(crate) tools: Vec<Symbol>,
|
||||
features: Option<&'sess Features>,
|
||||
sess: &'sess Session,
|
||||
stage: PhantomData<S>,
|
||||
stage: S,
|
||||
|
||||
/// *Only* parse attributes with this symbol.
|
||||
///
|
||||
|
|
@ -538,13 +634,14 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
sym: Symbol,
|
||||
target_span: Span,
|
||||
target_node_id: NodeId,
|
||||
features: Option<&'sess Features>,
|
||||
) -> Option<Attribute> {
|
||||
let mut p = Self {
|
||||
features: None,
|
||||
features,
|
||||
tools: Vec::new(),
|
||||
parse_only: Some(sym),
|
||||
sess,
|
||||
stage: PhantomData,
|
||||
stage: Early { emit_errors: ShouldEmit::Nothing },
|
||||
};
|
||||
let mut parsed = p.parse_attribute_list(
|
||||
attrs,
|
||||
|
|
@ -560,11 +657,55 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
|
||||
parsed.pop()
|
||||
}
|
||||
|
||||
pub fn parse_single<T>(
|
||||
sess: &'sess Session,
|
||||
attr: &ast::Attribute,
|
||||
target_span: Span,
|
||||
target_node_id: NodeId,
|
||||
features: Option<&'sess Features>,
|
||||
emit_errors: ShouldEmit,
|
||||
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
|
||||
template: &AttributeTemplate,
|
||||
) -> T {
|
||||
let mut parser = Self {
|
||||
features,
|
||||
tools: Vec::new(),
|
||||
parse_only: None,
|
||||
sess,
|
||||
stage: Early { emit_errors },
|
||||
};
|
||||
let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
|
||||
panic!("parse_single called on a doc attr")
|
||||
};
|
||||
let meta_parser = MetaItemParser::from_attr(normal_attr, parser.dcx());
|
||||
let path = meta_parser.path();
|
||||
let args = meta_parser.args();
|
||||
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
|
||||
shared: SharedContext {
|
||||
cx: &mut parser,
|
||||
target_span,
|
||||
target_id: target_node_id,
|
||||
emit_lint: &mut |_lint| {
|
||||
panic!("can't emit lints here for now (nothing uses this atm)");
|
||||
},
|
||||
},
|
||||
attr_span: attr.span,
|
||||
template,
|
||||
attr_path: path.get_attribute_path(),
|
||||
};
|
||||
parse_fn(&mut cx, args)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
||||
pub fn new(sess: &'sess Session, features: &'sess Features, tools: Vec<Symbol>) -> Self {
|
||||
Self { features: Some(features), tools, parse_only: None, sess, stage: PhantomData }
|
||||
pub fn new(
|
||||
sess: &'sess Session,
|
||||
features: &'sess Features,
|
||||
tools: Vec<Symbol>,
|
||||
stage: S,
|
||||
) -> Self {
|
||||
Self { features: Some(features), tools, parse_only: None, sess, stage }
|
||||
}
|
||||
|
||||
pub(crate) fn sess(&self) -> &'sess Session {
|
||||
|
|
@ -575,6 +716,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
self.features.expect("features not available at this point in the compiler")
|
||||
}
|
||||
|
||||
pub(crate) fn features_option(&self) -> Option<&'sess Features> {
|
||||
self.features
|
||||
}
|
||||
|
||||
pub(crate) fn dcx(&self) -> DiagCtxtHandle<'sess> {
|
||||
self.sess().dcx()
|
||||
}
|
||||
|
|
@ -709,6 +854,11 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
attributes
|
||||
}
|
||||
|
||||
/// Returns whether there is a parser for an attribute with this name
|
||||
pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
|
||||
Late::parsers().0.contains_key(path)
|
||||
}
|
||||
|
||||
fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
|
||||
match args {
|
||||
ast::AttrArgs::Empty => AttrArgs::Empty,
|
||||
|
|
@ -741,3 +891,32 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a single integer.
|
||||
///
|
||||
/// Used by attributes that take a single integer as argument, such as
|
||||
/// `#[link_ordinal]` and `#[rustc_layout_scalar_valid_range_start]`.
|
||||
/// `cx` is the context given to the attribute.
|
||||
/// `args` is the parser for the attribute arguments.
|
||||
pub(crate) fn parse_single_integer<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser<'_>,
|
||||
) -> Option<u128> {
|
||||
let Some(list) = args.list() else {
|
||||
cx.expected_list(cx.attr_span);
|
||||
return None;
|
||||
};
|
||||
let Some(single) = list.single() else {
|
||||
cx.expected_single_argument(list.span);
|
||||
return None;
|
||||
};
|
||||
let Some(lit) = single.lit() else {
|
||||
cx.expected_integer_literal(single.span());
|
||||
return None;
|
||||
};
|
||||
let LitKind::Int(num, _ty) = lit.kind else {
|
||||
cx.expected_integer_literal(single.span());
|
||||
return None;
|
||||
};
|
||||
Some(num.0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,11 +90,12 @@ mod lints;
|
|||
pub mod parser;
|
||||
mod session_diagnostics;
|
||||
|
||||
pub use attributes::cfg::*;
|
||||
pub use attributes::cfg::{CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg_attr};
|
||||
pub use attributes::cfg_old::*;
|
||||
pub use attributes::util::{
|
||||
find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version,
|
||||
};
|
||||
pub use context::{AttributeParser, Early, Late, OmitDoc};
|
||||
pub use context::{AttributeParser, Early, Late, OmitDoc, ShouldEmit};
|
||||
pub use lints::emit_attribute_lint;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
|
|
|||
|
|
@ -503,6 +503,14 @@ pub(crate) struct UnrecognizedReprHint {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_unstable_feature_bound_incompatible_stability)]
|
||||
#[help]
|
||||
pub(crate) struct UnstableFeatureBoundIncompatibleStability {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_naked_functions_incompatible_attribute, code = E0736)]
|
||||
pub(crate) struct NakedFunctionIncompatibleAttribute {
|
||||
|
|
@ -514,9 +522,20 @@ pub(crate) struct NakedFunctionIncompatibleAttribute {
|
|||
pub attr: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_link_ordinal_out_of_range)]
|
||||
#[note]
|
||||
pub(crate) struct LinkOrdinalOutOfRange {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub ordinal: u128,
|
||||
}
|
||||
|
||||
pub(crate) enum AttributeParseErrorReason {
|
||||
ExpectedNoArgs,
|
||||
ExpectedStringLiteral { byte_string: Option<Span> },
|
||||
ExpectedStringLiteral {
|
||||
byte_string: Option<Span>,
|
||||
},
|
||||
ExpectedIntegerLiteral,
|
||||
ExpectedAtLeastOneArgument,
|
||||
ExpectedSingleArgument,
|
||||
|
|
@ -524,7 +543,12 @@ pub(crate) enum AttributeParseErrorReason {
|
|||
UnexpectedLiteral,
|
||||
ExpectedNameValue(Option<Symbol>),
|
||||
DuplicateKey(Symbol),
|
||||
ExpectedSpecificArgument { possibilities: Vec<&'static str>, strings: bool },
|
||||
ExpectedSpecificArgument {
|
||||
possibilities: Vec<&'static str>,
|
||||
strings: bool,
|
||||
/// Should we tell the user to write a list when they didn't?
|
||||
list: bool,
|
||||
},
|
||||
}
|
||||
|
||||
pub(crate) struct AttributeParseError {
|
||||
|
|
@ -584,7 +608,13 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
|||
diag.code(E0565);
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedNameValue(None) => {
|
||||
// The suggestion we add below this match already contains enough information
|
||||
// If the span is the entire attribute, the suggestion we add below this match already contains enough information
|
||||
if self.span != self.attr_span {
|
||||
diag.span_label(
|
||||
self.span,
|
||||
format!("expected this to be of the form `... = \"...\"`"),
|
||||
);
|
||||
}
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedNameValue(Some(name)) => {
|
||||
diag.span_label(
|
||||
|
|
@ -592,7 +622,11 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
|||
format!("expected this to be of the form `{name} = \"...\"`"),
|
||||
);
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings } => {
|
||||
AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings,
|
||||
list: false,
|
||||
} => {
|
||||
let quote = if strings { '"' } else { '`' };
|
||||
match possibilities.as_slice() {
|
||||
&[] => {}
|
||||
|
|
@ -618,6 +652,38 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
|||
}
|
||||
}
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings,
|
||||
list: true,
|
||||
} => {
|
||||
let quote = if strings { '"' } else { '`' };
|
||||
match possibilities.as_slice() {
|
||||
&[] => {}
|
||||
&[x] => {
|
||||
diag.span_label(
|
||||
self.span,
|
||||
format!(
|
||||
"this attribute is only valid with {quote}{x}{quote} as an argument"
|
||||
),
|
||||
);
|
||||
}
|
||||
[first, second] => {
|
||||
diag.span_label(self.span, format!("this attribute is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument"));
|
||||
}
|
||||
[first @ .., second_to_last, last] => {
|
||||
let mut res = String::new();
|
||||
for i in first {
|
||||
res.push_str(&format!("{quote}{i}{quote}, "));
|
||||
}
|
||||
res.push_str(&format!(
|
||||
"{quote}{second_to_last}{quote} or {quote}{last}{quote}"
|
||||
));
|
||||
|
||||
diag.span_label(self.span, format!("this attribute is only valid with one of the following arguments: {res}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let suggestions = self.template.suggestions(false, &name);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
//! This file provides API for compiler consumers.
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::{Body, Promoted};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
|
|
@ -17,7 +19,39 @@ pub use super::polonius::legacy::{
|
|||
pub use super::region_infer::RegionInferenceContext;
|
||||
use crate::{BorrowCheckRootCtxt, do_mir_borrowck};
|
||||
|
||||
/// Options determining the output behavior of [`get_body_with_borrowck_facts`].
|
||||
/// Struct used during mir borrowck to collect bodies with facts for a typeck root and all
|
||||
/// its nested bodies.
|
||||
pub(crate) struct BorrowckConsumer<'tcx> {
|
||||
options: ConsumerOptions,
|
||||
bodies: FxHashMap<LocalDefId, BodyWithBorrowckFacts<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> BorrowckConsumer<'tcx> {
|
||||
pub(crate) fn new(options: ConsumerOptions) -> Self {
|
||||
Self { options, bodies: Default::default() }
|
||||
}
|
||||
|
||||
pub(crate) fn insert_body(&mut self, def_id: LocalDefId, body: BodyWithBorrowckFacts<'tcx>) {
|
||||
if self.bodies.insert(def_id, body).is_some() {
|
||||
bug!("unexpected previous body for {def_id:?}");
|
||||
}
|
||||
}
|
||||
|
||||
/// Should the Polonius input facts be computed?
|
||||
pub(crate) fn polonius_input(&self) -> bool {
|
||||
matches!(
|
||||
self.options,
|
||||
ConsumerOptions::PoloniusInputFacts | ConsumerOptions::PoloniusOutputFacts
|
||||
)
|
||||
}
|
||||
|
||||
/// Should we run Polonius and collect the output facts?
|
||||
pub(crate) fn polonius_output(&self) -> bool {
|
||||
matches!(self.options, ConsumerOptions::PoloniusOutputFacts)
|
||||
}
|
||||
}
|
||||
|
||||
/// Options determining the output behavior of [`get_bodies_with_borrowck_facts`].
|
||||
///
|
||||
/// If executing under `-Z polonius` the choice here has no effect, and everything as if
|
||||
/// [`PoloniusOutputFacts`](ConsumerOptions::PoloniusOutputFacts) had been selected
|
||||
|
|
@ -43,17 +77,6 @@ pub enum ConsumerOptions {
|
|||
PoloniusOutputFacts,
|
||||
}
|
||||
|
||||
impl ConsumerOptions {
|
||||
/// Should the Polonius input facts be computed?
|
||||
pub(crate) fn polonius_input(&self) -> bool {
|
||||
matches!(self, Self::PoloniusInputFacts | Self::PoloniusOutputFacts)
|
||||
}
|
||||
/// Should we run Polonius and collect the output facts?
|
||||
pub(crate) fn polonius_output(&self) -> bool {
|
||||
matches!(self, Self::PoloniusOutputFacts)
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Body` with information computed by the borrow checker. This struct is
|
||||
/// intended to be consumed by compiler consumers.
|
||||
///
|
||||
|
|
@ -82,25 +105,35 @@ pub struct BodyWithBorrowckFacts<'tcx> {
|
|||
pub output_facts: Option<Box<PoloniusOutput>>,
|
||||
}
|
||||
|
||||
/// This function computes borrowck facts for the given body. The [`ConsumerOptions`]
|
||||
/// determine which facts are returned. This function makes a copy of the body because
|
||||
/// it needs to regenerate the region identifiers. It should never be invoked during a
|
||||
/// typical compilation session due to the unnecessary overhead of returning
|
||||
/// [`BodyWithBorrowckFacts`].
|
||||
/// This function computes borrowck facts for the given def id and all its nested bodies.
|
||||
/// It must be called with a typeck root which will then borrowck all nested bodies as well.
|
||||
/// The [`ConsumerOptions`] determine which facts are returned. This function makes a copy
|
||||
/// of the bodies because it needs to regenerate the region identifiers. It should never be
|
||||
/// invoked during a typical compilation session due to the unnecessary overhead of
|
||||
/// returning [`BodyWithBorrowckFacts`].
|
||||
///
|
||||
/// Note:
|
||||
/// * This function will panic if the required body was already stolen. This
|
||||
/// * This function will panic if the required bodies were already stolen. This
|
||||
/// can, for example, happen when requesting a body of a `const` function
|
||||
/// because they are evaluated during typechecking. The panic can be avoided
|
||||
/// by overriding the `mir_borrowck` query. You can find a complete example
|
||||
/// that shows how to do this at `tests/run-make/obtain-borrowck/`.
|
||||
/// that shows how to do this at `tests/ui-fulldeps/obtain-borrowck.rs`.
|
||||
///
|
||||
/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
|
||||
pub fn get_body_with_borrowck_facts(
|
||||
pub fn get_bodies_with_borrowck_facts(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: LocalDefId,
|
||||
root_def_id: LocalDefId,
|
||||
options: ConsumerOptions,
|
||||
) -> BodyWithBorrowckFacts<'_> {
|
||||
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def_id);
|
||||
*do_mir_borrowck(&mut root_cx, def_id, Some(options)).1.unwrap()
|
||||
) -> FxHashMap<LocalDefId, BodyWithBorrowckFacts<'_>> {
|
||||
let mut root_cx =
|
||||
BorrowCheckRootCtxt::new(tcx, root_def_id, Some(BorrowckConsumer::new(options)));
|
||||
|
||||
// See comment in `rustc_borrowck::mir_borrowck`
|
||||
let nested_bodies = tcx.nested_bodies_within(root_def_id);
|
||||
for def_id in nested_bodies {
|
||||
root_cx.get_or_insert_nested(def_id);
|
||||
}
|
||||
|
||||
do_mir_borrowck(&mut root_cx, root_def_id);
|
||||
root_cx.consumer.unwrap().bodies
|
||||
}
|
||||
|
|
|
|||
|
|
@ -303,10 +303,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn has_ambiguous_copy(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
let Some(copy_trait_def) = self.infcx.tcx.lang_items().copy_trait() else { return false };
|
||||
// This is only going to be ambiguous if there are incoherent impls, because otherwise
|
||||
// ambiguity should never happen in MIR.
|
||||
self.infcx.type_implements_trait(copy_trait_def, [ty], self.infcx.param_env).may_apply()
|
||||
let Some(copy_def_id) = self.infcx.tcx.lang_items().copy_trait() else { return false };
|
||||
|
||||
// Avoid bogus move errors because of an incoherent `Copy` impl.
|
||||
self.infcx.type_implements_trait(copy_def_id, [ty], self.infcx.param_env).may_apply()
|
||||
&& self.infcx.tcx.coherent_trait(copy_def_id).is_err()
|
||||
}
|
||||
|
||||
fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> {
|
||||
|
|
|
|||
|
|
@ -681,46 +681,30 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
return (false, false, None);
|
||||
}
|
||||
let my_def = self.body.source.def_id();
|
||||
let my_hir = self.infcx.tcx.local_def_id_to_hir_id(my_def.as_local().unwrap());
|
||||
let Some(td) =
|
||||
self.infcx.tcx.impl_of_method(my_def).and_then(|x| self.infcx.tcx.trait_id_of_impl(x))
|
||||
else {
|
||||
return (false, false, None);
|
||||
};
|
||||
|
||||
let implemented_trait_item = self.infcx.tcx.associated_item(my_def).trait_item_def_id;
|
||||
|
||||
(
|
||||
true,
|
||||
td.is_local(),
|
||||
td.as_local().and_then(|tld| match self.infcx.tcx.hir_node_by_def_id(tld) {
|
||||
Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Trait(_, _, _, _, _, items), ..
|
||||
}) => {
|
||||
let mut f_in_trait_opt = None;
|
||||
for hir::TraitItemRef { id: fi, kind: k, .. } in *items {
|
||||
let hi = fi.hir_id();
|
||||
if !matches!(k, hir::AssocItemKind::Fn { .. }) {
|
||||
continue;
|
||||
}
|
||||
if self.infcx.tcx.hir_name(hi) != self.infcx.tcx.hir_name(my_hir) {
|
||||
continue;
|
||||
}
|
||||
f_in_trait_opt = Some(hi);
|
||||
break;
|
||||
}
|
||||
f_in_trait_opt.and_then(|f_in_trait| {
|
||||
if let Node::TraitItem(ti) = self.infcx.tcx.hir_node(f_in_trait)
|
||||
&& let hir::TraitItemKind::Fn(sig, _) = ti.kind
|
||||
&& let Some(ty) = sig.decl.inputs.get(local.index() - 1)
|
||||
&& let hir::TyKind::Ref(_, mut_ty) = ty.kind
|
||||
&& let hir::Mutability::Not = mut_ty.mutbl
|
||||
&& sig.decl.implicit_self.has_implicit_self()
|
||||
{
|
||||
Some(ty.span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
implemented_trait_item.and_then(|f_in_trait| {
|
||||
let f_in_trait = f_in_trait.as_local()?;
|
||||
if let Node::TraitItem(ti) = self.infcx.tcx.hir_node_by_def_id(f_in_trait)
|
||||
&& let hir::TraitItemKind::Fn(sig, _) = ti.kind
|
||||
&& let Some(ty) = sig.decl.inputs.get(local.index() - 1)
|
||||
&& let hir::TyKind::Ref(_, mut_ty) = ty.kind
|
||||
&& let hir::Mutability::Not = mut_ty.mutbl
|
||||
&& sig.decl.implicit_self.has_implicit_self()
|
||||
{
|
||||
Some(ty.span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ use smallvec::SmallVec;
|
|||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::borrow_set::{BorrowData, BorrowSet};
|
||||
use crate::consumers::{BodyWithBorrowckFacts, ConsumerOptions};
|
||||
use crate::consumers::BodyWithBorrowckFacts;
|
||||
use crate::dataflow::{BorrowIndex, Borrowck, BorrowckDomain, Borrows};
|
||||
use crate::diagnostics::{
|
||||
AccessKind, BorrowckDiagnosticsBuffer, IllegalMoveOriginKind, MoveError, RegionName,
|
||||
|
|
@ -124,7 +124,7 @@ fn mir_borrowck(
|
|||
let opaque_types = ConcreteOpaqueTypes(Default::default());
|
||||
Ok(tcx.arena.alloc(opaque_types))
|
||||
} else {
|
||||
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def);
|
||||
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def, None);
|
||||
// We need to manually borrowck all nested bodies from the HIR as
|
||||
// we do not generate MIR for dead code. Not doing so causes us to
|
||||
// never check closures in dead code.
|
||||
|
|
@ -134,7 +134,7 @@ fn mir_borrowck(
|
|||
}
|
||||
|
||||
let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
|
||||
do_mir_borrowck(&mut root_cx, def, None).0;
|
||||
do_mir_borrowck(&mut root_cx, def);
|
||||
debug_assert!(closure_requirements.is_none());
|
||||
debug_assert!(used_mut_upvars.is_empty());
|
||||
root_cx.finalize()
|
||||
|
|
@ -289,17 +289,12 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
|
|||
|
||||
/// Perform the actual borrow checking.
|
||||
///
|
||||
/// Use `consumer_options: None` for the default behavior of returning
|
||||
/// [`PropagatedBorrowCheckResults`] only. Otherwise, return [`BodyWithBorrowckFacts`]
|
||||
/// according to the given [`ConsumerOptions`].
|
||||
///
|
||||
/// For nested bodies this should only be called through `root_cx.get_or_insert_nested`.
|
||||
#[instrument(skip(root_cx), level = "debug")]
|
||||
fn do_mir_borrowck<'tcx>(
|
||||
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
|
||||
def: LocalDefId,
|
||||
consumer_options: Option<ConsumerOptions>,
|
||||
) -> (PropagatedBorrowCheckResults<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
|
||||
) -> PropagatedBorrowCheckResults<'tcx> {
|
||||
let tcx = root_cx.tcx;
|
||||
let infcx = BorrowckInferCtxt::new(tcx, def);
|
||||
let (input_body, promoted) = tcx.mir_promoted(def);
|
||||
|
|
@ -343,7 +338,6 @@ fn do_mir_borrowck<'tcx>(
|
|||
&location_table,
|
||||
&move_data,
|
||||
&borrow_set,
|
||||
consumer_options,
|
||||
);
|
||||
|
||||
// Dump MIR results into a file, if that is enabled. This lets us
|
||||
|
|
@ -483,23 +477,24 @@ fn do_mir_borrowck<'tcx>(
|
|||
used_mut_upvars: mbcx.used_mut_upvars,
|
||||
};
|
||||
|
||||
let body_with_facts = if consumer_options.is_some() {
|
||||
Some(Box::new(BodyWithBorrowckFacts {
|
||||
body: body_owned,
|
||||
promoted,
|
||||
borrow_set,
|
||||
region_inference_context: regioncx,
|
||||
location_table: polonius_input.as_ref().map(|_| location_table),
|
||||
input_facts: polonius_input,
|
||||
output_facts: polonius_output,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(consumer) = &mut root_cx.consumer {
|
||||
consumer.insert_body(
|
||||
def,
|
||||
BodyWithBorrowckFacts {
|
||||
body: body_owned,
|
||||
promoted,
|
||||
borrow_set,
|
||||
region_inference_context: regioncx,
|
||||
location_table: polonius_input.as_ref().map(|_| location_table),
|
||||
input_facts: polonius_input,
|
||||
output_facts: polonius_output,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
debug!("do_mir_borrowck: result = {:#?}", result);
|
||||
|
||||
(result, body_with_facts)
|
||||
result
|
||||
}
|
||||
|
||||
fn get_flow_results<'a, 'tcx>(
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ use rustc_span::sym;
|
|||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::borrow_set::BorrowSet;
|
||||
use crate::consumers::ConsumerOptions;
|
||||
use crate::diagnostics::RegionErrors;
|
||||
use crate::handle_placeholders::compute_sccs_applying_placeholder_outlives_constraints;
|
||||
use crate::polonius::PoloniusDiagnosticsContext;
|
||||
|
|
@ -83,12 +82,11 @@ pub(crate) fn compute_regions<'tcx>(
|
|||
location_table: &PoloniusLocationTable,
|
||||
move_data: &MoveData<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
consumer_options: Option<ConsumerOptions>,
|
||||
) -> NllOutput<'tcx> {
|
||||
let is_polonius_legacy_enabled = infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled();
|
||||
let polonius_input = consumer_options.map(|c| c.polonius_input()).unwrap_or_default()
|
||||
let polonius_input = root_cx.consumer.as_ref().map_or(false, |c| c.polonius_input())
|
||||
|| is_polonius_legacy_enabled;
|
||||
let polonius_output = consumer_options.map(|c| c.polonius_output()).unwrap_or_default()
|
||||
let polonius_output = root_cx.consumer.as_ref().map_or(false, |c| c.polonius_output())
|
||||
|| is_polonius_legacy_enabled;
|
||||
let mut polonius_facts =
|
||||
(polonius_input || PoloniusFacts::enabled(infcx.tcx)).then_some(PoloniusFacts::default());
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt, TypeVisitableExt};
|
|||
use rustc_span::ErrorGuaranteed;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::consumers::BorrowckConsumer;
|
||||
use crate::{ClosureRegionRequirements, ConcreteOpaqueTypes, PropagatedBorrowCheckResults};
|
||||
|
||||
/// The shared context used by both the root as well as all its nested
|
||||
|
|
@ -16,16 +17,24 @@ pub(super) struct BorrowCheckRootCtxt<'tcx> {
|
|||
concrete_opaque_types: ConcreteOpaqueTypes<'tcx>,
|
||||
nested_bodies: FxHashMap<LocalDefId, PropagatedBorrowCheckResults<'tcx>>,
|
||||
tainted_by_errors: Option<ErrorGuaranteed>,
|
||||
/// This should be `None` during normal compilation. See [`crate::consumers`] for more
|
||||
/// information on how this is used.
|
||||
pub(crate) consumer: Option<BorrowckConsumer<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> BorrowCheckRootCtxt<'tcx> {
|
||||
pub(super) fn new(tcx: TyCtxt<'tcx>, root_def_id: LocalDefId) -> BorrowCheckRootCtxt<'tcx> {
|
||||
pub(super) fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
root_def_id: LocalDefId,
|
||||
consumer: Option<BorrowckConsumer<'tcx>>,
|
||||
) -> BorrowCheckRootCtxt<'tcx> {
|
||||
BorrowCheckRootCtxt {
|
||||
tcx,
|
||||
root_def_id,
|
||||
concrete_opaque_types: Default::default(),
|
||||
nested_bodies: Default::default(),
|
||||
tainted_by_errors: None,
|
||||
consumer,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +80,7 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
|
|||
self.root_def_id.to_def_id()
|
||||
);
|
||||
if !self.nested_bodies.contains_key(&def_id) {
|
||||
let result = super::do_mir_borrowck(self, def_id, None).0;
|
||||
let result = super::do_mir_borrowck(self, def_id);
|
||||
if let Some(prev) = self.nested_bodies.insert(def_id, result) {
|
||||
bug!("unexpected previous nested body: {prev:?}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
||||
|
|
@ -7,7 +8,7 @@ use rustc_infer::infer::{InferCtxt, SubregionOrigin};
|
|||
use rustc_infer::traits::query::type_op::DeeplyNormalize;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions,
|
||||
self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, fold_regions,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
||||
|
|
@ -70,10 +71,12 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
|
||||
let QueryRegionConstraints { outlives } = query_constraints;
|
||||
let QueryRegionConstraints { outlives, assumptions } = query_constraints;
|
||||
let assumptions =
|
||||
elaborate::elaborate_outlives_assumptions(self.infcx.tcx, assumptions.iter().copied());
|
||||
|
||||
for &(predicate, constraint_category) in outlives {
|
||||
self.convert(predicate, constraint_category);
|
||||
self.convert(predicate, constraint_category, &assumptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,15 +115,20 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
|
||||
self.category = outlives_requirement.category;
|
||||
self.span = outlives_requirement.blame_span;
|
||||
self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
|
||||
self.convert(
|
||||
ty::OutlivesPredicate(subject, outlived_region),
|
||||
self.category,
|
||||
&Default::default(),
|
||||
);
|
||||
}
|
||||
(self.category, self.span, self.from_closure) = backup;
|
||||
}
|
||||
|
||||
fn convert(
|
||||
&mut self,
|
||||
predicate: ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
|
||||
predicate: ty::ArgOutlivesPredicate<'tcx>,
|
||||
constraint_category: ConstraintCategory<'tcx>,
|
||||
higher_ranked_assumptions: &FxHashSet<ty::ArgOutlivesPredicate<'tcx>>,
|
||||
) {
|
||||
let tcx = self.infcx.tcx;
|
||||
debug!("generate: constraints at: {:#?}", self.locations);
|
||||
|
|
@ -150,7 +158,15 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let mut next_outlives_predicates = vec![];
|
||||
for (ty::OutlivesPredicate(k1, r2), constraint_category) in outlives_predicates {
|
||||
for (pred, constraint_category) in outlives_predicates {
|
||||
// Constraint is implied by a coroutine's well-formedness.
|
||||
if self.infcx.tcx.sess.opts.unstable_opts.higher_ranked_assumptions
|
||||
&& higher_ranked_assumptions.contains(&pred)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let ty::OutlivesPredicate(k1, r2) = pred;
|
||||
match k1.kind() {
|
||||
GenericArgKind::Lifetime(r1) => {
|
||||
let r1_vid = self.to_region_vid(r1);
|
||||
|
|
@ -159,6 +175,9 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
}
|
||||
|
||||
GenericArgKind::Type(mut t1) => {
|
||||
// Scraped constraints may have had inference vars.
|
||||
t1 = self.infcx.resolve_vars_if_possible(t1);
|
||||
|
||||
// Normalize the type we receive from a `TypeOutlives` obligation
|
||||
// in the new trait solver.
|
||||
if infcx.next_trait_solver() {
|
||||
|
|
@ -263,14 +282,15 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
next_outlives_predicates: &mut Vec<(
|
||||
ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
|
||||
ty::ArgOutlivesPredicate<'tcx>,
|
||||
ConstraintCategory<'tcx>,
|
||||
)>,
|
||||
) -> Ty<'tcx> {
|
||||
match self.param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, self.span)
|
||||
{
|
||||
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
|
||||
if let Some(QueryRegionConstraints { outlives }) = constraints {
|
||||
// FIXME(higher_ranked_auto): What should we do with the assumptions here?
|
||||
if let Some(QueryRegionConstraints { outlives, assumptions: _ }) = constraints {
|
||||
next_outlives_predicates.extend(outlives.iter().copied());
|
||||
}
|
||||
ty
|
||||
|
|
|
|||
|
|
@ -131,6 +131,11 @@ pub(crate) fn type_check<'tcx>(
|
|||
pre_obligations.is_empty(),
|
||||
"there should be no incoming region obligations = {pre_obligations:#?}",
|
||||
);
|
||||
let pre_assumptions = infcx.take_registered_region_assumptions();
|
||||
assert!(
|
||||
pre_assumptions.is_empty(),
|
||||
"there should be no incoming region assumptions = {pre_assumptions:#?}",
|
||||
);
|
||||
|
||||
debug!(?normalized_inputs_and_output);
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,12 @@ builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a l
|
|||
builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
|
||||
builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
|
||||
|
||||
builtin_macros_cfg_select_no_matches = none of the predicates in this `cfg_select` evaluated to true
|
||||
|
||||
builtin_macros_cfg_select_unreachable = unreachable predicate
|
||||
.label = always matches
|
||||
.label2 = this predicate is never reached
|
||||
|
||||
builtin_macros_coerce_pointee_requires_maybe_sized = `derive(CoercePointee)` requires `{$name}` to be marked `?Sized`
|
||||
|
||||
builtin_macros_coerce_pointee_requires_one_field = `CoercePointee` can only be derived on `struct`s with at least one field
|
||||
|
|
|
|||
63
compiler/rustc_builtin_macros/src/cfg_select.rs
Normal file
63
compiler/rustc_builtin_macros/src/cfg_select.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_attr_parsing as attr;
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
|
||||
use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select};
|
||||
use rustc_span::{Ident, Span, sym};
|
||||
|
||||
use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable};
|
||||
|
||||
/// Selects the first arm whose predicate evaluates to true.
|
||||
fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> {
|
||||
for (cfg, tt, arm_span) in branches.reachable {
|
||||
if attr::cfg_matches(
|
||||
&cfg,
|
||||
&ecx.sess,
|
||||
ecx.current_expansion.lint_node_id,
|
||||
Some(ecx.ecfg.features),
|
||||
) {
|
||||
return Some((tt, arm_span));
|
||||
}
|
||||
}
|
||||
|
||||
branches.wildcard.map(|(_, tt, span)| (tt, span))
|
||||
}
|
||||
|
||||
pub(super) fn expand_cfg_select<'cx>(
|
||||
ecx: &'cx mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
tts: TokenStream,
|
||||
) -> MacroExpanderResult<'cx> {
|
||||
ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts)) {
|
||||
Ok(branches) => {
|
||||
if let Some((underscore, _, _)) = branches.wildcard {
|
||||
// Warn for every unreachable predicate. We store the fully parsed branch for rustfmt.
|
||||
for (predicate, _, _) in &branches.unreachable {
|
||||
let span = match predicate {
|
||||
CfgSelectPredicate::Wildcard(underscore) => underscore.span,
|
||||
CfgSelectPredicate::Cfg(cfg) => cfg.span(),
|
||||
};
|
||||
let err = CfgSelectUnreachable { span, wildcard_span: underscore.span };
|
||||
ecx.dcx().emit_warn(err);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((tts, arm_span)) = select_arm(ecx, branches) {
|
||||
return ExpandResult::from_tts(
|
||||
ecx,
|
||||
tts,
|
||||
sp,
|
||||
arm_span,
|
||||
Ident::with_dummy_span(sym::cfg_select),
|
||||
);
|
||||
} else {
|
||||
// Emit a compiler error when none of the predicates matched.
|
||||
let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp });
|
||||
DummyResult::any(sp, guar)
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let guar = err.emit();
|
||||
DummyResult::any(sp, guar)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ pub(crate) fn expand_deriving_copy(
|
|||
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);
|
||||
|
|
@ -46,6 +47,7 @@ pub(crate) fn expand_deriving_const_param_ty(
|
|||
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);
|
||||
|
|
@ -60,6 +62,7 @@ pub(crate) fn expand_deriving_const_param_ty(
|
|||
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);
|
||||
|
|
@ -83,6 +86,7 @@ pub(crate) fn expand_deriving_unsized_const_param_ty(
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ pub(crate) fn expand_deriving_clone(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand_ext(cx, mitem, item, push, is_simple)
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ pub(crate) fn expand_deriving_eq(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand_ext(cx, mitem, item, push, true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ pub(crate) fn expand_deriving_ord(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ pub(crate) fn expand_deriving_partial_eq(
|
|||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const: false,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
structural_trait_def.expand(cx, mitem, item, push);
|
||||
|
||||
|
|
@ -58,6 +59,7 @@ pub(crate) fn expand_deriving_partial_eq(
|
|||
methods,
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ pub(crate) fn expand_deriving_partial_ord(
|
|||
methods: vec![partial_cmp_def],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_debug(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ pub(crate) fn expand_deriving_default(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,9 +181,11 @@ use std::{iter, vec};
|
|||
pub(crate) use StaticFields::*;
|
||||
pub(crate) use SubstructureFields::*;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree};
|
||||
use rustc_ast::{
|
||||
self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind,
|
||||
Generics, Mutability, PatKind, VariantData,
|
||||
self as ast, AnonConst, AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg,
|
||||
GenericParamKind, Generics, Mutability, PatKind, Safety, VariantData,
|
||||
};
|
||||
use rustc_attr_data_structures::{AttributeKind, ReprPacked};
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
|
|
@ -222,6 +224,8 @@ pub(crate) struct TraitDef<'a> {
|
|||
pub associated_types: Vec<(Ident, Ty)>,
|
||||
|
||||
pub is_const: bool,
|
||||
|
||||
pub is_staged_api_crate: bool,
|
||||
}
|
||||
|
||||
pub(crate) struct MethodDef<'a> {
|
||||
|
|
@ -484,7 +488,7 @@ impl<'a> TraitDef<'a> {
|
|||
match item {
|
||||
Annotatable::Item(item) => {
|
||||
let is_packed = matches!(
|
||||
AttributeParser::parse_limited(cx.sess, &item.attrs, sym::repr, item.span, item.id),
|
||||
AttributeParser::parse_limited(cx.sess, &item.attrs, sym::repr, item.span, item.id, None),
|
||||
Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..)))
|
||||
);
|
||||
|
||||
|
|
@ -784,8 +788,45 @@ impl<'a> TraitDef<'a> {
|
|||
// Create the type of `self`.
|
||||
let path = cx.path_all(self.span, false, vec![type_ident], self_params);
|
||||
let self_type = cx.ty_path(path);
|
||||
let rustc_const_unstable =
|
||||
cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span));
|
||||
|
||||
let mut attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
|
||||
|
||||
// Only add `rustc_const_unstable` attributes if `derive_const` is used within libcore/libstd,
|
||||
// Other crates don't need stability attributes, so adding them is not useful, but libcore needs them
|
||||
// on all const trait impls.
|
||||
if self.is_const && self.is_staged_api_crate {
|
||||
attrs.push(
|
||||
cx.attr_nested(
|
||||
rustc_ast::AttrItem {
|
||||
unsafety: Safety::Default,
|
||||
path: rustc_const_unstable,
|
||||
args: AttrArgs::Delimited(DelimArgs {
|
||||
dspan: DelimSpan::from_single(self.span),
|
||||
delim: rustc_ast::token::Delimiter::Parenthesis,
|
||||
tokens: [
|
||||
TokenKind::Ident(sym::feature, IdentIsRaw::No),
|
||||
TokenKind::Eq,
|
||||
TokenKind::lit(LitKind::Str, sym::derive_const, None),
|
||||
TokenKind::Comma,
|
||||
TokenKind::Ident(sym::issue, IdentIsRaw::No),
|
||||
TokenKind::Eq,
|
||||
TokenKind::lit(LitKind::Str, sym::derive_const_issue, None),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|kind| {
|
||||
TokenTree::Token(Token { kind, span: self.span }, Spacing::Alone)
|
||||
})
|
||||
.collect(),
|
||||
}),
|
||||
tokens: None,
|
||||
},
|
||||
self.span,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
let attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
|
||||
let opt_trait_ref = Some(trait_ref);
|
||||
|
||||
cx.item(
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_hash(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
hash_trait_def.expand(cx, mitem, item, push);
|
||||
|
|
|
|||
|
|
@ -954,3 +954,21 @@ pub(crate) struct AsmExpectedOther {
|
|||
pub(crate) span: Span,
|
||||
pub(crate) is_inline_asm: bool,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_cfg_select_no_matches)]
|
||||
pub(crate) struct CfgSelectNoMatches {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_cfg_select_unreachable)]
|
||||
pub(crate) struct CfgSelectUnreachable {
|
||||
#[primary_span]
|
||||
#[label(builtin_macros_label2)]
|
||||
pub span: Span,
|
||||
|
||||
#[label]
|
||||
pub wildcard_span: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ mod autodiff;
|
|||
mod cfg;
|
||||
mod cfg_accessible;
|
||||
mod cfg_eval;
|
||||
mod cfg_select;
|
||||
mod compile_error;
|
||||
mod concat;
|
||||
mod concat_bytes;
|
||||
|
|
@ -79,6 +80,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
|||
asm: asm::expand_asm,
|
||||
assert: assert::expand_assert,
|
||||
cfg: cfg::expand_cfg,
|
||||
cfg_select: cfg_select::expand_cfg_select,
|
||||
column: source_util::expand_column,
|
||||
compile_error: compile_error::expand_compile_error,
|
||||
concat: concat::expand_concat,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ use std::sync::Arc;
|
|||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{join_path_idents, token};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_expand::base::{
|
||||
DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, resolve_path,
|
||||
|
|
@ -100,7 +100,7 @@ pub(crate) fn expand_mod(
|
|||
let sp = cx.with_def_site_ctxt(sp);
|
||||
check_zero_tts(cx, sp, tts, "module_path!");
|
||||
let mod_path = &cx.current_expansion.module.mod_path;
|
||||
let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::");
|
||||
let string = join_path_idents(mod_path);
|
||||
|
||||
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::assert_matches::assert_matches;
|
|||
use std::iter;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, GenericParamKind, attr};
|
||||
use rustc_ast::{self as ast, GenericParamKind, attr, join_path_idents};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::{Applicability, Diag, Level};
|
||||
use rustc_expand::base::*;
|
||||
|
|
@ -446,12 +446,7 @@ fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize,
|
|||
}
|
||||
|
||||
fn item_path(mod_path: &[Ident], item_ident: &Ident) -> String {
|
||||
mod_path
|
||||
.iter()
|
||||
.chain(iter::once(item_ident))
|
||||
.map(|x| x.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join("::")
|
||||
join_path_idents(mod_path.iter().chain(iter::once(item_ident)))
|
||||
}
|
||||
|
||||
enum ShouldPanic {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@
|
|||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
struct f32x4(pub [f32; 4]);
|
||||
|
||||
impl f32x4 {
|
||||
fn into_array(self) -> [f32; 4] {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
use std::intrinsics::simd::*;
|
||||
|
||||
fn main() {
|
||||
|
|
@ -29,22 +35,22 @@ fn main() {
|
|||
unsafe {
|
||||
let min0 = simd_fmin(x, y);
|
||||
let min1 = simd_fmin(y, x);
|
||||
assert_eq!(min0, min1);
|
||||
assert_eq!(min0.into_array(), min1.into_array());
|
||||
let e = f32x4([1.0, 1.0, 3.0, 3.0]);
|
||||
assert_eq!(min0, e);
|
||||
assert_eq!(min0.into_array(), e.into_array());
|
||||
let minn = simd_fmin(x, n);
|
||||
assert_eq!(minn, x);
|
||||
assert_eq!(minn.into_array(), x.into_array());
|
||||
let minn = simd_fmin(y, n);
|
||||
assert_eq!(minn, y);
|
||||
assert_eq!(minn.into_array(), y.into_array());
|
||||
|
||||
let max0 = simd_fmax(x, y);
|
||||
let max1 = simd_fmax(y, x);
|
||||
assert_eq!(max0, max1);
|
||||
assert_eq!(max0.into_array(), max1.into_array());
|
||||
let e = f32x4([2.0, 2.0, 4.0, 4.0]);
|
||||
assert_eq!(max0, e);
|
||||
assert_eq!(max0.into_array(), e.into_array());
|
||||
let maxn = simd_fmax(x, n);
|
||||
assert_eq!(maxn, x);
|
||||
assert_eq!(maxn.into_array(), x.into_array());
|
||||
let maxn = simd_fmax(y, n);
|
||||
assert_eq!(maxn, y);
|
||||
assert_eq!(maxn.into_array(), y.into_array());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -348,7 +348,8 @@ fn main() {
|
|||
struct V([f64; 2]);
|
||||
|
||||
let f = V([0.0, 1.0]);
|
||||
let _a = f.0[0];
|
||||
let fp = (&raw const f) as *const [f64; 2];
|
||||
let _a = (unsafe { &*fp })[0];
|
||||
|
||||
stack_val_align();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,6 +175,13 @@ pub(crate) fn codegen_const_value<'tcx>(
|
|||
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
|
||||
}
|
||||
GlobalAlloc::TypeId { .. } => {
|
||||
return CValue::const_val(
|
||||
fx,
|
||||
layout,
|
||||
ScalarInt::try_from_target_usize(offset.bytes(), fx.tcx).unwrap(),
|
||||
);
|
||||
}
|
||||
GlobalAlloc::Static(def_id) => {
|
||||
assert!(fx.tcx.is_static(def_id));
|
||||
let data_id = data_id_for_static(
|
||||
|
|
@ -360,6 +367,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
|||
GlobalAlloc::Memory(alloc) => alloc,
|
||||
GlobalAlloc::Function { .. }
|
||||
| GlobalAlloc::Static(_)
|
||||
| GlobalAlloc::TypeId { .. }
|
||||
| GlobalAlloc::VTable(..) => {
|
||||
unreachable!()
|
||||
}
|
||||
|
|
@ -471,6 +479,11 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
|||
.principal()
|
||||
.map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
|
||||
),
|
||||
GlobalAlloc::TypeId { .. } => {
|
||||
// Nothing to do, the bytes/offset of this pointer have already been written together with all other bytes,
|
||||
// so we just need to drop this provenance.
|
||||
continue;
|
||||
}
|
||||
GlobalAlloc::Static(def_id) => {
|
||||
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -530,8 +530,8 @@ fn codegen_cgu_content(
|
|||
for (mono_item, item_data) in mono_items {
|
||||
match mono_item {
|
||||
MonoItem::Fn(instance) => {
|
||||
if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED)
|
||||
{
|
||||
let flags = tcx.codegen_instance_attrs(instance.def).flags;
|
||||
if flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
rustc_codegen_ssa::mir::naked_asm::codegen_naked_asm(
|
||||
&mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm },
|
||||
instance,
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ fn codegen_and_compile_fn<'tcx>(
|
|||
module: &mut dyn Module,
|
||||
instance: Instance<'tcx>,
|
||||
) {
|
||||
if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
if tcx.codegen_instance_attrs(instance.def).flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
tcx.dcx()
|
||||
.span_fatal(tcx.def_span(instance.def_id()), "Naked asm is not supported in JIT mode");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ fn predefine_mono_items<'tcx>(
|
|||
is_compiler_builtins,
|
||||
);
|
||||
let is_naked = tcx
|
||||
.codegen_fn_attrs(instance.def_id())
|
||||
.codegen_instance_attrs(instance.def)
|
||||
.flags
|
||||
.contains(CodegenFnAttrFlags::NAKED);
|
||||
module
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ permissions:
|
|||
env:
|
||||
# Enable backtraces for easier debugging
|
||||
RUST_BACKTRACE: 1
|
||||
# TODO: remove when confish.sh is removed.
|
||||
OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -59,14 +57,12 @@ jobs:
|
|||
|
||||
- name: Setup path to libgccjit
|
||||
run: |
|
||||
sudo dpkg -i gcc-m68k-15.deb
|
||||
sudo dpkg --force-overwrite -i gcc-m68k-15.deb
|
||||
echo 'gcc-path = "/usr/lib/"' > config.toml
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
|
||||
|
||||
#- name: Cache rust repository
|
||||
## We only clone the rust repository for rustc tests
|
||||
|
|
@ -86,16 +82,20 @@ jobs:
|
|||
- name: Build sample project with target defined as JSON spec
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --cross
|
||||
./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
./y.sh clean all
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --cross
|
||||
./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu
|
||||
./y.sh test --mini-tests
|
||||
CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests
|
||||
./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu
|
||||
./y.sh test --mini-tests --target-triple m68k-unknown-linux-gnu
|
||||
# FIXME: since https://github.com/rust-lang/rust/pull/140809, we cannot run programs for architectures not
|
||||
# supported by the object crate, since this adds a dependency on symbols.o for the panic runtime.
|
||||
# And as such, a wrong order of the object files in the linker command now fails with an undefined reference
|
||||
# to some symbols like __rustc::rust_panic.
|
||||
#CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests --target-triple m68k-unknown-linux-gnu
|
||||
./y.sh clean all
|
||||
|
||||
- name: Prepare dependencies
|
||||
|
|
@ -104,9 +104,23 @@ jobs:
|
|||
git config --global user.name "User"
|
||||
./y.sh prepare --cross
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./y.sh test --release --clean --build-sysroot --sysroot-features compiler_builtins/no-f16-f128 ${{ matrix.commands }}
|
||||
# FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
|
||||
#- name: Run tests
|
||||
#run: |
|
||||
#./y.sh test --target-triple m68k-unknown-linux-gnu --release --clean --build-sysroot --sysroot-features compiler-builtins-no-f16-f128 ${{ matrix.commands }}
|
||||
|
||||
# FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
|
||||
#- name: Run Hello World!
|
||||
#run: |
|
||||
#./y.sh build --target-triple m68k-unknown-linux-gnu
|
||||
|
||||
#vm_dir=$(pwd)/vm
|
||||
#cd tests/hello-world
|
||||
#CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../../y.sh cargo build --target m68k-unknown-linux-gnu
|
||||
#sudo cp target/m68k-unknown-linux-gnu/debug/hello_world $vm_dir/home/
|
||||
#sudo chroot $vm_dir qemu-m68k-static /home/hello_world > hello_world_stdout
|
||||
#expected_output="40"
|
||||
#test $(cat hello_world_stdout) == $expected_output || (echo "Output differs. Actual output: $(cat hello_world_stdout)"; exit 1)
|
||||
|
||||
# Summary job for the merge queue.
|
||||
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
|
||||
|
|
|
|||
|
|
@ -78,7 +78,8 @@ jobs:
|
|||
- name: Run tests
|
||||
run: |
|
||||
# FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros.
|
||||
echo -n 'lto = "fat"' >> build_system/build_sysroot/Cargo.toml
|
||||
# FIXME(antoyo): this should probably not be needed since we embed the LTO bitcode.
|
||||
printf '[profile.release]\nlto = "fat"\n' >> build/build_sysroot/sysroot_src/library/Cargo.toml
|
||||
EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot --keep-lto-tests ${{ matrix.commands }}
|
||||
|
||||
- name: Run y.sh cargo build
|
||||
|
|
|
|||
|
|
@ -1,502 +0,0 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloc"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloctests"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.160"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6376049cfa92c0aa8b9ac95fae22184b981c658208d4ed8a1dc553cd83612895"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "coretests"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlmalloc"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cff88b751e7a276c4ab0e222c3f355190adc6dde9ce39c851db39da34990df7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-core",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fortanix-sgx-abi"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
"rustc-std-workspace-std",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"memchr",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic_abort"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic_unwind"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
"unwind",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc_macro"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
"rustc-literal-escaper",
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "profiler_builtins"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi-alloc"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e43c53ff1a01d423d1cb762fd991de07d32965ff0ca2e4f80444ac7804198203"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"r-efi",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-literal-escaper"
|
||||
version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-alloc"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-core"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-std"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "std"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"dlmalloc",
|
||||
"fortanix-sgx-abi",
|
||||
"hashbrown",
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"r-efi",
|
||||
"r-efi-alloc",
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
"rustc-demangle",
|
||||
"std_detect",
|
||||
"unwind",
|
||||
"wasi",
|
||||
"windows-targets 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "std_detect"
|
||||
version = "0.1.5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysroot"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"proc_macro",
|
||||
"profiler_builtins",
|
||||
"std",
|
||||
"test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
"getopts",
|
||||
"libc",
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
"rustc-std-workspace-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unwind"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
"unwinding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unwinding"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8393f2782b6060a807337ff353780c1ca15206f9ba2424df18cb6e733bd7b345"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
[package]
|
||||
authors = ["rustc_codegen_gcc devs"]
|
||||
name = "sysroot"
|
||||
version = "0.0.0"
|
||||
resolver = "2"
|
||||
|
||||
[dependencies]
|
||||
core = { path = "./sysroot_src/library/core" }
|
||||
compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
|
||||
alloc = { path = "./sysroot_src/library/alloc" }
|
||||
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
|
||||
test = { path = "./sysroot_src/library/test" }
|
||||
proc_macro = { path = "./sysroot_src/library/proc_macro" }
|
||||
|
||||
[patch.crates-io]
|
||||
rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }
|
||||
rustc-std-workspace-alloc = { path = "./sysroot_src/library/rustc-std-workspace-alloc" }
|
||||
rustc-std-workspace-std = { path = "./sysroot_src/library/rustc-std-workspace-std" }
|
||||
compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
|
||||
|
||||
# For compiler-builtins we always use a high number of codegen units.
|
||||
# The goal here is to place every single intrinsic into its own object
|
||||
# file to avoid symbol clashes with the system libgcc if possible. Note
|
||||
# that this number doesn't actually produce this many object files, we
|
||||
# just don't create more than this number of object files.
|
||||
#
|
||||
# It's a bit of a bummer that we have to pass this here, unfortunately.
|
||||
# Ideally this would be specified through an env var to Cargo so Cargo
|
||||
# knows how many CGUs are for this specific crate, but for now
|
||||
# per-crate configuration isn't specifiable in the environment.
|
||||
[profile.dev.package.compiler_builtins]
|
||||
codegen-units = 10000
|
||||
|
||||
[profile.release.package.compiler_builtins]
|
||||
codegen-units = 10000
|
||||
|
||||
[profile.release]
|
||||
debug = "limited"
|
||||
#lto = "fat" # TODO(antoyo): re-enable when the failing LTO tests regarding proc-macros are fixed.
|
||||
|
|
@ -1 +0,0 @@
|
|||
#![no_std]
|
||||
|
|
@ -5,7 +5,7 @@ use std::path::Path;
|
|||
|
||||
use crate::config::{Channel, ConfigInfo};
|
||||
use crate::utils::{
|
||||
copy_file, create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
|
||||
create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -53,11 +53,11 @@ impl BuildArg {
|
|||
}
|
||||
}
|
||||
|
||||
fn cleanup_sysroot_previous_build(start_dir: &Path) {
|
||||
fn cleanup_sysroot_previous_build(library_dir: &Path) {
|
||||
// Cleanup for previous run
|
||||
// Clean target dir except for build scripts and incremental cache
|
||||
let _ = walk_dir(
|
||||
start_dir.join("target"),
|
||||
library_dir.join("target"),
|
||||
&mut |dir: &Path| {
|
||||
for top in &["debug", "release"] {
|
||||
let _ = fs::remove_dir_all(dir.join(top).join("build"));
|
||||
|
|
@ -95,31 +95,13 @@ fn cleanup_sysroot_previous_build(start_dir: &Path) {
|
|||
&mut |_| Ok(()),
|
||||
false,
|
||||
);
|
||||
|
||||
let _ = fs::remove_file(start_dir.join("Cargo.lock"));
|
||||
let _ = fs::remove_file(start_dir.join("test_target/Cargo.lock"));
|
||||
let _ = fs::remove_dir_all(start_dir.join("sysroot"));
|
||||
}
|
||||
|
||||
pub fn create_build_sysroot_content(start_dir: &Path) -> Result<(), String> {
|
||||
if !start_dir.is_dir() {
|
||||
create_dir(start_dir)?;
|
||||
}
|
||||
copy_file("build_system/build_sysroot/Cargo.toml", start_dir.join("Cargo.toml"))?;
|
||||
copy_file("build_system/build_sysroot/Cargo.lock", start_dir.join("Cargo.lock"))?;
|
||||
|
||||
let src_dir = start_dir.join("src");
|
||||
if !src_dir.is_dir() {
|
||||
create_dir(&src_dir)?;
|
||||
}
|
||||
copy_file("build_system/build_sysroot/lib.rs", start_dir.join("src/lib.rs"))
|
||||
}
|
||||
|
||||
pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Result<(), String> {
|
||||
let start_dir = get_sysroot_dir();
|
||||
|
||||
cleanup_sysroot_previous_build(&start_dir);
|
||||
create_build_sysroot_content(&start_dir)?;
|
||||
let library_dir = start_dir.join("sysroot_src").join("library");
|
||||
cleanup_sysroot_previous_build(&library_dir);
|
||||
|
||||
// Builds libs
|
||||
let mut rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default();
|
||||
|
|
@ -157,9 +139,13 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
|
|||
rustflags.push_str(&cg_rustflags);
|
||||
}
|
||||
|
||||
args.push(&"--features");
|
||||
args.push(&"backtrace");
|
||||
|
||||
let mut env = env.clone();
|
||||
env.insert("RUSTFLAGS".to_string(), rustflags);
|
||||
run_command_with_output_and_env(&args, Some(&start_dir), Some(&env))?;
|
||||
let sysroot_dir = library_dir.join("sysroot");
|
||||
run_command_with_output_and_env(&args, Some(&sysroot_dir), Some(&env))?;
|
||||
|
||||
// Copy files to sysroot
|
||||
let sysroot_path = start_dir.join(format!("sysroot/lib/rustlib/{}/lib/", config.target_triple));
|
||||
|
|
@ -169,7 +155,7 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
|
|||
run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ())
|
||||
};
|
||||
walk_dir(
|
||||
start_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)),
|
||||
library_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)),
|
||||
&mut copier.clone(),
|
||||
&mut copier,
|
||||
false,
|
||||
|
|
@ -178,7 +164,7 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
|
|||
// Copy the source files to the sysroot (Rust for Linux needs this).
|
||||
let sysroot_src_path = start_dir.join("sysroot/lib/rustlib/src/rust");
|
||||
create_dir(&sysroot_src_path)?;
|
||||
run_command(&[&"cp", &"-r", &start_dir.join("sysroot_src/library/"), &sysroot_src_path], None)?;
|
||||
run_command(&[&"cp", &"-r", &library_dir, &sysroot_src_path], None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -352,11 +352,6 @@ impl ConfigInfo {
|
|||
None => return Err("no host found".to_string()),
|
||||
};
|
||||
|
||||
if self.target_triple.is_empty()
|
||||
&& let Some(overwrite) = env.get("OVERWRITE_TARGET_TRIPLE")
|
||||
{
|
||||
self.target_triple = overwrite.clone();
|
||||
}
|
||||
if self.target_triple.is_empty() {
|
||||
self.target_triple = self.host_triple.clone();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -588,7 +588,7 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> {
|
|||
&"always",
|
||||
&"--stage",
|
||||
&"0",
|
||||
&"tests/assembly/asm",
|
||||
&"tests/assembly-llvm/asm",
|
||||
&"--compiletest-rustc-args",
|
||||
&rustc_args,
|
||||
],
|
||||
|
|
|
|||
|
|
@ -303,19 +303,6 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> Result<(), String> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn copy_file<F: AsRef<Path>, T: AsRef<Path>>(from: F, to: T) -> Result<(), String> {
|
||||
fs::copy(&from, &to)
|
||||
.map_err(|error| {
|
||||
format!(
|
||||
"Failed to copy file `{}` into `{}`: {:?}",
|
||||
from.as_ref().display(),
|
||||
to.as_ref().display(),
|
||||
error
|
||||
)
|
||||
})
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
/// This function differs from `git_clone` in how it handles *where* the repository will be cloned.
|
||||
/// In `git_clone`, it is cloned in the provided path. In this function, the path you provide is
|
||||
/// the parent folder. So if you pass "a" as folder and try to clone "b.git", it will be cloned into
|
||||
|
|
|
|||
|
|
@ -62,14 +62,14 @@ generate it in [gimple.md](./doc/gimple.md).
|
|||
|
||||
* Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case.
|
||||
* Set the path to the cross-compiling libgccjit in `gcc-path` (in `config.toml`).
|
||||
* Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu`.
|
||||
* Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target m68k-unknown-linux-gnu`.
|
||||
* Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. You can specify which linker to use via `CG_RUSTFLAGS="-Clinker=<linker>"`, for instance: `CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc"`. Specify the target when building the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu`.
|
||||
* Build your project by specifying the target and the linker to use: `CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../y.sh cargo build --target m68k-unknown-linux-gnu`.
|
||||
|
||||
If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler).
|
||||
Then, you can use it the following way:
|
||||
|
||||
* Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json`
|
||||
* Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`.
|
||||
* Build your project by specifying the target specification file: `../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`.
|
||||
|
||||
If you get the following error:
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
)]
|
||||
#![no_core]
|
||||
#![allow(dead_code, internal_features, non_camel_case_types)]
|
||||
#![rustfmt::skip]
|
||||
#![rustfmt_skip]
|
||||
|
||||
extern crate mini_core;
|
||||
|
||||
|
|
@ -198,10 +198,17 @@ fn main() {
|
|||
assert_eq!(intrinsics::align_of::<u16>() as u8, 2);
|
||||
assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8);
|
||||
|
||||
assert!(!const { intrinsics::needs_drop::<u8>() });
|
||||
assert!(!const { intrinsics::needs_drop::<[u8]>() });
|
||||
assert!(const { intrinsics::needs_drop::<NoisyDrop>() });
|
||||
assert!(const { intrinsics::needs_drop::<NoisyDropUnsized>() });
|
||||
/*
|
||||
* TODO: re-enable in the next sync.
|
||||
let u8_needs_drop = const { intrinsics::needs_drop::<u8>() };
|
||||
assert!(!u8_needs_drop);
|
||||
let slice_needs_drop = const { intrinsics::needs_drop::<[u8]>() };
|
||||
assert!(!slice_needs_drop);
|
||||
let noisy_drop = const { intrinsics::needs_drop::<NoisyDrop>() };
|
||||
assert!(noisy_drop);
|
||||
let noisy_unsized_drop = const { intrinsics::needs_drop::<NoisyDropUnsized>() };
|
||||
assert!(noisy_unsized_drop);
|
||||
*/
|
||||
|
||||
Unique {
|
||||
pointer: 0 as *const &str,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2025-06-28"
|
||||
channel = "nightly-2025-07-04"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
|||
#[cfg_attr(not(feature = "master"), allow(unused_variables))] func: Function<'gcc>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
) {
|
||||
let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
|
||||
let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def);
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use std::sync::Arc;
|
|||
|
||||
use gccjit::{Context, OutputKind};
|
||||
use object::read::archive::ArchiveFile;
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
|
||||
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
|
||||
use rustc_codegen_ssa::back::symbol_export;
|
||||
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
|
@ -176,7 +176,7 @@ pub(crate) fn run_fat(
|
|||
cgcx: &CodegenContext<GccCodegenBackend>,
|
||||
modules: Vec<FatLtoInput<GccCodegenBackend>>,
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
|
||||
) -> Result<ModuleCodegen<GccContext>, FatalError> {
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
let lto_data = prepare_lto(cgcx, dcx)?;
|
||||
|
|
@ -201,7 +201,7 @@ fn fat_lto(
|
|||
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||
tmp_path: TempDir,
|
||||
//symbols_below_threshold: &[String],
|
||||
) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
|
||||
) -> Result<ModuleCodegen<GccContext>, FatalError> {
|
||||
let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module");
|
||||
info!("going for a fat lto");
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ fn fat_lto(
|
|||
// of now.
|
||||
module.module_llvm.temp_dir = Some(tmp_path);
|
||||
|
||||
Ok(LtoModuleCodegen::Fat(module))
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
pub struct ModuleBuffer(PathBuf);
|
||||
|
|
@ -358,7 +358,7 @@ pub(crate) fn run_thin(
|
|||
cgcx: &CodegenContext<GccCodegenBackend>,
|
||||
modules: Vec<(String, ThinBuffer)>,
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
) -> Result<(Vec<LtoModuleCodegen<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
let lto_data = prepare_lto(cgcx, dcx)?;
|
||||
|
|
@ -427,7 +427,7 @@ fn thin_lto(
|
|||
tmp_path: TempDir,
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
//_symbols_below_threshold: &[String],
|
||||
) -> Result<(Vec<LtoModuleCodegen<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
|
||||
info!("going for that thin, thin LTO");
|
||||
|
||||
|
|
@ -573,8 +573,7 @@ fn thin_lto(
|
|||
}*/
|
||||
|
||||
info!(" - {}: re-compiled", module_name);
|
||||
opt_jobs
|
||||
.push(LtoModuleCodegen::Thin(ThinModule { shared: shared.clone(), idx: module_index }));
|
||||
opt_jobs.push(ThinModule { shared: shared.clone(), idx: module_index });
|
||||
}
|
||||
|
||||
// Save the current ThinLTO import information for the next compilation
|
||||
|
|
|
|||
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