Merge from rustc
This commit is contained in:
commit
a4f765dcad
1554 changed files with 19575 additions and 10807 deletions
7
.github/workflows/post-merge.yml
vendored
7
.github/workflows/post-merge.yml
vendored
|
|
@ -25,12 +25,19 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
# Give GitHub some time to propagate the information that the PR was merged
|
||||
sleep 60
|
||||
|
||||
# Get closest bors merge commit
|
||||
PARENT_COMMIT=`git rev-list --author='bors <bors@rust-lang.org>' -n1 --first-parent HEAD^1`
|
||||
echo "Parent: ${PARENT_COMMIT}"
|
||||
|
||||
# Find PR for the current commit
|
||||
HEAD_PR=`gh pr list --search "${{ github.sha }}" --state merged --json number --jq '.[0].number'`
|
||||
if [ -z "${HEAD_PR}" ]; then
|
||||
echo "PR for commit SHA ${{ github.sha }} not found, exiting"
|
||||
exit 1
|
||||
fi
|
||||
echo "HEAD: ${{ github.sha }} (#${HEAD_PR})"
|
||||
|
||||
cd src/ci/citool
|
||||
|
|
|
|||
347
Cargo.lock
347
Cargo.lock
|
|
@ -158,12 +158,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.97"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
]
|
||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||
|
||||
[[package]]
|
||||
name = "ar_archive_writer"
|
||||
|
|
@ -188,9 +185,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
|||
|
||||
[[package]]
|
||||
name = "askama"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a4e46abb203e00ef226442d452769233142bbfdd79c3941e84c8e61c4112543"
|
||||
checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7"
|
||||
dependencies = [
|
||||
"askama_derive",
|
||||
"itoa",
|
||||
|
|
@ -201,9 +198,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "askama_derive"
|
||||
version = "0.13.0"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54398906821fd32c728135f7b351f0c7494ab95ae421d41b6f5a020e158f28a6"
|
||||
checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac"
|
||||
dependencies = [
|
||||
"askama_parser",
|
||||
"basic-toml",
|
||||
|
|
@ -213,7 +210,7 @@ dependencies = [
|
|||
"rustc-hash 2.1.1",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -225,7 +222,7 @@ dependencies = [
|
|||
"memchr",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"winnow 0.7.6",
|
||||
"winnow 0.7.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -281,9 +278,9 @@ checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
|||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "1.8.1"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "389a099b34312839e16420d499a9cad9650541715937ffbdd40d36f49e77eeb3"
|
||||
checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
|
|
@ -452,9 +449,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
|||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.40"
|
||||
version = "0.4.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
||||
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
|
|
@ -496,9 +493,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.36"
|
||||
version = "4.5.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04"
|
||||
checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
|
@ -516,9 +513,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.36"
|
||||
version = "4.5.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5"
|
||||
checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
|
@ -535,7 +532,7 @@ dependencies = [
|
|||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -561,13 +558,13 @@ dependencies = [
|
|||
"if_chain",
|
||||
"itertools",
|
||||
"parking_lot",
|
||||
"pulldown-cmark 0.11.3",
|
||||
"pulldown-cmark",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc_tools_util 0.4.2",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
"tempfile",
|
||||
"termize",
|
||||
"tokio",
|
||||
|
|
@ -653,16 +650,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "color-eyre"
|
||||
version = "0.6.3"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5"
|
||||
checksum = "e6e1761c0e16f8883bbbb8ce5990867f4f06bf11a0253da6495a04ce4b6ef0ec"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"color-spantrace",
|
||||
"eyre",
|
||||
"indenter",
|
||||
"once_cell",
|
||||
"owo-colors",
|
||||
"owo-colors 4.2.0",
|
||||
"tracing-error",
|
||||
]
|
||||
|
||||
|
|
@ -684,17 +681,17 @@ dependencies = [
|
|||
"nom",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color-spantrace"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2"
|
||||
checksum = "2ddd8d5bfda1e11a501d0a7303f3bfed9aa632ebdb859be40d0fd70478ed70d5"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"owo-colors",
|
||||
"owo-colors 4.2.0",
|
||||
"tracing-core",
|
||||
"tracing-error",
|
||||
]
|
||||
|
|
@ -780,6 +777,7 @@ name = "coverage-dump"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools",
|
||||
"leb128",
|
||||
"md-5",
|
||||
"miniz_oxide 0.7.4",
|
||||
|
|
@ -910,7 +908,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -921,7 +919,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
|||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -943,13 +941,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "derive-where"
|
||||
version = "1.2.7"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25"
|
||||
checksum = "e73f2692d4bd3cac41dca28934a39894200c9fabf49586d77d0e5954af1d7902"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -970,7 +968,7 @@ dependencies = [
|
|||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -980,7 +978,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||
dependencies = [
|
||||
"derive_builder_core",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -992,7 +990,7 @@ dependencies = [
|
|||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1082,7 +1080,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1361,7 +1359,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1434,9 +1432,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
|
|
@ -1502,9 +1500,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.2"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
|
|
@ -1761,7 +1759,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1919,9 +1917,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
|||
|
||||
[[package]]
|
||||
name = "jiff"
|
||||
version = "0.2.6"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f33145a5cbea837164362c7bd596106eb7c5198f97d1ba6f6ebb3223952e488"
|
||||
checksum = "d07d8d955d798e7a4d6f9c58cd1f1916e790b42b092758a9ef6e16fef9f1b3fd"
|
||||
dependencies = [
|
||||
"jiff-static",
|
||||
"log",
|
||||
|
|
@ -1932,13 +1930,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "jiff-static"
|
||||
version = "0.2.6"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43ce13c40ec6956157a3635d97a1ee2df323b263f09ea14165131289cb0f5c19"
|
||||
checksum = "f244cfe006d98d26f859c7abd1318d85327e1882dc9cef80f62daeeb0adcf300"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2071,14 +2069,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.11"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
|
||||
checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
|
|
@ -2202,7 +2200,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2307,7 +2305,7 @@ dependencies = [
|
|||
"libffi",
|
||||
"libloading",
|
||||
"measureme",
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"regex",
|
||||
"rustc_version",
|
||||
"smallvec",
|
||||
|
|
@ -2466,6 +2464,25 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-kit"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.2"
|
||||
|
|
@ -2525,9 +2542,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
|||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.107"
|
||||
version = "0.9.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07"
|
||||
checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
|
|
@ -2550,7 +2567,6 @@ dependencies = [
|
|||
"humansize",
|
||||
"humantime",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sysinfo",
|
||||
"tabled",
|
||||
|
|
@ -2577,6 +2593,12 @@ version = "3.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564"
|
||||
|
||||
[[package]]
|
||||
name = "pad"
|
||||
version = "0.1.6"
|
||||
|
|
@ -2681,7 +2703,7 @@ dependencies = [
|
|||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2798,7 +2820,7 @@ version = "0.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abec3fb083c10660b3854367697da94c674e9e82aa7511014dc958beeb7215e9"
|
||||
dependencies = [
|
||||
"owo-colors",
|
||||
"owo-colors 3.5.0",
|
||||
"pad",
|
||||
]
|
||||
|
||||
|
|
@ -2810,33 +2832,22 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.94"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psm"
|
||||
version = "0.1.25"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88"
|
||||
checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.11.3"
|
||||
|
|
@ -2895,13 +2906,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
|
||||
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
|
||||
dependencies = [
|
||||
"rand_chacha 0.9.0",
|
||||
"rand_core 0.9.3",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2930,7 +2940,7 @@ version = "0.6.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
"getrandom 0.2.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2973,9 +2983,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.11"
|
||||
version = "0.5.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3"
|
||||
checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
|
@ -2986,7 +2996,7 @@ version = "0.4.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
||||
dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
"getrandom 0.2.16",
|
||||
"libredox",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
|
@ -2997,7 +3007,7 @@ version = "0.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
|
||||
dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
"getrandom 0.2.16",
|
||||
"libredox",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
|
@ -3179,7 +3189,7 @@ name = "rustc_abi"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"rand_xoshiro",
|
||||
"rustc_data_structures",
|
||||
"rustc_hashes",
|
||||
|
|
@ -3583,13 +3593,13 @@ dependencies = [
|
|||
"rustc_query_system",
|
||||
"rustc_resolve",
|
||||
"rustc_session",
|
||||
"rustc_smir",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"rustc_trait_selection",
|
||||
"rustc_ty_utils",
|
||||
"serde_json",
|
||||
"shlex",
|
||||
"stable_mir",
|
||||
"tracing",
|
||||
"windows 0.59.0",
|
||||
]
|
||||
|
|
@ -3693,7 +3703,7 @@ dependencies = [
|
|||
"fluent-syntax",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
|
|
@ -3805,7 +3815,7 @@ dependencies = [
|
|||
name = "rustc_incremental"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -3839,7 +3849,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3985,7 +3995,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
|
|
@ -4015,6 +4025,7 @@ dependencies = [
|
|||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"tempfile",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
|
@ -4314,7 +4325,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"bitflags",
|
||||
"itertools",
|
||||
"pulldown-cmark 0.11.3",
|
||||
"pulldown-cmark",
|
||||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
|
|
@ -4371,7 +4382,7 @@ dependencies = [
|
|||
"bitflags",
|
||||
"getopts",
|
||||
"libc",
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
|
|
@ -4481,7 +4492,6 @@ dependencies = [
|
|||
"itertools",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
|
@ -4575,7 +4585,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
|
|
@ -4599,7 +4609,6 @@ dependencies = [
|
|||
"indexmap",
|
||||
"itertools",
|
||||
"minifier",
|
||||
"pulldown-cmark 0.9.6",
|
||||
"pulldown-cmark-escape",
|
||||
"regex",
|
||||
"rustdoc-json-types",
|
||||
|
|
@ -4666,7 +4675,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4700,9 +4709,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.5"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
|
||||
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
|
|
@ -4803,7 +4812,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4840,9 +4849,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
version = "0.10.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
|
|
@ -4961,9 +4970,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "stacker"
|
||||
version = "0.1.20"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "601f9201feb9b09c00266478bf459952b9ef9a6b94edb2f21eba14ab681a60a9"
|
||||
checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
|
|
@ -5049,9 +5058,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.100"
|
||||
version = "2.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
|
||||
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -5060,24 +5069,25 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.13.1"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
||||
checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.31.4"
|
||||
version = "0.35.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be"
|
||||
checksum = "b897c8ea620e181c7955369a31be5f48d9a9121cb59fd33ecef9ff2a34323422"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"windows 0.57.0",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-kit",
|
||||
"windows 0.61.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5161,7 +5171,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"indicatif",
|
||||
"num",
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"rand_chacha 0.9.0",
|
||||
"rayon",
|
||||
]
|
||||
|
|
@ -5198,7 +5208,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5209,7 +5219,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5335,9 +5345,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.8"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||
checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
|
@ -5375,7 +5385,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5546,7 +5556,7 @@ checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b"
|
|||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
"unic-langid-impl",
|
||||
]
|
||||
|
||||
|
|
@ -5762,7 +5772,7 @@ dependencies = [
|
|||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
|
@ -5784,7 +5794,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
|
@ -5952,16 +5962,6 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.57.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
|
||||
dependencies = [
|
||||
"windows-core 0.57.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.59.0"
|
||||
|
|
@ -5972,6 +5972,19 @@ dependencies = [
|
|||
"windows-targets 0.53.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.61.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core 0.61.0",
|
||||
"windows-future",
|
||||
"windows-link",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-bindgen"
|
||||
version = "0.61.0"
|
||||
|
|
@ -5984,15 +5997,12 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.57.0"
|
||||
name = "windows-collections"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
|
||||
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
|
||||
dependencies = [
|
||||
"windows-implement 0.57.0",
|
||||
"windows-interface 0.57.0",
|
||||
"windows-result 0.1.2",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-core 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6002,8 +6012,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce"
|
||||
dependencies = [
|
||||
"windows-implement 0.59.0",
|
||||
"windows-interface 0.59.1",
|
||||
"windows-result 0.3.2",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-strings 0.3.1",
|
||||
"windows-targets 0.53.0",
|
||||
]
|
||||
|
|
@ -6015,21 +6025,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.0",
|
||||
"windows-interface 0.59.1",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result 0.3.2",
|
||||
"windows-result",
|
||||
"windows-strings 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.57.0"
|
||||
name = "windows-future"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
|
||||
checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"windows-core 0.61.0",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6040,7 +6049,7 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6051,18 +6060,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.57.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6073,7 +6071,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6083,12 +6081,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.2"
|
||||
name = "windows-numerics"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
|
||||
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
"windows-core 0.61.0",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6341,9 +6340,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.6"
|
||||
version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10"
|
||||
checksum = "d9fb597c990f03753e08d3c29efbfcf2019a003b4bf4ba19225c158e1549f0f3"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
|
@ -6464,28 +6463,28 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.24"
|
||||
version = "0.8.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
|
||||
checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.24"
|
||||
version = "0.8.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
|
||||
checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6505,7 +6504,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
|
|
@ -6528,5 +6527,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
|
|
|||
166
RELEASES.md
166
RELEASES.md
|
|
@ -1,3 +1,169 @@
|
|||
Version 1.87.0 (2025-05-15)
|
||||
==========================
|
||||
|
||||
<a id="1.87.0-Language"></a>
|
||||
|
||||
Language
|
||||
--------
|
||||
- [Stabilize `asm_goto` feature](https://github.com/rust-lang/rust/pull/133870)
|
||||
- [Allow parsing open beginning ranges (`..EXPR`) after unary operators `!`, `~`, `-`, and `*`}](https://github.com/rust-lang/rust/pull/134900).
|
||||
- [Don't require method impls for methods with `Self: Sized` bounds in `impl`s for unsized types](https://github.com/rust-lang/rust/pull/135480)
|
||||
- [Stabilize `feature(precise_capturing_in_traits)` allowing `use<...>` bounds on return position `impl Trait` in `trait`s](https://github.com/rust-lang/rust/pull/138128)
|
||||
|
||||
<a id="1.87.0-Compiler"></a>
|
||||
|
||||
Compiler
|
||||
--------
|
||||
- [x86: make SSE2 required for i686 targets and use it to pass SIMD types](https://github.com/rust-lang/rust/pull/135408)
|
||||
|
||||
<a id="1.87.0-Platform-Support"></a>
|
||||
|
||||
Platform Support
|
||||
----------------
|
||||
- [Remove `i586-pc-windows-msvc` target](https://github.com/rust-lang/rust/pull/137957)
|
||||
|
||||
Refer to Rust's [platform support page][platform-support-doc]
|
||||
for more information on Rust's tiered platform support.
|
||||
|
||||
[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html
|
||||
|
||||
<a id="1.87.0-Libraries"></a>
|
||||
|
||||
Libraries
|
||||
---------
|
||||
- [Stabilize the anonymous pipe API](https://github.com/rust-lang/rust/issues/127154)
|
||||
- [Add support for unbounded left/right shift operations](https://github.com/rust-lang/rust/issues/129375)
|
||||
- [Print pointer metadata in `Debug` impl of raw pointers](https://github.com/rust-lang/rust/pull/135080)
|
||||
- [`Vec::with_capacity` guarantees it allocates with the amount requested, even if `Vec::capacity` returns a different number.](https://github.com/rust-lang/rust/pull/135933)
|
||||
- Most `std::arch` intrinsics which don't take pointer arguments can now be called from safe code if the caller has the appropriate target features already enabled (https://github.com/rust-lang/stdarch/pull/1714, https://github.com/rust-lang/stdarch/pull/1716, https://github.com/rust-lang/stdarch/pull/1717)
|
||||
- [Undeprecate `env::home_dir`](https://github.com/rust-lang/rust/pull/137327)
|
||||
- [Denote `ControlFlow` as `#[must_use]`](https://github.com/rust-lang/rust/pull/137449)
|
||||
- [Macros such as `assert_eq!` and `vec!` now support `const {...}` expressions](https://github.com/rust-lang/rust/pull/138162)
|
||||
|
||||
<a id="1.87.0-Stabilized-APIs"></a>
|
||||
|
||||
Stabilized APIs
|
||||
---------------
|
||||
|
||||
- [`Vec::extract_if`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.extract_if)
|
||||
- [`vec::ExtractIf`](https://doc.rust-lang.org/nightly/std/vec/struct.ExtractIf.html)
|
||||
- [`LinkedList::extract_if`](https://doc.rust-lang.org/nightly/std/collections/struct.LinkedList.html#method.extract_if)
|
||||
- [`linked_list::ExtractIf`](https://doc.rust-lang.org/nightly/std/collections/linked_list/struct.ExtractIf.html)
|
||||
- [`<[T]>::split_off`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off)
|
||||
- [`<[T]>::split_off_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_mut)
|
||||
- [`<[T]>::split_off_first`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first)
|
||||
- [`<[T]>::split_off_first_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_first_mut)
|
||||
- [`<[T]>::split_off_last`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last)
|
||||
- [`<[T]>::split_off_last_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_off_last_mut)
|
||||
- [`String::extend_from_within`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.extend_from_within)
|
||||
- [`os_str::Display`](https://doc.rust-lang.org/nightly/std/ffi/os_str/struct.Display.html)
|
||||
- [`OsString::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.display)
|
||||
- [`OsStr::display`](https://doc.rust-lang.org/nightly/std/ffi/struct.OsStr.html#method.display)
|
||||
- [`io::pipe`](https://doc.rust-lang.org/nightly/std/io/fn.pipe.html)
|
||||
- [`io::PipeReader`](https://doc.rust-lang.org/nightly/std/io/struct.PipeReader.html)
|
||||
- [`io::PipeWriter`](https://doc.rust-lang.org/nightly/std/io/struct.PipeWriter.html)
|
||||
- [`impl From<PipeReader> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeReader%3E-for-OwnedHandle)
|
||||
- [`impl From<PipeWriter> for OwnedHandle`](https://doc.rust-lang.org/nightly/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeWriter%3E-for-OwnedHandle)
|
||||
- [`impl From<PipeReader> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html)
|
||||
- [`impl From<PipeWriter> for Stdio`](https://doc.rust-lang.org/nightly/std/process/struct.Stdio.html#impl-From%3CPipeWriter%3E-for-Stdio)
|
||||
- [`impl From<PipeReader> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeReader%3E-for-OwnedFd)
|
||||
- [`impl From<PipeWriter> for OwnedFd`](https://doc.rust-lang.org/nightly/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeWriter%3E-for-OwnedFd)
|
||||
- [`Box<MaybeUninit<T>>::write`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.write)
|
||||
- [`impl TryFrom<Vec<u8>> for String`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#impl-TryFrom%3CVec%3Cu8%3E%3E-for-String)
|
||||
|
||||
These APIs are now stable in const contexts:
|
||||
|
||||
- [`<*const T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned)
|
||||
- [`<*const T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned)
|
||||
- [`<*mut T>::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from_unsigned-1)
|
||||
- [`<*mut T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.byte_offset_from_unsigned-1)
|
||||
- [`NonNull::offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.offset_from_unsigned)
|
||||
- [`NonNull::byte_offset_from_unsigned`](https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.byte_offset_from_unsigned)
|
||||
- [`<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.cast_signed)
|
||||
- [`NonZero::<uN>::cast_signed`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_signed-5).
|
||||
- [`<iN>::cast_signed`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.cast_signed).
|
||||
- [`NonZero::<iN>::cast_unsigned`](https://doc.rust-lang.org/nightly/std/num/struct.NonZero.html#method.cast_unsigned-5).
|
||||
- [`<uN>::is_multiple_of`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.is_multiple_of)
|
||||
- [`<uN>::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shl)
|
||||
- [`<uN>::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.unbounded_shr)
|
||||
- [`<iN>::unbounded_shl`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shl)
|
||||
- [`<iN>::unbounded_shr`](https://doc.rust-lang.org/nightly/std/primitive.isize.html#method.unbounded_shr)
|
||||
- [`<str>::from_utf8`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8)
|
||||
- [`<str>::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_mut)
|
||||
- [`<str>::from_utf8_unchecked`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked)
|
||||
- [`<str>::from_utf8_unchecked_mut`](https://doc.rust-lang.org/nightly/std/primitive.str.html#method.from_utf8_unchecked_mut)
|
||||
- [`core::str::from_utf8_mut`](https://doc.rust-lang.org/nightly/std/str/fn.from_utf8_mut.html)
|
||||
- [`<[T]>::copy_from_slice`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.copy_from_slice)
|
||||
- [`SocketAddr::set_ip`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_ip)
|
||||
- [`SocketAddr::set_port`](https://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_port),
|
||||
- [`SocketAddrV4::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_ip)
|
||||
- [`SocketAddrV4::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_port),
|
||||
- [`SocketAddrV6::set_ip`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_ip)
|
||||
- [`SocketAddrV6::set_port`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_port)
|
||||
- [`SocketAddrV6::set_flowinfo`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_flowinfo)
|
||||
- [`SocketAddrV6::set_scope_id`](https://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_scope_id)
|
||||
- [`char::is_digit`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_digit)
|
||||
- [`char::is_whitespace`](https://doc.rust-lang.org/nightly/std/primitive.char.html#method.is_whitespace)
|
||||
- [`<iN>::midpoint`](https://doc.rust-lang.org/std/primitive.isize.html#method.midpoint)
|
||||
- [`<[[T; N]]>::as_flattened`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_flattened)
|
||||
- [`<[[T; N]]>::as_flattened_mut`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_flattened_mut)
|
||||
- [`String::into_bytes`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.into_bytes)
|
||||
- [`String::as_str`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_str)
|
||||
- [`String::capacity`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.capacity)
|
||||
- [`String::as_bytes`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_bytes)
|
||||
- [`String::len`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.len)
|
||||
- [`String::is_empty`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.is_empty)
|
||||
- [`String::as_mut_str`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_mut_str)
|
||||
- [`String::as_mut_vec`](https://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_mut_vec)
|
||||
- [`Vec::as_ptr`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_ptr)
|
||||
- [`Vec::as_slice`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_slice)
|
||||
- [`Vec::capacity`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.capacity)
|
||||
- [`Vec::len`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.len)
|
||||
- [`Vec::is_empty`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.is_empty)
|
||||
- [`Vec::as_mut_slice`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_mut_slice)
|
||||
- [`Vec::as_mut_ptr`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_mut_ptr)
|
||||
|
||||
<a id="1.87.0-Cargo"></a>
|
||||
|
||||
Cargo
|
||||
-----
|
||||
- [Add terminal integration via ANSI OSC 9;4 sequences](https://github.com/rust-lang/cargo/pull/14615/)
|
||||
- [chore: bump openssl to v3](https://github.com/rust-lang/cargo/pull/15232/)
|
||||
- [feat(package): add --exclude-lockfile flag](https://github.com/rust-lang/cargo/pull/15234/)
|
||||
|
||||
<a id="1.87.0-Compatibility-Notes"></a>
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
- [Rust now raises an error for macro invocations inside the `#![crate_name]` attribute](https://github.com/rust-lang/rust/pull/127581)
|
||||
- [Unstable fields are now always considered to be inhabited](https://github.com/rust-lang/rust/pull/133889)
|
||||
- [Macro arguments of unary operators followed by open beginning ranges may now be matched differently](https://github.com/rust-lang/rust/pull/134900)
|
||||
- [Make `Debug` impl of raw pointers print metadata if present](https://github.com/rust-lang/rust/pull/135080)
|
||||
- [Warn against function pointers using unsupported ABI strings in dependencies](https://github.com/rust-lang/rust/pull/135767)
|
||||
- [Associated types on `dyn` types are no longer deduplicated](https://github.com/rust-lang/rust/pull/136458)
|
||||
- [Forbid attributes on `..` inside of struct patterns (`let Struct { #[attribute] .. }) =`](https://github.com/rust-lang/rust/pull/136490)
|
||||
- [Make `ptr_cast_add_auto_to_object` lint into hard error](https://github.com/rust-lang/rust/pull/136764)
|
||||
- Many `std::arch` intrinsics are now safe to call in some contexts, there may now be new `unused_unsafe` warnings in existing codebases.
|
||||
- [Limit `width` and `precision` formatting options to 16 bits on all targets](https://github.com/rust-lang/rust/pull/136932)
|
||||
- [Turn order dependent trait objects future incompat warning into a hard error](https://github.com/rust-lang/rust/pull/136968)
|
||||
- [Denote `ControlFlow` as `#[must_use]`](https://github.com/rust-lang/rust/pull/137449)
|
||||
- [Windows: The standard library no longer links `advapi32`, except on win7.](https://github.com/rust-lang/rust/pull/138233) Code such as C libraries that were relying on this assumption may need to explicitly link advapi32.
|
||||
- [Proc macros can no longer observe expanded `cfg(true)` attributes.](https://github.com/rust-lang/rust/pull/138844)
|
||||
- [Start changing the internal representation of pasted tokens](https://github.com/rust-lang/rust/pull/124141). Certain invalid declarative macros that were previously accepted in obscure circumstances are now correctly rejected by the compiler. Use of a `tt` fragment specifier can often fix these macros.
|
||||
- [Don't allow flattened format_args in const.](https://github.com/rust-lang/rust/pull/139624)
|
||||
|
||||
<a id="1.87.0-Internal-Changes"></a>
|
||||
|
||||
Internal Changes
|
||||
----------------
|
||||
|
||||
These changes do not affect any public interfaces of Rust, but they represent
|
||||
significant improvements to the performance or internals of rustc and related
|
||||
tools.
|
||||
|
||||
- [Update to LLVM 20](https://github.com/rust-lang/rust/pull/135763)
|
||||
|
||||
|
||||
Version 1.86.0 (2025-04-03)
|
||||
==========================
|
||||
|
||||
|
|
|
|||
|
|
@ -492,9 +492,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let mut generic_args = ThinVec::new();
|
||||
for (idx, arg) in args.iter().cloned().enumerate() {
|
||||
if legacy_args_idx.contains(&idx) {
|
||||
let parent_def_id = self.current_hir_id_owner.def_id;
|
||||
let node_id = self.next_node_id();
|
||||
self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, f.span);
|
||||
self.create_def(node_id, None, DefKind::AnonConst, f.span);
|
||||
let mut visitor = WillCreateDefIdsVisitor {};
|
||||
let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) {
|
||||
AstP(Expr {
|
||||
|
|
|
|||
|
|
@ -1310,7 +1310,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// create a fake body so that the entire rest of the compiler doesn't have to deal with
|
||||
// this as a special case.
|
||||
return self.lower_fn_body(decl, contract, |this| {
|
||||
if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)) {
|
||||
if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic))
|
||||
|| this.tcx.is_sdylib_interface_build()
|
||||
{
|
||||
let span = this.lower_span(span);
|
||||
let empty_block = hir::Block {
|
||||
hir_id: this.next_id(),
|
||||
|
|
|
|||
|
|
@ -500,12 +500,12 @@ enum GenericArgsMode {
|
|||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn create_def(
|
||||
&mut self,
|
||||
parent: LocalDefId,
|
||||
node_id: ast::NodeId,
|
||||
name: Option<Symbol>,
|
||||
def_kind: DefKind,
|
||||
span: Span,
|
||||
) -> LocalDefId {
|
||||
let parent = self.current_hir_id_owner.def_id;
|
||||
debug_assert_ne!(node_id, ast::DUMMY_NODE_ID);
|
||||
assert!(
|
||||
self.opt_local_def_id(node_id).is_none(),
|
||||
|
|
@ -515,7 +515,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.tcx.hir_def_key(self.local_def_id(node_id)),
|
||||
);
|
||||
|
||||
let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id();
|
||||
let def_id = self
|
||||
.tcx
|
||||
.at(span)
|
||||
.create_def(parent, name, def_kind, None, &mut self.resolver.disambiguator)
|
||||
.def_id();
|
||||
|
||||
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
|
||||
self.resolver.node_id_to_def_id.insert(node_id, def_id);
|
||||
|
|
@ -787,7 +791,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
LifetimeRes::Fresh { param, kind, .. } => {
|
||||
// Late resolution delegates to us the creation of the `LocalDefId`.
|
||||
let _def_id = self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
param,
|
||||
Some(kw::UnderscoreLifetime),
|
||||
DefKind::LifetimeParam,
|
||||
|
|
@ -2113,8 +2116,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
hir::ConstArgKind::Path(qpath)
|
||||
} else {
|
||||
// Construct an AnonConst where the expr is the "ty"'s path.
|
||||
|
||||
let parent_def_id = self.current_hir_id_owner.def_id;
|
||||
let node_id = self.next_node_id();
|
||||
let span = self.lower_span(span);
|
||||
|
||||
|
|
@ -2122,7 +2123,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// We're lowering a const argument that was originally thought to be a type argument,
|
||||
// so the def collector didn't create the def ahead of time. That's why we have to do
|
||||
// it here.
|
||||
let def_id = self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, span);
|
||||
let def_id = self.create_def(node_id, None, DefKind::AnonConst, span);
|
||||
let hir_id = self.lower_node_id(node_id);
|
||||
|
||||
let path_expr = Expr {
|
||||
|
|
|
|||
|
|
@ -522,14 +522,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
span: Span,
|
||||
base_type: Span,
|
||||
) -> &'hir hir::ConstArg<'hir> {
|
||||
let parent_def_id = self.current_hir_id_owner.def_id;
|
||||
let node_id = self.next_node_id();
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
// We're generating a range end that didn't exist in the AST,
|
||||
// so the def collector didn't create the def ahead of time. That's why we have to do
|
||||
// it here.
|
||||
let def_id = self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, span);
|
||||
let def_id = self.create_def(node_id, None, DefKind::AnonConst, span);
|
||||
let hir_id = self.lower_node_id(node_id);
|
||||
|
||||
let unstable_span = self.mark_span_with_reason(
|
||||
|
|
|
|||
|
|
@ -82,6 +82,10 @@ struct AstValidator<'a> {
|
|||
/// Used to ban explicit safety on foreign items when the extern block is not marked as unsafe.
|
||||
extern_mod_safety: Option<Safety>,
|
||||
|
||||
lint_node_id: NodeId,
|
||||
|
||||
is_sdylib_interface: bool,
|
||||
|
||||
lint_buffer: &'a mut LintBuffer,
|
||||
}
|
||||
|
||||
|
|
@ -826,7 +830,7 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara
|
|||
|
||||
impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
fn visit_attribute(&mut self, attr: &Attribute) {
|
||||
validate_attr::check_attr(&self.sess.psess, attr);
|
||||
validate_attr::check_attr(&self.sess.psess, attr, self.lint_node_id);
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'a Ty) {
|
||||
|
|
@ -839,6 +843,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.has_proc_macro_decls = true;
|
||||
}
|
||||
|
||||
let previous_lint_node_id = mem::replace(&mut self.lint_node_id, item.id);
|
||||
|
||||
if let Some(ident) = item.kind.ident()
|
||||
&& attr::contains_name(&item.attrs, sym::no_mangle)
|
||||
{
|
||||
|
|
@ -948,7 +954,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.check_defaultness(item.span, *defaultness);
|
||||
|
||||
let is_intrinsic = item.attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic));
|
||||
if body.is_none() && !is_intrinsic {
|
||||
if body.is_none() && !is_intrinsic && !self.is_sdylib_interface {
|
||||
self.dcx().emit_err(errors::FnWithoutBody {
|
||||
span: item.span,
|
||||
replace_span: self.ending_semi_or_hi(item.span),
|
||||
|
|
@ -1128,6 +1134,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
_ => visit::walk_item(self, item),
|
||||
}
|
||||
|
||||
self.lint_node_id = previous_lint_node_id;
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
||||
|
|
@ -1435,7 +1443,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
});
|
||||
}
|
||||
AssocItemKind::Fn(box Fn { body, .. }) => {
|
||||
if body.is_none() {
|
||||
if body.is_none() && !self.is_sdylib_interface {
|
||||
self.dcx().emit_err(errors::AssocFnWithoutBody {
|
||||
span: item.span,
|
||||
replace_span: self.ending_semi_or_hi(item.span),
|
||||
|
|
@ -1683,6 +1691,7 @@ pub fn check_crate(
|
|||
sess: &Session,
|
||||
features: &Features,
|
||||
krate: &Crate,
|
||||
is_sdylib_interface: bool,
|
||||
lints: &mut LintBuffer,
|
||||
) -> bool {
|
||||
let mut validator = AstValidator {
|
||||
|
|
@ -1694,6 +1703,8 @@ pub fn check_crate(
|
|||
outer_impl_trait_span: None,
|
||||
disallow_tilde_const: Some(TildeConstReason::Item),
|
||||
extern_mod_safety: None,
|
||||
lint_node_id: CRATE_NODE_ID,
|
||||
is_sdylib_interface,
|
||||
lint_buffer: lints,
|
||||
};
|
||||
visit::walk_crate(&mut validator, krate);
|
||||
|
|
|
|||
|
|
@ -514,6 +514,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
gate_all!(contracts_internals, "contract internal machinery is for internal use only");
|
||||
gate_all!(where_clause_attrs, "attributes in `where` clause are unstable");
|
||||
gate_all!(super_let, "`super let` is experimental");
|
||||
gate_all!(frontmatter, "frontmatters are experimental");
|
||||
|
||||
if !visitor.features.never_patterns() {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
|
|
|
|||
|
|
@ -244,9 +244,6 @@ struct BufEntry {
|
|||
// forgotten will trigger a panic in `drop`. (Closing a box more than once
|
||||
// isn't possible because `BoxMarker` doesn't implement `Copy` or `Clone`.)
|
||||
//
|
||||
// FIXME(nnethercote): the panic in `drop` is currently disabled because a few
|
||||
// places fail to close their boxes. It can be enabled once they are fixed.
|
||||
//
|
||||
// Note: it would be better to make open/close mismatching impossible and avoid
|
||||
// the need for this marker type altogether by having functions like
|
||||
// `with_ibox` that open a box, call a closure, and then close the box. That
|
||||
|
|
@ -261,8 +258,7 @@ impl !Copy for BoxMarker {}
|
|||
|
||||
impl Drop for BoxMarker {
|
||||
fn drop(&mut self) {
|
||||
// FIXME(nnethercote): enable once the bad cases are fixed
|
||||
//panic!("BoxMarker not ended with `Printer::end()`");
|
||||
panic!("BoxMarker not ended with `Printer::end()`");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ use std::borrow::Cow;
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast::token::{Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
||||
pub use state::{AnnNode, Comments, PpAnn, PrintState, State, print_crate};
|
||||
pub use state::{
|
||||
AnnNode, Comments, PpAnn, PrintState, State, print_crate, print_crate_as_interface,
|
||||
};
|
||||
|
||||
/// Print the token kind precisely, without converting `$crate` into its respective crate name.
|
||||
pub fn token_kind_to_string(tok: &TokenKind) -> Cow<'static, str> {
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ pub struct State<'a> {
|
|||
pub s: pp::Printer,
|
||||
comments: Option<Comments<'a>>,
|
||||
ann: &'a (dyn PpAnn + 'a),
|
||||
is_sdylib_interface: bool,
|
||||
}
|
||||
|
||||
const INDENT_UNIT: isize = 4;
|
||||
|
|
@ -237,9 +238,36 @@ pub fn print_crate<'a>(
|
|||
edition: Edition,
|
||||
g: &AttrIdGenerator,
|
||||
) -> String {
|
||||
let mut s =
|
||||
State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann };
|
||||
let mut s = State {
|
||||
s: pp::Printer::new(),
|
||||
comments: Some(Comments::new(sm, filename, input)),
|
||||
ann,
|
||||
is_sdylib_interface: false,
|
||||
};
|
||||
|
||||
print_crate_inner(&mut s, krate, is_expanded, edition, g);
|
||||
s.s.eof()
|
||||
}
|
||||
|
||||
pub fn print_crate_as_interface(
|
||||
krate: &ast::Crate,
|
||||
edition: Edition,
|
||||
g: &AttrIdGenerator,
|
||||
) -> String {
|
||||
let mut s =
|
||||
State { s: pp::Printer::new(), comments: None, ann: &NoAnn, is_sdylib_interface: true };
|
||||
|
||||
print_crate_inner(&mut s, krate, false, edition, g);
|
||||
s.s.eof()
|
||||
}
|
||||
|
||||
fn print_crate_inner<'a>(
|
||||
s: &mut State<'a>,
|
||||
krate: &ast::Crate,
|
||||
is_expanded: bool,
|
||||
edition: Edition,
|
||||
g: &AttrIdGenerator,
|
||||
) {
|
||||
// We need to print shebang before anything else
|
||||
// otherwise the resulting code will not compile
|
||||
// and shebang will be useless.
|
||||
|
|
@ -282,8 +310,7 @@ pub fn print_crate<'a>(
|
|||
s.print_item(item);
|
||||
}
|
||||
s.print_remaining_comments();
|
||||
s.ann.post(&mut s, AnnNode::Crate(krate));
|
||||
s.s.eof()
|
||||
s.ann.post(s, AnnNode::Crate(krate));
|
||||
}
|
||||
|
||||
/// Should two consecutive tokens be printed with a space between them?
|
||||
|
|
@ -1111,7 +1138,7 @@ impl<'a> PrintState<'a> for State<'a> {
|
|||
|
||||
impl<'a> State<'a> {
|
||||
pub fn new() -> State<'a> {
|
||||
State { s: pp::Printer::new(), comments: None, ann: &NoAnn }
|
||||
State { s: pp::Printer::new(), comments: None, ann: &NoAnn, is_sdylib_interface: false }
|
||||
}
|
||||
|
||||
fn commasep_cmnt<T, F, G>(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rustc_ast::{
|
|||
|
||||
use crate::pp::Breaks::Inconsistent;
|
||||
use crate::pprust::state::fixup::FixupContext;
|
||||
use crate::pprust::state::{AnnNode, BoxMarker, INDENT_UNIT, PrintState, State};
|
||||
use crate::pprust::state::{AnnNode, INDENT_UNIT, PrintState, State};
|
||||
|
||||
impl<'a> State<'a> {
|
||||
fn print_else(&mut self, els: Option<&ast::Expr>) {
|
||||
|
|
@ -485,12 +485,12 @@ impl<'a> State<'a> {
|
|||
self.print_block_with_attrs(body, attrs, cb, ib);
|
||||
}
|
||||
ast::ExprKind::Loop(blk, opt_label, _) => {
|
||||
let cb = self.cbox(0);
|
||||
let ib = self.ibox(0);
|
||||
if let Some(label) = opt_label {
|
||||
self.print_ident(label.ident);
|
||||
self.word_space(":");
|
||||
}
|
||||
let cb = self.cbox(0);
|
||||
let ib = self.ibox(0);
|
||||
self.word_nbsp("loop");
|
||||
self.print_block_with_attrs(blk, attrs, cb, ib);
|
||||
}
|
||||
|
|
@ -542,15 +542,6 @@ impl<'a> State<'a> {
|
|||
self.print_fn_params_and_ret(fn_decl, true);
|
||||
self.space();
|
||||
self.print_expr(body, FixupContext::default());
|
||||
// FIXME(nnethercote): Bogus. Reduce visibility of `ended` once it's fixed.
|
||||
let fake_ib = BoxMarker;
|
||||
self.end(fake_ib);
|
||||
|
||||
// A box will be closed by print_expr, but we didn't want an overall
|
||||
// wrapper so we closed the corresponding opening. so create an
|
||||
// empty box to satisfy the close.
|
||||
// FIXME(nnethercote): Bogus.
|
||||
let _ib = self.ibox(0);
|
||||
}
|
||||
ast::ExprKind::Block(blk, opt_label) => {
|
||||
if let Some(label) = opt_label {
|
||||
|
|
|
|||
|
|
@ -160,6 +160,10 @@ impl<'a> State<'a> {
|
|||
|
||||
/// Pretty-prints an item.
|
||||
pub(crate) fn print_item(&mut self, item: &ast::Item) {
|
||||
if self.is_sdylib_interface && item.span.is_dummy() {
|
||||
// Do not print prelude for interface files.
|
||||
return;
|
||||
}
|
||||
self.hardbreak_if_not_bol();
|
||||
self.maybe_print_comment(item.span.lo());
|
||||
self.print_outer_attributes(&item.attrs);
|
||||
|
|
@ -682,6 +686,13 @@ impl<'a> State<'a> {
|
|||
self.print_contract(contract);
|
||||
}
|
||||
if let Some((body, (cb, ib))) = body_cb_ib {
|
||||
if self.is_sdylib_interface {
|
||||
self.word(";");
|
||||
self.end(ib); // end inner head-block
|
||||
self.end(cb); // end outer head-block
|
||||
return;
|
||||
}
|
||||
|
||||
self.nbsp();
|
||||
self.print_block_with_attrs(body, attrs, cb, ib);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ fn parse_unstable<'a>(
|
|||
|
||||
for param in list.mixed() {
|
||||
let param_span = param.span();
|
||||
if let Some(ident) = param.meta_item().and_then(|i| i.word_without_args()) {
|
||||
if let Some(ident) = param.meta_item().and_then(|i| i.path_without_args().word()) {
|
||||
res.push(ident.name);
|
||||
} else {
|
||||
cx.emit_err(session_diagnostics::ExpectsFeatures {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use rustc_attr_data_structures::{AttributeKind, DeprecatedSince, Deprecation};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use super::SingleAttributeParser;
|
||||
|
|
@ -13,16 +12,13 @@ pub(crate) struct DeprecationParser;
|
|||
|
||||
fn get(
|
||||
cx: &AcceptContext<'_>,
|
||||
ident: Ident,
|
||||
name: Symbol,
|
||||
param_span: Span,
|
||||
arg: &ArgParser<'_>,
|
||||
item: &Option<Symbol>,
|
||||
) -> Option<Symbol> {
|
||||
if item.is_some() {
|
||||
cx.emit_err(session_diagnostics::MultipleItem {
|
||||
span: param_span,
|
||||
item: ident.to_string(),
|
||||
});
|
||||
cx.emit_err(session_diagnostics::MultipleItem { span: param_span, item: name.to_string() });
|
||||
return None;
|
||||
}
|
||||
if let Some(v) = arg.name_value() {
|
||||
|
|
@ -83,16 +79,16 @@ impl SingleAttributeParser for DeprecationParser {
|
|||
return None;
|
||||
};
|
||||
|
||||
let (ident, arg) = param.word_or_empty();
|
||||
let ident_name = param.path_without_args().word_sym();
|
||||
|
||||
match ident.name {
|
||||
sym::since => {
|
||||
since = Some(get(cx, ident, param_span, arg, &since)?);
|
||||
match ident_name {
|
||||
Some(name @ sym::since) => {
|
||||
since = Some(get(cx, name, param_span, param.args(), &since)?);
|
||||
}
|
||||
sym::note => {
|
||||
note = Some(get(cx, ident, param_span, arg, ¬e)?);
|
||||
Some(name @ sym::note) => {
|
||||
note = Some(get(cx, name, param_span, param.args(), ¬e)?);
|
||||
}
|
||||
sym::suggestion => {
|
||||
Some(name @ sym::suggestion) => {
|
||||
if !features.deprecated_suggestion() {
|
||||
cx.emit_err(session_diagnostics::DeprecatedItemSuggestion {
|
||||
span: param_span,
|
||||
|
|
@ -101,12 +97,12 @@ impl SingleAttributeParser for DeprecationParser {
|
|||
});
|
||||
}
|
||||
|
||||
suggestion = Some(get(cx, ident, param_span, arg, &suggestion)?);
|
||||
suggestion = Some(get(cx, name, param_span, param.args(), &suggestion)?);
|
||||
}
|
||||
_ => {
|
||||
cx.emit_err(session_diagnostics::UnknownMetaItem {
|
||||
span: param_span,
|
||||
item: ident.to_string(),
|
||||
item: param.path_without_args().to_string(),
|
||||
expected: if features.deprecated_suggestion() {
|
||||
&["since", "note", "suggestion"]
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -96,58 +96,75 @@ fn parse_repr(cx: &AcceptContext<'_>, param: &MetaItemParser<'_>) -> Option<Repr
|
|||
|
||||
// FIXME(jdonszelmann): invert the parsing here to match on the word first and then the
|
||||
// structure.
|
||||
let (ident, args) = param.word_or_empty();
|
||||
let (name, ident_span) = if let Some(ident) = param.path_without_args().word() {
|
||||
(Some(ident.name), ident.span)
|
||||
} else {
|
||||
(None, rustc_span::DUMMY_SP)
|
||||
};
|
||||
|
||||
match (ident.name, args) {
|
||||
(sym::align, ArgParser::NoArgs) => {
|
||||
cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident.span });
|
||||
let args = param.args();
|
||||
|
||||
match (name, args) {
|
||||
(Some(sym::align), ArgParser::NoArgs) => {
|
||||
cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident_span });
|
||||
None
|
||||
}
|
||||
(sym::align, ArgParser::List(l)) => parse_repr_align(cx, l, param.span(), AlignKind::Align),
|
||||
(Some(sym::align), ArgParser::List(l)) => {
|
||||
parse_repr_align(cx, l, param.span(), AlignKind::Align)
|
||||
}
|
||||
|
||||
(sym::packed, ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)),
|
||||
(sym::packed, ArgParser::List(l)) => {
|
||||
(Some(sym::packed), ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)),
|
||||
(Some(sym::packed), ArgParser::List(l)) => {
|
||||
parse_repr_align(cx, l, param.span(), AlignKind::Packed)
|
||||
}
|
||||
|
||||
(sym::align | sym::packed, ArgParser::NameValue(l)) => {
|
||||
(Some(name @ sym::align | name @ sym::packed), ArgParser::NameValue(l)) => {
|
||||
cx.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
|
||||
span: param.span(),
|
||||
// FIXME(jdonszelmann) can just be a string in the diag type
|
||||
repr_arg: &ident.to_string(),
|
||||
repr_arg: name,
|
||||
cause: IncorrectReprFormatGenericCause::from_lit_kind(
|
||||
param.span(),
|
||||
&l.value_as_lit().kind,
|
||||
ident.name.as_str(),
|
||||
name,
|
||||
),
|
||||
});
|
||||
None
|
||||
}
|
||||
|
||||
(sym::Rust, ArgParser::NoArgs) => Some(ReprRust),
|
||||
(sym::C, ArgParser::NoArgs) => Some(ReprC),
|
||||
(sym::simd, ArgParser::NoArgs) => Some(ReprSimd),
|
||||
(sym::transparent, ArgParser::NoArgs) => Some(ReprTransparent),
|
||||
(i @ int_pat!(), ArgParser::NoArgs) => {
|
||||
(Some(sym::Rust), ArgParser::NoArgs) => Some(ReprRust),
|
||||
(Some(sym::C), ArgParser::NoArgs) => Some(ReprC),
|
||||
(Some(sym::simd), ArgParser::NoArgs) => Some(ReprSimd),
|
||||
(Some(sym::transparent), ArgParser::NoArgs) => Some(ReprTransparent),
|
||||
(Some(name @ int_pat!()), ArgParser::NoArgs) => {
|
||||
// int_pat!() should make sure it always parses
|
||||
Some(ReprInt(int_type_of_word(i).unwrap()))
|
||||
Some(ReprInt(int_type_of_word(name).unwrap()))
|
||||
}
|
||||
|
||||
(
|
||||
sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(),
|
||||
Some(
|
||||
name @ sym::Rust
|
||||
| name @ sym::C
|
||||
| name @ sym::simd
|
||||
| name @ sym::transparent
|
||||
| name @ int_pat!(),
|
||||
),
|
||||
ArgParser::NameValue(_),
|
||||
) => {
|
||||
cx.emit_err(session_diagnostics::InvalidReprHintNoValue {
|
||||
span: param.span(),
|
||||
name: ident.to_string(),
|
||||
});
|
||||
cx.emit_err(session_diagnostics::InvalidReprHintNoValue { span: param.span(), name });
|
||||
None
|
||||
}
|
||||
(sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(), ArgParser::List(_)) => {
|
||||
cx.emit_err(session_diagnostics::InvalidReprHintNoParen {
|
||||
span: param.span(),
|
||||
name: ident.to_string(),
|
||||
});
|
||||
(
|
||||
Some(
|
||||
name @ sym::Rust
|
||||
| name @ sym::C
|
||||
| name @ sym::simd
|
||||
| name @ sym::transparent
|
||||
| name @ int_pat!(),
|
||||
),
|
||||
ArgParser::List(_),
|
||||
) => {
|
||||
cx.emit_err(session_diagnostics::InvalidReprHintNoParen { span: param.span(), name });
|
||||
None
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,9 +242,9 @@ pub(crate) fn parse_stability(
|
|||
return None;
|
||||
};
|
||||
|
||||
match param.word_or_empty_without_args().name {
|
||||
sym::feature => insert_value_into_option_or_error(cx, ¶m, &mut feature)?,
|
||||
sym::since => insert_value_into_option_or_error(cx, ¶m, &mut since)?,
|
||||
match param.path_without_args().word_sym() {
|
||||
Some(sym::feature) => insert_value_into_option_or_error(cx, ¶m, &mut feature)?,
|
||||
Some(sym::since) => insert_value_into_option_or_error(cx, ¶m, &mut since)?,
|
||||
_ => {
|
||||
cx.emit_err(session_diagnostics::UnknownMetaItem {
|
||||
span: param_span,
|
||||
|
|
@ -310,11 +310,10 @@ pub(crate) fn parse_unstability(
|
|||
return None;
|
||||
};
|
||||
|
||||
let (word, args) = param.word_or_empty();
|
||||
match word.name {
|
||||
sym::feature => insert_value_into_option_or_error(cx, ¶m, &mut feature)?,
|
||||
sym::reason => insert_value_into_option_or_error(cx, ¶m, &mut reason)?,
|
||||
sym::issue => {
|
||||
match param.path_without_args().word_sym() {
|
||||
Some(sym::feature) => insert_value_into_option_or_error(cx, ¶m, &mut feature)?,
|
||||
Some(sym::reason) => insert_value_into_option_or_error(cx, ¶m, &mut reason)?,
|
||||
Some(sym::issue) => {
|
||||
insert_value_into_option_or_error(cx, ¶m, &mut issue)?;
|
||||
|
||||
// These unwraps are safe because `insert_value_into_option_or_error` ensures the meta item
|
||||
|
|
@ -328,7 +327,7 @@ pub(crate) fn parse_unstability(
|
|||
session_diagnostics::InvalidIssueString {
|
||||
span: param.span(),
|
||||
cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind(
|
||||
args.name_value().unwrap().value_span,
|
||||
param.args().name_value().unwrap().value_span,
|
||||
err.kind(),
|
||||
),
|
||||
},
|
||||
|
|
@ -338,13 +337,15 @@ pub(crate) fn parse_unstability(
|
|||
},
|
||||
};
|
||||
}
|
||||
sym::soft => {
|
||||
if !args.no_args() {
|
||||
Some(sym::soft) => {
|
||||
if !param.args().no_args() {
|
||||
cx.emit_err(session_diagnostics::SoftNoArgs { span: param.span() });
|
||||
}
|
||||
is_soft = true;
|
||||
}
|
||||
sym::implied_by => insert_value_into_option_or_error(cx, ¶m, &mut implied_by)?,
|
||||
Some(sym::implied_by) => {
|
||||
insert_value_into_option_or_error(cx, ¶m, &mut implied_by)?
|
||||
}
|
||||
_ => {
|
||||
cx.emit_err(session_diagnostics::UnknownMetaItem {
|
||||
span: param.span(),
|
||||
|
|
|
|||
|
|
@ -78,8 +78,8 @@ impl<'a> PathParser<'a> {
|
|||
(self.len() == 1).then(|| **self.segments().next().as_ref().unwrap())
|
||||
}
|
||||
|
||||
pub fn word_or_empty(&self) -> Ident {
|
||||
self.word().unwrap_or_else(Ident::empty)
|
||||
pub fn word_sym(&self) -> Option<Symbol> {
|
||||
self.word().map(|ident| ident.name)
|
||||
}
|
||||
|
||||
/// Asserts that this MetaItem is some specific word.
|
||||
|
|
@ -284,11 +284,6 @@ impl<'a> MetaItemParser<'a> {
|
|||
Some(self.word()?.0)
|
||||
}
|
||||
|
||||
/// Like [`word`](Self::word), but returns an empty symbol instead of None
|
||||
pub fn word_or_empty_without_args(&self) -> Ident {
|
||||
self.word_or_empty().0
|
||||
}
|
||||
|
||||
/// Asserts that this MetaItem starts with a word, or single segment path.
|
||||
///
|
||||
/// Some examples:
|
||||
|
|
@ -300,12 +295,6 @@ impl<'a> MetaItemParser<'a> {
|
|||
Some((path.word()?, args))
|
||||
}
|
||||
|
||||
/// Like [`word`](Self::word), but returns an empty symbol instead of None
|
||||
pub fn word_or_empty(&self) -> (Ident, &ArgParser<'a>) {
|
||||
let (path, args) = self.deconstruct();
|
||||
(path.word().unwrap_or(Ident::empty()), args)
|
||||
}
|
||||
|
||||
/// Asserts that this MetaItem starts with some specific word.
|
||||
///
|
||||
/// See [`word`](Self::word) for examples of what a word is.
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ pub(crate) struct InvalidReprHintNoParen {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
pub name: String,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
@ -213,7 +213,7 @@ pub(crate) struct InvalidReprHintNoValue {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
pub name: String,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
/// Error code: E0565
|
||||
|
|
@ -295,21 +295,21 @@ pub(crate) struct IncorrectReprFormatExpectInteger {
|
|||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_generic, code = E0693)]
|
||||
pub(crate) struct IncorrectReprFormatGeneric<'a> {
|
||||
pub(crate) struct IncorrectReprFormatGeneric {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
pub repr_arg: &'a str,
|
||||
pub repr_arg: Symbol,
|
||||
|
||||
#[subdiagnostic]
|
||||
pub cause: Option<IncorrectReprFormatGenericCause<'a>>,
|
||||
pub cause: Option<IncorrectReprFormatGenericCause>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum IncorrectReprFormatGenericCause<'a> {
|
||||
pub(crate) enum IncorrectReprFormatGenericCause {
|
||||
#[suggestion(
|
||||
attr_parsing_suggestion,
|
||||
code = "{name}({int})",
|
||||
code = "{name}({value})",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
Int {
|
||||
|
|
@ -317,15 +317,15 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
|
|||
span: Span,
|
||||
|
||||
#[skip_arg]
|
||||
name: &'a str,
|
||||
name: Symbol,
|
||||
|
||||
#[skip_arg]
|
||||
int: u128,
|
||||
value: u128,
|
||||
},
|
||||
|
||||
#[suggestion(
|
||||
attr_parsing_suggestion,
|
||||
code = "{name}({symbol})",
|
||||
code = "{name}({value})",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
Symbol {
|
||||
|
|
@ -333,20 +333,20 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
|
|||
span: Span,
|
||||
|
||||
#[skip_arg]
|
||||
name: &'a str,
|
||||
name: Symbol,
|
||||
|
||||
#[skip_arg]
|
||||
symbol: Symbol,
|
||||
value: Symbol,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> IncorrectReprFormatGenericCause<'a> {
|
||||
pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option<Self> {
|
||||
match kind {
|
||||
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
|
||||
Some(Self::Int { span, name, int: int.get() })
|
||||
impl IncorrectReprFormatGenericCause {
|
||||
pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: Symbol) -> Option<Self> {
|
||||
match *kind {
|
||||
ast::LitKind::Int(value, ast::LitIntType::Unsuffixed) => {
|
||||
Some(Self::Int { span, name, value: value.get() })
|
||||
}
|
||||
ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }),
|
||||
ast::LitKind::Str(value, _) => Some(Self::Symbol { span, name, value }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2954,12 +2954,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let name = if borrow_span.in_external_macro(self.infcx.tcx.sess.source_map()) {
|
||||
// Don't name local variables in external macros.
|
||||
"value".to_string()
|
||||
} else {
|
||||
format!("`{name}`")
|
||||
};
|
||||
let name = format!("`{name}`");
|
||||
|
||||
let mut err = self.path_does_not_live_long_enough(borrow_span, &name);
|
||||
|
||||
|
|
|
|||
|
|
@ -317,6 +317,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
opt: DescribePlaceOpt,
|
||||
) -> Option<String> {
|
||||
let local = place.local;
|
||||
if self.body.local_decls[local]
|
||||
.source_info
|
||||
.span
|
||||
.in_external_macro(self.infcx.tcx.sess.source_map())
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut autoderef_index = None;
|
||||
let mut buf = String::new();
|
||||
let mut ok = self.append_local_to_string(local, &mut buf);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ use rustc_mir_dataflow::impls::{
|
|||
use rustc_mir_dataflow::move_paths::{
|
||||
InitIndex, InitLocation, LookupResult, MoveData, MovePathIndex,
|
||||
};
|
||||
use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results};
|
||||
use rustc_mir_dataflow::{Analysis, Results, ResultsVisitor, visit_results};
|
||||
use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER, UNUSED_MUT};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
use smallvec::SmallVec;
|
||||
|
|
@ -127,6 +127,14 @@ fn mir_borrowck(
|
|||
Ok(tcx.arena.alloc(opaque_types))
|
||||
} else {
|
||||
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def);
|
||||
// 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.
|
||||
let nested_bodies = tcx.nested_bodies_within(def);
|
||||
for def_id in nested_bodies {
|
||||
root_cx.get_or_insert_nested(def_id);
|
||||
}
|
||||
|
||||
let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
|
||||
do_mir_borrowck(&mut root_cx, def, None).0;
|
||||
debug_assert!(closure_requirements.is_none());
|
||||
|
|
@ -461,11 +469,13 @@ fn do_mir_borrowck<'tcx>(
|
|||
// Compute and report region errors, if any.
|
||||
mbcx.report_region_errors(nll_errors);
|
||||
|
||||
let mut flow_results = get_flow_results(tcx, body, &move_data, &borrow_set, ®ioncx);
|
||||
let (mut flow_analysis, flow_entry_states) =
|
||||
get_flow_results(tcx, body, &move_data, &borrow_set, ®ioncx);
|
||||
visit_results(
|
||||
body,
|
||||
traversal::reverse_postorder(body).map(|(bb, _)| bb),
|
||||
&mut flow_results,
|
||||
&mut flow_analysis,
|
||||
&flow_entry_states,
|
||||
&mut mbcx,
|
||||
);
|
||||
|
||||
|
|
@ -525,7 +535,7 @@ fn get_flow_results<'a, 'tcx>(
|
|||
move_data: &'a MoveData<'tcx>,
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
regioncx: &RegionInferenceContext<'tcx>,
|
||||
) -> Results<'tcx, Borrowck<'a, 'tcx>> {
|
||||
) -> (Borrowck<'a, 'tcx>, Results<BorrowckDomain>) {
|
||||
// We compute these three analyses individually, but them combine them into
|
||||
// a single results so that `mbcx` can visit them all together.
|
||||
let borrows = Borrows::new(tcx, body, regioncx, borrow_set).iterate_to_fixpoint(
|
||||
|
|
@ -550,14 +560,14 @@ fn get_flow_results<'a, 'tcx>(
|
|||
ever_inits: ever_inits.analysis,
|
||||
};
|
||||
|
||||
assert_eq!(borrows.entry_states.len(), uninits.entry_states.len());
|
||||
assert_eq!(borrows.entry_states.len(), ever_inits.entry_states.len());
|
||||
let entry_states: EntryStates<'_, Borrowck<'_, '_>> =
|
||||
itertools::izip!(borrows.entry_states, uninits.entry_states, ever_inits.entry_states)
|
||||
assert_eq!(borrows.results.len(), uninits.results.len());
|
||||
assert_eq!(borrows.results.len(), ever_inits.results.len());
|
||||
let results: Results<_> =
|
||||
itertools::izip!(borrows.results, uninits.results, ever_inits.results)
|
||||
.map(|(borrows, uninits, ever_inits)| BorrowckDomain { borrows, uninits, ever_inits })
|
||||
.collect();
|
||||
|
||||
Results { analysis, entry_states }
|
||||
(analysis, results)
|
||||
}
|
||||
|
||||
pub(crate) struct BorrowckInferCtxt<'tcx> {
|
||||
|
|
@ -705,7 +715,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
|
|||
impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> {
|
||||
fn visit_after_early_statement_effect(
|
||||
&mut self,
|
||||
_results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
|
||||
_analysis: &mut Borrowck<'a, 'tcx>,
|
||||
state: &BorrowckDomain,
|
||||
stmt: &Statement<'tcx>,
|
||||
location: Location,
|
||||
|
|
@ -781,7 +791,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a,
|
|||
|
||||
fn visit_after_early_terminator_effect(
|
||||
&mut self,
|
||||
_results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
|
||||
_analysis: &mut Borrowck<'a, 'tcx>,
|
||||
state: &BorrowckDomain,
|
||||
term: &Terminator<'tcx>,
|
||||
loc: Location,
|
||||
|
|
@ -901,7 +911,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a,
|
|||
|
||||
fn visit_after_primary_terminator_effect(
|
||||
&mut self,
|
||||
_results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
|
||||
_analysis: &mut Borrowck<'a, 'tcx>,
|
||||
state: &BorrowckDomain,
|
||||
term: &Terminator<'tcx>,
|
||||
loc: Location,
|
||||
|
|
|
|||
|
|
@ -267,13 +267,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
return Ty::new_error(self.tcx, e);
|
||||
}
|
||||
|
||||
if let Err(guar) = check_opaque_type_parameter_valid(
|
||||
if let Err(err) = check_opaque_type_parameter_valid(
|
||||
self,
|
||||
opaque_type_key,
|
||||
instantiated_ty.span,
|
||||
DefiningScopeKind::MirBorrowck,
|
||||
) {
|
||||
return Ty::new_error(self.tcx, guar);
|
||||
return Ty::new_error(self.tcx, err.report(self));
|
||||
}
|
||||
|
||||
let definition_ty = instantiated_ty
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ use rustc_middle::ty::RegionVid;
|
|||
|
||||
use crate::RegionInferenceContext;
|
||||
use crate::constraints::ConstraintSccIndex;
|
||||
use crate::region_infer::ConstraintSccs;
|
||||
use crate::universal_regions::UniversalRegions;
|
||||
|
||||
pub(crate) struct ReverseSccGraph {
|
||||
graph: VecGraph<ConstraintSccIndex>,
|
||||
|
|
@ -19,6 +21,29 @@ pub(crate) struct ReverseSccGraph {
|
|||
}
|
||||
|
||||
impl ReverseSccGraph {
|
||||
pub(super) fn compute(
|
||||
constraint_sccs: &ConstraintSccs,
|
||||
universal_regions: &UniversalRegions<'_>,
|
||||
) -> Self {
|
||||
let graph = constraint_sccs.reverse();
|
||||
let mut paired_scc_regions = universal_regions
|
||||
.universal_regions_iter()
|
||||
.map(|region| (constraint_sccs.scc(region), region))
|
||||
.collect::<Vec<_>>();
|
||||
paired_scc_regions.sort();
|
||||
let universal_regions = paired_scc_regions.iter().map(|&(_, region)| region).collect();
|
||||
|
||||
let mut scc_regions = FxIndexMap::default();
|
||||
let mut start = 0;
|
||||
for chunk in paired_scc_regions.chunk_by(|&(scc1, _), &(scc2, _)| scc1 == scc2) {
|
||||
let (scc, _) = chunk[0];
|
||||
|
||||
scc_regions.insert(scc, start..start + chunk.len());
|
||||
start += chunk.len();
|
||||
}
|
||||
ReverseSccGraph { graph, scc_regions, universal_regions }
|
||||
}
|
||||
|
||||
/// Find all universal regions that are required to outlive the given SCC.
|
||||
pub(super) fn upper_bounds(&self, scc0: ConstraintSccIndex) -> impl Iterator<Item = RegionVid> {
|
||||
let mut duplicates = FxIndexSet::default();
|
||||
|
|
@ -40,23 +65,7 @@ impl RegionInferenceContext<'_> {
|
|||
return;
|
||||
}
|
||||
|
||||
let graph = self.constraint_sccs.reverse();
|
||||
let mut paired_scc_regions = self
|
||||
.universal_regions()
|
||||
.universal_regions_iter()
|
||||
.map(|region| (self.constraint_sccs.scc(region), region))
|
||||
.collect::<Vec<_>>();
|
||||
paired_scc_regions.sort();
|
||||
let universal_regions = paired_scc_regions.iter().map(|&(_, region)| region).collect();
|
||||
|
||||
let mut scc_regions = FxIndexMap::default();
|
||||
let mut start = 0;
|
||||
for chunk in paired_scc_regions.chunk_by(|&(scc1, _), &(scc2, _)| scc1 == scc2) {
|
||||
let (scc, _) = chunk[0];
|
||||
scc_regions.insert(scc, start..start + chunk.len());
|
||||
start += chunk.len();
|
||||
}
|
||||
|
||||
self.rev_scc_graph = Some(ReverseSccGraph { graph, scc_regions, universal_regions });
|
||||
self.rev_scc_graph =
|
||||
Some(ReverseSccGraph::compute(&self.constraint_sccs, self.universal_regions()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,10 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
|
|||
self.tainted_by_errors = Some(guar);
|
||||
}
|
||||
|
||||
fn get_or_insert_nested(&mut self, def_id: LocalDefId) -> &PropagatedBorrowCheckResults<'tcx> {
|
||||
pub(super) fn get_or_insert_nested(
|
||||
&mut self,
|
||||
def_id: LocalDefId,
|
||||
) -> &PropagatedBorrowCheckResults<'tcx> {
|
||||
debug_assert_eq!(
|
||||
self.tcx.typeck_root_def_id(def_id.to_def_id()),
|
||||
self.root_def_id.to_def_id()
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
|
|||
|
||||
pub(crate) struct CreateResult<'tcx> {
|
||||
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
pub(crate) region_bound_pairs: RegionBoundPairs<'tcx>,
|
||||
pub(crate) known_type_outlives_obligations: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
|
||||
pub(crate) region_bound_pairs: Frozen<RegionBoundPairs<'tcx>>,
|
||||
pub(crate) known_type_outlives_obligations: Frozen<Vec<ty::PolyTypeOutlivesPredicate<'tcx>>>,
|
||||
pub(crate) normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
|
||||
}
|
||||
|
||||
|
|
@ -333,8 +333,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
outlives: self.outlives.freeze(),
|
||||
inverse_outlives: self.inverse_outlives.freeze(),
|
||||
}),
|
||||
known_type_outlives_obligations,
|
||||
region_bound_pairs: self.region_bound_pairs,
|
||||
known_type_outlives_obligations: Frozen::freeze(known_type_outlives_obligations),
|
||||
region_bound_pairs: Frozen::freeze(self.region_bound_pairs),
|
||||
normalized_inputs_and_output,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,8 +151,8 @@ pub(crate) fn type_check<'a, 'tcx>(
|
|||
body,
|
||||
promoted,
|
||||
user_type_annotations: &body.user_type_annotations,
|
||||
region_bound_pairs,
|
||||
known_type_outlives_obligations,
|
||||
region_bound_pairs: ®ion_bound_pairs,
|
||||
known_type_outlives_obligations: &known_type_outlives_obligations,
|
||||
reported_errors: Default::default(),
|
||||
universal_regions: &universal_region_relations.universal_regions,
|
||||
location_table,
|
||||
|
|
@ -216,8 +216,8 @@ struct TypeChecker<'a, 'tcx> {
|
|||
/// User type annotations are shared between the main MIR and the MIR of
|
||||
/// all of the promoted items.
|
||||
user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
|
||||
region_bound_pairs: RegionBoundPairs<'tcx>,
|
||||
known_type_outlives_obligations: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
|
||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||
known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
|
||||
universal_regions: &'a UniversalRegions<'tcx>,
|
||||
location_table: &'a PoloniusLocationTable,
|
||||
|
|
@ -412,9 +412,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
constraint_conversion::ConstraintConversion::new(
|
||||
self.infcx,
|
||||
self.universal_regions,
|
||||
&self.region_bound_pairs,
|
||||
self.region_bound_pairs,
|
||||
self.infcx.param_env,
|
||||
&self.known_type_outlives_obligations,
|
||||
self.known_type_outlives_obligations,
|
||||
locations,
|
||||
locations.span(self.body),
|
||||
category,
|
||||
|
|
@ -2506,9 +2506,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
constraint_conversion::ConstraintConversion::new(
|
||||
self.infcx,
|
||||
self.universal_regions,
|
||||
&self.region_bound_pairs,
|
||||
self.region_bound_pairs,
|
||||
self.infcx.param_env,
|
||||
&self.known_type_outlives_obligations,
|
||||
self.known_type_outlives_obligations,
|
||||
locations,
|
||||
self.body.span, // irrelevant; will be overridden.
|
||||
ConstraintCategory::Boring, // same as above.
|
||||
|
|
|
|||
|
|
@ -266,10 +266,6 @@ impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for ConstrainOpaqueTypeRegionVisitor<'t
|
|||
where
|
||||
OP: FnMut(ty::Region<'tcx>),
|
||||
{
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
|
||||
t.super_visit_with(self);
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) {
|
||||
match r.kind() {
|
||||
// ignore bound regions, keep visiting
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::ops::Range;
|
||||
|
||||
use parse::Position::ArgumentNamed;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
|
|
@ -335,7 +337,7 @@ fn make_format_args(
|
|||
return ExpandResult::Ready(Err(guar));
|
||||
}
|
||||
|
||||
let to_span = |inner_span: parse::InnerSpan| {
|
||||
let to_span = |inner_span: Range<usize>| {
|
||||
is_source_literal.then(|| {
|
||||
fmt_span.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end })
|
||||
})
|
||||
|
|
@ -407,7 +409,7 @@ fn make_format_args(
|
|||
let mut placeholder_index = 0;
|
||||
|
||||
for piece in &pieces {
|
||||
match *piece {
|
||||
match piece.clone() {
|
||||
parse::Piece::Lit(s) => {
|
||||
unfinished_literal.push_str(s);
|
||||
}
|
||||
|
|
@ -417,7 +419,8 @@ fn make_format_args(
|
|||
unfinished_literal.clear();
|
||||
}
|
||||
|
||||
let span = parser.arg_places.get(placeholder_index).and_then(|&s| to_span(s));
|
||||
let span =
|
||||
parser.arg_places.get(placeholder_index).and_then(|s| to_span(s.clone()));
|
||||
placeholder_index += 1;
|
||||
|
||||
let position_span = to_span(position_span);
|
||||
|
|
@ -609,7 +612,7 @@ fn make_format_args(
|
|||
fn invalid_placeholder_type_error(
|
||||
ecx: &ExtCtxt<'_>,
|
||||
ty: &str,
|
||||
ty_span: Option<parse::InnerSpan>,
|
||||
ty_span: Option<Range<usize>>,
|
||||
fmt_span: Span,
|
||||
) {
|
||||
let sp = ty_span.map(|sp| fmt_span.from_inner(InnerSpan::new(sp.start, sp.end)));
|
||||
|
|
|
|||
|
|
@ -1282,7 +1282,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
intrinsic.name,
|
||||
);
|
||||
}
|
||||
return Err(Instance::new(instance.def_id(), instance.args));
|
||||
return Err(Instance::new_raw(instance.def_id(), instance.args));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,11 @@ use crate::{GccCodegenBackend, GccContext, SyncContext, to_gcc_opt_level};
|
|||
|
||||
pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
|
||||
match crate_type {
|
||||
CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
|
||||
CrateType::Executable
|
||||
| CrateType::Dylib
|
||||
| CrateType::Staticlib
|
||||
| CrateType::Cdylib
|
||||
| CrateType::Sdylib => true,
|
||||
CrateType::Rlib | CrateType::ProcMacro => false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -399,7 +399,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
|||
}
|
||||
|
||||
// Fall back to default body
|
||||
_ => return Err(Instance::new(instance.def_id(), instance.args)),
|
||||
_ => return Err(Instance::new_raw(instance.def_id(), instance.args)),
|
||||
};
|
||||
|
||||
if !fn_abi.ret.is_ignore() {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ fn crate_type_allows_lto(crate_type: CrateType) -> bool {
|
|||
| CrateType::Dylib
|
||||
| CrateType::Staticlib
|
||||
| CrateType::Cdylib
|
||||
| CrateType::ProcMacro => true,
|
||||
| CrateType::ProcMacro
|
||||
| CrateType::Sdylib => true,
|
||||
CrateType::Rlib => false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -364,7 +364,12 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
|
||||
if !def_id.is_local() {
|
||||
let needs_dll_storage_attr = self.use_dll_storage_attrs
|
||||
&& !self.tcx.is_foreign_item(def_id)
|
||||
// If the symbol is a foreign item, then don't automatically apply DLLImport, as
|
||||
// we'll rely on the #[link] attribute instead. BUT, if this is an internal symbol
|
||||
// then it may be generated by the compiler in some crate, so we do need to apply
|
||||
// DLLImport when linking with the MSVC linker.
|
||||
&& (!self.tcx.is_foreign_item(def_id)
|
||||
|| (self.sess().target.is_like_msvc && fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)))
|
||||
// Local definitions can never be imported, so we must not apply
|
||||
// the DLLImport annotation.
|
||||
&& !dso_local
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ fn make_dummy_instance<'tcx>(tcx: TyCtxt<'tcx>, local_def_id: LocalDefId) -> ty:
|
|||
let def_id = local_def_id.to_def_id();
|
||||
|
||||
// Make a dummy instance that fills in all generics with placeholders.
|
||||
ty::Instance::new(
|
||||
ty::Instance::new_raw(
|
||||
def_id,
|
||||
ty::GenericArgs::for_item(tcx, def_id, |param, _| {
|
||||
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
||||
|
|
|
|||
|
|
@ -95,7 +95,11 @@ pub(crate) fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool {
|
|||
// in the `.debug_gdb_scripts` section. For that reason, we make sure that the
|
||||
// section is only emitted for leaf crates.
|
||||
let embed_visualizers = cx.tcx.crate_types().iter().any(|&crate_type| match crate_type {
|
||||
CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::Staticlib => {
|
||||
CrateType::Executable
|
||||
| CrateType::Dylib
|
||||
| CrateType::Cdylib
|
||||
| CrateType::Staticlib
|
||||
| CrateType::Sdylib => {
|
||||
// These are crate types for which we will embed pretty printers since they
|
||||
// are treated as leaf crates.
|
||||
true
|
||||
|
|
|
|||
|
|
@ -613,7 +613,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
_ => {
|
||||
debug!("unknown intrinsic '{}' -- falling back to default body", name);
|
||||
// Call the fallback body instead of generating the intrinsic code
|
||||
return Err(ty::Instance::new(instance.def_id(), instance.args));
|
||||
return Err(ty::Instance::new_raw(instance.def_id(), instance.args));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use rustc_session::config::{PrintKind, PrintRequest};
|
|||
use rustc_span::Symbol;
|
||||
use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
|
||||
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
|
||||
use crate::back::write::create_informational_target_machine;
|
||||
use crate::errors::{
|
||||
|
|
@ -180,27 +181,27 @@ impl<'a> TargetFeatureFoldStrength<'a> {
|
|||
|
||||
pub(crate) struct LLVMFeature<'a> {
|
||||
llvm_feature_name: &'a str,
|
||||
dependency: Option<TargetFeatureFoldStrength<'a>>,
|
||||
dependencies: SmallVec<[TargetFeatureFoldStrength<'a>; 1]>,
|
||||
}
|
||||
|
||||
impl<'a> LLVMFeature<'a> {
|
||||
fn new(llvm_feature_name: &'a str) -> Self {
|
||||
Self { llvm_feature_name, dependency: None }
|
||||
Self { llvm_feature_name, dependencies: SmallVec::new() }
|
||||
}
|
||||
|
||||
fn with_dependency(
|
||||
fn with_dependencies(
|
||||
llvm_feature_name: &'a str,
|
||||
dependency: TargetFeatureFoldStrength<'a>,
|
||||
dependencies: SmallVec<[TargetFeatureFoldStrength<'a>; 1]>,
|
||||
) -> Self {
|
||||
Self { llvm_feature_name, dependency: Some(dependency) }
|
||||
Self { llvm_feature_name, dependencies }
|
||||
}
|
||||
|
||||
fn contains(&self, feat: &str) -> bool {
|
||||
fn contains(&'a self, feat: &str) -> bool {
|
||||
self.iter().any(|dep| dep == feat)
|
||||
}
|
||||
|
||||
fn iter(&'a self) -> impl Iterator<Item = &'a str> {
|
||||
let dependencies = self.dependency.iter().map(|feat| feat.as_str());
|
||||
let dependencies = self.dependencies.iter().map(|feat| feat.as_str());
|
||||
std::iter::once(self.llvm_feature_name).chain(dependencies)
|
||||
}
|
||||
}
|
||||
|
|
@ -210,7 +211,7 @@ impl<'a> IntoIterator for LLVMFeature<'a> {
|
|||
type IntoIter = impl Iterator<Item = &'a str>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
let dependencies = self.dependency.into_iter().map(|feat| feat.as_str());
|
||||
let dependencies = self.dependencies.into_iter().map(|feat| feat.as_str());
|
||||
std::iter::once(self.llvm_feature_name).chain(dependencies)
|
||||
}
|
||||
}
|
||||
|
|
@ -240,9 +241,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
|
|||
&*sess.target.arch
|
||||
};
|
||||
match (arch, s) {
|
||||
("x86", "sse4.2") => Some(LLVMFeature::with_dependency(
|
||||
("x86", "sse4.2") => Some(LLVMFeature::with_dependencies(
|
||||
"sse4.2",
|
||||
TargetFeatureFoldStrength::EnableOnly("crc32"),
|
||||
smallvec![TargetFeatureFoldStrength::EnableOnly("crc32")],
|
||||
)),
|
||||
("x86", "pclmulqdq") => Some(LLVMFeature::new("pclmul")),
|
||||
("x86", "rdrand") => Some(LLVMFeature::new("rdrnd")),
|
||||
|
|
@ -262,9 +263,10 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
|
|||
("aarch64", "sme-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")),
|
||||
("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")),
|
||||
// Rust ties fp and neon together.
|
||||
("aarch64", "neon") => {
|
||||
Some(LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8")))
|
||||
}
|
||||
("aarch64", "neon") => Some(LLVMFeature::with_dependencies(
|
||||
"neon",
|
||||
smallvec![TargetFeatureFoldStrength::Both("fp-armv8")],
|
||||
)),
|
||||
// In LLVM neon implicitly enables fp, but we manually enable
|
||||
// neon when a feature only implicitly enables fp
|
||||
("aarch64", "fhm") => Some(LLVMFeature::new("fp16fml")),
|
||||
|
|
@ -281,9 +283,10 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
|
|||
// Filter out features that are not supported by the current LLVM version
|
||||
("riscv32" | "riscv64", "zacas") if get_version().0 < 20 => None,
|
||||
// Enable the evex512 target feature if an avx512 target feature is enabled.
|
||||
("x86", s) if s.starts_with("avx512") => {
|
||||
Some(LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512")))
|
||||
}
|
||||
("x86", s) if s.starts_with("avx512") => Some(LLVMFeature::with_dependencies(
|
||||
s,
|
||||
smallvec![TargetFeatureFoldStrength::EnableOnly("evex512")],
|
||||
)),
|
||||
// Support for `wide-arithmetic` will first land in LLVM 20 as part of
|
||||
// llvm/llvm-project#111598
|
||||
("wasm32" | "wasm64", "wide-arithmetic") if get_version() < (20, 0, 0) => None,
|
||||
|
|
@ -301,6 +304,21 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
|
|||
None
|
||||
}
|
||||
("x86", "movrs") if get_version().0 < 20 => None,
|
||||
("x86", "avx10.1") => Some(LLVMFeature::new("avx10.1-512")),
|
||||
("x86", "avx10.2") if get_version().0 < 20 => None,
|
||||
("x86", "avx10.2") if get_version().0 >= 20 => Some(LLVMFeature::new("avx10.2-512")),
|
||||
("x86", "apxf") => Some(LLVMFeature::with_dependencies(
|
||||
"egpr",
|
||||
smallvec![
|
||||
TargetFeatureFoldStrength::Both("push2pop2"),
|
||||
TargetFeatureFoldStrength::Both("ppx"),
|
||||
TargetFeatureFoldStrength::Both("ndd"),
|
||||
TargetFeatureFoldStrength::Both("ccmp"),
|
||||
TargetFeatureFoldStrength::Both("cf"),
|
||||
TargetFeatureFoldStrength::Both("nf"),
|
||||
TargetFeatureFoldStrength::Both("zu"),
|
||||
],
|
||||
)),
|
||||
(_, s) => Some(LLVMFeature::new(s)),
|
||||
}
|
||||
}
|
||||
|
|
@ -850,7 +868,7 @@ pub(crate) fn global_llvm_features(
|
|||
"{}{}",
|
||||
enable_disable, llvm_feature.llvm_feature_name
|
||||
))
|
||||
.chain(llvm_feature.dependency.into_iter().filter_map(
|
||||
.chain(llvm_feature.dependencies.into_iter().filter_map(
|
||||
move |feat| match (enable, feat) {
|
||||
(_, TargetFeatureFoldStrength::Both(f))
|
||||
| (true, TargetFeatureFoldStrength::EnableOnly(f)) => {
|
||||
|
|
|
|||
|
|
@ -1053,9 +1053,10 @@ fn link_natively(
|
|||
strip_with_external_utility(sess, stripcmd, out_filename, &["--strip-debug"])
|
||||
}
|
||||
// Per the manpage, `-x` is the maximum safe strip level for dynamic libraries. (#93988)
|
||||
(Strip::Symbols, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) => {
|
||||
strip_with_external_utility(sess, stripcmd, out_filename, &["-x"])
|
||||
}
|
||||
(
|
||||
Strip::Symbols,
|
||||
CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro | CrateType::Sdylib,
|
||||
) => strip_with_external_utility(sess, stripcmd, out_filename, &["-x"]),
|
||||
(Strip::Symbols, _) => {
|
||||
strip_with_external_utility(sess, stripcmd, out_filename, &["--strip-all"])
|
||||
}
|
||||
|
|
@ -1243,8 +1244,10 @@ fn add_sanitizer_libraries(
|
|||
// which should be linked to both executables and dynamic libraries.
|
||||
// Everywhere else the runtimes are currently distributed as static
|
||||
// libraries which should be linked to executables only.
|
||||
if matches!(crate_type, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro)
|
||||
&& !(sess.target.is_like_darwin || sess.target.is_like_msvc)
|
||||
if matches!(
|
||||
crate_type,
|
||||
CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro | CrateType::Sdylib
|
||||
) && !(sess.target.is_like_darwin || sess.target.is_like_msvc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1938,6 +1941,7 @@ fn add_late_link_args(
|
|||
codegen_results: &CodegenResults,
|
||||
) {
|
||||
let any_dynamic_crate = crate_type == CrateType::Dylib
|
||||
|| crate_type == CrateType::Sdylib
|
||||
|| codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| {
|
||||
*ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -337,7 +337,12 @@ pub(crate) trait Linker {
|
|||
fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]);
|
||||
fn no_crt_objects(&mut self);
|
||||
fn no_default_libraries(&mut self);
|
||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]);
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
tmpdir: &Path,
|
||||
crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
);
|
||||
fn subsystem(&mut self, subsystem: &str);
|
||||
fn linker_plugin_lto(&mut self);
|
||||
fn add_eh_frame_header(&mut self) {}
|
||||
|
|
@ -770,7 +775,12 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
tmpdir: &Path,
|
||||
crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
// Symbol visibility in object files typically takes care of this.
|
||||
if crate_type == CrateType::Executable {
|
||||
let should_export_executable_symbols =
|
||||
|
|
@ -799,7 +809,7 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
// Write a plain, newline-separated list of symbols
|
||||
let res: io::Result<()> = try {
|
||||
let mut f = File::create_buffered(&path)?;
|
||||
for sym in symbols {
|
||||
for (sym, _) in symbols {
|
||||
debug!(" _{sym}");
|
||||
writeln!(f, "_{sym}")?;
|
||||
}
|
||||
|
|
@ -814,9 +824,12 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
// .def file similar to MSVC one but without LIBRARY section
|
||||
// because LD doesn't like when it's empty
|
||||
writeln!(f, "EXPORTS")?;
|
||||
for symbol in symbols {
|
||||
for (symbol, kind) in symbols {
|
||||
let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" };
|
||||
debug!(" _{symbol}");
|
||||
writeln!(f, " {symbol}")?;
|
||||
// Quote the name in case it's reserved by linker in some way
|
||||
// (this accounts for names with dots in particular).
|
||||
writeln!(f, " \"{symbol}\"{kind_marker}")?;
|
||||
}
|
||||
};
|
||||
if let Err(error) = res {
|
||||
|
|
@ -829,7 +842,7 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
writeln!(f, "{{")?;
|
||||
if !symbols.is_empty() {
|
||||
writeln!(f, " global:")?;
|
||||
for sym in symbols {
|
||||
for (sym, _) in symbols {
|
||||
debug!(" {sym};");
|
||||
writeln!(f, " {sym};")?;
|
||||
}
|
||||
|
|
@ -1096,7 +1109,12 @@ impl<'a> Linker for MsvcLinker<'a> {
|
|||
// crates. Upstream rlibs may be linked statically to this dynamic library,
|
||||
// in which case they may continue to transitively be used and hence need
|
||||
// their symbols exported.
|
||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
tmpdir: &Path,
|
||||
crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
// Symbol visibility takes care of this typically
|
||||
if crate_type == CrateType::Executable {
|
||||
let should_export_executable_symbols =
|
||||
|
|
@ -1114,9 +1132,10 @@ impl<'a> Linker for MsvcLinker<'a> {
|
|||
// straight to exports.
|
||||
writeln!(f, "LIBRARY")?;
|
||||
writeln!(f, "EXPORTS")?;
|
||||
for symbol in symbols {
|
||||
for (symbol, kind) in symbols {
|
||||
let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" };
|
||||
debug!(" _{symbol}");
|
||||
writeln!(f, " {symbol}")?;
|
||||
writeln!(f, " {symbol}{kind_marker}")?;
|
||||
}
|
||||
};
|
||||
if let Err(error) = res {
|
||||
|
|
@ -1257,14 +1276,19 @@ impl<'a> Linker for EmLinker<'a> {
|
|||
self.cc_arg("-nodefaultlibs");
|
||||
}
|
||||
|
||||
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
_tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
debug!("EXPORTED SYMBOLS:");
|
||||
|
||||
self.cc_arg("-s");
|
||||
|
||||
let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
|
||||
let encoded = serde_json::to_string(
|
||||
&symbols.iter().map(|sym| "_".to_owned() + sym).collect::<Vec<_>>(),
|
||||
&symbols.iter().map(|(sym, _)| "_".to_owned() + sym).collect::<Vec<_>>(),
|
||||
)
|
||||
.unwrap();
|
||||
debug!("{encoded}");
|
||||
|
|
@ -1426,8 +1450,13 @@ impl<'a> Linker for WasmLd<'a> {
|
|||
|
||||
fn no_default_libraries(&mut self) {}
|
||||
|
||||
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||
for sym in symbols {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
_tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
for (sym, _) in symbols {
|
||||
self.link_args(&["--export", sym]);
|
||||
}
|
||||
|
||||
|
|
@ -1561,7 +1590,7 @@ impl<'a> Linker for L4Bender<'a> {
|
|||
self.cc_arg("-nostdlib");
|
||||
}
|
||||
|
||||
fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) {
|
||||
fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[(String, SymbolExportKind)]) {
|
||||
// ToDo, not implemented, copy from GCC
|
||||
self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented);
|
||||
}
|
||||
|
|
@ -1718,12 +1747,17 @@ impl<'a> Linker for AixLinker<'a> {
|
|||
|
||||
fn no_default_libraries(&mut self) {}
|
||||
|
||||
fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
let path = tmpdir.join("list.exp");
|
||||
let res: io::Result<()> = try {
|
||||
let mut f = File::create_buffered(&path)?;
|
||||
// FIXME: use llvm-nm to generate export list.
|
||||
for symbol in symbols {
|
||||
for (symbol, _) in symbols {
|
||||
debug!(" _{symbol}");
|
||||
writeln!(f, " {symbol}")?;
|
||||
}
|
||||
|
|
@ -1767,9 +1801,12 @@ fn for_each_exported_symbols_include_dep<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
|
||||
pub(crate) fn exported_symbols(
|
||||
tcx: TyCtxt<'_>,
|
||||
crate_type: CrateType,
|
||||
) -> Vec<(String, SymbolExportKind)> {
|
||||
if let Some(ref exports) = tcx.sess.target.override_export_symbols {
|
||||
return exports.iter().map(ToString::to_string).collect();
|
||||
return exports.iter().map(|name| (name.to_string(), SymbolExportKind::Text)).collect();
|
||||
}
|
||||
|
||||
if let CrateType::ProcMacro = crate_type {
|
||||
|
|
@ -1779,7 +1816,10 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<St
|
|||
}
|
||||
}
|
||||
|
||||
fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
|
||||
fn exported_symbols_for_non_proc_macro(
|
||||
tcx: TyCtxt<'_>,
|
||||
crate_type: CrateType,
|
||||
) -> Vec<(String, SymbolExportKind)> {
|
||||
let mut symbols = Vec::new();
|
||||
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
|
||||
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
|
||||
|
|
@ -1787,17 +1827,18 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -
|
|||
// from any cdylib. The latter doesn't work anyway as we use hidden visibility for
|
||||
// compiler-builtins. Most linkers silently ignore it, but ld64 gives a warning.
|
||||
if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) {
|
||||
symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate(
|
||||
tcx, symbol, cnum,
|
||||
symbols.push((
|
||||
symbol_export::exporting_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
|
||||
info.kind,
|
||||
));
|
||||
symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, cnum);
|
||||
symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, info, cnum);
|
||||
}
|
||||
});
|
||||
|
||||
symbols
|
||||
}
|
||||
|
||||
fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
|
||||
fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<(String, SymbolExportKind)> {
|
||||
// `exported_symbols` will be empty when !should_codegen.
|
||||
if !tcx.sess.opts.output_types.should_codegen() {
|
||||
return Vec::new();
|
||||
|
|
@ -1807,7 +1848,10 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
|
|||
let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
|
||||
let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx);
|
||||
|
||||
vec![proc_macro_decls_name, metadata_symbol_name]
|
||||
vec![
|
||||
(proc_macro_decls_name, SymbolExportKind::Text),
|
||||
(metadata_symbol_name, SymbolExportKind::Text),
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn linked_symbols(
|
||||
|
|
@ -1815,7 +1859,7 @@ pub(crate) fn linked_symbols(
|
|||
crate_type: CrateType,
|
||||
) -> Vec<(String, SymbolExportKind)> {
|
||||
match crate_type {
|
||||
CrateType::Executable | CrateType::Cdylib | CrateType::Dylib => (),
|
||||
CrateType::Executable | CrateType::Cdylib | CrateType::Dylib | CrateType::Sdylib => (),
|
||||
CrateType::Staticlib | CrateType::ProcMacro | CrateType::Rlib => {
|
||||
return Vec::new();
|
||||
}
|
||||
|
|
@ -1829,7 +1873,9 @@ pub(crate) fn linked_symbols(
|
|||
|| info.used
|
||||
{
|
||||
symbols.push((
|
||||
symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
|
||||
symbol_export::linking_symbol_name_for_instance_in_crate(
|
||||
tcx, symbol, info.kind, cnum,
|
||||
),
|
||||
info.kind,
|
||||
));
|
||||
}
|
||||
|
|
@ -1904,7 +1950,13 @@ impl<'a> Linker for PtxLinker<'a> {
|
|||
|
||||
fn ehcont_guard(&mut self) {}
|
||||
|
||||
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {}
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
_tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
_symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
}
|
||||
|
||||
fn subsystem(&mut self, _subsystem: &str) {}
|
||||
|
||||
|
|
@ -1973,10 +2025,15 @@ impl<'a> Linker for LlbcLinker<'a> {
|
|||
|
||||
fn ehcont_guard(&mut self) {}
|
||||
|
||||
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
_tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
match _crate_type {
|
||||
CrateType::Cdylib => {
|
||||
for sym in symbols {
|
||||
for (sym, _) in symbols {
|
||||
self.link_args(&["--export-symbol", sym]);
|
||||
}
|
||||
}
|
||||
|
|
@ -2050,11 +2107,16 @@ impl<'a> Linker for BpfLinker<'a> {
|
|||
|
||||
fn ehcont_guard(&mut self) {}
|
||||
|
||||
fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
let path = tmpdir.join("symbols");
|
||||
let res: io::Result<()> = try {
|
||||
let mut f = File::create_buffered(&path)?;
|
||||
for sym in symbols {
|
||||
for (sym, _) in symbols {
|
||||
writeln!(f, "{sym}")?;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -270,45 +270,61 @@ pub(super) fn elf_os_abi(sess: &Session) -> u8 {
|
|||
|
||||
pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
|
||||
match architecture {
|
||||
Architecture::Mips => {
|
||||
let arch = match sess.target.options.cpu.as_ref() {
|
||||
"mips1" => elf::EF_MIPS_ARCH_1,
|
||||
"mips2" => elf::EF_MIPS_ARCH_2,
|
||||
Architecture::Mips | Architecture::Mips64 | Architecture::Mips64_N32 => {
|
||||
// "N32" indicates an "ILP32" data model on a 64-bit MIPS CPU
|
||||
// like SPARC's "v8+", x86_64's "x32", or the watchOS "arm64_32".
|
||||
let is_32bit = architecture == Architecture::Mips;
|
||||
let mut e_flags = match sess.target.options.cpu.as_ref() {
|
||||
"mips1" if is_32bit => elf::EF_MIPS_ARCH_1,
|
||||
"mips2" if is_32bit => elf::EF_MIPS_ARCH_2,
|
||||
"mips3" => elf::EF_MIPS_ARCH_3,
|
||||
"mips4" => elf::EF_MIPS_ARCH_4,
|
||||
"mips5" => elf::EF_MIPS_ARCH_5,
|
||||
s if s.contains("r6") => elf::EF_MIPS_ARCH_32R6,
|
||||
_ => elf::EF_MIPS_ARCH_32R2,
|
||||
"mips32r2" if is_32bit => elf::EF_MIPS_ARCH_32R2,
|
||||
"mips32r6" if is_32bit => elf::EF_MIPS_ARCH_32R6,
|
||||
"mips64r2" if !is_32bit => elf::EF_MIPS_ARCH_64R2,
|
||||
"mips64r6" if !is_32bit => elf::EF_MIPS_ARCH_64R6,
|
||||
s if s.starts_with("mips32") && !is_32bit => {
|
||||
sess.dcx().fatal(format!("invalid CPU `{}` for 64-bit MIPS target", s))
|
||||
}
|
||||
s if s.starts_with("mips64") && is_32bit => {
|
||||
sess.dcx().fatal(format!("invalid CPU `{}` for 32-bit MIPS target", s))
|
||||
}
|
||||
_ if is_32bit => elf::EF_MIPS_ARCH_32R2,
|
||||
_ => elf::EF_MIPS_ARCH_64R2,
|
||||
};
|
||||
|
||||
let mut e_flags = elf::EF_MIPS_CPIC | arch;
|
||||
|
||||
// If the ABI is explicitly given, use it or default to O32.
|
||||
match sess.target.options.llvm_abiname.to_lowercase().as_str() {
|
||||
"n32" => e_flags |= elf::EF_MIPS_ABI2,
|
||||
"o32" => e_flags |= elf::EF_MIPS_ABI_O32,
|
||||
_ => e_flags |= elf::EF_MIPS_ABI_O32,
|
||||
// If the ABI is explicitly given, use it, or default to O32 on 32-bit MIPS,
|
||||
// which is the only "true" 32-bit option that LLVM supports.
|
||||
match sess.target.options.llvm_abiname.as_ref() {
|
||||
"o32" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32,
|
||||
"n32" if !is_32bit => e_flags |= elf::EF_MIPS_ABI2,
|
||||
"n64" if !is_32bit => {}
|
||||
"" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32,
|
||||
"" => sess.dcx().fatal("LLVM ABI must be specifed for 64-bit MIPS targets"),
|
||||
s if is_32bit => {
|
||||
sess.dcx().fatal(format!("invalid LLVM ABI `{}` for 32-bit MIPS target", s))
|
||||
}
|
||||
s => sess.dcx().fatal(format!("invalid LLVM ABI `{}` for 64-bit MIPS target", s)),
|
||||
};
|
||||
|
||||
if sess.target.options.relocation_model != RelocModel::Static {
|
||||
e_flags |= elf::EF_MIPS_PIC;
|
||||
// PIC means position-independent code. CPIC means "calls PIC".
|
||||
// CPIC was mutually exclusive with PIC according to
|
||||
// the SVR4 MIPS ABI https://refspecs.linuxfoundation.org/elf/mipsabi.pdf
|
||||
// and should have only appeared on static objects with dynamically calls.
|
||||
// At some point someone (GCC?) decided to set CPIC even for PIC.
|
||||
// Nowadays various things expect both set on the same object file
|
||||
// and may even error if you mix CPIC and non-CPIC object files,
|
||||
// despite that being the entire point of the CPIC ABI extension!
|
||||
// As we are in Rome, we do as the Romans do.
|
||||
e_flags |= elf::EF_MIPS_PIC | elf::EF_MIPS_CPIC;
|
||||
}
|
||||
if sess.target.options.cpu.contains("r6") {
|
||||
e_flags |= elf::EF_MIPS_NAN2008;
|
||||
}
|
||||
e_flags
|
||||
}
|
||||
Architecture::Mips64 => {
|
||||
// copied from `mips64el-linux-gnuabi64-gcc foo.c -c`
|
||||
let e_flags = elf::EF_MIPS_CPIC
|
||||
| elf::EF_MIPS_PIC
|
||||
| if sess.target.options.cpu.contains("r6") {
|
||||
elf::EF_MIPS_ARCH_64R6 | elf::EF_MIPS_NAN2008
|
||||
} else {
|
||||
elf::EF_MIPS_ARCH_64R2
|
||||
};
|
||||
e_flags
|
||||
}
|
||||
Architecture::Riscv32 | Architecture::Riscv64 => {
|
||||
// Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc
|
||||
let mut e_flags: u32 = 0x0;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ fn crate_export_threshold(crate_type: CrateType) -> SymbolExportLevel {
|
|||
CrateType::Executable | CrateType::Staticlib | CrateType::ProcMacro | CrateType::Cdylib => {
|
||||
SymbolExportLevel::C
|
||||
}
|
||||
CrateType::Rlib | CrateType::Dylib => SymbolExportLevel::Rust,
|
||||
CrateType::Rlib | CrateType::Dylib | CrateType::Sdylib => SymbolExportLevel::Rust,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ pub fn crates_export_threshold(crate_types: &[CrateType]) -> SymbolExportLevel {
|
|||
}
|
||||
|
||||
fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<SymbolExportInfo> {
|
||||
if !tcx.sess.opts.output_types.should_codegen() {
|
||||
if !tcx.sess.opts.output_types.should_codegen() && !tcx.is_sdylib_interface_build() {
|
||||
return Default::default();
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ fn exported_symbols_provider_local<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
_: LocalCrate,
|
||||
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
if !tcx.sess.opts.output_types.should_codegen() {
|
||||
if !tcx.sess.opts.output_types.should_codegen() && !tcx.is_sdylib_interface_build() {
|
||||
return &[];
|
||||
}
|
||||
|
||||
|
|
@ -612,7 +612,7 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>(
|
|||
ExportedSymbol::Generic(def_id, args) => {
|
||||
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
|
||||
tcx,
|
||||
Instance::new(def_id, args),
|
||||
Instance::new_raw(def_id, args),
|
||||
instantiating_crate,
|
||||
)
|
||||
}
|
||||
|
|
@ -660,7 +660,7 @@ fn calling_convention_for_symbol<'tcx>(
|
|||
None
|
||||
}
|
||||
ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)),
|
||||
ExportedSymbol::Generic(def_id, args) => Some(Instance::new(def_id, args)),
|
||||
ExportedSymbol::Generic(def_id, args) => Some(Instance::new_raw(def_id, args)),
|
||||
// DropGlue always use the Rust calling convention and thus follow the target's default
|
||||
// symbol decoration scheme.
|
||||
ExportedSymbol::DropGlue(..) => None,
|
||||
|
|
@ -692,6 +692,7 @@ fn calling_convention_for_symbol<'tcx>(
|
|||
pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
symbol: ExportedSymbol<'tcx>,
|
||||
export_kind: SymbolExportKind,
|
||||
instantiating_crate: CrateNum,
|
||||
) -> String {
|
||||
let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);
|
||||
|
|
@ -712,8 +713,9 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
|
|||
let prefix = match &target.arch[..] {
|
||||
"x86" => Some('_'),
|
||||
"x86_64" => None,
|
||||
"arm64ec" => Some('#'),
|
||||
// Only x86/64 use symbol decorations.
|
||||
// Only functions are decorated for arm64ec.
|
||||
"arm64ec" if export_kind == SymbolExportKind::Text => Some('#'),
|
||||
// Only x86/64 and arm64ec use symbol decorations.
|
||||
_ => return undecorated,
|
||||
};
|
||||
|
||||
|
|
@ -753,9 +755,10 @@ pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>(
|
|||
/// Add it to the symbols list for all kernel functions, so that it is exported in the linked
|
||||
/// object.
|
||||
pub(crate) fn extend_exported_symbols<'tcx>(
|
||||
symbols: &mut Vec<String>,
|
||||
symbols: &mut Vec<(String, SymbolExportKind)>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
symbol: ExportedSymbol<'tcx>,
|
||||
info: SymbolExportInfo,
|
||||
instantiating_crate: CrateNum,
|
||||
) {
|
||||
let (conv, _) = calling_convention_for_symbol(tcx, symbol);
|
||||
|
|
@ -767,7 +770,7 @@ pub(crate) fn extend_exported_symbols<'tcx>(
|
|||
let undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);
|
||||
|
||||
// Add the symbol for the kernel descriptor (with .kd suffix)
|
||||
symbols.push(format!("{undecorated}.kd"));
|
||||
symbols.push((format!("{undecorated}.kd"), info.kind));
|
||||
}
|
||||
|
||||
fn maybe_emutls_symbol_name<'tcx>(
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
|||
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_hir::ItemId;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ItemId, Target};
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
|
||||
|
|
@ -457,7 +457,13 @@ where
|
|||
rustc_hir::InlineAsmOperand::SymFn { expr } => {
|
||||
let ty = cx.tcx().typeck(item_id.owner_id).expr_ty(expr);
|
||||
let instance = match ty.kind() {
|
||||
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
|
||||
&ty::FnDef(def_id, args) => Instance::expect_resolve(
|
||||
cx.tcx(),
|
||||
ty::TypingEnv::fully_monomorphized(),
|
||||
def_id,
|
||||
args,
|
||||
expr.span,
|
||||
),
|
||||
_ => span_bug!(*op_sp, "asm sym is not a function"),
|
||||
};
|
||||
|
||||
|
|
@ -1032,21 +1038,35 @@ impl CrateInfo {
|
|||
// by the compiler, but that's ok because all this stuff is unstable anyway.
|
||||
let target = &tcx.sess.target;
|
||||
if !are_upstream_rust_objects_already_included(tcx.sess) {
|
||||
let missing_weak_lang_items: FxIndexSet<Symbol> = info
|
||||
let add_prefix = match (target.is_like_windows, target.arch.as_ref()) {
|
||||
(true, "x86") => |name: String, _: SymbolExportKind| format!("_{name}"),
|
||||
(true, "arm64ec") => {
|
||||
// Only functions are decorated for arm64ec.
|
||||
|name: String, export_kind: SymbolExportKind| match export_kind {
|
||||
SymbolExportKind::Text => format!("#{name}"),
|
||||
_ => name,
|
||||
}
|
||||
}
|
||||
_ => |name: String, _: SymbolExportKind| name,
|
||||
};
|
||||
let missing_weak_lang_items: FxIndexSet<(Symbol, SymbolExportKind)> = info
|
||||
.used_crates
|
||||
.iter()
|
||||
.flat_map(|&cnum| tcx.missing_lang_items(cnum))
|
||||
.filter(|l| l.is_weak())
|
||||
.filter_map(|&l| {
|
||||
let name = l.link_name()?;
|
||||
lang_items::required(tcx, l).then_some(name)
|
||||
let export_kind = match l.target() {
|
||||
Target::Fn => SymbolExportKind::Text,
|
||||
Target::Static => SymbolExportKind::Data,
|
||||
_ => bug!(
|
||||
"Don't know what the export kind is for lang item of kind {:?}",
|
||||
l.target()
|
||||
),
|
||||
};
|
||||
lang_items::required(tcx, l).then_some((name, export_kind))
|
||||
})
|
||||
.collect();
|
||||
let prefix = match (target.is_like_windows, target.arch.as_ref()) {
|
||||
(true, "x86") => "_",
|
||||
(true, "arm64ec") => "#",
|
||||
_ => "",
|
||||
};
|
||||
|
||||
// This loop only adds new items to values of the hash map, so the order in which we
|
||||
// iterate over the values is not important.
|
||||
|
|
@ -1059,10 +1079,13 @@ impl CrateInfo {
|
|||
.for_each(|(_, linked_symbols)| {
|
||||
let mut symbols = missing_weak_lang_items
|
||||
.iter()
|
||||
.map(|item| {
|
||||
.map(|(item, export_kind)| {
|
||||
(
|
||||
format!("{prefix}{}", mangle_internal_symbol(tcx, item.as_str())),
|
||||
SymbolExportKind::Text,
|
||||
add_prefix(
|
||||
mangle_internal_symbol(tcx, item.as_str()),
|
||||
*export_kind,
|
||||
),
|
||||
*export_kind,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
|
@ -1077,12 +1100,12 @@ impl CrateInfo {
|
|||
// errors.
|
||||
linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| {
|
||||
(
|
||||
format!(
|
||||
"{prefix}{}",
|
||||
add_prefix(
|
||||
mangle_internal_symbol(
|
||||
tcx,
|
||||
global_fn_name(method.name).as_str()
|
||||
)
|
||||
global_fn_name(method.name).as_str(),
|
||||
),
|
||||
SymbolExportKind::Text,
|
||||
),
|
||||
SymbolExportKind::Text,
|
||||
)
|
||||
|
|
@ -1092,7 +1115,7 @@ impl CrateInfo {
|
|||
}
|
||||
|
||||
let embed_visualizers = tcx.crate_types().iter().any(|&crate_type| match crate_type {
|
||||
CrateType::Executable | CrateType::Dylib | CrateType::Cdylib => {
|
||||
CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::Sdylib => {
|
||||
// These are crate types for which we invoke the linker and can embed
|
||||
// NatVis visualizers.
|
||||
true
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ pub struct CrateInfo {
|
|||
pub target_cpu: String,
|
||||
pub target_features: Vec<String>,
|
||||
pub crate_types: Vec<CrateType>,
|
||||
pub exported_symbols: UnordMap<CrateType, Vec<String>>,
|
||||
pub exported_symbols: UnordMap<CrateType, Vec<(String, SymbolExportKind)>>,
|
||||
pub linked_symbols: FxIndexMap<CrateType, Vec<(String, SymbolExportKind)>>,
|
||||
pub local_crate_name: Symbol,
|
||||
pub compiler_builtins: Option<CrateNum>,
|
||||
|
|
|
|||
|
|
@ -95,7 +95,9 @@ fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndL
|
|||
);
|
||||
|
||||
let instance = match mono_type.kind() {
|
||||
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
|
||||
&ty::FnDef(def_id, args) => {
|
||||
Instance::expect_resolve(cx.tcx(), cx.typing_env(), def_id, args, value.span)
|
||||
}
|
||||
_ => bug!("asm sym is not a function"),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@ use hir::def::DefKind;
|
|||
use rustc_ast::Mutability;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult};
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::sym;
|
||||
use tracing::{instrument, trace};
|
||||
|
||||
use super::{
|
||||
|
|
@ -66,6 +66,7 @@ fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
|
|||
ecx: &mut InterpCx<'tcx, M>,
|
||||
alloc_id: AllocId,
|
||||
mutability: Mutability,
|
||||
disambiguator: Option<&mut DisambiguatorState>,
|
||||
) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, ()> {
|
||||
trace!("intern_shallow {:?}", alloc_id);
|
||||
// remove allocation
|
||||
|
|
@ -88,7 +89,13 @@ fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
|
|||
// link the alloc id to the actual allocation
|
||||
let alloc = ecx.tcx.mk_const_alloc(alloc);
|
||||
if let Some(static_id) = ecx.machine.static_def_id() {
|
||||
intern_as_new_static(ecx.tcx, static_id, alloc_id, alloc);
|
||||
intern_as_new_static(
|
||||
ecx.tcx,
|
||||
static_id,
|
||||
alloc_id,
|
||||
alloc,
|
||||
disambiguator.expect("disambiguator needed"),
|
||||
);
|
||||
} else {
|
||||
ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
|
||||
}
|
||||
|
|
@ -102,11 +109,18 @@ fn intern_as_new_static<'tcx>(
|
|||
static_id: LocalDefId,
|
||||
alloc_id: AllocId,
|
||||
alloc: ConstAllocation<'tcx>,
|
||||
disambiguator: &mut DisambiguatorState,
|
||||
) {
|
||||
// `intern_const_alloc_recursive` is called once per static and it contains the `DisambiguatorState`.
|
||||
// The `<static_id>::{{nested}}` path is thus unique to `intern_const_alloc_recursive` and the
|
||||
// `DisambiguatorState` ensures the generated path is unique for this call as we generate
|
||||
// `<static_id>::{{nested#n}}` where `n` is the `n`th `intern_as_new_static` call.
|
||||
let feed = tcx.create_def(
|
||||
static_id,
|
||||
Some(sym::nested),
|
||||
None,
|
||||
DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
|
||||
Some(DefPathData::NestedStatic),
|
||||
disambiguator,
|
||||
);
|
||||
tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());
|
||||
|
||||
|
|
@ -154,6 +168,8 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
|
|||
intern_kind: InternKind,
|
||||
ret: &MPlaceTy<'tcx>,
|
||||
) -> Result<(), InternResult> {
|
||||
let mut disambiguator = DisambiguatorState::new();
|
||||
|
||||
// We are interning recursively, and for mutability we are distinguishing the "root" allocation
|
||||
// that we are starting in, and all other allocations that we are encountering recursively.
|
||||
let (base_mutability, inner_mutability, is_static) = match intern_kind {
|
||||
|
|
@ -197,7 +213,9 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
|
|||
alloc.1.mutability = base_mutability;
|
||||
alloc.1.provenance().ptrs().iter().map(|&(_, prov)| prov).collect()
|
||||
} else {
|
||||
intern_shallow(ecx, base_alloc_id, base_mutability).unwrap().collect()
|
||||
intern_shallow(ecx, base_alloc_id, base_mutability, Some(&mut disambiguator))
|
||||
.unwrap()
|
||||
.collect()
|
||||
};
|
||||
// We need to distinguish "has just been interned" from "was already in `tcx`",
|
||||
// so we track this in a separate set.
|
||||
|
|
@ -291,7 +309,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
|
|||
// okay with losing some potential for immutability here. This can anyway only affect
|
||||
// `static mut`.
|
||||
just_interned.insert(alloc_id);
|
||||
match intern_shallow(ecx, alloc_id, inner_mutability) {
|
||||
match intern_shallow(ecx, alloc_id, inner_mutability, Some(&mut disambiguator)) {
|
||||
Ok(nested) => todo.extend(nested),
|
||||
Err(()) => {
|
||||
ecx.tcx.dcx().delayed_bug("found dangling pointer during const interning");
|
||||
|
|
@ -313,8 +331,9 @@ pub fn intern_const_alloc_for_constprop<'tcx, T, M: CompileTimeMachine<'tcx, T>>
|
|||
return interp_ok(());
|
||||
}
|
||||
// Move allocation to `tcx`.
|
||||
if let Some(_) =
|
||||
(intern_shallow(ecx, alloc_id, Mutability::Not).map_err(|()| err_ub!(DeadLocal))?).next()
|
||||
if let Some(_) = intern_shallow(ecx, alloc_id, Mutability::Not, None)
|
||||
.map_err(|()| err_ub!(DeadLocal))?
|
||||
.next()
|
||||
{
|
||||
// We are not doing recursive interning, so we don't currently support provenance.
|
||||
// (If this assertion ever triggers, we should just implement a
|
||||
|
|
@ -340,7 +359,7 @@ impl<'tcx> InterpCx<'tcx, DummyMachine> {
|
|||
let dest = self.allocate(layout, MemoryKind::Stack)?;
|
||||
f(self, &dest.clone().into())?;
|
||||
let alloc_id = dest.ptr().provenance.unwrap().alloc_id(); // this was just allocated, it must have provenance
|
||||
for prov in intern_shallow(self, alloc_id, Mutability::Not).unwrap() {
|
||||
for prov in intern_shallow(self, alloc_id, Mutability::Not, None).unwrap() {
|
||||
// We are not doing recursive interning, so we don't currently support provenance.
|
||||
// (If this assertion ever triggers, we should just implement a
|
||||
// proper recursive interning loop -- or just call `intern_const_alloc_recursive`.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! A graph module for use in dataflow, region resolution, and elsewhere.
|
||||
//! See [`LinkedGraph`].
|
||||
//!
|
||||
//! # Interface details
|
||||
//!
|
||||
|
|
@ -28,7 +28,23 @@ use tracing::debug;
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub struct Graph<N, E> {
|
||||
/// A concrete graph implementation that supports:
|
||||
/// - Nodes and/or edges labelled with custom data types (`N` and `E` respectively).
|
||||
/// - Incremental addition of new nodes/edges (but not removal).
|
||||
/// - Flat storage of node/edge data in a pair of vectors.
|
||||
/// - Iteration over any node's out-edges or in-edges, via linked lists
|
||||
/// threaded through the node/edge data.
|
||||
///
|
||||
/// # Caution
|
||||
/// This is an older graph implementation that is still used by some pieces
|
||||
/// of diagnostic/debugging code. New code that needs a graph data structure
|
||||
/// should consider using `VecGraph` instead, or implementing its own
|
||||
/// special-purpose graph with the specific features needed.
|
||||
///
|
||||
/// This graph implementation predates the later [graph traits](crate::graph),
|
||||
/// and does not implement those traits, so it has its own implementations of a
|
||||
/// few basic graph algorithms.
|
||||
pub struct LinkedGraph<N, E> {
|
||||
nodes: Vec<Node<N>>,
|
||||
edges: Vec<Edge<E>>,
|
||||
}
|
||||
|
|
@ -71,13 +87,13 @@ impl NodeIndex {
|
|||
}
|
||||
}
|
||||
|
||||
impl<N: Debug, E: Debug> Graph<N, E> {
|
||||
pub fn new() -> Graph<N, E> {
|
||||
Graph { nodes: Vec::new(), edges: Vec::new() }
|
||||
impl<N: Debug, E: Debug> LinkedGraph<N, E> {
|
||||
pub fn new() -> Self {
|
||||
Self { nodes: Vec::new(), edges: Vec::new() }
|
||||
}
|
||||
|
||||
pub fn with_capacity(nodes: usize, edges: usize) -> Graph<N, E> {
|
||||
Graph { nodes: Vec::with_capacity(nodes), edges: Vec::with_capacity(edges) }
|
||||
pub fn with_capacity(nodes: usize, edges: usize) -> Self {
|
||||
Self { nodes: Vec::with_capacity(nodes), edges: Vec::with_capacity(edges) }
|
||||
}
|
||||
|
||||
// # Simple accessors
|
||||
|
|
@ -249,7 +265,7 @@ impl<N: Debug, E: Debug> Graph<N, E> {
|
|||
// # Iterators
|
||||
|
||||
pub struct AdjacentEdges<'g, N, E> {
|
||||
graph: &'g Graph<N, E>,
|
||||
graph: &'g LinkedGraph<N, E>,
|
||||
direction: Direction,
|
||||
next: EdgeIndex,
|
||||
}
|
||||
|
|
@ -285,7 +301,7 @@ impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
|
|||
}
|
||||
|
||||
pub struct DepthFirstTraversal<'g, N, E> {
|
||||
graph: &'g Graph<N, E>,
|
||||
graph: &'g LinkedGraph<N, E>,
|
||||
stack: Vec<NodeIndex>,
|
||||
visited: DenseBitSet<usize>,
|
||||
direction: Direction,
|
||||
|
|
@ -293,7 +309,7 @@ pub struct DepthFirstTraversal<'g, N, E> {
|
|||
|
||||
impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
|
||||
pub fn with_start_node(
|
||||
graph: &'g Graph<N, E>,
|
||||
graph: &'g LinkedGraph<N, E>,
|
||||
start_node: NodeIndex,
|
||||
direction: Direction,
|
||||
) -> Self {
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
use tracing::debug;
|
||||
|
||||
use crate::graph::implementation::*;
|
||||
use super::{Debug, LinkedGraph, NodeIndex};
|
||||
|
||||
type TestGraph = Graph<&'static str, &'static str>;
|
||||
type TestGraph = LinkedGraph<&'static str, &'static str>;
|
||||
|
||||
fn create_graph() -> TestGraph {
|
||||
let mut graph = Graph::new();
|
||||
let mut graph = LinkedGraph::new();
|
||||
|
||||
// Create a simple graph
|
||||
//
|
||||
|
|
@ -56,7 +56,7 @@ fn each_edge() {
|
|||
}
|
||||
|
||||
fn test_adjacent_edges<N: PartialEq + Debug, E: PartialEq + Debug>(
|
||||
graph: &Graph<N, E>,
|
||||
graph: &LinkedGraph<N, E>,
|
||||
start_index: NodeIndex,
|
||||
start_data: N,
|
||||
expected_incoming: &[(E, N)],
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
use rustc_index::Idx;
|
||||
|
||||
pub mod dominators;
|
||||
pub mod implementation;
|
||||
pub mod iterate;
|
||||
pub mod linked_graph;
|
||||
mod reference;
|
||||
pub mod reversed;
|
||||
pub mod scc;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ pub use self::freeze::{FreezeLock, FreezeReadGuard, FreezeWriteGuard};
|
|||
pub use self::lock::{Lock, LockGuard, Mode};
|
||||
pub use self::mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
|
||||
pub use self::parallel::{
|
||||
join, par_for_each_in, par_map, parallel_guard, scope, spawn, try_par_for_each_in,
|
||||
broadcast, join, par_for_each_in, par_map, parallel_guard, scope, spawn, try_par_for_each_in,
|
||||
};
|
||||
pub use self::vec::{AppendOnlyIndexVec, AppendOnlyVec};
|
||||
pub use self::worker_local::{Registry, WorkerLocal};
|
||||
|
|
|
|||
|
|
@ -237,3 +237,13 @@ pub fn par_map<I: DynSend, T: IntoIterator<Item = I>, R: DynSend, C: FromIterato
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn broadcast<R: DynSend>(op: impl Fn(usize) -> R + DynSync) -> Vec<R> {
|
||||
if mode::is_dyn_thread_safe() {
|
||||
let op = FromDyn::from(op);
|
||||
let results = rayon_core::broadcast(|context| op.derive(op(context.index())));
|
||||
results.into_iter().map(|r| r.into_inner()).collect()
|
||||
} else {
|
||||
vec![op(0)]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,13 +44,13 @@ rustc_privacy = { path = "../rustc_privacy" }
|
|||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_resolve = { path = "../rustc_resolve" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_smir = { path = "../rustc_smir" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
||||
rustc_ty_utils = { path = "../rustc_ty_utils" }
|
||||
serde_json = "1.0.59"
|
||||
shlex = "1.0"
|
||||
stable_mir = { path = "../stable_mir", features = ["rustc_internal"] }
|
||||
tracing = { version = "0.1.35" }
|
||||
# tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ use rustc_metadata::locator;
|
|||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
|
||||
use rustc_session::config::{
|
||||
CG_OPTIONS, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, UnstableOptions,
|
||||
Z_OPTIONS, nightly_options, parse_target_triple,
|
||||
CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType,
|
||||
UnstableOptions, Z_OPTIONS, nightly_options, parse_target_triple,
|
||||
};
|
||||
use rustc_session::getopts::{self, Matches};
|
||||
use rustc_session::lint::{Lint, LintId};
|
||||
|
|
@ -352,6 +352,8 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
|
|||
|
||||
passes::write_dep_info(tcx);
|
||||
|
||||
passes::write_interface(tcx);
|
||||
|
||||
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
|
||||
&& sess.opts.output_types.len() == 1
|
||||
{
|
||||
|
|
@ -461,6 +463,7 @@ fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, col
|
|||
// Allow "E0123" or "0123" form.
|
||||
let upper_cased_code = code.to_ascii_uppercase();
|
||||
if let Ok(code) = upper_cased_code.strip_prefix('E').unwrap_or(&upper_cased_code).parse::<u32>()
|
||||
&& code <= ErrCode::MAX_AS_U32
|
||||
&& let Ok(description) = registry.try_find_description(ErrCode::from_u32(code))
|
||||
{
|
||||
let mut is_in_code_block = false;
|
||||
|
|
@ -816,6 +819,7 @@ fn print_crate_info(
|
|||
let supported_crate_types = CRATE_TYPES
|
||||
.iter()
|
||||
.filter(|(_, crate_type)| !invalid_output_for_target(&sess, *crate_type))
|
||||
.filter(|(_, crate_type)| *crate_type != CrateType::Sdylib)
|
||||
.map(|(crate_type_sym, _)| *crate_type_sym)
|
||||
.collect::<BTreeSet<_>>();
|
||||
for supported_crate_type in supported_crate_types {
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ use rustc_middle::ty::{self, TyCtxt};
|
|||
use rustc_mir_build::thir::print::{thir_flat, thir_tree};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::{OutFileName, PpHirMode, PpMode, PpSourceMode};
|
||||
use rustc_smir::rustc_internal::pretty::write_smir_pretty;
|
||||
use rustc_span::{FileName, Ident};
|
||||
use stable_mir::rustc_internal::pretty::write_smir_pretty;
|
||||
use tracing::debug;
|
||||
use {rustc_ast as ast, rustc_hir_pretty as pprust_hir};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
Attempt was made to import an unimportable type. This can happen when trying
|
||||
to import a type from a trait.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0253
|
||||
```
|
||||
#![feature(import_trait_associated_functions)]
|
||||
|
||||
mod foo {
|
||||
pub trait MyTrait {
|
||||
type SomeType;
|
||||
|
|
|
|||
|
|
@ -274,7 +274,12 @@ impl<'a> StripUnconfigured<'a> {
|
|||
/// is in the original source file. Gives a compiler error if the syntax of
|
||||
/// the attribute is incorrect.
|
||||
pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec<Attribute> {
|
||||
validate_attr::check_attribute_safety(&self.sess.psess, AttributeSafety::Normal, &cfg_attr);
|
||||
validate_attr::check_attribute_safety(
|
||||
&self.sess.psess,
|
||||
Some(AttributeSafety::Normal),
|
||||
&cfg_attr,
|
||||
ast::CRATE_NODE_ID,
|
||||
);
|
||||
|
||||
// A trace attribute left in AST in place of the original `cfg_attr` attribute.
|
||||
// It can later be used by lints or other diagnostics.
|
||||
|
|
|
|||
|
|
@ -1983,7 +1983,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
let mut span: Option<Span> = None;
|
||||
while let Some(attr) = attrs.next() {
|
||||
rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
|
||||
validate_attr::check_attr(&self.cx.sess.psess, attr);
|
||||
validate_attr::check_attr(
|
||||
&self.cx.sess.psess,
|
||||
attr,
|
||||
self.cx.current_expansion.lint_node_id,
|
||||
);
|
||||
|
||||
let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
|
||||
span = Some(current_span);
|
||||
|
|
|
|||
|
|
@ -536,6 +536,12 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
// Unstable attributes:
|
||||
// ==========================================================================
|
||||
|
||||
// Linking:
|
||||
gated!(
|
||||
export_stable, Normal, template!(Word), WarnFollowing,
|
||||
EncodeCrossCrate::No, experimental!(export_stable)
|
||||
),
|
||||
|
||||
// Testing:
|
||||
gated!(
|
||||
test_runner, CrateLevel, template!(List: "path"), ErrorFollowing,
|
||||
|
|
|
|||
|
|
@ -316,6 +316,7 @@ declare_features! (
|
|||
// Unstable `#[target_feature]` directives.
|
||||
(unstable, aarch64_unstable_target_feature, "1.82.0", Some(44839)),
|
||||
(unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)),
|
||||
(unstable, apx_target_feature, "CURRENT_RUSTC_VERSION", Some(139284)),
|
||||
(unstable, arm_target_feature, "1.27.0", Some(44839)),
|
||||
(unstable, avx512_target_feature, "1.27.0", Some(44839)),
|
||||
(unstable, bpf_target_feature, "1.54.0", Some(44839)),
|
||||
|
|
@ -393,6 +394,8 @@ declare_features! (
|
|||
(unstable, async_for_loop, "1.77.0", Some(118898)),
|
||||
/// Allows `async` trait bound modifier.
|
||||
(unstable, async_trait_bounds, "1.85.0", Some(62290)),
|
||||
/// Allows using Intel AVX10 target features and intrinsics
|
||||
(unstable, avx10_target_feature, "CURRENT_RUSTC_VERSION", Some(138843)),
|
||||
/// Allows using C-variadics.
|
||||
(unstable, c_variadic, "1.34.0", Some(44930)),
|
||||
/// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled.
|
||||
|
|
@ -483,6 +486,8 @@ declare_features! (
|
|||
(unstable, explicit_extern_abis, "CURRENT_RUSTC_VERSION", Some(134986)),
|
||||
/// Allows explicit tail calls via `become` expression.
|
||||
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
|
||||
/// Allows using `#[export_stable]` which indicates that an item is exportable.
|
||||
(incomplete, export_stable, "CURRENT_RUSTC_VERSION", Some(139939)),
|
||||
/// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions
|
||||
/// for functions with varargs.
|
||||
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
|
||||
|
|
@ -506,6 +511,8 @@ declare_features! (
|
|||
(incomplete, fn_delegation, "1.76.0", Some(118212)),
|
||||
/// Allows impls for the Freeze trait.
|
||||
(internal, freeze_impls, "1.78.0", Some(121675)),
|
||||
/// Frontmatter `---` blocks for use by external tools.
|
||||
(unstable, frontmatter, "CURRENT_RUSTC_VERSION", Some(136889)),
|
||||
/// Allows defining gen blocks and `gen fn`.
|
||||
(unstable, gen_blocks, "1.75.0", Some(117078)),
|
||||
/// Infer generic args for both consts and types.
|
||||
|
|
|
|||
|
|
@ -269,18 +269,10 @@ impl DefKind {
|
|||
| DefKind::TyParam
|
||||
| DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()),
|
||||
|
||||
// An associated type name will be missing for an RPITIT.
|
||||
DefKind::AssocTy => {
|
||||
if let Some(name) = name {
|
||||
DefPathData::TypeNs(name)
|
||||
} else {
|
||||
DefPathData::AnonAssocTy
|
||||
}
|
||||
}
|
||||
// An associated type name will be missing for an RPITIT (DefPathData::AnonAssocTy),
|
||||
// but those provide their own DefPathData.
|
||||
DefKind::AssocTy => DefPathData::TypeNs(name.unwrap()),
|
||||
|
||||
// It's not exactly an anon const, but wrt DefPathData, there
|
||||
// is no difference.
|
||||
DefKind::Static { nested: true, .. } => DefPathData::AnonConst,
|
||||
DefKind::Fn
|
||||
| DefKind::Const
|
||||
| DefKind::ConstParam
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ impl DefPathTable {
|
|||
//
|
||||
// See the documentation for DefPathHash for more information.
|
||||
panic!(
|
||||
"found DefPathHash collision between {def_path1:?} and {def_path2:?}. \
|
||||
"found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
|
||||
Compilation cannot continue."
|
||||
);
|
||||
}
|
||||
|
|
@ -97,13 +97,31 @@ impl DefPathTable {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DisambiguatorState {
|
||||
next: UnordMap<(LocalDefId, DefPathData), u32>,
|
||||
}
|
||||
|
||||
impl DisambiguatorState {
|
||||
pub fn new() -> Self {
|
||||
Self { next: Default::default() }
|
||||
}
|
||||
|
||||
/// Creates a `DisambiguatorState` where the next allocated `(LocalDefId, DefPathData)` pair
|
||||
/// will have `index` as the disambiguator.
|
||||
pub fn with(def_id: LocalDefId, data: DefPathData, index: u32) -> Self {
|
||||
let mut this = Self::new();
|
||||
this.next.insert((def_id, data), index);
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
/// The definition table containing node definitions.
|
||||
/// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s.
|
||||
/// It also stores mappings to convert `LocalDefId`s to/from `HirId`s.
|
||||
#[derive(Debug)]
|
||||
pub struct Definitions {
|
||||
table: DefPathTable,
|
||||
next_disambiguator: UnordMap<(LocalDefId, DefPathData), u32>,
|
||||
}
|
||||
|
||||
/// A unique identifier that we can use to lookup a definition
|
||||
|
|
@ -127,7 +145,7 @@ impl DefKey {
|
|||
let DisambiguatedDefPathData { ref data, disambiguator } = self.disambiguated_data;
|
||||
|
||||
std::mem::discriminant(data).hash(&mut hasher);
|
||||
if let Some(name) = data.get_opt_name() {
|
||||
if let Some(name) = data.hashed_symbol() {
|
||||
// Get a stable hash by considering the symbol chars rather than
|
||||
// the symbol index.
|
||||
name.as_str().hash(&mut hasher);
|
||||
|
|
@ -173,7 +191,11 @@ impl DisambiguatedDefPathData {
|
|||
}
|
||||
}
|
||||
DefPathDataName::Anon { namespace } => {
|
||||
write!(writer, "{{{}#{}}}", namespace, self.disambiguator)
|
||||
if let DefPathData::AnonAssocTy(method) = self.data {
|
||||
write!(writer, "{}::{{{}#{}}}", method, namespace, self.disambiguator)
|
||||
} else {
|
||||
write!(writer, "{{{}#{}}}", namespace, self.disambiguator)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -287,10 +309,15 @@ pub enum DefPathData {
|
|||
/// An existential `impl Trait` type node.
|
||||
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
|
||||
OpaqueTy,
|
||||
/// An anonymous associated type from an RPITIT.
|
||||
AnonAssocTy,
|
||||
/// Used for remapped captured lifetimes in an existential `impl Trait` type node.
|
||||
OpaqueLifetime(Symbol),
|
||||
/// An anonymous associated type from an RPITIT. The symbol refers to the name of the method
|
||||
/// that defined the type.
|
||||
AnonAssocTy(Symbol),
|
||||
/// A synthetic body for a coroutine's by-move body.
|
||||
SyntheticCoroutineBody,
|
||||
/// Additional static data referred to by a static.
|
||||
NestedStatic,
|
||||
}
|
||||
|
||||
impl Definitions {
|
||||
|
|
@ -342,11 +369,20 @@ impl Definitions {
|
|||
let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) };
|
||||
assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
|
||||
|
||||
Definitions { table, next_disambiguator: Default::default() }
|
||||
Definitions { table }
|
||||
}
|
||||
|
||||
/// Adds a definition with a parent definition.
|
||||
pub fn create_def(&mut self, parent: LocalDefId, data: DefPathData) -> LocalDefId {
|
||||
/// Creates a definition with a parent definition.
|
||||
/// If there are multiple definitions with the same DefPathData and the same parent, use
|
||||
/// `disambiguator` to differentiate them. Distinct `DisambiguatorState` instances are not
|
||||
/// guaranteed to generate unique disambiguators and should instead ensure that the `parent`
|
||||
/// and `data` pair is distinct from other instances.
|
||||
pub fn create_def(
|
||||
&mut self,
|
||||
parent: LocalDefId,
|
||||
data: DefPathData,
|
||||
disambiguator: &mut DisambiguatorState,
|
||||
) -> LocalDefId {
|
||||
// We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a
|
||||
// reference to `Definitions` and we're already holding a mutable reference.
|
||||
debug!(
|
||||
|
|
@ -354,12 +390,12 @@ impl Definitions {
|
|||
self.def_path(parent).to_string_no_crate_verbose(),
|
||||
);
|
||||
|
||||
// The root node must be created with `create_root_def()`.
|
||||
// The root node must be created in `new()`.
|
||||
assert!(data != DefPathData::CrateRoot);
|
||||
|
||||
// Find the next free disambiguator for this key.
|
||||
let disambiguator = {
|
||||
let next_disamb = self.next_disambiguator.entry((parent, data)).or_insert(0);
|
||||
let next_disamb = disambiguator.next.entry((parent, data)).or_insert(0);
|
||||
let disambiguator = *next_disamb;
|
||||
*next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
|
||||
disambiguator
|
||||
|
|
@ -411,7 +447,8 @@ impl DefPathData {
|
|||
pub fn get_opt_name(&self) -> Option<Symbol> {
|
||||
use self::DefPathData::*;
|
||||
match *self {
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name)
|
||||
| OpaqueLifetime(name) => Some(name),
|
||||
|
||||
Impl
|
||||
| ForeignMod
|
||||
|
|
@ -422,17 +459,37 @@ impl DefPathData {
|
|||
| Ctor
|
||||
| AnonConst
|
||||
| OpaqueTy
|
||||
| AnonAssocTy
|
||||
| SyntheticCoroutineBody => None,
|
||||
| AnonAssocTy(..)
|
||||
| SyntheticCoroutineBody
|
||||
| NestedStatic => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn hashed_symbol(&self) -> Option<Symbol> {
|
||||
use self::DefPathData::*;
|
||||
match *self {
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name)
|
||||
| OpaqueLifetime(name) => Some(name),
|
||||
|
||||
Impl
|
||||
| ForeignMod
|
||||
| CrateRoot
|
||||
| Use
|
||||
| GlobalAsm
|
||||
| Closure
|
||||
| Ctor
|
||||
| AnonConst
|
||||
| OpaqueTy
|
||||
| SyntheticCoroutineBody
|
||||
| NestedStatic => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> DefPathDataName {
|
||||
use self::DefPathData::*;
|
||||
match *self {
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => {
|
||||
DefPathDataName::Named(name)
|
||||
}
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name)
|
||||
| OpaqueLifetime(name) => DefPathDataName::Named(name),
|
||||
// Note that this does not show up in user print-outs.
|
||||
CrateRoot => DefPathDataName::Anon { namespace: kw::Crate },
|
||||
Impl => DefPathDataName::Anon { namespace: kw::Impl },
|
||||
|
|
@ -443,8 +500,9 @@ impl DefPathData {
|
|||
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
|
||||
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
|
||||
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
|
||||
AnonAssocTy => DefPathDataName::Anon { namespace: sym::anon_assoc },
|
||||
AnonAssocTy(..) => DefPathDataName::Anon { namespace: sym::anon_assoc },
|
||||
SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
|
||||
NestedStatic => DefPathDataName::Anon { namespace: sym::nested },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,21 +50,14 @@ fn trait_object_roundtrips() {
|
|||
}
|
||||
|
||||
fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) {
|
||||
let unambig = TyKind::TraitObject::<'_, ()>(
|
||||
&[],
|
||||
TaggedRef::new(
|
||||
&const {
|
||||
Lifetime {
|
||||
hir_id: HirId::INVALID,
|
||||
ident: Ident::new(sym::name, DUMMY_SP),
|
||||
kind: LifetimeKind::Static,
|
||||
source: LifetimeSource::Other,
|
||||
syntax: LifetimeSyntax::Hidden,
|
||||
}
|
||||
},
|
||||
syntax,
|
||||
),
|
||||
);
|
||||
let lt = Lifetime {
|
||||
hir_id: HirId::INVALID,
|
||||
ident: Ident::new(sym::name, DUMMY_SP),
|
||||
kind: LifetimeKind::Static,
|
||||
source: LifetimeSource::Other,
|
||||
syntax: LifetimeSyntax::Hidden,
|
||||
};
|
||||
let unambig = TyKind::TraitObject::<'_, ()>(&[], TaggedRef::new(<, syntax));
|
||||
let unambig_to_ambig = unsafe { std::mem::transmute::<_, TyKind<'_, AmbigArg>>(unambig) };
|
||||
|
||||
match unambig_to_ambig {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::iter;
|
|||
use hir::def_id::{DefId, DefIdMap, LocalDefId};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err};
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit::VisitorExt;
|
||||
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};
|
||||
|
|
@ -14,10 +14,10 @@ use rustc_infer::traits::util;
|
|||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{
|
||||
self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
|
||||
TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast,
|
||||
TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
||||
|
|
@ -1137,65 +1137,319 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
|||
// but found 0" it's confusing, because it looks like there
|
||||
// are zero. Since I don't quite know how to phrase things at
|
||||
// the moment, give a kind of vague error message.
|
||||
if trait_params != impl_params {
|
||||
let span = tcx
|
||||
.hir_get_generics(impl_m.def_id.expect_local())
|
||||
.expect("expected impl item to have generics or else we can't compare them")
|
||||
.span;
|
||||
if trait_params == impl_params {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut generics_span = None;
|
||||
let mut bounds_span = vec![];
|
||||
let mut where_span = None;
|
||||
if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
|
||||
&& let Some(trait_generics) = trait_node.generics()
|
||||
{
|
||||
generics_span = Some(trait_generics.span);
|
||||
// FIXME: we could potentially look at the impl's bounds to not point at bounds that
|
||||
// *are* present in the impl.
|
||||
for p in trait_generics.predicates {
|
||||
if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind {
|
||||
for b in pred.bounds {
|
||||
if !delay && let Some(guar) = check_region_late_boundedness(tcx, impl_m, trait_m) {
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
let span = tcx
|
||||
.hir_get_generics(impl_m.def_id.expect_local())
|
||||
.expect("expected impl item to have generics or else we can't compare them")
|
||||
.span;
|
||||
|
||||
let mut generics_span = None;
|
||||
let mut bounds_span = vec![];
|
||||
let mut where_span = None;
|
||||
|
||||
if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
|
||||
&& let Some(trait_generics) = trait_node.generics()
|
||||
{
|
||||
generics_span = Some(trait_generics.span);
|
||||
// FIXME: we could potentially look at the impl's bounds to not point at bounds that
|
||||
// *are* present in the impl.
|
||||
for p in trait_generics.predicates {
|
||||
match p.kind {
|
||||
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
|
||||
bounds,
|
||||
..
|
||||
})
|
||||
| hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
|
||||
bounds,
|
||||
..
|
||||
}) => {
|
||||
for b in *bounds {
|
||||
if let hir::GenericBound::Outlives(lt) = b {
|
||||
bounds_span.push(lt.ident.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id)
|
||||
&& let Some(impl_generics) = impl_node.generics()
|
||||
{
|
||||
let mut impl_bounds = 0;
|
||||
for p in impl_generics.predicates {
|
||||
if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind {
|
||||
for b in pred.bounds {
|
||||
}
|
||||
if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id)
|
||||
&& let Some(impl_generics) = impl_node.generics()
|
||||
{
|
||||
let mut impl_bounds = 0;
|
||||
for p in impl_generics.predicates {
|
||||
match p.kind {
|
||||
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
|
||||
bounds,
|
||||
..
|
||||
})
|
||||
| hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
|
||||
bounds,
|
||||
..
|
||||
}) => {
|
||||
for b in *bounds {
|
||||
if let hir::GenericBound::Outlives(_) = b {
|
||||
impl_bounds += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if impl_bounds == bounds_span.len() {
|
||||
bounds_span = vec![];
|
||||
} else if impl_generics.has_where_clause_predicates {
|
||||
where_span = Some(impl_generics.where_clause_span);
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if impl_bounds == bounds_span.len() {
|
||||
bounds_span = vec![];
|
||||
} else if impl_generics.has_where_clause_predicates {
|
||||
where_span = Some(impl_generics.where_clause_span);
|
||||
}
|
||||
}
|
||||
let reported = tcx
|
||||
.dcx()
|
||||
.create_err(LifetimesOrBoundsMismatchOnTrait {
|
||||
span,
|
||||
item_kind: impl_m.descr(),
|
||||
ident: impl_m.ident(tcx),
|
||||
generics_span,
|
||||
bounds_span,
|
||||
where_span,
|
||||
})
|
||||
.emit_unless(delay);
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
let reported = tcx
|
||||
.dcx()
|
||||
.create_err(LifetimesOrBoundsMismatchOnTrait {
|
||||
span,
|
||||
item_kind: impl_m.descr(),
|
||||
ident: impl_m.ident(tcx),
|
||||
generics_span,
|
||||
bounds_span,
|
||||
where_span,
|
||||
})
|
||||
.emit_unless(delay);
|
||||
|
||||
Err(reported)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
enum LateEarlyMismatch<'tcx> {
|
||||
EarlyInImpl(DefId, DefId, ty::Region<'tcx>),
|
||||
LateInImpl(DefId, DefId, ty::Region<'tcx>),
|
||||
}
|
||||
|
||||
fn check_region_late_boundedness<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_m: ty::AssocItem,
|
||||
trait_m: ty::AssocItem,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
if !impl_m.is_fn() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let (infcx, param_env) = tcx
|
||||
.infer_ctxt()
|
||||
.build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, impl_m.def_id));
|
||||
|
||||
let impl_m_args = infcx.fresh_args_for_item(DUMMY_SP, impl_m.def_id);
|
||||
let impl_m_sig = tcx.fn_sig(impl_m.def_id).instantiate(tcx, impl_m_args);
|
||||
let impl_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, impl_m_sig);
|
||||
|
||||
let trait_m_args = infcx.fresh_args_for_item(DUMMY_SP, trait_m.def_id);
|
||||
let trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_args);
|
||||
let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_m_sig);
|
||||
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
// Equate the signatures so that we can infer whether a late-bound param was present where
|
||||
// an early-bound param was expected, since we replace the late-bound lifetimes with
|
||||
// `ReLateParam`, and early-bound lifetimes with infer vars, so the early-bound args will
|
||||
// resolve to `ReLateParam` if there is a mismatch.
|
||||
let Ok(()) = ocx.eq(
|
||||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
ty::Binder::dummy(trait_m_sig),
|
||||
ty::Binder::dummy(impl_m_sig),
|
||||
) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let errors = ocx.select_where_possible();
|
||||
if !errors.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut mismatched = vec![];
|
||||
|
||||
let impl_generics = tcx.generics_of(impl_m.def_id);
|
||||
for (id_arg, arg) in
|
||||
std::iter::zip(ty::GenericArgs::identity_for_item(tcx, impl_m.def_id), impl_m_args)
|
||||
{
|
||||
if let ty::GenericArgKind::Lifetime(r) = arg.unpack()
|
||||
&& let ty::ReVar(vid) = r.kind()
|
||||
&& let r = infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.opportunistic_resolve_var(tcx, vid)
|
||||
&& let ty::ReLateParam(ty::LateParamRegion {
|
||||
kind: ty::LateParamRegionKind::Named(trait_param_def_id, _),
|
||||
..
|
||||
}) = r.kind()
|
||||
&& let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()
|
||||
{
|
||||
mismatched.push(LateEarlyMismatch::EarlyInImpl(
|
||||
impl_generics.region_param(ebr, tcx).def_id,
|
||||
trait_param_def_id,
|
||||
id_arg.expect_region(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let trait_generics = tcx.generics_of(trait_m.def_id);
|
||||
for (id_arg, arg) in
|
||||
std::iter::zip(ty::GenericArgs::identity_for_item(tcx, trait_m.def_id), trait_m_args)
|
||||
{
|
||||
if let ty::GenericArgKind::Lifetime(r) = arg.unpack()
|
||||
&& let ty::ReVar(vid) = r.kind()
|
||||
&& let r = infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.opportunistic_resolve_var(tcx, vid)
|
||||
&& let ty::ReLateParam(ty::LateParamRegion {
|
||||
kind: ty::LateParamRegionKind::Named(impl_param_def_id, _),
|
||||
..
|
||||
}) = r.kind()
|
||||
&& let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()
|
||||
{
|
||||
mismatched.push(LateEarlyMismatch::LateInImpl(
|
||||
impl_param_def_id,
|
||||
trait_generics.region_param(ebr, tcx).def_id,
|
||||
id_arg.expect_region(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if mismatched.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let spans: Vec<_> = mismatched
|
||||
.iter()
|
||||
.map(|param| {
|
||||
let (LateEarlyMismatch::EarlyInImpl(impl_param_def_id, ..)
|
||||
| LateEarlyMismatch::LateInImpl(impl_param_def_id, ..)) = param;
|
||||
tcx.def_span(impl_param_def_id)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut diag = tcx
|
||||
.dcx()
|
||||
.struct_span_err(spans, "lifetime parameters do not match the trait definition")
|
||||
.with_note("lifetime parameters differ in whether they are early- or late-bound")
|
||||
.with_code(E0195);
|
||||
for mismatch in mismatched {
|
||||
match mismatch {
|
||||
LateEarlyMismatch::EarlyInImpl(
|
||||
impl_param_def_id,
|
||||
trait_param_def_id,
|
||||
early_bound_region,
|
||||
) => {
|
||||
let mut multispan = MultiSpan::from_spans(vec![
|
||||
tcx.def_span(impl_param_def_id),
|
||||
tcx.def_span(trait_param_def_id),
|
||||
]);
|
||||
multispan
|
||||
.push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");
|
||||
multispan
|
||||
.push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");
|
||||
multispan.push_span_label(
|
||||
tcx.def_span(impl_param_def_id),
|
||||
format!("`{}` is early-bound", tcx.item_name(impl_param_def_id)),
|
||||
);
|
||||
multispan.push_span_label(
|
||||
tcx.def_span(trait_param_def_id),
|
||||
format!("`{}` is late-bound", tcx.item_name(trait_param_def_id)),
|
||||
);
|
||||
if let Some(span) =
|
||||
find_region_in_predicates(tcx, impl_m.def_id, early_bound_region)
|
||||
{
|
||||
multispan.push_span_label(
|
||||
span,
|
||||
format!(
|
||||
"this lifetime bound makes `{}` early-bound",
|
||||
tcx.item_name(impl_param_def_id)
|
||||
),
|
||||
);
|
||||
}
|
||||
diag.span_note(
|
||||
multispan,
|
||||
format!(
|
||||
"`{}` differs between the trait and impl",
|
||||
tcx.item_name(impl_param_def_id)
|
||||
),
|
||||
);
|
||||
}
|
||||
LateEarlyMismatch::LateInImpl(
|
||||
impl_param_def_id,
|
||||
trait_param_def_id,
|
||||
early_bound_region,
|
||||
) => {
|
||||
let mut multispan = MultiSpan::from_spans(vec![
|
||||
tcx.def_span(impl_param_def_id),
|
||||
tcx.def_span(trait_param_def_id),
|
||||
]);
|
||||
multispan
|
||||
.push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");
|
||||
multispan
|
||||
.push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");
|
||||
multispan.push_span_label(
|
||||
tcx.def_span(impl_param_def_id),
|
||||
format!("`{}` is late-bound", tcx.item_name(impl_param_def_id)),
|
||||
);
|
||||
multispan.push_span_label(
|
||||
tcx.def_span(trait_param_def_id),
|
||||
format!("`{}` is early-bound", tcx.item_name(trait_param_def_id)),
|
||||
);
|
||||
if let Some(span) =
|
||||
find_region_in_predicates(tcx, trait_m.def_id, early_bound_region)
|
||||
{
|
||||
multispan.push_span_label(
|
||||
span,
|
||||
format!(
|
||||
"this lifetime bound makes `{}` early-bound",
|
||||
tcx.item_name(trait_param_def_id)
|
||||
),
|
||||
);
|
||||
}
|
||||
diag.span_note(
|
||||
multispan,
|
||||
format!(
|
||||
"`{}` differs between the trait and impl",
|
||||
tcx.item_name(impl_param_def_id)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(diag.emit())
|
||||
}
|
||||
|
||||
fn find_region_in_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
early_bound_region: ty::Region<'tcx>,
|
||||
) -> Option<Span> {
|
||||
for (pred, span) in tcx.explicit_predicates_of(def_id).instantiate_identity(tcx) {
|
||||
if pred.visit_with(&mut FindRegion(early_bound_region)).is_break() {
|
||||
return Some(span);
|
||||
}
|
||||
}
|
||||
|
||||
struct FindRegion<'tcx>(ty::Region<'tcx>);
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindRegion<'tcx> {
|
||||
type Result = ControlFlow<()>;
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
|
||||
if r == self.0 { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(infcx))]
|
||||
|
|
|
|||
|
|
@ -76,6 +76,36 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
/// Convenience function to *deeply* normalize during wfcheck. In the old solver,
|
||||
/// this just dispatches to [`WfCheckingCtxt::normalize`], but in the new solver
|
||||
/// this calls `deeply_normalize` and reports errors if they are encountered.
|
||||
///
|
||||
/// This function should be called in favor of `normalize` in cases where we will
|
||||
/// then check the well-formedness of the type, since we only use the normalized
|
||||
/// signature types for implied bounds when checking regions.
|
||||
// FIXME(-Znext-solver): This should be removed when we compute implied outlives
|
||||
// bounds using the unnormalized signature of the function we're checking.
|
||||
fn deeply_normalize<T>(&self, span: Span, loc: Option<WellFormedLoc>, value: T) -> T
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
if self.infcx.next_trait_solver() {
|
||||
match self.ocx.deeply_normalize(
|
||||
&ObligationCause::new(span, self.body_def_id, ObligationCauseCode::WellFormed(loc)),
|
||||
self.param_env,
|
||||
value.clone(),
|
||||
) {
|
||||
Ok(value) => value,
|
||||
Err(errors) => {
|
||||
self.infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||
value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.normalize(span, loc, value)
|
||||
}
|
||||
}
|
||||
|
||||
fn register_wf_obligation(&self, span: Span, loc: Option<WellFormedLoc>, term: ty::Term<'tcx>) {
|
||||
let cause = traits::ObligationCause::new(
|
||||
span,
|
||||
|
|
@ -297,7 +327,8 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
|
|||
{
|
||||
let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
let item_ty = wfcx.normalize(hir_ty.span, Some(WellFormedLoc::Ty(def_id)), ty);
|
||||
let item_ty =
|
||||
wfcx.deeply_normalize(hir_ty.span, Some(WellFormedLoc::Ty(def_id)), ty);
|
||||
wfcx.register_wf_obligation(
|
||||
hir_ty.span,
|
||||
Some(WellFormedLoc::Ty(def_id)),
|
||||
|
|
@ -1073,7 +1104,7 @@ fn check_associated_item(
|
|||
match item.kind {
|
||||
ty::AssocKind::Const { .. } => {
|
||||
let ty = tcx.type_of(item.def_id).instantiate_identity();
|
||||
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
wfcx.register_wf_obligation(span, loc, ty.into());
|
||||
check_sized_if_body(
|
||||
wfcx,
|
||||
|
|
@ -1102,7 +1133,7 @@ fn check_associated_item(
|
|||
}
|
||||
if item.defaultness(tcx).has_value() {
|
||||
let ty = tcx.type_of(item.def_id).instantiate_identity();
|
||||
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
wfcx.register_wf_obligation(span, loc, ty.into());
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -1149,7 +1180,7 @@ fn check_type_defn<'tcx>(
|
|||
let field_id = field.did.expect_local();
|
||||
let hir::FieldDef { ty: hir_ty, .. } =
|
||||
tcx.hir_node_by_def_id(field_id).expect_field();
|
||||
let ty = wfcx.normalize(
|
||||
let ty = wfcx.deeply_normalize(
|
||||
hir_ty.span,
|
||||
None,
|
||||
tcx.type_of(field.did).instantiate_identity(),
|
||||
|
|
@ -1310,7 +1341,7 @@ fn check_item_type(
|
|||
|
||||
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
|
||||
let ty = tcx.type_of(item_id).instantiate_identity();
|
||||
let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
let item_ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
|
||||
let forbid_unsized = match unsized_handling {
|
||||
UnsizedHandling::Forbid => true,
|
||||
|
|
@ -1375,7 +1406,7 @@ fn check_impl<'tcx>(
|
|||
// other `Foo` impls are incoherent.
|
||||
tcx.ensure_ok().coherent_trait(trait_ref.def_id)?;
|
||||
let trait_span = hir_trait_ref.path.span;
|
||||
let trait_ref = wfcx.normalize(
|
||||
let trait_ref = wfcx.deeply_normalize(
|
||||
trait_span,
|
||||
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
|
||||
trait_ref,
|
||||
|
|
@ -1435,7 +1466,7 @@ fn check_impl<'tcx>(
|
|||
}
|
||||
None => {
|
||||
let self_ty = tcx.type_of(item.owner_id).instantiate_identity();
|
||||
let self_ty = wfcx.normalize(
|
||||
let self_ty = wfcx.deeply_normalize(
|
||||
item.span,
|
||||
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
|
||||
self_ty,
|
||||
|
|
@ -1640,7 +1671,7 @@ fn check_fn_or_method<'tcx>(
|
|||
|
||||
sig.inputs_and_output =
|
||||
tcx.mk_type_list_from_iter(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| {
|
||||
wfcx.normalize(
|
||||
wfcx.deeply_normalize(
|
||||
arg_span(idx),
|
||||
Some(WellFormedLoc::Param {
|
||||
function: def_id,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use rustc_ast::visit::walk_list;
|
|||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
|
||||
use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
|
||||
use rustc_hir::{
|
||||
self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node,
|
||||
|
|
@ -63,6 +64,7 @@ impl ResolvedArg {
|
|||
struct BoundVarContext<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
rbv: &'a mut ResolveBoundVars,
|
||||
disambiguator: &'a mut DisambiguatorState,
|
||||
scope: ScopeRef<'a>,
|
||||
}
|
||||
|
||||
|
|
@ -245,8 +247,12 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||
#[instrument(level = "debug", skip(tcx))]
|
||||
fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
|
||||
let mut rbv = ResolveBoundVars::default();
|
||||
let mut visitor =
|
||||
BoundVarContext { tcx, rbv: &mut rbv, scope: &Scope::Root { opt_parent_item: None } };
|
||||
let mut visitor = BoundVarContext {
|
||||
tcx,
|
||||
rbv: &mut rbv,
|
||||
scope: &Scope::Root { opt_parent_item: None },
|
||||
disambiguator: &mut DisambiguatorState::new(),
|
||||
};
|
||||
match tcx.hir_owner_node(local_def_id) {
|
||||
hir::OwnerNode::Item(item) => visitor.visit_item(item),
|
||||
hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
|
||||
|
|
@ -515,9 +521,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||
|
||||
let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque);
|
||||
if capture_all_in_scope_lifetimes {
|
||||
let tcx = self.tcx;
|
||||
let lifetime_ident = |def_id: LocalDefId| {
|
||||
let name = self.tcx.item_name(def_id.to_def_id());
|
||||
let span = self.tcx.def_span(def_id);
|
||||
let name = tcx.item_name(def_id.to_def_id());
|
||||
let span = tcx.def_span(def_id);
|
||||
Ident::new(name, span)
|
||||
};
|
||||
|
||||
|
|
@ -1091,8 +1098,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
where
|
||||
F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
|
||||
{
|
||||
let BoundVarContext { tcx, rbv, .. } = self;
|
||||
let mut this = BoundVarContext { tcx: *tcx, rbv, scope: &wrap_scope };
|
||||
let BoundVarContext { tcx, rbv, disambiguator, .. } = self;
|
||||
let mut this = BoundVarContext { tcx: *tcx, rbv, disambiguator, scope: &wrap_scope };
|
||||
let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
|
||||
{
|
||||
let _enter = span.enter();
|
||||
|
|
@ -1446,7 +1453,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
|
||||
#[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)]
|
||||
fn remap_opaque_captures(
|
||||
&self,
|
||||
&mut self,
|
||||
opaque_capture_scopes: &Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
|
||||
mut lifetime: ResolvedArg,
|
||||
ident: Ident,
|
||||
|
|
@ -1462,8 +1469,17 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
for &(opaque_def_id, captures) in opaque_capture_scopes.iter().rev() {
|
||||
let mut captures = captures.borrow_mut();
|
||||
let remapped = *captures.entry(lifetime).or_insert_with(|| {
|
||||
let feed =
|
||||
self.tcx.create_def(opaque_def_id, Some(ident.name), DefKind::LifetimeParam);
|
||||
// `opaque_def_id` is unique to the `BoundVarContext` pass which is executed once
|
||||
// per `resolve_bound_vars` query. This is the only location that creates
|
||||
// `OpaqueLifetime` paths. `<opaque_def_id>::OpaqueLifetime(..)` is thus unique
|
||||
// to this query and duplicates within the query are handled by `self.disambiguator`.
|
||||
let feed = self.tcx.create_def(
|
||||
opaque_def_id,
|
||||
None,
|
||||
DefKind::LifetimeParam,
|
||||
Some(DefPathData::OpaqueLifetime(ident.name)),
|
||||
&mut self.disambiguator,
|
||||
);
|
||||
feed.def_span(ident.span);
|
||||
feed.def_ident_span(Some(ident.span));
|
||||
feed.def_id()
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
|||
use rustc_hir::{AmbigArg, HirId};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{
|
||||
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
TypeVisitor, Upcast,
|
||||
self as ty, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitableExt, TypeVisitor, Upcast,
|
||||
};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_trait_selection::traits;
|
||||
|
|
@ -996,7 +996,7 @@ struct GenericParamAndBoundVarCollector<'a, 'tcx> {
|
|||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
|
||||
type Result = ControlFlow<ErrorGuaranteed>;
|
||||
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
|
||||
fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
binder: &ty::Binder<'tcx, T>,
|
||||
) -> Self::Result {
|
||||
|
|
|
|||
|
|
@ -172,7 +172,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
let principal_trait = regular_traits.into_iter().next();
|
||||
|
||||
let mut needed_associated_types = vec![];
|
||||
// A stable ordering of associated types from the principal trait and all its
|
||||
// supertraits. We use this to ensure that different substitutions of a trait
|
||||
// don't result in `dyn Trait` types with different projections lists, which
|
||||
// can be unsound: <https://github.com/rust-lang/rust/pull/136458>.
|
||||
// We achieve a stable ordering by walking over the unsubstituted principal
|
||||
// trait ref.
|
||||
let mut ordered_associated_types = vec![];
|
||||
|
||||
if let Some((principal_trait, ref spans)) = principal_trait {
|
||||
let principal_trait = principal_trait.map_bound(|trait_pred| {
|
||||
assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
|
||||
|
|
@ -197,16 +204,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// FIXME(negative_bounds): Handle this correctly...
|
||||
let trait_ref =
|
||||
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
|
||||
needed_associated_types.extend(
|
||||
ordered_associated_types.extend(
|
||||
tcx.associated_items(pred.trait_ref.def_id)
|
||||
.in_definition_order()
|
||||
// We only care about associated types.
|
||||
.filter(|item| item.is_type())
|
||||
// No RPITITs -- they're not dyn-compatible for now.
|
||||
.filter(|item| !item.is_impl_trait_in_trait())
|
||||
// If the associated type has a `where Self: Sized` bound,
|
||||
// we do not need to constrain the associated type.
|
||||
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
|
||||
.map(|item| (item.def_id, trait_ref)),
|
||||
);
|
||||
}
|
||||
|
|
@ -278,14 +282,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
}
|
||||
|
||||
// We compute the list of projection bounds taking the ordered associated types,
|
||||
// and check if there was an entry in the collected `projection_bounds`. Those
|
||||
// are computed by first taking the user-written associated types, then elaborating
|
||||
// the principal trait ref, and only using those if there was no user-written.
|
||||
// See note below about how we handle missing associated types with `Self: Sized`,
|
||||
// which are not required to be provided, but are still used if they are provided.
|
||||
let mut missing_assoc_types = FxIndexSet::default();
|
||||
let projection_bounds: Vec<_> = needed_associated_types
|
||||
let projection_bounds: Vec<_> = ordered_associated_types
|
||||
.into_iter()
|
||||
.filter_map(|key| {
|
||||
if let Some(assoc) = projection_bounds.get(&key) {
|
||||
Some(*assoc)
|
||||
} else {
|
||||
missing_assoc_types.insert(key);
|
||||
// If the associated type has a `where Self: Sized` bound, then
|
||||
// we do not need to provide the associated type. This results in
|
||||
// a `dyn Trait` type that has a different number of projection
|
||||
// bounds, which may lead to type mismatches.
|
||||
if !tcx.generics_require_sized_self(key.0) {
|
||||
missing_assoc_types.insert(key);
|
||||
}
|
||||
None
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1770,7 +1770,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
span: Span,
|
||||
opt_self_ty: Option<Ty<'tcx>>,
|
||||
item_def_id: DefId,
|
||||
trait_segment: &hir::PathSegment<'tcx>,
|
||||
trait_segment: Option<&hir::PathSegment<'tcx>>,
|
||||
item_segment: &hir::PathSegment<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
match self.lower_qpath_shared(
|
||||
|
|
@ -1795,7 +1795,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
span: Span,
|
||||
opt_self_ty: Option<Ty<'tcx>>,
|
||||
item_def_id: DefId,
|
||||
trait_segment: &hir::PathSegment<'tcx>,
|
||||
trait_segment: Option<&hir::PathSegment<'tcx>>,
|
||||
item_segment: &hir::PathSegment<'tcx>,
|
||||
) -> Const<'tcx> {
|
||||
match self.lower_qpath_shared(
|
||||
|
|
@ -1820,7 +1820,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
span: Span,
|
||||
opt_self_ty: Option<Ty<'tcx>>,
|
||||
item_def_id: DefId,
|
||||
trait_segment: &hir::PathSegment<'tcx>,
|
||||
trait_segment: Option<&hir::PathSegment<'tcx>>,
|
||||
item_segment: &hir::PathSegment<'tcx>,
|
||||
assoc_tag: ty::AssocTag,
|
||||
) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed> {
|
||||
|
|
@ -1840,7 +1840,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
debug!(?self_ty);
|
||||
|
||||
let trait_ref =
|
||||
self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false);
|
||||
self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment.unwrap(), false);
|
||||
debug!(?trait_ref);
|
||||
|
||||
let item_args =
|
||||
|
|
@ -2196,16 +2196,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
}
|
||||
Res::Def(DefKind::AssocTy, def_id) => {
|
||||
debug_assert!(path.segments.len() >= 2);
|
||||
let _ = self.prohibit_generic_args(
|
||||
path.segments[..path.segments.len() - 2].iter(),
|
||||
GenericsArgsErrExtend::None,
|
||||
);
|
||||
let trait_segment = if let [modules @ .., trait_, _item] = path.segments {
|
||||
let _ = self.prohibit_generic_args(modules.iter(), GenericsArgsErrExtend::None);
|
||||
Some(trait_)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.lower_qpath_ty(
|
||||
span,
|
||||
opt_self_ty,
|
||||
def_id,
|
||||
&path.segments[path.segments.len() - 2],
|
||||
trait_segment,
|
||||
path.segments.last().unwrap(),
|
||||
)
|
||||
}
|
||||
|
|
@ -2413,16 +2414,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
|
||||
}
|
||||
Res::Def(DefKind::AssocConst, did) => {
|
||||
debug_assert!(path.segments.len() >= 2);
|
||||
let _ = self.prohibit_generic_args(
|
||||
path.segments[..path.segments.len() - 2].iter(),
|
||||
GenericsArgsErrExtend::None,
|
||||
);
|
||||
let trait_segment = if let [modules @ .., trait_, _item] = path.segments {
|
||||
let _ = self.prohibit_generic_args(modules.iter(), GenericsArgsErrExtend::None);
|
||||
Some(trait_)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.lower_qpath_const(
|
||||
span,
|
||||
opt_self_ty,
|
||||
did,
|
||||
&path.segments[path.segments.len() - 2],
|
||||
trait_segment,
|
||||
path.segments.last().unwrap(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||
check::maybe_check_static_with_link_section(tcx, item_def_id);
|
||||
}
|
||||
DefKind::Const if tcx.generics_of(item_def_id).is_empty() => {
|
||||
let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty());
|
||||
let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty());
|
||||
let cid = GlobalId { instance, promoted: None };
|
||||
let typing_env = ty::TypingEnv::fully_monomorphized();
|
||||
tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid));
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
self.print_attr_item(&unparsed, unparsed.span);
|
||||
self.word("]");
|
||||
self.hardbreak()
|
||||
}
|
||||
hir::Attribute::Parsed(AttributeKind::DocComment { style, kind, comment, .. }) => {
|
||||
self.word(rustc_ast_pretty::pprust::state::doc_comment_to_string(
|
||||
|
|
@ -183,7 +184,7 @@ impl<'a> State<'a> {
|
|||
Node::Ty(a) => self.print_type(a),
|
||||
Node::AssocItemConstraint(a) => self.print_assoc_item_constraint(a),
|
||||
Node::TraitRef(a) => self.print_trait_ref(a),
|
||||
Node::OpaqueTy(o) => self.print_opaque_ty(o),
|
||||
Node::OpaqueTy(_) => panic!("cannot print Node::OpaqueTy"),
|
||||
Node::Pat(a) => self.print_pat(a),
|
||||
Node::TyPat(a) => self.print_ty_pat(a),
|
||||
Node::PatField(a) => self.print_patfield(a),
|
||||
|
|
@ -654,10 +655,11 @@ impl<'a> State<'a> {
|
|||
self.bclose(item.span, cb);
|
||||
}
|
||||
hir::ItemKind::GlobalAsm { asm, .. } => {
|
||||
// FIXME(nnethercote): `ib` is unclosed
|
||||
let (cb, _ib) = self.head("global_asm!");
|
||||
let (cb, ib) = self.head("global_asm!");
|
||||
self.print_inline_asm(asm);
|
||||
self.end(cb)
|
||||
self.word(";");
|
||||
self.end(cb);
|
||||
self.end(ib);
|
||||
}
|
||||
hir::ItemKind::TyAlias(ident, ty, generics) => {
|
||||
let (cb, ib) = self.head("type");
|
||||
|
|
@ -764,14 +766,6 @@ impl<'a> State<'a> {
|
|||
self.print_path(t.path, false);
|
||||
}
|
||||
|
||||
fn print_opaque_ty(&mut self, o: &hir::OpaqueTy<'_>) {
|
||||
// FIXME(nnethercote): `cb` and `ib` are unclosed
|
||||
let (_cb, _ib) = self.head("opaque");
|
||||
self.word("{");
|
||||
self.print_bounds("impl", o.bounds);
|
||||
self.word("}");
|
||||
}
|
||||
|
||||
fn print_formal_generic_params(&mut self, generic_params: &[hir::GenericParam<'_>]) {
|
||||
if !generic_params.is_empty() {
|
||||
self.word("for");
|
||||
|
|
@ -1509,7 +1503,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
hir::ExprKind::DropTemps(init) => {
|
||||
// Print `{`:
|
||||
let cb = self.cbox(INDENT_UNIT);
|
||||
let cb = self.cbox(0);
|
||||
let ib = self.ibox(0);
|
||||
self.bopen(ib);
|
||||
|
||||
|
|
@ -1532,16 +1526,18 @@ impl<'a> State<'a> {
|
|||
self.print_if(test, blk, elseopt);
|
||||
}
|
||||
hir::ExprKind::Loop(blk, opt_label, _, _) => {
|
||||
let cb = self.cbox(0);
|
||||
let ib = self.ibox(0);
|
||||
if let Some(label) = opt_label {
|
||||
self.print_ident(label.ident);
|
||||
self.word_space(":");
|
||||
}
|
||||
let (cb, ib) = self.head("loop");
|
||||
self.word_nbsp("loop");
|
||||
self.print_block(blk, cb, ib);
|
||||
}
|
||||
hir::ExprKind::Match(expr, arms, _) => {
|
||||
let cb = self.cbox(INDENT_UNIT);
|
||||
let ib = self.ibox(INDENT_UNIT);
|
||||
let cb = self.cbox(0);
|
||||
let ib = self.ibox(0);
|
||||
self.word_nbsp("match");
|
||||
self.print_expr_as_cond(expr);
|
||||
self.space();
|
||||
|
|
@ -1572,15 +1568,6 @@ impl<'a> State<'a> {
|
|||
|
||||
// This is a bare expression.
|
||||
self.ann.nested(self, Nested::Body(body));
|
||||
// FIXME(nnethercote): this is bogus
|
||||
let fake_ib = BoxMarker;
|
||||
self.end(fake_ib);
|
||||
|
||||
// A box will be closed by `print_expr`, but we didn't want an overall
|
||||
// wrapper so we closed the corresponding opening. so create an
|
||||
// empty box to satisfy the close.
|
||||
// FIXME(nnethercote): this is bogus, and `print_expr` is missing
|
||||
let _ib = self.ibox(0);
|
||||
}
|
||||
hir::ExprKind::Block(blk, opt_label) => {
|
||||
if let Some(label) = opt_label {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_trait_selection::traits::{
|
|||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::coercion::{AsCoercionSite, CoerceMany};
|
||||
use crate::{Diverges, Expectation, FnCtxt, Needs};
|
||||
use crate::{Diverges, Expectation, FnCtxt, GatherLocalsVisitor, Needs};
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
#[instrument(skip(self), level = "debug", ret)]
|
||||
|
|
@ -43,6 +43,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// #55810: Type check patterns first so we get types for all bindings.
|
||||
let scrut_span = scrut.span.find_ancestor_inside(expr.span).unwrap_or(scrut.span);
|
||||
for arm in arms {
|
||||
GatherLocalsVisitor::gather_from_arm(self, arm);
|
||||
|
||||
self.check_pat_top(arm.pat, scrutinee_ty, Some(scrut_span), Some(scrut), None);
|
||||
}
|
||||
|
||||
|
|
@ -601,7 +603,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// FIXME(-Znext-solver): Remove this branch once `replace_opaque_types_with_infer` is gone.
|
||||
ty::Infer(ty::TyVar(_)) => self
|
||||
.inner
|
||||
.borrow()
|
||||
.borrow_mut()
|
||||
.opaque_types()
|
||||
.iter_opaque_types()
|
||||
.find(|(_, v)| v.ty == expected_ty)
|
||||
.map(|(k, _)| (k.def_id, k.args))?,
|
||||
|
|
|
|||
|
|
@ -1051,20 +1051,19 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
fn check_ref_cast(
|
||||
&self,
|
||||
fcx: &FnCtxt<'a, 'tcx>,
|
||||
m_expr: ty::TypeAndMut<'tcx>,
|
||||
m_cast: ty::TypeAndMut<'tcx>,
|
||||
mut m_expr: ty::TypeAndMut<'tcx>,
|
||||
mut m_cast: ty::TypeAndMut<'tcx>,
|
||||
) -> Result<CastKind, CastError<'tcx>> {
|
||||
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
|
||||
m_expr.ty = fcx.try_structurally_resolve_type(self.expr_span, m_expr.ty);
|
||||
m_cast.ty = fcx.try_structurally_resolve_type(self.cast_span, m_cast.ty);
|
||||
|
||||
if m_expr.mutbl >= m_cast.mutbl
|
||||
&& let ty::Array(ety, _) = m_expr.ty.kind()
|
||||
&& fcx.can_eq(fcx.param_env, *ety, m_cast.ty)
|
||||
{
|
||||
// Due to the limitations of LLVM global constants,
|
||||
// region pointers end up pointing at copies of
|
||||
// vector elements instead of the original values.
|
||||
// To allow raw pointers to work correctly, we
|
||||
// need to special-case obtaining a raw pointer
|
||||
// from a region pointer to a vector.
|
||||
// Due to historical reasons we allow directly casting references of
|
||||
// arrays into raw pointers of their element type.
|
||||
|
||||
// Coerce to a raw pointer so that we generate RawPtr in MIR.
|
||||
let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ use std::cell::RefCell;
|
|||
use rustc_abi::ExternAbi;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir_analysis::check::check_function_signature;
|
||||
use rustc_infer::infer::RegionVariableOrigin;
|
||||
|
|
@ -50,7 +49,9 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||
|
||||
let span = body.value.span;
|
||||
|
||||
GatherLocalsVisitor::new(fcx).visit_body(body);
|
||||
for param in body.params {
|
||||
GatherLocalsVisitor::gather_from_param(fcx, param);
|
||||
}
|
||||
|
||||
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
|
||||
// (as it's created inside the body itself, not passed in from outside).
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ use rustc_errors::{
|
|||
};
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ExprKind, HirId, QPath};
|
||||
use rustc_hir_analysis::NoVariantNamed;
|
||||
|
|
@ -50,8 +49,8 @@ use crate::errors::{
|
|||
YieldExprOutsideOfCoroutine,
|
||||
};
|
||||
use crate::{
|
||||
BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, Needs, TupleArgumentsFlag, cast,
|
||||
fatally_break_rust, report_unexpected_variant_res, type_error_struct,
|
||||
BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, GatherLocalsVisitor, Needs,
|
||||
TupleArgumentsFlag, cast, fatally_break_rust, report_unexpected_variant_res, type_error_struct,
|
||||
};
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
|
@ -1518,11 +1517,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let_expr: &'tcx hir::LetExpr<'tcx>,
|
||||
hir_id: HirId,
|
||||
) -> Ty<'tcx> {
|
||||
GatherLocalsVisitor::gather_from_let_expr(self, let_expr, hir_id);
|
||||
|
||||
// for let statements, this is done in check_stmt
|
||||
let init = let_expr.init;
|
||||
self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression");
|
||||
|
||||
// otherwise check exactly as a let statement
|
||||
self.check_decl((let_expr, hir_id).into());
|
||||
|
||||
// but return a bool, for this is a boolean expression
|
||||
if let ast::Recovered::Yes(error_guaranteed) = let_expr.recovered {
|
||||
self.set_tainted_by_errors(error_guaranteed);
|
||||
|
|
@ -1827,7 +1830,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Create a new function context.
|
||||
let def_id = block.def_id;
|
||||
let fcx = FnCtxt::new(self, self.param_env, def_id);
|
||||
crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
|
||||
|
||||
let ty = fcx.check_expr_with_expectation(body.value, expected);
|
||||
fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::SizedConstOrStatic);
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ pub trait TypeInformationCtxt<'tcx> {
|
|||
|
||||
fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T;
|
||||
|
||||
fn try_structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
|
||||
fn structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
|
||||
|
||||
fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error;
|
||||
|
||||
|
|
@ -191,8 +191,8 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
|
|||
self.infcx.resolve_vars_if_possible(t)
|
||||
}
|
||||
|
||||
fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
(**self).try_structurally_resolve_type(sp, ty)
|
||||
fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
(**self).structurally_resolve_type(sp, ty)
|
||||
}
|
||||
|
||||
fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error {
|
||||
|
|
@ -236,7 +236,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
|
|||
self.0.maybe_typeck_results().expect("expected typeck results")
|
||||
}
|
||||
|
||||
fn try_structurally_resolve_type(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
fn structurally_resolve_type(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
// FIXME: Maybe need to normalize here.
|
||||
ty
|
||||
}
|
||||
|
|
@ -776,7 +776,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
|
||||
// Select just those fields of the `with`
|
||||
// expression that will actually be used
|
||||
match self.cx.try_structurally_resolve_type(with_expr.span, with_place.place.ty()).kind() {
|
||||
match self.cx.structurally_resolve_type(with_expr.span, with_place.place.ty()).kind() {
|
||||
ty::Adt(adt, args) if adt.is_struct() => {
|
||||
// Consume those fields of the with expression that are needed.
|
||||
for (f_index, with_field) in adt.non_enum_variant().fields.iter_enumerated() {
|
||||
|
|
@ -1176,7 +1176,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
/// two operations: a dereference to reach the array data and then an index to
|
||||
/// jump forward to the relevant item.
|
||||
impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> {
|
||||
fn resolve_type_vars_or_bug(
|
||||
fn expect_and_resolve_type(
|
||||
&self,
|
||||
id: HirId,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
|
|
@ -1185,12 +1185,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
Some(ty) => {
|
||||
let ty = self.cx.resolve_vars_if_possible(ty);
|
||||
self.cx.error_reported_in_ty(ty)?;
|
||||
if ty.is_ty_var() {
|
||||
debug!("resolve_type_vars_or_bug: infer var from {:?}", ty);
|
||||
Err(self.cx.report_bug(self.cx.tcx().hir_span(id), "encountered type variable"))
|
||||
} else {
|
||||
Ok(ty)
|
||||
}
|
||||
Ok(ty)
|
||||
}
|
||||
None => {
|
||||
// FIXME: We shouldn't be relying on the infcx being tainted.
|
||||
|
|
@ -1201,15 +1196,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
}
|
||||
|
||||
fn node_ty(&self, hir_id: HirId) -> Result<Ty<'tcx>, Cx::Error> {
|
||||
self.resolve_type_vars_or_bug(hir_id, self.cx.typeck_results().node_type_opt(hir_id))
|
||||
self.expect_and_resolve_type(hir_id, self.cx.typeck_results().node_type_opt(hir_id))
|
||||
}
|
||||
|
||||
fn expr_ty(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, Cx::Error> {
|
||||
self.resolve_type_vars_or_bug(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr))
|
||||
self.expect_and_resolve_type(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr))
|
||||
}
|
||||
|
||||
fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, Cx::Error> {
|
||||
self.resolve_type_vars_or_bug(
|
||||
self.expect_and_resolve_type(
|
||||
expr.hir_id,
|
||||
self.cx.typeck_results().expr_ty_adjusted_opt(expr),
|
||||
)
|
||||
|
|
@ -1264,10 +1259,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
// a bind-by-ref means that the base_ty will be the type of the ident itself,
|
||||
// but what we want here is the type of the underlying value being borrowed.
|
||||
// So peel off one-level, turning the &T into T.
|
||||
match self
|
||||
.cx
|
||||
.try_structurally_resolve_type(pat.span, base_ty)
|
||||
.builtin_deref(false)
|
||||
match self.cx.structurally_resolve_type(pat.span, base_ty).builtin_deref(false)
|
||||
{
|
||||
Some(ty) => Ok(ty),
|
||||
None => {
|
||||
|
|
@ -1513,10 +1505,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
if node_ty != place_ty
|
||||
&& self
|
||||
.cx
|
||||
.try_structurally_resolve_type(
|
||||
self.cx.tcx().hir_span(base_place.hir_id),
|
||||
place_ty,
|
||||
)
|
||||
.structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), place_ty)
|
||||
.is_impl_trait()
|
||||
{
|
||||
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
|
||||
|
|
@ -1538,7 +1527,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
let base_ty = self.expr_ty_adjusted(base)?;
|
||||
|
||||
let ty::Ref(region, _, mutbl) =
|
||||
*self.cx.try_structurally_resolve_type(base.span, base_ty).kind()
|
||||
*self.cx.structurally_resolve_type(base.span, base_ty).kind()
|
||||
else {
|
||||
span_bug!(expr.span, "cat_overloaded_place: base is not a reference");
|
||||
};
|
||||
|
|
@ -1556,7 +1545,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
let base_curr_ty = base_place.place.ty();
|
||||
let deref_ty = match self
|
||||
.cx
|
||||
.try_structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), base_curr_ty)
|
||||
.structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), base_curr_ty)
|
||||
.builtin_deref(true)
|
||||
{
|
||||
Some(ty) => ty,
|
||||
|
|
@ -1584,7 +1573,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
) -> Result<VariantIdx, Cx::Error> {
|
||||
let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id);
|
||||
let ty = self.cx.typeck_results().node_type(pat_hir_id);
|
||||
let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else {
|
||||
let ty::Adt(adt_def, _) = self.cx.structurally_resolve_type(span, ty).kind() else {
|
||||
return Err(self
|
||||
.cx
|
||||
.report_bug(span, "struct or tuple struct pattern not applied to an ADT"));
|
||||
|
|
@ -1616,7 +1605,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
span: Span,
|
||||
) -> Result<usize, Cx::Error> {
|
||||
let ty = self.cx.typeck_results().node_type(pat_hir_id);
|
||||
match self.cx.try_structurally_resolve_type(span, ty).kind() {
|
||||
match self.cx.structurally_resolve_type(span, ty).kind() {
|
||||
ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
|
||||
_ => {
|
||||
self.cx
|
||||
|
|
@ -1631,7 +1620,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
/// Here `pat_hir_id` is the HirId of the pattern itself.
|
||||
fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> Result<usize, Cx::Error> {
|
||||
let ty = self.cx.typeck_results().node_type(pat_hir_id);
|
||||
match self.cx.try_structurally_resolve_type(span, ty).kind() {
|
||||
match self.cx.structurally_resolve_type(span, ty).kind() {
|
||||
ty::Tuple(args) => Ok(args.len()),
|
||||
_ => Err(self.cx.report_bug(span, "tuple pattern not applied to a tuple")),
|
||||
}
|
||||
|
|
@ -1820,7 +1809,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
PatKind::Slice(before, ref slice, after) => {
|
||||
let Some(element_ty) = self
|
||||
.cx
|
||||
.try_structurally_resolve_type(pat.span, place_with_id.place.ty())
|
||||
.structurally_resolve_type(pat.span, place_with_id.place.ty())
|
||||
.builtin_index()
|
||||
else {
|
||||
debug!("explicit index of non-indexable type {:?}", place_with_id);
|
||||
|
|
@ -1890,7 +1879,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
}
|
||||
|
||||
fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
||||
if let ty::Adt(def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() {
|
||||
if let ty::Adt(def, _) = self.cx.structurally_resolve_type(span, ty).kind() {
|
||||
// Note that if a non-exhaustive SingleVariant is defined in another crate, we need
|
||||
// to assume that more cases will be added to the variant in the future. This mean
|
||||
// that we should handle non-exhaustive SingleVariant the same way we would handle
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ use crate::method::probe::IsSuggestion;
|
|||
use crate::method::probe::Mode::MethodCall;
|
||||
use crate::method::probe::ProbeScope::TraitsInScope;
|
||||
use crate::{
|
||||
BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy, Needs, TupleArgumentsFlag, errors,
|
||||
struct_span_code_err,
|
||||
BreakableCtxt, Diverges, Expectation, FnCtxt, GatherLocalsVisitor, LoweredTy, Needs,
|
||||
TupleArgumentsFlag, errors, struct_span_code_err,
|
||||
};
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
|
|
@ -1765,6 +1765,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
/// Type check a `let` statement.
|
||||
fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) {
|
||||
GatherLocalsVisitor::gather_from_local(self, local);
|
||||
|
||||
let ty = self.check_decl(local.into());
|
||||
self.write_ty(local.hir_id, ty);
|
||||
if local.pat.is_never_pattern() {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,14 @@ impl<'a> From<(&'a hir::LetExpr<'a>, HirId)> for Declaration<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The `GatherLocalsVisitor` is responsible for initializing local variable types
|
||||
/// in the [`ty::TypeckResults`] for all subpatterns in statements and expressions
|
||||
/// like `let`, `match`, and params of function bodies. It also adds `Sized` bounds
|
||||
/// for these types (with exceptions for unsized feature gates like `unsized_fn_params`).
|
||||
///
|
||||
/// Failure to visit locals will cause an ICE in writeback when the local's type is
|
||||
/// resolved. Visiting locals twice will ICE in the `GatherLocalsVisitor`, since it
|
||||
/// will overwrite the type previously stored in the local.
|
||||
pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
|
||||
fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
// parameters are special cases of patterns, but we want to handle them as
|
||||
|
|
@ -63,9 +71,37 @@ pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
|
|||
outermost_fn_param_pat: Option<(Span, HirId)>,
|
||||
}
|
||||
|
||||
// N.B. additional `gather_*` functions should be careful to only walk the pattern
|
||||
// for new expressions, since visiting sub-expressions or nested bodies may initialize
|
||||
// locals which are not conceptually owned by the gathered statement or expression.
|
||||
impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
|
||||
pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>) -> Self {
|
||||
Self { fcx, outermost_fn_param_pat: None }
|
||||
pub(crate) fn gather_from_local(fcx: &'a FnCtxt<'a, 'tcx>, local: &'tcx hir::LetStmt<'tcx>) {
|
||||
let mut visitor = GatherLocalsVisitor { fcx, outermost_fn_param_pat: None };
|
||||
visitor.declare(local.into());
|
||||
visitor.visit_pat(local.pat);
|
||||
}
|
||||
|
||||
pub(crate) fn gather_from_let_expr(
|
||||
fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
let_expr: &'tcx hir::LetExpr<'tcx>,
|
||||
expr_hir_id: hir::HirId,
|
||||
) {
|
||||
let mut visitor = GatherLocalsVisitor { fcx, outermost_fn_param_pat: None };
|
||||
visitor.declare((let_expr, expr_hir_id).into());
|
||||
visitor.visit_pat(let_expr.pat);
|
||||
}
|
||||
|
||||
pub(crate) fn gather_from_param(fcx: &'a FnCtxt<'a, 'tcx>, param: &'tcx hir::Param<'tcx>) {
|
||||
let mut visitor = GatherLocalsVisitor {
|
||||
fcx,
|
||||
outermost_fn_param_pat: Some((param.ty_span, param.hir_id)),
|
||||
};
|
||||
visitor.visit_pat(param.pat);
|
||||
}
|
||||
|
||||
pub(crate) fn gather_from_arm(fcx: &'a FnCtxt<'a, 'tcx>, local: &'tcx hir::Arm<'tcx>) {
|
||||
let mut visitor = GatherLocalsVisitor { fcx, outermost_fn_param_pat: None };
|
||||
visitor.visit_pat(local.pat);
|
||||
}
|
||||
|
||||
fn assign(&mut self, span: Span, nid: HirId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
|
||||
|
|
@ -73,12 +109,12 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
|
|||
None => {
|
||||
// Infer the variable's type.
|
||||
let var_ty = self.fcx.next_ty_var(span);
|
||||
self.fcx.locals.borrow_mut().insert(nid, var_ty);
|
||||
assert_eq!(self.fcx.locals.borrow_mut().insert(nid, var_ty), None);
|
||||
var_ty
|
||||
}
|
||||
Some(typ) => {
|
||||
// Take type that the user specified.
|
||||
self.fcx.locals.borrow_mut().insert(nid, typ);
|
||||
assert_eq!(self.fcx.locals.borrow_mut().insert(nid, typ), None);
|
||||
typ
|
||||
}
|
||||
}
|
||||
|
|
@ -133,13 +169,6 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
|
|||
intravisit::walk_expr(self, expr)
|
||||
}
|
||||
|
||||
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
|
||||
let old_outermost_fn_param_pat =
|
||||
self.outermost_fn_param_pat.replace((param.ty_span, param.hir_id));
|
||||
intravisit::walk_param(self, param);
|
||||
self.outermost_fn_param_pat = old_outermost_fn_param_pat;
|
||||
}
|
||||
|
||||
// Add pattern bindings.
|
||||
fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
|
||||
if let PatKind::Binding(_, _, ident, _) = p.kind {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ mod gather_locals;
|
|||
mod intrinsicck;
|
||||
mod method;
|
||||
mod op;
|
||||
mod opaque_types;
|
||||
mod pat;
|
||||
mod place_op;
|
||||
mod rvalue_scopes;
|
||||
|
|
@ -46,7 +47,6 @@ use rustc_errors::codes::*;
|
|||
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{HirId, HirIdMap, Node};
|
||||
use rustc_hir_analysis::check::check_abi;
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
|
|
@ -191,9 +191,6 @@ fn typeck_with_inspect<'tcx>(
|
|||
let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id)));
|
||||
fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code);
|
||||
|
||||
// Gather locals in statics (because of block expressions).
|
||||
GatherLocalsVisitor::new(&fcx).visit_body(body);
|
||||
|
||||
fcx.check_expr_coercible_to_type(body.value, expected_type, None);
|
||||
|
||||
fcx.write_ty(id, expected_type);
|
||||
|
|
@ -249,9 +246,7 @@ fn typeck_with_inspect<'tcx>(
|
|||
|
||||
let typeck_results = fcx.resolve_type_vars_in_body(body);
|
||||
|
||||
// We clone the defined opaque types during writeback in the new solver
|
||||
// because we have to use them during normalization.
|
||||
let _ = fcx.infcx.take_opaque_types();
|
||||
fcx.detect_opaque_types_added_during_writeback();
|
||||
|
||||
// Consistency check our TypeckResults instance can hold all ItemLocalIds
|
||||
// it will need to hold.
|
||||
|
|
|
|||
26
compiler/rustc_hir_typeck/src/opaque_types.rs
Normal file
26
compiler/rustc_hir_typeck/src/opaque_types.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
use super::FnCtxt;
|
||||
impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
/// We may in theory add further uses of an opaque after cloning the opaque
|
||||
/// types storage during writeback when computing the defining uses.
|
||||
///
|
||||
/// Silently ignoring them is dangerous and could result in ICE or even in
|
||||
/// unsoundness, so we make sure we catch such cases here. There's currently
|
||||
/// no known code where this actually happens, even with the new solver which
|
||||
/// does normalize types in writeback after cloning the opaque type storage.
|
||||
///
|
||||
/// FIXME(@lcnr): I believe this should be possible in theory and would like
|
||||
/// an actual test here. After playing around with this for an hour, I wasn't
|
||||
/// able to do anything which didn't already try to normalize the opaque before
|
||||
/// then, either allowing compilation to succeed or causing an ambiguity error.
|
||||
pub(super) fn detect_opaque_types_added_during_writeback(&self) {
|
||||
let num_entries = self.checked_opaque_types_storage_entries.take().unwrap();
|
||||
for (key, hidden_type) in
|
||||
self.inner.borrow_mut().opaque_types().opaque_types_added_since(num_entries)
|
||||
{
|
||||
let opaque_type_string = self.tcx.def_path_str(key.def_id);
|
||||
let msg = format!("unexpected cyclic definition of `{opaque_type_string}`");
|
||||
self.dcx().span_delayed_bug(hidden_type.span, msg);
|
||||
}
|
||||
let _ = self.take_opaque_types();
|
||||
}
|
||||
}
|
||||
|
|
@ -177,16 +177,20 @@ enum PeelKind {
|
|||
/// Only peel reference types. This is used for explicit `deref!(_)` patterns, which dereference
|
||||
/// any number of `&`/`&mut` references, plus a single smart pointer.
|
||||
ExplicitDerefPat,
|
||||
/// Implicitly peel any number of references, and if `deref_patterns` is enabled, smart pointer
|
||||
/// ADTs. In order to peel only as much as necessary for the pattern to match, the `until_adt`
|
||||
/// field contains the ADT def that the pattern is a constructor for, if applicable, so that we
|
||||
/// don't peel it. See [`ResolvedPat`] for more information.
|
||||
Implicit { until_adt: Option<DefId> },
|
||||
/// Implicitly peel references, and if `deref_patterns` is enabled, smart pointer ADTs.
|
||||
Implicit {
|
||||
/// The ADT the pattern is a constructor for, if applicable, so that we don't peel it. See
|
||||
/// [`ResolvedPat`] for more information.
|
||||
until_adt: Option<DefId>,
|
||||
/// The number of references at the head of the pattern's type, so we can leave that many
|
||||
/// untouched. This is `1` for string literals, and `0` for most patterns.
|
||||
pat_ref_layers: usize,
|
||||
},
|
||||
}
|
||||
|
||||
impl AdjustMode {
|
||||
const fn peel_until_adt(opt_adt_def: Option<DefId>) -> AdjustMode {
|
||||
AdjustMode::Peel { kind: PeelKind::Implicit { until_adt: opt_adt_def } }
|
||||
AdjustMode::Peel { kind: PeelKind::Implicit { until_adt: opt_adt_def, pat_ref_layers: 0 } }
|
||||
}
|
||||
const fn peel_all() -> AdjustMode {
|
||||
AdjustMode::peel_until_adt(None)
|
||||
|
|
@ -488,9 +492,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
match pat.kind {
|
||||
// Peel off a `&` or `&mut` from the scrutinee type. See the examples in
|
||||
// `tests/ui/rfcs/rfc-2005-default-binding-mode`.
|
||||
_ if let AdjustMode::Peel { .. } = adjust_mode
|
||||
_ if let AdjustMode::Peel { kind: peel_kind } = adjust_mode
|
||||
&& pat.default_binding_modes
|
||||
&& let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() =>
|
||||
&& let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind()
|
||||
&& self.should_peel_ref(peel_kind, expected) =>
|
||||
{
|
||||
debug!("inspecting {:?}", expected);
|
||||
|
||||
|
|
@ -531,24 +536,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// If `deref_patterns` is enabled, peel a smart pointer from the scrutinee type. See the
|
||||
// examples in `tests/ui/pattern/deref_patterns/`.
|
||||
_ if self.tcx.features().deref_patterns()
|
||||
&& let AdjustMode::Peel { kind: PeelKind::Implicit { until_adt } } = adjust_mode
|
||||
&& let AdjustMode::Peel { kind: peel_kind } = adjust_mode
|
||||
&& pat.default_binding_modes
|
||||
// For simplicity, only apply overloaded derefs if `expected` is a known ADT.
|
||||
// FIXME(deref_patterns): we'll get better diagnostics for users trying to
|
||||
// implicitly deref generics if we allow them here, but primitives, tuples, and
|
||||
// inference vars definitely should be stopped. Figure out what makes most sense.
|
||||
&& let ty::Adt(scrutinee_adt, _) = *expected.kind()
|
||||
// Don't peel if the pattern type already matches the scrutinee. E.g., stop here if
|
||||
// matching on a `Cow<'a, T>` scrutinee with a `Cow::Owned(_)` pattern.
|
||||
&& until_adt != Some(scrutinee_adt.did())
|
||||
// At this point, the pattern isn't able to match `expected` without peeling. Check
|
||||
// that it implements `Deref` before assuming it's a smart pointer, to get a normal
|
||||
// type error instead of a missing impl error if not. This only checks for `Deref`,
|
||||
// not `DerefPure`: we require that too, but we want a trait error if it's missing.
|
||||
&& let Some(deref_trait) = self.tcx.lang_items().deref_trait()
|
||||
&& self
|
||||
.type_implements_trait(deref_trait, [expected], self.param_env)
|
||||
.may_apply() =>
|
||||
&& self.should_peel_smart_pointer(peel_kind, expected) =>
|
||||
{
|
||||
debug!("scrutinee ty {expected:?} is a smart pointer, inserting overloaded deref");
|
||||
// The scrutinee is a smart pointer; implicitly dereference it. This adds a
|
||||
|
|
@ -660,14 +650,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
match &pat.kind {
|
||||
// Type checking these product-like types successfully always require
|
||||
// that the expected type be of those types and not reference types.
|
||||
PatKind::Tuple(..)
|
||||
| PatKind::Range(..)
|
||||
| PatKind::Slice(..) => AdjustMode::peel_all(),
|
||||
PatKind::Tuple(..) | PatKind::Range(..) | PatKind::Slice(..) => AdjustMode::peel_all(),
|
||||
// When checking an explicit deref pattern, only peel reference types.
|
||||
// FIXME(deref_patterns): If box patterns and deref patterns need to coexist, box
|
||||
// patterns may want `PeelKind::Implicit`, stopping on encountering a box.
|
||||
| PatKind::Box(_)
|
||||
| PatKind::Deref(_) => AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat },
|
||||
PatKind::Box(_) | PatKind::Deref(_) => {
|
||||
AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat }
|
||||
}
|
||||
// A never pattern behaves somewhat like a literal or unit variant.
|
||||
PatKind::Never => AdjustMode::peel_all(),
|
||||
// For patterns with paths, how we peel the scrutinee depends on the path's resolution.
|
||||
|
|
@ -680,23 +669,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// String and byte-string literals result in types `&str` and `&[u8]` respectively.
|
||||
// All other literals result in non-reference types.
|
||||
// As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
|
||||
//
|
||||
// Call `resolve_vars_if_possible` here for inline const blocks.
|
||||
PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() {
|
||||
ty::Ref(..) => AdjustMode::Pass,
|
||||
_ => {
|
||||
// Path patterns have already been handled, and inline const blocks currently
|
||||
// aren't possible to write, so any handling for them would be untested.
|
||||
if cfg!(debug_assertions)
|
||||
&& self.tcx.features().deref_patterns()
|
||||
&& !matches!(lt.kind, PatExprKind::Lit { .. })
|
||||
{
|
||||
span_bug!(lt.span, "FIXME(deref_patterns): adjust mode unimplemented for {:?}", lt.kind);
|
||||
}
|
||||
AdjustMode::peel_all()
|
||||
// As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}` unless
|
||||
// `deref_patterns` is enabled.
|
||||
PatKind::Expr(lt) => {
|
||||
// Path patterns have already been handled, and inline const blocks currently
|
||||
// aren't possible to write, so any handling for them would be untested.
|
||||
if cfg!(debug_assertions)
|
||||
&& self.tcx.features().deref_patterns()
|
||||
&& !matches!(lt.kind, PatExprKind::Lit { .. })
|
||||
{
|
||||
span_bug!(
|
||||
lt.span,
|
||||
"FIXME(deref_patterns): adjust mode unimplemented for {:?}",
|
||||
lt.kind
|
||||
);
|
||||
}
|
||||
},
|
||||
// Call `resolve_vars_if_possible` here for inline const blocks.
|
||||
let lit_ty = self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt));
|
||||
// If `deref_patterns` is enabled, allow `if let "foo" = &&"foo" {}`.
|
||||
if self.tcx.features().deref_patterns() {
|
||||
let mut peeled_ty = lit_ty;
|
||||
let mut pat_ref_layers = 0;
|
||||
while let ty::Ref(_, inner_ty, mutbl) =
|
||||
*self.try_structurally_resolve_type(pat.span, peeled_ty).kind()
|
||||
{
|
||||
// We rely on references at the head of constants being immutable.
|
||||
debug_assert!(mutbl.is_not());
|
||||
pat_ref_layers += 1;
|
||||
peeled_ty = inner_ty;
|
||||
}
|
||||
AdjustMode::Peel {
|
||||
kind: PeelKind::Implicit { until_adt: None, pat_ref_layers },
|
||||
}
|
||||
} else {
|
||||
if lit_ty.is_ref() { AdjustMode::Pass } else { AdjustMode::peel_all() }
|
||||
}
|
||||
}
|
||||
|
||||
// Ref patterns are complicated, we handle them in `check_pat_ref`.
|
||||
PatKind::Ref(..)
|
||||
|
|
@ -720,6 +728,67 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Assuming `expected` is a reference type, determine whether to peel it before matching.
|
||||
fn should_peel_ref(&self, peel_kind: PeelKind, mut expected: Ty<'tcx>) -> bool {
|
||||
debug_assert!(expected.is_ref());
|
||||
let pat_ref_layers = match peel_kind {
|
||||
PeelKind::ExplicitDerefPat => 0,
|
||||
PeelKind::Implicit { pat_ref_layers, .. } => pat_ref_layers,
|
||||
};
|
||||
|
||||
// Most patterns don't have reference types, so we'll want to peel all references from the
|
||||
// scrutinee before matching. To optimize for the common case, return early.
|
||||
if pat_ref_layers == 0 {
|
||||
return true;
|
||||
}
|
||||
debug_assert!(
|
||||
self.tcx.features().deref_patterns(),
|
||||
"Peeling for patterns with reference types is gated by `deref_patterns`."
|
||||
);
|
||||
|
||||
// If the pattern has as many or more layers of reference as the expected type, we can match
|
||||
// without peeling more, unless we find a smart pointer or `&mut` that we also need to peel.
|
||||
// We don't treat `&` and `&mut` as interchangeable, but by peeling `&mut`s before matching,
|
||||
// we can still, e.g., match on a `&mut str` with a string literal pattern. This is because
|
||||
// string literal patterns may be used where `str` is expected.
|
||||
let mut expected_ref_layers = 0;
|
||||
while let ty::Ref(_, inner_ty, mutbl) = *expected.kind() {
|
||||
if mutbl.is_mut() {
|
||||
// Mutable references can't be in the final value of constants, thus they can't be
|
||||
// at the head of their types, thus we should always peel `&mut`.
|
||||
return true;
|
||||
}
|
||||
expected_ref_layers += 1;
|
||||
expected = inner_ty;
|
||||
}
|
||||
pat_ref_layers < expected_ref_layers || self.should_peel_smart_pointer(peel_kind, expected)
|
||||
}
|
||||
|
||||
/// Determine whether `expected` is a smart pointer type that should be peeled before matching.
|
||||
fn should_peel_smart_pointer(&self, peel_kind: PeelKind, expected: Ty<'tcx>) -> bool {
|
||||
// Explicit `deref!(_)` patterns match against smart pointers; don't peel in that case.
|
||||
if let PeelKind::Implicit { until_adt, .. } = peel_kind
|
||||
// For simplicity, only apply overloaded derefs if `expected` is a known ADT.
|
||||
// FIXME(deref_patterns): we'll get better diagnostics for users trying to
|
||||
// implicitly deref generics if we allow them here, but primitives, tuples, and
|
||||
// inference vars definitely should be stopped. Figure out what makes most sense.
|
||||
&& let ty::Adt(scrutinee_adt, _) = *expected.kind()
|
||||
// Don't peel if the pattern type already matches the scrutinee. E.g., stop here if
|
||||
// matching on a `Cow<'a, T>` scrutinee with a `Cow::Owned(_)` pattern.
|
||||
&& until_adt != Some(scrutinee_adt.did())
|
||||
// At this point, the pattern isn't able to match `expected` without peeling. Check
|
||||
// that it implements `Deref` before assuming it's a smart pointer, to get a normal
|
||||
// type error instead of a missing impl error if not. This only checks for `Deref`,
|
||||
// not `DerefPure`: we require that too, but we want a trait error if it's missing.
|
||||
&& let Some(deref_trait) = self.tcx.lang_items().deref_trait()
|
||||
&& self.type_implements_trait(deref_trait, [expected], self.param_env).may_apply()
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> {
|
||||
let ty = match <.kind {
|
||||
rustc_hir::PatExprKind::Lit { lit, negated } => {
|
||||
|
|
@ -866,6 +935,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// be peeled to `str` while ty here is still `&str`, if we don't
|
||||
// err early here, a rather confusing unification error will be
|
||||
// emitted instead).
|
||||
let ty = self.try_structurally_resolve_type(expr.span, ty);
|
||||
let fail =
|
||||
!(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error());
|
||||
Some((fail, ty, expr.span))
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use std::cell::RefCell;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::{self as hir, HirId, HirIdMap, LangItem};
|
||||
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
||||
use rustc_infer::infer::{InferCtxt, InferOk, OpaqueTypeStorageEntries, TyCtxtInferExt};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode};
|
||||
use rustc_span::Span;
|
||||
|
|
@ -37,6 +37,11 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
|
|||
|
||||
pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx, FulfillmentError<'tcx>>>>,
|
||||
|
||||
// Used to detect opaque types uses added after we've already checked them.
|
||||
//
|
||||
// See [FnCtxt::detect_opaque_types_added_during_writeback] for more details.
|
||||
pub(super) checked_opaque_types_storage_entries: Cell<Option<OpaqueTypeStorageEntries>>,
|
||||
|
||||
/// Some additional `Sized` obligations badly affect type inference.
|
||||
/// These obligations are added in a later stage of typeck.
|
||||
/// Removing these may also cause additional complications, see #101066.
|
||||
|
|
@ -85,12 +90,14 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
|
|||
let infcx =
|
||||
tcx.infer_ctxt().ignoring_regions().build(TypingMode::typeck_for_body(tcx, def_id));
|
||||
let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
|
||||
let fulfillment_cx = RefCell::new(<dyn TraitEngine<'_, _>>::new(&infcx));
|
||||
|
||||
TypeckRootCtxt {
|
||||
typeck_results,
|
||||
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_, _>>::new(&infcx)),
|
||||
infcx,
|
||||
typeck_results,
|
||||
locals: RefCell::new(Default::default()),
|
||||
fulfillment_cx,
|
||||
checked_opaque_types_storage_entries: Cell::new(None),
|
||||
deferred_sized_obligations: RefCell::new(Vec::new()),
|
||||
deferred_call_resolutions: RefCell::new(Default::default()),
|
||||
deferred_cast_checks: RefCell::new(Vec::new()),
|
||||
|
|
|
|||
|
|
@ -535,13 +535,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||
let tcx = self.tcx();
|
||||
// We clone the opaques instead of stealing them here as they are still used for
|
||||
// normalization in the next generation trait solver.
|
||||
//
|
||||
// FIXME(-Znext-solver): Opaque types defined after this would simply get dropped
|
||||
// at the end of typeck. While this seems unlikely to happen in practice this
|
||||
// should still get fixed. Either by preventing writeback from defining new opaque
|
||||
// types or by using this function at the end of writeback and running it as a
|
||||
// fixpoint.
|
||||
let opaque_types = self.fcx.infcx.clone_opaque_types();
|
||||
let num_entries = self.fcx.inner.borrow_mut().opaque_types().num_entries();
|
||||
let prev = self.fcx.checked_opaque_types_storage_entries.replace(Some(num_entries));
|
||||
debug_assert_eq!(prev, None);
|
||||
for (opaque_type_key, hidden_type) in opaque_types {
|
||||
let hidden_type = self.resolve(hidden_type, &hidden_type.span);
|
||||
let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span);
|
||||
|
|
@ -555,15 +552,16 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
if let Err(guar) = check_opaque_type_parameter_valid(
|
||||
if let Err(err) = check_opaque_type_parameter_valid(
|
||||
&self.fcx,
|
||||
opaque_type_key,
|
||||
hidden_type.span,
|
||||
DefiningScopeKind::HirTypeck,
|
||||
) {
|
||||
self.typeck_results
|
||||
.concrete_opaque_types
|
||||
.insert(opaque_type_key.def_id, ty::OpaqueHiddenType::new_error(tcx, guar));
|
||||
self.typeck_results.concrete_opaque_types.insert(
|
||||
opaque_type_key.def_id,
|
||||
ty::OpaqueHiddenType::new_error(tcx, err.report(self.fcx)),
|
||||
);
|
||||
}
|
||||
|
||||
let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ use std::fs::{self, File};
|
|||
use std::io::Write;
|
||||
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::graph::implementation::{Direction, INCOMING, NodeIndex, OUTGOING};
|
||||
use rustc_data_structures::graph::linked_graph::{Direction, INCOMING, NodeIndex, OUTGOING};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_middle::dep_graph::{
|
||||
|
|
|
|||
|
|
@ -44,10 +44,6 @@ pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) {
|
|||
sess.time("assert_dep_graph", || assert_dep_graph(tcx));
|
||||
sess.time("check_dirty_clean", || dirty_clean::check_dirty_clean_annotations(tcx));
|
||||
|
||||
if sess.opts.unstable_opts.incremental_info {
|
||||
tcx.dep_graph.print_incremental_info()
|
||||
}
|
||||
|
||||
join(
|
||||
move || {
|
||||
sess.time("incr_comp_persist_dep_graph", || {
|
||||
|
|
@ -172,12 +168,5 @@ pub(crate) fn build_dep_graph(
|
|||
// First encode the commandline arguments hash
|
||||
sess.opts.dep_tracking_hash(false).encode(&mut encoder);
|
||||
|
||||
Some(DepGraph::new(
|
||||
sess,
|
||||
prev_graph,
|
||||
prev_work_products,
|
||||
encoder,
|
||||
sess.opts.unstable_opts.query_dep_graph,
|
||||
sess.opts.unstable_opts.incremental_info,
|
||||
))
|
||||
Some(DepGraph::new(sess, prev_graph, prev_work_products, encoder))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
|
||||
let certainty = if errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
|
||||
|
||||
let opaque_types = self.take_opaque_types_for_query_response();
|
||||
let opaque_types = self
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.opaque_type_storage
|
||||
.take_opaque_types()
|
||||
.map(|(k, v)| (k, v.ty))
|
||||
.collect();
|
||||
|
||||
Ok(QueryResponse {
|
||||
var_values: inference_vars,
|
||||
|
|
@ -143,24 +149,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Used by the new solver as that one takes the opaque types at the end of a probe
|
||||
/// to deal with multiple candidates without having to recompute them.
|
||||
pub fn clone_opaque_types_for_query_response(
|
||||
&self,
|
||||
) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
|
||||
self.inner
|
||||
.borrow()
|
||||
.opaque_type_storage
|
||||
.opaque_types
|
||||
.iter()
|
||||
.map(|(k, v)| (*k, v.ty))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
|
||||
self.take_opaque_types().into_iter().map(|(k, v)| (k, v.ty)).collect()
|
||||
}
|
||||
|
||||
/// Given the (canonicalized) result to a canonical query,
|
||||
/// instantiates the result so it can be used, plugging in the
|
||||
/// values from the canonical query. (Note that the result may
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||
|
||||
use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin};
|
||||
use super::{
|
||||
BoundRegionConversionTime, InferCtxt, OpaqueTypeStorageEntries, RegionVariableOrigin,
|
||||
SubregionOrigin,
|
||||
};
|
||||
|
||||
impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
||||
type Interner = TyCtxt<'tcx>;
|
||||
|
|
@ -121,19 +124,19 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
|||
self.enter_forall(value, f)
|
||||
}
|
||||
|
||||
fn equate_ty_vids_raw(&self, a: rustc_type_ir::TyVid, b: rustc_type_ir::TyVid) {
|
||||
fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
|
||||
self.inner.borrow_mut().type_variables().equate(a, b);
|
||||
}
|
||||
|
||||
fn equate_int_vids_raw(&self, a: rustc_type_ir::IntVid, b: rustc_type_ir::IntVid) {
|
||||
fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid) {
|
||||
self.inner.borrow_mut().int_unification_table().union(a, b);
|
||||
}
|
||||
|
||||
fn equate_float_vids_raw(&self, a: rustc_type_ir::FloatVid, b: rustc_type_ir::FloatVid) {
|
||||
fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid) {
|
||||
self.inner.borrow_mut().float_unification_table().union(a, b);
|
||||
}
|
||||
|
||||
fn equate_const_vids_raw(&self, a: rustc_type_ir::ConstVid, b: rustc_type_ir::ConstVid) {
|
||||
fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid) {
|
||||
self.inner.borrow_mut().const_unification_table().union(a, b);
|
||||
}
|
||||
|
||||
|
|
@ -141,8 +144,8 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
|||
&self,
|
||||
relation: &mut R,
|
||||
target_is_expected: bool,
|
||||
target_vid: rustc_type_ir::TyVid,
|
||||
instantiation_variance: rustc_type_ir::Variance,
|
||||
target_vid: ty::TyVid,
|
||||
instantiation_variance: ty::Variance,
|
||||
source_ty: Ty<'tcx>,
|
||||
) -> RelateResult<'tcx, ()> {
|
||||
self.instantiate_ty_var(
|
||||
|
|
@ -154,19 +157,11 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
fn instantiate_int_var_raw(
|
||||
&self,
|
||||
vid: rustc_type_ir::IntVid,
|
||||
value: rustc_type_ir::IntVarValue,
|
||||
) {
|
||||
fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue) {
|
||||
self.inner.borrow_mut().int_unification_table().union_value(vid, value);
|
||||
}
|
||||
|
||||
fn instantiate_float_var_raw(
|
||||
&self,
|
||||
vid: rustc_type_ir::FloatVid,
|
||||
value: rustc_type_ir::FloatVarValue,
|
||||
) {
|
||||
fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue) {
|
||||
self.inner.borrow_mut().float_unification_table().union_value(vid, value);
|
||||
}
|
||||
|
||||
|
|
@ -174,7 +169,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
|||
&self,
|
||||
relation: &mut R,
|
||||
target_is_expected: bool,
|
||||
target_vid: rustc_type_ir::ConstVid,
|
||||
target_vid: ty::ConstVid,
|
||||
source_ct: ty::Const<'tcx>,
|
||||
) -> RelateResult<'tcx, ()> {
|
||||
self.instantiate_const_var(relation, target_is_expected, target_vid, source_ct)
|
||||
|
|
@ -221,4 +216,58 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
|||
fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
|
||||
self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span));
|
||||
}
|
||||
|
||||
type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries;
|
||||
fn opaque_types_storage_num_entries(&self) -> OpaqueTypeStorageEntries {
|
||||
self.inner.borrow_mut().opaque_types().num_entries()
|
||||
}
|
||||
fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
|
||||
self.inner.borrow_mut().opaque_types().iter_lookup_table().map(|(k, h)| (k, h.ty)).collect()
|
||||
}
|
||||
fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.opaque_types()
|
||||
.iter_duplicate_entries()
|
||||
.map(|(k, h)| (k, h.ty))
|
||||
.collect()
|
||||
}
|
||||
fn clone_opaque_types_added_since(
|
||||
&self,
|
||||
prev_entries: OpaqueTypeStorageEntries,
|
||||
) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.opaque_types()
|
||||
.opaque_types_added_since(prev_entries)
|
||||
.map(|(k, h)| (k, h.ty))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn register_hidden_type_in_storage(
|
||||
&self,
|
||||
opaque_type_key: ty::OpaqueTypeKey<'tcx>,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
self.register_hidden_type_in_storage(
|
||||
opaque_type_key,
|
||||
ty::OpaqueHiddenType { span, ty: hidden_ty },
|
||||
)
|
||||
}
|
||||
fn add_duplicate_opaque_type(
|
||||
&self,
|
||||
opaque_type_key: ty::OpaqueTypeKey<'tcx>,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.opaque_types()
|
||||
.add_duplicate(opaque_type_key, ty::OpaqueHiddenType { span, ty: hidden_ty })
|
||||
}
|
||||
|
||||
fn reset_opaque_types(&self) {
|
||||
let _ = self.take_opaque_types();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
use std::fmt;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::graph::implementation::{
|
||||
Direction, Graph, INCOMING, NodeIndex, OUTGOING,
|
||||
use rustc_data_structures::graph::linked_graph::{
|
||||
Direction, INCOMING, LinkedGraph, NodeIndex, OUTGOING,
|
||||
};
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
|
|
@ -118,7 +118,7 @@ struct RegionAndOrigin<'tcx> {
|
|||
origin: SubregionOrigin<'tcx>,
|
||||
}
|
||||
|
||||
type RegionGraph<'tcx> = Graph<(), Constraint<'tcx>>;
|
||||
type RegionGraph<'tcx> = LinkedGraph<(), Constraint<'tcx>>;
|
||||
|
||||
struct LexicalResolver<'cx, 'tcx> {
|
||||
region_rels: &'cx RegionRelations<'cx, 'tcx>,
|
||||
|
|
@ -668,7 +668,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
fn construct_graph(&self) -> RegionGraph<'tcx> {
|
||||
let num_vars = self.num_vars();
|
||||
|
||||
let mut graph = Graph::new();
|
||||
let mut graph = LinkedGraph::new();
|
||||
|
||||
for _ in 0..num_vars {
|
||||
graph.add_node(());
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use free_regions::RegionRelations;
|
|||
pub use freshen::TypeFreshener;
|
||||
use lexical_region_resolve::LexicalRegionResolutions;
|
||||
pub use lexical_region_resolve::RegionResolutionError;
|
||||
use opaque_types::OpaqueTypeStorage;
|
||||
pub use opaque_types::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable};
|
||||
use region_constraints::{
|
||||
GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound,
|
||||
};
|
||||
|
|
@ -31,9 +31,9 @@ use rustc_middle::traits::solve::Goal;
|
|||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{
|
||||
self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs,
|
||||
GenericArgsRef, GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Term, TermKind,
|
||||
Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
|
||||
TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
|
||||
GenericArgsRef, GenericParamDefKind, InferConst, IntVid, OpaqueHiddenType, OpaqueTypeKey,
|
||||
PseudoCanonicalInput, Term, TermKind, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder,
|
||||
TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
|
||||
};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use snapshot::undo_log::InferCtxtUndoLogs;
|
||||
|
|
@ -198,7 +198,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> {
|
||||
pub fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> {
|
||||
self.opaque_type_storage.with_log(&mut self.undo_log)
|
||||
}
|
||||
|
||||
|
|
@ -224,15 +224,6 @@ impl<'tcx> InferCtxtInner<'tcx> {
|
|||
.expect("region constraints already solved")
|
||||
.with_log(&mut self.undo_log)
|
||||
}
|
||||
|
||||
// Iterates through the opaque type definitions without taking them; this holds the
|
||||
// `InferCtxtInner` lock, so make sure to not do anything with `InferCtxt` side-effects
|
||||
// while looping through this.
|
||||
pub fn iter_opaque_types(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>)> {
|
||||
self.opaque_type_storage.opaque_types.iter().map(|(&k, &v)| (k, v))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InferCtxt<'tcx> {
|
||||
|
|
@ -954,13 +945,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
pub fn take_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
|
||||
std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
|
||||
pub fn take_opaque_types(&self) -> Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
|
||||
self.inner.borrow_mut().opaque_type_storage.take_opaque_types().collect()
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
pub fn clone_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
|
||||
self.inner.borrow().opaque_type_storage.opaque_types.clone()
|
||||
pub fn clone_opaque_types(&self) -> Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
|
||||
self.inner.borrow_mut().opaque_type_storage.iter_opaque_types().collect()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
|
|
@ -19,8 +18,7 @@ use crate::traits::{self, Obligation, PredicateObligations};
|
|||
|
||||
mod table;
|
||||
|
||||
pub(crate) type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>;
|
||||
pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable};
|
||||
pub use table::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable};
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
/// This is a backwards compatibility hack to prevent breaking changes from
|
||||
|
|
|
|||
|
|
@ -1,18 +1,27 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::undo_log::UndoLogs;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
|
||||
use tracing::instrument;
|
||||
|
||||
use super::OpaqueTypeMap;
|
||||
use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub(crate) struct OpaqueTypeStorage<'tcx> {
|
||||
/// Opaque types found in explicit return types and their
|
||||
/// associated fresh inference variable. Writeback resolves these
|
||||
/// variables to get the concrete type, which can be used to
|
||||
/// 'de-opaque' OpaqueHiddenType, after typeck is done with all functions.
|
||||
pub opaque_types: OpaqueTypeMap<'tcx>,
|
||||
pub struct OpaqueTypeStorage<'tcx> {
|
||||
opaque_types: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
duplicate_entries: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>,
|
||||
}
|
||||
|
||||
/// The number of entries in the opaque type storage at a given point.
|
||||
///
|
||||
/// Used to check that we haven't added any new opaque types after checking
|
||||
/// the opaque types currently in the storage.
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct OpaqueTypeStorageEntries {
|
||||
opaque_types: usize,
|
||||
duplicate_entries: usize,
|
||||
}
|
||||
|
||||
impl<'tcx> OpaqueTypeStorage<'tcx> {
|
||||
|
|
@ -33,6 +42,70 @@ impl<'tcx> OpaqueTypeStorage<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn pop_duplicate_entry(&mut self) {
|
||||
let entry = self.duplicate_entries.pop();
|
||||
assert!(entry.is_some());
|
||||
}
|
||||
|
||||
pub(crate) fn is_empty(&self) -> bool {
|
||||
let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
|
||||
opaque_types.is_empty() && duplicate_entries.is_empty()
|
||||
}
|
||||
|
||||
pub(crate) fn take_opaque_types(
|
||||
&mut self,
|
||||
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
|
||||
let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
|
||||
std::mem::take(opaque_types).into_iter().chain(std::mem::take(duplicate_entries))
|
||||
}
|
||||
|
||||
pub fn num_entries(&self) -> OpaqueTypeStorageEntries {
|
||||
OpaqueTypeStorageEntries {
|
||||
opaque_types: self.opaque_types.len(),
|
||||
duplicate_entries: self.duplicate_entries.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn opaque_types_added_since(
|
||||
&self,
|
||||
prev_entries: OpaqueTypeStorageEntries,
|
||||
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
|
||||
self.opaque_types
|
||||
.iter()
|
||||
.skip(prev_entries.opaque_types)
|
||||
.map(|(k, v)| (*k, *v))
|
||||
.chain(self.duplicate_entries.iter().skip(prev_entries.duplicate_entries).copied())
|
||||
}
|
||||
|
||||
/// Only returns the opaque types from the lookup table. These are used
|
||||
/// when normalizing opaque types and have a unique key.
|
||||
///
|
||||
/// Outside of canonicalization one should generally use `iter_opaque_types`
|
||||
/// to also consider duplicate entries.
|
||||
pub fn iter_lookup_table(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
|
||||
self.opaque_types.iter().map(|(k, v)| (*k, *v))
|
||||
}
|
||||
|
||||
/// Only returns the opaque types which are stored in `duplicate_entries`.
|
||||
///
|
||||
/// These have to considered when checking all opaque type uses but are e.g.
|
||||
/// irrelevant for canonical inputs as nested queries never meaningfully
|
||||
/// accesses them.
|
||||
pub fn iter_duplicate_entries(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
|
||||
self.duplicate_entries.iter().copied()
|
||||
}
|
||||
|
||||
pub fn iter_opaque_types(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
|
||||
let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
|
||||
opaque_types.iter().map(|(k, v)| (*k, *v)).chain(duplicate_entries.iter().copied())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn with_log<'a>(
|
||||
&'a mut self,
|
||||
|
|
@ -44,21 +117,27 @@ impl<'tcx> OpaqueTypeStorage<'tcx> {
|
|||
|
||||
impl<'tcx> Drop for OpaqueTypeStorage<'tcx> {
|
||||
fn drop(&mut self) {
|
||||
if !self.opaque_types.is_empty() {
|
||||
if !self.is_empty() {
|
||||
ty::tls::with(|tcx| tcx.dcx().delayed_bug(format!("{:?}", self.opaque_types)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct OpaqueTypeTable<'a, 'tcx> {
|
||||
pub struct OpaqueTypeTable<'a, 'tcx> {
|
||||
storage: &'a mut OpaqueTypeStorage<'tcx>,
|
||||
|
||||
undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
|
||||
}
|
||||
impl<'tcx> Deref for OpaqueTypeTable<'_, 'tcx> {
|
||||
type Target = OpaqueTypeStorage<'tcx>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.storage
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(crate) fn register(
|
||||
pub fn register(
|
||||
&mut self,
|
||||
key: OpaqueTypeKey<'tcx>,
|
||||
hidden_type: OpaqueHiddenType<'tcx>,
|
||||
|
|
@ -72,4 +151,9 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
|
|||
self.undo_log.push(UndoLog::OpaqueTypes(key, None));
|
||||
None
|
||||
}
|
||||
|
||||
pub fn add_duplicate(&mut self, key: OpaqueTypeKey<'tcx>, hidden_type: OpaqueHiddenType<'tcx>) {
|
||||
self.storage.duplicate_entries.push((key, hidden_type));
|
||||
self.undo_log.push(UndoLog::DuplicateOpaqueType);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,10 +24,6 @@ impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for FreeRegionsVisitor<'tcx, OP>
|
|||
where
|
||||
OP: FnMut(ty::Region<'tcx>),
|
||||
{
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
|
||||
t.super_visit_with(self);
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) {
|
||||
match r.kind() {
|
||||
// ignore bound regions, keep visiting
|
||||
|
|
|
|||
|
|
@ -63,11 +63,11 @@ use rustc_data_structures::undo_log::UndoLogs;
|
|||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::ty::outlives::{Component, push_outlives_components};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesPredicate, Region, Ty, TyCtxt,
|
||||
TypeFoldable as _, TypeVisitableExt,
|
||||
};
|
||||
use rustc_type_ir::outlives::{Component, push_outlives_components};
|
||||
use smallvec::smallvec;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
|
||||
use rustc_middle::ty::outlives::{Component, compute_alias_components_recursive};
|
||||
use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt};
|
||||
use rustc_type_ir::outlives::{Component, compute_alias_components_recursive};
|
||||
use smallvec::smallvec;
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_middle::ty;
|
||||
|
||||
use super::InferCtxt;
|
||||
use crate::infer::Term;
|
||||
use crate::traits::{Obligation, PredicateObligations};
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
|
|
@ -11,24 +12,32 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
/// of the given projection. This allows us to proceed with projections
|
||||
/// while they cannot be resolved yet due to missing information or
|
||||
/// simply due to the lack of access to the trait resolution machinery.
|
||||
pub fn projection_ty_to_infer(
|
||||
pub fn projection_term_to_infer(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
projection_ty: ty::AliasTy<'tcx>,
|
||||
alias_term: ty::AliasTerm<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
recursion_depth: usize,
|
||||
obligations: &mut PredicateObligations<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
) -> Term<'tcx> {
|
||||
debug_assert!(!self.next_trait_solver());
|
||||
let ty_var = self.next_ty_var(self.tcx.def_span(projection_ty.def_id));
|
||||
|
||||
let span = self.tcx.def_span(alias_term.def_id);
|
||||
let infer_var = if alias_term.kind(self.tcx).is_type() {
|
||||
self.next_ty_var(span).into()
|
||||
} else {
|
||||
self.next_const_var(span).into()
|
||||
};
|
||||
|
||||
let projection =
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
|
||||
projection_term: projection_ty.into(),
|
||||
term: ty_var.into(),
|
||||
projection_term: alias_term,
|
||||
term: infer_var,
|
||||
}));
|
||||
let obligation =
|
||||
Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
|
||||
obligations.push(obligation);
|
||||
ty_var
|
||||
|
||||
infer_var
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@
|
|||
//! (except for some relations used for diagnostics and heuristics in the compiler).
|
||||
//! As well as the implementation of `Relate` for interned things (`Ty`/`Const`/etc).
|
||||
|
||||
pub use rustc_middle::ty::relate::RelateResult;
|
||||
pub use rustc_type_ir::relate::combine::PredicateEmittingRelation;
|
||||
pub use rustc_type_ir::relate::*;
|
||||
pub use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
|
||||
pub use rustc_middle::ty::relate::{RelateResult, *};
|
||||
|
||||
mod generalize;
|
||||
mod higher_ranked;
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys}
|
|||
use rustc_middle::ty::relate::{
|
||||
Relate, RelateResult, TypeRelation, relate_args_invariantly, relate_args_with_variances,
|
||||
};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TyVar};
|
||||
use rustc_middle::ty::{self, DelayedSet, Ty, TyCtxt, TyVar};
|
||||
use rustc_span::Span;
|
||||
use rustc_type_ir::data_structures::DelayedSet;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::infer::BoundRegionConversionTime::HigherRankedType;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{
|
||||
self, Const, FallibleTypeFolder, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder,
|
||||
self, Const, DelayedMap, FallibleTypeFolder, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder,
|
||||
TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
use rustc_type_ir::data_structures::DelayedMap;
|
||||
|
||||
use super::{FixupError, FixupResult, InferCtxt};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ use std::ops::Range;
|
|||
use rustc_data_structures::{snapshot_vec as sv, unify as ut};
|
||||
use rustc_middle::ty::{
|
||||
self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder,
|
||||
TypeSuperFoldable,
|
||||
TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
use rustc_type_ir::TypeVisitableExt;
|
||||
use tracing::instrument;
|
||||
use ut::UnifyKey;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ pub struct Snapshot<'tcx> {
|
|||
/// Records the "undo" data for a single operation that affects some form of inference variable.
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum UndoLog<'tcx> {
|
||||
DuplicateOpaqueType,
|
||||
OpaqueTypes(OpaqueTypeKey<'tcx>, Option<OpaqueHiddenType<'tcx>>),
|
||||
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
|
||||
ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
|
||||
|
|
@ -58,6 +59,7 @@ impl_from! {
|
|||
impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
|
||||
fn reverse(&mut self, undo: UndoLog<'tcx>) {
|
||||
match undo {
|
||||
UndoLog::DuplicateOpaqueType => self.opaque_type_storage.pop_duplicate_entry(),
|
||||
UndoLog::OpaqueTypes(key, idx) => self.opaque_type_storage.remove(key, idx),
|
||||
UndoLog::TypeVariables(undo) => self.type_variable_storage.reverse(undo),
|
||||
UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo),
|
||||
|
|
|
|||
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