mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Merge ref 'eda4fc7733ee' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh. Upstream ref: rust-lang/rust@eda4fc7733 Filtered ref: rust-lang/stdarch@3f3adc6031 Upstream diff: https://github.com/rust-lang/rust/compare/139651428df86cf88443295542c12ea617cbb587...eda4fc7733ee89e484d7120cafbd80dcb2fce66e This merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
@@ -94,6 +94,10 @@ jobs:
|
||||
CACHE_DOMAIN: ci-caches.rust-lang.org
|
||||
continue-on-error: ${{ matrix.continue_on_error || false }}
|
||||
strategy:
|
||||
# If the user starts multiple jobs in a try build, let them all finish.
|
||||
# Try builds are sometimes used to test several jobs at once, and it is useful to know which
|
||||
# of them would succeed or not.
|
||||
fail-fast: ${{ needs.calculate_matrix.outputs.run_type != 'try' }}
|
||||
matrix:
|
||||
# Check the `calculate_matrix` job to see how is the matrix defined.
|
||||
include: ${{ fromJSON(needs.calculate_matrix.outputs.jobs) }}
|
||||
|
||||
@@ -83,7 +83,8 @@ Ben Sago <ogham@users.noreply.github.com> <ogham@bsago.me>
|
||||
Ben Striegel <ben.striegel@gmail.com>
|
||||
Benjamin Jackman <ben@jackman.biz>
|
||||
Benoît Cortier <benoit.cortier@fried-world.eu>
|
||||
binarycat <binarycat@envs.net> lolbinarycat <dogedoge61+github@gmail.com> <dogedoge61@gmail.com>
|
||||
binarycat <binarycat@envs.net> lolbinarycat <dogedoge61+github@gmail.com>
|
||||
binarycat <binarycat@envs.net> lolbinarycat <dogedoge61@gmail.com>
|
||||
Bheesham Persaud <bheesham123@hotmail.com> Bheesham Persaud <bheesham.persaud@live.ca>
|
||||
bjorn3 <17426603+bjorn3@users.noreply.github.com> <bjorn3@users.noreply.github.com>
|
||||
bjorn3 <17426603+bjorn3@users.noreply.github.com> <bjorn3_gh@protonmail.com>
|
||||
@@ -579,9 +580,14 @@ Ralph Giles <giles@thaumas.net> Ralph Giles <giles@mozilla.com>
|
||||
Ramkumar Ramachandra <r@artagnon.com> <artagnon@gmail.com>
|
||||
Raphaël Huchet <rap2hpoutre@users.noreply.github.com>
|
||||
rChaser53 <tayoshizawa29@gmail.com>
|
||||
Redddy <rust@redddy.com>
|
||||
Redddy <rust@redddy.com> <midzy0228@gmail.com>
|
||||
Redddy <rust@redddy.com> <78539407+reddevilmidzy@users.noreply.github.com>
|
||||
Rémy Rakic <remy.rakic@gmail.com>
|
||||
Rémy Rakic <remy.rakic@gmail.com> <remy.rakic@arm.com>
|
||||
Rémy Rakic <remy.rakic@gmail.com> <remy.rakic+github@gmail.com>
|
||||
Rémy Rakic <remy.rakic@gmail.com> <remy.rakic+rust@gmail.com>
|
||||
Rémy Rakic <remy.rakic@gmail.com> <lqd@users.noreply.github.com>
|
||||
Renato Riccieri Santos Zannon <renato@rrsz.com.br>
|
||||
Richard Diamond <wichard@vitalitystudios.com> <wichard@hahbee.co>
|
||||
Ricky Hosfelt <ricky@hosfelt.io>
|
||||
|
||||
+69
-147
@@ -52,16 +52,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "annotate-snippets"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccaf7e9dfbb6ab22c82e473cd1a8a7bd313c19a5b7e40970f3d89ef5a5c9e81e"
|
||||
dependencies = [
|
||||
"unicode-width 0.1.14",
|
||||
"yansi-term",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "annotate-snippets"
|
||||
version = "0.11.5"
|
||||
@@ -630,7 +620,7 @@ checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
||||
|
||||
[[package]]
|
||||
name = "clippy"
|
||||
version = "0.1.95"
|
||||
version = "0.1.96"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"askama",
|
||||
@@ -657,7 +647,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clippy_config"
|
||||
version = "0.1.95"
|
||||
version = "0.1.96"
|
||||
dependencies = [
|
||||
"clippy_utils",
|
||||
"itertools",
|
||||
@@ -681,7 +671,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clippy_lints"
|
||||
version = "0.1.95"
|
||||
version = "0.1.96"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"cargo_metadata 0.18.1",
|
||||
@@ -713,7 +703,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clippy_utils"
|
||||
version = "0.1.95"
|
||||
version = "0.1.96"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"itertools",
|
||||
@@ -1117,7 +1107,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "declare_clippy_lint"
|
||||
version = "0.1.95"
|
||||
version = "0.1.96"
|
||||
|
||||
[[package]]
|
||||
name = "derive-where"
|
||||
@@ -1213,16 +1203,6 @@ dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.5.0"
|
||||
@@ -1231,26 +1211,15 @@ checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users 0.5.2",
|
||||
"redox_users",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users 0.4.6",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch2"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
|
||||
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block2",
|
||||
@@ -1665,7 +1634,6 @@ dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
"foldhash 0.1.5",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1675,6 +1643,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||
dependencies = [
|
||||
"foldhash 0.2.0",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1898,9 +1868,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "id-arena"
|
||||
version = "2.2.1"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
|
||||
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
@@ -2652,9 +2622,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
@@ -2667,9 +2637,9 @@ checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-kit"
|
||||
version = "0.3.2"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15"
|
||||
checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"objc2-core-foundation",
|
||||
@@ -3228,17 +3198,6 @@ dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
||||
dependencies = [
|
||||
"getrandom 0.2.16",
|
||||
"libredox",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.5.2"
|
||||
@@ -3514,6 +3473,7 @@ dependencies = [
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
"rustc_hir",
|
||||
"rustc_macros",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
@@ -3546,6 +3506,7 @@ dependencies = [
|
||||
"rustc_lexer",
|
||||
"rustc_macros",
|
||||
"rustc_parse",
|
||||
"rustc_parse_format",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
@@ -3640,7 +3601,6 @@ dependencies = [
|
||||
"rustc_macros",
|
||||
"rustc_metadata",
|
||||
"rustc_middle",
|
||||
"rustc_query_system",
|
||||
"rustc_sanitizers",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
@@ -3808,7 +3768,6 @@ name = "rustc_error_messages"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"fluent-bundle",
|
||||
"fluent-syntax",
|
||||
"icu_list",
|
||||
"icu_locale",
|
||||
"intl-memoizer",
|
||||
@@ -3819,7 +3778,6 @@ dependencies = [
|
||||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
"rustc_span",
|
||||
"tracing",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
@@ -4163,6 +4121,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4243,7 +4202,6 @@ dependencies = [
|
||||
"rustc_index",
|
||||
"rustc_lint_defs",
|
||||
"rustc_macros",
|
||||
"rustc_query_system",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
@@ -4495,12 +4453,10 @@ dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_hashes",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_query_system",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
@@ -4508,23 +4464,6 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_query_system"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
"rustc_hir",
|
||||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_resolve"
|
||||
version = "0.0.0"
|
||||
@@ -4703,7 +4642,6 @@ dependencies = [
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_next_trait_solver",
|
||||
"rustc_parse_format",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_transmute",
|
||||
@@ -4769,6 +4707,7 @@ dependencies = [
|
||||
"ena",
|
||||
"indexmap",
|
||||
"rustc-hash 2.1.1",
|
||||
"rustc_abi",
|
||||
"rustc_ast_ir",
|
||||
"rustc_data_structures",
|
||||
"rustc_error_messages",
|
||||
@@ -4892,9 +4831,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustfmt-nightly"
|
||||
version = "1.8.0"
|
||||
version = "1.9.0"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.2",
|
||||
"annotate-snippets 0.11.5",
|
||||
"anyhow",
|
||||
"bytecount",
|
||||
"cargo_metadata 0.18.1",
|
||||
@@ -4907,11 +4846,13 @@ dependencies = [
|
||||
"itertools",
|
||||
"regex",
|
||||
"rustfmt-config_proc_macro",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"term",
|
||||
"thiserror 1.0.69",
|
||||
"toml 0.7.8",
|
||||
"toml 0.9.8",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"unicode-properties",
|
||||
@@ -5374,9 +5315,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.38.0"
|
||||
version = "0.38.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe840c5b1afe259a5657392a4dbb74473a14c8db999c3ec2f4ae812e028a94da"
|
||||
checksum = "1efc19935b4b66baa6f654ac7924c192f55b175c00a7ab72410fc24284dacda8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"objc2-core-foundation",
|
||||
@@ -5431,13 +5372,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.7.0"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
|
||||
checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1"
|
||||
dependencies = [
|
||||
"dirs-next",
|
||||
"rustversion",
|
||||
"winapi",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5772,6 +5711,16 @@ dependencies = [
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-serde"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.20"
|
||||
@@ -5783,12 +5732,15 @@ dependencies = [
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"regex-automata",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
"tracing-serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6174,9 +6126,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-component-ld"
|
||||
version = "0.5.20"
|
||||
version = "0.5.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "846d20ed66ae37b7a237e36dfcd2fdc979eae82a46cdb0586f9bba80782fd789"
|
||||
checksum = "59dcd765f510df84d1677a502c49057761486597a95950b4c92153e5707af091"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -6185,7 +6137,7 @@ dependencies = [
|
||||
"libc",
|
||||
"tempfile",
|
||||
"wasi-preview1-component-adapter-provider",
|
||||
"wasmparser 0.243.0",
|
||||
"wasmparser 0.245.1",
|
||||
"wat",
|
||||
"windows-sys 0.61.2",
|
||||
"winsplit",
|
||||
@@ -6212,24 +6164,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-encoder"
|
||||
version = "0.243.0"
|
||||
version = "0.245.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c55db9c896d70bd9fa535ce83cd4e1f2ec3726b0edd2142079f594fc3be1cb35"
|
||||
checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c"
|
||||
dependencies = [
|
||||
"leb128fmt",
|
||||
"wasmparser 0.243.0",
|
||||
"wasmparser 0.245.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-metadata"
|
||||
version = "0.243.0"
|
||||
version = "0.245.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eae05bf9579f45a62e8d0a4e3f52eaa8da518883ac5afa482ec8256c329ecd56"
|
||||
checksum = "da55e60097e8b37b475a0fa35c3420dd71d9eb7bd66109978ab55faf56a57efb"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indexmap",
|
||||
"wasm-encoder 0.243.0",
|
||||
"wasmparser 0.243.0",
|
||||
"wasm-encoder 0.245.1",
|
||||
"wasmparser 0.245.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6254,12 +6206,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.243.0"
|
||||
version = "0.245.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6d8db401b0528ec316dfbe579e6ab4152d61739cfe076706d2009127970159d"
|
||||
checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"hashbrown 0.15.5",
|
||||
"hashbrown 0.16.1",
|
||||
"indexmap",
|
||||
"semver",
|
||||
"serde",
|
||||
@@ -6267,22 +6219,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wast"
|
||||
version = "243.0.0"
|
||||
version = "245.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df21d01c2d91e46cb7a221d79e58a2d210ea02020d57c092e79255cc2999ca7f"
|
||||
checksum = "28cf1149285569120b8ce39db8b465e8a2b55c34cbb586bd977e43e2bc7300bf"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"leb128fmt",
|
||||
"memchr",
|
||||
"unicode-width 0.2.2",
|
||||
"wasm-encoder 0.243.0",
|
||||
"wasm-encoder 0.245.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wat"
|
||||
version = "1.243.0"
|
||||
version = "1.245.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "226a9a91cd80a50449312fef0c75c23478fcecfcc4092bdebe1dc8e760ef521b"
|
||||
checksum = "cd48d1679b6858988cb96b154dda0ec5bbb09275b71db46057be37332d5477be"
|
||||
dependencies = [
|
||||
"wast",
|
||||
]
|
||||
@@ -6297,22 +6249,6 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
@@ -6322,12 +6258,6 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.61.3"
|
||||
@@ -6729,9 +6659,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wit-component"
|
||||
version = "0.243.0"
|
||||
version = "0.245.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36f9fc53513e461ce51dcf17a3e331752cb829f1d187069e54af5608fc998fe4"
|
||||
checksum = "4894f10d2d5cbc17c77e91f86a1e48e191a788da4425293b55c98b44ba3fcac9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
@@ -6740,19 +6670,20 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"wasm-encoder 0.243.0",
|
||||
"wasm-encoder 0.245.1",
|
||||
"wasm-metadata",
|
||||
"wasmparser 0.243.0",
|
||||
"wasmparser 0.245.1",
|
||||
"wit-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-parser"
|
||||
version = "0.243.0"
|
||||
version = "0.245.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df983a8608e513d8997f435bb74207bf0933d0e49ca97aa9d8a6157164b9b7fc"
|
||||
checksum = "330698718e82983499419494dd1e3d7811a457a9bf9f69734e8c5f07a2547929"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hashbrown 0.16.1",
|
||||
"id-arena",
|
||||
"indexmap",
|
||||
"log",
|
||||
@@ -6761,7 +6692,7 @@ dependencies = [
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"unicode-xid",
|
||||
"wasmparser 0.243.0",
|
||||
"wasmparser 0.245.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6793,15 +6724,6 @@ dependencies = [
|
||||
"lzma-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi-term"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.8.1"
|
||||
|
||||
@@ -52,6 +52,8 @@ See https://www.rust-lang.org/community for a list of chat platforms and forums.
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
|
||||
For a detailed explanation of the compiler's architecture and how to begin contributing, see the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/).
|
||||
|
||||
## License
|
||||
|
||||
Rust is primarily distributed under the terms of both the MIT license and the
|
||||
|
||||
+115
@@ -1,3 +1,118 @@
|
||||
Version 1.94.0 (2026-03-05)
|
||||
==========================
|
||||
|
||||
<a id="1.94.0-Language"></a>
|
||||
|
||||
Language
|
||||
--------
|
||||
- [Impls and impl items inherit `dead_code` lint level of the corresponding traits and trait items](https://github.com/rust-lang/rust/pull/144113)
|
||||
- [Stabilize additional 29 RISC-V target features including large portions of the RVA22U64 / RVA23U64 profiles](https://github.com/rust-lang/rust/pull/145948)
|
||||
- [Add warn-by-default `unused_visibilities` lint for visibility on `const _` declarations](https://github.com/rust-lang/rust/pull/147136)
|
||||
- [Update to Unicode 17](https://github.com/rust-lang/rust/pull/148321)
|
||||
- [Avoid incorrect lifetime errors for closures](https://github.com/rust-lang/rust/pull/148329)
|
||||
|
||||
<a id="1.94.0-Platform-Support"></a>
|
||||
|
||||
Platform Support
|
||||
----------------
|
||||
|
||||
- [Add `riscv64im-unknown-none-elf` as a tier 3 target](https://github.com/rust-lang/rust/pull/148790)
|
||||
|
||||
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.94.0-Libraries"></a>
|
||||
|
||||
Libraries
|
||||
---------
|
||||
|
||||
- [Relax `T: Ord` bound for some `BinaryHeap<T>` methods.](https://github.com/rust-lang/rust/pull/149408)
|
||||
|
||||
<a id="1.94.0-Stabilized-APIs"></a>
|
||||
|
||||
Stabilized APIs
|
||||
---------------
|
||||
|
||||
- [`<[T]>::array_windows`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.array_windows)
|
||||
- [`<[T]>::element_offset`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.element_offset)
|
||||
- [`LazyCell::get`](https://doc.rust-lang.org/stable/std/cell/struct.LazyCell.html#method.get)
|
||||
- [`LazyCell::get_mut`](https://doc.rust-lang.org/stable/std/cell/struct.LazyCell.html#method.get_mut)
|
||||
- [`LazyCell::force_mut`](https://doc.rust-lang.org/stable/std/cell/struct.LazyCell.html#method.force_mut)
|
||||
- [`LazyLock::get`](https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html#method.get)
|
||||
- [`LazyLock::get_mut`](https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html#method.get_mut)
|
||||
- [`LazyLock::force_mut`](https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html#method.force_mut)
|
||||
- [`impl TryFrom<char> for usize`](https://doc.rust-lang.org/stable/std/convert/trait.TryFrom.html#impl-TryFrom%3Cchar%3E-for-usize)
|
||||
- [`std::iter::Peekable::next_if_map`](https://doc.rust-lang.org/stable/std/iter/struct.Peekable.html#method.next_if_map)
|
||||
- [`std::iter::Peekable::next_if_map_mut`](https://doc.rust-lang.org/stable/std/iter/struct.Peekable.html#method.next_if_map_mut)
|
||||
- [x86 `avx512fp16` intrinsics](https://github.com/rust-lang/rust/issues/127213)
|
||||
(excluding those that depend directly on the unstable `f16` type)
|
||||
- [AArch64 NEON fp16 intrinsics](https://github.com/rust-lang/rust/issues/136306)
|
||||
(excluding those that depend directly on the unstable `f16` type)
|
||||
- [`f32::consts::EULER_GAMMA`](https://doc.rust-lang.org/stable/std/f32/consts/constant.EULER_GAMMA.html)
|
||||
- [`f64::consts::EULER_GAMMA`](https://doc.rust-lang.org/stable/std/f64/consts/constant.EULER_GAMMA.html)
|
||||
- [`f32::consts::GOLDEN_RATIO`](https://doc.rust-lang.org/stable/std/f32/consts/constant.GOLDEN_RATIO.html)
|
||||
- [`f64::consts::GOLDEN_RATIO`](https://doc.rust-lang.org/stable/std/f64/consts/constant.GOLDEN_RATIO.html)
|
||||
|
||||
|
||||
These previously stable APIs are now stable in const contexts:
|
||||
|
||||
- [`f32::mul_add`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.mul_add)
|
||||
- [`f64::mul_add`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.mul_add)
|
||||
|
||||
|
||||
<a id="1.94.0-Cargo"></a>
|
||||
|
||||
Cargo
|
||||
-----
|
||||
|
||||
- Stabilize the config include key. The top-level include config key allows loading additional config files, enabling better organization, sharing, and management of Cargo configurations across projects and environments. [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#including-extra-configuration-files) [#16284](https://github.com/rust-lang/cargo/pull/16284)
|
||||
- Stabilize the pubtime field in registry index. This records when a crate version was published and enables time-based dependency resolution in the future. Note that crates.io will gradually backfill existing packages when a new version is published. Not all crates have pubtime yet. [#16369](https://github.com/rust-lang/cargo/pull/16369) [#16372](https://github.com/rust-lang/cargo/pull/16372)
|
||||
- Cargo now parses [TOML v1.1](https://toml.io/en/v1.1.0) for manifests and configuration files. Note that using these features in Cargo.toml will raise your development MSRV, but the published manifest remains compatible with older parsers. [#16415](https://github.com/rust-lang/cargo/pull/16415)
|
||||
- [Make `CARGO_BIN_EXE_<crate>` available at runtime ](https://github.com/rust-lang/cargo/pull/16421/)
|
||||
|
||||
<a id="1.94.0-Compatibility-Notes"></a>
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
- [Forbid freely casting lifetime bounds of `dyn`-types](https://github.com/rust-lang/rust/pull/136776)
|
||||
- [Make closure capturing have consistent and correct behaviour around patterns](https://github.com/rust-lang/rust/pull/138961)
|
||||
Some finer details of how precise closure captures get affected by pattern matching have been changed. In some cases, this can cause a non-move closure that was previously capturing an entire variable by move, to now capture only part of that variable by move, and other parts by borrow. This can cause the borrow checker to complain where it previously didn't, or cause `Drop` to run at a different point in time.
|
||||
- [Standard library macros are now imported via prelude, not via injected `#[macro_use]`](https://github.com/rust-lang/rust/pull/139493)
|
||||
This will raise an error if macros of the same name are glob imported.
|
||||
For example if a crate defines their own `matches` macro and then glob imports that,
|
||||
it's now ambiguous whether the custom or standard library `matches` is meant and
|
||||
an explicit import of the name is required to resolve the ambiguity.
|
||||
One exception is `core::panic` and `std::panic`, if their import is ambiguous
|
||||
a new warning ([`ambiguous_panic_imports`](https://github.com/rust-lang/rust/issues/147319)) is raised.
|
||||
This may raise a new warning ([`ambiguous_panic_imports`](https://github.com/rust-lang/rust/issues/147319)) on `#![no_std]` code glob importing the std crate.
|
||||
Both `core::panic!` and `std::panic!` are then in scope and which is used is ambiguous.
|
||||
- [Don't strip shebang in expression-context `include!(…)`s](https://github.com/rust-lang/rust/pull/146377)
|
||||
This can cause previously working includes to no longer compile if they included files which started with a shebang.
|
||||
- [Ambiguous glob reexports are now also visible cross-crate](https://github.com/rust-lang/rust/pull/147984)
|
||||
This unifies behavior between local and cross-crate errors on these exports, which may introduce new ambiguity errors.
|
||||
- [Don't normalize where-clauses before checking well-formedness](https://github.com/rust-lang/rust/pull/148477)
|
||||
- [Introduce a future compatibility warning on codegen attributes on body-free trait methods](https://github.com/rust-lang/rust/pull/148756)
|
||||
These attributes currently have no effect in this position.
|
||||
- [On Windows `std::time::SystemTime::checked_sub_duration` will return `None` for times before the Windows epoch (1/1/1601)](https://github.com/rust-lang/rust/pull/148825)
|
||||
- [Lifetime identifiers such as `'a` are now NFC normalized](https://github.com/rust-lang/rust/pull/149192).
|
||||
- [Overhaul filename handling for cross-compiler consistency](https://github.com/rust-lang/rust/pull/149709)
|
||||
Any paths emitted by compiler now always respect the relative-ness of the paths and `--remap-path-prefix` given originally.
|
||||
One side-effect of this change is that paths emitted for local crates in Cargo (path dependencies and workspace members) are no longer absolute but relative when emitted as part of a diagnostic in a downstream crate.
|
||||
|
||||
<a id="1.94.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.
|
||||
|
||||
- [Switch to `annotate-snippets` for error emission](https://github.com/rust-lang/rust/pull/150032)
|
||||
This should preserve mostly the same outputs in rustc error messages.
|
||||
|
||||
Version 1.93.1 (2026-02-12)
|
||||
===========================
|
||||
|
||||
|
||||
@@ -302,6 +302,11 @@
|
||||
# If you set this, you likely want to set `cargo` as well.
|
||||
#build.rustc = "/path/to/rustc"
|
||||
|
||||
# Use this rustdoc binary as the stage0 snapshot rustdoc.
|
||||
# If unspecified, then the binary "rustdoc" (with platform-specific extension, e.g. ".exe")
|
||||
# in the same directory as "rustc" will be used.
|
||||
#build.rustdoc = "/path/to/rustdoc"
|
||||
|
||||
# Instead of downloading the src/stage0 version of rustfmt specified,
|
||||
# use this rustfmt binary instead as the stage0 snapshot rustfmt.
|
||||
#build.rustfmt = "/path/to/rustfmt"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::assert_matches;
|
||||
use std::str::FromStr;
|
||||
|
||||
use rustc_data_structures::assert_matches;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
||||
@@ -21,7 +21,64 @@
|
||||
mod ty;
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
pub use ty::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx};
|
||||
pub use ty::{Layout, TyAbiInterface, TyAndLayout};
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// The *source-order* index of a field in a variant.
|
||||
///
|
||||
/// This is how most code after type checking refers to fields, rather than
|
||||
/// using names (as names have hygiene complications and more complex lookup).
|
||||
///
|
||||
/// Particularly for `repr(Rust)` types, this may not be the same as *layout* order.
|
||||
/// (It is for `repr(C)` `struct`s, however.)
|
||||
///
|
||||
/// For example, in the following types,
|
||||
/// ```rust
|
||||
/// # enum Never {}
|
||||
/// # #[repr(u16)]
|
||||
/// enum Demo1 {
|
||||
/// Variant0 { a: Never, b: i32 } = 100,
|
||||
/// Variant1 { c: u8, d: u64 } = 10,
|
||||
/// }
|
||||
/// struct Demo2 { e: u8, f: u16, g: u8 }
|
||||
/// ```
|
||||
/// `b` is `FieldIdx(1)` in `VariantIdx(0)`,
|
||||
/// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and
|
||||
/// `f` is `FieldIdx(1)` in `VariantIdx(0)`.
|
||||
#[cfg_attr(feature = "nightly", derive(rustc_macros::HashStable_Generic))]
|
||||
#[encodable]
|
||||
#[orderable]
|
||||
#[gate_rustc_only]
|
||||
pub struct FieldIdx {}
|
||||
}
|
||||
|
||||
impl FieldIdx {
|
||||
/// The second field, at index 1.
|
||||
///
|
||||
/// For use alongside [`FieldIdx::ZERO`], particularly with scalar pairs.
|
||||
pub const ONE: FieldIdx = FieldIdx::from_u32(1);
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// The *source-order* index of a variant in a type.
|
||||
///
|
||||
/// For enums, these are always `0..variant_count`, regardless of any
|
||||
/// custom discriminants that may have been defined, and including any
|
||||
/// variants that may end up uninhabited due to field types. (Some of the
|
||||
/// variants may not be present in a monomorphized ABI [`Variants`], but
|
||||
/// those skipped variants are always counted when determining the *index*.)
|
||||
///
|
||||
/// `struct`s, `tuples`, and `unions`s are considered to have a single variant
|
||||
/// with variant index zero, aka [`FIRST_VARIANT`].
|
||||
#[cfg_attr(feature = "nightly", derive(rustc_macros::HashStable_Generic))]
|
||||
#[encodable]
|
||||
#[orderable]
|
||||
#[gate_rustc_only]
|
||||
pub struct VariantIdx {
|
||||
/// Equivalent to `VariantIdx(0)`.
|
||||
const FIRST_VARIANT = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// A variant is absent if it's uninhabited and only has ZST fields.
|
||||
// Present uninhabited variants only require space for their fields,
|
||||
@@ -291,9 +348,9 @@ pub fn layout_of_struct_or_enum<
|
||||
always_sized: bool,
|
||||
) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
|
||||
let (present_first, present_second) = {
|
||||
let mut present_variants = variants
|
||||
.iter_enumerated()
|
||||
.filter_map(|(i, v)| if !repr.c() && absent(v) { None } else { Some(i) });
|
||||
let mut present_variants = variants.iter_enumerated().filter_map(|(i, v)| {
|
||||
if !repr.inhibit_enum_layout_opt() && absent(v) { None } else { Some(i) }
|
||||
});
|
||||
(present_variants.next(), present_variants.next())
|
||||
};
|
||||
let present_first = match present_first {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_macros::HashStable_Generic;
|
||||
|
||||
use crate::layout::{FieldIdx, VariantIdx};
|
||||
use crate::{
|
||||
AbiAlign, Align, BackendRepr, FieldsShape, Float, HasDataLayout, LayoutData, Niche,
|
||||
PointeeInfo, Primitive, Size, Variants,
|
||||
@@ -11,60 +12,6 @@
|
||||
|
||||
// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// The *source-order* index of a field in a variant.
|
||||
///
|
||||
/// This is how most code after type checking refers to fields, rather than
|
||||
/// using names (as names have hygiene complications and more complex lookup).
|
||||
///
|
||||
/// Particularly for `repr(Rust)` types, this may not be the same as *layout* order.
|
||||
/// (It is for `repr(C)` `struct`s, however.)
|
||||
///
|
||||
/// For example, in the following types,
|
||||
/// ```rust
|
||||
/// # enum Never {}
|
||||
/// # #[repr(u16)]
|
||||
/// enum Demo1 {
|
||||
/// Variant0 { a: Never, b: i32 } = 100,
|
||||
/// Variant1 { c: u8, d: u64 } = 10,
|
||||
/// }
|
||||
/// struct Demo2 { e: u8, f: u16, g: u8 }
|
||||
/// ```
|
||||
/// `b` is `FieldIdx(1)` in `VariantIdx(0)`,
|
||||
/// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and
|
||||
/// `f` is `FieldIdx(1)` in `VariantIdx(0)`.
|
||||
#[derive(HashStable_Generic)]
|
||||
#[encodable]
|
||||
#[orderable]
|
||||
pub struct FieldIdx {}
|
||||
}
|
||||
|
||||
impl FieldIdx {
|
||||
/// The second field, at index 1.
|
||||
///
|
||||
/// For use alongside [`FieldIdx::ZERO`], particularly with scalar pairs.
|
||||
pub const ONE: FieldIdx = FieldIdx::from_u32(1);
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// The *source-order* index of a variant in a type.
|
||||
///
|
||||
/// For enums, these are always `0..variant_count`, regardless of any
|
||||
/// custom discriminants that may have been defined, and including any
|
||||
/// variants that may end up uninhabited due to field types. (Some of the
|
||||
/// variants may not be present in a monomorphized ABI [`Variants`], but
|
||||
/// those skipped variants are always counted when determining the *index*.)
|
||||
///
|
||||
/// `struct`s, `tuples`, and `unions`s are considered to have a single variant
|
||||
/// with variant index zero, aka [`FIRST_VARIANT`].
|
||||
#[derive(HashStable_Generic)]
|
||||
#[encodable]
|
||||
#[orderable]
|
||||
pub struct VariantIdx {
|
||||
/// Equivalent to `VariantIdx(0)`.
|
||||
const FIRST_VARIANT = 0;
|
||||
}
|
||||
}
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
|
||||
#[rustc_pass_by_value]
|
||||
pub struct Layout<'a>(pub Interned<'a, LayoutData<FieldIdx, VariantIdx>>);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(all(feature = "nightly", bootstrap, test), feature(assert_matches))]
|
||||
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
||||
#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
|
||||
#![cfg_attr(feature = "nightly", feature(step_trait))]
|
||||
@@ -64,9 +63,9 @@
|
||||
#[cfg(feature = "nightly")]
|
||||
pub use extern_abi::CVariadicStatus;
|
||||
pub use extern_abi::{ExternAbi, all_names};
|
||||
pub use layout::{FIRST_VARIANT, FieldIdx, LayoutCalculator, LayoutCalculatorError, VariantIdx};
|
||||
#[cfg(feature = "nightly")]
|
||||
pub use layout::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx};
|
||||
pub use layout::{LayoutCalculator, LayoutCalculatorError};
|
||||
pub use layout::{Layout, TyAbiInterface, TyAndLayout};
|
||||
|
||||
/// Requirements for a `StableHashingContext` to be used in this crate.
|
||||
/// This is a hack to allow using the `HashStable_Generic` derive macro
|
||||
@@ -1036,6 +1035,19 @@ impl Align {
|
||||
// LLVM has a maximal supported alignment of 2^29, we inherit that.
|
||||
pub const MAX: Align = Align { pow2: 29 };
|
||||
|
||||
/// Either `1 << (pointer_bits - 1)` or [`Align::MAX`], whichever is smaller.
|
||||
#[inline]
|
||||
pub fn max_for_target(tdl: &TargetDataLayout) -> Align {
|
||||
let pointer_bits = tdl.pointer_size().bits();
|
||||
if let Ok(pointer_bits) = u8::try_from(pointer_bits)
|
||||
&& pointer_bits <= Align::MAX.pow2
|
||||
{
|
||||
Align { pow2: pointer_bits - 1 }
|
||||
} else {
|
||||
Align::MAX
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_bits(bits: u64) -> Result<Align, AlignFromBytesError> {
|
||||
Align::from_bytes(Size::from_bits(bits).bytes())
|
||||
@@ -2132,21 +2144,22 @@ pub enum PointerKind {
|
||||
}
|
||||
|
||||
/// Encodes extra information we have about a pointer.
|
||||
///
|
||||
/// Note that this information is advisory only, and backends are free to ignore it:
|
||||
/// if the information is wrong, that can cause UB, but if the information is absent,
|
||||
/// that must always be okay.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct PointeeInfo {
|
||||
/// If this is `None`, then this is a raw pointer, so size and alignment are not guaranteed to
|
||||
/// be reliable.
|
||||
/// If this is `None`, then this is a raw pointer.
|
||||
pub safe: Option<PointerKind>,
|
||||
/// If `safe` is `Some`, then the pointer is either null or dereferenceable for this many bytes.
|
||||
/// If `size` is not zero, then the pointer is either null or dereferenceable for this many bytes
|
||||
/// (independent of `safe`).
|
||||
///
|
||||
/// On a function argument, "dereferenceable" here means "dereferenceable for the entire duration
|
||||
/// of this function call", i.e. it is UB for the memory that this pointer points to be freed
|
||||
/// while this function is still running.
|
||||
/// The size can be zero if the pointer is not dereferenceable.
|
||||
pub size: Size,
|
||||
/// If `safe` is `Some`, then the pointer is aligned as indicated.
|
||||
/// The pointer is guaranteed to be aligned this much (independent of `safe`).
|
||||
pub align: Align,
|
||||
}
|
||||
|
||||
|
||||
@@ -1724,6 +1724,12 @@ pub enum StructRest {
|
||||
Rest(Span),
|
||||
/// No trailing `..` or expression.
|
||||
None,
|
||||
/// No trailing `..` or expression, and also, a parse error occurred inside the struct braces.
|
||||
///
|
||||
/// This struct should be treated similarly to as if it had an `..` in it,
|
||||
/// in particular rather than reporting missing fields, because the parse error
|
||||
/// makes which fields the struct was intended to have not fully known.
|
||||
NoneWithError(ErrorGuaranteed),
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
@@ -2553,6 +2559,11 @@ pub enum TyKind {
|
||||
/// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero<u32>`,
|
||||
/// just as part of the type system.
|
||||
Pat(Box<Ty>, Box<TyPat>),
|
||||
/// A `field_of` expression (e.g., `builtin # field_of(Struct, field)`).
|
||||
///
|
||||
/// Usually not written directly in user code but indirectly via the macro
|
||||
/// `core::field::field_of!(...)`.
|
||||
FieldOf(Box<Ty>, Option<Ident>, Ident),
|
||||
/// Sometimes we need a dummy value when no error has occurred.
|
||||
Dummy,
|
||||
/// Placeholder for a kind that has failed to be defined.
|
||||
@@ -3131,8 +3142,16 @@ pub enum Const {
|
||||
/// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
|
||||
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, Walkable)]
|
||||
pub enum Defaultness {
|
||||
/// Item is unmarked. Implicitly determined based off of position.
|
||||
/// For impls, this is `final`; for traits, this is `default`.
|
||||
///
|
||||
/// If you're expanding an item in a built-in macro or parsing an item
|
||||
/// by hand, you probably want to use this.
|
||||
Implicit,
|
||||
/// `default`
|
||||
Default(Span),
|
||||
Final,
|
||||
/// `final`; per RFC 3678, only trait items may be *explicitly* marked final.
|
||||
Final(Span),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic, Walkable)]
|
||||
@@ -3534,6 +3553,19 @@ pub fn is_pub(&self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub struct ImplRestriction {
|
||||
pub kind: RestrictionKind,
|
||||
pub span: Span,
|
||||
pub tokens: Option<LazyAttrTokenStream>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub enum RestrictionKind {
|
||||
Unrestricted,
|
||||
Restricted { path: Box<Path>, id: NodeId, shorthand: bool },
|
||||
}
|
||||
|
||||
/// Field definition in a struct, variant or union.
|
||||
///
|
||||
/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
|
||||
@@ -3733,6 +3765,7 @@ pub struct Trait {
|
||||
pub constness: Const,
|
||||
pub safety: Safety,
|
||||
pub is_auto: IsAuto,
|
||||
pub impl_restriction: ImplRestriction,
|
||||
pub ident: Ident,
|
||||
pub generics: Generics,
|
||||
#[visitable(extra = BoundKind::SuperTraits)]
|
||||
@@ -4140,7 +4173,7 @@ pub fn defaultness(&self) -> Defaultness {
|
||||
| Self::Fn(box Fn { defaultness, .. })
|
||||
| Self::Type(box TyAlias { defaultness, .. }) => defaultness,
|
||||
Self::MacCall(..) | Self::Delegation(..) | Self::DelegationMac(..) => {
|
||||
Defaultness::Final
|
||||
Defaultness::Implicit
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4203,9 +4236,7 @@ pub fn ident(&self) -> Option<Ident> {
|
||||
impl From<ForeignItemKind> for ItemKind {
|
||||
fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
|
||||
match foreign_item_kind {
|
||||
ForeignItemKind::Static(box static_foreign_item) => {
|
||||
ItemKind::Static(Box::new(static_foreign_item))
|
||||
}
|
||||
ForeignItemKind::Static(static_foreign_item) => ItemKind::Static(static_foreign_item),
|
||||
ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
|
||||
ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
|
||||
ForeignItemKind::MacCall(a) => ItemKind::MacCall(a),
|
||||
@@ -4218,7 +4249,7 @@ impl TryFrom<ItemKind> for ForeignItemKind {
|
||||
|
||||
fn try_from(item_kind: ItemKind) -> Result<ForeignItemKind, ItemKind> {
|
||||
Ok(match item_kind {
|
||||
ItemKind::Static(box static_item) => ForeignItemKind::Static(Box::new(static_item)),
|
||||
ItemKind::Static(static_item) => ForeignItemKind::Static(static_item),
|
||||
ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind),
|
||||
ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind),
|
||||
ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
use crate::tokenstream::LazyAttrTokenStream;
|
||||
use crate::{
|
||||
Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField,
|
||||
FieldDef, ForeignItem, GenericParam, Item, NodeId, Param, Pat, PatField, Path, Stmt, StmtKind,
|
||||
Ty, Variant, Visibility, WherePredicate,
|
||||
FieldDef, ForeignItem, GenericParam, ImplRestriction, Item, NodeId, Param, Pat, PatField, Path,
|
||||
Stmt, StmtKind, Ty, Variant, Visibility, WherePredicate,
|
||||
};
|
||||
|
||||
/// A trait for AST nodes having an ID.
|
||||
@@ -97,7 +97,19 @@ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
};
|
||||
}
|
||||
|
||||
impl_has_tokens!(AssocItem, AttrItem, Block, Expr, ForeignItem, Item, Pat, Path, Ty, Visibility);
|
||||
impl_has_tokens!(
|
||||
AssocItem,
|
||||
AttrItem,
|
||||
Block,
|
||||
Expr,
|
||||
ForeignItem,
|
||||
Item,
|
||||
Pat,
|
||||
Path,
|
||||
Ty,
|
||||
Visibility,
|
||||
ImplRestriction
|
||||
);
|
||||
impl_has_tokens_none!(
|
||||
Arm,
|
||||
ExprField,
|
||||
@@ -242,7 +254,7 @@ fn visit_attrs(&mut self, _f: impl FnOnce(&mut AttrVec)) {}
|
||||
Variant,
|
||||
WherePredicate,
|
||||
);
|
||||
impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility);
|
||||
impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility, ImplRestriction);
|
||||
|
||||
impl<T: HasAttrs> HasAttrs for Box<T> {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
|
||||
@@ -296,6 +296,10 @@ fn is_doc_keyword_or_attribute(&self) -> bool {
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn is_rustc_doc_primitive(&self) -> bool {
|
||||
self.has_name(sym::rustc_doc_primitive)
|
||||
}
|
||||
}
|
||||
|
||||
impl Attribute {
|
||||
@@ -935,6 +939,9 @@ fn is_proc_macro_attr(&self) -> bool {
|
||||
|
||||
/// Returns `true` is this attribute contains `doc(keyword)` or `doc(attribute)`.
|
||||
fn is_doc_keyword_or_attribute(&self) -> bool;
|
||||
|
||||
/// Returns `true` if this is a `#[rustc_doc_primitive]` attribute.
|
||||
fn is_rustc_doc_primitive(&self) -> bool;
|
||||
}
|
||||
|
||||
// FIXME(fn_delegation): use function delegation instead of manually forwarding
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
//! This crate handles the user facing autodiff macro. For each `#[autodiff(...)]` attribute,
|
||||
//! we create an [`AutoDiffItem`] which contains the source and target function names. The source
|
||||
//! we create an `RustcAutodiff` which contains the source and target function names. The source
|
||||
//! is the function to which the autodiff attribute is applied, and the target is the function
|
||||
//! getting generated by us (with a name given by the user as the first autodiff arg).
|
||||
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::expand::typetree::TypeTree;
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::expand::{Decodable, Encodable, HashStable_Generic};
|
||||
use crate::{Ty, TyKind};
|
||||
|
||||
@@ -31,6 +32,12 @@ pub enum DiffMode {
|
||||
Reverse,
|
||||
}
|
||||
|
||||
impl DiffMode {
|
||||
pub fn all_modes() -> &'static [Symbol] {
|
||||
&[sym::Source, sym::Forward, sym::Reverse]
|
||||
}
|
||||
}
|
||||
|
||||
/// Dual and Duplicated (and their Only variants) are getting lowered to the same Enzyme Activity.
|
||||
/// However, under forward mode we overwrite the previous shadow value, while for reverse mode
|
||||
/// we add to the previous shadow value. To not surprise users, we picked different names.
|
||||
@@ -76,43 +83,20 @@ pub fn is_dual_or_const(&self) -> bool {
|
||||
use DiffActivity::*;
|
||||
matches!(self, |Dual| DualOnly | Dualv | DualvOnly | Const)
|
||||
}
|
||||
}
|
||||
/// We generate one of these structs for each `#[autodiff(...)]` attribute.
|
||||
#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct AutoDiffItem {
|
||||
/// The name of the function getting differentiated
|
||||
pub source: String,
|
||||
/// The name of the function being generated
|
||||
pub target: String,
|
||||
pub attrs: AutoDiffAttrs,
|
||||
pub inputs: Vec<TypeTree>,
|
||||
pub output: TypeTree,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct AutoDiffAttrs {
|
||||
/// Conceptually either forward or reverse mode AD, as described in various autodiff papers and
|
||||
/// e.g. in the [JAX
|
||||
/// Documentation](https://jax.readthedocs.io/en/latest/_tutorials/advanced-autodiff.html#how-it-s-made-two-foundational-autodiff-functions).
|
||||
pub mode: DiffMode,
|
||||
/// A user-provided, batching width. If not given, we will default to 1 (no batching).
|
||||
/// Calling a differentiated, non-batched function through a loop 100 times is equivalent to:
|
||||
/// - Calling the function 50 times with a batch size of 2
|
||||
/// - Calling the function 25 times with a batch size of 4,
|
||||
/// etc. A batched function takes more (or longer) arguments, and might be able to benefit from
|
||||
/// cache locality, better re-usal of primal values, and other optimizations.
|
||||
/// We will (before LLVM's vectorizer runs) just generate most LLVM-IR instructions `width`
|
||||
/// times, so this massively increases code size. As such, values like 1024 are unlikely to
|
||||
/// work. We should consider limiting this to u8 or u16, but will leave it at u32 for
|
||||
/// experiments for now and focus on documenting the implications of a large width.
|
||||
pub width: u32,
|
||||
pub ret_activity: DiffActivity,
|
||||
pub input_activity: Vec<DiffActivity>,
|
||||
}
|
||||
|
||||
impl AutoDiffAttrs {
|
||||
pub fn has_primal_ret(&self) -> bool {
|
||||
matches!(self.ret_activity, DiffActivity::Active | DiffActivity::Dual)
|
||||
pub fn all_activities() -> &'static [Symbol] {
|
||||
&[
|
||||
sym::None,
|
||||
sym::Active,
|
||||
sym::ActiveOnly,
|
||||
sym::Const,
|
||||
sym::Dual,
|
||||
sym::Dualv,
|
||||
sym::DualOnly,
|
||||
sym::DualvOnly,
|
||||
sym::Duplicated,
|
||||
sym::DuplicatedOnly,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,59 +225,3 @@ fn from_str(s: &str) -> Result<DiffActivity, ()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AutoDiffAttrs {
|
||||
pub fn has_ret_activity(&self) -> bool {
|
||||
self.ret_activity != DiffActivity::None
|
||||
}
|
||||
pub fn has_active_only_ret(&self) -> bool {
|
||||
self.ret_activity == DiffActivity::ActiveOnly
|
||||
}
|
||||
|
||||
pub const fn error() -> Self {
|
||||
AutoDiffAttrs {
|
||||
mode: DiffMode::Error,
|
||||
width: 0,
|
||||
ret_activity: DiffActivity::None,
|
||||
input_activity: Vec::new(),
|
||||
}
|
||||
}
|
||||
pub fn source() -> Self {
|
||||
AutoDiffAttrs {
|
||||
mode: DiffMode::Source,
|
||||
width: 0,
|
||||
ret_activity: DiffActivity::None,
|
||||
input_activity: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_active(&self) -> bool {
|
||||
self.mode != DiffMode::Error
|
||||
}
|
||||
|
||||
pub fn is_source(&self) -> bool {
|
||||
self.mode == DiffMode::Source
|
||||
}
|
||||
pub fn apply_autodiff(&self) -> bool {
|
||||
!matches!(self.mode, DiffMode::Error | DiffMode::Source)
|
||||
}
|
||||
|
||||
pub fn into_item(
|
||||
self,
|
||||
source: String,
|
||||
target: String,
|
||||
inputs: Vec<TypeTree>,
|
||||
output: TypeTree,
|
||||
) -> AutoDiffItem {
|
||||
AutoDiffItem { source, target, inputs, output, attrs: self }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for AutoDiffItem {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Differentiating {} -> {}", self.source, self.target)?;
|
||||
write!(f, " with attributes: {:?}", self.attrs)?;
|
||||
write!(f, " with inputs: {:?}", self.inputs)?;
|
||||
write!(f, " with output: {:?}", self.output)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#![doc(test(attr(deny(warnings), allow(internal_features))))]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_order_by)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
@@ -298,6 +298,7 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
|
||||
| ast::TyKind::ImplicitSelf
|
||||
| ast::TyKind::CVarArgs
|
||||
| ast::TyKind::Pat(..)
|
||||
| ast::TyKind::FieldOf(..)
|
||||
| ast::TyKind::Dummy
|
||||
| ast::TyKind::Err(..) => break None,
|
||||
}
|
||||
|
||||
@@ -467,6 +467,7 @@ pub fn ctxt(&self) -> Option<FnCtxt> {
|
||||
RangeEnd,
|
||||
RangeSyntax,
|
||||
Recovered,
|
||||
RestrictionKind,
|
||||
Safety,
|
||||
StaticItem,
|
||||
StrLit,
|
||||
@@ -595,6 +596,7 @@ fn visit_ident(&mut self, Ident { name: _, span }: &$($lt)? $($mut)? Ident) -> S
|
||||
fn visit_poly_trait_ref(PolyTraitRef);
|
||||
fn visit_precise_capturing_arg(PreciseCapturingArg);
|
||||
fn visit_qself(QSelf);
|
||||
fn visit_impl_restriction(ImplRestriction);
|
||||
fn visit_trait_ref(TraitRef);
|
||||
fn visit_ty_pat(TyPat);
|
||||
fn visit_ty(Ty);
|
||||
@@ -757,9 +759,10 @@ fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
|
||||
) -> V::Result;
|
||||
}
|
||||
|
||||
// this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
|
||||
// This is only used by the MutVisitor. We include this symmetry here to make writing other
|
||||
// functions easier.
|
||||
$(${ignore($lt)}
|
||||
#[expect(unused, rustc::pass_by_value)]
|
||||
#[expect(unused, rustc::disallowed_pass_by_ref)]
|
||||
#[inline]
|
||||
)?
|
||||
fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, span: &$($lt)? $($mut)? Span) -> V::Result {
|
||||
@@ -1115,6 +1118,7 @@ pub fn walk_fn<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, kind: FnKind<$($lt)?
|
||||
pub fn walk_poly_trait_ref(PolyTraitRef);
|
||||
pub fn walk_precise_capturing_arg(PreciseCapturingArg);
|
||||
pub fn walk_qself(QSelf);
|
||||
pub fn walk_impl_restriction(ImplRestriction);
|
||||
pub fn walk_trait_ref(TraitRef);
|
||||
pub fn walk_ty_pat(TyPat);
|
||||
pub fn walk_ty(Ty);
|
||||
|
||||
@@ -42,11 +42,12 @@
|
||||
use hir::def::{DefKind, PartialRes, Res};
|
||||
use hir::{BodyId, HirId};
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::*;
|
||||
use rustc_attr_parsing::{AttributeParser, ShouldEmit};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::Target;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::attrs::{AttributeKind, InlineAttr};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::span_bug;
|
||||
@@ -54,11 +55,15 @@
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol};
|
||||
use smallvec::SmallVec;
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode};
|
||||
use crate::delegation::generics::{GenericsGenerationResult, GenericsGenerationResults};
|
||||
use crate::errors::{CycleInDelegationSignatureResolution, UnresolvedDelegationCallee};
|
||||
use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt};
|
||||
use crate::{
|
||||
AllowReturnTypeNotation, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext,
|
||||
ParamMode, ResolverAstLoweringExt,
|
||||
};
|
||||
|
||||
mod generics;
|
||||
|
||||
pub(crate) struct DelegationResults<'hir> {
|
||||
pub body_id: hir::BodyId,
|
||||
@@ -184,18 +189,48 @@ pub(crate) fn lower_delegation(
|
||||
// we need a function to extract this information
|
||||
let (param_count, c_variadic) = self.param_count(root_function_id);
|
||||
|
||||
let mut generics = self.lower_delegation_generics(
|
||||
delegation,
|
||||
ids.root_function_id(),
|
||||
item_id,
|
||||
span,
|
||||
);
|
||||
|
||||
let body_id = self.lower_delegation_body(
|
||||
delegation,
|
||||
item_id,
|
||||
is_method,
|
||||
param_count,
|
||||
&mut generics,
|
||||
span,
|
||||
);
|
||||
|
||||
// Here we use `delegee_id`, as this id will then be used to calculate parent for generics
|
||||
// inheritance, and we want this id to point on a delegee, not on the original
|
||||
// function (see https://github.com/rust-lang/rust/issues/150152#issuecomment-3674834654)
|
||||
let decl = self.lower_delegation_decl(delegee_id, param_count, c_variadic, span);
|
||||
let decl = self.lower_delegation_decl(
|
||||
delegee_id,
|
||||
param_count,
|
||||
c_variadic,
|
||||
span,
|
||||
&generics,
|
||||
);
|
||||
|
||||
// Here we pass `root_function_id` as we want to inherit signature (including consts, async)
|
||||
// from the root function that started delegation
|
||||
let sig = self.lower_delegation_sig(root_function_id, decl, span);
|
||||
|
||||
let body_id = self.lower_delegation_body(delegation, is_method, param_count, span);
|
||||
let ident = self.lower_ident(delegation.ident);
|
||||
let generics = self.lower_delegation_generics(span);
|
||||
|
||||
let generics = self.arena.alloc(hir::Generics {
|
||||
has_where_clause_predicates: false,
|
||||
params: self.arena.alloc_from_iter(generics.all_params(item_id, span, self)),
|
||||
predicates: self
|
||||
.arena
|
||||
.alloc_from_iter(generics.all_predicates(item_id, span, self)),
|
||||
span,
|
||||
where_clause_span: span,
|
||||
});
|
||||
|
||||
DelegationResults { body_id, sig, ident, generics }
|
||||
}
|
||||
Err(err) => self.generate_delegation_error(err, span, delegation),
|
||||
@@ -264,11 +299,14 @@ fn create_new_attrs(
|
||||
.flatten()
|
||||
})
|
||||
.flatten(),
|
||||
None => self
|
||||
.tcx
|
||||
.get_all_attrs(*def_id)
|
||||
.iter()
|
||||
.find(|base_attr| (addition_info.equals)(base_attr)),
|
||||
None =>
|
||||
{
|
||||
#[allow(deprecated)]
|
||||
self.tcx
|
||||
.get_all_attrs(*def_id)
|
||||
.iter()
|
||||
.find(|base_attr| (addition_info.equals)(base_attr))
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(original_attr) = original_attr {
|
||||
@@ -292,7 +330,7 @@ fn parse_local_original_attrs(&self, def_id: DefId) -> Option<Vec<hir::Attribute
|
||||
self.tcx.sess,
|
||||
attrs,
|
||||
None,
|
||||
Target::Fn,
|
||||
hir::Target::Fn,
|
||||
DUMMY_SP,
|
||||
DUMMY_NODE_ID,
|
||||
Some(self.tcx.features()),
|
||||
@@ -361,16 +399,6 @@ fn get_resolution_id(&self, node_id: NodeId) -> Option<DefId> {
|
||||
self.resolver.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id())
|
||||
}
|
||||
|
||||
fn lower_delegation_generics(&mut self, span: Span) -> &'hir hir::Generics<'hir> {
|
||||
self.arena.alloc(hir::Generics {
|
||||
params: &[],
|
||||
predicates: &[],
|
||||
has_where_clause_predicates: false,
|
||||
where_clause_span: span,
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
||||
// Function parameter count, including C variadic `...` if present.
|
||||
fn param_count(&self, def_id: DefId) -> (usize, bool /*c_variadic*/) {
|
||||
if let Some(local_sig_id) = def_id.as_local() {
|
||||
@@ -390,6 +418,7 @@ fn lower_delegation_decl(
|
||||
param_count: usize,
|
||||
c_variadic: bool,
|
||||
span: Span,
|
||||
generics: &GenericsGenerationResults<'hir>,
|
||||
) -> &'hir hir::FnDecl<'hir> {
|
||||
// The last parameter in C variadic functions is skipped in the signature,
|
||||
// like during regular lowering.
|
||||
@@ -402,7 +431,13 @@ fn lower_delegation_decl(
|
||||
|
||||
let output = self.arena.alloc(hir::Ty {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output),
|
||||
kind: hir::TyKind::InferDelegation(
|
||||
sig_id,
|
||||
hir::InferDelegationKind::Output(self.arena.alloc(hir::DelegationGenerics {
|
||||
child_args_segment_id: generics.child.args_segment_id,
|
||||
parent_args_segment_id: generics.parent.args_segment_id,
|
||||
})),
|
||||
),
|
||||
span,
|
||||
});
|
||||
|
||||
@@ -457,6 +492,7 @@ fn lower_delegation_sig(
|
||||
abi: sig.abi,
|
||||
}
|
||||
};
|
||||
|
||||
hir::FnSig { decl, header, span }
|
||||
}
|
||||
|
||||
@@ -498,6 +534,7 @@ fn generate_arg(
|
||||
} else {
|
||||
Symbol::intern(&format!("arg{idx}"))
|
||||
};
|
||||
|
||||
let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
|
||||
ident: Ident::with_dummy_span(name),
|
||||
hir_id: self.next_id(),
|
||||
@@ -513,8 +550,10 @@ fn generate_arg(
|
||||
fn lower_delegation_body(
|
||||
&mut self,
|
||||
delegation: &Delegation,
|
||||
item_id: NodeId,
|
||||
is_method: bool,
|
||||
param_count: usize,
|
||||
generics: &mut GenericsGenerationResults<'hir>,
|
||||
span: Span,
|
||||
) -> BodyId {
|
||||
let block = delegation.body.as_deref();
|
||||
@@ -545,7 +584,8 @@ fn lower_delegation_body(
|
||||
args.push(arg);
|
||||
}
|
||||
|
||||
let final_expr = this.finalize_body_lowering(delegation, args, span);
|
||||
let final_expr = this.finalize_body_lowering(delegation, item_id, args, generics, span);
|
||||
|
||||
(this.arena.alloc_from_iter(parameters), final_expr)
|
||||
})
|
||||
}
|
||||
@@ -581,7 +621,9 @@ fn lower_target_expr(&mut self, block: &Block) -> hir::Expr<'hir> {
|
||||
fn finalize_body_lowering(
|
||||
&mut self,
|
||||
delegation: &Delegation,
|
||||
item_id: NodeId,
|
||||
args: Vec<hir::Expr<'hir>>,
|
||||
generics: &mut GenericsGenerationResults<'hir>,
|
||||
span: Span,
|
||||
) -> hir::Expr<'hir> {
|
||||
let args = self.arena.alloc_from_iter(args);
|
||||
@@ -606,6 +648,10 @@ fn finalize_body_lowering(
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
|
||||
// FIXME(fn_delegation): proper support for parent generics propagation
|
||||
// in method call scenario.
|
||||
let segment = self.process_segment(item_id, span, &segment, &mut generics.child, false);
|
||||
let segment = self.arena.alloc(segment);
|
||||
|
||||
self.arena.alloc(hir::Expr {
|
||||
@@ -624,9 +670,41 @@ fn finalize_body_lowering(
|
||||
None,
|
||||
);
|
||||
|
||||
let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(path), span));
|
||||
let new_path = match path {
|
||||
hir::QPath::Resolved(ty, path) => {
|
||||
let mut new_path = path.clone();
|
||||
let len = new_path.segments.len();
|
||||
|
||||
new_path.segments = self.arena.alloc_from_iter(
|
||||
new_path.segments.iter().enumerate().map(|(idx, segment)| {
|
||||
let mut process_segment = |result, add_lifetimes| {
|
||||
self.process_segment(item_id, span, segment, result, add_lifetimes)
|
||||
};
|
||||
|
||||
if idx + 2 == len {
|
||||
process_segment(&mut generics.parent, true)
|
||||
} else if idx + 1 == len {
|
||||
process_segment(&mut generics.child, false)
|
||||
} else {
|
||||
segment.clone()
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
hir::QPath::Resolved(ty, self.arena.alloc(new_path))
|
||||
}
|
||||
hir::QPath::TypeRelative(ty, segment) => {
|
||||
let segment =
|
||||
self.process_segment(item_id, span, segment, &mut generics.child, false);
|
||||
|
||||
hir::QPath::TypeRelative(ty, self.arena.alloc(segment))
|
||||
}
|
||||
};
|
||||
|
||||
let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(new_path), span));
|
||||
self.arena.alloc(self.mk_expr(hir::ExprKind::Call(callee_path, args), span))
|
||||
};
|
||||
|
||||
let block = self.arena.alloc(hir::Block {
|
||||
stmts: &[],
|
||||
expr: Some(call),
|
||||
@@ -639,14 +717,40 @@ fn finalize_body_lowering(
|
||||
self.mk_expr(hir::ExprKind::Block(block, None), span)
|
||||
}
|
||||
|
||||
fn process_segment(
|
||||
&mut self,
|
||||
item_id: NodeId,
|
||||
span: Span,
|
||||
segment: &hir::PathSegment<'hir>,
|
||||
result: &mut GenericsGenerationResult<'hir>,
|
||||
add_lifetimes: bool,
|
||||
) -> hir::PathSegment<'hir> {
|
||||
// The first condition is needed when there is SelfAndUserSpecified case,
|
||||
// we don't want to propagate generics params in this situation.
|
||||
let segment = if !result.generics.is_user_specified()
|
||||
&& let Some(args) = result
|
||||
.generics
|
||||
.into_hir_generics(self, item_id, span)
|
||||
.into_generic_args(self, add_lifetimes, span)
|
||||
{
|
||||
hir::PathSegment { args: Some(args), ..segment.clone() }
|
||||
} else {
|
||||
segment.clone()
|
||||
};
|
||||
|
||||
if result.generics.is_user_specified() {
|
||||
result.args_segment_id = Some(segment.hir_id);
|
||||
}
|
||||
|
||||
segment
|
||||
}
|
||||
|
||||
fn generate_delegation_error(
|
||||
&mut self,
|
||||
err: ErrorGuaranteed,
|
||||
span: Span,
|
||||
delegation: &Delegation,
|
||||
) -> DelegationResults<'hir> {
|
||||
let generics = self.lower_delegation_generics(span);
|
||||
|
||||
let decl = self.arena.alloc(hir::FnDecl {
|
||||
inputs: &[],
|
||||
output: hir::FnRetTy::DefaultReturn(span),
|
||||
@@ -693,6 +797,7 @@ fn generate_delegation_error(
|
||||
(&[], this.mk_expr(body_expr, span))
|
||||
});
|
||||
|
||||
let generics = hir::Generics::empty();
|
||||
DelegationResults { ident, generics, body_id, sig }
|
||||
}
|
||||
|
||||
@@ -711,13 +816,13 @@ fn mk_expr(&mut self, kind: hir::ExprKind<'hir>, span: Span) -> hir::Expr<'hir>
|
||||
}
|
||||
}
|
||||
|
||||
struct SelfResolver<'a> {
|
||||
resolver: &'a mut ResolverAstLowering,
|
||||
struct SelfResolver<'a, 'tcx> {
|
||||
resolver: &'a mut ResolverAstLowering<'tcx>,
|
||||
path_id: NodeId,
|
||||
self_param_id: NodeId,
|
||||
}
|
||||
|
||||
impl<'a> SelfResolver<'a> {
|
||||
impl SelfResolver<'_, '_> {
|
||||
fn try_replace_id(&mut self, id: NodeId) {
|
||||
if let Some(res) = self.resolver.partial_res_map.get(&id)
|
||||
&& let Some(Res::Local(sig_id)) = res.full_res()
|
||||
@@ -729,7 +834,7 @@ fn try_replace_id(&mut self, id: NodeId) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, 'a> Visitor<'ast> for SelfResolver<'a> {
|
||||
impl<'ast, 'a> Visitor<'ast> for SelfResolver<'a, '_> {
|
||||
fn visit_id(&mut self, id: NodeId) {
|
||||
self.try_replace_id(id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,578 @@
|
||||
use hir::HirId;
|
||||
use hir::def::{DefKind, Res};
|
||||
use rustc_ast::*;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::GenericParamDefKind;
|
||||
use rustc_middle::{bug, ty};
|
||||
use rustc_span::sym::{self};
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::{DUMMY_SP, Ident, Span};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use crate::{AstOwner, LoweringContext};
|
||||
|
||||
pub(super) enum DelegationGenerics<T> {
|
||||
/// User-specified args are present: `reuse foo::<String>;`.
|
||||
UserSpecified,
|
||||
/// The default case when no user-specified args are present: `reuse Trait::foo;`.
|
||||
Default(Option<T>),
|
||||
/// In free-to-trait reuse, when user specified args for trait `reuse Trait::<i32>::foo;`
|
||||
/// in this case we need to both generate `Self` and process user args.
|
||||
SelfAndUserSpecified(Option<T>),
|
||||
}
|
||||
|
||||
/// Used for storing either AST generics or their lowered HIR version. Firstly we obtain
|
||||
/// AST generics either from local function from AST index or from external function
|
||||
/// through `tcx`. Next, at some point of generics processing we need to lower those
|
||||
/// generics to HIR, for this purpose we use `into_hir_generics` that lowers AST generics
|
||||
/// and replaces Ast variant with Hir. Such approach is useful as we can call this method
|
||||
/// at any time knowing that lowering will occur at most only once. Then, in order to obtain generic
|
||||
/// params or args we use `hir_generics_or_empty` or `into_generic_args` functions.
|
||||
/// There also may be situations when we obtained AST generics but never lowered them to HIR,
|
||||
/// meaning we did not propagate them and thus we do not need to generate generic params
|
||||
/// (i.e., method call scenarios), in such a case this approach helps
|
||||
/// a lot as if `into_hir_generics` will not be called then lowering will not happen.
|
||||
pub(super) enum HirOrAstGenerics<'hir> {
|
||||
Ast(DelegationGenerics<Generics>),
|
||||
Hir(DelegationGenerics<&'hir hir::Generics<'hir>>),
|
||||
}
|
||||
|
||||
pub(super) struct GenericsGenerationResult<'hir> {
|
||||
pub(super) generics: HirOrAstGenerics<'hir>,
|
||||
pub(super) args_segment_id: Option<HirId>,
|
||||
}
|
||||
|
||||
pub(super) struct GenericsGenerationResults<'hir> {
|
||||
pub(super) parent: GenericsGenerationResult<'hir>,
|
||||
pub(super) child: GenericsGenerationResult<'hir>,
|
||||
}
|
||||
|
||||
impl<T> DelegationGenerics<T> {
|
||||
fn is_user_specified(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
DelegationGenerics::UserSpecified | DelegationGenerics::SelfAndUserSpecified { .. }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'hir> HirOrAstGenerics<'hir> {
|
||||
pub(super) fn into_hir_generics(
|
||||
&mut self,
|
||||
ctx: &mut LoweringContext<'_, 'hir>,
|
||||
item_id: NodeId,
|
||||
span: Span,
|
||||
) -> &mut HirOrAstGenerics<'hir> {
|
||||
if let HirOrAstGenerics::Ast(generics) = self {
|
||||
let process_params = |generics: &mut Generics| {
|
||||
ctx.lower_delegation_generic_params(item_id, span, &mut generics.params)
|
||||
};
|
||||
|
||||
let hir_generics = match generics {
|
||||
DelegationGenerics::UserSpecified => DelegationGenerics::UserSpecified,
|
||||
DelegationGenerics::Default(generics) => {
|
||||
DelegationGenerics::Default(generics.as_mut().map(process_params))
|
||||
}
|
||||
DelegationGenerics::SelfAndUserSpecified(generics) => {
|
||||
DelegationGenerics::SelfAndUserSpecified(generics.as_mut().map(process_params))
|
||||
}
|
||||
};
|
||||
|
||||
*self = HirOrAstGenerics::Hir(hir_generics);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> {
|
||||
match self {
|
||||
HirOrAstGenerics::Ast(_) => hir::Generics::empty(),
|
||||
HirOrAstGenerics::Hir(hir_generics) => match hir_generics {
|
||||
DelegationGenerics::UserSpecified => hir::Generics::empty(),
|
||||
DelegationGenerics::Default(generics)
|
||||
| DelegationGenerics::SelfAndUserSpecified(generics) => {
|
||||
generics.unwrap_or(hir::Generics::empty())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn into_generic_args(
|
||||
&self,
|
||||
ctx: &mut LoweringContext<'_, 'hir>,
|
||||
add_lifetimes: bool,
|
||||
span: Span,
|
||||
) -> Option<&'hir hir::GenericArgs<'hir>> {
|
||||
match self {
|
||||
HirOrAstGenerics::Ast(_) => {
|
||||
bug!("Attempting to get generic args before lowering to HIR")
|
||||
}
|
||||
HirOrAstGenerics::Hir(hir_generics) => match hir_generics {
|
||||
DelegationGenerics::UserSpecified => None,
|
||||
DelegationGenerics::Default(generics)
|
||||
| DelegationGenerics::SelfAndUserSpecified(generics) => generics.map(|generics| {
|
||||
ctx.create_generics_args_from_params(generics.params, add_lifetimes, span)
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn is_user_specified(&self) -> bool {
|
||||
match self {
|
||||
HirOrAstGenerics::Ast(ast_generics) => ast_generics.is_user_specified(),
|
||||
HirOrAstGenerics::Hir(hir_generics) => hir_generics.is_user_specified(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GenericsGenerationResult<'a> {
|
||||
fn new(generics: DelegationGenerics<Generics>) -> GenericsGenerationResult<'a> {
|
||||
GenericsGenerationResult {
|
||||
generics: HirOrAstGenerics::Ast(generics),
|
||||
args_segment_id: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'hir> GenericsGenerationResults<'hir> {
|
||||
pub(super) fn all_params(
|
||||
&mut self,
|
||||
item_id: NodeId,
|
||||
span: Span,
|
||||
ctx: &mut LoweringContext<'_, 'hir>,
|
||||
) -> impl Iterator<Item = hir::GenericParam<'hir>> {
|
||||
// Now we always call `into_hir_generics` both on child and parent,
|
||||
// however in future we would not do that, when scenarios like
|
||||
// method call will be supported (if HIR generics were not obtained
|
||||
// then it means that we did not propagated them, thus we do not need
|
||||
// to generate params).
|
||||
let parent = self
|
||||
.parent
|
||||
.generics
|
||||
.into_hir_generics(ctx, item_id, span)
|
||||
.hir_generics_or_empty()
|
||||
.params;
|
||||
|
||||
let child = self
|
||||
.child
|
||||
.generics
|
||||
.into_hir_generics(ctx, item_id, span)
|
||||
.hir_generics_or_empty()
|
||||
.params;
|
||||
|
||||
// Order generics, firstly we have parent and child lifetimes,
|
||||
// then parent and child types and consts.
|
||||
// `generics_of` in `rustc_hir_analysis` will order them anyway,
|
||||
// however we want the order to be consistent in HIR too.
|
||||
parent
|
||||
.iter()
|
||||
.filter(|p| p.is_lifetime())
|
||||
.chain(child.iter().filter(|p| p.is_lifetime()))
|
||||
.chain(parent.iter().filter(|p| !p.is_lifetime()))
|
||||
.chain(child.iter().filter(|p| !p.is_lifetime()))
|
||||
.copied()
|
||||
}
|
||||
|
||||
/// As we add hack predicates(`'a: 'a`) for all lifetimes (see `lower_delegation_generic_params`
|
||||
/// and `generate_lifetime_predicate` functions) we need to add them to delegation generics.
|
||||
/// Those predicates will not affect resulting predicate inheritance and folding
|
||||
/// in `rustc_hir_analysis`, as we inherit all predicates from delegation signature.
|
||||
pub(super) fn all_predicates(
|
||||
&mut self,
|
||||
item_id: NodeId,
|
||||
span: Span,
|
||||
ctx: &mut LoweringContext<'_, 'hir>,
|
||||
) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
|
||||
// Now we always call `into_hir_generics` both on child and parent,
|
||||
// however in future we would not do that, when scenarios like
|
||||
// method call will be supported (if HIR generics were not obtained
|
||||
// then it means that we did not propagated them, thus we do not need
|
||||
// to generate predicates).
|
||||
self.parent
|
||||
.generics
|
||||
.into_hir_generics(ctx, item_id, span)
|
||||
.hir_generics_or_empty()
|
||||
.predicates
|
||||
.into_iter()
|
||||
.chain(
|
||||
self.child
|
||||
.generics
|
||||
.into_hir_generics(ctx, item_id, span)
|
||||
.hir_generics_or_empty()
|
||||
.predicates
|
||||
.into_iter(),
|
||||
)
|
||||
.copied()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'hir> LoweringContext<'_, 'hir> {
|
||||
pub(super) fn lower_delegation_generics(
|
||||
&mut self,
|
||||
delegation: &Delegation,
|
||||
root_fn_id: DefId,
|
||||
item_id: NodeId,
|
||||
span: Span,
|
||||
) -> GenericsGenerationResults<'hir> {
|
||||
let delegation_in_free_ctx = !matches!(
|
||||
self.tcx.def_kind(self.tcx.local_parent(self.local_def_id(item_id))),
|
||||
DefKind::Trait | DefKind::Impl { .. }
|
||||
);
|
||||
|
||||
let root_function_in_trait =
|
||||
matches!(self.tcx.def_kind(self.tcx.parent(root_fn_id)), DefKind::Trait);
|
||||
|
||||
let generate_self = delegation_in_free_ctx && root_function_in_trait;
|
||||
|
||||
let parent_generics_factory = |this: &mut Self, user_specified: bool| {
|
||||
this.get_parent_generics(
|
||||
this.tcx.parent(root_fn_id),
|
||||
generate_self,
|
||||
user_specified,
|
||||
span,
|
||||
)
|
||||
};
|
||||
|
||||
let segments = &delegation.path.segments;
|
||||
let len = segments.len();
|
||||
|
||||
let can_add_generics_to_parent = len >= 2
|
||||
&& self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| {
|
||||
matches!(self.tcx.def_kind(def_id), DefKind::Trait | DefKind::TraitAlias)
|
||||
});
|
||||
|
||||
let parent_generics = if can_add_generics_to_parent {
|
||||
if segments[len - 2].args.is_some() {
|
||||
if generate_self {
|
||||
DelegationGenerics::SelfAndUserSpecified(parent_generics_factory(self, true))
|
||||
} else {
|
||||
DelegationGenerics::UserSpecified
|
||||
}
|
||||
} else {
|
||||
DelegationGenerics::Default(parent_generics_factory(self, false))
|
||||
}
|
||||
} else {
|
||||
DelegationGenerics::Default(None)
|
||||
};
|
||||
|
||||
let child_generics = if segments[len - 1].args.is_some() {
|
||||
DelegationGenerics::UserSpecified
|
||||
} else {
|
||||
DelegationGenerics::Default(self.get_fn_like_generics(root_fn_id, span))
|
||||
};
|
||||
|
||||
GenericsGenerationResults {
|
||||
parent: GenericsGenerationResult::new(parent_generics),
|
||||
child: GenericsGenerationResult::new(child_generics),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_delegation_generic_params(
|
||||
&mut self,
|
||||
item_id: NodeId,
|
||||
span: Span,
|
||||
params: &mut ThinVec<GenericParam>,
|
||||
) -> &'hir hir::Generics<'hir> {
|
||||
for p in params.iter_mut() {
|
||||
// We want to create completely new params, so we generate
|
||||
// a new id, otherwise assertions will be triggered.
|
||||
p.id = self.next_node_id();
|
||||
|
||||
// Remove default params, as they are not supported on functions
|
||||
// and there will duplicate DefId when we try to lower them later.
|
||||
match &mut p.kind {
|
||||
GenericParamKind::Lifetime => {}
|
||||
GenericParamKind::Type { default } => *default = None,
|
||||
GenericParamKind::Const { default, .. } => *default = None,
|
||||
}
|
||||
|
||||
// Note that we use self.disambiguator here, if we will create new every time
|
||||
// we will get ICE if params have the same name.
|
||||
self.resolver.node_id_to_def_id.insert(
|
||||
p.id,
|
||||
self.tcx
|
||||
.create_def(
|
||||
self.resolver.node_id_to_def_id[&item_id],
|
||||
Some(p.ident.name),
|
||||
match p.kind {
|
||||
GenericParamKind::Lifetime => DefKind::LifetimeParam,
|
||||
GenericParamKind::Type { .. } => DefKind::TyParam,
|
||||
GenericParamKind::Const { .. } => DefKind::ConstParam,
|
||||
},
|
||||
None,
|
||||
&mut self.disambiguator,
|
||||
)
|
||||
.def_id(),
|
||||
);
|
||||
}
|
||||
|
||||
// Fallback to default generic param lowering, we modified them in the loop above.
|
||||
let params = self.arena.alloc_from_iter(
|
||||
params.iter().map(|p| self.lower_generic_param(p, hir::GenericParamSource::Generics)),
|
||||
);
|
||||
|
||||
// HACK: for now we generate predicates such that all lifetimes are early bound,
|
||||
// we can not not generate early-bound lifetimes, but we can't know which of them
|
||||
// are late-bound at this level of compilation.
|
||||
// FIXME(fn_delegation): proper support for late bound lifetimes.
|
||||
self.arena.alloc(hir::Generics {
|
||||
params,
|
||||
predicates: self.arena.alloc_from_iter(
|
||||
params
|
||||
.iter()
|
||||
.filter_map(|p| p.is_lifetime().then(|| self.generate_lifetime_predicate(p))),
|
||||
),
|
||||
has_where_clause_predicates: false,
|
||||
where_clause_span: span,
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_lifetime_predicate(
|
||||
&mut self,
|
||||
p: &hir::GenericParam<'hir>,
|
||||
) -> hir::WherePredicate<'hir> {
|
||||
let create_lifetime = |this: &mut Self| -> &'hir hir::Lifetime {
|
||||
this.arena.alloc(hir::Lifetime {
|
||||
hir_id: this.next_id(),
|
||||
ident: p.name.ident(),
|
||||
kind: rustc_hir::LifetimeKind::Param(p.def_id),
|
||||
source: rustc_hir::LifetimeSource::Path {
|
||||
angle_brackets: rustc_hir::AngleBrackets::Full,
|
||||
},
|
||||
syntax: rustc_hir::LifetimeSyntax::ExplicitBound,
|
||||
})
|
||||
};
|
||||
|
||||
hir::WherePredicate {
|
||||
hir_id: self.next_id(),
|
||||
span: DUMMY_SP,
|
||||
kind: self.arena.alloc(hir::WherePredicateKind::RegionPredicate(
|
||||
hir::WhereRegionPredicate {
|
||||
in_where_clause: true,
|
||||
lifetime: create_lifetime(self),
|
||||
bounds: self
|
||||
.arena
|
||||
.alloc_slice(&[hir::GenericBound::Outlives(create_lifetime(self))]),
|
||||
},
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_generics_args_from_params(
|
||||
&mut self,
|
||||
params: &[hir::GenericParam<'hir>],
|
||||
add_lifetimes: bool,
|
||||
span: Span,
|
||||
) -> &'hir hir::GenericArgs<'hir> {
|
||||
self.arena.alloc(hir::GenericArgs {
|
||||
args: self.arena.alloc_from_iter(params.iter().filter_map(|p| {
|
||||
// Skip self generic arg, we do not need to propagate it.
|
||||
if p.name.ident().name == kw::SelfUpper {
|
||||
return None;
|
||||
}
|
||||
|
||||
let create_path = |this: &mut Self| {
|
||||
let res = Res::Def(
|
||||
match p.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
|
||||
hir::GenericParamKind::Type { .. } => DefKind::TyParam,
|
||||
hir::GenericParamKind::Const { .. } => DefKind::ConstParam,
|
||||
},
|
||||
p.def_id.to_def_id(),
|
||||
);
|
||||
|
||||
hir::QPath::Resolved(
|
||||
None,
|
||||
self.arena.alloc(hir::Path {
|
||||
segments: this.arena.alloc_slice(&[hir::PathSegment {
|
||||
args: None,
|
||||
hir_id: this.next_id(),
|
||||
ident: p.name.ident(),
|
||||
infer_args: false,
|
||||
res,
|
||||
}]),
|
||||
res,
|
||||
span: p.span,
|
||||
}),
|
||||
)
|
||||
};
|
||||
|
||||
match p.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => match add_lifetimes {
|
||||
true => Some(hir::GenericArg::Lifetime(self.arena.alloc(hir::Lifetime {
|
||||
hir_id: self.next_id(),
|
||||
ident: p.name.ident(),
|
||||
kind: hir::LifetimeKind::Param(p.def_id),
|
||||
source: hir::LifetimeSource::Path {
|
||||
angle_brackets: hir::AngleBrackets::Full,
|
||||
},
|
||||
syntax: hir::LifetimeSyntax::ExplicitBound,
|
||||
}))),
|
||||
false => None,
|
||||
},
|
||||
hir::GenericParamKind::Type { .. } => {
|
||||
Some(hir::GenericArg::Type(self.arena.alloc(hir::Ty {
|
||||
hir_id: self.next_id(),
|
||||
span: p.span,
|
||||
kind: hir::TyKind::Path(create_path(self)),
|
||||
})))
|
||||
}
|
||||
hir::GenericParamKind::Const { .. } => {
|
||||
Some(hir::GenericArg::Const(self.arena.alloc(hir::ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Path(create_path(self)),
|
||||
span: p.span,
|
||||
})))
|
||||
}
|
||||
}
|
||||
})),
|
||||
constraints: &[],
|
||||
parenthesized: hir::GenericArgsParentheses::No,
|
||||
span_ext: span,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_fn_like_generics(&mut self, id: DefId, span: Span) -> Option<Generics> {
|
||||
if let Some(local_id) = id.as_local() {
|
||||
match self.ast_index.get(local_id) {
|
||||
Some(AstOwner::Item(item)) if let ItemKind::Fn(f) = &item.kind => {
|
||||
Some(f.generics.clone())
|
||||
}
|
||||
Some(AstOwner::AssocItem(item, _)) if let AssocItemKind::Fn(f) = &item.kind => {
|
||||
Some(f.generics.clone())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
self.get_external_generics(id, false, span)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_external_generics(
|
||||
&mut self,
|
||||
id: DefId,
|
||||
processing_parent: bool,
|
||||
span: Span,
|
||||
) -> Option<Generics> {
|
||||
let generics = self.tcx.generics_of(id);
|
||||
if generics.own_params.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Skip first Self parameter if we are in trait, it will be added later.
|
||||
let to_skip = (processing_parent && generics.has_self) as usize;
|
||||
|
||||
Some(Generics {
|
||||
params: generics
|
||||
.own_params
|
||||
.iter()
|
||||
.skip(to_skip)
|
||||
.map(|p| GenericParam {
|
||||
attrs: Default::default(),
|
||||
bounds: Default::default(),
|
||||
colon_span: None,
|
||||
id: self.next_node_id(),
|
||||
ident: Ident::with_dummy_span(p.name),
|
||||
is_placeholder: false,
|
||||
kind: match p.kind {
|
||||
GenericParamDefKind::Lifetime => GenericParamKind::Lifetime,
|
||||
GenericParamDefKind::Type { .. } => {
|
||||
GenericParamKind::Type { default: None }
|
||||
}
|
||||
GenericParamDefKind::Const { .. } => self.map_const_kind(p, span),
|
||||
},
|
||||
})
|
||||
.collect(),
|
||||
where_clause: Default::default(),
|
||||
span: DUMMY_SP,
|
||||
})
|
||||
}
|
||||
|
||||
fn map_const_kind(&mut self, p: &ty::GenericParamDef, span: Span) -> GenericParamKind {
|
||||
let const_type = self.tcx.type_of(p.def_id).instantiate_identity();
|
||||
|
||||
let (type_symbol, res) = match const_type.kind() {
|
||||
ty::Bool => (sym::bool, Res::PrimTy(hir::PrimTy::Bool)),
|
||||
ty::Uint(uint) => (uint.name(), Res::PrimTy(hir::PrimTy::Uint(*uint))),
|
||||
ty::Int(int) => (int.name(), Res::PrimTy(hir::PrimTy::Int(*int))),
|
||||
ty::Char => (sym::char, Res::PrimTy(hir::PrimTy::Char)),
|
||||
_ => {
|
||||
self.tcx
|
||||
.dcx()
|
||||
.span_delayed_bug(span, format!("Unexpected const type: {}", const_type));
|
||||
|
||||
(sym::dummy, Res::Err)
|
||||
}
|
||||
};
|
||||
|
||||
let node_id = self.next_node_id();
|
||||
|
||||
self.resolver.partial_res_map.insert(node_id, hir::def::PartialRes::new(res));
|
||||
|
||||
GenericParamKind::Const {
|
||||
ty: Box::new(Ty {
|
||||
id: node_id,
|
||||
kind: TyKind::Path(
|
||||
None,
|
||||
Path {
|
||||
segments: thin_vec![PathSegment {
|
||||
ident: Ident::with_dummy_span(type_symbol),
|
||||
id: self.next_node_id(),
|
||||
args: None
|
||||
}],
|
||||
span: DUMMY_SP,
|
||||
tokens: None,
|
||||
},
|
||||
),
|
||||
span: DUMMY_SP,
|
||||
tokens: None,
|
||||
}),
|
||||
span: DUMMY_SP,
|
||||
default: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_parent_generics(
|
||||
&mut self,
|
||||
id: DefId,
|
||||
add_self: bool,
|
||||
user_specified: bool,
|
||||
span: Span,
|
||||
) -> Option<Generics> {
|
||||
// If args are user-specified we still maybe need to add self.
|
||||
let mut generics = if user_specified {
|
||||
None
|
||||
} else {
|
||||
if let Some(local_id) = id.as_local() {
|
||||
if let Some(AstOwner::Item(item)) = self.ast_index.get(local_id)
|
||||
&& matches!(item.kind, ItemKind::Trait(..))
|
||||
{
|
||||
item.opt_generics().cloned()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
self.get_external_generics(id, true, span)
|
||||
}
|
||||
};
|
||||
|
||||
if add_self {
|
||||
generics.get_or_insert_default().params.insert(
|
||||
0,
|
||||
GenericParam {
|
||||
id: self.next_node_id(),
|
||||
ident: Ident::new(kw::SelfUpper, DUMMY_SP),
|
||||
attrs: Default::default(),
|
||||
bounds: vec![],
|
||||
is_placeholder: false,
|
||||
kind: GenericParamKind::Type { default: None },
|
||||
colon_span: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
generics
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::msg;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_hir::{HirId, Target, find_attr};
|
||||
@@ -341,12 +340,13 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
|
||||
self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))),
|
||||
),
|
||||
ExprKind::Struct(se) => {
|
||||
let rest = match &se.rest {
|
||||
StructRest::Base(e) => hir::StructTailExpr::Base(self.lower_expr(e)),
|
||||
let rest = match se.rest {
|
||||
StructRest::Base(ref e) => hir::StructTailExpr::Base(self.lower_expr(e)),
|
||||
StructRest::Rest(sp) => {
|
||||
hir::StructTailExpr::DefaultFields(self.lower_span(*sp))
|
||||
hir::StructTailExpr::DefaultFields(self.lower_span(sp))
|
||||
}
|
||||
StructRest::None => hir::StructTailExpr::None,
|
||||
StructRest::NoneWithError(guar) => hir::StructTailExpr::NoneWithError(guar),
|
||||
};
|
||||
hir::ExprKind::Struct(
|
||||
self.arena.alloc(self.lower_qpath(
|
||||
@@ -805,7 +805,7 @@ pub(super) fn maybe_forward_track_caller(
|
||||
) {
|
||||
if self.tcx.features().async_fn_track_caller()
|
||||
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
|
||||
&& find_attr!(*attrs, AttributeKind::TrackCaller(_))
|
||||
&& find_attr!(*attrs, TrackCaller(_))
|
||||
{
|
||||
let unstable_span = self.mark_span_with_reason(
|
||||
DesugaringKind::Async,
|
||||
@@ -1072,8 +1072,7 @@ fn lower_expr_closure(
|
||||
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
||||
|
||||
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
|
||||
|
||||
let mut coroutine_kind = find_attr!(attrs, AttributeKind::Coroutine(_) => hir::CoroutineKind::Coroutine(Movability::Movable));
|
||||
let mut coroutine_kind = find_attr!(attrs, Coroutine(_) => hir::CoroutineKind::Coroutine(Movability::Movable));
|
||||
|
||||
// FIXME(contracts): Support contracts on closures?
|
||||
let body_id = this.lower_fn_body(decl, None, |this| {
|
||||
@@ -1437,7 +1436,7 @@ fn destructure_assign_mut(
|
||||
Some(self.lower_span(e.span))
|
||||
}
|
||||
StructRest::Rest(span) => Some(self.lower_span(*span)),
|
||||
StructRest::None => None,
|
||||
StructRest::None | StructRest::NoneWithError(_) => None,
|
||||
};
|
||||
let struct_pat = hir::PatKind::Struct(qpath, field_pats, fields_omitted);
|
||||
return self.pat_without_dbm(lhs.span, struct_pat);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
pub(super) struct ItemLowerer<'a, 'hir> {
|
||||
pub(super) tcx: TyCtxt<'hir>,
|
||||
pub(super) resolver: &'a mut ResolverAstLowering,
|
||||
pub(super) resolver: &'a mut ResolverAstLowering<'hir>,
|
||||
pub(super) ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
|
||||
pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<'hir>>,
|
||||
}
|
||||
@@ -57,7 +57,7 @@ fn with_lctx(
|
||||
owner: NodeId,
|
||||
f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
|
||||
) {
|
||||
let mut lctx = LoweringContext::new(self.tcx, self.resolver);
|
||||
let mut lctx = LoweringContext::new(self.tcx, self.ast_index, self.resolver);
|
||||
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
||||
|
||||
for (def_id, info) in lctx.children {
|
||||
@@ -243,7 +243,7 @@ fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
|
||||
vis_span,
|
||||
span: self.lower_span(i.span),
|
||||
has_delayed_lints: !self.delayed_lints.is_empty(),
|
||||
eii: find_attr!(attrs, AttributeKind::EiiImpls(..) | AttributeKind::EiiDeclaration(..)),
|
||||
eii: find_attr!(attrs, EiiImpls(..) | EiiDeclaration(..)),
|
||||
};
|
||||
self.arena.alloc(item)
|
||||
}
|
||||
@@ -512,6 +512,8 @@ fn lower_item_kind(
|
||||
constness,
|
||||
is_auto,
|
||||
safety,
|
||||
// FIXME(impl_restrictions): lower to HIR
|
||||
impl_restriction: _,
|
||||
ident,
|
||||
generics,
|
||||
bounds,
|
||||
@@ -707,10 +709,7 @@ fn lower_use_tree(
|
||||
vis_span,
|
||||
span: this.lower_span(use_tree.span),
|
||||
has_delayed_lints: !this.delayed_lints.is_empty(),
|
||||
eii: find_attr!(
|
||||
attrs,
|
||||
AttributeKind::EiiImpls(..) | AttributeKind::EiiDeclaration(..)
|
||||
),
|
||||
eii: find_attr!(attrs, EiiImpls(..) | EiiDeclaration(..)),
|
||||
};
|
||||
hir::OwnerNode::Item(this.arena.alloc(item))
|
||||
});
|
||||
@@ -939,7 +938,7 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
|
||||
);
|
||||
let trait_item_def_id = hir_id.expect_owner();
|
||||
|
||||
let (ident, generics, kind, has_default) = match &i.kind {
|
||||
let (ident, generics, kind, has_value) = match &i.kind {
|
||||
AssocItemKind::Const(box ConstItem {
|
||||
ident,
|
||||
generics,
|
||||
@@ -1088,13 +1087,26 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
|
||||
}
|
||||
};
|
||||
|
||||
let defaultness = match i.kind.defaultness() {
|
||||
// We do not yet support `final` on trait associated items other than functions.
|
||||
// Even though we reject `final` on non-functions during AST validation, we still
|
||||
// need to stop propagating it here because later compiler passes do not expect
|
||||
// and cannot handle such items.
|
||||
Defaultness::Final(..) if !matches!(i.kind, AssocItemKind::Fn(..)) => {
|
||||
Defaultness::Implicit
|
||||
}
|
||||
defaultness => defaultness,
|
||||
};
|
||||
let (defaultness, _) = self
|
||||
.lower_defaultness(defaultness, has_value, || hir::Defaultness::Default { has_value });
|
||||
|
||||
let item = hir::TraitItem {
|
||||
owner_id: trait_item_def_id,
|
||||
ident: self.lower_ident(ident),
|
||||
generics,
|
||||
kind,
|
||||
span: self.lower_span(i.span),
|
||||
defaultness: hir::Defaultness::Default { has_value: has_default },
|
||||
defaultness,
|
||||
has_delayed_lints: !self.delayed_lints.is_empty(),
|
||||
};
|
||||
self.arena.alloc(item)
|
||||
@@ -1122,7 +1134,8 @@ fn lower_trait_impl_header(
|
||||
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
|
||||
// to not cause an assertion failure inside the `lower_defaultness` function.
|
||||
let has_val = true;
|
||||
let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val);
|
||||
let (defaultness, defaultness_span) =
|
||||
self.lower_defaultness(defaultness, has_val, || hir::Defaultness::Final);
|
||||
let modifiers = TraitBoundModifiers {
|
||||
constness: BoundConstness::Never,
|
||||
asyncness: BoundAsyncness::Normal,
|
||||
@@ -1151,7 +1164,8 @@ fn lower_impl_item(
|
||||
) -> &'hir hir::ImplItem<'hir> {
|
||||
// Since `default impl` is not yet implemented, this is always true in impls.
|
||||
let has_value = true;
|
||||
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
|
||||
let (defaultness, _) =
|
||||
self.lower_defaultness(i.kind.defaultness(), has_value, || hir::Defaultness::Final);
|
||||
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
|
||||
let attrs = self.lower_attrs(
|
||||
hir_id,
|
||||
@@ -1304,15 +1318,14 @@ fn lower_defaultness(
|
||||
&self,
|
||||
d: Defaultness,
|
||||
has_value: bool,
|
||||
implicit: impl FnOnce() -> hir::Defaultness,
|
||||
) -> (hir::Defaultness, Option<Span>) {
|
||||
match d {
|
||||
Defaultness::Implicit => (implicit(), None),
|
||||
Defaultness::Default(sp) => {
|
||||
(hir::Defaultness::Default { has_value }, Some(self.lower_span(sp)))
|
||||
}
|
||||
Defaultness::Final => {
|
||||
assert!(has_value);
|
||||
(hir::Defaultness::Final, None)
|
||||
}
|
||||
Defaultness::Final(sp) => (hir::Defaultness::Final, Some(self.lower_span(sp))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1410,9 +1423,7 @@ fn lower_maybe_coroutine_body(
|
||||
// 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 find_attr!(attrs, AttributeKind::RustcIntrinsic)
|
||||
|| this.tcx.is_sdylib_interface_build()
|
||||
{
|
||||
if find_attr!(attrs, RustcIntrinsic) || this.tcx.is_sdylib_interface_build() {
|
||||
let span = this.lower_span(span);
|
||||
let empty_block = hir::Block {
|
||||
hir_id: this.next_id(),
|
||||
@@ -1690,7 +1701,7 @@ pub(super) fn lower_fn_header(
|
||||
let safety = self.lower_safety(h.safety, default_safety);
|
||||
|
||||
// Treat safe `#[target_feature]` functions as unsafe, but also remember that we did so.
|
||||
let safety = if find_attr!(attrs, AttributeKind::TargetFeature { was_forced: false, .. })
|
||||
let safety = if find_attr!(attrs, TargetFeature { was_forced: false, .. })
|
||||
&& safety.is_safe()
|
||||
&& !self.tcx.sess.target.is_like_wasm
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![recursion_limit = "256"]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
use std::mem;
|
||||
@@ -47,7 +47,6 @@
|
||||
use rustc_data_structures::sync::spawn;
|
||||
use rustc_data_structures::tagged_ptr::TaggedRef;
|
||||
use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
|
||||
@@ -90,7 +89,16 @@ macro_rules! arena_vec {
|
||||
|
||||
struct LoweringContext<'a, 'hir> {
|
||||
tcx: TyCtxt<'hir>,
|
||||
resolver: &'a mut ResolverAstLowering,
|
||||
|
||||
// During lowering of delegation we need to access AST of other functions
|
||||
// in order to properly propagate generics, we could have done it at resolve
|
||||
// stage, however it will require either to firstly identify functions that
|
||||
// are being reused and store their generics, or to store generics of all functions
|
||||
// in resolver. This approach helps with those problems, as functions that are reused
|
||||
// will be in AST index.
|
||||
ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
|
||||
|
||||
resolver: &'a mut ResolverAstLowering<'hir>,
|
||||
disambiguator: DisambiguatorState,
|
||||
|
||||
/// Used to allocate HIR nodes.
|
||||
@@ -124,7 +132,7 @@ struct LoweringContext<'a, 'hir> {
|
||||
|
||||
current_hir_id_owner: hir::OwnerId,
|
||||
item_local_id_counter: hir::ItemLocalId,
|
||||
trait_map: ItemLocalMap<Box<[TraitCandidate]>>,
|
||||
trait_map: ItemLocalMap<&'hir [TraitCandidate<'hir>]>,
|
||||
|
||||
impl_trait_defs: Vec<hir::GenericParam<'hir>>,
|
||||
impl_trait_bounds: Vec<hir::WherePredicate<'hir>>,
|
||||
@@ -150,11 +158,16 @@ struct LoweringContext<'a, 'hir> {
|
||||
}
|
||||
|
||||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self {
|
||||
fn new(
|
||||
tcx: TyCtxt<'hir>,
|
||||
ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
|
||||
resolver: &'a mut ResolverAstLowering<'hir>,
|
||||
) -> Self {
|
||||
let registered_tools = tcx.registered_tools(()).iter().map(|x| x.name).collect();
|
||||
Self {
|
||||
// Pseudo-globals.
|
||||
tcx,
|
||||
ast_index,
|
||||
resolver,
|
||||
disambiguator: DisambiguatorState::new(),
|
||||
arena: tcx.hir_arena,
|
||||
@@ -234,7 +247,7 @@ fn lower(&self, span: Span) -> Span {
|
||||
}
|
||||
|
||||
#[extension(trait ResolverAstLoweringExt)]
|
||||
impl ResolverAstLowering {
|
||||
impl ResolverAstLowering<'_> {
|
||||
fn legacy_const_generic_args(&self, expr: &Expr, tcx: TyCtxt<'_>) -> Option<Vec<usize>> {
|
||||
let ExprKind::Path(None, path) = &expr.kind else {
|
||||
return None;
|
||||
@@ -255,10 +268,10 @@ fn legacy_const_generic_args(&self, expr: &Expr, tcx: TyCtxt<'_>) -> Option<Vec<
|
||||
return None;
|
||||
}
|
||||
|
||||
// we can use parsed attrs here since for other crates they're already available
|
||||
find_attr!(
|
||||
// we can use parsed attrs here since for other crates they're already available
|
||||
tcx.get_all_attrs(def_id),
|
||||
AttributeKind::RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes
|
||||
tcx, def_id,
|
||||
RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes
|
||||
)
|
||||
.map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect())
|
||||
}
|
||||
@@ -734,8 +747,8 @@ fn lower_node_id(&mut self, ast_node_id: NodeId) -> HirId {
|
||||
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
|
||||
}
|
||||
|
||||
if let Some(traits) = self.resolver.trait_map.remove(&ast_node_id) {
|
||||
self.trait_map.insert(hir_id.local_id, traits.into_boxed_slice());
|
||||
if let Some(&traits) = self.resolver.trait_map.get(&ast_node_id) {
|
||||
self.trait_map.insert(hir_id.local_id, traits);
|
||||
}
|
||||
|
||||
// Check whether the same `NodeId` is lowered more than once.
|
||||
@@ -1497,6 +1510,13 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> {
|
||||
TyKind::Pat(ty, pat) => {
|
||||
hir::TyKind::Pat(self.lower_ty_alloc(ty, itctx), self.lower_ty_pat(pat, ty.span))
|
||||
}
|
||||
TyKind::FieldOf(ty, variant, field) => hir::TyKind::FieldOf(
|
||||
self.lower_ty_alloc(ty, itctx),
|
||||
self.arena.alloc(hir::TyFieldPath {
|
||||
variant: variant.map(|variant| self.lower_ident(variant)),
|
||||
field: self.lower_ident(*field),
|
||||
}),
|
||||
),
|
||||
TyKind::MacCall(_) => {
|
||||
span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now")
|
||||
}
|
||||
@@ -2522,16 +2542,6 @@ fn lower_expr_to_const_arg_direct(&mut self, expr: &Expr) -> hir::ConstArg<'hir>
|
||||
ExprKind::Block(block, _) => {
|
||||
if let [stmt] = block.stmts.as_slice()
|
||||
&& let StmtKind::Expr(expr) = &stmt.kind
|
||||
&& matches!(
|
||||
expr.kind,
|
||||
ExprKind::Block(..)
|
||||
| ExprKind::Path(..)
|
||||
| ExprKind::Struct(..)
|
||||
| ExprKind::Call(..)
|
||||
| ExprKind::Tup(..)
|
||||
| ExprKind::Array(..)
|
||||
| ExprKind::ConstBlock(..)
|
||||
)
|
||||
{
|
||||
return self.lower_expr_to_const_arg_direct(expr);
|
||||
}
|
||||
@@ -2554,6 +2564,17 @@ fn lower_expr_to_const_arg_direct(&mut self, expr: &Expr) -> hir::ConstArg<'hir>
|
||||
let span = expr.span;
|
||||
let literal = self.lower_lit(literal, span);
|
||||
|
||||
if !matches!(literal.node, LitKind::Int(..)) {
|
||||
let err =
|
||||
self.dcx().struct_span_err(expr.span, "negated literal must be an integer");
|
||||
|
||||
return ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Error(err.emit()),
|
||||
span,
|
||||
};
|
||||
}
|
||||
|
||||
ConstArg {
|
||||
hir_id: self.lower_node_id(expr.id),
|
||||
kind: hir::ConstArgKind::Literal { lit: literal.node, negated: true },
|
||||
|
||||
@@ -112,7 +112,7 @@ pub(crate) fn lower_qpath(
|
||||
}
|
||||
// `a::b::Trait(Args)::TraitItem`
|
||||
Res::Def(DefKind::AssocFn, _)
|
||||
| Res::Def(DefKind::AssocConst, _)
|
||||
| Res::Def(DefKind::AssocConst { .. }, _)
|
||||
| Res::Def(DefKind::AssocTy, _)
|
||||
if i + 2 == proj_start =>
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
|
||||
@@ -65,6 +65,28 @@ fn constness(&self) -> Option<Span> {
|
||||
}
|
||||
}
|
||||
|
||||
enum AllowDefault {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
impl AllowDefault {
|
||||
fn when(b: bool) -> Self {
|
||||
if b { Self::Yes } else { Self::No }
|
||||
}
|
||||
}
|
||||
|
||||
enum AllowFinal {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
impl AllowFinal {
|
||||
fn when(b: bool) -> Self {
|
||||
if b { Self::Yes } else { Self::No }
|
||||
}
|
||||
}
|
||||
|
||||
struct AstValidator<'a> {
|
||||
sess: &'a Session,
|
||||
features: &'a Features,
|
||||
@@ -563,10 +585,32 @@ fn check_fn_ptr_safety(&self, span: Span, safety: Safety) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
|
||||
if let Defaultness::Default(def_span) = defaultness {
|
||||
let span = self.sess.source_map().guess_head_span(span);
|
||||
self.dcx().emit_err(errors::ForbiddenDefault { span, def_span });
|
||||
fn check_defaultness(
|
||||
&self,
|
||||
span: Span,
|
||||
defaultness: Defaultness,
|
||||
allow_default: AllowDefault,
|
||||
allow_final: AllowFinal,
|
||||
) {
|
||||
match defaultness {
|
||||
Defaultness::Default(def_span) if matches!(allow_default, AllowDefault::No) => {
|
||||
let span = self.sess.source_map().guess_head_span(span);
|
||||
self.dcx().emit_err(errors::ForbiddenDefault { span, def_span });
|
||||
}
|
||||
Defaultness::Final(def_span) if matches!(allow_final, AllowFinal::No) => {
|
||||
let span = self.sess.source_map().guess_head_span(span);
|
||||
self.dcx().emit_err(errors::ForbiddenFinal { span, def_span });
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_final_has_body(&self, item: &Item<AssocItemKind>, defaultness: Defaultness) {
|
||||
if let AssocItemKind::Fn(box Fn { body: None, .. }) = &item.kind
|
||||
&& let Defaultness::Final(def_span) = defaultness
|
||||
{
|
||||
let span = self.sess.source_map().guess_head_span(item.span);
|
||||
self.dcx().emit_err(errors::ForbiddenFinalWithoutBody { span, def_span });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -698,13 +742,11 @@ fn check_c_variadic_type(&self, fk: FnKind<'a>, attrs: &'a AttrVec) {
|
||||
unreachable!("C variable argument list cannot be used in closures")
|
||||
};
|
||||
|
||||
// C-variadics are not yet implemented in const evaluation.
|
||||
if let Const::Yes(const_span) = sig.header.constness {
|
||||
self.dcx().emit_err(errors::ConstAndCVariadic {
|
||||
spans: vec![const_span, variadic_param.span],
|
||||
const_span,
|
||||
variadic_span: variadic_param.span,
|
||||
});
|
||||
if let Const::Yes(_) = sig.header.constness
|
||||
&& !self.features.enabled(sym::const_c_variadic)
|
||||
{
|
||||
let msg = format!("c-variadic const function definitions are unstable");
|
||||
feature_err(&self.sess, sym::const_c_variadic, sig.span, msg).emit();
|
||||
}
|
||||
|
||||
if let Some(coroutine_kind) = sig.header.coroutine_kind {
|
||||
@@ -1192,7 +1234,7 @@ fn visit_item(&mut self, item: &'a Item) {
|
||||
},
|
||||
) => {
|
||||
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
|
||||
self.check_defaultness(item.span, *defaultness);
|
||||
self.check_defaultness(item.span, *defaultness, AllowDefault::No, AllowFinal::No);
|
||||
|
||||
for EiiImpl { eii_macro_path, .. } in eii_impls {
|
||||
self.visit_path(eii_macro_path);
|
||||
@@ -1362,7 +1404,7 @@ fn visit_item(&mut self, item: &'a Item) {
|
||||
});
|
||||
}
|
||||
ItemKind::Const(box ConstItem { defaultness, ident, rhs_kind, .. }) => {
|
||||
self.check_defaultness(item.span, *defaultness);
|
||||
self.check_defaultness(item.span, *defaultness, AllowDefault::No, AllowFinal::No);
|
||||
if !rhs_kind.has_expr() {
|
||||
self.dcx().emit_err(errors::ConstWithoutBody {
|
||||
span: item.span,
|
||||
@@ -1400,7 +1442,7 @@ fn visit_item(&mut self, item: &'a Item) {
|
||||
ItemKind::TyAlias(
|
||||
ty_alias @ box TyAlias { defaultness, bounds, after_where_clause, ty, .. },
|
||||
) => {
|
||||
self.check_defaultness(item.span, *defaultness);
|
||||
self.check_defaultness(item.span, *defaultness, AllowDefault::No, AllowFinal::No);
|
||||
if ty.is_none() {
|
||||
self.dcx().emit_err(errors::TyAliasWithoutBody {
|
||||
span: item.span,
|
||||
@@ -1430,7 +1472,7 @@ fn visit_item(&mut self, item: &'a Item) {
|
||||
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
||||
match &fi.kind {
|
||||
ForeignItemKind::Fn(box Fn { defaultness, ident, sig, body, .. }) => {
|
||||
self.check_defaultness(fi.span, *defaultness);
|
||||
self.check_defaultness(fi.span, *defaultness, AllowDefault::No, AllowFinal::No);
|
||||
self.check_foreign_fn_bodyless(*ident, body.as_deref());
|
||||
self.check_foreign_fn_headerless(sig.header);
|
||||
self.check_foreign_item_ascii_only(*ident);
|
||||
@@ -1450,7 +1492,7 @@ fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
||||
ty,
|
||||
..
|
||||
}) => {
|
||||
self.check_defaultness(fi.span, *defaultness);
|
||||
self.check_defaultness(fi.span, *defaultness, AllowDefault::No, AllowFinal::No);
|
||||
self.check_foreign_kind_bodyless(*ident, "type", ty.as_ref().map(|b| b.span));
|
||||
self.check_type_no_bounds(bounds, "`extern` blocks");
|
||||
self.check_foreign_ty_genericless(generics, after_where_clause);
|
||||
@@ -1709,9 +1751,19 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
|
||||
self.check_nomangle_item_asciionly(ident, item.span);
|
||||
}
|
||||
|
||||
if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() {
|
||||
self.check_defaultness(item.span, item.kind.defaultness());
|
||||
}
|
||||
let defaultness = item.kind.defaultness();
|
||||
self.check_defaultness(
|
||||
item.span,
|
||||
defaultness,
|
||||
// `default` is allowed on all associated items in impls.
|
||||
AllowDefault::when(matches!(ctxt, AssocCtxt::Impl { .. })),
|
||||
// `final` is allowed on all associated *functions* in traits.
|
||||
AllowFinal::when(
|
||||
ctxt == AssocCtxt::Trait && matches!(item.kind, AssocItemKind::Fn(..)),
|
||||
),
|
||||
);
|
||||
|
||||
self.check_final_has_body(item, defaultness);
|
||||
|
||||
if let AssocCtxt::Impl { .. } = ctxt {
|
||||
match &item.kind {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use rustc_ast::ParamKindOrd;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@@ -159,6 +159,24 @@ pub(crate) struct ForbiddenDefault {
|
||||
pub def_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("`final` is only allowed on associated functions in traits")]
|
||||
pub(crate) struct ForbiddenFinal {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label("`final` because of this")]
|
||||
pub def_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("`final` is only allowed on associated functions if they have a body")]
|
||||
pub(crate) struct ForbiddenFinalWithoutBody {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label("`final` because of this")]
|
||||
pub def_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("associated constant in `impl` without body")]
|
||||
pub(crate) struct AssocConstWithoutBody {
|
||||
@@ -653,7 +671,7 @@ pub(crate) struct MissingUnsafeOnExtern {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("extern blocks should be unsafe")]
|
||||
pub(crate) struct MissingUnsafeOnExternLint {
|
||||
#[suggestion(
|
||||
@@ -823,17 +841,6 @@ pub(crate) struct ConstAndCoroutine {
|
||||
pub coroutine_kind: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("functions cannot be both `const` and C-variadic")]
|
||||
pub(crate) struct ConstAndCVariadic {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
#[label("`const` because of this")]
|
||||
pub const_span: Span,
|
||||
#[label("C-variadic because of this")]
|
||||
pub variadic_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("functions cannot be both `{$coroutine_kind}` and C-variadic")]
|
||||
pub(crate) struct CoroutineAndCVariadic {
|
||||
@@ -1020,7 +1027,7 @@ pub(crate) struct MissingAbi {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("`extern` declarations without an explicit ABI are deprecated")]
|
||||
pub(crate) struct MissingAbiSugg {
|
||||
#[suggestion(
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::{self as ast, AttrVec, NodeId, PatKind, attr, token};
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
use rustc_errors::msg;
|
||||
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features};
|
||||
use rustc_hir::Attribute;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::parse::{feature_err, feature_warn};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::errors;
|
||||
@@ -427,7 +430,7 @@ fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
|
||||
false
|
||||
}
|
||||
ast::AssocItemKind::Const(box ast::ConstItem {
|
||||
rhs_kind: ast::ConstItemRhsKind::TypeConst { .. },
|
||||
rhs_kind: ast::ConstItemRhsKind::TypeConst { rhs },
|
||||
..
|
||||
}) => {
|
||||
// Make sure this is only allowed if the feature gate is enabled.
|
||||
@@ -438,6 +441,17 @@ fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
|
||||
i.span,
|
||||
"associated `type const` are unstable"
|
||||
);
|
||||
// Make sure associated `type const` defaults in traits are only allowed
|
||||
// if the feature gate is enabled.
|
||||
// #![feature(associated_type_defaults)]
|
||||
if ctxt == AssocCtxt::Trait && rhs.is_some() {
|
||||
gate!(
|
||||
&self,
|
||||
associated_type_defaults,
|
||||
i.span,
|
||||
"associated type defaults are unstable"
|
||||
);
|
||||
}
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
@@ -481,11 +495,6 @@ macro_rules! gate_all {
|
||||
}
|
||||
};
|
||||
}
|
||||
gate_all!(
|
||||
if_let_guard,
|
||||
"`if let` guards are experimental",
|
||||
"you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`"
|
||||
);
|
||||
gate_all!(
|
||||
async_trait_bounds,
|
||||
"`async` trait bounds are unstable",
|
||||
@@ -580,6 +589,8 @@ macro_rules! gate_all {
|
||||
gate_all!(frontmatter, "frontmatters are experimental");
|
||||
gate_all!(coroutines, "coroutine syntax is experimental");
|
||||
gate_all!(const_block_items, "const block items are experimental");
|
||||
gate_all!(final_associated_functions, "`final` on trait functions is experimental");
|
||||
gate_all!(impl_restriction, "`impl` restrictions are experimental");
|
||||
|
||||
if !visitor.features.never_patterns() {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
@@ -640,17 +651,27 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
|
||||
return;
|
||||
}
|
||||
let mut errored = false;
|
||||
for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) {
|
||||
|
||||
if let Some(Attribute::Parsed(AttributeKind::Feature(feature_idents, first_span))) =
|
||||
AttributeParser::parse_limited(
|
||||
sess,
|
||||
&krate.attrs,
|
||||
sym::feature,
|
||||
DUMMY_SP,
|
||||
krate.id,
|
||||
Some(&features),
|
||||
)
|
||||
{
|
||||
// `feature(...)` used on non-nightly. This is definitely an error.
|
||||
let mut err = errors::FeatureOnNonNightly {
|
||||
span: attr.span,
|
||||
span: first_span,
|
||||
channel: option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"),
|
||||
stable_features: vec![],
|
||||
sugg: None,
|
||||
};
|
||||
|
||||
let mut all_stable = true;
|
||||
for ident in attr.meta_item_list().into_iter().flatten().flat_map(|nested| nested.ident()) {
|
||||
for ident in feature_idents {
|
||||
let name = ident.name;
|
||||
let stable_since = features
|
||||
.enabled_lang_features()
|
||||
@@ -665,7 +686,7 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
|
||||
}
|
||||
}
|
||||
if all_stable {
|
||||
err.sugg = Some(attr.span);
|
||||
err.sugg = Some(first_span);
|
||||
}
|
||||
sess.dcx().emit_err(err);
|
||||
errored = true;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(iter_is_partitioned)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
@@ -80,6 +80,10 @@ pub fn vis_to_string(v: &ast::Visibility) -> String {
|
||||
State::new().vis_to_string(v)
|
||||
}
|
||||
|
||||
pub fn impl_restriction_to_string(r: &ast::ImplRestriction) -> String {
|
||||
State::new().impl_restriction_to_string(r)
|
||||
}
|
||||
|
||||
pub fn meta_list_item_to_string(li: &ast::MetaItemInner) -> String {
|
||||
State::new().meta_list_item_to_string(li)
|
||||
}
|
||||
|
||||
@@ -1110,6 +1110,10 @@ fn vis_to_string(&self, v: &ast::Visibility) -> String {
|
||||
Self::to_string(|s| s.print_visibility(v))
|
||||
}
|
||||
|
||||
fn impl_restriction_to_string(&self, r: &ast::ImplRestriction) -> String {
|
||||
Self::to_string(|s| s.print_impl_restriction(r))
|
||||
}
|
||||
|
||||
fn block_to_string(&self, blk: &ast::Block) -> String {
|
||||
Self::to_string(|s| {
|
||||
let (cb, ib) = s.head("");
|
||||
@@ -1377,6 +1381,23 @@ pub fn print_type(&mut self, ty: &ast::Ty) {
|
||||
self.word(" is ");
|
||||
self.print_ty_pat(pat);
|
||||
}
|
||||
ast::TyKind::FieldOf(ty, variant, field) => {
|
||||
self.word("builtin # field_of");
|
||||
self.popen();
|
||||
let ib = self.ibox(0);
|
||||
self.print_type(ty);
|
||||
self.word(",");
|
||||
self.space();
|
||||
|
||||
if let Some(variant) = variant {
|
||||
self.print_ident(*variant);
|
||||
self.word(".");
|
||||
}
|
||||
self.print_ident(*field);
|
||||
|
||||
self.end(ib);
|
||||
self.pclose();
|
||||
}
|
||||
}
|
||||
self.end(ib);
|
||||
}
|
||||
@@ -1394,6 +1415,9 @@ fn print_formal_generic_params(&mut self, generic_params: &[ast::GenericParam])
|
||||
}
|
||||
|
||||
fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
|
||||
if let ast::Parens::Yes = t.parens {
|
||||
self.popen();
|
||||
}
|
||||
self.print_formal_generic_params(&t.bound_generic_params);
|
||||
|
||||
let ast::TraitBoundModifiers { constness, asyncness, polarity } = t.modifiers;
|
||||
@@ -1416,7 +1440,10 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
|
||||
}
|
||||
}
|
||||
|
||||
self.print_trait_ref(&t.trait_ref)
|
||||
self.print_trait_ref(&t.trait_ref);
|
||||
if let ast::Parens::Yes = t.parens {
|
||||
self.pclose();
|
||||
}
|
||||
}
|
||||
|
||||
fn print_stmt(&mut self, st: &ast::Stmt) {
|
||||
|
||||
@@ -162,7 +162,7 @@ fn print_expr_struct(
|
||||
self.word("{");
|
||||
let has_rest = match rest {
|
||||
ast::StructRest::Base(_) | ast::StructRest::Rest(_) => true,
|
||||
ast::StructRest::None => false,
|
||||
ast::StructRest::None | ast::StructRest::NoneWithError(_) => false,
|
||||
};
|
||||
if fields.is_empty() && !has_rest {
|
||||
self.word("}");
|
||||
|
||||
@@ -51,7 +51,7 @@ pub(crate) fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
|
||||
expr.as_deref(),
|
||||
vis,
|
||||
*safety,
|
||||
ast::Defaultness::Final,
|
||||
ast::Defaultness::Implicit,
|
||||
define_opaque.as_deref(),
|
||||
),
|
||||
ast::ForeignItemKind::TyAlias(box ast::TyAlias {
|
||||
@@ -201,7 +201,7 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
|
||||
body.as_deref(),
|
||||
&item.vis,
|
||||
ast::Safety::Default,
|
||||
ast::Defaultness::Final,
|
||||
ast::Defaultness::Implicit,
|
||||
define_opaque.as_deref(),
|
||||
);
|
||||
}
|
||||
@@ -365,6 +365,7 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
|
||||
constness,
|
||||
safety,
|
||||
is_auto,
|
||||
impl_restriction,
|
||||
ident,
|
||||
generics,
|
||||
bounds,
|
||||
@@ -375,6 +376,7 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
|
||||
self.print_constness(*constness);
|
||||
self.print_safety(*safety);
|
||||
self.print_is_auto(*is_auto);
|
||||
self.print_impl_restriction(impl_restriction);
|
||||
self.word_nbsp("trait");
|
||||
self.print_ident(*ident);
|
||||
self.print_generic_params(&generics.params);
|
||||
@@ -483,6 +485,20 @@ pub(crate) fn print_visibility(&mut self, vis: &ast::Visibility) {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn print_impl_restriction(&mut self, impl_restriction: &ast::ImplRestriction) {
|
||||
match &impl_restriction.kind {
|
||||
ast::RestrictionKind::Restricted { path, shorthand, .. } => {
|
||||
let path = Self::to_string(|s| s.print_path(path, false, 0));
|
||||
if *shorthand {
|
||||
self.word_nbsp(format!("impl({path})"))
|
||||
} else {
|
||||
self.word_nbsp(format!("impl(in {path})"))
|
||||
}
|
||||
}
|
||||
ast::RestrictionKind::Unrestricted => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_defaultness(&mut self, defaultness: ast::Defaultness) {
|
||||
if let ast::Defaultness::Default(_) = defaultness {
|
||||
self.word_nbsp("default");
|
||||
|
||||
@@ -15,6 +15,7 @@ rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
rustc_parse_format = { path = "../rustc_parse_format" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
|
||||
@@ -52,8 +52,8 @@ fn extend(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct AllowConstFnUnstableParser;
|
||||
impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
|
||||
pub(crate) struct RustcAllowConstFnUnstableParser;
|
||||
impl<S: Stage> CombineAttributeParser<S> for RustcAllowConstFnUnstableParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable];
|
||||
type Item = Symbol;
|
||||
const CONVERT: ConvertFn<Self::Item> =
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_ast::expand::autodiff_attrs::{DiffActivity, DiffMode};
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_hir::attrs::{AttributeKind, RustcAutodiff};
|
||||
use rustc_hir::{MethodKind, Target};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::attributes::prelude::Allow;
|
||||
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::parser::{ArgParser, MetaItemOrLitParser};
|
||||
use crate::target_checking::AllowedTargets;
|
||||
|
||||
pub(crate) struct RustcAutodiffParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcAutodiffParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_autodiff];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
]);
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
List: &["MODE", "WIDTH", "INPUT_ACTIVITIES", "OUTPUT_ACTIVITY"],
|
||||
"https://doc.rust-lang.org/std/autodiff/index.html"
|
||||
);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
let list = match args {
|
||||
ArgParser::NoArgs => return Some(AttributeKind::RustcAutodiff(None)),
|
||||
ArgParser::List(list) => list,
|
||||
ArgParser::NameValue(_) => {
|
||||
cx.expected_list_or_no_args(cx.attr_span);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let mut items = list.mixed().peekable();
|
||||
|
||||
// Parse name
|
||||
let Some(mode) = items.next() else {
|
||||
cx.expected_at_least_one_argument(list.span);
|
||||
return None;
|
||||
};
|
||||
let Some(mode) = mode.meta_item() else {
|
||||
cx.expected_identifier(mode.span());
|
||||
return None;
|
||||
};
|
||||
let Ok(()) = mode.args().no_args() else {
|
||||
cx.expected_identifier(mode.span());
|
||||
return None;
|
||||
};
|
||||
let Some(mode) = mode.path().word() else {
|
||||
cx.expected_identifier(mode.span());
|
||||
return None;
|
||||
};
|
||||
let Ok(mode) = DiffMode::from_str(mode.as_str()) else {
|
||||
cx.expected_specific_argument(mode.span, DiffMode::all_modes());
|
||||
return None;
|
||||
};
|
||||
|
||||
// Parse width
|
||||
let width = if let Some(width) = items.peek()
|
||||
&& let MetaItemOrLitParser::Lit(width) = width
|
||||
&& let LitKind::Int(width, _) = width.kind
|
||||
&& let Ok(width) = width.0.try_into()
|
||||
{
|
||||
_ = items.next();
|
||||
width
|
||||
} else {
|
||||
1
|
||||
};
|
||||
|
||||
// Parse activities
|
||||
let mut activities = ThinVec::new();
|
||||
for activity in items {
|
||||
let MetaItemOrLitParser::MetaItemParser(activity) = activity else {
|
||||
cx.expected_specific_argument(activity.span(), DiffActivity::all_activities());
|
||||
return None;
|
||||
};
|
||||
let Ok(()) = activity.args().no_args() else {
|
||||
cx.expected_specific_argument(activity.span(), DiffActivity::all_activities());
|
||||
return None;
|
||||
};
|
||||
let Some(activity) = activity.path().word() else {
|
||||
cx.expected_specific_argument(activity.span(), DiffActivity::all_activities());
|
||||
return None;
|
||||
};
|
||||
let Ok(activity) = DiffActivity::from_str(activity.as_str()) else {
|
||||
cx.expected_specific_argument(activity.span, DiffActivity::all_activities());
|
||||
return None;
|
||||
};
|
||||
|
||||
activities.push(activity);
|
||||
}
|
||||
let Some(ret_activity) = activities.pop() else {
|
||||
cx.expected_specific_argument(
|
||||
list.span.with_lo(list.span.hi()),
|
||||
DiffActivity::all_activities(),
|
||||
);
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(AttributeKind::RustcAutodiff(Some(Box::new(RustcAutodiff {
|
||||
mode,
|
||||
width,
|
||||
input_activity: activities,
|
||||
ret_activity,
|
||||
}))))
|
||||
}
|
||||
}
|
||||
@@ -128,20 +128,14 @@ pub fn parse_cfg_select(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(features) = features
|
||||
&& features.enabled(sym::cfg_select)
|
||||
{
|
||||
let it = branches
|
||||
.reachable
|
||||
.iter()
|
||||
.map(|(entry, _, _)| CfgSelectPredicate::Cfg(entry.clone()))
|
||||
.chain(branches.wildcard.as_ref().map(|(t, _, _)| CfgSelectPredicate::Wildcard(*t)))
|
||||
.chain(
|
||||
branches.unreachable.iter().map(|(entry, _, _)| CfgSelectPredicate::clone(entry)),
|
||||
);
|
||||
let it = branches
|
||||
.reachable
|
||||
.iter()
|
||||
.map(|(entry, _, _)| CfgSelectPredicate::Cfg(entry.clone()))
|
||||
.chain(branches.wildcard.as_ref().map(|(t, _, _)| CfgSelectPredicate::Wildcard(*t)))
|
||||
.chain(branches.unreachable.iter().map(|(entry, _, _)| CfgSelectPredicate::clone(entry)));
|
||||
|
||||
lint_unreachable(p, it, lint_node_id);
|
||||
}
|
||||
lint_unreachable(p, it, lint_node_id);
|
||||
|
||||
Ok(branches)
|
||||
}
|
||||
|
||||
@@ -153,9 +153,9 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ObjcClassParser;
|
||||
pub(crate) struct RustcObjcClassParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for ObjcClassParser {
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcObjcClassParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_class];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
@@ -185,9 +185,9 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ObjcSelectorParser;
|
||||
pub(crate) struct RustcObjcSelectorParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for ObjcSelectorParser {
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcObjcSelectorParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_selector];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
@@ -709,13 +709,13 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcPassIndirectlyInNonRusticAbisPa
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassIndirectlyInNonRusticAbis;
|
||||
}
|
||||
|
||||
pub(crate) struct EiiForeignItemParser;
|
||||
pub(crate) struct RustcEiiForeignItemParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for EiiForeignItemParser {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcEiiForeignItemParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_eii_foreign_item];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::EiiForeignItem;
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEiiForeignItem;
|
||||
}
|
||||
|
||||
pub(crate) struct PatchableFunctionEntryParser;
|
||||
|
||||
@@ -292,3 +292,105 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcNoImplicitBoundsParser {
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds;
|
||||
}
|
||||
|
||||
pub(crate) struct DefaultLibAllocatorParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for DefaultLibAllocatorParser {
|
||||
const PATH: &[Symbol] = &[sym::default_lib_allocator];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::DefaultLibAllocator;
|
||||
}
|
||||
|
||||
pub(crate) struct FeatureParser;
|
||||
|
||||
impl<S: Stage> CombineAttributeParser<S> for FeatureParser {
|
||||
const PATH: &[Symbol] = &[sym::feature];
|
||||
type Item = Ident;
|
||||
const CONVERT: ConvertFn<Self::Item> = AttributeKind::Feature;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["feature1, feature2, ..."]);
|
||||
|
||||
fn extend(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
let ArgParser::List(list) = args else {
|
||||
cx.expected_list(cx.attr_span, args);
|
||||
return Vec::new();
|
||||
};
|
||||
|
||||
if list.is_empty() {
|
||||
cx.warn_empty_attribute(cx.attr_span);
|
||||
}
|
||||
|
||||
let mut res = Vec::new();
|
||||
|
||||
for elem in list.mixed() {
|
||||
let Some(elem) = elem.meta_item() else {
|
||||
cx.expected_identifier(elem.span());
|
||||
continue;
|
||||
};
|
||||
if let Err(arg_span) = elem.args().no_args() {
|
||||
cx.expected_no_args(arg_span);
|
||||
continue;
|
||||
}
|
||||
|
||||
let path = elem.path();
|
||||
let Some(ident) = path.word() else {
|
||||
cx.expected_identifier(path.span());
|
||||
continue;
|
||||
};
|
||||
res.push(ident);
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RegisterToolParser;
|
||||
|
||||
impl<S: Stage> CombineAttributeParser<S> for RegisterToolParser {
|
||||
const PATH: &[Symbol] = &[sym::register_tool];
|
||||
type Item = Ident;
|
||||
const CONVERT: ConvertFn<Self::Item> = AttributeKind::RegisterTool;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["tool1, tool2, ..."]);
|
||||
|
||||
fn extend(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
let ArgParser::List(list) = args else {
|
||||
cx.expected_list(cx.attr_span, args);
|
||||
return Vec::new();
|
||||
};
|
||||
|
||||
if list.is_empty() {
|
||||
cx.warn_empty_attribute(cx.attr_span);
|
||||
}
|
||||
|
||||
let mut res = Vec::new();
|
||||
|
||||
for elem in list.mixed() {
|
||||
let Some(elem) = elem.meta_item() else {
|
||||
cx.expected_identifier(elem.span());
|
||||
continue;
|
||||
};
|
||||
if let Err(arg_span) = elem.args().no_args() {
|
||||
cx.expected_no_args(arg_span);
|
||||
continue;
|
||||
}
|
||||
|
||||
let path = elem.path();
|
||||
let Some(ident) = path.word() else {
|
||||
cx.expected_identifier(path.span());
|
||||
continue;
|
||||
};
|
||||
|
||||
res.push(ident);
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
DeprecatedItemSuggestion, InvalidSince, MissingNote, MissingSince,
|
||||
};
|
||||
|
||||
pub(crate) struct DeprecationParser;
|
||||
|
||||
fn get<S: Stage>(
|
||||
cx: &AcceptContext<'_, '_, S>,
|
||||
name: Symbol,
|
||||
@@ -33,7 +31,8 @@ fn get<S: Stage>(
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
|
||||
pub(crate) struct DeprecatedParser;
|
||||
impl<S: Stage> SingleAttributeParser<S> for DeprecatedParser {
|
||||
const PATH: &[Symbol] = &[sym::deprecated];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
@@ -164,7 +163,7 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(AttributeKind::Deprecation {
|
||||
Some(AttributeKind::Deprecated {
|
||||
deprecation: Deprecation { since, note, suggestion },
|
||||
span: cx.attr_span,
|
||||
})
|
||||
|
||||
@@ -0,0 +1,536 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use rustc_errors::E0232;
|
||||
use rustc_hir::AttrPath;
|
||||
use rustc_hir::attrs::diagnostic::{
|
||||
AppendConstMessage, Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg,
|
||||
Name, NameValue, OnUnimplementedCondition, Piece, Predicate,
|
||||
};
|
||||
use rustc_hir::lints::{AttributeLintKind, FormatWarning};
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_parse_format::{
|
||||
Argument, FormatSpec, ParseError, ParseMode, Parser, Piece as RpfPiece, Position,
|
||||
};
|
||||
use rustc_session::lint::builtin::{
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
|
||||
};
|
||||
use rustc_span::{Ident, InnerSpan, Span, Symbol, kw, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser};
|
||||
|
||||
pub(crate) mod do_not_recommend;
|
||||
pub(crate) mod on_const;
|
||||
pub(crate) mod on_unimplemented;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) enum Mode {
|
||||
/// `#[rustc_on_unimplemented]`
|
||||
RustcOnUnimplemented,
|
||||
/// `#[diagnostic::on_unimplemented]`
|
||||
DiagnosticOnUnimplemented,
|
||||
/// `#[diagnostic::on_const]`
|
||||
DiagnosticOnConst,
|
||||
}
|
||||
|
||||
fn merge_directives<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
first: &mut Option<(Span, Directive)>,
|
||||
later: (Span, Directive),
|
||||
) {
|
||||
if let Some((_, first)) = first {
|
||||
if first.is_rustc_attr || later.1.is_rustc_attr {
|
||||
cx.emit_err(DupesNotAllowed);
|
||||
}
|
||||
|
||||
merge(cx, &mut first.message, later.1.message, sym::message);
|
||||
merge(cx, &mut first.label, later.1.label, sym::label);
|
||||
first.notes.extend(later.1.notes);
|
||||
} else {
|
||||
*first = Some(later);
|
||||
}
|
||||
}
|
||||
|
||||
fn merge<T, S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
first: &mut Option<(Span, T)>,
|
||||
later: Option<(Span, T)>,
|
||||
option_name: Symbol,
|
||||
) {
|
||||
match (first, later) {
|
||||
(Some(_) | None, None) => {}
|
||||
(Some((first_span, _)), Some((later_span, _))) => {
|
||||
cx.emit_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::IgnoredDiagnosticOption {
|
||||
first_span: *first_span,
|
||||
later_span,
|
||||
option_name,
|
||||
},
|
||||
later_span,
|
||||
);
|
||||
}
|
||||
(first @ None, Some(later)) => {
|
||||
first.get_or_insert(later);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_directive_items<'p, S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
mode: Mode,
|
||||
items: impl Iterator<Item = &'p MetaItemOrLitParser>,
|
||||
is_root: bool,
|
||||
) -> Option<Directive> {
|
||||
let condition = None;
|
||||
let mut message: Option<(Span, _)> = None;
|
||||
let mut label: Option<(Span, _)> = None;
|
||||
let mut notes = ThinVec::new();
|
||||
let mut parent_label = None;
|
||||
let mut subcommands = ThinVec::new();
|
||||
let mut append_const_msg = None;
|
||||
|
||||
for item in items {
|
||||
let span = item.span();
|
||||
|
||||
macro malformed() {{
|
||||
match mode {
|
||||
Mode::RustcOnUnimplemented => {
|
||||
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
|
||||
}
|
||||
Mode::DiagnosticOnUnimplemented => {
|
||||
cx.emit_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedOnUnimplementedAttr { span },
|
||||
span,
|
||||
);
|
||||
}
|
||||
Mode::DiagnosticOnConst => {
|
||||
cx.emit_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedOnConstAttr { span },
|
||||
span,
|
||||
);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}}
|
||||
|
||||
macro or_malformed($($code:tt)*) {{
|
||||
let Some(ret) = (||{
|
||||
Some($($code)*)
|
||||
})() else {
|
||||
|
||||
malformed!()
|
||||
};
|
||||
ret
|
||||
}}
|
||||
|
||||
macro duplicate($name: ident, $($first_span:tt)*) {{
|
||||
match mode {
|
||||
Mode::RustcOnUnimplemented => {
|
||||
cx.emit_err(NoValueInOnUnimplemented { span: item.span() });
|
||||
}
|
||||
Mode::DiagnosticOnUnimplemented |Mode::DiagnosticOnConst => {
|
||||
cx.emit_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::IgnoredDiagnosticOption {
|
||||
first_span: $($first_span)*,
|
||||
later_span: span,
|
||||
option_name: $name,
|
||||
},
|
||||
span,
|
||||
);
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
let item: &MetaItemParser = or_malformed!(item.meta_item()?);
|
||||
let name = or_malformed!(item.ident()?).name;
|
||||
|
||||
// Some things like `message = "message"` must have a value.
|
||||
// But with things like `append_const_msg` that is optional.
|
||||
let value: Option<Ident> = match item.args().name_value() {
|
||||
Some(nv) => Some(or_malformed!(nv.value_as_ident()?)),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let mut parse_format = |input: Ident| {
|
||||
let snippet = cx.sess.source_map().span_to_snippet(input.span).ok();
|
||||
let is_snippet = snippet.is_some();
|
||||
match parse_format_string(input.name, snippet, input.span, mode) {
|
||||
Ok((f, warnings)) => {
|
||||
for warning in warnings {
|
||||
let (FormatWarning::InvalidSpecifier { span, .. }
|
||||
| FormatWarning::PositionalArgument { span, .. }) = warning;
|
||||
cx.emit_lint(
|
||||
MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
|
||||
AttributeLintKind::MalformedDiagnosticFormat { warning },
|
||||
span,
|
||||
);
|
||||
}
|
||||
|
||||
f
|
||||
}
|
||||
Err(e) => {
|
||||
cx.emit_lint(
|
||||
MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
|
||||
AttributeLintKind::DiagnosticWrappedParserError {
|
||||
description: e.description,
|
||||
label: e.label,
|
||||
span: slice_span(input.span, e.span, is_snippet),
|
||||
},
|
||||
input.span,
|
||||
);
|
||||
// We could not parse the input, just use it as-is.
|
||||
FormatString {
|
||||
input: input.name,
|
||||
span: input.span,
|
||||
pieces: thin_vec![Piece::Lit(input.name)],
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
match (mode, name) {
|
||||
(_, sym::message) => {
|
||||
let value = or_malformed!(value?);
|
||||
if let Some(message) = &message {
|
||||
duplicate!(name, message.0)
|
||||
} else {
|
||||
message = Some((item.span(), parse_format(value)));
|
||||
}
|
||||
}
|
||||
(_, sym::label) => {
|
||||
let value = or_malformed!(value?);
|
||||
if let Some(label) = &label {
|
||||
duplicate!(name, label.0)
|
||||
} else {
|
||||
label = Some((item.span(), parse_format(value)));
|
||||
}
|
||||
}
|
||||
(_, sym::note) => {
|
||||
let value = or_malformed!(value?);
|
||||
notes.push(parse_format(value))
|
||||
}
|
||||
|
||||
(Mode::RustcOnUnimplemented, sym::append_const_msg) => {
|
||||
append_const_msg = if let Some(msg) = value {
|
||||
Some(AppendConstMessage::Custom(msg.name, item.span()))
|
||||
} else {
|
||||
Some(AppendConstMessage::Default)
|
||||
}
|
||||
}
|
||||
(Mode::RustcOnUnimplemented, sym::parent_label) => {
|
||||
let value = or_malformed!(value?);
|
||||
if parent_label.is_none() {
|
||||
parent_label = Some(parse_format(value));
|
||||
} else {
|
||||
duplicate!(name, span)
|
||||
}
|
||||
}
|
||||
(Mode::RustcOnUnimplemented, sym::on) => {
|
||||
if is_root {
|
||||
let items = or_malformed!(item.args().list()?);
|
||||
let mut iter = items.mixed();
|
||||
let condition: &MetaItemOrLitParser = match iter.next() {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
cx.emit_err(InvalidOnClause::Empty { span });
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let condition = parse_condition(condition);
|
||||
|
||||
if items.len() < 2 {
|
||||
// Something like `#[rustc_on_unimplemented(on(.., /* nothing */))]`
|
||||
// There's a condition but no directive behind it, this is a mistake.
|
||||
malformed!();
|
||||
}
|
||||
|
||||
let mut directive =
|
||||
or_malformed!(parse_directive_items(cx, mode, iter, false)?);
|
||||
|
||||
match condition {
|
||||
Ok(c) => {
|
||||
directive.condition = Some(c);
|
||||
subcommands.push(directive);
|
||||
}
|
||||
Err(e) => {
|
||||
cx.emit_err(e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
malformed!();
|
||||
}
|
||||
}
|
||||
|
||||
_other => {
|
||||
malformed!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(Directive {
|
||||
is_rustc_attr: matches!(mode, Mode::RustcOnUnimplemented),
|
||||
condition,
|
||||
subcommands,
|
||||
message,
|
||||
label,
|
||||
notes,
|
||||
parent_label,
|
||||
append_const_msg,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn parse_format_string(
|
||||
input: Symbol,
|
||||
snippet: Option<String>,
|
||||
span: Span,
|
||||
mode: Mode,
|
||||
) -> Result<(FormatString, Vec<FormatWarning>), ParseError> {
|
||||
let s = input.as_str();
|
||||
let mut parser = Parser::new(s, None, snippet, false, ParseMode::Diagnostic);
|
||||
let pieces: Vec<_> = parser.by_ref().collect();
|
||||
|
||||
if let Some(err) = parser.errors.into_iter().next() {
|
||||
return Err(err);
|
||||
}
|
||||
let mut warnings = Vec::new();
|
||||
|
||||
let pieces = pieces
|
||||
.into_iter()
|
||||
.map(|piece| match piece {
|
||||
RpfPiece::Lit(lit) => Piece::Lit(Symbol::intern(lit)),
|
||||
RpfPiece::NextArgument(arg) => {
|
||||
warn_on_format_spec(&arg.format, &mut warnings, span, parser.is_source_literal);
|
||||
let arg = parse_arg(&arg, mode, &mut warnings, span, parser.is_source_literal);
|
||||
Piece::Arg(arg)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok((FormatString { input, pieces, span }, warnings))
|
||||
}
|
||||
|
||||
fn parse_arg(
|
||||
arg: &Argument<'_>,
|
||||
mode: Mode,
|
||||
warnings: &mut Vec<FormatWarning>,
|
||||
input_span: Span,
|
||||
is_source_literal: bool,
|
||||
) -> FormatArg {
|
||||
let span = slice_span(input_span, arg.position_span.clone(), is_source_literal);
|
||||
|
||||
match arg.position {
|
||||
// Something like "hello {name}"
|
||||
Position::ArgumentNamed(name) => match (mode, Symbol::intern(name)) {
|
||||
// Only `#[rustc_on_unimplemented]` can use these
|
||||
(Mode::RustcOnUnimplemented { .. }, sym::ItemContext) => FormatArg::ItemContext,
|
||||
(Mode::RustcOnUnimplemented { .. }, sym::This) => FormatArg::This,
|
||||
(Mode::RustcOnUnimplemented { .. }, sym::Trait) => FormatArg::Trait,
|
||||
// Any attribute can use these
|
||||
(_, kw::SelfUpper) => FormatArg::SelfUpper,
|
||||
(_, generic_param) => FormatArg::GenericParam { generic_param, span },
|
||||
},
|
||||
|
||||
// `{:1}` and `{}` are ignored
|
||||
Position::ArgumentIs(idx) => {
|
||||
warnings.push(FormatWarning::PositionalArgument {
|
||||
span,
|
||||
help: format!("use `{{{idx}}}` to print a number in braces"),
|
||||
});
|
||||
FormatArg::AsIs(Symbol::intern(&format!("{{{idx}}}")))
|
||||
}
|
||||
Position::ArgumentImplicitlyIs(_) => {
|
||||
warnings.push(FormatWarning::PositionalArgument {
|
||||
span,
|
||||
help: String::from("use `{{}}` to print empty braces"),
|
||||
});
|
||||
FormatArg::AsIs(sym::empty_braces)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `#[rustc_on_unimplemented]` and `#[diagnostic::...]` don't actually do anything
|
||||
/// with specifiers, so emit a warning if they are used.
|
||||
fn warn_on_format_spec(
|
||||
spec: &FormatSpec<'_>,
|
||||
warnings: &mut Vec<FormatWarning>,
|
||||
input_span: Span,
|
||||
is_source_literal: bool,
|
||||
) {
|
||||
if spec.ty != "" {
|
||||
let span = spec
|
||||
.ty_span
|
||||
.as_ref()
|
||||
.map(|inner| slice_span(input_span, inner.clone(), is_source_literal))
|
||||
.unwrap_or(input_span);
|
||||
warnings.push(FormatWarning::InvalidSpecifier { span, name: spec.ty.into() })
|
||||
}
|
||||
}
|
||||
|
||||
fn slice_span(input: Span, Range { start, end }: Range<usize>, is_source_literal: bool) -> Span {
|
||||
if is_source_literal { input.from_inner(InnerSpan { start, end }) } else { input }
|
||||
}
|
||||
|
||||
pub(crate) fn parse_condition(
|
||||
input: &MetaItemOrLitParser,
|
||||
) -> Result<OnUnimplementedCondition, InvalidOnClause> {
|
||||
let span = input.span();
|
||||
let pred = parse_predicate(input)?;
|
||||
Ok(OnUnimplementedCondition { span, pred })
|
||||
}
|
||||
|
||||
fn parse_predicate(input: &MetaItemOrLitParser) -> Result<Predicate, InvalidOnClause> {
|
||||
let Some(meta_item) = input.meta_item() else {
|
||||
return Err(InvalidOnClause::UnsupportedLiteral { span: input.span() });
|
||||
};
|
||||
|
||||
let Some(predicate) = meta_item.ident() else {
|
||||
return Err(InvalidOnClause::ExpectedIdentifier {
|
||||
span: meta_item.path().span(),
|
||||
path: meta_item.path().get_attribute_path(),
|
||||
});
|
||||
};
|
||||
|
||||
match meta_item.args() {
|
||||
ArgParser::List(mis) => match predicate.name {
|
||||
sym::any => Ok(Predicate::Any(parse_predicate_sequence(mis)?)),
|
||||
sym::all => Ok(Predicate::All(parse_predicate_sequence(mis)?)),
|
||||
sym::not => {
|
||||
if let Some(single) = mis.single() {
|
||||
Ok(Predicate::Not(Box::new(parse_predicate(single)?)))
|
||||
} else {
|
||||
Err(InvalidOnClause::ExpectedOnePredInNot { span: mis.span })
|
||||
}
|
||||
}
|
||||
invalid_pred => {
|
||||
Err(InvalidOnClause::InvalidPredicate { span: predicate.span, invalid_pred })
|
||||
}
|
||||
},
|
||||
ArgParser::NameValue(p) => {
|
||||
let Some(value) = p.value_as_ident() else {
|
||||
return Err(InvalidOnClause::UnsupportedLiteral { span: p.args_span() });
|
||||
};
|
||||
let name = parse_name(predicate.name);
|
||||
let value = parse_filter(value.name);
|
||||
let kv = NameValue { name, value };
|
||||
Ok(Predicate::Match(kv))
|
||||
}
|
||||
ArgParser::NoArgs => {
|
||||
let flag = parse_flag(predicate)?;
|
||||
Ok(Predicate::Flag(flag))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_predicate_sequence(
|
||||
sequence: &MetaItemListParser,
|
||||
) -> Result<ThinVec<Predicate>, InvalidOnClause> {
|
||||
sequence.mixed().map(parse_predicate).collect()
|
||||
}
|
||||
|
||||
fn parse_flag(Ident { name, span }: Ident) -> Result<Flag, InvalidOnClause> {
|
||||
match name {
|
||||
sym::crate_local => Ok(Flag::CrateLocal),
|
||||
sym::direct => Ok(Flag::Direct),
|
||||
sym::from_desugaring => Ok(Flag::FromDesugaring),
|
||||
invalid_flag => Err(InvalidOnClause::InvalidFlag { invalid_flag, span }),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_name(name: Symbol) -> Name {
|
||||
match name {
|
||||
kw::SelfUpper => Name::SelfUpper,
|
||||
sym::from_desugaring => Name::FromDesugaring,
|
||||
sym::cause => Name::Cause,
|
||||
generic => Name::GenericArg(generic),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_filter(input: Symbol) -> FilterFormatString {
|
||||
let pieces = Parser::new(input.as_str(), None, None, false, ParseMode::Diagnostic)
|
||||
.map(|p| match p {
|
||||
RpfPiece::Lit(s) => LitOrArg::Lit(Symbol::intern(s)),
|
||||
// We just ignore formatspecs here
|
||||
RpfPiece::NextArgument(a) => match a.position {
|
||||
// In `TypeErrCtxt::on_unimplemented_note` we substitute `"{integral}"` even
|
||||
// if the integer type has been resolved, to allow targeting all integers.
|
||||
// `"{integer}"` and `"{float}"` come from numerics that haven't been inferred yet,
|
||||
// from the `Display` impl of `InferTy` to be precise.
|
||||
//
|
||||
// Don't try to format these later!
|
||||
Position::ArgumentNamed(arg @ ("integer" | "integral" | "float")) => {
|
||||
LitOrArg::Lit(Symbol::intern(&format!("{{{arg}}}")))
|
||||
}
|
||||
|
||||
Position::ArgumentNamed(arg) => LitOrArg::Arg(Symbol::intern(arg)),
|
||||
Position::ArgumentImplicitlyIs(_) => LitOrArg::Lit(sym::empty_braces),
|
||||
Position::ArgumentIs(idx) => LitOrArg::Lit(Symbol::intern(&format!("{{{idx}}}"))),
|
||||
},
|
||||
})
|
||||
.collect();
|
||||
FilterFormatString { pieces }
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
pub(crate) enum InvalidOnClause {
|
||||
#[diag("empty `on`-clause in `#[rustc_on_unimplemented]`", code = E0232)]
|
||||
Empty {
|
||||
#[primary_span]
|
||||
#[label("empty `on`-clause here")]
|
||||
span: Span,
|
||||
},
|
||||
#[diag("expected a single predicate in `not(..)`", code = E0232)]
|
||||
ExpectedOnePredInNot {
|
||||
#[primary_span]
|
||||
#[label("unexpected quantity of predicates here")]
|
||||
span: Span,
|
||||
},
|
||||
#[diag("literals inside `on`-clauses are not supported", code = E0232)]
|
||||
UnsupportedLiteral {
|
||||
#[primary_span]
|
||||
#[label("unexpected literal here")]
|
||||
span: Span,
|
||||
},
|
||||
#[diag("expected an identifier inside this `on`-clause", code = E0232)]
|
||||
ExpectedIdentifier {
|
||||
#[primary_span]
|
||||
#[label("expected an identifier here, not `{$path}`")]
|
||||
span: Span,
|
||||
path: AttrPath,
|
||||
},
|
||||
#[diag("this predicate is invalid", code = E0232)]
|
||||
InvalidPredicate {
|
||||
#[primary_span]
|
||||
#[label("expected one of `any`, `all` or `not` here, not `{$invalid_pred}`")]
|
||||
span: Span,
|
||||
invalid_pred: Symbol,
|
||||
},
|
||||
#[diag("invalid flag in `on`-clause", code = E0232)]
|
||||
InvalidFlag {
|
||||
#[primary_span]
|
||||
#[label(
|
||||
"expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}`"
|
||||
)]
|
||||
span: Span,
|
||||
invalid_flag: Symbol,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("this attribute must have a value", code = E0232)]
|
||||
#[note("e.g. `#[rustc_on_unimplemented(message=\"foo\")]`")]
|
||||
pub(crate) struct NoValueInOnUnimplemented {
|
||||
#[primary_span]
|
||||
#[label("expected value here")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(
|
||||
"using multiple `rustc_on_unimplemented` (or mixing it with `diagnostic::on_unimplemented`) is not supported"
|
||||
)]
|
||||
pub(crate) struct DupesNotAllowed;
|
||||
@@ -0,0 +1,65 @@
|
||||
use rustc_hir::attrs::diagnostic::Directive;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES;
|
||||
|
||||
use crate::attributes::diagnostic::*;
|
||||
use crate::attributes::prelude::*;
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct OnConstParser {
|
||||
span: Option<Span>,
|
||||
directive: Option<(Span, Directive)>,
|
||||
}
|
||||
|
||||
impl<S: Stage> AttributeParser<S> for OnConstParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
|
||||
&[sym::diagnostic, sym::on_const],
|
||||
template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]),
|
||||
|this, cx, args| {
|
||||
if !cx.features().diagnostic_on_const() {
|
||||
return;
|
||||
}
|
||||
|
||||
let span = cx.attr_span;
|
||||
this.span = Some(span);
|
||||
|
||||
let items = match args {
|
||||
ArgParser::List(items) if items.len() != 0 => items,
|
||||
ArgParser::NoArgs | ArgParser::List(_) => {
|
||||
cx.emit_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::MissingOptionsForOnConst,
|
||||
span,
|
||||
);
|
||||
return;
|
||||
}
|
||||
ArgParser::NameValue(_) => {
|
||||
cx.emit_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedOnConstAttr { span },
|
||||
span,
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let Some(directive) =
|
||||
parse_directive_items(cx, Mode::DiagnosticOnConst, items.mixed(), true)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
merge_directives(cx, &mut this.directive, (span, directive));
|
||||
},
|
||||
)];
|
||||
|
||||
//FIXME Still checked in `check_attr.rs`
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
if let Some(span) = self.span {
|
||||
Some(AttributeKind::OnConst { span, directive: self.directive.map(|d| Box::new(d.1)) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
use rustc_hir::attrs::diagnostic::Directive;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES;
|
||||
|
||||
use crate::attributes::diagnostic::*;
|
||||
use crate::attributes::prelude::*;
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct OnUnimplementedParser {
|
||||
span: Option<Span>,
|
||||
directive: Option<(Span, Directive)>,
|
||||
}
|
||||
|
||||
impl OnUnimplementedParser {
|
||||
fn parse<'sess, S: Stage>(
|
||||
&mut self,
|
||||
cx: &mut AcceptContext<'_, 'sess, S>,
|
||||
args: &ArgParser,
|
||||
mode: Mode,
|
||||
) {
|
||||
let span = cx.attr_span;
|
||||
self.span = Some(span);
|
||||
|
||||
// If target is not a trait, returning early will make `finalize` emit a
|
||||
// `AttributeKind::OnUnimplemented {span, directive: None }`, to prevent it being
|
||||
// accidentally used on non-trait items like trait aliases.
|
||||
if !matches!(cx.target, Target::Trait) {
|
||||
// Lint later emitted in check_attr
|
||||
return;
|
||||
}
|
||||
|
||||
let items = match args {
|
||||
ArgParser::List(items) if items.len() != 0 => items,
|
||||
ArgParser::NoArgs | ArgParser::List(_) => {
|
||||
cx.emit_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::MissingOptionsForOnUnimplemented,
|
||||
span,
|
||||
);
|
||||
return;
|
||||
}
|
||||
ArgParser::NameValue(_) => {
|
||||
cx.emit_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedOnUnimplementedAttr { span },
|
||||
span,
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
|
||||
merge_directives(cx, &mut self.directive, (span, directive));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Stage> AttributeParser<S> for OnUnimplementedParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[
|
||||
(
|
||||
&[sym::diagnostic, sym::on_unimplemented],
|
||||
template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]),
|
||||
|this, cx, args| {
|
||||
this.parse(cx, args, Mode::DiagnosticOnUnimplemented);
|
||||
},
|
||||
),
|
||||
(
|
||||
&[sym::rustc_on_unimplemented],
|
||||
template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]),
|
||||
|this, cx, args| {
|
||||
this.parse(cx, args, Mode::RustcOnUnimplemented);
|
||||
},
|
||||
),
|
||||
];
|
||||
//FIXME attribute is not parsed for non-traits but diagnostics are issued in `check_attr.rs`
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
if let Some(span) = self.span {
|
||||
Some(AttributeKind::OnUnimplemented {
|
||||
span,
|
||||
directive: self.directive.map(|d| Box::new(d.1)),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,8 @@
|
||||
use crate::parser::ArgParser;
|
||||
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
|
||||
|
||||
pub(crate) struct DummyParser;
|
||||
impl<S: Stage> SingleAttributeParser<S> for DummyParser {
|
||||
pub(crate) struct RustcDummyParser;
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcDummyParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dummy];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
|
||||
|
||||
@@ -524,8 +524,8 @@ impl<S: Stage> NoArgsAttributeParser<S> for FfiPureParser {
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;
|
||||
}
|
||||
|
||||
pub(crate) struct StdInternalSymbolParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for StdInternalSymbolParser {
|
||||
pub(crate) struct RustcStdInternalSymbolParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcStdInternalSymbolParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_std_internal_symbol];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::prelude::*;
|
||||
|
||||
pub(crate) struct AsPtrParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for AsPtrParser {
|
||||
pub(crate) struct RustcAsPtrParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcAsPtrParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_as_ptr];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
@@ -14,8 +14,8 @@ impl<S: Stage> NoArgsAttributeParser<S> for AsPtrParser {
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAsPtr;
|
||||
}
|
||||
|
||||
pub(crate) struct PubTransparentParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for PubTransparentParser {
|
||||
pub(crate) struct RustcPubTransparentParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcPubTransparentParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_pub_transparent];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
@@ -26,8 +26,8 @@ impl<S: Stage> NoArgsAttributeParser<S> for PubTransparentParser {
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPubTransparent;
|
||||
}
|
||||
|
||||
pub(crate) struct PassByValueParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for PassByValueParser {
|
||||
pub(crate) struct RustcPassByValueParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcPassByValueParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_pass_by_value];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
@@ -38,8 +38,8 @@ impl<S: Stage> NoArgsAttributeParser<S> for PassByValueParser {
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassByValue;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcShouldNotBeCalledOnConstItems;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcShouldNotBeCalledOnConstItems {
|
||||
pub(crate) struct RustcShouldNotBeCalledOnConstItemsParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcShouldNotBeCalledOnConstItemsParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_should_not_be_called_on_const_items];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
mod prelude;
|
||||
|
||||
pub(crate) mod allow_unstable;
|
||||
pub(crate) mod autodiff;
|
||||
pub(crate) mod body;
|
||||
pub(crate) mod cfg;
|
||||
pub(crate) mod cfg_select;
|
||||
@@ -39,7 +40,7 @@
|
||||
pub(crate) mod crate_level;
|
||||
pub(crate) mod debugger;
|
||||
pub(crate) mod deprecation;
|
||||
pub(crate) mod do_not_recommend;
|
||||
pub(crate) mod diagnostic;
|
||||
pub(crate) mod doc;
|
||||
pub(crate) mod dummy;
|
||||
pub(crate) mod inline;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rustc_abi::Align;
|
||||
use rustc_abi::{Align, Size};
|
||||
use rustc_ast::{IntTy, LitIntType, LitKind, UintTy};
|
||||
use rustc_hir::attrs::{IntType, ReprAttr};
|
||||
|
||||
@@ -229,7 +229,7 @@ fn parse_repr_align<S: Stage>(
|
||||
return None;
|
||||
};
|
||||
|
||||
match parse_alignment(&lit.kind) {
|
||||
match parse_alignment(&lit.kind, cx) {
|
||||
Ok(literal) => Some(match align_kind {
|
||||
AlignKind::Packed => ReprAttr::ReprPacked(literal),
|
||||
AlignKind::Align => ReprAttr::ReprAlign(literal),
|
||||
@@ -248,30 +248,42 @@ fn parse_repr_align<S: Stage>(
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_alignment(node: &LitKind) -> Result<Align, &'static str> {
|
||||
if let LitKind::Int(literal, LitIntType::Unsuffixed) = node {
|
||||
// `Align::from_bytes` accepts 0 as an input, check is_power_of_two() first
|
||||
if literal.get().is_power_of_two() {
|
||||
// Only possible error is larger than 2^29
|
||||
literal
|
||||
.get()
|
||||
.try_into()
|
||||
.ok()
|
||||
.and_then(|v| Align::from_bytes(v).ok())
|
||||
.ok_or("larger than 2^29")
|
||||
} else {
|
||||
Err("not a power of two")
|
||||
}
|
||||
} else {
|
||||
Err("not an unsuffixed integer")
|
||||
fn parse_alignment<S: Stage>(
|
||||
node: &LitKind,
|
||||
cx: &AcceptContext<'_, '_, S>,
|
||||
) -> Result<Align, String> {
|
||||
let LitKind::Int(literal, LitIntType::Unsuffixed) = node else {
|
||||
return Err("not an unsuffixed integer".to_string());
|
||||
};
|
||||
|
||||
// `Align::from_bytes` accepts 0 as a valid input,
|
||||
// so we check if its a power of two first
|
||||
if !literal.get().is_power_of_two() {
|
||||
return Err("not a power of two".to_string());
|
||||
}
|
||||
// lit must be < 2^29
|
||||
let align = literal
|
||||
.get()
|
||||
.try_into()
|
||||
.ok()
|
||||
.and_then(|a| Align::from_bytes(a).ok())
|
||||
.ok_or("larger than 2^29".to_string())?;
|
||||
|
||||
// alignment must not be larger than the pointer width (`isize::MAX`)
|
||||
let max = Size::from_bits(cx.sess.target.pointer_width).signed_int_max() as u64;
|
||||
if align.bytes() > max {
|
||||
return Err(format!(
|
||||
"alignment larger than `isize::MAX` bytes ({max} for the current target)"
|
||||
));
|
||||
}
|
||||
Ok(align)
|
||||
}
|
||||
|
||||
/// Parse #[align(N)].
|
||||
#[derive(Default)]
|
||||
pub(crate) struct AlignParser(Option<(Align, Span)>);
|
||||
pub(crate) struct RustcAlignParser(Option<(Align, Span)>);
|
||||
|
||||
impl AlignParser {
|
||||
impl RustcAlignParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_align];
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["<alignment in bytes>"]);
|
||||
|
||||
@@ -294,7 +306,7 @@ fn parse<S: Stage>(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParse
|
||||
return;
|
||||
};
|
||||
|
||||
match parse_alignment(&lit.kind) {
|
||||
match parse_alignment(&lit.kind, cx) {
|
||||
Ok(literal) => self.0 = Ord::max(self.0, Some((literal, cx.attr_span))),
|
||||
Err(message) => {
|
||||
cx.emit_err(session_diagnostics::InvalidAlignmentValue {
|
||||
@@ -308,7 +320,7 @@ fn parse<S: Stage>(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParse
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Stage> AttributeParser<S> for AlignParser {
|
||||
impl<S: Stage> AttributeParser<S> for RustcAlignParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(Self::PATH, Self::TEMPLATE, Self::parse)];
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
@@ -321,29 +333,29 @@ impl<S: Stage> AttributeParser<S> for AlignParser {
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
let (align, span) = self.0?;
|
||||
Some(AttributeKind::Align { align, span })
|
||||
Some(AttributeKind::RustcAlign { align, span })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct AlignStaticParser(AlignParser);
|
||||
pub(crate) struct RustcAlignStaticParser(RustcAlignParser);
|
||||
|
||||
impl AlignStaticParser {
|
||||
impl RustcAlignStaticParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_align_static];
|
||||
const TEMPLATE: AttributeTemplate = AlignParser::TEMPLATE;
|
||||
const TEMPLATE: AttributeTemplate = RustcAlignParser::TEMPLATE;
|
||||
|
||||
fn parse<S: Stage>(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) {
|
||||
self.0.parse(cx, args)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Stage> AttributeParser<S> for AlignStaticParser {
|
||||
impl<S: Stage> AttributeParser<S> for RustcAlignStaticParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(Self::PATH, Self::TEMPLATE, Self::parse)];
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]);
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
let (align, span) = self.0.0?;
|
||||
Some(AttributeKind::Align { align, span })
|
||||
Some(AttributeKind::RustcAlign { align, span })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use rustc_hir::Target;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::{MethodKind, Target};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use crate::attributes::prelude::Allow;
|
||||
@@ -25,6 +25,20 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpDefParentsParser {
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpDefParents;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDumpInferredOutlivesParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpInferredOutlivesParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dump_inferred_outlives];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Union),
|
||||
Allow(Target::TyAlias),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpInferredOutlives;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDumpItemBoundsParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpItemBoundsParser {
|
||||
@@ -34,21 +48,88 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpItemBoundsParser {
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDumpObjectLifetimeDefaultsParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpObjectLifetimeDefaultsParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dump_object_lifetime_defaults];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::AssocConst),
|
||||
Allow(Target::AssocTy),
|
||||
Allow(Target::Const),
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::ForeignFn),
|
||||
Allow(Target::Impl { of_trait: false }),
|
||||
Allow(Target::Impl { of_trait: true }),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::Trait { body: false })),
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Trait),
|
||||
Allow(Target::TraitAlias),
|
||||
Allow(Target::TyAlias),
|
||||
Allow(Target::Union),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpObjectLifetimeDefaults;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDumpPredicatesParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpPredicatesParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dump_predicates];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Union),
|
||||
Allow(Target::Trait),
|
||||
Allow(Target::AssocConst),
|
||||
Allow(Target::AssocTy),
|
||||
Allow(Target::Const),
|
||||
Allow(Target::Delegation { mac: false }),
|
||||
Allow(Target::Delegation { mac: true }),
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Impl { of_trait: false }),
|
||||
Allow(Target::Impl { of_trait: true }),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::Trait { body: false })),
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Trait),
|
||||
Allow(Target::TraitAlias),
|
||||
Allow(Target::TyAlias),
|
||||
Allow(Target::Union),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpPredicates;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDumpVariancesParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpVariancesParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dump_variances];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::Trait { body: false })),
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Union),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariances;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDumpVariancesOfOpaquesParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpVariancesOfOpaquesParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dump_variances_of_opaques];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariancesOfOpaques;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDumpVtableParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpVtableParser {
|
||||
|
||||
@@ -71,9 +71,9 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcNeverReturnsNullPointerParser;
|
||||
pub(crate) struct RustcNeverReturnsNullPtrParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcNeverReturnsNullPointerParser {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcNeverReturnsNullPtrParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_never_returns_null_ptr];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
@@ -83,7 +83,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcNeverReturnsNullPointerParser {
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNeverReturnsNullPointer;
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNeverReturnsNullPtr;
|
||||
}
|
||||
pub(crate) struct RustcNoImplicitAutorefsParser;
|
||||
|
||||
@@ -175,6 +175,20 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcInheritOverflowChecksParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcInheritOverflowChecksParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_inherit_overflow_checks];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
Allow(Target::Closure),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInheritOverflowChecks;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcLintOptDenyFieldAccessParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcLintOptDenyFieldAccessParser {
|
||||
@@ -574,15 +588,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcLintUntrackedQueryInformationPa
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintUntrackedQueryInformation;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcObjectLifetimeDefaultParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcObjectLifetimeDefaultParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_object_lifetime_default];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcObjectLifetimeDefault;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcSimdMonomorphizeLaneLimitParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcSimdMonomorphizeLaneLimitParser {
|
||||
@@ -854,7 +859,6 @@ fn extend(
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcNonConstTraitMethodParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcNonConstTraitMethodParser {
|
||||
@@ -1178,9 +1182,34 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcSymbolName;
|
||||
pub(crate) struct RustcDoNotConstCheckParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcSymbolName {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDoNotConstCheckParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_do_not_const_check];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
Allow(Target::Method(MethodKind::Trait { body: false })),
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDoNotConstCheck;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcNonnullOptimizationGuaranteedParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcNonnullOptimizationGuaranteedParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonnullOptimizationGuaranteed;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcSymbolNameParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcSymbolNameParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_symbol_name];
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
@@ -1191,7 +1220,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcSymbolName {
|
||||
Allow(Target::Impl { of_trait: false }),
|
||||
]);
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const PATH: &[Symbol] = &[sym::rustc_symbol_name];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
@@ -1203,9 +1231,10 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDefPath;
|
||||
pub(crate) struct RustcDefPathParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcDefPath {
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcDefPathParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_def_path];
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
@@ -1216,7 +1245,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcDefPath {
|
||||
Allow(Target::Impl { of_trait: false }),
|
||||
]);
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const PATH: &[Symbol] = &[sym::rustc_def_path];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
@@ -1228,24 +1256,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcIntrinsicParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcIntrinsicParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_intrinsic];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcIntrinsicConstStableIndirectParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcIntrinsicConstStableIndirectParser {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcStrictCoherenceParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcStrictCoherenceParser {
|
||||
@@ -1295,3 +1305,45 @@ impl<S: Stage> NoArgsAttributeParser<S> for PreludeImportParser {
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Use)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDocPrimitiveParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcDocPrimitiveParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_doc_primitive];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Mod)]);
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "primitive name");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
let Some(nv) = args.name_value() else {
|
||||
cx.expected_name_value(args.span().unwrap_or(cx.attr_span), None);
|
||||
return None;
|
||||
};
|
||||
|
||||
let Some(value_str) = nv.value_as_str() else {
|
||||
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(AttributeKind::RustcDocPrimitive(cx.attr_span, value_str))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcIntrinsicParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcIntrinsicParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_intrinsic];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcIntrinsicConstStableIndirectParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcIntrinsicConstStableIndirectParser {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
use super::prelude::*;
|
||||
use super::util::parse_version;
|
||||
use crate::session_diagnostics::{self};
|
||||
use crate::session_diagnostics;
|
||||
|
||||
macro_rules! reject_outside_std {
|
||||
($cx: ident) => {
|
||||
@@ -177,15 +177,15 @@ fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ConstStabilityIndirectParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for ConstStabilityIndirectParser {
|
||||
pub(crate) struct RustcConstStableIndirectParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcConstStableIndirectParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_const_stable_indirect];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConstStabilityIndirect;
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConstStableIndirect;
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
||||
@@ -93,28 +93,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcVarianceParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcVarianceParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_variance];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Union),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcVariance;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcVarianceOfOpaquesParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcVarianceOfOpaquesParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_variance_of_opaques];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcVarianceOfOpaques;
|
||||
}
|
||||
|
||||
pub(crate) struct ReexportTestHarnessMainParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for ReexportTestHarnessMainParser {
|
||||
@@ -215,20 +193,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcEvaluateWhereClausesParser {
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEvaluateWhereClauses;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcOutlivesParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcOutlivesParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_outlives];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Union),
|
||||
Allow(Target::TyAlias),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOutlives;
|
||||
}
|
||||
|
||||
pub(crate) struct TestRunnerParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for TestRunnerParser {
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
use crate::target_checking::Policy::{Allow, Warn};
|
||||
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
|
||||
|
||||
pub(crate) struct SkipDuringMethodDispatchParser;
|
||||
impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
|
||||
pub(crate) struct RustcSkipDuringMethodDispatchParser;
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcSkipDuringMethodDispatchParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
@@ -58,8 +58,8 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ParenSugarParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for ParenSugarParser {
|
||||
pub(crate) struct RustcParenSugarParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcParenSugarParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_paren_sugar];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
@@ -81,16 +81,16 @@ impl<S: Stage> NoArgsAttributeParser<S> for MarkerParser {
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Marker;
|
||||
}
|
||||
|
||||
pub(crate) struct DenyExplicitImplParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for DenyExplicitImplParser {
|
||||
pub(crate) struct RustcDenyExplicitImplParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDenyExplicitImplParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDenyExplicitImpl;
|
||||
}
|
||||
|
||||
pub(crate) struct DynIncompatibleTraitParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for DynIncompatibleTraitParser {
|
||||
pub(crate) struct RustcDynIncompatibleTraitParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDynIncompatibleTraitParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_trait];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
@@ -99,16 +99,16 @@ impl<S: Stage> NoArgsAttributeParser<S> for DynIncompatibleTraitParser {
|
||||
|
||||
// Specialization
|
||||
|
||||
pub(crate) struct SpecializationTraitParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for SpecializationTraitParser {
|
||||
pub(crate) struct RustcSpecializationTraitParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcSpecializationTraitParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_specialization_trait];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcSpecializationTrait;
|
||||
}
|
||||
|
||||
pub(crate) struct UnsafeSpecializationMarkerParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for UnsafeSpecializationMarkerParser {
|
||||
pub(crate) struct RustcUnsafeSpecializationMarkerParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcUnsafeSpecializationMarkerParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
@@ -117,16 +117,16 @@ impl<S: Stage> NoArgsAttributeParser<S> for UnsafeSpecializationMarkerParser {
|
||||
|
||||
// Coherence
|
||||
|
||||
pub(crate) struct CoinductiveParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for CoinductiveParser {
|
||||
pub(crate) struct RustcCoinductiveParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcCoinductiveParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_coinductive];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoinductive;
|
||||
}
|
||||
|
||||
pub(crate) struct AllowIncoherentImplParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for AllowIncoherentImplParser {
|
||||
pub(crate) struct RustcAllowIncoherentImplParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcAllowIncoherentImplParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
use super::prelude::*;
|
||||
|
||||
pub(crate) struct TransparencyParser;
|
||||
pub(crate) struct RustcMacroTransparencyParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for TransparencyParser {
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcMacroTransparencyParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_macro_transparency];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Custom(|cx, used, unused| {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
use crate::AttributeParser;
|
||||
// Glob imports to avoid big, bitrotty import lists
|
||||
use crate::attributes::allow_unstable::*;
|
||||
use crate::attributes::autodiff::*;
|
||||
use crate::attributes::body::*;
|
||||
use crate::attributes::cfi_encoding::*;
|
||||
use crate::attributes::codegen_attrs::*;
|
||||
@@ -26,7 +27,9 @@
|
||||
use crate::attributes::crate_level::*;
|
||||
use crate::attributes::debugger::*;
|
||||
use crate::attributes::deprecation::*;
|
||||
use crate::attributes::do_not_recommend::*;
|
||||
use crate::attributes::diagnostic::do_not_recommend::*;
|
||||
use crate::attributes::diagnostic::on_const::*;
|
||||
use crate::attributes::diagnostic::on_unimplemented::*;
|
||||
use crate::attributes::doc::*;
|
||||
use crate::attributes::dummy::*;
|
||||
use crate::attributes::inline::*;
|
||||
@@ -139,27 +142,31 @@ mod late {
|
||||
attribute_parsers!(
|
||||
pub(crate) static ATTRIBUTE_PARSERS = [
|
||||
// tidy-alphabetical-start
|
||||
AlignParser,
|
||||
AlignStaticParser,
|
||||
BodyStabilityParser,
|
||||
ConfusablesParser,
|
||||
ConstStabilityParser,
|
||||
DocParser,
|
||||
MacroUseParser,
|
||||
NakedParser,
|
||||
OnConstParser,
|
||||
OnUnimplementedParser,
|
||||
RustcAlignParser,
|
||||
RustcAlignStaticParser,
|
||||
RustcCguTestAttributeParser,
|
||||
StabilityParser,
|
||||
UsedParser,
|
||||
// tidy-alphabetical-end
|
||||
|
||||
// tidy-alphabetical-start
|
||||
Combine<AllowConstFnUnstableParser>,
|
||||
Combine<AllowInternalUnstableParser>,
|
||||
Combine<CrateTypeParser>,
|
||||
Combine<DebuggerViualizerParser>,
|
||||
Combine<FeatureParser>,
|
||||
Combine<ForceTargetFeatureParser>,
|
||||
Combine<LinkParser>,
|
||||
Combine<RegisterToolParser>,
|
||||
Combine<ReprParser>,
|
||||
Combine<RustcAllowConstFnUnstableParser>,
|
||||
Combine<RustcCleanParser>,
|
||||
Combine<RustcLayoutParser>,
|
||||
Combine<RustcMirParser>,
|
||||
@@ -174,9 +181,8 @@ mod late {
|
||||
Single<CoverageParser>,
|
||||
Single<CrateNameParser>,
|
||||
Single<CustomMirParser>,
|
||||
Single<DeprecationParser>,
|
||||
Single<DeprecatedParser>,
|
||||
Single<DoNotRecommendParser>,
|
||||
Single<DummyParser>,
|
||||
Single<ExportNameParser>,
|
||||
Single<IgnoreParser>,
|
||||
Single<InlineParser>,
|
||||
@@ -190,8 +196,6 @@ mod late {
|
||||
Single<MoveSizeLimitParser>,
|
||||
Single<MustNotSuspendParser>,
|
||||
Single<MustUseParser>,
|
||||
Single<ObjcClassParser>,
|
||||
Single<ObjcSelectorParser>,
|
||||
Single<OptimizeParser>,
|
||||
Single<PatchableFunctionEntryParser>,
|
||||
Single<PathAttributeParser>,
|
||||
@@ -201,43 +205,42 @@ mod late {
|
||||
Single<ReexportTestHarnessMainParser>,
|
||||
Single<RustcAbiParser>,
|
||||
Single<RustcAllocatorZeroedVariantParser>,
|
||||
Single<RustcAutodiffParser>,
|
||||
Single<RustcBuiltinMacroParser>,
|
||||
Single<RustcDefPath>,
|
||||
Single<RustcDefPathParser>,
|
||||
Single<RustcDeprecatedSafe2024Parser>,
|
||||
Single<RustcDiagnosticItemParser>,
|
||||
Single<RustcDocPrimitiveParser>,
|
||||
Single<RustcDummyParser>,
|
||||
Single<RustcForceInlineParser>,
|
||||
Single<RustcIfThisChangedParser>,
|
||||
Single<RustcLayoutScalarValidRangeEndParser>,
|
||||
Single<RustcLayoutScalarValidRangeStartParser>,
|
||||
Single<RustcLegacyConstGenericsParser>,
|
||||
Single<RustcLintOptDenyFieldAccessParser>,
|
||||
Single<RustcMacroTransparencyParser>,
|
||||
Single<RustcMustImplementOneOfParser>,
|
||||
Single<RustcNeverTypeOptionsParser>,
|
||||
Single<RustcObjcClassParser>,
|
||||
Single<RustcObjcSelectorParser>,
|
||||
Single<RustcReservationImplParser>,
|
||||
Single<RustcScalableVectorParser>,
|
||||
Single<RustcSimdMonomorphizeLaneLimitParser>,
|
||||
Single<RustcSymbolName>,
|
||||
Single<RustcSkipDuringMethodDispatchParser>,
|
||||
Single<RustcSymbolNameParser>,
|
||||
Single<RustcTestMarkerParser>,
|
||||
Single<SanitizeParser>,
|
||||
Single<ShouldPanicParser>,
|
||||
Single<SkipDuringMethodDispatchParser>,
|
||||
Single<TestRunnerParser>,
|
||||
Single<TransparencyParser>,
|
||||
Single<TypeLengthLimitParser>,
|
||||
Single<WindowsSubsystemParser>,
|
||||
Single<WithoutArgs<AllowIncoherentImplParser>>,
|
||||
Single<WithoutArgs<AllowInternalUnsafeParser>>,
|
||||
Single<WithoutArgs<AsPtrParser>>,
|
||||
Single<WithoutArgs<AutomaticallyDerivedParser>>,
|
||||
Single<WithoutArgs<CoinductiveParser>>,
|
||||
Single<WithoutArgs<ColdParser>>,
|
||||
Single<WithoutArgs<CompilerBuiltinsParser>>,
|
||||
Single<WithoutArgs<ConstContinueParser>>,
|
||||
Single<WithoutArgs<ConstStabilityIndirectParser>>,
|
||||
Single<WithoutArgs<CoroutineParser>>,
|
||||
Single<WithoutArgs<DenyExplicitImplParser>>,
|
||||
Single<WithoutArgs<DynIncompatibleTraitParser>>,
|
||||
Single<WithoutArgs<EiiForeignItemParser>>,
|
||||
Single<WithoutArgs<DefaultLibAllocatorParser>>,
|
||||
Single<WithoutArgs<ExportStableParser>>,
|
||||
Single<WithoutArgs<FfiConstParser>>,
|
||||
Single<WithoutArgs<FfiPureParser>>,
|
||||
@@ -258,31 +261,41 @@ mod late {
|
||||
Single<WithoutArgs<NonExhaustiveParser>>,
|
||||
Single<WithoutArgs<PanicHandlerParser>>,
|
||||
Single<WithoutArgs<PanicRuntimeParser>>,
|
||||
Single<WithoutArgs<ParenSugarParser>>,
|
||||
Single<WithoutArgs<PassByValueParser>>,
|
||||
Single<WithoutArgs<PinV2Parser>>,
|
||||
Single<WithoutArgs<PointeeParser>>,
|
||||
Single<WithoutArgs<PreludeImportParser>>,
|
||||
Single<WithoutArgs<ProcMacroAttributeParser>>,
|
||||
Single<WithoutArgs<ProcMacroParser>>,
|
||||
Single<WithoutArgs<ProfilerRuntimeParser>>,
|
||||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<RustcAllocatorParser>>,
|
||||
Single<WithoutArgs<RustcAllocatorZeroedParser>>,
|
||||
Single<WithoutArgs<RustcAllowIncoherentImplParser>>,
|
||||
Single<WithoutArgs<RustcAsPtrParser>>,
|
||||
Single<WithoutArgs<RustcCaptureAnalysisParser>>,
|
||||
Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
|
||||
Single<WithoutArgs<RustcCoinductiveParser>>,
|
||||
Single<WithoutArgs<RustcConstStableIndirectParser>>,
|
||||
Single<WithoutArgs<RustcConversionSuggestionParser>>,
|
||||
Single<WithoutArgs<RustcDeallocatorParser>>,
|
||||
Single<WithoutArgs<RustcDelayedBugFromInsideQueryParser>>,
|
||||
Single<WithoutArgs<RustcDenyExplicitImplParser>>,
|
||||
Single<WithoutArgs<RustcDoNotConstCheckParser>>,
|
||||
Single<WithoutArgs<RustcDumpDefParentsParser>>,
|
||||
Single<WithoutArgs<RustcDumpInferredOutlivesParser>>,
|
||||
Single<WithoutArgs<RustcDumpItemBoundsParser>>,
|
||||
Single<WithoutArgs<RustcDumpObjectLifetimeDefaultsParser>>,
|
||||
Single<WithoutArgs<RustcDumpPredicatesParser>>,
|
||||
Single<WithoutArgs<RustcDumpUserArgsParser>>,
|
||||
Single<WithoutArgs<RustcDumpVariancesOfOpaquesParser>>,
|
||||
Single<WithoutArgs<RustcDumpVariancesParser>>,
|
||||
Single<WithoutArgs<RustcDumpVtableParser>>,
|
||||
Single<WithoutArgs<RustcDynIncompatibleTraitParser>>,
|
||||
Single<WithoutArgs<RustcEffectiveVisibilityParser>>,
|
||||
Single<WithoutArgs<RustcEiiForeignItemParser>>,
|
||||
Single<WithoutArgs<RustcEvaluateWhereClausesParser>>,
|
||||
Single<WithoutArgs<RustcHasIncoherentInherentImplsParser>>,
|
||||
Single<WithoutArgs<RustcHiddenTypeOfOpaquesParser>>,
|
||||
Single<WithoutArgs<RustcInheritOverflowChecksParser>>,
|
||||
Single<WithoutArgs<RustcInsignificantDtorParser>>,
|
||||
Single<WithoutArgs<RustcIntrinsicConstStableIndirectParser>>,
|
||||
Single<WithoutArgs<RustcIntrinsicParser>>,
|
||||
@@ -290,30 +303,30 @@ mod late {
|
||||
Single<WithoutArgs<RustcLintQueryInstabilityParser>>,
|
||||
Single<WithoutArgs<RustcLintUntrackedQueryInformationParser>>,
|
||||
Single<WithoutArgs<RustcMainParser>>,
|
||||
Single<WithoutArgs<RustcNeverReturnsNullPointerParser>>,
|
||||
Single<WithoutArgs<RustcNeverReturnsNullPtrParser>>,
|
||||
Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,
|
||||
Single<WithoutArgs<RustcNoImplicitBoundsParser>>,
|
||||
Single<WithoutArgs<RustcNoMirInlineParser>>,
|
||||
Single<WithoutArgs<RustcNonConstTraitMethodParser>>,
|
||||
Single<WithoutArgs<RustcNonnullOptimizationGuaranteedParser>>,
|
||||
Single<WithoutArgs<RustcNounwindParser>>,
|
||||
Single<WithoutArgs<RustcObjectLifetimeDefaultParser>>,
|
||||
Single<WithoutArgs<RustcOffloadKernelParser>>,
|
||||
Single<WithoutArgs<RustcOutlivesParser>>,
|
||||
Single<WithoutArgs<RustcParenSugarParser>>,
|
||||
Single<WithoutArgs<RustcPassByValueParser>>,
|
||||
Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
|
||||
Single<WithoutArgs<RustcPreserveUbChecksParser>>,
|
||||
Single<WithoutArgs<RustcProcMacroDeclsParser>>,
|
||||
Single<WithoutArgs<RustcPubTransparentParser>>,
|
||||
Single<WithoutArgs<RustcReallocatorParser>>,
|
||||
Single<WithoutArgs<RustcRegionsParser>>,
|
||||
Single<WithoutArgs<RustcShouldNotBeCalledOnConstItems>>,
|
||||
Single<WithoutArgs<RustcShouldNotBeCalledOnConstItemsParser>>,
|
||||
Single<WithoutArgs<RustcSpecializationTraitParser>>,
|
||||
Single<WithoutArgs<RustcStdInternalSymbolParser>>,
|
||||
Single<WithoutArgs<RustcStrictCoherenceParser>>,
|
||||
Single<WithoutArgs<RustcTrivialFieldReadsParser>>,
|
||||
Single<WithoutArgs<RustcVarianceOfOpaquesParser>>,
|
||||
Single<WithoutArgs<RustcVarianceParser>>,
|
||||
Single<WithoutArgs<SpecializationTraitParser>>,
|
||||
Single<WithoutArgs<StdInternalSymbolParser>>,
|
||||
Single<WithoutArgs<RustcUnsafeSpecializationMarkerParser>>,
|
||||
Single<WithoutArgs<ThreadLocalParser>>,
|
||||
Single<WithoutArgs<TrackCallerParser>>,
|
||||
Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
|
||||
// tidy-alphabetical-end
|
||||
];
|
||||
);
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![feature(decl_macro)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![recursion_limit = "256"]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
@@ -522,6 +522,13 @@ fn expected_lit(&mut self) -> Diag<'sess> {
|
||||
return self.parser.dcx().create_err(err);
|
||||
}
|
||||
|
||||
if let ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden } = self.should_emit {
|
||||
// Do not attempt to suggest anything in `Recovery::Forbidden` mode.
|
||||
// Malformed diagnostic-attr arguments that start with an `if` expression can lead to
|
||||
// an ICE (https://github.com/rust-lang/rust/issues/152744), because callers may cancel the `InvalidMetaItem` error.
|
||||
return self.parser.dcx().create_err(err);
|
||||
}
|
||||
|
||||
// Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and
|
||||
// don't `uninterpolate` the token to avoid suggesting anything butchered or questionable
|
||||
// when macro metavariables are involved.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::num::IntErrorKind;
|
||||
|
||||
use rustc_ast::{self as ast};
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
|
||||
@@ -227,12 +227,12 @@ pub(crate) struct InvalidReprAlignNeedArg {
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("invalid `repr({$repr_arg})` attribute: {$error_part}", code = E0589)]
|
||||
pub(crate) struct InvalidReprGeneric<'a> {
|
||||
pub(crate) struct InvalidReprGeneric {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
pub repr_arg: String,
|
||||
pub error_part: &'a str,
|
||||
pub error_part: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@@ -479,7 +479,7 @@ pub(crate) struct InvalidTarget {
|
||||
pub(crate) struct InvalidAlignmentValue {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub error_part: &'static str,
|
||||
pub error_part: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
|
||||
use rustc_span::def_id::{DefId, LocalDefId};
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
use rustc_span::{BytePos, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_span::{BytePos, ExpnKind, Ident, MacroKind, Span, Symbol, kw, sym};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
|
||||
use rustc_trait_selection::error_reporting::traits::call_kind::CallKind;
|
||||
@@ -535,7 +535,7 @@ fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) {
|
||||
if let Some(pat) = finder.parent_pat {
|
||||
sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string()));
|
||||
}
|
||||
err.multipart_suggestion_verbose(
|
||||
err.multipart_suggestion(
|
||||
"borrow this binding in the pattern to avoid moving the value",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
@@ -1157,7 +1157,10 @@ fn suggest_cloning_on_functional_record_update(
|
||||
let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = base.kind else { return };
|
||||
let (hir::def::Res::Local(_)
|
||||
| hir::def::Res::Def(
|
||||
DefKind::Const | DefKind::ConstParam | DefKind::Static { .. } | DefKind::AssocConst,
|
||||
DefKind::Const { .. }
|
||||
| DefKind::ConstParam
|
||||
| DefKind::Static { .. }
|
||||
| DefKind::AssocConst { .. },
|
||||
_,
|
||||
)) = path.res
|
||||
else {
|
||||
@@ -1435,6 +1438,12 @@ fn suggest_cloning_inner(
|
||||
expr: &hir::Expr<'_>,
|
||||
) -> bool {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
// Don't suggest `.clone()` in a derive macro expansion.
|
||||
if let ExpnKind::Macro(MacroKind::Derive, _) = self.body.span.ctxt().outer_expn_data().kind
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if let Some(_) = self.clone_on_reference(expr) {
|
||||
// Avoid redundant clone suggestion already suggested in `explain_captures`.
|
||||
// See `tests/ui/moves/needs-clone-through-deref.rs`
|
||||
@@ -1509,7 +1518,7 @@ fn suggest_cloning_inner(
|
||||
} else {
|
||||
"consider cloning the value if the performance cost is acceptable"
|
||||
};
|
||||
err.multipart_suggestion_verbose(msg, sugg, Applicability::MachineApplicable);
|
||||
err.multipart_suggestion(msg, sugg, Applicability::MachineApplicable);
|
||||
true
|
||||
}
|
||||
|
||||
@@ -2759,7 +2768,7 @@ fn visit_stmt(&mut self, s: &'hir hir::Stmt<'hir>) {
|
||||
.chain(finder.closure_call_changes)
|
||||
.collect();
|
||||
|
||||
err.multipart_suggestion_verbose(
|
||||
err.multipart_suggestion(
|
||||
"try explicitly passing `&Self` into the closure as an argument",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
@@ -3347,7 +3356,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
||||
|
||||
let addition =
|
||||
format!("let {}binding = {};\n{}", mutability, s, " ".repeat(p));
|
||||
err.multipart_suggestion_verbose(
|
||||
err.multipart_suggestion(
|
||||
msg,
|
||||
vec![
|
||||
(stmt.span.shrink_to_lo(), addition),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Print diagnostics to explain why values are borrowed.
|
||||
|
||||
use rustc_data_structures::assert_matches;
|
||||
use std::assert_matches;
|
||||
|
||||
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
use rustc_abi::{FieldIdx, VariantIdx};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_errors::formatting::DiagMessageAddArg;
|
||||
use rustc_errors::{Applicability, Diag, DiagMessage, EmissionGuarantee, MultiSpan, listify, msg};
|
||||
use rustc_hir::def::{CtorKind, Namespace};
|
||||
use rustc_hir::{
|
||||
@@ -1309,12 +1310,9 @@ fn explain_captures(
|
||||
&& !spans.is_empty()
|
||||
{
|
||||
let mut span: MultiSpan = spans.clone().into();
|
||||
err.arg("ty", param_ty.to_string());
|
||||
let msg = err.dcx.eagerly_translate_to_string(
|
||||
msg!("`{$ty}` is made to be an `FnOnce` closure here"),
|
||||
err.args.iter(),
|
||||
);
|
||||
err.remove_arg("ty");
|
||||
let msg = msg!("`{$ty}` is made to be an `FnOnce` closure here")
|
||||
.arg("ty", param_ty.to_string())
|
||||
.format();
|
||||
for sp in spans {
|
||||
span.push_span_label(sp, msg.clone());
|
||||
}
|
||||
@@ -1511,11 +1509,7 @@ fn explain_captures(
|
||||
)
|
||||
}
|
||||
};
|
||||
err.multipart_suggestion_verbose(
|
||||
msg,
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
|
||||
for error in errors {
|
||||
if let FulfillmentErrorCode::Select(
|
||||
SelectionError::Unimplemented,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
|
||||
use rustc_span::{BytePos, ExpnKind, MacroKind, Span, sym};
|
||||
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use tracing::debug;
|
||||
@@ -294,7 +294,7 @@ fn has_ambiguous_copy(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
|
||||
// Avoid bogus move errors because of an incoherent `Copy` impl.
|
||||
self.infcx.type_implements_trait(copy_def_id, [ty], self.infcx.param_env).may_apply()
|
||||
&& self.infcx.tcx.coherent_trait(copy_def_id).is_err()
|
||||
&& self.infcx.tcx.ensure_result().coherent_trait(copy_def_id).is_err()
|
||||
}
|
||||
|
||||
fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> {
|
||||
@@ -375,7 +375,7 @@ pub(in crate::diagnostics) fn suggest_clone_of_captured_var_in_move_closure(
|
||||
.source_map()
|
||||
.indentation_before(stmt.span)
|
||||
.unwrap_or_else(|| " ".to_string());
|
||||
err.multipart_suggestion_verbose(
|
||||
err.multipart_suggestion(
|
||||
"consider cloning the value before moving it into the closure",
|
||||
vec![
|
||||
(
|
||||
@@ -405,7 +405,7 @@ pub(in crate::diagnostics) fn suggest_clone_of_captured_var_in_move_closure(
|
||||
.source_map()
|
||||
.indentation_before(closure_expr.span)
|
||||
.unwrap_or_else(|| " ".to_string());
|
||||
err.multipart_suggestion_verbose(
|
||||
err.multipart_suggestion(
|
||||
"consider cloning the value before moving it into the closure",
|
||||
vec![
|
||||
(
|
||||
@@ -626,7 +626,7 @@ fn get_closure_bound_clause_span(
|
||||
let predicates = match parent.kind {
|
||||
hir::ExprKind::Call(callee, _) => {
|
||||
let ty = typeck_result.node_type_opt(callee.hir_id)?;
|
||||
let ty::FnDef(fn_def_id, args) = ty.kind() else { return None };
|
||||
let ty::FnDef(fn_def_id, args) = *ty.kind() else { return None };
|
||||
tcx.predicates_of(fn_def_id).instantiate(tcx, args)
|
||||
}
|
||||
hir::ExprKind::MethodCall(..) => {
|
||||
@@ -700,14 +700,14 @@ fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span
|
||||
binds_to.sort();
|
||||
binds_to.dedup();
|
||||
|
||||
self.add_move_error_details(err, &binds_to);
|
||||
self.add_move_error_details(err, &binds_to, &[]);
|
||||
}
|
||||
}
|
||||
GroupedMoveError::MovesFromValue { mut binds_to, .. } => {
|
||||
binds_to.sort();
|
||||
binds_to.dedup();
|
||||
self.add_move_error_suggestions(err, &binds_to);
|
||||
self.add_move_error_details(err, &binds_to);
|
||||
let desugar_spans = self.add_move_error_suggestions(err, &binds_to);
|
||||
self.add_move_error_details(err, &binds_to, &desugar_spans);
|
||||
}
|
||||
// No binding. Nothing to suggest.
|
||||
GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => {
|
||||
@@ -823,7 +823,7 @@ fn add_borrow_suggestions(&self, err: &mut Diag<'_>, span: Span) {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_move_error_suggestions(&self, err: &mut Diag<'_>, binds_to: &[Local]) {
|
||||
fn add_move_error_suggestions(&self, err: &mut Diag<'_>, binds_to: &[Local]) -> Vec<Span> {
|
||||
/// A HIR visitor to associate each binding with a `&` or `&mut` that could be removed to
|
||||
/// make it bind by reference instead (if possible)
|
||||
struct BindingFinder<'tcx> {
|
||||
@@ -843,6 +843,8 @@ struct BindingFinder<'tcx> {
|
||||
ref_pat_for_binding: Vec<(Span, Option<&'tcx hir::Pat<'tcx>>)>,
|
||||
/// Output: ref patterns that can't be removed straightforwardly
|
||||
cannot_remove: FxHashSet<HirId>,
|
||||
/// Output: binding spans from destructuring assignment desugaring
|
||||
desugar_binding_spans: Vec<Span>,
|
||||
}
|
||||
impl<'tcx> Visitor<'tcx> for BindingFinder<'tcx> {
|
||||
type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
|
||||
@@ -883,16 +885,38 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
|
||||
}
|
||||
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = p.kind {
|
||||
// the spans in `binding_spans` encompass both the ident and binding mode
|
||||
if let Some(&bind_sp) =
|
||||
self.binding_spans.iter().find(|bind_sp| bind_sp.contains(ident.span))
|
||||
{
|
||||
self.ref_pat_for_binding.push((bind_sp, self.ref_pat));
|
||||
// Skip synthetic bindings from destructuring assignment desugaring
|
||||
// These have name `lhs` and their parent is a `LetStmt` with
|
||||
// `LocalSource::AssignDesugar`
|
||||
let dominated_by_desugar_assign = ident.name == sym::lhs
|
||||
&& self.tcx.hir_parent_iter(p.hir_id).any(|(_, node)| {
|
||||
matches!(
|
||||
node,
|
||||
hir::Node::LetStmt(&hir::LetStmt {
|
||||
source: hir::LocalSource::AssignDesugar,
|
||||
..
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
if dominated_by_desugar_assign {
|
||||
if let Some(&bind_sp) =
|
||||
self.binding_spans.iter().find(|bind_sp| bind_sp.contains(ident.span))
|
||||
{
|
||||
self.desugar_binding_spans.push(bind_sp);
|
||||
}
|
||||
} else {
|
||||
// we've encountered a binding that we're not reporting a move error for.
|
||||
// we don't want to change its type, so don't remove the surrounding `&`.
|
||||
if let Some(ref_pat) = self.ref_pat {
|
||||
self.cannot_remove.insert(ref_pat.hir_id);
|
||||
// the spans in `binding_spans` encompass both the ident and binding mode
|
||||
if let Some(&bind_sp) =
|
||||
self.binding_spans.iter().find(|bind_sp| bind_sp.contains(ident.span))
|
||||
{
|
||||
self.ref_pat_for_binding.push((bind_sp, self.ref_pat));
|
||||
} else {
|
||||
// we've encountered a binding that we're not reporting a move error for.
|
||||
// we don't want to change its type, so don't remove the surrounding `&`.
|
||||
if let Some(ref_pat) = self.ref_pat {
|
||||
self.cannot_remove.insert(ref_pat.hir_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -913,10 +937,10 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
|
||||
binding_spans.push(bind_to.source_info.span);
|
||||
}
|
||||
}
|
||||
let Some(pat_span) = pat_span else { return };
|
||||
let Some(pat_span) = pat_span else { return Vec::new() };
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
let Some(body) = tcx.hir_maybe_body_owned_by(self.mir_def_id()) else { return };
|
||||
let Some(body) = tcx.hir_maybe_body_owned_by(self.mir_def_id()) else { return Vec::new() };
|
||||
let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
let mut finder = BindingFinder {
|
||||
typeck_results,
|
||||
@@ -928,6 +952,7 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
|
||||
has_adjustments: false,
|
||||
ref_pat_for_binding: Vec::new(),
|
||||
cannot_remove: FxHashSet::default(),
|
||||
desugar_binding_spans: Vec::new(),
|
||||
};
|
||||
finder.visit_body(body);
|
||||
|
||||
@@ -952,9 +977,15 @@ fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
|
||||
for (span, msg, suggestion) in suggestions {
|
||||
err.span_suggestion_verbose(span, msg, suggestion, Applicability::MachineApplicable);
|
||||
}
|
||||
finder.desugar_binding_spans
|
||||
}
|
||||
|
||||
fn add_move_error_details(&self, err: &mut Diag<'_>, binds_to: &[Local]) {
|
||||
fn add_move_error_details(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
binds_to: &[Local],
|
||||
desugar_spans: &[Span],
|
||||
) {
|
||||
for (j, local) in binds_to.iter().enumerate() {
|
||||
let bind_to = &self.body.local_decls[*local];
|
||||
let binding_span = bind_to.source_info.span;
|
||||
@@ -968,7 +999,11 @@ fn add_move_error_details(&self, err: &mut Diag<'_>, binds_to: &[Local]) {
|
||||
if binds_to.len() == 1 {
|
||||
let place_desc = self.local_name(*local).map(|sym| format!("`{sym}`"));
|
||||
|
||||
if let Some(expr) = self.find_expr(binding_span) {
|
||||
if !desugar_spans.contains(&binding_span)
|
||||
&& let Some(expr) = self.find_expr(binding_span)
|
||||
{
|
||||
// The binding_span doesn't correspond to a let binding desugaring
|
||||
// and is an expression where calling `.clone()` would be valid.
|
||||
let local_place: PlaceRef<'tcx> = (*local).into();
|
||||
self.suggest_cloning(err, local_place, bind_to.ty, expr, None);
|
||||
}
|
||||
|
||||
@@ -614,7 +614,7 @@ pub(crate) fn report_mutability_error(
|
||||
}
|
||||
_ => {
|
||||
let local = &self.body.local_decls[local];
|
||||
match local.local_info() {
|
||||
match *local.local_info() {
|
||||
LocalInfo::StaticRef { def_id, .. } => {
|
||||
let span = self.infcx.tcx.def_span(def_id);
|
||||
err.span_label(span, format!("this `static` cannot be {acted_on}"));
|
||||
@@ -1340,7 +1340,7 @@ fn suggest_make_local_mut(&self, err: &mut Diag<'_>, local: Local, name: Symbol)
|
||||
return;
|
||||
}
|
||||
|
||||
err.multipart_suggestion_verbose(
|
||||
err.multipart_suggestion(
|
||||
format!(
|
||||
"consider changing this to be a mutable {pointer_desc}{}{extra}",
|
||||
if is_trait_sig {
|
||||
@@ -1365,7 +1365,7 @@ fn suggest_make_local_mut(&self, err: &mut Diag<'_>, local: Local, name: Symbol)
|
||||
if self.infcx.tcx.sess.source_map().is_imported(span) {
|
||||
return;
|
||||
}
|
||||
err.multipart_suggestion_verbose(
|
||||
err.multipart_suggestion(
|
||||
"consider using `get_mut`",
|
||||
vec![(span, suggestion)],
|
||||
Applicability::MaybeIncorrect,
|
||||
|
||||
@@ -290,7 +290,7 @@ fn suggest_static_lifetime_for_gat_from_hrtb(
|
||||
});
|
||||
if suggestions.len() > 0 {
|
||||
suggestions.dedup();
|
||||
diag.multipart_suggestion_verbose(
|
||||
diag.multipart_suggestion(
|
||||
msg!("consider restricting the type parameter to the `'static` lifetime"),
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
@@ -902,7 +902,7 @@ fn add_static_impl_trait_suggestion(
|
||||
spans_suggs.push((alias_span.shrink_to_hi(), "<'a>".to_string()));
|
||||
}
|
||||
|
||||
diag.multipart_suggestion_verbose(
|
||||
diag.multipart_suggestion(
|
||||
format!(
|
||||
"to declare that the trait object {captures}, you can add a lifetime parameter `'a` in the type alias"
|
||||
),
|
||||
@@ -926,7 +926,7 @@ fn maybe_suggest_constrain_dyn_trait_impl(
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
let ConstraintCategory::CallArgument(Some(func_ty)) = category else { return };
|
||||
let ty::FnDef(fn_did, args) = func_ty.kind() else { return };
|
||||
let ty::FnDef(fn_did, args) = *func_ty.kind() else { return };
|
||||
debug!(?fn_did, ?args);
|
||||
|
||||
// Only suggest this on function calls, not closures
|
||||
@@ -938,7 +938,7 @@ fn maybe_suggest_constrain_dyn_trait_impl(
|
||||
let Ok(Some(instance)) = ty::Instance::try_resolve(
|
||||
tcx,
|
||||
self.infcx.typing_env(self.infcx.param_env),
|
||||
*fn_did,
|
||||
fn_did,
|
||||
self.infcx.resolve_vars_if_possible(args),
|
||||
) else {
|
||||
return;
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(default_field_values)]
|
||||
#![feature(file_buffered)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
@@ -27,7 +25,6 @@
|
||||
use rustc_data_structures::frozen::Frozen;
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_errors::LintDiagnostic;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
@@ -124,7 +121,7 @@ fn mir_borrowck(
|
||||
// We should eagerly check stalled coroutine obligations from HIR typeck.
|
||||
// Not doing so leads to silent normalization failures later, which will
|
||||
// fail to register opaque types in the next solver.
|
||||
tcx.check_coroutine_obligations(def)?;
|
||||
tcx.ensure_result().check_coroutine_obligations(def)?;
|
||||
|
||||
let input_body: &Body<'_> = &input_body.borrow();
|
||||
if let Some(guar) = input_body.tainted_by_errors {
|
||||
@@ -715,7 +712,7 @@ fn deref(&self) -> &Self::Target {
|
||||
}
|
||||
}
|
||||
|
||||
struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
|
||||
pub(crate) struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
|
||||
root_cx: &'a mut BorrowCheckRootCtxt<'tcx>,
|
||||
infcx: &'infcx BorrowckInferCtxt<'tcx>,
|
||||
body: &'a Body<'tcx>,
|
||||
@@ -1428,13 +1425,15 @@ fn check_backward_incompatible_drop(
|
||||
borrow,
|
||||
Some((WriteKind::StorageDeadOrDrop, place)),
|
||||
);
|
||||
this.infcx.tcx.node_span_lint(
|
||||
this.infcx.tcx.emit_node_span_lint(
|
||||
TAIL_EXPR_DROP_ORDER,
|
||||
CRATE_HIR_ID,
|
||||
borrowed,
|
||||
|diag| {
|
||||
session_diagnostics::TailExprDropOrder { borrowed }.decorate_lint(diag);
|
||||
explain.add_explanation_to_diagnostic(&this, diag, "", None, None);
|
||||
session_diagnostics::TailExprDropOrder {
|
||||
borrowed,
|
||||
callback: |diag| {
|
||||
explain.add_explanation_to_diagnostic(&this, diag, "", None, None);
|
||||
},
|
||||
},
|
||||
);
|
||||
// We may stop at the first case
|
||||
@@ -1544,8 +1543,7 @@ fn consume_rvalue(
|
||||
Rvalue::Use(operand)
|
||||
| Rvalue::Repeat(operand, _)
|
||||
| Rvalue::UnaryOp(_ /*un_op*/, operand)
|
||||
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
|
||||
| Rvalue::ShallowInitBox(operand, _ /*ty*/) => {
|
||||
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/) => {
|
||||
self.consume_operand(location, (operand, span), state)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
use polonius_engine::{Algorithm, AllFacts, Output};
|
||||
use rustc_data_structures::frozen::Frozen;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::find_attr;
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_middle::mir::pretty::PrettyPrintMirOptions;
|
||||
@@ -296,7 +295,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
|
||||
) {
|
||||
let tcx = infcx.tcx;
|
||||
let base_def_id = tcx.typeck_root_def_id(body.source.def_id());
|
||||
if !find_attr!(tcx.get_all_attrs(base_def_id), AttributeKind::RustcRegions) {
|
||||
if !find_attr!(tcx, base_def_id, RustcRegions) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -297,8 +297,9 @@ fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) {
|
||||
Rvalue::Use(operand)
|
||||
| Rvalue::Repeat(operand, _)
|
||||
| Rvalue::UnaryOp(_ /*un_op*/, operand)
|
||||
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
|
||||
| Rvalue::ShallowInitBox(operand, _ /*ty*/) => self.consume_operand(location, operand),
|
||||
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/) => {
|
||||
self.consume_operand(location, operand)
|
||||
}
|
||||
|
||||
&Rvalue::Discriminant(place) => {
|
||||
self.access_place(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::{GenericArg, Ty};
|
||||
use rustc_span::Span;
|
||||
|
||||
@@ -47,7 +47,7 @@ pub(crate) struct GenericDoesNotLiveLongEnough {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("variable does not need to be mutable")]
|
||||
pub(crate) struct VarNeedNotMut {
|
||||
#[suggestion(
|
||||
@@ -595,9 +595,20 @@ pub(crate) struct SimdIntrinsicArgConst {
|
||||
pub intrinsic: String,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag("relative drop order changing in Rust 2024")]
|
||||
pub(crate) struct TailExprDropOrder {
|
||||
#[label("this temporary value will be dropped at the end of the block")]
|
||||
pub(crate) struct TailExprDropOrder<F: FnOnce(&mut Diag<'_, ()>)> {
|
||||
pub borrowed: Span,
|
||||
pub callback: F,
|
||||
}
|
||||
|
||||
impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for TailExprDropOrder<F> {
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
|
||||
let Self { borrowed, callback } = self;
|
||||
let mut diag = Diag::new(dcx, level, "relative drop order changing in Rust 2024")
|
||||
.with_span_label(
|
||||
borrowed,
|
||||
"this temporary value will be dropped at the end of the block",
|
||||
);
|
||||
callback(&mut diag);
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,7 +296,8 @@ pub(crate) fn create(mut self) -> CreateResult<'tcx> {
|
||||
// - We must compute the normalized signature and then compute implied bounds from that
|
||||
// in order to connect any unconstrained region vars created during normalization to
|
||||
// the types of the locals corresponding to the inputs and outputs of the item. (#136547)
|
||||
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
|
||||
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst { .. })
|
||||
{
|
||||
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
|
||||
let result: Result<_, ErrorGuaranteed> = param_env
|
||||
.and(DeeplyNormalize { value: ty })
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
|
||||
//! contain revealed `impl Trait` values).
|
||||
|
||||
use std::assert_matches;
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin};
|
||||
use rustc_middle::mir::*;
|
||||
|
||||
@@ -1004,17 +1004,6 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||
}
|
||||
}
|
||||
|
||||
Rvalue::ShallowInitBox(_operand, ty) => {
|
||||
let trait_ref =
|
||||
ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, span), [*ty]);
|
||||
|
||||
self.prove_trait_ref(
|
||||
trait_ref,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::SizedBound,
|
||||
);
|
||||
}
|
||||
|
||||
Rvalue::Cast(cast_kind, op, ty) => {
|
||||
match *cast_kind {
|
||||
CastKind::PointerCoercion(
|
||||
@@ -1024,12 +1013,12 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
|
||||
let src_ty = op.ty(self.body, tcx);
|
||||
let mut src_sig = src_ty.fn_sig(tcx);
|
||||
if let ty::FnDef(def_id, _) = src_ty.kind()
|
||||
if let ty::FnDef(def_id, _) = *src_ty.kind()
|
||||
&& let ty::FnPtr(_, target_hdr) = *ty.kind()
|
||||
&& tcx.codegen_fn_attrs(def_id).safe_target_features
|
||||
&& target_hdr.safety.is_safe()
|
||||
&& let Some(safe_sig) = tcx.adjust_target_feature_sig(
|
||||
*def_id,
|
||||
def_id,
|
||||
src_sig,
|
||||
self.body.source.def_id(),
|
||||
)
|
||||
@@ -2231,7 +2220,6 @@ fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationInde
|
||||
| Rvalue::Ref(..)
|
||||
| Rvalue::RawPtr(..)
|
||||
| Rvalue::Cast(..)
|
||||
| Rvalue::ShallowInitBox(..)
|
||||
| Rvalue::BinaryOp(..)
|
||||
| Rvalue::CopyForDeref(..)
|
||||
| Rvalue::UnaryOp(..)
|
||||
|
||||
@@ -83,7 +83,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
|
||||
|
||||
let body = Some(cx.block_expr(call));
|
||||
let kind = ItemKind::Fn(Box::new(Fn {
|
||||
defaultness: ast::Defaultness::Final,
|
||||
defaultness: ast::Defaultness::Implicit,
|
||||
sig,
|
||||
ident: Ident::from_str_and_span(&global_fn_name(ALLOC_ERROR_HANDLER), span),
|
||||
generics: Generics::default(),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{AsmMacro, token};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
@@ -5,11 +6,11 @@
|
||||
use rustc_expand::base::*;
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_parse::parser::asm::*;
|
||||
use rustc_parse_format as parse;
|
||||
use rustc_session::lint;
|
||||
use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, sym};
|
||||
use rustc_target::asm::InlineAsmArch;
|
||||
use smallvec::smallvec;
|
||||
use {rustc_ast as ast, rustc_parse_format as parse};
|
||||
|
||||
use crate::errors;
|
||||
use crate::util::{ExprToSpannedString, expr_to_spanned_string};
|
||||
|
||||
@@ -8,8 +8,7 @@ mod llvm_enzyme {
|
||||
use std::string::String;
|
||||
|
||||
use rustc_ast::expand::autodiff_attrs::{
|
||||
AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
|
||||
valid_ty_for_activity,
|
||||
DiffActivity, DiffMode, valid_input_activity, valid_ret_activity, valid_ty_for_activity,
|
||||
};
|
||||
use rustc_ast::token::{Lit, LitKind, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::*;
|
||||
@@ -20,6 +19,7 @@ mod llvm_enzyme {
|
||||
MetaItemInner, MgcaDisambiguation, PatKind, Path, PathSegment, TyKind, Visibility,
|
||||
};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_hir::attrs::RustcAutodiff;
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
use tracing::{debug, trace};
|
||||
@@ -87,7 +87,7 @@ pub(crate) fn from_ast(
|
||||
meta_item: &ThinVec<MetaItemInner>,
|
||||
has_ret: bool,
|
||||
mode: DiffMode,
|
||||
) -> AutoDiffAttrs {
|
||||
) -> RustcAutodiff {
|
||||
let dcx = ecx.sess.dcx();
|
||||
|
||||
// Now we check, whether the user wants autodiff in batch/vector mode, or scalar mode.
|
||||
@@ -105,7 +105,7 @@ pub(crate) fn from_ast(
|
||||
span: meta_item[1].span(),
|
||||
width: x,
|
||||
});
|
||||
return AutoDiffAttrs::error();
|
||||
return RustcAutodiff::error();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -129,7 +129,7 @@ pub(crate) fn from_ast(
|
||||
};
|
||||
}
|
||||
if errors {
|
||||
return AutoDiffAttrs::error();
|
||||
return RustcAutodiff::error();
|
||||
}
|
||||
|
||||
// If a return type exist, we need to split the last activity,
|
||||
@@ -145,11 +145,11 @@ pub(crate) fn from_ast(
|
||||
(&DiffActivity::None, activities.as_slice())
|
||||
};
|
||||
|
||||
AutoDiffAttrs {
|
||||
RustcAutodiff {
|
||||
mode,
|
||||
width,
|
||||
ret_activity: *ret_activity,
|
||||
input_activity: input_activity.to_vec(),
|
||||
input_activity: input_activity.iter().cloned().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ pub(crate) fn expand_with_mode(
|
||||
// first get information about the annotable item: visibility, signature, name and generic
|
||||
// parameters.
|
||||
// these will be used to generate the differentiated version of the function
|
||||
let Some((vis, sig, primal, generics, impl_of_trait)) = (match &item {
|
||||
let Some((vis, sig, primal, generics, is_impl)) = (match &item {
|
||||
Annotatable::Item(iitem) => {
|
||||
extract_item_info(iitem).map(|(v, s, p, g)| (v, s, p, g, false))
|
||||
}
|
||||
@@ -224,13 +224,13 @@ pub(crate) fn expand_with_mode(
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
Annotatable::AssocItem(assoc_item, Impl { of_trait }) => match &assoc_item.kind {
|
||||
Annotatable::AssocItem(assoc_item, Impl { of_trait: _ }) => match &assoc_item.kind {
|
||||
ast::AssocItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => Some((
|
||||
assoc_item.vis.clone(),
|
||||
sig.clone(),
|
||||
ident.clone(),
|
||||
generics.clone(),
|
||||
*of_trait,
|
||||
true,
|
||||
)),
|
||||
_ => None,
|
||||
},
|
||||
@@ -309,7 +309,7 @@ pub(crate) fn expand_with_mode(
|
||||
ts.pop();
|
||||
let ts: TokenStream = TokenStream::from_iter(ts);
|
||||
|
||||
let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret, mode);
|
||||
let x: RustcAutodiff = from_ast(ecx, &meta_item_vec, has_ret, mode);
|
||||
if !x.is_active() {
|
||||
// We encountered an error, so we return the original item.
|
||||
// This allows us to potentially parse other attributes.
|
||||
@@ -328,13 +328,13 @@ pub(crate) fn expand_with_mode(
|
||||
span,
|
||||
&d_sig,
|
||||
&generics,
|
||||
impl_of_trait,
|
||||
is_impl,
|
||||
)],
|
||||
);
|
||||
|
||||
// The first element of it is the name of the function to be generated
|
||||
let d_fn = Box::new(ast::Fn {
|
||||
defaultness: ast::Defaultness::Final,
|
||||
defaultness: ast::Defaultness::Implicit,
|
||||
sig: d_sig,
|
||||
ident: first_ident(&meta_item_vec[0]),
|
||||
generics,
|
||||
@@ -603,7 +603,7 @@ fn gen_turbofish_expr(
|
||||
fn gen_enzyme_decl(
|
||||
ecx: &ExtCtxt<'_>,
|
||||
sig: &ast::FnSig,
|
||||
x: &AutoDiffAttrs,
|
||||
x: &RustcAutodiff,
|
||||
span: Span,
|
||||
) -> ast::FnSig {
|
||||
let dcx = ecx.sess.dcx();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Attributes injected into the crate root from command line using `-Z crate-attr`.
|
||||
|
||||
use rustc_ast::{self as ast};
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::Diag;
|
||||
use rustc_parse::parser::attr::InnerAttrPolicy;
|
||||
use rustc_parse::{parse_in, source_str_to_stream};
|
||||
|
||||
@@ -26,15 +26,17 @@ pub(crate) fn expand_deriving_eq(
|
||||
additional_bounds: Vec::new(),
|
||||
supports_unions: true,
|
||||
methods: vec![MethodDef {
|
||||
name: sym::assert_receiver_is_total_eq,
|
||||
name: sym::assert_fields_are_eq,
|
||||
generics: Bounds::empty(),
|
||||
explicit_self: true,
|
||||
nonself_args: vec![],
|
||||
ret_ty: Unit,
|
||||
attributes: thin_vec![
|
||||
// This method will never be called, so doing codegen etc. for it is unnecessary.
|
||||
// We prevent this by adding `#[inline]`, which improves compile-time.
|
||||
cx.attr_word(sym::inline, span),
|
||||
cx.attr_nested_word(sym::doc, sym::hidden, span),
|
||||
cx.attr_nested_word(sym::coverage, sym::off, span)
|
||||
cx.attr_nested_word(sym::coverage, sym::off, span),
|
||||
],
|
||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||
|
||||
@@ -136,7 +136,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
|
||||
of_trait: Some(Box::new(ast::TraitImplHeader {
|
||||
safety: ast::Safety::Default,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
defaultness: ast::Defaultness::Implicit,
|
||||
trait_ref,
|
||||
})),
|
||||
constness: ast::Const::No,
|
||||
@@ -159,7 +159,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
|
||||
of_trait: Some(Box::new(ast::TraitImplHeader {
|
||||
safety: ast::Safety::Default,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
defaultness: ast::Defaultness::Implicit,
|
||||
trait_ref,
|
||||
})),
|
||||
constness: ast::Const::No,
|
||||
|
||||
@@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_debug(
|
||||
name: sym::fmt,
|
||||
generics: Bounds::empty(),
|
||||
explicit_self: true,
|
||||
nonself_args: vec![(fmtr, sym::f)],
|
||||
nonself_args: vec![(fmtr, sym::character('f'))],
|
||||
ret_ty: Path(path_std!(fmt::Result)),
|
||||
attributes: thin_vec![cx.attr_word(sym::inline, span)],
|
||||
fieldless_variants_strategy:
|
||||
|
||||
@@ -67,7 +67,7 @@ fn default_struct_substructure(
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
substr: &Substructure<'_>,
|
||||
summary: &StaticFields,
|
||||
summary: &StaticFields<'_>,
|
||||
) -> BlockOrExpr {
|
||||
let expr = match summary {
|
||||
Unnamed(_, IsTuple::No) => cx.expr_ident(trait_span, substr.type_ident),
|
||||
@@ -78,16 +78,16 @@ fn default_struct_substructure(
|
||||
Named(fields) => {
|
||||
let default_fields = fields
|
||||
.iter()
|
||||
.map(|(ident, span, default_val)| {
|
||||
.map(|&(ident, span, default_val)| {
|
||||
let value = match default_val {
|
||||
// We use `Default::default()`.
|
||||
None => default_call(cx, *span),
|
||||
None => default_call(cx, span),
|
||||
// We use the field default const expression.
|
||||
Some(val) => {
|
||||
cx.expr(val.value.span, ast::ExprKind::ConstBlock(val.clone()))
|
||||
}
|
||||
};
|
||||
cx.field_imm(*span, *ident, value)
|
||||
cx.field_imm(span, ident, value)
|
||||
})
|
||||
.collect();
|
||||
cx.expr_struct_ident(trait_span, substr.type_ident, default_fields)
|
||||
|
||||
@@ -303,11 +303,11 @@ pub(crate) enum IsTuple {
|
||||
}
|
||||
|
||||
/// Fields for a static method
|
||||
pub(crate) enum StaticFields {
|
||||
pub(crate) enum StaticFields<'a> {
|
||||
/// Tuple and unit structs/enum variants like this.
|
||||
Unnamed(Vec<Span>, IsTuple),
|
||||
/// Normal structs/struct variants.
|
||||
Named(Vec<(Ident, Span, Option<AnonConst>)>),
|
||||
Named(Vec<(Ident, Span, Option<&'a AnonConst>)>),
|
||||
}
|
||||
|
||||
/// A summary of the possible sets of fields.
|
||||
@@ -331,7 +331,7 @@ pub(crate) enum SubstructureFields<'a> {
|
||||
EnumDiscr(FieldInfo, Option<Box<Expr>>),
|
||||
|
||||
/// A static method where `Self` is a struct.
|
||||
StaticStruct(&'a ast::VariantData, StaticFields),
|
||||
StaticStruct(&'a ast::VariantData, StaticFields<'a>),
|
||||
|
||||
/// A static method where `Self` is an enum.
|
||||
StaticEnum(&'a ast::EnumDef),
|
||||
@@ -540,7 +540,6 @@ pub(crate) fn expand_ext(
|
||||
.filter(|a| {
|
||||
a.has_any_name(&[
|
||||
sym::allow,
|
||||
sym::expect,
|
||||
sym::warn,
|
||||
sym::deny,
|
||||
sym::forbid,
|
||||
@@ -596,7 +595,7 @@ fn create_derived_impl(
|
||||
cx: &ExtCtxt<'_>,
|
||||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
field_tys: Vec<Box<ast::Ty>>,
|
||||
field_tys: Vec<&ast::Ty>,
|
||||
methods: Vec<Box<ast::AssocItem>>,
|
||||
is_packed: bool,
|
||||
) -> Box<ast::Item> {
|
||||
@@ -614,7 +613,7 @@ fn create_derived_impl(
|
||||
},
|
||||
attrs: ast::AttrVec::new(),
|
||||
kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias {
|
||||
defaultness: ast::Defaultness::Final,
|
||||
defaultness: ast::Defaultness::Implicit,
|
||||
ident,
|
||||
generics: Generics::default(),
|
||||
after_where_clause: ast::WhereClause::default(),
|
||||
@@ -851,7 +850,7 @@ fn create_derived_impl(
|
||||
of_trait: Some(Box::new(ast::TraitImplHeader {
|
||||
safety: self.safety,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
defaultness: ast::Defaultness::Implicit,
|
||||
trait_ref,
|
||||
})),
|
||||
constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No },
|
||||
@@ -870,8 +869,7 @@ fn expand_struct_def(
|
||||
from_scratch: bool,
|
||||
is_packed: bool,
|
||||
) -> Box<ast::Item> {
|
||||
let field_tys: Vec<Box<ast::Ty>> =
|
||||
struct_def.fields().iter().map(|field| field.ty.clone()).collect();
|
||||
let field_tys = Vec::from_iter(struct_def.fields().iter().map(|field| &*field.ty));
|
||||
|
||||
let methods = self
|
||||
.methods
|
||||
@@ -923,11 +921,13 @@ fn expand_enum_def(
|
||||
generics: &Generics,
|
||||
from_scratch: bool,
|
||||
) -> Box<ast::Item> {
|
||||
let mut field_tys = Vec::new();
|
||||
|
||||
for variant in &enum_def.variants {
|
||||
field_tys.extend(variant.data.fields().iter().map(|field| field.ty.clone()));
|
||||
}
|
||||
let field_tys = Vec::from_iter(
|
||||
enum_def
|
||||
.variants
|
||||
.iter()
|
||||
.flat_map(|variant| variant.data.fields())
|
||||
.map(|field| &*field.ty),
|
||||
);
|
||||
|
||||
let methods = self
|
||||
.methods
|
||||
@@ -1073,7 +1073,7 @@ fn create_method(
|
||||
let trait_lo_sp = span.shrink_to_lo();
|
||||
|
||||
let sig = ast::FnSig { header: ast::FnHeader::default(), decl: fn_decl, span };
|
||||
let defaultness = ast::Defaultness::Final;
|
||||
let defaultness = ast::Defaultness::Implicit;
|
||||
|
||||
// Create the method.
|
||||
Box::new(ast::AssocItem {
|
||||
@@ -1160,8 +1160,8 @@ fn expand_struct_method_body<'b>(
|
||||
fn expand_static_struct_method_body(
|
||||
&self,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_: &TraitDef<'_>,
|
||||
struct_def: &VariantData,
|
||||
trait_: &TraitDef<'a>,
|
||||
struct_def: &'a VariantData,
|
||||
type_ident: Ident,
|
||||
nonselflike_args: &[Box<Expr>],
|
||||
) -> BlockOrExpr {
|
||||
@@ -1480,13 +1480,13 @@ fn expand_static_enum_method_body(
|
||||
|
||||
// general helper methods.
|
||||
impl<'a> TraitDef<'a> {
|
||||
fn summarise_struct(&self, cx: &ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
|
||||
fn summarise_struct(&self, cx: &ExtCtxt<'_>, struct_def: &'a VariantData) -> StaticFields<'a> {
|
||||
let mut named_idents = Vec::new();
|
||||
let mut just_spans = Vec::new();
|
||||
for field in struct_def.fields() {
|
||||
let sp = field.span.with_ctxt(self.span.ctxt());
|
||||
match field.ident {
|
||||
Some(ident) => named_idents.push((ident, sp, field.default.clone())),
|
||||
Some(ident) => named_idents.push((ident, sp, field.default.as_ref())),
|
||||
_ => just_spans.push(sp),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::formatting::DiagMessageAddArg;
|
||||
use rustc_errors::{
|
||||
Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans,
|
||||
Subdiagnostic, msg,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("avoid using `.intel_syntax`, Intel syntax is the default")]
|
||||
pub(crate) struct AvoidIntelSyntax;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("avoid using `.att_syntax`, prefer using `options(att_syntax)` instead")]
|
||||
pub(crate) struct AvoidAttSyntax;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("include macro expected single expression in source")]
|
||||
pub(crate) struct IncompleteInclude;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("cannot test inner items")]
|
||||
pub(crate) struct UnnameableTestItems;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("duplicated attribute")]
|
||||
pub(crate) struct DuplicateMacroAttribute;
|
||||
|
||||
@@ -763,15 +764,17 @@ pub(crate) struct FormatUnusedArg {
|
||||
// form of diagnostic.
|
||||
impl Subdiagnostic for FormatUnusedArg {
|
||||
fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
|
||||
diag.arg("named", self.named);
|
||||
let msg = diag.eagerly_translate(msg!(
|
||||
"{$named ->
|
||||
[true] named argument
|
||||
*[false] argument
|
||||
} never used"
|
||||
));
|
||||
diag.remove_arg("named");
|
||||
diag.span_label(self.span, msg);
|
||||
diag.span_label(
|
||||
self.span,
|
||||
msg!(
|
||||
"{$named ->
|
||||
[true] named argument
|
||||
*[false] argument
|
||||
} never used"
|
||||
)
|
||||
.arg("named", self.named)
|
||||
.format(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -946,17 +949,14 @@ pub(crate) struct AsmClobberNoReg {
|
||||
|
||||
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AsmClobberNoReg {
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
|
||||
// eager translation as `span_labels` takes `AsRef<str>`
|
||||
let lbl1 = dcx.eagerly_translate_to_string(msg!("clobber_abi"), [].into_iter());
|
||||
let lbl2 = dcx.eagerly_translate_to_string(msg!("generic outputs"), [].into_iter());
|
||||
Diag::new(
|
||||
dcx,
|
||||
level,
|
||||
msg!("asm with `clobber_abi` must specify explicit registers for outputs"),
|
||||
)
|
||||
.with_span(self.spans.clone())
|
||||
.with_span_labels(self.clobbers, &lbl1)
|
||||
.with_span_labels(self.spans, &lbl2)
|
||||
.with_span_labels(self.clobbers, "clobber_abi")
|
||||
.with_span_labels(self.spans, "generic outputs")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ fn allocator_fn(&self, method: &AllocatorMethod) -> Stmt {
|
||||
let sig = FnSig { decl, header, span: self.span };
|
||||
let body = Some(self.cx.block_expr(result));
|
||||
let kind = ItemKind::Fn(Box::new(Fn {
|
||||
defaultness: ast::Defaultness::Final,
|
||||
defaultness: ast::Defaultness::Implicit,
|
||||
sig,
|
||||
ident: Ident::from_str_and_span(&global_fn_name(method.name), self.span),
|
||||
generics: Generics::default(),
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(assert_matches))]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_order_by)]
|
||||
#![feature(proc_macro_internals)]
|
||||
#![feature(proc_macro_quote)]
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
//! The expansion from a test function to the appropriate test struct for libtest
|
||||
//! Ideally, this code would be in libtest but for efficiency and error messages it lives here.
|
||||
|
||||
use std::iter;
|
||||
use std::{assert_matches, iter};
|
||||
|
||||
use rustc_ast::{self as ast, GenericParamKind, HasNodeId, attr, join_path_idents};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_errors::{Applicability, Diag, Level};
|
||||
use rustc_expand::base::*;
|
||||
use rustc_hir::Attribute;
|
||||
@@ -283,7 +282,7 @@ pub(crate) fn expand_test_or_bench(
|
||||
// const $ident: test::TestDescAndFn =
|
||||
ast::ItemKind::Const(
|
||||
ast::ConstItem {
|
||||
defaultness: ast::Defaultness::Final,
|
||||
defaultness: ast::Defaultness::Implicit,
|
||||
ident: Ident::new(fn_.ident.name, sp),
|
||||
generics: ast::Generics::default(),
|
||||
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
|
||||
|
||||
@@ -330,7 +330,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> Box<ast::Item> {
|
||||
|
||||
let decl = ecx.fn_decl(ThinVec::new(), ast::FnRetTy::Ty(main_ret_ty));
|
||||
let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
|
||||
let defaultness = ast::Defaultness::Final;
|
||||
let defaultness = ast::Defaultness::Implicit;
|
||||
|
||||
// Honor the reexport_test_harness_main attribute
|
||||
let main_ident = match cx.reexport_test_harness_main {
|
||||
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
#!/bin/bash
|
||||
# Ported from rust-lang/rust commit d29e4783dff30f9526eeba3929ebfe86c00c9dad in src/ci/scripts/free-disk-space-linux.sh
|
||||
set -euo pipefail
|
||||
|
||||
# Script inspired by https://github.com/jlumbroso/free-disk-space
|
||||
isX86() {
|
||||
local arch
|
||||
arch=$(uname -m)
|
||||
if [ "$arch" = "x86_64" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# In aws codebuild, the variable RUNNER_ENVIRONMENT is "self-hosted".
|
||||
isGitHubRunner() {
|
||||
# `:-` means "use the value of RUNNER_ENVIRONMENT if it exists, otherwise use an empty string".
|
||||
if [[ "${RUNNER_ENVIRONMENT:-}" == "github-hosted" ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# print a line of the specified character
|
||||
printSeparationLine() {
|
||||
for ((i = 0; i < 80; i++)); do
|
||||
printf "%s" "$1"
|
||||
done
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
# REF: https://stackoverflow.com/a/450821/408734
|
||||
getAvailableSpace() {
|
||||
df -a | awk 'NR > 1 {avail+=$4} END {print avail}'
|
||||
}
|
||||
|
||||
# REF: https://unix.stackexchange.com/a/44087/60849
|
||||
formatByteCount() {
|
||||
numfmt --to=iec-i --suffix=B --padding=7 "${1}000"
|
||||
}
|
||||
|
||||
# macro to output saved space
|
||||
printSavedSpace() {
|
||||
# Disk space before the operation
|
||||
local before=${1}
|
||||
local title=${2:-}
|
||||
|
||||
local after
|
||||
after=$(getAvailableSpace)
|
||||
local saved=$((after - before))
|
||||
|
||||
if [ "$saved" -lt 0 ]; then
|
||||
echo "::warning::Saved space is negative: $saved. Using '0' as saved space."
|
||||
saved=0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
printSeparationLine "*"
|
||||
if [ -n "${title}" ]; then
|
||||
echo "=> ${title}: Saved $(formatByteCount "$saved")"
|
||||
else
|
||||
echo "=> Saved $(formatByteCount "$saved")"
|
||||
fi
|
||||
printSeparationLine "*"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# macro to print output of df with caption
|
||||
printDF() {
|
||||
local caption=${1}
|
||||
|
||||
printSeparationLine "="
|
||||
echo "${caption}"
|
||||
echo ""
|
||||
echo "$ df -h"
|
||||
echo ""
|
||||
df -h
|
||||
printSeparationLine "="
|
||||
}
|
||||
|
||||
removeUnusedFilesAndDirs() {
|
||||
local to_remove=(
|
||||
"/usr/share/java"
|
||||
)
|
||||
|
||||
if isGitHubRunner; then
|
||||
to_remove+=(
|
||||
"/usr/local/aws-sam-cli"
|
||||
"/usr/local/doc/cmake"
|
||||
"/usr/local/julia"*
|
||||
"/usr/local/lib/android"
|
||||
"/usr/local/share/chromedriver-"*
|
||||
"/usr/local/share/chromium"
|
||||
"/usr/local/share/cmake-"*
|
||||
"/usr/local/share/edge_driver"
|
||||
"/usr/local/share/emacs"
|
||||
"/usr/local/share/gecko_driver"
|
||||
"/usr/local/share/icons"
|
||||
"/usr/local/share/powershell"
|
||||
"/usr/local/share/vcpkg"
|
||||
"/usr/local/share/vim"
|
||||
"/usr/share/apache-maven-"*
|
||||
"/usr/share/gradle-"*
|
||||
"/usr/share/kotlinc"
|
||||
"/usr/share/miniconda"
|
||||
"/usr/share/php"
|
||||
"/usr/share/ri"
|
||||
"/usr/share/swift"
|
||||
|
||||
# binaries
|
||||
"/usr/local/bin/azcopy"
|
||||
"/usr/local/bin/bicep"
|
||||
"/usr/local/bin/ccmake"
|
||||
"/usr/local/bin/cmake-"*
|
||||
"/usr/local/bin/cmake"
|
||||
"/usr/local/bin/cpack"
|
||||
"/usr/local/bin/ctest"
|
||||
"/usr/local/bin/helm"
|
||||
"/usr/local/bin/kind"
|
||||
"/usr/local/bin/kustomize"
|
||||
"/usr/local/bin/minikube"
|
||||
"/usr/local/bin/packer"
|
||||
"/usr/local/bin/phpunit"
|
||||
"/usr/local/bin/pulumi-"*
|
||||
"/usr/local/bin/pulumi"
|
||||
"/usr/local/bin/stack"
|
||||
|
||||
# Haskell runtime
|
||||
"/usr/local/.ghcup"
|
||||
|
||||
# Azure
|
||||
"/opt/az"
|
||||
"/usr/share/az_"*
|
||||
)
|
||||
|
||||
if [ -n "${AGENT_TOOLSDIRECTORY:-}" ]; then
|
||||
# Environment variable set by GitHub Actions
|
||||
to_remove+=(
|
||||
"${AGENT_TOOLSDIRECTORY}"
|
||||
)
|
||||
else
|
||||
echo "::warning::AGENT_TOOLSDIRECTORY is not set. Skipping removal."
|
||||
fi
|
||||
else
|
||||
# Remove folders and files present in AWS CodeBuild
|
||||
to_remove+=(
|
||||
# binaries
|
||||
"/usr/local/bin/ecs-cli"
|
||||
"/usr/local/bin/eksctl"
|
||||
"/usr/local/bin/kubectl"
|
||||
|
||||
"${HOME}/.gradle"
|
||||
"${HOME}/.dotnet"
|
||||
"${HOME}/.goenv"
|
||||
"${HOME}/.phpenv"
|
||||
|
||||
)
|
||||
fi
|
||||
|
||||
for element in "${to_remove[@]}"; do
|
||||
if [ ! -e "$element" ]; then
|
||||
# The file or directory doesn't exist.
|
||||
# Maybe it was removed in a newer version of the runner or it's not present in a
|
||||
# specific architecture (e.g. ARM).
|
||||
echo "::warning::Directory or file $element does not exist, skipping."
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove all files and directories at once to save time.
|
||||
sudo rm -rf "${to_remove[@]}"
|
||||
}
|
||||
|
||||
execAndMeasureSpaceChange() {
|
||||
local operation=${1} # Function to execute
|
||||
local title=${2}
|
||||
|
||||
local before
|
||||
before=$(getAvailableSpace)
|
||||
$operation
|
||||
|
||||
printSavedSpace "$before" "$title"
|
||||
}
|
||||
|
||||
# REF: https://github.com/apache/flink/blob/master/tools/azure-pipelines/free_disk_space.sh
|
||||
cleanPackages() {
|
||||
local packages=(
|
||||
'^aspnetcore-.*'
|
||||
'^dotnet-.*'
|
||||
'^llvm-.*'
|
||||
'^mongodb-.*'
|
||||
'firefox'
|
||||
'libgl1-mesa-dri'
|
||||
'mono-devel'
|
||||
'php.*'
|
||||
)
|
||||
|
||||
if isGitHubRunner; then
|
||||
packages+=(
|
||||
azure-cli
|
||||
)
|
||||
|
||||
if isX86; then
|
||||
packages+=(
|
||||
'google-chrome-stable'
|
||||
'google-cloud-cli'
|
||||
'google-cloud-sdk'
|
||||
'powershell'
|
||||
)
|
||||
fi
|
||||
else
|
||||
packages+=(
|
||||
'google-chrome-stable'
|
||||
)
|
||||
fi
|
||||
|
||||
WAIT_DPKG_LOCK="-o DPkg::Lock::Timeout=60"
|
||||
sudo apt-get ${WAIT_DPKG_LOCK} -qq remove -y --fix-missing "${packages[@]}"
|
||||
|
||||
sudo apt-get ${WAIT_DPKG_LOCK} autoremove -y \
|
||||
|| echo "::warning::The command [sudo apt-get autoremove -y] failed"
|
||||
sudo apt-get ${WAIT_DPKG_LOCK} clean \
|
||||
|| echo "::warning::The command [sudo apt-get clean] failed"
|
||||
}
|
||||
|
||||
# They aren't present in ubuntu 24 runners.
|
||||
cleanDocker() {
|
||||
echo "=> Removing the following docker images:"
|
||||
sudo docker image ls
|
||||
echo "=> Removing docker images..."
|
||||
sudo docker image prune --all --force || true
|
||||
}
|
||||
|
||||
# Remove Swap storage
|
||||
cleanSwap() {
|
||||
sudo swapoff -a || true
|
||||
sudo rm -rf /mnt/swapfile || true
|
||||
free -h
|
||||
}
|
||||
|
||||
# Display initial disk space stats
|
||||
AVAILABLE_INITIAL=$(getAvailableSpace)
|
||||
|
||||
printDF "BEFORE CLEAN-UP:"
|
||||
echo ""
|
||||
execAndMeasureSpaceChange cleanPackages "Unused packages"
|
||||
execAndMeasureSpaceChange cleanDocker "Docker images"
|
||||
execAndMeasureSpaceChange cleanSwap "Swap storage"
|
||||
execAndMeasureSpaceChange removeUnusedFilesAndDirs "Unused files and directories"
|
||||
|
||||
# Output saved space statistic
|
||||
echo ""
|
||||
printDF "AFTER CLEAN-UP:"
|
||||
|
||||
echo ""
|
||||
echo ""
|
||||
|
||||
printSavedSpace "$AVAILABLE_INITIAL" "Total saved"
|
||||
@@ -49,6 +49,12 @@ jobs:
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: Free disk space
|
||||
if: runner.os == 'Linux'
|
||||
env:
|
||||
RUNNER_ENVIRONMENT: github-hosted
|
||||
run: .github/scripts/free-disk-space.sh
|
||||
|
||||
- name: Cache cargo target dir
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
|
||||
@@ -13,6 +13,6 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
sed -i 's/components.*/components = []/' rust-toolchain.toml
|
||||
- uses: rustsec/audit-check@v1.4.1
|
||||
- uses: rustsec/audit-check@v2.0.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -28,9 +28,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.19.0"
|
||||
version = "3.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
]
|
||||
@@ -43,42 +43,42 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-assembler-x64"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bd963a645179fa33834ba61fa63353998543b07f877e208da9eb47d4a70d1e7"
|
||||
checksum = "0377b13bf002a0774fcccac4f1102a10f04893d24060cf4b7350c87e4cbb647c"
|
||||
dependencies = [
|
||||
"cranelift-assembler-x64-meta",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-assembler-x64-meta"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f6d5739c9dc6b5553ca758d78d87d127dd19f397f776efecf817b8ba8d0bb01"
|
||||
checksum = "cfa027979140d023b25bf7509fb7ede3a54c3d3871fb5ead4673c4b633f671a2"
|
||||
dependencies = [
|
||||
"cranelift-srcgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff402c11bb1c9652b67a3e885e84b1b8d00c13472c8fd85211e06a41a63c3e03"
|
||||
checksum = "618e4da87d9179a70b3c2f664451ca8898987aa6eb9f487d16988588b5d8cc40"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bitset"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "769a0d88c2f5539e9c5536a93a7bf164b0dc68d91e3d00723e5b4ffc1440afdc"
|
||||
checksum = "db53764b5dad233b37b8f5dc54d3caa9900c54579195e00f17ea21f03f71aaa7"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4351f721fb3b26add1c180f0a75c7474bab2f903c8b777c6ca65238ded59a78"
|
||||
checksum = "4ae927f1d8c0abddaa863acd201471d56e7fc6c3925104f4861ed4dc3e28b421"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"cranelift-assembler-x64",
|
||||
@@ -102,9 +102,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61f86c0ba5b96713643f4dd0de0df12844de9c7bb137d6829b174b706939aa74"
|
||||
checksum = "d3fcf1e3e6757834bd2584f4cbff023fcc198e9279dcb5d684b4bb27a9b19f54"
|
||||
dependencies = [
|
||||
"cranelift-assembler-x64-meta",
|
||||
"cranelift-codegen-shared",
|
||||
@@ -114,33 +114,33 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f08605eee8d51fd976a970bd5b16c9529b51b624f8af68f80649ffb172eb85a4"
|
||||
checksum = "205dcb9e6ccf9d368b7466be675ff6ee54a63e36da6fe20e72d45169cf6fd254"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-control"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "623aab0a09e40f0cf0b5d35eb7832bae4c4f13e3768228e051a6c1a60e88ef5f"
|
||||
checksum = "108eca9fcfe86026054f931eceaf57b722c1b97464bf8265323a9b5877238817"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea0f066e07e3bcbe38884cc5c94c32c7a90267d69df80f187d9dfe421adaa7c4"
|
||||
checksum = "a0d96496910065d3165f84ff8e1e393916f4c086f88ac8e1b407678bc78735aa"
|
||||
dependencies = [
|
||||
"cranelift-bitset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40865b02a0e52ca8e580ad64feef530cb1d05f6bb4972b4eef05e3eaeae81701"
|
||||
checksum = "e303983ad7e23c850f24d9c41fc3cb346e1b930f066d3966545e4c98dac5c9fb"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
@@ -150,15 +150,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "104b3c117ae513e9af1d90679842101193a5ccb96ac9f997966d85ea25be2852"
|
||||
checksum = "24b0cf8d867d891245836cac7abafb0a5b0ea040a019d720702b3b8bcba40bfa"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3aa5f855cfb8e4253ed2d0dfc1a0b6ebe4912e67aa8b7ee14026ff55ca17f1fe"
|
||||
checksum = "dcf1e35da6eca2448395f483eb172ce71dd7842f7dc96f44bb8923beafe43c6d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@@ -176,9 +176,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1d01806b191b59f4fc4680293dd5f554caf2de5b62f95eff5beef7acb46c29c"
|
||||
checksum = "792ba2a54100e34f8a36e3e329a5207cafd1f0918a031d34695db73c163fdcc7"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@@ -187,9 +187,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5c54e0a358bc05b48f2032e1c320e7f468da068604f2869b77052eab68eb0fe"
|
||||
checksum = "e24b641e315443e27807b69c440fe766737d7e718c68beb665a2d69259c77bf3"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
@@ -198,9 +198,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-object"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d17e0216be5daabab616647c1918e06dae0708474ba5f7b7762ac24ea5eb126"
|
||||
checksum = "ecba1f219a201cf946150538e631defd620c5051b62c52ecb89a0004bab263d4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@@ -213,9 +213,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-srcgen"
|
||||
version = "0.127.0"
|
||||
version = "0.128.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc6f4b039f453b66c75e9f7886e5a2af96276e151f44dc19b24b58f9a0c98009"
|
||||
checksum = "a4e378a54e7168a689486d67ee1f818b7e5356e54ae51a1d7a53f4f13f7f8b7a"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
@@ -257,9 +257,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.4"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
dependencies = [
|
||||
"foldhash",
|
||||
]
|
||||
@@ -282,9 +282,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.178"
|
||||
version = "0.2.180"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
@@ -298,9 +298,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
@@ -337,27 +337,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.103"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.42"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regalloc2"
|
||||
version = "0.13.3"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e249c660440317032a71ddac302f25f1d5dff387667bcc3978d1f77aa31ac34"
|
||||
checksum = "08effbc1fa53aaebff69521a5c05640523fab037b34a4a2c109506bc938246fa"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"bumpalo",
|
||||
@@ -446,9 +446,9 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.111"
|
||||
version = "2.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -457,9 +457,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.13.3"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c"
|
||||
checksum = "b1dd07eb858a2067e2f3c7155d54e929265c264e6f37efe3ee7a8d1b5a1dd0ba"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
@@ -469,9 +469,9 @@ checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-jit-icache-coherence"
|
||||
version = "40.0.0"
|
||||
version = "41.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0858b470463f3e7c73acd6049046049e64be17b98901c2db5047450cf83df1fe"
|
||||
checksum = "bada5ca1cc47df7d14100e2254e187c2486b426df813cea2dd2553a7469f7674"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
@@ -481,9 +481,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-math"
|
||||
version = "40.0.0"
|
||||
version = "41.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "222e1a590ece4e898f20af1e541b61d2cb803f2557e7eaff23e6c1db5434454a"
|
||||
checksum = "cf6f615d528eda9adc6eefb062135f831b5215c348f4c3ec3e143690c730605b"
|
||||
dependencies = [
|
||||
"libm",
|
||||
]
|
||||
|
||||
@@ -8,12 +8,12 @@ crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
# These have to be in sync with each other
|
||||
cranelift-codegen = { version = "0.127.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] }
|
||||
cranelift-frontend = { version = "0.127.0" }
|
||||
cranelift-module = { version = "0.127.0" }
|
||||
cranelift-native = { version = "0.127.0" }
|
||||
cranelift-jit = { version = "0.127.0", optional = true }
|
||||
cranelift-object = { version = "0.127.0" }
|
||||
cranelift-codegen = { version = "0.128.3", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] }
|
||||
cranelift-frontend = { version = "0.128.3" }
|
||||
cranelift-module = { version = "0.128.3" }
|
||||
cranelift-native = { version = "0.128.3" }
|
||||
cranelift-jit = { version = "0.128.3", optional = true }
|
||||
cranelift-object = { version = "0.128.3" }
|
||||
target-lexicon = "0.13"
|
||||
gimli = { version = "0.32", default-features = false, features = ["write"] }
|
||||
object = { version = "0.37.3", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
@@ -24,12 +24,12 @@ smallvec = "1.8.1"
|
||||
|
||||
[patch.crates-io]
|
||||
# Uncomment to use an unreleased version of cranelift
|
||||
#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-40.0.0" }
|
||||
#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-40.0.0" }
|
||||
#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-40.0.0" }
|
||||
#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-40.0.0" }
|
||||
#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-40.0.0" }
|
||||
#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-40.0.0" }
|
||||
#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" }
|
||||
#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" }
|
||||
#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" }
|
||||
#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" }
|
||||
#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" }
|
||||
#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" }
|
||||
|
||||
# Uncomment to use local checkout of cranelift
|
||||
#cranelift-codegen = { path = "../wasmtime/cranelift/codegen" }
|
||||
|
||||
@@ -43,6 +43,8 @@ pub(crate) fn build_backend(
|
||||
|
||||
cmd.arg("--release");
|
||||
|
||||
cmd.arg("-Zno-embed-metadata");
|
||||
|
||||
eprintln!("[BUILD] rustc_codegen_cranelift");
|
||||
crate::utils::spawn_and_wait(cmd);
|
||||
|
||||
|
||||
@@ -235,17 +235,14 @@ fn build_clif_sysroot_for_triple(
|
||||
|
||||
if let Some(prefix) = env::var_os("CG_CLIF_STDLIB_REMAP_PATH_PREFIX") {
|
||||
rustflags.push("--remap-path-prefix".to_owned());
|
||||
rustflags.push(format!(
|
||||
"{}={}",
|
||||
STDLIB_SRC.to_path(dirs).to_str().unwrap(),
|
||||
prefix.to_str().unwrap()
|
||||
));
|
||||
rustflags.push(format!("library/={}/library", prefix.to_str().unwrap()));
|
||||
}
|
||||
compiler.rustflags.extend(rustflags);
|
||||
let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
|
||||
build_cmd.arg("--release");
|
||||
build_cmd.arg("--features").arg("backtrace panic-unwind");
|
||||
build_cmd.arg(format!("-Zroot-dir={}", STDLIB_SRC.to_path(dirs).display()));
|
||||
build_cmd.arg("-Zno-embed-metadata");
|
||||
build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true");
|
||||
build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
|
||||
if compiler.triple.contains("apple") {
|
||||
@@ -260,7 +257,7 @@ fn build_clif_sysroot_for_triple(
|
||||
for entry in fs::read_dir(build_dir.join("deps")).unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
if let Some(ext) = entry.path().extension() {
|
||||
if ext == "rmeta" || ext == "d" || ext == "dSYM" || ext == "clif" {
|
||||
if ext == "d" || ext == "dSYM" || ext == "clif" {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -20,7 +20,7 @@ aot.mini_core_hello_world
|
||||
|
||||
testsuite.base_sysroot
|
||||
aot.arbitrary_self_types_pointers_and_wrappers
|
||||
jit.std_example
|
||||
#jit.std_example # FIXME(#1619) broken for some reason
|
||||
aot.std_example
|
||||
aot.dst_field_align
|
||||
aot.subslice-patterns-const-eval
|
||||
|
||||
@@ -622,11 +622,6 @@ fn deref(&self) -> &Self::Target {
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "exchange_malloc"]
|
||||
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
|
||||
unsafe { libc::malloc(size) }
|
||||
}
|
||||
|
||||
#[lang = "drop"]
|
||||
pub trait Drop {
|
||||
fn drop(&mut self);
|
||||
|
||||
+1
-1
@@ -17,8 +17,8 @@ index 1e336bf..35e6f54 100644
|
||||
@@ -2,4 +2,3 @@
|
||||
// tidy-alphabetical-start
|
||||
-#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
|
||||
#![cfg_attr(test, feature(cfg_select))]
|
||||
#![feature(array_ptr_get)]
|
||||
#![feature(array_try_from_fn)]
|
||||
diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs
|
||||
index b735957..ea728b6 100644
|
||||
--- a/coretests/tests/atomic.rs
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
From 116abc64add4d617104993a7a3011f20bcf31ef2 Mon Sep 17 00:00:00 2001
|
||||
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
|
||||
Date: Mon, 26 Jan 2026 16:20:58 +0000
|
||||
Subject: [PATCH] Ensure va_end doesn't get emitted unless VaList is actually
|
||||
used
|
||||
|
||||
---
|
||||
library/core/src/ffi/va_list.rs | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs
|
||||
index d0f1553..75129af 100644
|
||||
--- a/library/core/src/ffi/va_list.rs
|
||||
+++ b/library/core/src/ffi/va_list.rs
|
||||
@@ -217,6 +217,7 @@ impl Clone for VaList<'_> {
|
||||
|
||||
#[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
|
||||
impl<'f> const Drop for VaList<'f> {
|
||||
+ #[inline]
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: this variable argument list is being dropped, so won't be read from again.
|
||||
unsafe { va_end(self) }
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
From 285d5716fcfa6d43a3516d899b73bc85da322c25 Mon Sep 17 00:00:00 2001
|
||||
From: xonx <119700621+xonx4l@users.noreply.github.com>
|
||||
Date: Sun, 15 Feb 2026 14:06:49 +0000
|
||||
Subject: [PATCH] Disable f16 math tests for cranelift
|
||||
|
||||
---
|
||||
coretests/tests/floats/mod.rs | 26 +++++++++++++-------------
|
||||
1 file changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/coretests/tests/floats/mod.rs b/coretests/tests/floats/mod.rs
|
||||
index c61961f8584..d7b4fa20322 100644
|
||||
--- a/coretests/tests/floats/mod.rs
|
||||
+++ b/coretests/tests/floats/mod.rs
|
||||
@@ -1534,7 +1534,7 @@ fn s_nan() -> Float {
|
||||
name: powf,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -1557,7 +1557,7 @@ fn s_nan() -> Float {
|
||||
name: exp,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -1578,7 +1578,7 @@ fn s_nan() -> Float {
|
||||
name: exp2,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -1598,7 +1598,7 @@ fn s_nan() -> Float {
|
||||
name: ln,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -1620,7 +1620,7 @@ fn s_nan() -> Float {
|
||||
name: log,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -1645,7 +1645,7 @@ fn s_nan() -> Float {
|
||||
name: log2,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -1668,7 +1668,7 @@ fn s_nan() -> Float {
|
||||
name: log10,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -1692,7 +1692,7 @@ fn s_nan() -> Float {
|
||||
name: asinh,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -1725,7 +1725,7 @@ fn s_nan() -> Float {
|
||||
name: acosh,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -1753,7 +1753,7 @@ fn s_nan() -> Float {
|
||||
name: atanh,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -1779,7 +1779,7 @@ fn s_nan() -> Float {
|
||||
name: gamma,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -1814,7 +1814,7 @@ fn s_nan() -> Float {
|
||||
name: ln_gamma,
|
||||
attrs: {
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
@@ -2027,7 +2027,7 @@ fn s_nan() -> Float {
|
||||
attrs: {
|
||||
// FIXME(f16_f128): add math tests when available
|
||||
const: #[cfg(false)],
|
||||
- f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
|
||||
+ f16: #[cfg(false)], // FIXME(rust-lang/rustc_codegen_cranelift#1622)
|
||||
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
|
||||
},
|
||||
test {
|
||||
--
|
||||
2.50.1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2025-12-23"
|
||||
channel = "nightly-2026-02-18"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"]
|
||||
profile = "minimal"
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import gdb
|
||||
|
||||
|
||||
def jitmap_raw():
|
||||
pid = gdb.selected_inferior().pid
|
||||
jitmap_file = open("/tmp/perf-%d.map" % (pid,), "r")
|
||||
jitmap = jitmap_file.read()
|
||||
jitmap_file.close()
|
||||
return jitmap
|
||||
|
||||
|
||||
def jit_functions():
|
||||
jitmap = jitmap_raw()
|
||||
|
||||
functions = []
|
||||
for line in jitmap.strip().split("\n"):
|
||||
[addr, size, name] = line.split(" ")
|
||||
functions.append((int(addr, 16), int(size, 16), name))
|
||||
|
||||
return functions
|
||||
|
||||
|
||||
class JitDecorator(gdb.FrameDecorator.FrameDecorator):
|
||||
def __init__(self, fobj, name):
|
||||
super(JitDecorator, self).__init__(fobj)
|
||||
self.name = name
|
||||
|
||||
def function(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class JitFilter:
|
||||
"""
|
||||
A backtrace filter which reads perf map files produced by cranelift-jit.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.name = "JitFilter"
|
||||
self.enabled = True
|
||||
self.priority = 0
|
||||
|
||||
gdb.current_progspace().frame_filters[self.name] = self
|
||||
|
||||
# FIXME add an actual unwinder or somehow register JITed .eh_frame with gdb to avoid relying on
|
||||
# gdb unwinder heuristics.
|
||||
def filter(self, frame_iter):
|
||||
for frame in frame_iter:
|
||||
frame_addr = frame.inferior_frame().pc()
|
||||
for addr, size, name in jit_functions():
|
||||
if frame_addr >= addr and frame_addr < addr + size:
|
||||
yield JitDecorator(frame, name)
|
||||
break
|
||||
else:
|
||||
yield frame
|
||||
|
||||
|
||||
JitFilter()
|
||||
@@ -49,25 +49,45 @@ std-features = ["panic-unwind"]
|
||||
EOF
|
||||
|
||||
cat <<EOF | git apply -
|
||||
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
|
||||
index 2e16f2cf27..3ac3df99a8 100644
|
||||
--- a/src/bootstrap/bootstrap.py
|
||||
+++ b/src/bootstrap/bootstrap.py
|
||||
@@ -1147,6 +1147,8 @@ class RustBuild(object):
|
||||
args += ["-Zwarnings"]
|
||||
env["CARGO_BUILD_WARNINGS"] = "deny"
|
||||
|
||||
+ env["RUSTFLAGS"] += " -Zbinary-dep-depinfo"
|
||||
+
|
||||
# Add RUSTFLAGS_BOOTSTRAP to RUSTFLAGS for bootstrap compilation.
|
||||
# Note that RUSTFLAGS_BOOTSTRAP should always be added to the end of
|
||||
# RUSTFLAGS, since that causes RUSTFLAGS_BOOTSTRAP to override RUSTFLAGS.
|
||||
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
|
||||
index a656927b1f6..44fc5546fac 100644
|
||||
--- a/src/bootstrap/src/core/config/config.rs
|
||||
+++ b/src/bootstrap/src/core/config/config.rs
|
||||
@@ -2249,14 +2249,6 @@ pub fn parse_download_ci_llvm<'a>(
|
||||
);
|
||||
@@ -2249,7 +2249,7 @@ pub fn parse_download_ci_llvm<'a>(
|
||||
}
|
||||
|
||||
- #[cfg(not(test))]
|
||||
#[cfg(not(test))]
|
||||
- if b && dwn_ctx.is_running_on_ci && CiEnv::is_rust_lang_managed_ci_job() {
|
||||
- // On rust-lang CI, we must always rebuild LLVM if there were any modifications to it
|
||||
- panic!(
|
||||
- "\`llvm.download-ci-llvm\` cannot be set to \`true\` on CI. Use \`if-unchanged\` instead."
|
||||
- );
|
||||
- }
|
||||
-
|
||||
// If download-ci-llvm=true we also want to check that CI llvm is available
|
||||
b && llvm::is_ci_llvm_available_for_target(&dwn_ctx.host_target, asserts)
|
||||
}
|
||||
+ if false && dwn_ctx.is_running_on_ci && CiEnv::is_rust_lang_managed_ci_job() {
|
||||
// On rust-lang CI, we must always rebuild LLVM if there were any modifications to it
|
||||
panic!(
|
||||
"\`llvm.download-ci-llvm\` cannot be set to \`true\` on CI. Use \`if-unchanged\` instead."
|
||||
diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs
|
||||
index 330fb465de..a4593ed96f 100644
|
||||
--- a/src/build_helper/src/git.rs
|
||||
+++ b/src/build_helper/src/git.rs
|
||||
@@ -218,7 +218,7 @@ pub fn get_closest_upstream_commit(
|
||||
config: &GitConfig<'_>,
|
||||
env: CiEnv,
|
||||
) -> Result<Option<String>, String> {
|
||||
- let base = match env {
|
||||
+ let base = match CiEnv::None {
|
||||
CiEnv::None => "HEAD",
|
||||
CiEnv::GitHubActions => {
|
||||
// On CI, we should always have a non-upstream merge commit at the tip,
|
||||
EOF
|
||||
|
||||
popd
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user