Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2025-05-10 05:01:09 +00:00
commit a4f765dcad
1554 changed files with 19575 additions and 10807 deletions

View file

@ -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

View file

@ -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",
]

View file

@ -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)
==========================

View file

@ -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 {

View file

@ -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(),

View file

@ -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 {

View file

@ -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(

View file

@ -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);

View file

@ -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) {

View file

@ -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()`");
}
}

View file

@ -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> {

View file

@ -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)

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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, &note)?);
Some(name @ sym::note) => {
note = Some(get(cx, name, param_span, param.args(), &note)?);
}
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 {

View file

@ -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
}

View file

@ -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, &param, &mut feature)?,
sym::since => insert_value_into_option_or_error(cx, &param, &mut since)?,
match param.path_without_args().word_sym() {
Some(sym::feature) => insert_value_into_option_or_error(cx, &param, &mut feature)?,
Some(sym::since) => insert_value_into_option_or_error(cx, &param, &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, &param, &mut feature)?,
sym::reason => insert_value_into_option_or_error(cx, &param, &mut reason)?,
sym::issue => {
match param.path_without_args().word_sym() {
Some(sym::feature) => insert_value_into_option_or_error(cx, &param, &mut feature)?,
Some(sym::reason) => insert_value_into_option_or_error(cx, &param, &mut reason)?,
Some(sym::issue) => {
insert_value_into_option_or_error(cx, &param, &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, &param, &mut implied_by)?,
Some(sym::implied_by) => {
insert_value_into_option_or_error(cx, &param, &mut implied_by)?
}
_ => {
cx.emit_err(session_diagnostics::UnknownMetaItem {
span: param.span(),

View file

@ -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.

View file

@ -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,
}
}

View file

@ -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);

View file

@ -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);

View file

@ -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, &regioncx);
let (mut flow_analysis, flow_entry_states) =
get_flow_results(tcx, body, &move_data, &borrow_set, &regioncx);
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,

View file

@ -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

View file

@ -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()));
}
}

View file

@ -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()

View file

@ -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,
}
}

View file

@ -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: &region_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.

View file

@ -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

View file

@ -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)));

View file

@ -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));
}
}

View file

@ -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,
}
}

View file

@ -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() {

View file

@ -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,
}
}

View file

@ -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

View file

@ -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 {

View file

@ -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

View file

@ -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));
}
};

View file

@ -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)) => {

View file

@ -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)
});

View file

@ -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}")?;
}
};

View file

@ -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;

View file

@ -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>(

View file

@ -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

View file

@ -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>,

View file

@ -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"),
};

View file

@ -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`.

View file

@ -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 {

View file

@ -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)],

View file

@ -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;

View file

@ -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};

View file

@ -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)]
}
}

View file

@ -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

View file

@ -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 {

View file

@ -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};

View file

@ -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;

View file

@ -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.

View file

@ -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);

View file

@ -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,

View file

@ -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.

View file

@ -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

View file

@ -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 },
}
}
}

View file

@ -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(&lt, syntax));
let unambig_to_ambig = unsafe { std::mem::transmute::<_, TyKind<'_, AmbigArg>>(unambig) };
match unambig_to_ambig {

View file

@ -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))]

View file

@ -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,

View file

@ -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()

View file

@ -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 {

View file

@ -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
}
})

View file

@ -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(),
)
}

View file

@ -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));

View file

@ -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 {

View file

@ -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))?,

View file

@ -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);

View file

@ -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).

View file

@ -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);

View file

@ -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

View file

@ -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() {

View file

@ -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 {

View file

@ -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.

View 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();
}
}

View file

@ -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 &lt.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))

View file

@ -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()),

View file

@ -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(

View file

@ -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::{

View file

@ -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))
}

View file

@ -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

View file

@ -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();
}
}

View file

@ -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(());

View file

@ -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)]

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -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};

View file

@ -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};

View file

@ -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
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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};

View file

@ -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;

View file

@ -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