mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-12 08:36:03 +00:00
Auto merge of #17581 - lnicola:sync-from-rust, r=lnicola
minor: Sync from rust
This commit is contained in:
commit
a3d6efc9bc
1
.clang-format
Normal file
1
.clang-format
Normal file
@ -0,0 +1 @@
|
||||
BasedOnStyle: LLVM
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -50,6 +50,7 @@ build/
|
||||
/target
|
||||
/src/bootstrap/target
|
||||
/src/tools/x/target
|
||||
/inc-fat/
|
||||
# Created by default with `src/ci/docker/run.sh`
|
||||
/obj/
|
||||
/rustc-ice*
|
||||
|
2
.ignore
Normal file
2
.ignore
Normal file
@ -0,0 +1,2 @@
|
||||
# Make vscode *not* count `config.toml` as ignored, so it is included in search
|
||||
!/config.toml
|
@ -29,12 +29,14 @@ Files: compiler/*
|
||||
x
|
||||
x.ps1
|
||||
x.py
|
||||
.clang-format
|
||||
.editorconfig
|
||||
.git-blame-ignore-revs
|
||||
.gitattributes
|
||||
.gitignore
|
||||
.gitmodules
|
||||
.mailmap
|
||||
.ignore
|
||||
Copyright: The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: MIT or Apache-2.0
|
||||
|
||||
|
318
Cargo.lock
318
Cargo.lock
@ -228,6 +228,12 @@ dependencies = [
|
||||
"backtrace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ar"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69"
|
||||
|
||||
[[package]]
|
||||
name = "ar_archive_writer"
|
||||
version = "0.2.0"
|
||||
@ -266,7 +272,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -601,9 +607,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.5.5"
|
||||
version = "4.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2020fa13af48afc65a9a87335bda648309ab3d154cd03c7ff95b378c7ed39c4"
|
||||
checksum = "fbca90c87c2a04da41e95d1856e8bcd22f159bdbfa147314d2ce5218057b0e58"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
@ -617,7 +623,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -638,13 +644,13 @@ dependencies = [
|
||||
"filetime",
|
||||
"futures",
|
||||
"if_chain",
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"parking_lot",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc_tools_util",
|
||||
"serde",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
"tempfile",
|
||||
"termize",
|
||||
"tokio",
|
||||
@ -670,7 +676,7 @@ dependencies = [
|
||||
"aho-corasick",
|
||||
"clap",
|
||||
"indoc",
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"opener 0.6.1",
|
||||
"shell-escape",
|
||||
"walkdir",
|
||||
@ -685,7 +691,7 @@ dependencies = [
|
||||
"clippy_config",
|
||||
"clippy_utils",
|
||||
"declare_clippy_lint",
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"quine-mc_cluskey",
|
||||
"regex",
|
||||
"regex-syntax 0.8.4",
|
||||
@ -707,8 +713,9 @@ version = "0.1.81"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"clippy_config",
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"rustc-semver",
|
||||
"rustc_apfloat",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -754,7 +761,7 @@ dependencies = [
|
||||
"nom",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -990,7 +997,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1001,7 +1008,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1025,9 +1032,9 @@ dependencies = [
|
||||
name = "declare_clippy_lint"
|
||||
version = "0.1.81"
|
||||
dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1068,7 +1075,7 @@ dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1078,7 +1085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b"
|
||||
dependencies = [
|
||||
"derive_builder_core",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1089,7 +1096,7 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1101,7 +1108,7 @@ dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1132,16 +1139,16 @@ version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
|
||||
dependencies = [
|
||||
"dirs-sys 0.4.1",
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "4.0.0"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
|
||||
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
|
||||
dependencies = [
|
||||
"dirs-sys 0.3.7",
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1154,17 +1161,6 @@ dependencies = [
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.4.1"
|
||||
@ -1190,13 +1186,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.4"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
|
||||
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1516,7 +1512,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1749,7 +1745,7 @@ dependencies = [
|
||||
"markup5ever",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1790,18 +1786,6 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_list"
|
||||
version = "1.5.0"
|
||||
@ -1855,51 +1839,6 @@ version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_collections",
|
||||
"icu_normalizer_data",
|
||||
"icu_properties",
|
||||
"icu_provider",
|
||||
"smallvec",
|
||||
"utf16_iter",
|
||||
"utf8_iter",
|
||||
"write16",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_collections",
|
||||
"icu_locid_transform",
|
||||
"icu_properties_data",
|
||||
"icu_provider",
|
||||
"tinystr",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties_data"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
|
||||
|
||||
[[package]]
|
||||
name = "icu_provider"
|
||||
version = "1.5.0"
|
||||
@ -1938,7 +1877,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1949,14 +1888,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "1.0.0"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed"
|
||||
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
|
||||
dependencies = [
|
||||
"icu_normalizer",
|
||||
"icu_properties",
|
||||
"smallvec",
|
||||
"utf8_iter",
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2075,15 +2012,6 @@ version = "1.70.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
@ -2165,9 +2093,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "leb128"
|
||||
@ -2226,7 +2154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.48.5",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2540,9 +2468,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.3"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
|
||||
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"compiler_builtins",
|
||||
@ -2968,7 +2896,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3160,9 +3088,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.85"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -3213,7 +3141,19 @@ dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"getopts",
|
||||
"memchr",
|
||||
"pulldown-cmark-escape",
|
||||
"pulldown-cmark-escape 0.10.1",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8746739f11d39ce5ad5c2520a9b75285310dbfe78c541ccf832d38615765aec0"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"memchr",
|
||||
"pulldown-cmark-escape 0.11.0",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
@ -3223,6 +3163,12 @@ version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3"
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark-escape"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark-to-cmark"
|
||||
version = "13.0.0"
|
||||
@ -3472,6 +3418,8 @@ dependencies = [
|
||||
name = "run_make_support"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"ar",
|
||||
"bstr",
|
||||
"gimli 0.28.1",
|
||||
"object 0.34.0",
|
||||
"regex",
|
||||
@ -3531,6 +3479,13 @@ dependencies = [
|
||||
"stable_mir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-perf-wrapper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-rayon"
|
||||
version = "0.5.0"
|
||||
@ -3664,7 +3619,7 @@ dependencies = [
|
||||
name = "rustc_ast_passes"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
@ -3684,7 +3639,7 @@ dependencies = [
|
||||
name = "rustc_ast_pretty"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"rustc_ast",
|
||||
"rustc_lexer",
|
||||
"rustc_span",
|
||||
@ -3725,7 +3680,7 @@ name = "rustc_borrowck"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"either",
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"polonius-engine",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
@ -3778,7 +3733,7 @@ name = "rustc_codegen_llvm"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"libc",
|
||||
"measureme",
|
||||
"object 0.32.2",
|
||||
@ -3817,7 +3772,7 @@ dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"cc",
|
||||
"either",
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"object 0.32.2",
|
||||
@ -4064,7 +4019,7 @@ dependencies = [
|
||||
"fluent-syntax",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
@ -4097,7 +4052,7 @@ dependencies = [
|
||||
name = "rustc_hir_analysis"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
@ -4136,7 +4091,7 @@ dependencies = [
|
||||
name = "rustc_hir_typeck"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"rustc_ast",
|
||||
"rustc_ast_ir",
|
||||
"rustc_attr",
|
||||
@ -4198,7 +4153,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4213,8 +4168,10 @@ dependencies = [
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_next_trait_solver",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"rustc_type_ir",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
]
|
||||
@ -4345,7 +4302,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@ -4420,7 +4377,7 @@ dependencies = [
|
||||
name = "rustc_mir_build"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"rustc_apfloat",
|
||||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
@ -4467,7 +4424,7 @@ name = "rustc_mir_transform"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"either",
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
@ -4667,7 +4624,7 @@ name = "rustc_resolve"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"pulldown-cmark 0.9.6",
|
||||
"pulldown-cmark 0.11.0",
|
||||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
@ -4746,6 +4703,8 @@ name = "rustc_smir"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_data_structures",
|
||||
"rustc_hir",
|
||||
"rustc_middle",
|
||||
@ -4761,6 +4720,7 @@ dependencies = [
|
||||
name = "rustc_span"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"derivative",
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"md-5",
|
||||
@ -4820,9 +4780,7 @@ checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f"
|
||||
name = "rustc_trait_selection"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"derivative",
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"rustc_ast",
|
||||
"rustc_ast_ir",
|
||||
"rustc_attr",
|
||||
@ -4830,7 +4788,6 @@ dependencies = [
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_infer",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
@ -4843,7 +4800,6 @@ dependencies = [
|
||||
"rustc_target",
|
||||
"rustc_transmute",
|
||||
"rustc_type_ir",
|
||||
"rustc_type_ir_macros",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
]
|
||||
@ -4865,7 +4821,7 @@ dependencies = [
|
||||
name = "rustc_transmute"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"rustc_ast_ir",
|
||||
"rustc_data_structures",
|
||||
"rustc_hir",
|
||||
@ -4881,7 +4837,7 @@ dependencies = [
|
||||
name = "rustc_ty_utils"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"rustc_ast_ir",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
@ -4905,6 +4861,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"derivative",
|
||||
"indexmap",
|
||||
"rustc_ast_ir",
|
||||
"rustc_data_structures",
|
||||
"rustc_index",
|
||||
@ -4922,7 +4879,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@ -4944,8 +4901,9 @@ dependencies = [
|
||||
"base64",
|
||||
"expect-test",
|
||||
"indexmap",
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"minifier",
|
||||
"pulldown-cmark 0.9.6",
|
||||
"regex",
|
||||
"rustdoc-json-types",
|
||||
"serde",
|
||||
@ -5020,25 +4978,24 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustfmt-nightly"
|
||||
version = "1.7.0"
|
||||
version = "1.7.1"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.2",
|
||||
"anyhow",
|
||||
"bytecount",
|
||||
"cargo_metadata 0.15.4",
|
||||
"cargo_metadata 0.18.1",
|
||||
"clap",
|
||||
"clap-cargo",
|
||||
"diff",
|
||||
"dirs",
|
||||
"getopts",
|
||||
"ignore",
|
||||
"itertools 0.11.0",
|
||||
"lazy_static",
|
||||
"itertools",
|
||||
"regex",
|
||||
"rustfmt-config_proc_macro",
|
||||
"serde",
|
||||
@ -5171,7 +5128,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5464,9 +5421,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.66"
|
||||
version = "2.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
|
||||
checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -5481,7 +5438,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5658,7 +5615,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5696,12 +5653,15 @@ dependencies = [
|
||||
name = "tidy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"build_helper",
|
||||
"cargo_metadata 0.15.4",
|
||||
"fluent-syntax",
|
||||
"ignore",
|
||||
"miropt-test-tools",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"semver",
|
||||
"similar",
|
||||
"termcolor",
|
||||
"walkdir",
|
||||
]
|
||||
@ -5871,7 +5831,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6071,7 +6031,7 @@ checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
"unic-langid-impl",
|
||||
]
|
||||
|
||||
@ -6091,6 +6051,12 @@ dependencies = [
|
||||
"ucd-parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
@ -6192,9 +6158,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.1"
|
||||
version = "2.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56"
|
||||
checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
@ -6207,24 +6173,12 @@ version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "utf16_iter"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
|
||||
|
||||
[[package]]
|
||||
name = "utf8-width"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
|
||||
|
||||
[[package]]
|
||||
name = "utf8_iter"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
@ -6309,7 +6263,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -6331,7 +6285,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -6404,15 +6358,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-bindgen"
|
||||
version = "0.57.0"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ccb96113d6277ba543c0f77e1c5494af8094bf9daf9b85acdc3f1b620e7c7b4"
|
||||
checksum = "91cd28d93c692351f3a6e5615567c56756e330bee1c99c6bdd57bfc5ab15f589"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
"windows-metadata",
|
||||
]
|
||||
|
||||
@ -6427,9 +6381,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-metadata"
|
||||
version = "0.57.0"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8308d076825b9d9e5abc64f8113e96d02b2aeeba869b20fdd65c7e70cda13dfc"
|
||||
checksum = "2e837f3c3012cfe9e7086302a93f441a7999439be1ad4c530d55d2f6d2921809"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
@ -6588,12 +6542,6 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "write16"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
version = "0.5.5"
|
||||
@ -6664,7 +6612,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@ -6685,7 +6633,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6705,7 +6653,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@ -6728,5 +6676,5 @@ checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
"syn 2.0.67",
|
||||
]
|
||||
|
@ -44,6 +44,7 @@ members = [
|
||||
"src/tools/rustdoc-gui-test",
|
||||
"src/tools/opt-dist",
|
||||
"src/tools/coverage-dump",
|
||||
"src/tools/rustc-perf-wrapper",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
|
@ -48,7 +48,7 @@ If building LLVM from source, you'll need additional tools:
|
||||
[LLVM's documentation](https://llvm.org/docs/GettingStarted.html#host-c-toolchain-both-compiler-and-standard-library)
|
||||
* `ninja`, or GNU `make` 3.81 or later (Ninja is recommended, especially on
|
||||
Windows)
|
||||
* `cmake` 3.13.4 or later
|
||||
* `cmake` version listed on [LLVM's documentation](https://llvm.org/docs/GettingStarted.html#software)
|
||||
* `libstdc++-static` may be required on some Linux distributions such as Fedora
|
||||
and Ubuntu
|
||||
|
||||
|
@ -186,7 +186,7 @@ pub trait LayoutCalculator {
|
||||
let (present_first, present_second) = {
|
||||
let mut present_variants = variants
|
||||
.iter_enumerated()
|
||||
.filter_map(|(i, v)| if absent(v) { None } else { Some(i) });
|
||||
.filter_map(|(i, v)| if !repr.c() && absent(v) { None } else { Some(i) });
|
||||
(present_variants.next(), present_variants.next())
|
||||
};
|
||||
let present_first = match present_first {
|
||||
@ -621,7 +621,7 @@ where
|
||||
let discr_type = repr.discr_type();
|
||||
let bits = Integer::from_attr(dl, discr_type).size().bits();
|
||||
for (i, mut val) in discriminants {
|
||||
if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
|
||||
if !repr.c() && variants[i].iter().any(|f| f.abi.is_uninhabited()) {
|
||||
continue;
|
||||
}
|
||||
if discr_type.is_signed() {
|
||||
|
@ -427,11 +427,13 @@ pub struct Size {
|
||||
raw: u64,
|
||||
}
|
||||
|
||||
// Safety: Ord is implement as just comparing numerical values and numerical values
|
||||
// are not changed by (de-)serialization.
|
||||
#[cfg(feature = "nightly")]
|
||||
unsafe impl StableOrd for Size {
|
||||
impl StableOrd for Size {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = true;
|
||||
|
||||
// `Ord` is implemented as just comparing numerical values and numerical values
|
||||
// are not changed by (de-)serialization.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
// This is debug-printed a lot in larger structs, don't waste too much space there
|
||||
@ -1427,7 +1429,7 @@ pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
|
||||
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
|
||||
Single { index: VariantIdx },
|
||||
|
||||
/// Enum-likes with more than one inhabited variant: each variant comes with
|
||||
/// Enum-likes with more than one variant: each variant comes with
|
||||
/// a *discriminant* (usually the same as the variant index but the user can
|
||||
/// assign explicit discriminant values). That discriminant is encoded
|
||||
/// as a *tag* on the machine. The layout of each variant is
|
||||
|
@ -176,6 +176,8 @@ pub enum GenericArgs {
|
||||
AngleBracketed(AngleBracketedArgs),
|
||||
/// The `(A, B)` and `C` in `Foo(A, B) -> C`.
|
||||
Parenthesized(ParenthesizedArgs),
|
||||
/// `(..)` in return type notation.
|
||||
ParenthesizedElided(Span),
|
||||
}
|
||||
|
||||
impl GenericArgs {
|
||||
@ -187,6 +189,7 @@ impl GenericArgs {
|
||||
match self {
|
||||
AngleBracketed(data) => data.span,
|
||||
Parenthesized(data) => data.span,
|
||||
ParenthesizedElided(span) => *span,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -194,11 +197,11 @@ impl GenericArgs {
|
||||
/// Concrete argument in the sequence of generic args.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum GenericArg {
|
||||
/// `'a` in `Foo<'a>`
|
||||
/// `'a` in `Foo<'a>`.
|
||||
Lifetime(Lifetime),
|
||||
/// `Bar` in `Foo<Bar>`
|
||||
/// `Bar` in `Foo<Bar>`.
|
||||
Type(P<Ty>),
|
||||
/// `1` in `Foo<1>`
|
||||
/// `1` in `Foo<1>`.
|
||||
Const(AnonConst),
|
||||
}
|
||||
|
||||
@ -352,7 +355,7 @@ pub enum GenericParamKind {
|
||||
ty: P<Ty>,
|
||||
/// Span of the `const` keyword.
|
||||
kw_span: Span,
|
||||
/// Optional default value for the const generic param
|
||||
/// Optional default value for the const generic param.
|
||||
default: Option<AnonConst>,
|
||||
},
|
||||
}
|
||||
@ -711,6 +714,7 @@ pub enum ByRef {
|
||||
}
|
||||
|
||||
impl ByRef {
|
||||
#[must_use]
|
||||
pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self {
|
||||
if let ByRef::Yes(old_mutbl) = &mut self {
|
||||
*old_mutbl = cmp::min(*old_mutbl, mutbl);
|
||||
@ -829,7 +833,7 @@ pub enum PatKind {
|
||||
/// only one rest pattern may occur in the pattern sequences.
|
||||
Rest,
|
||||
|
||||
// A never pattern `!`
|
||||
// A never pattern `!`.
|
||||
Never,
|
||||
|
||||
/// Parentheses in patterns used for grouping (i.e., `(PAT)`).
|
||||
@ -1118,9 +1122,9 @@ impl LocalKind {
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct Arm {
|
||||
pub attrs: AttrVec,
|
||||
/// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`
|
||||
/// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`.
|
||||
pub pat: P<Pat>,
|
||||
/// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`
|
||||
/// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`.
|
||||
pub guard: Option<P<Expr>>,
|
||||
/// Match arm body. Omitted if the pattern is a never pattern.
|
||||
pub body: Option<P<Expr>>,
|
||||
@ -1351,12 +1355,12 @@ pub struct Closure {
|
||||
pub fn_arg_span: Span,
|
||||
}
|
||||
|
||||
/// Limit types of a range (inclusive or exclusive)
|
||||
/// Limit types of a range (inclusive or exclusive).
|
||||
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)]
|
||||
pub enum RangeLimits {
|
||||
/// Inclusive at the beginning, exclusive at the end
|
||||
/// Inclusive at the beginning, exclusive at the end.
|
||||
HalfOpen,
|
||||
/// Inclusive at the beginning and end
|
||||
/// Inclusive at the beginning and end.
|
||||
Closed,
|
||||
}
|
||||
|
||||
@ -1397,9 +1401,9 @@ pub struct StructExpr {
|
||||
pub enum ExprKind {
|
||||
/// An array (e.g, `[a, b, c, d]`).
|
||||
Array(ThinVec<P<Expr>>),
|
||||
/// Allow anonymous constants from an inline `const` block
|
||||
/// Allow anonymous constants from an inline `const` block.
|
||||
ConstBlock(AnonConst),
|
||||
/// A function call
|
||||
/// A function call.
|
||||
///
|
||||
/// The first field resolves to the function itself,
|
||||
/// and the second field is the list of arguments.
|
||||
@ -1453,8 +1457,11 @@ pub enum ExprKind {
|
||||
/// A block (`'label: { ... }`).
|
||||
Block(P<Block>, Option<Label>),
|
||||
/// An `async` block (`async move { ... }`),
|
||||
/// or a `gen` block (`gen move { ... }`)
|
||||
Gen(CaptureBy, P<Block>, GenBlockKind),
|
||||
/// or a `gen` block (`gen move { ... }`).
|
||||
///
|
||||
/// The span is the "decl", which is the header before the body `{ }`
|
||||
/// including the `asyng`/`gen` keywords and possibly `move`.
|
||||
Gen(CaptureBy, P<Block>, GenBlockKind, Span),
|
||||
/// An await expression (`my_future.await`). Span is of await keyword.
|
||||
Await(P<Expr>, Span),
|
||||
|
||||
@ -2048,7 +2055,7 @@ impl UintTy {
|
||||
/// * the `A: Bound` in `Trait<A: Bound>`
|
||||
/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy`
|
||||
/// * the `C = { Ct }` in `Trait<C = { Ct }>` (feature `associated_const_equality`)
|
||||
/// * the `f(): Bound` in `Trait<f(): Bound>` (feature `return_type_notation`)
|
||||
/// * the `f(..): Bound` in `Trait<f(..): Bound>` (feature `return_type_notation`)
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct AssocItemConstraint {
|
||||
pub id: NodeId,
|
||||
@ -2126,7 +2133,8 @@ pub struct BareFnTy {
|
||||
pub ext: Extern,
|
||||
pub generic_params: ThinVec<GenericParam>,
|
||||
pub decl: P<FnDecl>,
|
||||
/// Span of the `fn(...) -> ...` part.
|
||||
/// Span of the `[unsafe] [extern] fn(...) -> ...` part, i.e. everything
|
||||
/// after the generic params (if there are any, e.g. `for<'a>`).
|
||||
pub decl_span: Span,
|
||||
}
|
||||
|
||||
@ -2149,9 +2157,9 @@ pub enum TyKind {
|
||||
Never,
|
||||
/// A tuple (`(A, B, C, D,...)`).
|
||||
Tup(ThinVec<P<Ty>>),
|
||||
/// An anonymous struct type i.e. `struct { foo: Type }`
|
||||
/// An anonymous struct type i.e. `struct { foo: Type }`.
|
||||
AnonStruct(NodeId, ThinVec<FieldDef>),
|
||||
/// An anonymous union type i.e. `union { bar: Type }`
|
||||
/// An anonymous union type i.e. `union { bar: Type }`.
|
||||
AnonUnion(NodeId, ThinVec<FieldDef>),
|
||||
/// A path (`module::module::...::Type`), optionally
|
||||
/// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
|
||||
@ -2225,9 +2233,9 @@ pub enum TraitObjectSyntax {
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum PreciseCapturingArg {
|
||||
/// Lifetime parameter
|
||||
/// Lifetime parameter.
|
||||
Lifetime(Lifetime),
|
||||
/// Type or const parameter
|
||||
/// Type or const parameter.
|
||||
Arg(Path, NodeId),
|
||||
}
|
||||
|
||||
@ -2521,11 +2529,11 @@ pub enum Safety {
|
||||
/// Iterator`.
|
||||
#[derive(Copy, Clone, Encodable, Decodable, Debug)]
|
||||
pub enum CoroutineKind {
|
||||
/// `async`, which returns an `impl Future`
|
||||
/// `async`, which returns an `impl Future`.
|
||||
Async { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId },
|
||||
/// `gen`, which returns an `impl Iterator`
|
||||
/// `gen`, which returns an `impl Iterator`.
|
||||
Gen { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId },
|
||||
/// `async gen`, which returns an `impl AsyncIterator`
|
||||
/// `async gen`, which returns an `impl AsyncIterator`.
|
||||
AsyncGen { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId },
|
||||
}
|
||||
|
||||
@ -2742,7 +2750,7 @@ pub struct Variant {
|
||||
pub data: VariantData,
|
||||
/// Explicit discriminant, e.g., `Foo = 1`.
|
||||
pub disr_expr: Option<AnonConst>,
|
||||
/// Is a macro placeholder
|
||||
/// Is a macro placeholder.
|
||||
pub is_placeholder: bool,
|
||||
}
|
||||
|
||||
@ -3016,19 +3024,19 @@ impl Item {
|
||||
/// `extern` qualifier on a function item or function type.
|
||||
#[derive(Clone, Copy, Encodable, Decodable, Debug)]
|
||||
pub enum Extern {
|
||||
/// No explicit extern keyword was used
|
||||
/// No explicit extern keyword was used.
|
||||
///
|
||||
/// E.g. `fn foo() {}`
|
||||
/// E.g. `fn foo() {}`.
|
||||
None,
|
||||
/// An explicit extern keyword was used, but with implicit ABI
|
||||
/// An explicit extern keyword was used, but with implicit ABI.
|
||||
///
|
||||
/// E.g. `extern fn foo() {}`
|
||||
/// E.g. `extern fn foo() {}`.
|
||||
///
|
||||
/// This is just `extern "C"` (see `rustc_target::spec::abi::Abi::FALLBACK`)
|
||||
/// This is just `extern "C"` (see `rustc_target::spec::abi::Abi::FALLBACK`).
|
||||
Implicit(Span),
|
||||
/// An explicit extern keyword was used with an explicit ABI
|
||||
/// An explicit extern keyword was used with an explicit ABI.
|
||||
///
|
||||
/// E.g. `extern "C" fn foo() {}`
|
||||
/// E.g. `extern "C" fn foo() {}`.
|
||||
Explicit(StrLit, Span),
|
||||
}
|
||||
|
||||
@ -3047,13 +3055,13 @@ impl Extern {
|
||||
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
|
||||
#[derive(Clone, Copy, Encodable, Decodable, Debug)]
|
||||
pub struct FnHeader {
|
||||
/// Whether this is `unsafe`, or has a default safety
|
||||
/// Whether this is `unsafe`, or has a default safety.
|
||||
pub safety: Safety,
|
||||
/// Whether this is `async`, `gen`, or nothing.
|
||||
pub coroutine_kind: Option<CoroutineKind>,
|
||||
/// The `const` keyword, if any
|
||||
pub constness: Const,
|
||||
/// The `extern` keyword and corresponding ABI string, if any
|
||||
/// The `extern` keyword and corresponding ABI string, if any.
|
||||
pub ext: Extern,
|
||||
}
|
||||
|
||||
@ -3184,38 +3192,6 @@ pub struct StaticItem {
|
||||
pub expr: Option<P<Expr>>,
|
||||
}
|
||||
|
||||
/// A static item in `extern` block.
|
||||
// This struct is identical to StaticItem for now but it's going to have a safety attribute.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct StaticForeignItem {
|
||||
pub ty: P<Ty>,
|
||||
pub safety: Safety,
|
||||
pub mutability: Mutability,
|
||||
pub expr: Option<P<Expr>>,
|
||||
}
|
||||
|
||||
impl From<StaticItem> for StaticForeignItem {
|
||||
fn from(static_item: StaticItem) -> StaticForeignItem {
|
||||
StaticForeignItem {
|
||||
ty: static_item.ty,
|
||||
safety: static_item.safety,
|
||||
mutability: static_item.mutability,
|
||||
expr: static_item.expr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StaticForeignItem> for StaticItem {
|
||||
fn from(static_item: StaticForeignItem) -> StaticItem {
|
||||
StaticItem {
|
||||
ty: static_item.ty,
|
||||
safety: static_item.safety,
|
||||
mutability: static_item.mutability,
|
||||
expr: static_item.expr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct ConstItem {
|
||||
pub defaultness: Defaultness,
|
||||
@ -3279,7 +3255,7 @@ pub enum ItemKind {
|
||||
///
|
||||
/// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
|
||||
Trait(Box<Trait>),
|
||||
/// Trait alias
|
||||
/// Trait alias.
|
||||
///
|
||||
/// E.g., `trait Foo = Bar + Quux;`.
|
||||
TraitAlias(Generics, GenericBounds),
|
||||
@ -3430,7 +3406,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum ForeignItemKind {
|
||||
/// A foreign static item (`static FOO: u8`).
|
||||
Static(Box<StaticForeignItem>),
|
||||
Static(Box<StaticItem>),
|
||||
/// An foreign function.
|
||||
Fn(Box<Fn>),
|
||||
/// An foreign type.
|
||||
|
@ -10,8 +10,6 @@ use crate::{AssocItem, Expr, ForeignItem, Item, NodeId};
|
||||
use crate::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
|
||||
use crate::{AttrVec, Attribute, Stmt, StmtKind};
|
||||
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@ -91,37 +89,6 @@ impl<T: AstDeref<Target: HasNodeId>> HasNodeId for T {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for AST nodes having a span.
|
||||
pub trait HasSpan {
|
||||
fn span(&self) -> Span;
|
||||
}
|
||||
|
||||
macro_rules! impl_has_span {
|
||||
($($T:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl HasSpan for $T {
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
impl_has_span!(AssocItem, Block, Expr, ForeignItem, Item, Pat, Path, Stmt, Ty, Visibility);
|
||||
|
||||
impl<T: AstDeref<Target: HasSpan>> HasSpan for T {
|
||||
fn span(&self) -> Span {
|
||||
self.ast_deref().span()
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSpan for AttrItem {
|
||||
fn span(&self) -> Span {
|
||||
self.span()
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for AST nodes having (or not having) collected tokens.
|
||||
pub trait HasTokens {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream>;
|
||||
|
@ -202,14 +202,17 @@ impl Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tokens(&self) -> TokenStream {
|
||||
// Named `get_tokens` to distinguish it from the `<Attribute as HasTokens>::tokens` method.
|
||||
pub fn get_tokens(&self) -> TokenStream {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal
|
||||
.tokens
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| panic!("attribute is missing tokens: {self:?}"))
|
||||
.to_attr_token_stream()
|
||||
.to_tokenstream(),
|
||||
AttrKind::Normal(normal) => TokenStream::new(
|
||||
normal
|
||||
.tokens
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| panic!("attribute is missing tokens: {self:?}"))
|
||||
.to_attr_token_stream()
|
||||
.to_token_trees(),
|
||||
),
|
||||
&AttrKind::DocComment(comment_kind, data) => TokenStream::token_alone(
|
||||
token::DocComment(comment_kind, self.style, data),
|
||||
self.span,
|
||||
@ -327,7 +330,8 @@ impl MetaItem {
|
||||
I: Iterator<Item = &'a TokenTree>,
|
||||
{
|
||||
// FIXME: Share code with `parse_path`.
|
||||
let path = match tokens.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref() {
|
||||
let tt = tokens.next().map(|tt| TokenTree::uninterpolate(tt));
|
||||
let path = match tt.as_deref() {
|
||||
Some(&TokenTree::Token(
|
||||
Token { kind: ref kind @ (token::Ident(..) | token::PathSep), span },
|
||||
_,
|
||||
@ -368,6 +372,12 @@ impl MetaItem {
|
||||
token::Nonterminal::NtPath(path) => (**path).clone(),
|
||||
_ => return None,
|
||||
},
|
||||
Some(TokenTree::Token(
|
||||
Token { kind: token::OpenDelim(_) | token::CloseDelim(_), .. },
|
||||
_,
|
||||
)) => {
|
||||
panic!("Should be `AttrTokenTree::Delimited`, not delim tokens: {:?}", tt);
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi());
|
||||
|
@ -44,7 +44,7 @@ pub mod tokenstream;
|
||||
pub mod visit;
|
||||
|
||||
pub use self::ast::*;
|
||||
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasSpan, HasTokens};
|
||||
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasTokens};
|
||||
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
|
||||
|
@ -20,7 +20,7 @@ use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
use smallvec::{smallvec, Array, SmallVec};
|
||||
use std::ops::DerefMut;
|
||||
use std::{panic, ptr};
|
||||
use std::panic;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
pub trait ExpectOne<A: Array> {
|
||||
@ -318,19 +318,8 @@ pub trait MutVisitor: Sized {
|
||||
//
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
pub fn visit_clobber<T: DummyAstNode>(t: &mut T, f: impl FnOnce(T) -> T) {
|
||||
unsafe {
|
||||
// Safe because `t` is used in a read-only fashion by `read()` before
|
||||
// being overwritten by `write()`.
|
||||
let old_t = ptr::read(t);
|
||||
let new_t =
|
||||
panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t))).unwrap_or_else(|err| {
|
||||
// Set `t` to some valid but possible meaningless value,
|
||||
// and pass the fatal error further.
|
||||
ptr::write(t, T::dummy());
|
||||
panic::resume_unwind(err);
|
||||
});
|
||||
ptr::write(t, new_t);
|
||||
}
|
||||
let old_t = std::mem::replace(t, T::dummy());
|
||||
*t = f(old_t);
|
||||
}
|
||||
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
@ -402,10 +391,10 @@ fn visit_attr_args<T: MutVisitor>(args: &mut AttrArgs, vis: &mut T) {
|
||||
AttrArgs::Empty => {}
|
||||
AttrArgs::Delimited(args) => visit_delim_args(args, vis),
|
||||
AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => {
|
||||
vis.visit_span(eq_span);
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_span(eq_span);
|
||||
}
|
||||
AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
|
||||
AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => {
|
||||
unreachable!("in literal form when visiting mac args eq: {:?}", lit)
|
||||
}
|
||||
}
|
||||
@ -414,13 +403,13 @@ fn visit_attr_args<T: MutVisitor>(args: &mut AttrArgs, vis: &mut T) {
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
fn visit_delim_args<T: MutVisitor>(args: &mut DelimArgs, vis: &mut T) {
|
||||
let DelimArgs { dspan, delim: _, tokens } = args;
|
||||
visit_delim_span(dspan, vis);
|
||||
visit_tts(tokens, vis);
|
||||
visit_delim_span(dspan, vis);
|
||||
}
|
||||
|
||||
pub fn visit_delim_span<T: MutVisitor>(dspan: &mut DelimSpan, vis: &mut T) {
|
||||
vis.visit_span(&mut dspan.open);
|
||||
vis.visit_span(&mut dspan.close);
|
||||
pub fn visit_delim_span<T: MutVisitor>(DelimSpan { open, close }: &mut DelimSpan, vis: &mut T) {
|
||||
vis.visit_span(open);
|
||||
vis.visit_span(close);
|
||||
}
|
||||
|
||||
pub fn noop_flat_map_pat_field<T: MutVisitor>(
|
||||
@ -429,10 +418,10 @@ pub fn noop_flat_map_pat_field<T: MutVisitor>(
|
||||
) -> SmallVec<[PatField; 1]> {
|
||||
let PatField { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = &mut fp;
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_pat(pat);
|
||||
vis.visit_span(span);
|
||||
visit_attrs(attrs, vis);
|
||||
smallvec![fp]
|
||||
}
|
||||
|
||||
@ -441,11 +430,12 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
|
||||
vis.visit_path(prefix);
|
||||
match kind {
|
||||
UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)),
|
||||
UseTreeKind::Nested { items, .. } => {
|
||||
UseTreeKind::Nested { items, span } => {
|
||||
for (tree, id) in items {
|
||||
vis.visit_use_tree(tree);
|
||||
vis.visit_id(id);
|
||||
vis.visit_use_tree(tree);
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
UseTreeKind::Glob => {}
|
||||
}
|
||||
@ -454,8 +444,8 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
|
||||
|
||||
pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
|
||||
let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_pat(pat);
|
||||
visit_opt(guard, |guard| vis.visit_expr(guard));
|
||||
visit_opt(body, |body| vis.visit_expr(body));
|
||||
@ -486,12 +476,9 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
|
||||
let Ty { id, kind, span, tokens } = ty.deref_mut();
|
||||
vis.visit_id(id);
|
||||
match kind {
|
||||
TyKind::Infer
|
||||
| TyKind::ImplicitSelf
|
||||
| TyKind::Err(_)
|
||||
| TyKind::Dummy
|
||||
| TyKind::Never
|
||||
| TyKind::CVarArgs => {}
|
||||
TyKind::Err(_guar) => {}
|
||||
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Never | TyKind::CVarArgs => {
|
||||
}
|
||||
TyKind::Slice(ty) => vis.visit_ty(ty),
|
||||
TyKind::Ptr(mt) => vis.visit_mt(mt),
|
||||
TyKind::Ref(lt, mt) => {
|
||||
@ -533,8 +520,8 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
|
||||
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
|
||||
}
|
||||
}
|
||||
vis.visit_span(span);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis: &mut T) {
|
||||
@ -548,10 +535,10 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
|
||||
visitor: &mut T,
|
||||
) -> SmallVec<[Variant; 1]> {
|
||||
let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
|
||||
visitor.visit_ident(ident);
|
||||
visitor.visit_vis(vis);
|
||||
visit_attrs(attrs, visitor);
|
||||
visitor.visit_id(id);
|
||||
visit_attrs(attrs, visitor);
|
||||
visitor.visit_vis(vis);
|
||||
visitor.visit_ident(ident);
|
||||
visitor.visit_variant_data(data);
|
||||
visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
|
||||
visitor.visit_span(span);
|
||||
@ -563,13 +550,13 @@ fn noop_visit_ident<T: MutVisitor>(Ident { name: _, span }: &mut Ident, vis: &mu
|
||||
}
|
||||
|
||||
fn noop_visit_path<T: MutVisitor>(Path { segments, span, tokens }: &mut Path, vis: &mut T) {
|
||||
vis.visit_span(span);
|
||||
for PathSegment { ident, id, args } in segments {
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_id(id);
|
||||
vis.visit_ident(ident);
|
||||
visit_opt(args, |args| vis.visit_generic_args(args));
|
||||
}
|
||||
visit_lazy_tts(tokens, vis);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
fn noop_visit_qself<T: MutVisitor>(qself: &mut Option<P<QSelf>>, vis: &mut T) {
|
||||
@ -584,6 +571,7 @@ fn noop_visit_generic_args<T: MutVisitor>(generic_args: &mut GenericArgs, vis: &
|
||||
match generic_args {
|
||||
GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data),
|
||||
GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data),
|
||||
GenericArgs::ParenthesizedElided(span) => vis.visit_span(span),
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,15 +599,17 @@ fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
|
||||
args: &mut ParenthesizedArgs,
|
||||
vis: &mut T,
|
||||
) {
|
||||
let ParenthesizedArgs { inputs, output, span, .. } = args;
|
||||
let ParenthesizedArgs { inputs, output, span, inputs_span } = args;
|
||||
visit_thin_vec(inputs, |input| vis.visit_ty(input));
|
||||
noop_visit_fn_ret_ty(output, vis);
|
||||
vis.visit_span(span);
|
||||
vis.visit_span(inputs_span);
|
||||
}
|
||||
|
||||
fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
|
||||
let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut();
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_pat(pat);
|
||||
visit_opt(ty, |ty| vis.visit_ty(ty));
|
||||
match kind {
|
||||
@ -632,10 +622,9 @@ fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
|
||||
vis.visit_block(els);
|
||||
}
|
||||
}
|
||||
vis.visit_span(span);
|
||||
visit_opt(colon_sp, |sp| vis.visit_span(sp));
|
||||
visit_attrs(attrs, vis);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
visit_opt(colon_sp, |sp| vis.visit_span(sp));
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
|
||||
@ -651,7 +640,7 @@ fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
|
||||
visit_lazy_tts(tokens, vis);
|
||||
visit_lazy_tts(attr_tokens, vis);
|
||||
}
|
||||
AttrKind::DocComment(..) => {}
|
||||
AttrKind::DocComment(_kind, _sym) => {}
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
@ -689,34 +678,24 @@ pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> Smal
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_pat(pat);
|
||||
vis.visit_span(span);
|
||||
vis.visit_ty(ty);
|
||||
vis.visit_span(span);
|
||||
smallvec![param]
|
||||
}
|
||||
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
fn visit_attr_tt<T: MutVisitor>(tt: &mut AttrTokenTree, vis: &mut T) {
|
||||
match tt {
|
||||
AttrTokenTree::Token(token, _) => {
|
||||
AttrTokenTree::Token(token, _spacing) => {
|
||||
visit_token(token, vis);
|
||||
}
|
||||
AttrTokenTree::Delimited(DelimSpan { open, close }, _spacing, _delim, tts) => {
|
||||
vis.visit_span(open);
|
||||
vis.visit_span(close);
|
||||
AttrTokenTree::Delimited(dspan, _spacing, _delim, tts) => {
|
||||
visit_attr_tts(tts, vis);
|
||||
visit_delim_span(dspan, vis);
|
||||
}
|
||||
AttrTokenTree::Attributes(data) => {
|
||||
for attr in &mut *data.attrs {
|
||||
match &mut attr.kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
visit_lazy_tts(&mut normal.tokens, vis);
|
||||
}
|
||||
AttrKind::DocComment(..) => {
|
||||
vis.visit_span(&mut attr.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
visit_lazy_tts_opt_mut(Some(&mut data.tokens), vis);
|
||||
AttrTokenTree::AttrsTarget(AttrsTarget { attrs, tokens }) => {
|
||||
visit_attrs(attrs, vis);
|
||||
visit_lazy_tts_opt_mut(Some(tokens), vis);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -724,13 +703,12 @@ fn visit_attr_tt<T: MutVisitor>(tt: &mut AttrTokenTree, vis: &mut T) {
|
||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
fn visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
|
||||
match tt {
|
||||
TokenTree::Token(token, _) => {
|
||||
TokenTree::Token(token, _spacing) => {
|
||||
visit_token(token, vis);
|
||||
}
|
||||
TokenTree::Delimited(DelimSpan { open, close }, _spacing, _delim, tts) => {
|
||||
vis.visit_span(open);
|
||||
vis.visit_span(close);
|
||||
TokenTree::Delimited(dspan, _spacing, _delim, tts) => {
|
||||
visit_tts(tts, vis);
|
||||
visit_delim_span(dspan, vis);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -771,7 +749,7 @@ fn visit_lazy_tts<T: MutVisitor>(lazy_tts: &mut Option<LazyAttrTokenStream>, vis
|
||||
pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
|
||||
let Token { kind, span } = t;
|
||||
match kind {
|
||||
token::Ident(name, _) | token::Lifetime(name) => {
|
||||
token::Ident(name, _ /*raw*/) | token::Lifetime(name) => {
|
||||
let mut ident = Ident::new(*name, *span);
|
||||
vis.visit_ident(&mut ident);
|
||||
*name = ident.name;
|
||||
@ -894,9 +872,9 @@ fn noop_visit_coroutine_kind<T: MutVisitor>(coroutine_kind: &mut CoroutineKind,
|
||||
CoroutineKind::Async { span, closure_id, return_impl_trait_id }
|
||||
| CoroutineKind::Gen { span, closure_id, return_impl_trait_id }
|
||||
| CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id } => {
|
||||
vis.visit_span(span);
|
||||
vis.visit_id(closure_id);
|
||||
vis.visit_id(return_impl_trait_id);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -918,10 +896,11 @@ fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T) {
|
||||
match pb {
|
||||
GenericBound::Trait(ty, _modifier) => vis.visit_poly_trait_ref(ty),
|
||||
GenericBound::Outlives(lifetime) => noop_visit_lifetime(lifetime, vis),
|
||||
GenericBound::Use(args, _) => {
|
||||
GenericBound::Use(args, span) => {
|
||||
for arg in args {
|
||||
vis.visit_precise_capturing_arg(arg);
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -932,8 +911,8 @@ fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg
|
||||
vis.visit_lifetime(lt);
|
||||
}
|
||||
PreciseCapturingArg::Arg(path, id) => {
|
||||
vis.visit_path(path);
|
||||
vis.visit_id(id);
|
||||
vis.visit_path(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -944,11 +923,8 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
|
||||
) -> SmallVec<[GenericParam; 1]> {
|
||||
let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param;
|
||||
vis.visit_id(id);
|
||||
vis.visit_ident(ident);
|
||||
if let Some(colon_span) = colon_span {
|
||||
vis.visit_span(colon_span);
|
||||
}
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_ident(ident);
|
||||
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
|
||||
match kind {
|
||||
GenericParamKind::Lifetime => {}
|
||||
@ -960,6 +936,9 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
|
||||
visit_opt(default, |default| vis.visit_anon_const(default));
|
||||
}
|
||||
}
|
||||
if let Some(colon_span) = colon_span {
|
||||
vis.visit_span(colon_span);
|
||||
}
|
||||
smallvec![param]
|
||||
}
|
||||
|
||||
@ -979,6 +958,14 @@ fn noop_visit_generics<T: MutVisitor>(generics: &mut Generics, vis: &mut T) {
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
fn noop_visit_ty_alias_where_clauses<T: MutVisitor>(tawcs: &mut TyAliasWhereClauses, vis: &mut T) {
|
||||
let TyAliasWhereClauses { before, after, split: _ } = tawcs;
|
||||
let TyAliasWhereClause { has_where_token: _, span: span_before } = before;
|
||||
let TyAliasWhereClause { has_where_token: _, span: span_after } = after;
|
||||
vis.visit_span(span_before);
|
||||
vis.visit_span(span_after);
|
||||
}
|
||||
|
||||
fn noop_visit_where_clause<T: MutVisitor>(wc: &mut WhereClause, vis: &mut T) {
|
||||
let WhereClause { has_where_token: _, predicates, span } = wc;
|
||||
visit_thin_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
|
||||
@ -989,42 +976,42 @@ fn noop_visit_where_predicate<T: MutVisitor>(pred: &mut WherePredicate, vis: &mu
|
||||
match pred {
|
||||
WherePredicate::BoundPredicate(bp) => {
|
||||
let WhereBoundPredicate { span, bound_generic_params, bounded_ty, bounds } = bp;
|
||||
vis.visit_span(span);
|
||||
bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
|
||||
vis.visit_ty(bounded_ty);
|
||||
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
|
||||
vis.visit_span(span);
|
||||
}
|
||||
WherePredicate::RegionPredicate(rp) => {
|
||||
let WhereRegionPredicate { span, lifetime, bounds } = rp;
|
||||
vis.visit_span(span);
|
||||
noop_visit_lifetime(lifetime, vis);
|
||||
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
|
||||
vis.visit_span(span);
|
||||
}
|
||||
WherePredicate::EqPredicate(ep) => {
|
||||
let WhereEqPredicate { span, lhs_ty, rhs_ty } = ep;
|
||||
vis.visit_span(span);
|
||||
vis.visit_ty(lhs_ty);
|
||||
vis.visit_ty(rhs_ty);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut T) {
|
||||
match vdata {
|
||||
VariantData::Struct { fields, .. } => {
|
||||
VariantData::Struct { fields, recovered: _ } => {
|
||||
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
|
||||
}
|
||||
VariantData::Tuple(fields, id) => {
|
||||
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
|
||||
vis.visit_id(id);
|
||||
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
|
||||
}
|
||||
VariantData::Unit(id) => vis.visit_id(id),
|
||||
}
|
||||
}
|
||||
|
||||
fn noop_visit_trait_ref<T: MutVisitor>(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) {
|
||||
vis.visit_path(path);
|
||||
vis.visit_id(ref_id);
|
||||
vis.visit_path(path);
|
||||
}
|
||||
|
||||
fn noop_visit_poly_trait_ref<T: MutVisitor>(p: &mut PolyTraitRef, vis: &mut T) {
|
||||
@ -1039,12 +1026,12 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
|
||||
visitor: &mut T,
|
||||
) -> SmallVec<[FieldDef; 1]> {
|
||||
let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd;
|
||||
visitor.visit_span(span);
|
||||
visit_opt(ident, |ident| visitor.visit_ident(ident));
|
||||
visitor.visit_vis(vis);
|
||||
visitor.visit_id(id);
|
||||
visitor.visit_ty(ty);
|
||||
visit_attrs(attrs, visitor);
|
||||
visitor.visit_vis(vis);
|
||||
visit_opt(ident, |ident| visitor.visit_ident(ident));
|
||||
visitor.visit_ty(ty);
|
||||
visitor.visit_span(span);
|
||||
smallvec![fd]
|
||||
}
|
||||
|
||||
@ -1053,11 +1040,11 @@ pub fn noop_flat_map_expr_field<T: MutVisitor>(
|
||||
vis: &mut T,
|
||||
) -> SmallVec<[ExprField; 1]> {
|
||||
let ExprField { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = &mut f;
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_id(id);
|
||||
vis.visit_span(span);
|
||||
visit_attrs(attrs, vis);
|
||||
smallvec![f]
|
||||
}
|
||||
|
||||
@ -1069,8 +1056,8 @@ pub fn noop_visit_block<T: MutVisitor>(block: &mut P<Block>, vis: &mut T) {
|
||||
let Block { id, stmts, rules: _, span, tokens, could_be_bare_literal: _ } = block.deref_mut();
|
||||
vis.visit_id(id);
|
||||
stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
|
||||
vis.visit_span(span);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn noop_visit_item_kind(kind: &mut impl NoopVisitItemKind, vis: &mut impl MutVisitor) {
|
||||
@ -1091,45 +1078,37 @@ impl NoopVisitItemKind for ItemKind {
|
||||
}
|
||||
ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
|
||||
visit_defaultness(defaultness, vis);
|
||||
visit_fn_sig(sig, vis);
|
||||
vis.visit_generics(generics);
|
||||
visit_fn_sig(sig, vis);
|
||||
visit_opt(body, |body| vis.visit_block(body));
|
||||
}
|
||||
ItemKind::Mod(safety, mod_kind) => {
|
||||
visit_safety(safety, vis);
|
||||
match mod_kind {
|
||||
ModKind::Loaded(items, _inline, ModSpans { inner_span, inject_use_span }) => {
|
||||
items.flat_map_in_place(|item| vis.flat_map_item(item));
|
||||
vis.visit_span(inner_span);
|
||||
vis.visit_span(inject_use_span);
|
||||
items.flat_map_in_place(|item| vis.flat_map_item(item));
|
||||
}
|
||||
ModKind::Unloaded => {}
|
||||
}
|
||||
}
|
||||
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
|
||||
ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
|
||||
ItemKind::TyAlias(box TyAlias {
|
||||
defaultness,
|
||||
generics,
|
||||
where_clauses,
|
||||
bounds,
|
||||
ty,
|
||||
..
|
||||
}) => {
|
||||
ItemKind::TyAlias(box TyAlias { defaultness, generics, where_clauses, bounds, ty }) => {
|
||||
visit_defaultness(defaultness, vis);
|
||||
vis.visit_generics(generics);
|
||||
vis.visit_span(&mut where_clauses.before.span);
|
||||
vis.visit_span(&mut where_clauses.after.span);
|
||||
visit_bounds(bounds, vis);
|
||||
visit_opt(ty, |ty| vis.visit_ty(ty));
|
||||
noop_visit_ty_alias_where_clauses(where_clauses, vis);
|
||||
}
|
||||
ItemKind::Enum(EnumDef { variants }, generics) => {
|
||||
variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
|
||||
vis.visit_generics(generics);
|
||||
variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
|
||||
}
|
||||
ItemKind::Struct(variant_data, generics) | ItemKind::Union(variant_data, generics) => {
|
||||
vis.visit_variant_data(variant_data);
|
||||
vis.visit_generics(generics);
|
||||
vis.visit_variant_data(variant_data);
|
||||
}
|
||||
ItemKind::Impl(box Impl {
|
||||
defaultness,
|
||||
@ -1217,14 +1196,12 @@ impl NoopVisitItemKind for AssocItemKind {
|
||||
where_clauses,
|
||||
bounds,
|
||||
ty,
|
||||
..
|
||||
}) => {
|
||||
visit_defaultness(defaultness, visitor);
|
||||
visitor.visit_generics(generics);
|
||||
visitor.visit_span(&mut where_clauses.before.span);
|
||||
visitor.visit_span(&mut where_clauses.after.span);
|
||||
visit_bounds(bounds, visitor);
|
||||
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
||||
noop_visit_ty_alias_where_clauses(where_clauses, visitor);
|
||||
}
|
||||
AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
||||
AssocItemKind::Delegation(box Delegation {
|
||||
@ -1302,20 +1279,15 @@ pub fn noop_flat_map_item<K: NoopVisitItemKind>(
|
||||
visitor.visit_vis(vis);
|
||||
visitor.visit_ident(ident);
|
||||
kind.noop_visit(visitor);
|
||||
visitor.visit_span(span);
|
||||
visit_lazy_tts(tokens, visitor);
|
||||
visitor.visit_span(span);
|
||||
smallvec![item]
|
||||
}
|
||||
|
||||
impl NoopVisitItemKind for ForeignItemKind {
|
||||
fn noop_visit(&mut self, visitor: &mut impl MutVisitor) {
|
||||
match self {
|
||||
ForeignItemKind::Static(box StaticForeignItem {
|
||||
ty,
|
||||
mutability: _,
|
||||
expr,
|
||||
safety: _,
|
||||
}) => {
|
||||
ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
|
||||
visitor.visit_ty(ty);
|
||||
visit_opt(expr, |expr| visitor.visit_expr(expr));
|
||||
}
|
||||
@ -1331,14 +1303,12 @@ impl NoopVisitItemKind for ForeignItemKind {
|
||||
where_clauses,
|
||||
bounds,
|
||||
ty,
|
||||
..
|
||||
}) => {
|
||||
visit_defaultness(defaultness, visitor);
|
||||
visitor.visit_generics(generics);
|
||||
visitor.visit_span(&mut where_clauses.before.span);
|
||||
visitor.visit_span(&mut where_clauses.after.span);
|
||||
visit_bounds(bounds, visitor);
|
||||
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
||||
noop_visit_ty_alias_where_clauses(where_clauses, visitor);
|
||||
}
|
||||
ForeignItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
||||
}
|
||||
@ -1349,7 +1319,8 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
|
||||
let Pat { id, kind, span, tokens } = pat.deref_mut();
|
||||
vis.visit_id(id);
|
||||
match kind {
|
||||
PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {}
|
||||
PatKind::Err(_guar) => {}
|
||||
PatKind::Wild | PatKind::Rest | PatKind::Never => {}
|
||||
PatKind::Ident(_binding_mode, ident, sub) => {
|
||||
vis.visit_ident(ident);
|
||||
visit_opt(sub, |sub| vis.visit_pat(sub));
|
||||
@ -1383,8 +1354,8 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
|
||||
PatKind::Paren(inner) => vis.visit_pat(inner),
|
||||
PatKind::MacCall(mac) => vis.visit_mac_call(mac),
|
||||
}
|
||||
vis.visit_span(span);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
fn noop_visit_anon_const<T: MutVisitor>(AnonConst { id, value }: &mut AnonConst, vis: &mut T) {
|
||||
@ -1393,13 +1364,22 @@ fn noop_visit_anon_const<T: MutVisitor>(AnonConst { id, value }: &mut AnonConst,
|
||||
}
|
||||
|
||||
fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
|
||||
for (op, _) in &mut asm.operands {
|
||||
// FIXME: Visit spans inside all this currently ignored stuff.
|
||||
let InlineAsm {
|
||||
template: _,
|
||||
template_strs: _,
|
||||
operands,
|
||||
clobber_abis: _,
|
||||
options: _,
|
||||
line_spans: _,
|
||||
} = asm;
|
||||
for (op, span) in operands {
|
||||
match op {
|
||||
InlineAsmOperand::In { expr, .. }
|
||||
| InlineAsmOperand::Out { expr: Some(expr), .. }
|
||||
| InlineAsmOperand::InOut { expr, .. } => vis.visit_expr(expr),
|
||||
InlineAsmOperand::Out { expr: None, .. } => {}
|
||||
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
|
||||
InlineAsmOperand::In { expr, reg: _ }
|
||||
| InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ }
|
||||
| InlineAsmOperand::InOut { expr, reg: _, late: _ } => vis.visit_expr(expr),
|
||||
InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {}
|
||||
InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
|
||||
vis.visit_expr(in_expr);
|
||||
if let Some(out_expr) = out_expr {
|
||||
vis.visit_expr(out_expr);
|
||||
@ -1409,6 +1389,7 @@ fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
|
||||
InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym),
|
||||
InlineAsmOperand::Label { block } => vis.visit_block(block),
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1422,18 +1403,26 @@ fn noop_visit_inline_asm_sym<T: MutVisitor>(
|
||||
}
|
||||
|
||||
fn noop_visit_format_args<T: MutVisitor>(fmt: &mut FormatArgs, vis: &mut T) {
|
||||
for arg in fmt.arguments.all_args_mut() {
|
||||
if let FormatArgumentKind::Named(name) = &mut arg.kind {
|
||||
vis.visit_ident(name);
|
||||
// FIXME: visit the template exhaustively.
|
||||
let FormatArgs { span, template: _, arguments } = fmt;
|
||||
for FormatArgument { kind, expr } in arguments.all_args_mut() {
|
||||
match kind {
|
||||
FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => {
|
||||
vis.visit_ident(ident)
|
||||
}
|
||||
FormatArgumentKind::Normal => {}
|
||||
}
|
||||
vis.visit_expr(&mut arg.expr);
|
||||
vis.visit_expr(expr);
|
||||
}
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn noop_visit_expr<T: MutVisitor>(
|
||||
Expr { kind, id, span, attrs, tokens }: &mut Expr,
|
||||
vis: &mut T,
|
||||
) {
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
match kind {
|
||||
ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
|
||||
ExprKind::ConstBlock(anon_const) => {
|
||||
@ -1454,10 +1443,10 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
args: call_args,
|
||||
span,
|
||||
}) => {
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_id(id);
|
||||
visit_opt(seg_args, |args| vis.visit_generic_args(args));
|
||||
vis.visit_method_receiver_expr(receiver);
|
||||
vis.visit_id(id);
|
||||
vis.visit_ident(ident);
|
||||
visit_opt(seg_args, |args| vis.visit_generic_args(args));
|
||||
visit_thin_exprs(call_args, vis);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
@ -1474,10 +1463,11 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_ty(ty);
|
||||
}
|
||||
ExprKind::AddrOf(_, _, ohs) => vis.visit_expr(ohs),
|
||||
ExprKind::Let(pat, scrutinee, _, _) => {
|
||||
ExprKind::AddrOf(_kind, _mut, ohs) => vis.visit_expr(ohs),
|
||||
ExprKind::Let(pat, scrutinee, span, _recovered) => {
|
||||
vis.visit_pat(pat);
|
||||
vis.visit_expr(scrutinee);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
ExprKind::If(cond, tr, fl) => {
|
||||
vis.visit_expr(cond);
|
||||
@ -1485,19 +1475,19 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
visit_opt(fl, |fl| ensure_sufficient_stack(|| vis.visit_expr(fl)));
|
||||
}
|
||||
ExprKind::While(cond, body, label) => {
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
vis.visit_expr(cond);
|
||||
vis.visit_block(body);
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
}
|
||||
ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
vis.visit_pat(pat);
|
||||
vis.visit_expr(iter);
|
||||
vis.visit_block(body);
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
}
|
||||
ExprKind::Loop(body, label, span) => {
|
||||
vis.visit_block(body);
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
vis.visit_block(body);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
ExprKind::Match(expr, arms, _kind) => {
|
||||
@ -1525,11 +1515,12 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
vis.visit_span(fn_arg_span);
|
||||
}
|
||||
ExprKind::Block(blk, label) => {
|
||||
vis.visit_block(blk);
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
vis.visit_block(blk);
|
||||
}
|
||||
ExprKind::Gen(_capture_by, body, _) => {
|
||||
ExprKind::Gen(_capture_by, body, _kind, decl_span) => {
|
||||
vis.visit_block(body);
|
||||
vis.visit_span(decl_span);
|
||||
}
|
||||
ExprKind::Await(expr, await_kw_span) => {
|
||||
vis.visit_expr(expr);
|
||||
@ -1604,12 +1595,13 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
}
|
||||
ExprKind::Try(expr) => vis.visit_expr(expr),
|
||||
ExprKind::TryBlock(body) => vis.visit_block(body),
|
||||
ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err(_) | ExprKind::Dummy => {}
|
||||
ExprKind::Lit(_token) => {}
|
||||
ExprKind::IncludedBytes(_bytes) => {}
|
||||
ExprKind::Err(_guar) => {}
|
||||
ExprKind::Dummy => {}
|
||||
}
|
||||
vis.visit_id(id);
|
||||
vis.visit_span(span);
|
||||
visit_attrs(attrs, vis);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn noop_filter_map_expr<T: MutVisitor>(mut e: P<Expr>, vis: &mut T) -> Option<P<Expr>> {
|
||||
@ -1624,7 +1616,6 @@ pub fn noop_flat_map_stmt<T: MutVisitor>(
|
||||
vis: &mut T,
|
||||
) -> SmallVec<[Stmt; 1]> {
|
||||
vis.visit_id(&mut id);
|
||||
vis.visit_span(&mut span);
|
||||
let stmts: SmallVec<_> = noop_flat_map_stmt_kind(kind, vis)
|
||||
.into_iter()
|
||||
.map(|kind| Stmt { id, kind, span })
|
||||
@ -1635,6 +1626,7 @@ pub fn noop_flat_map_stmt<T: MutVisitor>(
|
||||
the visitor should implement custom statement visiting"
|
||||
);
|
||||
}
|
||||
vis.visit_span(&mut span);
|
||||
stmts
|
||||
}
|
||||
|
||||
@ -1650,8 +1642,8 @@ fn noop_flat_map_stmt_kind<T: MutVisitor>(kind: StmtKind, vis: &mut T) -> SmallV
|
||||
StmtKind::Empty => smallvec![StmtKind::Empty],
|
||||
StmtKind::MacCall(mut mac) => {
|
||||
let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
|
||||
vis.visit_mac_call(mac_);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_mac_call(mac_);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
smallvec![StmtKind::MacCall(mac)]
|
||||
}
|
||||
@ -1659,14 +1651,16 @@ fn noop_flat_map_stmt_kind<T: MutVisitor>(kind: StmtKind, vis: &mut T) -> SmallV
|
||||
}
|
||||
|
||||
fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
|
||||
match &mut visibility.kind {
|
||||
let Visibility { kind, span, tokens } = visibility;
|
||||
match kind {
|
||||
VisibilityKind::Public | VisibilityKind::Inherited => {}
|
||||
VisibilityKind::Restricted { path, id, shorthand: _ } => {
|
||||
vis.visit_path(path);
|
||||
vis.visit_id(id);
|
||||
vis.visit_path(path);
|
||||
}
|
||||
}
|
||||
vis.visit_span(&mut visibility.span);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
fn noop_visit_capture_by<T: MutVisitor>(capture_by: &mut CaptureBy, vis: &mut T) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
pub use BinOpToken::*;
|
||||
pub use LitKind::*;
|
||||
pub use Nonterminal::*;
|
||||
pub use NtExprKind::*;
|
||||
pub use NtPatKind::*;
|
||||
pub use TokenKind::*;
|
||||
|
||||
use crate::ast;
|
||||
@ -558,9 +560,10 @@ impl Token {
|
||||
/// Returns `true` if the token can appear at the start of a const param.
|
||||
pub fn can_begin_const_arg(&self) -> bool {
|
||||
match self.kind {
|
||||
OpenDelim(Delimiter::Brace) => true,
|
||||
OpenDelim(Delimiter::Brace) | Literal(..) | BinOp(Minus) => true,
|
||||
Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
|
||||
Interpolated(ref nt) => matches!(&**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
|
||||
_ => self.can_begin_literal_maybe_minus(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -620,6 +623,21 @@ impl Token {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_begin_string_literal(&self) -> bool {
|
||||
match self.uninterpolate().kind {
|
||||
Literal(..) => true,
|
||||
Interpolated(ref nt) => match &**nt {
|
||||
NtLiteral(_) => true,
|
||||
NtExpr(e) => match &e.kind {
|
||||
ast::ExprKind::Lit(_) => true,
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience function for matching on identifiers during parsing.
|
||||
/// Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token
|
||||
/// into the regular identifier or lifetime token it refers to,
|
||||
@ -855,6 +873,27 @@ impl PartialEq<TokenKind> for Token {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)]
|
||||
pub enum NtPatKind {
|
||||
// Matches or-patterns. Was written using `pat` in edition 2021 or later.
|
||||
PatWithOr,
|
||||
// Doesn't match or-patterns.
|
||||
// - `inferred`: was written using `pat` in edition 2015 or 2018.
|
||||
// - `!inferred`: was written using `pat_param`.
|
||||
PatParam { inferred: bool },
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)]
|
||||
pub enum NtExprKind {
|
||||
// Matches expressions using the post-edition 2024. Was written using
|
||||
// `expr` in edition 2024 or later.
|
||||
Expr,
|
||||
// Matches expressions using the pre-edition 2024 rules.
|
||||
// - `inferred`: was written using `expr` in edition 2021 or earlier.
|
||||
// - `!inferred`: was written using `expr_2021`.
|
||||
Expr2021 { inferred: bool },
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable)]
|
||||
/// For interpolation during macro expansion.
|
||||
pub enum Nonterminal {
|
||||
@ -876,15 +915,8 @@ pub enum NonterminalKind {
|
||||
Item,
|
||||
Block,
|
||||
Stmt,
|
||||
PatParam {
|
||||
/// Keep track of whether the user used `:pat_param` or `:pat` and we inferred it from the
|
||||
/// edition of the span. This is used for diagnostics.
|
||||
inferred: bool,
|
||||
},
|
||||
PatWithOr,
|
||||
Expr,
|
||||
/// Matches an expression using the rules from edition 2021 and earlier.
|
||||
Expr2021,
|
||||
Pat(NtPatKind),
|
||||
Expr(NtExprKind),
|
||||
Ty,
|
||||
Ident,
|
||||
Lifetime,
|
||||
@ -906,15 +938,22 @@ impl NonterminalKind {
|
||||
sym::item => NonterminalKind::Item,
|
||||
sym::block => NonterminalKind::Block,
|
||||
sym::stmt => NonterminalKind::Stmt,
|
||||
sym::pat => match edition() {
|
||||
Edition::Edition2015 | Edition::Edition2018 => {
|
||||
NonterminalKind::PatParam { inferred: true }
|
||||
sym::pat => {
|
||||
if edition().at_least_rust_2021() {
|
||||
NonterminalKind::Pat(PatWithOr)
|
||||
} else {
|
||||
NonterminalKind::Pat(PatParam { inferred: true })
|
||||
}
|
||||
Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr,
|
||||
},
|
||||
sym::pat_param => NonterminalKind::PatParam { inferred: false },
|
||||
sym::expr => NonterminalKind::Expr,
|
||||
sym::expr_2021 if edition().at_least_rust_2021() => NonterminalKind::Expr2021,
|
||||
}
|
||||
sym::pat_param => NonterminalKind::Pat(PatParam { inferred: false }),
|
||||
sym::expr => {
|
||||
if edition().at_least_rust_2024() {
|
||||
NonterminalKind::Expr(Expr)
|
||||
} else {
|
||||
NonterminalKind::Expr(Expr2021 { inferred: true })
|
||||
}
|
||||
}
|
||||
sym::expr_2021 => NonterminalKind::Expr(Expr2021 { inferred: false }),
|
||||
sym::ty => NonterminalKind::Ty,
|
||||
sym::ident => NonterminalKind::Ident,
|
||||
sym::lifetime => NonterminalKind::Lifetime,
|
||||
@ -926,15 +965,16 @@ impl NonterminalKind {
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
fn symbol(self) -> Symbol {
|
||||
match self {
|
||||
NonterminalKind::Item => sym::item,
|
||||
NonterminalKind::Block => sym::block,
|
||||
NonterminalKind::Stmt => sym::stmt,
|
||||
NonterminalKind::PatParam { inferred: false } => sym::pat_param,
|
||||
NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat,
|
||||
NonterminalKind::Expr => sym::expr,
|
||||
NonterminalKind::Expr2021 => sym::expr_2021,
|
||||
NonterminalKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat,
|
||||
NonterminalKind::Pat(PatParam { inferred: false }) => sym::pat_param,
|
||||
NonterminalKind::Expr(Expr2021 { inferred: true } | Expr) => sym::expr,
|
||||
NonterminalKind::Expr(Expr2021 { inferred: false }) => sym::expr_2021,
|
||||
NonterminalKind::Ty => sym::ty,
|
||||
NonterminalKind::Ident => sym::ident,
|
||||
NonterminalKind::Lifetime => sym::lifetime,
|
||||
|
@ -14,7 +14,7 @@
|
||||
//! ownership of the original.
|
||||
|
||||
use crate::ast::{AttrStyle, StmtKind};
|
||||
use crate::ast_traits::{HasAttrs, HasSpan, HasTokens};
|
||||
use crate::ast_traits::{HasAttrs, HasTokens};
|
||||
use crate::token::{self, Delimiter, Nonterminal, Token, TokenKind};
|
||||
use crate::AttrVec;
|
||||
|
||||
@ -23,7 +23,6 @@ use rustc_data_structures::sync::{self, Lrc};
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_serialize::{Decodable, Encodable};
|
||||
use rustc_span::{sym, Span, SpanDecoder, SpanEncoder, Symbol, DUMMY_SP};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::{cmp, fmt, iter};
|
||||
@ -171,8 +170,8 @@ pub enum AttrTokenTree {
|
||||
Delimited(DelimSpan, DelimSpacing, Delimiter, AttrTokenStream),
|
||||
/// Stores the attributes for an attribute target,
|
||||
/// along with the tokens for that attribute target.
|
||||
/// See `AttributesData` for more information
|
||||
Attributes(AttributesData),
|
||||
/// See `AttrsTarget` for more information
|
||||
AttrsTarget(AttrsTarget),
|
||||
}
|
||||
|
||||
impl AttrTokenStream {
|
||||
@ -180,42 +179,33 @@ impl AttrTokenStream {
|
||||
AttrTokenStream(Lrc::new(tokens))
|
||||
}
|
||||
|
||||
/// Converts this `AttrTokenStream` to a plain `TokenStream`.
|
||||
/// During conversion, `AttrTokenTree::Attributes` get 'flattened'
|
||||
/// Converts this `AttrTokenStream` to a plain `Vec<TokenTree>`.
|
||||
/// During conversion, `AttrTokenTree::AttrsTarget` get 'flattened'
|
||||
/// back to a `TokenStream` of the form `outer_attr attr_target`.
|
||||
/// If there are inner attributes, they are inserted into the proper
|
||||
/// place in the attribute target tokens.
|
||||
pub fn to_tokenstream(&self) -> TokenStream {
|
||||
let trees: Vec<_> = self
|
||||
.0
|
||||
.iter()
|
||||
.flat_map(|tree| match &tree {
|
||||
pub fn to_token_trees(&self) -> Vec<TokenTree> {
|
||||
let mut res = Vec::with_capacity(self.0.len());
|
||||
for tree in self.0.iter() {
|
||||
match tree {
|
||||
AttrTokenTree::Token(inner, spacing) => {
|
||||
smallvec![TokenTree::Token(inner.clone(), *spacing)].into_iter()
|
||||
res.push(TokenTree::Token(inner.clone(), *spacing));
|
||||
}
|
||||
AttrTokenTree::Delimited(span, spacing, delim, stream) => {
|
||||
smallvec![TokenTree::Delimited(
|
||||
res.push(TokenTree::Delimited(
|
||||
*span,
|
||||
*spacing,
|
||||
*delim,
|
||||
stream.to_tokenstream()
|
||||
),]
|
||||
.into_iter()
|
||||
TokenStream::new(stream.to_token_trees()),
|
||||
))
|
||||
}
|
||||
AttrTokenTree::Attributes(data) => {
|
||||
let idx = data
|
||||
AttrTokenTree::AttrsTarget(target) => {
|
||||
let idx = target
|
||||
.attrs
|
||||
.partition_point(|attr| matches!(attr.style, crate::AttrStyle::Outer));
|
||||
let (outer_attrs, inner_attrs) = data.attrs.split_at(idx);
|
||||
let (outer_attrs, inner_attrs) = target.attrs.split_at(idx);
|
||||
|
||||
let mut target_tokens: Vec<_> = data
|
||||
.tokens
|
||||
.to_attr_token_stream()
|
||||
.to_tokenstream()
|
||||
.0
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect();
|
||||
let mut target_tokens = target.tokens.to_attr_token_stream().to_token_trees();
|
||||
if !inner_attrs.is_empty() {
|
||||
let mut found = false;
|
||||
// Check the last two trees (to account for a trailing semi)
|
||||
@ -224,7 +214,7 @@ impl AttrTokenStream {
|
||||
// Inner attributes are only supported on extern blocks, functions,
|
||||
// impls, and modules. All of these have their inner attributes
|
||||
// placed at the beginning of the rightmost outermost braced group:
|
||||
// e.g. fn foo() { #![my_attr} }
|
||||
// e.g. fn foo() { #![my_attr] }
|
||||
//
|
||||
// Therefore, we can insert them back into the right location
|
||||
// without needing to do any extra position tracking.
|
||||
@ -237,7 +227,7 @@ impl AttrTokenStream {
|
||||
|
||||
let mut stream = TokenStream::default();
|
||||
for inner_attr in inner_attrs {
|
||||
stream.push_stream(inner_attr.tokens());
|
||||
stream.push_stream(inner_attr.get_tokens());
|
||||
}
|
||||
stream.push_stream(delim_tokens.clone());
|
||||
*tree = TokenTree::Delimited(*span, *spacing, *delim, stream);
|
||||
@ -251,17 +241,14 @@ impl AttrTokenStream {
|
||||
"Failed to find trailing delimited group in: {target_tokens:?}"
|
||||
);
|
||||
}
|
||||
let mut flat: SmallVec<[_; 1]> =
|
||||
SmallVec::with_capacity(target_tokens.len() + outer_attrs.len());
|
||||
for attr in outer_attrs {
|
||||
flat.extend(attr.tokens().0.iter().cloned());
|
||||
res.extend(attr.get_tokens().0.iter().cloned());
|
||||
}
|
||||
flat.extend(target_tokens);
|
||||
flat.into_iter()
|
||||
res.extend(target_tokens);
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
TokenStream::new(trees)
|
||||
}
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,7 +262,7 @@ impl AttrTokenStream {
|
||||
/// have an `attrs` field containing the `#[cfg(FALSE)]` attr,
|
||||
/// and a `tokens` field storing the (unparsed) tokens `struct Foo {}`
|
||||
#[derive(Clone, Debug, Encodable, Decodable)]
|
||||
pub struct AttributesData {
|
||||
pub struct AttrsTarget {
|
||||
/// Attributes, both outer and inner.
|
||||
/// These are stored in the original order that they were parsed in.
|
||||
pub attrs: AttrVec,
|
||||
@ -409,8 +396,8 @@ impl PartialEq<TokenStream> for TokenStream {
|
||||
}
|
||||
|
||||
impl TokenStream {
|
||||
pub fn new(streams: Vec<TokenTree>) -> TokenStream {
|
||||
TokenStream(Lrc::new(streams))
|
||||
pub fn new(tts: Vec<TokenTree>) -> TokenStream {
|
||||
TokenStream(Lrc::new(tts))
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
@ -449,19 +436,19 @@ impl TokenStream {
|
||||
TokenStream::new(vec![TokenTree::token_alone(kind, span)])
|
||||
}
|
||||
|
||||
pub fn from_ast(node: &(impl HasAttrs + HasSpan + HasTokens + fmt::Debug)) -> TokenStream {
|
||||
pub fn from_ast(node: &(impl HasAttrs + HasTokens + fmt::Debug)) -> TokenStream {
|
||||
let Some(tokens) = node.tokens() else {
|
||||
panic!("missing tokens for node at {:?}: {:?}", node.span(), node);
|
||||
panic!("missing tokens for node: {:?}", node);
|
||||
};
|
||||
let attrs = node.attrs();
|
||||
let attr_stream = if attrs.is_empty() {
|
||||
tokens.to_attr_token_stream()
|
||||
} else {
|
||||
let attr_data =
|
||||
AttributesData { attrs: attrs.iter().cloned().collect(), tokens: tokens.clone() };
|
||||
AttrTokenStream::new(vec![AttrTokenTree::Attributes(attr_data)])
|
||||
let target =
|
||||
AttrsTarget { attrs: attrs.iter().cloned().collect(), tokens: tokens.clone() };
|
||||
AttrTokenStream::new(vec![AttrTokenTree::AttrsTarget(target)])
|
||||
};
|
||||
attr_stream.to_tokenstream()
|
||||
TokenStream::new(attr_stream.to_token_trees())
|
||||
}
|
||||
|
||||
pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream {
|
||||
@ -778,6 +765,7 @@ mod size_asserts {
|
||||
static_assert_size!(AttrTokenStream, 8);
|
||||
static_assert_size!(AttrTokenTree, 32);
|
||||
static_assert_size!(LazyAttrTokenStream, 8);
|
||||
static_assert_size!(Option<LazyAttrTokenStream>, 8); // must be small, used in many AST nodes
|
||||
static_assert_size!(TokenStream, 8);
|
||||
static_assert_size!(TokenTree, 32);
|
||||
// tidy-alphabetical-end
|
||||
|
@ -1,7 +1,8 @@
|
||||
//! Routines the parser and pretty-printer use to classify AST nodes.
|
||||
|
||||
use crate::ast::ExprKind::*;
|
||||
use crate::{ast, token::Delimiter};
|
||||
use crate::ast::{self, MatchKind};
|
||||
use crate::token::Delimiter;
|
||||
|
||||
/// This classification determines whether various syntactic positions break out
|
||||
/// of parsing the current expression (true) or continue parsing more of the
|
||||
@ -81,6 +82,82 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the leftmost token of the given expression is the label of a
|
||||
/// labeled loop or block, such as in `'inner: loop { break 'inner 1 } + 1`.
|
||||
///
|
||||
/// Such expressions are not allowed as the value of an unlabeled break.
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// 'outer: {
|
||||
/// break 'inner: loop { break 'inner 1 } + 1; // invalid syntax
|
||||
///
|
||||
/// break 'outer 'inner: loop { break 'inner 1 } + 1; // okay
|
||||
///
|
||||
/// break ('inner: loop { break 'inner 1 } + 1); // okay
|
||||
///
|
||||
/// break ('inner: loop { break 'inner 1 }) + 1; // okay
|
||||
/// }
|
||||
/// ```
|
||||
pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool {
|
||||
loop {
|
||||
match &expr.kind {
|
||||
Block(_, label) | ForLoop { label, .. } | Loop(_, label, _) | While(_, _, label) => {
|
||||
return label.is_some();
|
||||
}
|
||||
|
||||
Assign(e, _, _)
|
||||
| AssignOp(_, e, _)
|
||||
| Await(e, _)
|
||||
| Binary(_, e, _)
|
||||
| Call(e, _)
|
||||
| Cast(e, _)
|
||||
| Field(e, _)
|
||||
| Index(e, _, _)
|
||||
| Match(e, _, MatchKind::Postfix)
|
||||
| Range(Some(e), _, _)
|
||||
| Try(e) => {
|
||||
expr = e;
|
||||
}
|
||||
MethodCall(method_call) => {
|
||||
expr = &method_call.receiver;
|
||||
}
|
||||
|
||||
AddrOf(..)
|
||||
| Array(..)
|
||||
| Become(..)
|
||||
| Break(..)
|
||||
| Closure(..)
|
||||
| ConstBlock(..)
|
||||
| Continue(..)
|
||||
| FormatArgs(..)
|
||||
| Gen(..)
|
||||
| If(..)
|
||||
| IncludedBytes(..)
|
||||
| InlineAsm(..)
|
||||
| Let(..)
|
||||
| Lit(..)
|
||||
| MacCall(..)
|
||||
| Match(_, _, MatchKind::Prefix)
|
||||
| OffsetOf(..)
|
||||
| Paren(..)
|
||||
| Path(..)
|
||||
| Range(None, _, _)
|
||||
| Repeat(..)
|
||||
| Ret(..)
|
||||
| Struct(..)
|
||||
| TryBlock(..)
|
||||
| Tup(..)
|
||||
| Type(..)
|
||||
| Unary(..)
|
||||
| Underscore
|
||||
| Yeet(..)
|
||||
| Yield(..)
|
||||
| Err(..)
|
||||
| Dummy => return false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum TrailingBrace<'a> {
|
||||
/// Trailing brace in a macro call, like the one in `x as *const brace! {}`.
|
||||
/// We will suggest changing the macro call to a different delimiter.
|
||||
@ -234,6 +311,6 @@ fn path_return_type(path: &ast::Path) -> Option<&ast::Ty> {
|
||||
ast::FnRetTy::Default(_) => None,
|
||||
ast::FnRetTy::Ty(ret) => Some(ret),
|
||||
},
|
||||
ast::GenericArgs::AngleBracketed(_) => None,
|
||||
ast::GenericArgs::AngleBracketed(_) | ast::GenericArgs::ParenthesizedElided(_) => None,
|
||||
}
|
||||
}
|
||||
|
@ -233,8 +233,7 @@ pub const PREC_JUMP: i8 = -30;
|
||||
pub const PREC_RANGE: i8 = -10;
|
||||
// The range 2..=14 is reserved for AssocOp binary operator precedences.
|
||||
pub const PREC_PREFIX: i8 = 50;
|
||||
pub const PREC_POSTFIX: i8 = 60;
|
||||
pub const PREC_PAREN: i8 = 99;
|
||||
pub const PREC_UNAMBIGUOUS: i8 = 60;
|
||||
pub const PREC_FORCE_PAREN: i8 = 100;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@ -325,37 +324,35 @@ impl ExprPrecedence {
|
||||
| ExprPrecedence::Let
|
||||
| ExprPrecedence::Unary => PREC_PREFIX,
|
||||
|
||||
// Unary, postfix
|
||||
ExprPrecedence::Await
|
||||
| ExprPrecedence::Call
|
||||
| ExprPrecedence::MethodCall
|
||||
| ExprPrecedence::Field
|
||||
| ExprPrecedence::Index
|
||||
| ExprPrecedence::Try
|
||||
| ExprPrecedence::InlineAsm
|
||||
| ExprPrecedence::Mac
|
||||
| ExprPrecedence::FormatArgs
|
||||
| ExprPrecedence::OffsetOf
|
||||
| ExprPrecedence::PostfixMatch => PREC_POSTFIX,
|
||||
|
||||
// Never need parens
|
||||
ExprPrecedence::Array
|
||||
| ExprPrecedence::Repeat
|
||||
| ExprPrecedence::Tup
|
||||
| ExprPrecedence::Lit
|
||||
| ExprPrecedence::Path
|
||||
| ExprPrecedence::Paren
|
||||
| ExprPrecedence::If
|
||||
| ExprPrecedence::While
|
||||
| ExprPrecedence::ForLoop
|
||||
| ExprPrecedence::Loop
|
||||
| ExprPrecedence::Match
|
||||
| ExprPrecedence::ConstBlock
|
||||
| ExprPrecedence::Await
|
||||
| ExprPrecedence::Block
|
||||
| ExprPrecedence::TryBlock
|
||||
| ExprPrecedence::Call
|
||||
| ExprPrecedence::ConstBlock
|
||||
| ExprPrecedence::Field
|
||||
| ExprPrecedence::ForLoop
|
||||
| ExprPrecedence::FormatArgs
|
||||
| ExprPrecedence::Gen
|
||||
| ExprPrecedence::If
|
||||
| ExprPrecedence::Index
|
||||
| ExprPrecedence::InlineAsm
|
||||
| ExprPrecedence::Lit
|
||||
| ExprPrecedence::Loop
|
||||
| ExprPrecedence::Mac
|
||||
| ExprPrecedence::Match
|
||||
| ExprPrecedence::MethodCall
|
||||
| ExprPrecedence::OffsetOf
|
||||
| ExprPrecedence::Paren
|
||||
| ExprPrecedence::Path
|
||||
| ExprPrecedence::PostfixMatch
|
||||
| ExprPrecedence::Repeat
|
||||
| ExprPrecedence::Struct
|
||||
| ExprPrecedence::Err => PREC_PAREN,
|
||||
| ExprPrecedence::Try
|
||||
| ExprPrecedence::TryBlock
|
||||
| ExprPrecedence::Tup
|
||||
| ExprPrecedence::While
|
||||
| ExprPrecedence::Err => PREC_UNAMBIGUOUS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
//! those that are created by the expansion of a macro.
|
||||
|
||||
use crate::ast::*;
|
||||
use crate::ptr::P;
|
||||
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
@ -298,40 +299,45 @@ pub trait Visitor<'ast>: Sized {
|
||||
}
|
||||
|
||||
pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
|
||||
walk_list!(visitor, visit_item, &krate.items);
|
||||
walk_list!(visitor, visit_attribute, &krate.attrs);
|
||||
let Crate { attrs, items, spans: _, id: _, is_placeholder: _ } = krate;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
walk_list!(visitor, visit_item, items);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) -> V::Result {
|
||||
walk_list!(visitor, visit_attribute, &local.attrs);
|
||||
try_visit!(visitor.visit_pat(&local.pat));
|
||||
visit_opt!(visitor, visit_ty, &local.ty);
|
||||
if let Some((init, els)) = local.kind.init_else_opt() {
|
||||
let Local { id: _, pat, ty, kind, span: _, colon_sp: _, attrs, tokens: _ } = local;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_pat(pat));
|
||||
visit_opt!(visitor, visit_ty, ty);
|
||||
if let Some((init, els)) = kind.init_else_opt() {
|
||||
try_visit!(visitor.visit_expr(init));
|
||||
visit_opt!(visitor, visit_block, els);
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) -> V::Result {
|
||||
visitor.visit_ident(label.ident)
|
||||
pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, Label { ident }: &'a Label) -> V::Result {
|
||||
visitor.visit_ident(*ident)
|
||||
}
|
||||
|
||||
pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) -> V::Result {
|
||||
visitor.visit_ident(lifetime.ident)
|
||||
let Lifetime { id: _, ident } = lifetime;
|
||||
visitor.visit_ident(*ident)
|
||||
}
|
||||
|
||||
pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef) -> V::Result
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params);
|
||||
visitor.visit_trait_ref(&trait_ref.trait_ref)
|
||||
let PolyTraitRef { bound_generic_params, trait_ref, span: _ } = trait_ref;
|
||||
walk_list!(visitor, visit_generic_param, bound_generic_params);
|
||||
visitor.visit_trait_ref(trait_ref)
|
||||
}
|
||||
|
||||
pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) -> V::Result {
|
||||
visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
|
||||
let TraitRef { path, ref_id } = trait_ref;
|
||||
visitor.visit_path(path, *ref_id)
|
||||
}
|
||||
|
||||
impl WalkItemKind for ItemKind {
|
||||
@ -341,9 +347,10 @@ impl WalkItemKind for ItemKind {
|
||||
_ctxt: AssocCtxt,
|
||||
visitor: &mut V,
|
||||
) -> V::Result {
|
||||
let Item { id, span, vis, ident, .. } = item;
|
||||
match self {
|
||||
ItemKind::ExternCrate(_) => {}
|
||||
ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, item.id, false)),
|
||||
ItemKind::ExternCrate(_rename) => {}
|
||||
ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, *id, false)),
|
||||
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
visit_opt!(visitor, visit_expr, expr);
|
||||
@ -354,9 +361,8 @@ impl WalkItemKind for ItemKind {
|
||||
visit_opt!(visitor, visit_expr, expr);
|
||||
}
|
||||
ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
|
||||
let kind =
|
||||
FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
|
||||
try_visit!(visitor.visit_fn(kind, item.span, item.id));
|
||||
let kind = FnKind::Fn(FnCtxt::Free, *ident, sig, vis, generics, body.as_deref());
|
||||
try_visit!(visitor.visit_fn(kind, *span, *id));
|
||||
}
|
||||
ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
|
||||
ModKind::Loaded(items, _inline, _inner_span) => {
|
||||
@ -364,11 +370,17 @@ impl WalkItemKind for ItemKind {
|
||||
}
|
||||
ModKind::Unloaded => {}
|
||||
},
|
||||
ItemKind::ForeignMod(foreign_module) => {
|
||||
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
|
||||
ItemKind::ForeignMod(ForeignMod { safety: _, abi: _, items }) => {
|
||||
walk_list!(visitor, visit_foreign_item, items);
|
||||
}
|
||||
ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
|
||||
ItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
|
||||
ItemKind::TyAlias(box TyAlias {
|
||||
generics,
|
||||
bounds,
|
||||
ty,
|
||||
defaultness: _,
|
||||
where_clauses: _,
|
||||
}) => {
|
||||
try_visit!(visitor.visit_generics(generics));
|
||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
|
||||
visit_opt!(visitor, visit_ty, ty);
|
||||
@ -407,7 +419,7 @@ impl WalkItemKind for ItemKind {
|
||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
|
||||
}
|
||||
ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
|
||||
ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, item.id)),
|
||||
ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, *id)),
|
||||
ItemKind::Delegation(box Delegation {
|
||||
id,
|
||||
qself,
|
||||
@ -416,18 +428,14 @@ impl WalkItemKind for ItemKind {
|
||||
body,
|
||||
from_glob: _,
|
||||
}) => {
|
||||
if let Some(qself) = qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(walk_qself(visitor, qself));
|
||||
try_visit!(visitor.visit_path(path, *id));
|
||||
visit_opt!(visitor, visit_ident, *rename);
|
||||
visit_opt!(visitor, visit_block, body);
|
||||
}
|
||||
ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
|
||||
if let Some(qself) = qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(visitor.visit_path(prefix, item.id));
|
||||
try_visit!(walk_qself(visitor, qself));
|
||||
try_visit!(visitor.visit_path(prefix, *id));
|
||||
if let Some(suffixes) = suffixes {
|
||||
for (ident, rename) in suffixes {
|
||||
visitor.visit_ident(*ident);
|
||||
@ -452,9 +460,9 @@ pub fn walk_item<'a, V: Visitor<'a>>(
|
||||
|
||||
pub fn walk_enum_def<'a, V: Visitor<'a>>(
|
||||
visitor: &mut V,
|
||||
enum_definition: &'a EnumDef,
|
||||
EnumDef { variants }: &'a EnumDef,
|
||||
) -> V::Result {
|
||||
walk_list!(visitor, visit_variant, &enum_definition.variants);
|
||||
walk_list!(visitor, visit_variant, variants);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
@ -462,48 +470,52 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) -
|
||||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
try_visit!(visitor.visit_ident(variant.ident));
|
||||
try_visit!(visitor.visit_vis(&variant.vis));
|
||||
try_visit!(visitor.visit_variant_data(&variant.data));
|
||||
visit_opt!(visitor, visit_variant_discr, &variant.disr_expr);
|
||||
walk_list!(visitor, visit_attribute, &variant.attrs);
|
||||
let Variant { attrs, id: _, span: _, vis, ident, data, disr_expr, is_placeholder: _ } = variant;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_vis(vis));
|
||||
try_visit!(visitor.visit_ident(*ident));
|
||||
try_visit!(visitor.visit_variant_data(data));
|
||||
visit_opt!(visitor, visit_variant_discr, disr_expr);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) -> V::Result {
|
||||
try_visit!(visitor.visit_expr(&f.expr));
|
||||
try_visit!(visitor.visit_ident(f.ident));
|
||||
walk_list!(visitor, visit_attribute, &f.attrs);
|
||||
let ExprField { attrs, id: _, span: _, ident, expr, is_shorthand: _, is_placeholder: _ } = f;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_ident(*ident));
|
||||
try_visit!(visitor.visit_expr(expr));
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) -> V::Result {
|
||||
try_visit!(visitor.visit_ident(fp.ident));
|
||||
try_visit!(visitor.visit_pat(&fp.pat));
|
||||
walk_list!(visitor, visit_attribute, &fp.attrs);
|
||||
let PatField { ident, pat, is_shorthand: _, attrs, id: _, span: _, is_placeholder: _ } = fp;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_ident(*ident));
|
||||
try_visit!(visitor.visit_pat(pat));
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
|
||||
match &typ.kind {
|
||||
let Ty { id, kind, span: _, tokens: _ } = typ;
|
||||
match kind {
|
||||
TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(visitor.visit_ty(ty)),
|
||||
TyKind::Ptr(mutable_type) => try_visit!(visitor.visit_ty(&mutable_type.ty)),
|
||||
TyKind::Ref(opt_lifetime, mutable_type) => {
|
||||
TyKind::Ptr(MutTy { ty, mutbl: _ }) => try_visit!(visitor.visit_ty(ty)),
|
||||
TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ }) => {
|
||||
visit_opt!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref);
|
||||
try_visit!(visitor.visit_ty(&mutable_type.ty));
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
}
|
||||
TyKind::Tup(tuple_element_types) => {
|
||||
walk_list!(visitor, visit_ty, tuple_element_types);
|
||||
}
|
||||
TyKind::BareFn(function_declaration) => {
|
||||
walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
|
||||
try_visit!(walk_fn_decl(visitor, &function_declaration.decl));
|
||||
let BareFnTy { safety: _, ext: _, generic_params, decl, decl_span: _ } =
|
||||
&**function_declaration;
|
||||
walk_list!(visitor, visit_generic_param, generic_params);
|
||||
try_visit!(walk_fn_decl(visitor, decl));
|
||||
}
|
||||
TyKind::Path(maybe_qself, path) => {
|
||||
if let Some(qself) = maybe_qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(visitor.visit_path(path, typ.id));
|
||||
try_visit!(walk_qself(visitor, maybe_qself));
|
||||
try_visit!(visitor.visit_path(path, *id));
|
||||
}
|
||||
TyKind::Pat(ty, pat) => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
@ -513,25 +525,35 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
try_visit!(visitor.visit_anon_const(length));
|
||||
}
|
||||
TyKind::TraitObject(bounds, ..) => {
|
||||
TyKind::TraitObject(bounds, _syntax) => {
|
||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject);
|
||||
}
|
||||
TyKind::ImplTrait(_, bounds) => {
|
||||
TyKind::ImplTrait(_id, bounds) => {
|
||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
|
||||
}
|
||||
TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
|
||||
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {}
|
||||
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy => {}
|
||||
TyKind::Err(_guar) => {}
|
||||
TyKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
|
||||
TyKind::Never | TyKind::CVarArgs => {}
|
||||
TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => {
|
||||
TyKind::AnonStruct(_id, ref fields) | TyKind::AnonUnion(_id, ref fields) => {
|
||||
walk_list!(visitor, visit_field_def, fields);
|
||||
}
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
fn walk_qself<'a, V: Visitor<'a>>(visitor: &mut V, qself: &'a Option<P<QSelf>>) -> V::Result {
|
||||
if let Some(qself) = qself {
|
||||
let QSelf { ty, path_span: _, position: _ } = &**qself;
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) -> V::Result {
|
||||
walk_list!(visitor, visit_path_segment, &path.segments);
|
||||
let Path { span: _, segments, tokens: _ } = path;
|
||||
walk_list!(visitor, visit_path_segment, segments);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
@ -540,14 +562,15 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
|
||||
use_tree: &'a UseTree,
|
||||
id: NodeId,
|
||||
) -> V::Result {
|
||||
try_visit!(visitor.visit_path(&use_tree.prefix, id));
|
||||
match use_tree.kind {
|
||||
let UseTree { prefix, kind, span: _ } = use_tree;
|
||||
try_visit!(visitor.visit_path(prefix, id));
|
||||
match kind {
|
||||
UseTreeKind::Simple(rename) => {
|
||||
// The extra IDs are handled during AST lowering.
|
||||
visit_opt!(visitor, visit_ident, rename);
|
||||
visit_opt!(visitor, visit_ident, *rename);
|
||||
}
|
||||
UseTreeKind::Glob => {}
|
||||
UseTreeKind::Nested { ref items, .. } => {
|
||||
UseTreeKind::Nested { ref items, span: _ } => {
|
||||
for &(ref nested_tree, nested_id) in items {
|
||||
try_visit!(visitor.visit_use_tree(nested_tree, nested_id, true));
|
||||
}
|
||||
@ -560,8 +583,9 @@ pub fn walk_path_segment<'a, V: Visitor<'a>>(
|
||||
visitor: &mut V,
|
||||
segment: &'a PathSegment,
|
||||
) -> V::Result {
|
||||
try_visit!(visitor.visit_ident(segment.ident));
|
||||
visit_opt!(visitor, visit_generic_args, &segment.args);
|
||||
let PathSegment { ident, id: _, args } = segment;
|
||||
try_visit!(visitor.visit_ident(*ident));
|
||||
visit_opt!(visitor, visit_generic_args, args);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
@ -570,8 +594,8 @@ where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
match generic_args {
|
||||
GenericArgs::AngleBracketed(data) => {
|
||||
for arg in &data.args {
|
||||
GenericArgs::AngleBracketed(AngleBracketedArgs { span: _, args }) => {
|
||||
for arg in args {
|
||||
match arg {
|
||||
AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)),
|
||||
AngleBracketedArg::Constraint(c) => {
|
||||
@ -581,9 +605,11 @@ where
|
||||
}
|
||||
}
|
||||
GenericArgs::Parenthesized(data) => {
|
||||
walk_list!(visitor, visit_ty, &data.inputs);
|
||||
try_visit!(visitor.visit_fn_ret_ty(&data.output));
|
||||
let ParenthesizedArgs { span: _, inputs, inputs_span: _, output } = data;
|
||||
walk_list!(visitor, visit_ty, inputs);
|
||||
try_visit!(visitor.visit_fn_ret_ty(output));
|
||||
}
|
||||
GenericArgs::ParenthesizedElided(_span) => {}
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
@ -603,9 +629,10 @@ pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>(
|
||||
visitor: &mut V,
|
||||
constraint: &'a AssocItemConstraint,
|
||||
) -> V::Result {
|
||||
try_visit!(visitor.visit_ident(constraint.ident));
|
||||
visit_opt!(visitor, visit_generic_args, &constraint.gen_args);
|
||||
match &constraint.kind {
|
||||
let AssocItemConstraint { id: _, ident, gen_args, kind, span: _ } = constraint;
|
||||
try_visit!(visitor.visit_ident(*ident));
|
||||
visit_opt!(visitor, visit_generic_args, gen_args);
|
||||
match kind {
|
||||
AssocItemConstraintKind::Equality { term } => match term {
|
||||
Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)),
|
||||
Term::Const(c) => try_visit!(visitor.visit_anon_const(c)),
|
||||
@ -618,43 +645,39 @@ pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>(
|
||||
}
|
||||
|
||||
pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Result {
|
||||
match &pattern.kind {
|
||||
let Pat { id, kind, span: _, tokens: _ } = pattern;
|
||||
match kind {
|
||||
PatKind::TupleStruct(opt_qself, path, elems) => {
|
||||
if let Some(qself) = opt_qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(visitor.visit_path(path, pattern.id));
|
||||
try_visit!(walk_qself(visitor, opt_qself));
|
||||
try_visit!(visitor.visit_path(path, *id));
|
||||
walk_list!(visitor, visit_pat, elems);
|
||||
}
|
||||
PatKind::Path(opt_qself, path) => {
|
||||
if let Some(qself) = opt_qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(visitor.visit_path(path, pattern.id))
|
||||
try_visit!(walk_qself(visitor, opt_qself));
|
||||
try_visit!(visitor.visit_path(path, *id))
|
||||
}
|
||||
PatKind::Struct(opt_qself, path, fields, _) => {
|
||||
if let Some(qself) = opt_qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(visitor.visit_path(path, pattern.id));
|
||||
PatKind::Struct(opt_qself, path, fields, _rest) => {
|
||||
try_visit!(walk_qself(visitor, opt_qself));
|
||||
try_visit!(visitor.visit_path(path, *id));
|
||||
walk_list!(visitor, visit_pat_field, fields);
|
||||
}
|
||||
PatKind::Box(subpattern)
|
||||
| PatKind::Deref(subpattern)
|
||||
| PatKind::Ref(subpattern, _)
|
||||
| PatKind::Paren(subpattern) => {
|
||||
PatKind::Box(subpattern) | PatKind::Deref(subpattern) | PatKind::Paren(subpattern) => {
|
||||
try_visit!(visitor.visit_pat(subpattern));
|
||||
}
|
||||
PatKind::Ident(_, ident, optional_subpattern) => {
|
||||
PatKind::Ref(subpattern, _ /*mutbl*/) => {
|
||||
try_visit!(visitor.visit_pat(subpattern));
|
||||
}
|
||||
PatKind::Ident(_bmode, ident, optional_subpattern) => {
|
||||
try_visit!(visitor.visit_ident(*ident));
|
||||
visit_opt!(visitor, visit_pat, optional_subpattern);
|
||||
}
|
||||
PatKind::Lit(expression) => try_visit!(visitor.visit_expr(expression)),
|
||||
PatKind::Range(lower_bound, upper_bound, _) => {
|
||||
PatKind::Range(lower_bound, upper_bound, _end) => {
|
||||
visit_opt!(visitor, visit_expr, lower_bound);
|
||||
visit_opt!(visitor, visit_expr, upper_bound);
|
||||
}
|
||||
PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {}
|
||||
PatKind::Wild | PatKind::Rest | PatKind::Never => {}
|
||||
PatKind::Err(_guar) => {}
|
||||
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
|
||||
walk_list!(visitor, visit_pat, elems);
|
||||
}
|
||||
@ -672,12 +695,7 @@ impl WalkItemKind for ForeignItemKind {
|
||||
) -> V::Result {
|
||||
let &Item { id, span, ident, ref vis, .. } = item;
|
||||
match self {
|
||||
ForeignItemKind::Static(box StaticForeignItem {
|
||||
ty,
|
||||
mutability: _,
|
||||
expr,
|
||||
safety: _,
|
||||
}) => {
|
||||
ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
visit_opt!(visitor, visit_expr, expr);
|
||||
}
|
||||
@ -685,7 +703,13 @@ impl WalkItemKind for ForeignItemKind {
|
||||
let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref());
|
||||
try_visit!(visitor.visit_fn(kind, span, id));
|
||||
}
|
||||
ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
|
||||
ForeignItemKind::TyAlias(box TyAlias {
|
||||
generics,
|
||||
bounds,
|
||||
ty,
|
||||
defaultness: _,
|
||||
where_clauses: _,
|
||||
}) => {
|
||||
try_visit!(visitor.visit_generics(generics));
|
||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
|
||||
visit_opt!(visitor, visit_ty, ty);
|
||||
@ -702,7 +726,7 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB
|
||||
match bound {
|
||||
GenericBound::Trait(typ, _modifier) => visitor.visit_poly_trait_ref(typ),
|
||||
GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound),
|
||||
GenericBound::Use(args, _) => {
|
||||
GenericBound::Use(args, _span) => {
|
||||
walk_list!(visitor, visit_precise_capturing_arg, args);
|
||||
V::Result::output()
|
||||
}
|
||||
@ -727,13 +751,15 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(
|
||||
visitor: &mut V,
|
||||
param: &'a GenericParam,
|
||||
) -> V::Result {
|
||||
try_visit!(visitor.visit_ident(param.ident));
|
||||
walk_list!(visitor, visit_attribute, ¶m.attrs);
|
||||
walk_list!(visitor, visit_param_bound, ¶m.bounds, BoundKind::Bound);
|
||||
match ¶m.kind {
|
||||
let GenericParam { id: _, ident, attrs, bounds, is_placeholder: _, kind, colon_span: _ } =
|
||||
param;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_ident(*ident));
|
||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
|
||||
match kind {
|
||||
GenericParamKind::Lifetime => (),
|
||||
GenericParamKind::Type { default } => visit_opt!(visitor, visit_ty, default),
|
||||
GenericParamKind::Const { ty, default, .. } => {
|
||||
GenericParamKind::Const { ty, default, kw_span: _ } => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
visit_opt!(visitor, visit_anon_const, default);
|
||||
}
|
||||
@ -742,8 +768,10 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(
|
||||
}
|
||||
|
||||
pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) -> V::Result {
|
||||
walk_list!(visitor, visit_generic_param, &generics.params);
|
||||
walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
|
||||
let Generics { params, where_clause, span: _ } = generics;
|
||||
let WhereClause { has_where_token: _, predicates, span: _ } = where_clause;
|
||||
walk_list!(visitor, visit_generic_param, params);
|
||||
walk_list!(visitor, visit_where_predicate, predicates);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
@ -769,17 +797,17 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(
|
||||
bounded_ty,
|
||||
bounds,
|
||||
bound_generic_params,
|
||||
..
|
||||
span: _,
|
||||
}) => {
|
||||
walk_list!(visitor, visit_generic_param, bound_generic_params);
|
||||
try_visit!(visitor.visit_ty(bounded_ty));
|
||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
|
||||
walk_list!(visitor, visit_generic_param, bound_generic_params);
|
||||
}
|
||||
WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, .. }) => {
|
||||
WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, span: _ }) => {
|
||||
try_visit!(visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound));
|
||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
|
||||
}
|
||||
WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, .. }) => {
|
||||
WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span: _ }) => {
|
||||
try_visit!(visitor.visit_ty(lhs_ty));
|
||||
try_visit!(visitor.visit_ty(rhs_ty));
|
||||
}
|
||||
@ -788,26 +816,28 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(
|
||||
}
|
||||
|
||||
pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) -> V::Result {
|
||||
if let FnRetTy::Ty(output_ty) = ret_ty {
|
||||
try_visit!(visitor.visit_ty(output_ty));
|
||||
match ret_ty {
|
||||
FnRetTy::Default(_span) => {}
|
||||
FnRetTy::Ty(output_ty) => try_visit!(visitor.visit_ty(output_ty)),
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_fn_decl<'a, V: Visitor<'a>>(
|
||||
visitor: &mut V,
|
||||
function_declaration: &'a FnDecl,
|
||||
FnDecl { inputs, output }: &'a FnDecl,
|
||||
) -> V::Result {
|
||||
walk_list!(visitor, visit_param, &function_declaration.inputs);
|
||||
visitor.visit_fn_ret_ty(&function_declaration.output)
|
||||
walk_list!(visitor, visit_param, inputs);
|
||||
visitor.visit_fn_ret_ty(output)
|
||||
}
|
||||
|
||||
pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Result {
|
||||
match kind {
|
||||
FnKind::Fn(_, _, sig, _, generics, body) => {
|
||||
FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body) => {
|
||||
// Identifier and visibility are visited as a part of the item.
|
||||
try_visit!(visitor.visit_fn_header(header));
|
||||
try_visit!(visitor.visit_generics(generics));
|
||||
try_visit!(visitor.visit_fn_header(&sig.header));
|
||||
try_visit!(walk_fn_decl(visitor, &sig.decl));
|
||||
try_visit!(walk_fn_decl(visitor, decl));
|
||||
visit_opt!(visitor, visit_block, body);
|
||||
}
|
||||
FnKind::Closure(binder, decl, body) => {
|
||||
@ -838,7 +868,13 @@ impl WalkItemKind for AssocItemKind {
|
||||
FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
|
||||
try_visit!(visitor.visit_fn(kind, span, id));
|
||||
}
|
||||
AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) => {
|
||||
AssocItemKind::Type(box TyAlias {
|
||||
generics,
|
||||
bounds,
|
||||
ty,
|
||||
defaultness: _,
|
||||
where_clauses: _,
|
||||
}) => {
|
||||
try_visit!(visitor.visit_generics(generics));
|
||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
|
||||
visit_opt!(visitor, visit_ty, ty);
|
||||
@ -854,18 +890,14 @@ impl WalkItemKind for AssocItemKind {
|
||||
body,
|
||||
from_glob: _,
|
||||
}) => {
|
||||
if let Some(qself) = qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(walk_qself(visitor, qself));
|
||||
try_visit!(visitor.visit_path(path, *id));
|
||||
visit_opt!(visitor, visit_ident, *rename);
|
||||
visit_opt!(visitor, visit_block, body);
|
||||
}
|
||||
AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
|
||||
if let Some(qself) = qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(visitor.visit_path(prefix, item.id));
|
||||
try_visit!(walk_qself(visitor, qself));
|
||||
try_visit!(visitor.visit_path(prefix, id));
|
||||
if let Some(suffixes) = suffixes {
|
||||
for (ident, rename) in suffixes {
|
||||
visitor.visit_ident(*ident);
|
||||
@ -887,10 +919,10 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(
|
||||
ctxt: AssocCtxt,
|
||||
) -> V::Result {
|
||||
let &Item { id: _, span: _, ident, ref vis, ref attrs, ref kind, tokens: _ } = item;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_vis(vis));
|
||||
try_visit!(visitor.visit_ident(ident));
|
||||
try_visit!(kind.walk(item, ctxt, visitor));
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
@ -903,53 +935,68 @@ pub fn walk_struct_def<'a, V: Visitor<'a>>(
|
||||
}
|
||||
|
||||
pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result {
|
||||
try_visit!(visitor.visit_vis(&field.vis));
|
||||
visit_opt!(visitor, visit_ident, field.ident);
|
||||
try_visit!(visitor.visit_ty(&field.ty));
|
||||
walk_list!(visitor, visit_attribute, &field.attrs);
|
||||
let FieldDef { attrs, id: _, span: _, vis, ident, ty, is_placeholder: _ } = field;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_vis(vis));
|
||||
visit_opt!(visitor, visit_ident, *ident);
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::Result {
|
||||
walk_list!(visitor, visit_stmt, &block.stmts);
|
||||
let Block { stmts, id: _, rules: _, span: _, tokens: _, could_be_bare_literal: _ } = block;
|
||||
walk_list!(visitor, visit_stmt, stmts);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
|
||||
match &statement.kind {
|
||||
let Stmt { id: _, kind, span: _ } = statement;
|
||||
match kind {
|
||||
StmtKind::Let(local) => try_visit!(visitor.visit_local(local)),
|
||||
StmtKind::Item(item) => try_visit!(visitor.visit_item(item)),
|
||||
StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)),
|
||||
StmtKind::Empty => {}
|
||||
StmtKind::MacCall(mac) => {
|
||||
let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
|
||||
try_visit!(visitor.visit_mac_call(mac));
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_mac_call(mac));
|
||||
}
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) -> V::Result {
|
||||
visitor.visit_path(&mac.path, DUMMY_NODE_ID)
|
||||
let MacCall { path, args: _ } = mac;
|
||||
visitor.visit_path(path, DUMMY_NODE_ID)
|
||||
}
|
||||
|
||||
pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) -> V::Result {
|
||||
visitor.visit_expr(&constant.value)
|
||||
let AnonConst { id: _, value } = constant;
|
||||
visitor.visit_expr(value)
|
||||
}
|
||||
|
||||
pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result {
|
||||
for (op, _) in &asm.operands {
|
||||
let InlineAsm {
|
||||
template: _,
|
||||
template_strs: _,
|
||||
operands,
|
||||
clobber_abis: _,
|
||||
options: _,
|
||||
line_spans: _,
|
||||
} = asm;
|
||||
for (op, _span) in operands {
|
||||
match op {
|
||||
InlineAsmOperand::In { expr, .. }
|
||||
| InlineAsmOperand::Out { expr: Some(expr), .. }
|
||||
| InlineAsmOperand::InOut { expr, .. } => try_visit!(visitor.visit_expr(expr)),
|
||||
InlineAsmOperand::Out { expr: None, .. } => {}
|
||||
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
|
||||
InlineAsmOperand::In { expr, reg: _ }
|
||||
| InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ }
|
||||
| InlineAsmOperand::InOut { expr, reg: _, late: _ } => {
|
||||
try_visit!(visitor.visit_expr(expr))
|
||||
}
|
||||
InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {}
|
||||
InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
|
||||
try_visit!(visitor.visit_expr(in_expr));
|
||||
visit_opt!(visitor, visit_expr, out_expr);
|
||||
}
|
||||
InlineAsmOperand::Const { anon_const, .. } => {
|
||||
InlineAsmOperand::Const { anon_const } => {
|
||||
try_visit!(visitor.visit_anon_const(anon_const))
|
||||
}
|
||||
InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)),
|
||||
@ -961,28 +1008,30 @@ pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm)
|
||||
|
||||
pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(
|
||||
visitor: &mut V,
|
||||
sym: &'a InlineAsmSym,
|
||||
InlineAsmSym { id, qself, path }: &'a InlineAsmSym,
|
||||
) -> V::Result {
|
||||
if let Some(qself) = &sym.qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
visitor.visit_path(&sym.path, sym.id)
|
||||
try_visit!(walk_qself(visitor, qself));
|
||||
visitor.visit_path(path, *id)
|
||||
}
|
||||
|
||||
pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result {
|
||||
for arg in fmt.arguments.all_args() {
|
||||
if let FormatArgumentKind::Named(name) = arg.kind {
|
||||
try_visit!(visitor.visit_ident(name));
|
||||
let FormatArgs { span: _, template: _, arguments } = fmt;
|
||||
for FormatArgument { kind, expr } in arguments.all_args() {
|
||||
match kind {
|
||||
FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => {
|
||||
try_visit!(visitor.visit_ident(*ident))
|
||||
}
|
||||
FormatArgumentKind::Normal => {}
|
||||
}
|
||||
try_visit!(visitor.visit_expr(&arg.expr));
|
||||
try_visit!(visitor.visit_expr(expr));
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V::Result {
|
||||
walk_list!(visitor, visit_attribute, &expression.attrs);
|
||||
|
||||
match &expression.kind {
|
||||
let Expr { id, kind, span, attrs, tokens: _ } = expression;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
match kind {
|
||||
ExprKind::Array(subexpressions) => {
|
||||
walk_list!(visitor, visit_expr, subexpressions);
|
||||
}
|
||||
@ -992,12 +1041,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||
try_visit!(visitor.visit_anon_const(count));
|
||||
}
|
||||
ExprKind::Struct(se) => {
|
||||
if let Some(qself) = &se.qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(visitor.visit_path(&se.path, expression.id));
|
||||
walk_list!(visitor, visit_expr_field, &se.fields);
|
||||
match &se.rest {
|
||||
let StructExpr { qself, path, fields, rest } = &**se;
|
||||
try_visit!(walk_qself(visitor, qself));
|
||||
try_visit!(visitor.visit_path(path, *id));
|
||||
walk_list!(visitor, visit_expr_field, fields);
|
||||
match rest {
|
||||
StructRest::Base(expr) => try_visit!(visitor.visit_expr(expr)),
|
||||
StructRest::Rest(_span) => {}
|
||||
StructRest::None => {}
|
||||
@ -1011,22 +1059,25 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||
walk_list!(visitor, visit_expr, arguments);
|
||||
}
|
||||
ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => {
|
||||
try_visit!(visitor.visit_path_segment(seg));
|
||||
try_visit!(visitor.visit_expr(receiver));
|
||||
try_visit!(visitor.visit_path_segment(seg));
|
||||
walk_list!(visitor, visit_expr, args);
|
||||
}
|
||||
ExprKind::Binary(_, left_expression, right_expression) => {
|
||||
ExprKind::Binary(_op, left_expression, right_expression) => {
|
||||
try_visit!(visitor.visit_expr(left_expression));
|
||||
try_visit!(visitor.visit_expr(right_expression));
|
||||
}
|
||||
ExprKind::AddrOf(_, _, subexpression) | ExprKind::Unary(_, subexpression) => {
|
||||
ExprKind::AddrOf(_kind, _mutbl, subexpression) => {
|
||||
try_visit!(visitor.visit_expr(subexpression));
|
||||
}
|
||||
ExprKind::Unary(_op, subexpression) => {
|
||||
try_visit!(visitor.visit_expr(subexpression));
|
||||
}
|
||||
ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => {
|
||||
try_visit!(visitor.visit_expr(subexpression));
|
||||
try_visit!(visitor.visit_ty(typ));
|
||||
}
|
||||
ExprKind::Let(pat, expr, _, _) => {
|
||||
ExprKind::Let(pat, expr, _span, _recovered) => {
|
||||
try_visit!(visitor.visit_pat(pat));
|
||||
try_visit!(visitor.visit_expr(expr));
|
||||
}
|
||||
@ -1046,7 +1097,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||
try_visit!(visitor.visit_expr(iter));
|
||||
try_visit!(visitor.visit_block(body));
|
||||
}
|
||||
ExprKind::Loop(block, opt_label, _) => {
|
||||
ExprKind::Loop(block, opt_label, _span) => {
|
||||
visit_opt!(visitor, visit_label, opt_label);
|
||||
try_visit!(visitor.visit_block(block));
|
||||
}
|
||||
@ -1066,23 +1117,19 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||
fn_arg_span: _,
|
||||
}) => {
|
||||
try_visit!(visitor.visit_capture_by(capture_clause));
|
||||
try_visit!(visitor.visit_fn(
|
||||
FnKind::Closure(binder, fn_decl, body),
|
||||
expression.span,
|
||||
expression.id
|
||||
))
|
||||
try_visit!(visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), *span, *id))
|
||||
}
|
||||
ExprKind::Block(block, opt_label) => {
|
||||
visit_opt!(visitor, visit_label, opt_label);
|
||||
try_visit!(visitor.visit_block(block));
|
||||
}
|
||||
ExprKind::Gen(_, body, _) => try_visit!(visitor.visit_block(body)),
|
||||
ExprKind::Await(expr, _) => try_visit!(visitor.visit_expr(expr)),
|
||||
ExprKind::Assign(lhs, rhs, _) => {
|
||||
ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)),
|
||||
ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
|
||||
ExprKind::Assign(lhs, rhs, _span) => {
|
||||
try_visit!(visitor.visit_expr(lhs));
|
||||
try_visit!(visitor.visit_expr(rhs));
|
||||
}
|
||||
ExprKind::AssignOp(_, left_expression, right_expression) => {
|
||||
ExprKind::AssignOp(_op, left_expression, right_expression) => {
|
||||
try_visit!(visitor.visit_expr(left_expression));
|
||||
try_visit!(visitor.visit_expr(right_expression));
|
||||
}
|
||||
@ -1090,20 +1137,18 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||
try_visit!(visitor.visit_expr(subexpression));
|
||||
try_visit!(visitor.visit_ident(*ident));
|
||||
}
|
||||
ExprKind::Index(main_expression, index_expression, _) => {
|
||||
ExprKind::Index(main_expression, index_expression, _span) => {
|
||||
try_visit!(visitor.visit_expr(main_expression));
|
||||
try_visit!(visitor.visit_expr(index_expression));
|
||||
}
|
||||
ExprKind::Range(start, end, _) => {
|
||||
ExprKind::Range(start, end, _limit) => {
|
||||
visit_opt!(visitor, visit_expr, start);
|
||||
visit_opt!(visitor, visit_expr, end);
|
||||
}
|
||||
ExprKind::Underscore => {}
|
||||
ExprKind::Path(maybe_qself, path) => {
|
||||
if let Some(qself) = maybe_qself {
|
||||
try_visit!(visitor.visit_ty(&qself.ty));
|
||||
}
|
||||
try_visit!(visitor.visit_path(path, expression.id));
|
||||
try_visit!(walk_qself(visitor, maybe_qself));
|
||||
try_visit!(visitor.visit_path(path, *id));
|
||||
}
|
||||
ExprKind::Break(opt_label, opt_expr) => {
|
||||
visit_opt!(visitor, visit_label, opt_label);
|
||||
@ -1132,38 +1177,53 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||
}
|
||||
ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)),
|
||||
ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)),
|
||||
ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err(_) | ExprKind::Dummy => {}
|
||||
ExprKind::Lit(_token) => {}
|
||||
ExprKind::IncludedBytes(_bytes) => {}
|
||||
ExprKind::Err(_guar) => {}
|
||||
ExprKind::Dummy => {}
|
||||
}
|
||||
|
||||
visitor.visit_expr_post(expression)
|
||||
}
|
||||
|
||||
pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::Result {
|
||||
walk_list!(visitor, visit_attribute, ¶m.attrs);
|
||||
try_visit!(visitor.visit_pat(¶m.pat));
|
||||
try_visit!(visitor.visit_ty(¶m.ty));
|
||||
let Param { attrs, ty, pat, id: _, span: _, is_placeholder: _ } = param;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_pat(pat));
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result {
|
||||
try_visit!(visitor.visit_pat(&arm.pat));
|
||||
visit_opt!(visitor, visit_expr, &arm.guard);
|
||||
visit_opt!(visitor, visit_expr, &arm.body);
|
||||
walk_list!(visitor, visit_attribute, &arm.attrs);
|
||||
let Arm { attrs, pat, guard, body, span: _, id: _, is_placeholder: _ } = arm;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_pat(pat));
|
||||
visit_opt!(visitor, visit_expr, guard);
|
||||
visit_opt!(visitor, visit_expr, body);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) -> V::Result {
|
||||
if let VisibilityKind::Restricted { ref path, id, shorthand: _ } = vis.kind {
|
||||
try_visit!(visitor.visit_path(path, id));
|
||||
let Visibility { kind, span: _, tokens: _ } = vis;
|
||||
match kind {
|
||||
VisibilityKind::Restricted { path, id, shorthand: _ } => {
|
||||
try_visit!(visitor.visit_path(path, *id));
|
||||
}
|
||||
VisibilityKind::Public | VisibilityKind::Inherited => {}
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) -> V::Result {
|
||||
match &attr.kind {
|
||||
AttrKind::Normal(normal) => try_visit!(walk_attr_args(visitor, &normal.item.args)),
|
||||
AttrKind::DocComment(..) => {}
|
||||
let Attribute { kind, id: _, style: _, span: _ } = attr;
|
||||
match kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
let NormalAttr { item, tokens: _ } = &**normal;
|
||||
let AttrItem { unsafety: _, path, args, tokens: _ } = item;
|
||||
try_visit!(visitor.visit_path(path, DUMMY_NODE_ID));
|
||||
try_visit!(walk_attr_args(visitor, args));
|
||||
}
|
||||
AttrKind::DocComment(_kind, _sym) => {}
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
@ -1171,9 +1231,9 @@ pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute)
|
||||
pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -> V::Result {
|
||||
match args {
|
||||
AttrArgs::Empty => {}
|
||||
AttrArgs::Delimited(_) => {}
|
||||
AttrArgs::Delimited(_args) => {}
|
||||
AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => try_visit!(visitor.visit_expr(expr)),
|
||||
AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
|
||||
AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => {
|
||||
unreachable!("in literal form when walking mac args eq: {:?}", lit)
|
||||
}
|
||||
}
|
||||
|
@ -36,10 +36,15 @@ ast_lowering_bad_return_type_notation_inputs =
|
||||
argument types not allowed with return type notation
|
||||
.suggestion = remove the input types
|
||||
|
||||
ast_lowering_bad_return_type_notation_needs_dots = return type notation arguments must be elided with `..`
|
||||
.suggestion = add `..`
|
||||
|
||||
ast_lowering_bad_return_type_notation_output =
|
||||
return type not allowed with return type notation
|
||||
.suggestion = remove the return type
|
||||
|
||||
ast_lowering_bad_return_type_notation_position = return type notation not allowed in this position yet
|
||||
|
||||
ast_lowering_base_expression_double_dot =
|
||||
base expression required after `..`
|
||||
.suggestion = add a base expression here
|
||||
@ -78,7 +83,7 @@ ast_lowering_inline_asm_unsupported_target =
|
||||
ast_lowering_invalid_abi =
|
||||
invalid ABI: found `{$abi}`
|
||||
.label = invalid ABI
|
||||
.note = invoke `{$command}` for a full list of supported calling conventions.
|
||||
.note = invoke `{$command}` for a full list of supported calling conventions
|
||||
|
||||
ast_lowering_invalid_abi_clobber_abi =
|
||||
invalid ABI for `clobber_abi`
|
||||
@ -130,6 +135,9 @@ ast_lowering_never_pattern_with_guard =
|
||||
|
||||
ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait`
|
||||
|
||||
ast_lowering_no_precise_captures_on_rpitit = `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
|
||||
.note = currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
|
||||
|
||||
ast_lowering_previously_used_here = previously used here
|
||||
|
||||
ast_lowering_register1 = register `{$reg1_name}`
|
||||
|
@ -66,14 +66,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let Ok(sig_id) = sig_id else {
|
||||
return false;
|
||||
};
|
||||
if let Some(local_sig_id) = sig_id.as_local() {
|
||||
self.has_self(sig_id, span)
|
||||
}
|
||||
|
||||
fn has_self(&self, def_id: DefId, span: Span) -> bool {
|
||||
if let Some(local_sig_id) = def_id.as_local() {
|
||||
// The value may be missing due to recursive delegation.
|
||||
// Error will be emmited later during HIR ty lowering.
|
||||
self.resolver.delegation_fn_sigs.get(&local_sig_id).map_or(false, |sig| sig.has_self)
|
||||
} else {
|
||||
match self.tcx.def_kind(sig_id) {
|
||||
match self.tcx.def_kind(def_id) {
|
||||
DefKind::Fn => false,
|
||||
DefKind::AssocFn => self.tcx.associated_item(sig_id).fn_has_self_parameter,
|
||||
DefKind::AssocFn => self.tcx.associated_item(def_id).fn_has_self_parameter,
|
||||
_ => span_bug!(span, "unexpected DefKind for delegation item"),
|
||||
}
|
||||
}
|
||||
@ -107,12 +111,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
span: Span,
|
||||
) -> Result<DefId, ErrorGuaranteed> {
|
||||
let sig_id = if self.is_in_trait_impl { item_id } else { path_id };
|
||||
let sig_id =
|
||||
self.resolver.get_partial_res(sig_id).and_then(|r| r.expect_full_res().opt_def_id());
|
||||
sig_id.ok_or_else(|| {
|
||||
self.tcx
|
||||
.dcx()
|
||||
.span_delayed_bug(span, "LoweringContext: couldn't resolve delegation item")
|
||||
self.get_resolution_id(sig_id, span)
|
||||
}
|
||||
|
||||
fn get_resolution_id(&self, node_id: NodeId, span: Span) -> Result<DefId, ErrorGuaranteed> {
|
||||
let def_id =
|
||||
self.resolver.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id());
|
||||
def_id.ok_or_else(|| {
|
||||
self.tcx.dcx().span_delayed_bug(
|
||||
span,
|
||||
format!("LoweringContext: couldn't resolve node {:?} in delegation item", node_id),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@ -122,7 +131,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
predicates: &[],
|
||||
has_where_clause_predicates: false,
|
||||
where_clause_span: span,
|
||||
span: span,
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
||||
@ -222,12 +231,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}));
|
||||
|
||||
let path = self.arena.alloc(hir::Path { span, res: Res::Local(param_id), segments });
|
||||
|
||||
hir::Expr {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
|
||||
span,
|
||||
}
|
||||
self.mk_expr(hir::ExprKind::Path(hir::QPath::Resolved(None, path)), span)
|
||||
}
|
||||
|
||||
fn lower_delegation_body(
|
||||
@ -236,19 +240,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
param_count: usize,
|
||||
span: Span,
|
||||
) -> BodyId {
|
||||
let path = self.lower_qpath(
|
||||
delegation.id,
|
||||
&delegation.qself,
|
||||
&delegation.path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
let block = delegation.body.as_deref();
|
||||
|
||||
self.lower_body(|this| {
|
||||
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
|
||||
let mut args: Vec<hir::Expr<'hir>> = Vec::new();
|
||||
let mut parameters: Vec<hir::Param<'_>> = Vec::with_capacity(param_count);
|
||||
let mut args: Vec<hir::Expr<'_>> = Vec::with_capacity(param_count);
|
||||
|
||||
for idx in 0..param_count {
|
||||
let (param, pat_node_id) = this.generate_param(span);
|
||||
@ -264,11 +260,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
};
|
||||
self_resolver.visit_block(block);
|
||||
let block = this.lower_block(block, false);
|
||||
hir::Expr {
|
||||
hir_id: this.next_id(),
|
||||
kind: hir::ExprKind::Block(block, None),
|
||||
span: block.span,
|
||||
}
|
||||
this.mk_expr(hir::ExprKind::Block(block, None), block.span)
|
||||
} else {
|
||||
let pat_hir_id = this.lower_node_id(pat_node_id);
|
||||
this.generate_arg(pat_hir_id, span)
|
||||
@ -276,43 +268,41 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
args.push(arg);
|
||||
}
|
||||
|
||||
let args = self.arena.alloc_from_iter(args);
|
||||
let final_expr = this.generate_call(path, args);
|
||||
let final_expr = this.finalize_body_lowering(delegation, args, span);
|
||||
(this.arena.alloc_from_iter(parameters), final_expr)
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_call(
|
||||
// Generates fully qualified call for the resulting body.
|
||||
fn finalize_body_lowering(
|
||||
&mut self,
|
||||
path: hir::QPath<'hir>,
|
||||
args: &'hir [hir::Expr<'hir>],
|
||||
delegation: &Delegation,
|
||||
args: Vec<hir::Expr<'hir>>,
|
||||
span: Span,
|
||||
) -> hir::Expr<'hir> {
|
||||
let callee = self.arena.alloc(hir::Expr {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ExprKind::Path(path),
|
||||
span: path.span(),
|
||||
});
|
||||
let path = self.lower_qpath(
|
||||
delegation.id,
|
||||
&delegation.qself,
|
||||
&delegation.path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
|
||||
let expr = self.arena.alloc(hir::Expr {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ExprKind::Call(callee, args),
|
||||
span: path.span(),
|
||||
});
|
||||
let args = self.arena.alloc_from_iter(args);
|
||||
let path_expr = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(path), span));
|
||||
let call = self.arena.alloc(self.mk_expr(hir::ExprKind::Call(path_expr, args), span));
|
||||
|
||||
let block = self.arena.alloc(hir::Block {
|
||||
stmts: &[],
|
||||
expr: Some(expr),
|
||||
expr: Some(call),
|
||||
hir_id: self.next_id(),
|
||||
rules: hir::BlockCheckMode::DefaultBlock,
|
||||
span: path.span(),
|
||||
span,
|
||||
targeted_by_break: false,
|
||||
});
|
||||
|
||||
hir::Expr {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ExprKind::Block(block, None),
|
||||
span: path.span(),
|
||||
}
|
||||
self.mk_expr(hir::ExprKind::Block(block, None), span)
|
||||
}
|
||||
|
||||
fn generate_delegation_error(
|
||||
@ -333,11 +323,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let header = self.generate_header_error();
|
||||
let sig = hir::FnSig { decl, header, span };
|
||||
|
||||
let body_id = self.lower_body(|this| {
|
||||
let expr =
|
||||
hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
|
||||
(&[], expr)
|
||||
});
|
||||
let body_id = self.lower_body(|this| (&[], this.mk_expr(hir::ExprKind::Err(err), span)));
|
||||
DelegationResults { generics, body_id, sig }
|
||||
}
|
||||
|
||||
@ -349,6 +335,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
abi: abi::Abi::Rust,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mk_expr(&mut self, kind: hir::ExprKind<'hir>, span: Span) -> hir::Expr<'hir> {
|
||||
hir::Expr { hir_id: self.next_id(), kind, span }
|
||||
}
|
||||
}
|
||||
|
||||
struct SelfResolver<'a> {
|
||||
|
@ -393,6 +393,17 @@ pub enum BadReturnTypeNotation {
|
||||
#[suggestion(code = "", applicability = "maybe-incorrect")]
|
||||
span: Span,
|
||||
},
|
||||
#[diag(ast_lowering_bad_return_type_notation_needs_dots)]
|
||||
NeedsDots {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "(..)", applicability = "maybe-incorrect")]
|
||||
span: Span,
|
||||
},
|
||||
#[diag(ast_lowering_bad_return_type_notation_position)]
|
||||
Position {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -424,6 +435,14 @@ pub(crate) struct NoPreciseCapturesOnApit {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering_no_precise_captures_on_rpitit)]
|
||||
#[note]
|
||||
pub(crate) struct NoPreciseCapturesOnRpitit {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering_yield_in_closure)]
|
||||
pub(crate) struct YieldInClosure {
|
||||
|
@ -103,7 +103,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
ParamMode::Optional,
|
||||
ParenthesizedGenericArgs::Err,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
// Method calls can't have bound modifiers
|
||||
None,
|
||||
));
|
||||
@ -227,7 +226,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
*fn_arg_span,
|
||||
),
|
||||
},
|
||||
ExprKind::Gen(capture_clause, block, genblock_kind) => {
|
||||
ExprKind::Gen(capture_clause, block, genblock_kind, decl_span) => {
|
||||
let desugaring_kind = match genblock_kind {
|
||||
GenBlockKind::Async => hir::CoroutineDesugaring::Async,
|
||||
GenBlockKind::Gen => hir::CoroutineDesugaring::Gen,
|
||||
@ -237,6 +236,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
*capture_clause,
|
||||
e.id,
|
||||
None,
|
||||
*decl_span,
|
||||
e.span,
|
||||
desugaring_kind,
|
||||
hir::CoroutineSource::Block,
|
||||
@ -616,6 +616,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
capture_clause: CaptureBy,
|
||||
closure_node_id: NodeId,
|
||||
return_ty: Option<hir::FnRetTy<'hir>>,
|
||||
fn_decl_span: Span,
|
||||
span: Span,
|
||||
desugaring_kind: hir::CoroutineDesugaring,
|
||||
coroutine_source: hir::CoroutineSource,
|
||||
@ -692,7 +693,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
bound_generic_params: &[],
|
||||
fn_decl,
|
||||
body,
|
||||
fn_decl_span: self.lower_span(span),
|
||||
fn_decl_span: self.lower_span(fn_decl_span),
|
||||
fn_arg_span: None,
|
||||
kind: hir::ClosureKind::Coroutine(coroutine_kind),
|
||||
constness: hir::Constness::NotConst,
|
||||
@ -1083,6 +1084,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
||||
&inner_decl,
|
||||
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
|
||||
fn_decl_span,
|
||||
body.span,
|
||||
coroutine_kind,
|
||||
hir::CoroutineSource::Closure,
|
||||
|
@ -56,7 +56,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||
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.resolver, self.ast_index);
|
||||
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
||||
|
||||
for (def_id, info) in lctx.children {
|
||||
@ -190,6 +190,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let (generics, (ty, body_id)) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
@ -211,6 +212,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// declaration (decl), not the return types.
|
||||
let coroutine_kind = header.coroutine_kind;
|
||||
let body_id = this.lower_maybe_coroutine_body(
|
||||
*fn_sig_span,
|
||||
span,
|
||||
hir_id,
|
||||
decl,
|
||||
@ -220,7 +222,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) =
|
||||
this.lower_generics(generics, header.constness, id, itctx, |this| {
|
||||
this.lower_generics(generics, header.constness, false, id, itctx, |this| {
|
||||
this.lower_fn_decl(
|
||||
decl,
|
||||
id,
|
||||
@ -264,6 +266,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let (generics, ty) = self.lower_generics(
|
||||
&generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| match ty {
|
||||
@ -292,6 +295,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let (generics, variants) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
@ -306,6 +310,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let (generics, struct_def) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_variant_data(hir_id, struct_def),
|
||||
@ -316,6 +321,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let (generics, vdata) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| this.lower_variant_data(hir_id, vdata),
|
||||
@ -347,12 +353,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// parent lifetime.
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, (trait_ref, lowered_ty)) =
|
||||
self.lower_generics(ast_generics, *constness, id, itctx, |this| {
|
||||
self.lower_generics(ast_generics, Const::No, false, id, itctx, |this| {
|
||||
let modifiers = TraitBoundModifiers {
|
||||
constness: match *constness {
|
||||
Const::Yes(span) => BoundConstness::Maybe(span),
|
||||
Const::No => BoundConstness::Never,
|
||||
},
|
||||
constness: BoundConstness::Never,
|
||||
asyncness: BoundAsyncness::Normal,
|
||||
// we don't use this in bound lowering
|
||||
polarity: BoundPolarity::Positive,
|
||||
@ -388,6 +391,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
|
||||
};
|
||||
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
|
||||
constness: self.lower_constness(*constness),
|
||||
safety: self.lower_safety(*safety, hir::Safety::Safe),
|
||||
polarity,
|
||||
defaultness,
|
||||
@ -399,15 +403,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}))
|
||||
}
|
||||
ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
|
||||
// FIXME(const_trait_impl, effects, fee1-dead) this should be simplified if possible
|
||||
let constness = attrs
|
||||
.unwrap_or(&[])
|
||||
.iter()
|
||||
.find(|x| x.has_name(sym::const_trait))
|
||||
.map_or(Const::No, |x| Const::Yes(x.span));
|
||||
let (generics, (safety, items, bounds)) = self.lower_generics(
|
||||
generics,
|
||||
constness,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
@ -428,6 +427,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let (generics, bounds) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
@ -608,30 +608,48 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// This is used to track which lifetimes have already been defined,
|
||||
// and which need to be replicated when lowering an async fn.
|
||||
|
||||
let generics = match parent_hir.node().expect_item().kind {
|
||||
let parent_item = parent_hir.node().expect_item();
|
||||
let constness = match parent_item.kind {
|
||||
hir::ItemKind::Impl(impl_) => {
|
||||
self.is_in_trait_impl = impl_.of_trait.is_some();
|
||||
&impl_.generics
|
||||
// N.B. the impl should always lower to methods that have `const host: bool` params if the trait
|
||||
// is const. It doesn't matter whether the `impl` itself is const. Disallowing const fn from
|
||||
// calling non-const impls are done through associated types.
|
||||
if let Some(def_id) = impl_.of_trait.and_then(|tr| tr.trait_def_id()) {
|
||||
if let Some(local_def) = def_id.as_local() {
|
||||
match &self.ast_index[local_def] {
|
||||
AstOwner::Item(ast::Item { attrs, .. }) => attrs
|
||||
.iter()
|
||||
.find(|attr| attr.has_name(sym::const_trait))
|
||||
.map_or(Const::No, |attr| Const::Yes(attr.span)),
|
||||
_ => Const::No,
|
||||
}
|
||||
} else {
|
||||
if self.tcx.is_const_trait(def_id) {
|
||||
// FIXME(effects) span
|
||||
Const::Yes(self.tcx.def_ident_span(def_id).unwrap())
|
||||
} else {
|
||||
Const::No
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Const::No
|
||||
}
|
||||
}
|
||||
hir::ItemKind::Trait(_, _, generics, _, _) => generics,
|
||||
hir::ItemKind::Trait(_, _, _, _, _) => parent_hir
|
||||
.attrs
|
||||
.get(parent_item.hir_id().local_id)
|
||||
.iter()
|
||||
.find(|attr| attr.has_name(sym::const_trait))
|
||||
.map_or(Const::No, |attr| Const::Yes(attr.span)),
|
||||
kind => {
|
||||
span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
|
||||
}
|
||||
};
|
||||
|
||||
if self.tcx.features().effects {
|
||||
self.host_param_id = generics
|
||||
.params
|
||||
.iter()
|
||||
.find(|param| {
|
||||
matches!(param.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })
|
||||
})
|
||||
.map(|param| param.def_id);
|
||||
}
|
||||
|
||||
match ctxt {
|
||||
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
|
||||
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
|
||||
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item, constness)),
|
||||
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item, constness)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -647,7 +665,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let fdec = &sig.decl;
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, (fn_dec, fn_args)) =
|
||||
self.lower_generics(generics, Const::No, i.id, itctx, |this| {
|
||||
self.lower_generics(generics, Const::No, false, i.id, itctx, |this| {
|
||||
(
|
||||
// Disallow `impl Trait` in foreign items.
|
||||
this.lower_fn_decl(
|
||||
@ -664,12 +682,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics, safety)
|
||||
}
|
||||
ForeignItemKind::Static(box StaticForeignItem {
|
||||
ty,
|
||||
mutability,
|
||||
expr: _,
|
||||
safety,
|
||||
}) => {
|
||||
ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => {
|
||||
let ty = self
|
||||
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
|
||||
let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
|
||||
@ -769,7 +782,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
|
||||
fn lower_trait_item(
|
||||
&mut self,
|
||||
i: &AssocItem,
|
||||
trait_constness: Const,
|
||||
) -> &'hir hir::TraitItem<'hir> {
|
||||
let hir_id = self.lower_node_id(i.id);
|
||||
self.lower_attrs(hir_id, &i.attrs);
|
||||
let trait_item_def_id = hir_id.expect_owner();
|
||||
@ -779,6 +796,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let (generics, kind) = self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
@ -799,11 +817,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
i.id,
|
||||
FnDeclKind::Trait,
|
||||
sig.header.coroutine_kind,
|
||||
trait_constness,
|
||||
);
|
||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
|
||||
}
|
||||
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
|
||||
let body_id = self.lower_maybe_coroutine_body(
|
||||
sig.span,
|
||||
i.span,
|
||||
hir_id,
|
||||
&sig.decl,
|
||||
@ -816,6 +836,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
i.id,
|
||||
FnDeclKind::Trait,
|
||||
sig.header.coroutine_kind,
|
||||
trait_constness,
|
||||
);
|
||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
|
||||
}
|
||||
@ -825,6 +846,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let (generics, kind) = self.lower_generics(
|
||||
&generics,
|
||||
Const::No,
|
||||
false,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
@ -897,7 +919,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
self.expr(span, hir::ExprKind::Err(guar))
|
||||
}
|
||||
|
||||
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
|
||||
fn lower_impl_item(
|
||||
&mut self,
|
||||
i: &AssocItem,
|
||||
constness_of_trait: Const,
|
||||
) -> &'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);
|
||||
@ -908,6 +934,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
|
||||
generics,
|
||||
Const::No,
|
||||
false,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
@ -920,6 +947,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
),
|
||||
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
|
||||
let body_id = self.lower_maybe_coroutine_body(
|
||||
sig.span,
|
||||
i.span,
|
||||
hir_id,
|
||||
&sig.decl,
|
||||
@ -932,6 +960,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
i.id,
|
||||
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
|
||||
sig.header.coroutine_kind,
|
||||
constness_of_trait,
|
||||
);
|
||||
|
||||
(generics, hir::ImplItemKind::Fn(sig, body_id))
|
||||
@ -942,6 +971,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
self.lower_generics(
|
||||
&generics,
|
||||
Const::No,
|
||||
false,
|
||||
i.id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| match ty {
|
||||
@ -1116,6 +1146,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
/// `gen {}` block as appropriate.
|
||||
fn lower_maybe_coroutine_body(
|
||||
&mut self,
|
||||
fn_decl_span: Span,
|
||||
span: Span,
|
||||
fn_id: hir::HirId,
|
||||
decl: &FnDecl,
|
||||
@ -1129,6 +1160,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
||||
decl,
|
||||
|this| this.lower_block_expr(body),
|
||||
fn_decl_span,
|
||||
body.span,
|
||||
coroutine_kind,
|
||||
hir::CoroutineSource::Fn,
|
||||
@ -1150,6 +1182,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
&mut self,
|
||||
decl: &FnDecl,
|
||||
lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
|
||||
fn_decl_span: Span,
|
||||
body_span: Span,
|
||||
coroutine_kind: CoroutineKind,
|
||||
coroutine_source: hir::CoroutineSource,
|
||||
@ -1320,13 +1353,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
};
|
||||
let closure_id = coroutine_kind.closure_id();
|
||||
|
||||
let span = if let FnRetTy::Default(span) = decl.output
|
||||
&& matches!(coroutine_source, rustc_hir::CoroutineSource::Closure)
|
||||
{
|
||||
body_span.with_lo(span.lo())
|
||||
} else {
|
||||
body_span
|
||||
};
|
||||
let coroutine_expr = self.make_desugared_coroutine_expr(
|
||||
// The default capture mode here is by-ref. Later on during upvar analysis,
|
||||
// we will force the captured arguments to by-move, but for async closures,
|
||||
@ -1335,7 +1361,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
CaptureBy::Ref,
|
||||
closure_id,
|
||||
None,
|
||||
span,
|
||||
fn_decl_span,
|
||||
body_span,
|
||||
desugaring_kind,
|
||||
coroutine_source,
|
||||
mkbody,
|
||||
@ -1357,15 +1384,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
id: NodeId,
|
||||
kind: FnDeclKind,
|
||||
coroutine_kind: Option<CoroutineKind>,
|
||||
parent_constness: Const,
|
||||
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
||||
let header = self.lower_fn_header(sig.header);
|
||||
// Don't pass along the user-provided constness of trait associated functions; we don't want to
|
||||
// synthesize a host effect param for them. We reject `const` on them during AST validation.
|
||||
let constness = if kind == FnDeclKind::Inherent { sig.header.constness } else { Const::No };
|
||||
let constness =
|
||||
if kind == FnDeclKind::Inherent { sig.header.constness } else { parent_constness };
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) = self.lower_generics(generics, constness, id, itctx, |this| {
|
||||
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
|
||||
});
|
||||
let (generics, decl) =
|
||||
self.lower_generics(generics, constness, kind == FnDeclKind::Impl, id, itctx, |this| {
|
||||
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
|
||||
});
|
||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||
}
|
||||
|
||||
@ -1441,6 +1471,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
&mut self,
|
||||
generics: &Generics,
|
||||
constness: Const,
|
||||
force_append_constness: bool,
|
||||
parent_node_id: NodeId,
|
||||
itctx: ImplTraitContext,
|
||||
f: impl FnOnce(&mut Self) -> T,
|
||||
@ -1501,7 +1532,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// if the effects feature is enabled. This needs to be done before we lower where
|
||||
// clauses since where clauses need to bind to the DefId of the host param
|
||||
let host_param_parts = if let Const::Yes(span) = constness
|
||||
&& self.tcx.features().effects
|
||||
// if this comes from implementing a `const` trait, we must force constness to be appended
|
||||
// to the impl item, no matter whether effects is enabled.
|
||||
&& (self.tcx.features().effects || force_append_constness)
|
||||
{
|
||||
let span = self.lower_span(span);
|
||||
let param_node_id = self.next_node_id();
|
||||
@ -1614,6 +1647,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}),
|
||||
)),
|
||||
)),
|
||||
// FIXME(effects) we might not need a default.
|
||||
default: Some(self.arena.alloc(hir::AnonConst {
|
||||
def_id: anon_const,
|
||||
hir_id: const_id,
|
||||
@ -1621,6 +1655,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
span,
|
||||
})),
|
||||
is_host_effect: true,
|
||||
synthetic: true,
|
||||
},
|
||||
colon_span: None,
|
||||
pure_wrt_drop: false,
|
||||
|
@ -142,14 +142,19 @@ struct LoweringContext<'a, 'hir> {
|
||||
generics_def_id_map: Vec<LocalDefIdMap<LocalDefId>>,
|
||||
|
||||
host_param_id: Option<LocalDefId>,
|
||||
ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
|
||||
}
|
||||
|
||||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self {
|
||||
fn new(
|
||||
tcx: TyCtxt<'hir>,
|
||||
resolver: &'a mut ResolverAstLowering,
|
||||
ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
// Pseudo-globals.
|
||||
tcx,
|
||||
resolver: resolver,
|
||||
resolver,
|
||||
arena: tcx.hir_arena,
|
||||
|
||||
// HirId handling.
|
||||
@ -185,6 +190,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
|
||||
generics_def_id_map: Default::default(),
|
||||
host_param_id: None,
|
||||
ast_index,
|
||||
}
|
||||
}
|
||||
|
||||
@ -979,20 +985,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
|
||||
}
|
||||
GenericArgs::Parenthesized(data) => {
|
||||
if data.inputs.is_empty() && matches!(data.output, FnRetTy::Default(..)) {
|
||||
let parenthesized = if self.tcx.features().return_type_notation {
|
||||
hir::GenericArgsParentheses::ReturnTypeNotation
|
||||
} else {
|
||||
self.emit_bad_parenthesized_trait_in_assoc_ty(data);
|
||||
hir::GenericArgsParentheses::No
|
||||
};
|
||||
GenericArgsCtor {
|
||||
args: Default::default(),
|
||||
constraints: &[],
|
||||
parenthesized,
|
||||
span: data.inputs_span,
|
||||
}
|
||||
} else if let Some(first_char) = constraint.ident.as_str().chars().next()
|
||||
if let Some(first_char) = constraint.ident.as_str().chars().next()
|
||||
&& first_char.is_ascii_lowercase()
|
||||
{
|
||||
let mut err = if !data.inputs.is_empty() {
|
||||
@ -1004,7 +997,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
span: data.inputs_span.shrink_to_hi().to(ty.span),
|
||||
})
|
||||
} else {
|
||||
unreachable!("inputs are empty and return type is not provided")
|
||||
self.dcx().create_err(errors::BadReturnTypeNotation::NeedsDots {
|
||||
span: data.inputs_span,
|
||||
})
|
||||
};
|
||||
if !self.tcx.features().return_type_notation
|
||||
&& self.tcx.sess.is_nightly_build()
|
||||
@ -1034,6 +1029,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
.0
|
||||
}
|
||||
}
|
||||
GenericArgs::ParenthesizedElided(span) => GenericArgsCtor {
|
||||
args: Default::default(),
|
||||
constraints: &[],
|
||||
parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
|
||||
span: *span,
|
||||
},
|
||||
};
|
||||
gen_args_ctor.into_generic_args(self)
|
||||
} else {
|
||||
@ -1594,6 +1595,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
};
|
||||
debug!(?captured_lifetimes_to_duplicate);
|
||||
|
||||
match fn_kind {
|
||||
// Deny `use<>` on RPITIT in trait/trait-impl for now.
|
||||
Some(FnDeclKind::Trait | FnDeclKind::Impl) => {
|
||||
if let Some(span) = bounds.iter().find_map(|bound| match *bound {
|
||||
ast::GenericBound::Use(_, span) => Some(span),
|
||||
_ => None,
|
||||
}) {
|
||||
self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnRpitit { span });
|
||||
}
|
||||
}
|
||||
None
|
||||
| Some(
|
||||
FnDeclKind::Fn
|
||||
| FnDeclKind::Inherent
|
||||
| FnDeclKind::ExternFn
|
||||
| FnDeclKind::Closure
|
||||
| FnDeclKind::Pointer,
|
||||
) => {}
|
||||
}
|
||||
|
||||
self.lower_opaque_inner(
|
||||
opaque_ty_node_id,
|
||||
origin,
|
||||
@ -2115,7 +2136,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
param: &GenericParam,
|
||||
source: hir::GenericParamSource,
|
||||
) -> hir::GenericParam<'hir> {
|
||||
let (name, kind) = self.lower_generic_param_kind(param, source);
|
||||
let (name, kind) = self.lower_generic_param_kind(
|
||||
param,
|
||||
source,
|
||||
attr::contains_name(¶m.attrs, sym::rustc_runtime),
|
||||
);
|
||||
|
||||
let hir_id = self.lower_node_id(param.id);
|
||||
self.lower_attrs(hir_id, ¶m.attrs);
|
||||
@ -2135,6 +2160,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
&mut self,
|
||||
param: &GenericParam,
|
||||
source: hir::GenericParamSource,
|
||||
is_host_effect: bool,
|
||||
) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
|
||||
match ¶m.kind {
|
||||
GenericParamKind::Lifetime => {
|
||||
@ -2200,7 +2226,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
(
|
||||
hir::ParamName::Plain(self.lower_ident(param.ident)),
|
||||
hir::GenericParamKind::Const { ty, default, is_host_effect: false },
|
||||
hir::GenericParamKind::Const { ty, default, is_host_effect, synthetic: false },
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -2587,78 +2613,6 @@ struct GenericArgsCtor<'hir> {
|
||||
}
|
||||
|
||||
impl<'hir> GenericArgsCtor<'hir> {
|
||||
fn push_constness(
|
||||
&mut self,
|
||||
lcx: &mut LoweringContext<'_, 'hir>,
|
||||
constness: ast::BoundConstness,
|
||||
) {
|
||||
if !lcx.tcx.features().effects {
|
||||
return;
|
||||
}
|
||||
|
||||
let (span, body) = match constness {
|
||||
BoundConstness::Never => return,
|
||||
BoundConstness::Always(span) => {
|
||||
let span = lcx.lower_span(span);
|
||||
|
||||
let body = hir::ExprKind::Lit(
|
||||
lcx.arena.alloc(hir::Lit { node: LitKind::Bool(false), span }),
|
||||
);
|
||||
|
||||
(span, body)
|
||||
}
|
||||
BoundConstness::Maybe(span) => {
|
||||
let span = lcx.lower_span(span);
|
||||
|
||||
let Some(host_param_id) = lcx.host_param_id else {
|
||||
lcx.dcx().span_delayed_bug(
|
||||
span,
|
||||
"no host param id for call in const yet no errors reported",
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
let hir_id = lcx.next_id();
|
||||
let res = Res::Def(DefKind::ConstParam, host_param_id.to_def_id());
|
||||
let body = hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
lcx.arena.alloc(hir::Path {
|
||||
span,
|
||||
res,
|
||||
segments: arena_vec![
|
||||
lcx;
|
||||
hir::PathSegment::new(
|
||||
Ident { name: sym::host, span },
|
||||
hir_id,
|
||||
res
|
||||
)
|
||||
],
|
||||
}),
|
||||
));
|
||||
|
||||
(span, body)
|
||||
}
|
||||
};
|
||||
let body = lcx.lower_body(|lcx| (&[], lcx.expr(span, body)));
|
||||
|
||||
let id = lcx.next_node_id();
|
||||
let hir_id = lcx.next_id();
|
||||
|
||||
let def_id = lcx.create_def(
|
||||
lcx.current_hir_id_owner.def_id,
|
||||
id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
span,
|
||||
);
|
||||
|
||||
lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
|
||||
self.args.push(hir::GenericArg::Const(hir::ConstArg {
|
||||
value: lcx.arena.alloc(hir::AnonConst { def_id, hir_id, body, span }),
|
||||
is_desugared_from_effects: true,
|
||||
}))
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.args.is_empty()
|
||||
&& self.constraints.is_empty()
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::ImplTraitPosition;
|
||||
|
||||
use super::errors::{
|
||||
AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, GenericTypeWithParentheses, UseAngleBrackets,
|
||||
AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, BadReturnTypeNotation,
|
||||
GenericTypeWithParentheses, UseAngleBrackets,
|
||||
};
|
||||
use super::ResolverAstLoweringExt;
|
||||
use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs};
|
||||
@ -107,8 +108,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
param_mode,
|
||||
parenthesized_generic_args,
|
||||
itctx,
|
||||
// if this is the last segment, add constness to the trait path
|
||||
if i == proj_start - 1 { modifiers.map(|m| m.constness) } else { None },
|
||||
bound_modifier_allowed_features.clone(),
|
||||
)
|
||||
},
|
||||
@ -165,7 +164,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
ParenthesizedGenericArgs::Err,
|
||||
itctx,
|
||||
None,
|
||||
None,
|
||||
));
|
||||
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
|
||||
|
||||
@ -208,7 +206,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
ParenthesizedGenericArgs::Err,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
})),
|
||||
span: self.lower_span(p.span),
|
||||
@ -222,7 +219,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
param_mode: ParamMode,
|
||||
parenthesized_generic_args: ParenthesizedGenericArgs,
|
||||
itctx: ImplTraitContext,
|
||||
constness: Option<ast::BoundConstness>,
|
||||
// Additional features ungated with a bound modifier like `async`.
|
||||
// This is passed down to the implicit associated type binding in
|
||||
// parenthesized bounds.
|
||||
@ -276,6 +272,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
)
|
||||
}
|
||||
},
|
||||
GenericArgs::ParenthesizedElided(span) => {
|
||||
self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
|
||||
(
|
||||
GenericArgsCtor {
|
||||
args: Default::default(),
|
||||
constraints: &[],
|
||||
parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
|
||||
span: *span,
|
||||
},
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(
|
||||
@ -289,10 +297,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
)
|
||||
};
|
||||
|
||||
if let Some(constness) = constness {
|
||||
generic_args.push_constness(self, constness);
|
||||
}
|
||||
|
||||
let has_lifetimes =
|
||||
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
||||
|
||||
|
@ -28,7 +28,10 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim
|
||||
.label = {ast_passes_auto_super_lifetime}
|
||||
.suggestion = remove the super traits or lifetime bounds
|
||||
|
||||
ast_passes_bad_c_variadic = only foreign or `unsafe extern "C"` functions may be C-variadic
|
||||
ast_passes_bad_c_variadic = only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg
|
||||
|
||||
ast_passes_bare_fn_invalid_safety = function pointers cannot be declared with `safe` safety qualifier
|
||||
.suggestion = remove safe from this item
|
||||
|
||||
ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
|
||||
.cannot_have = cannot have a body
|
||||
@ -167,6 +170,9 @@ ast_passes_invalid_unnamed_field_ty =
|
||||
unnamed fields can only have struct or union types
|
||||
.label = not a struct or union
|
||||
|
||||
ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier
|
||||
.suggestion = remove safe from this item
|
||||
|
||||
ast_passes_item_underscore = `{$kind}` items in this context need a name
|
||||
.label = `_` is not a valid name for this `{$kind}` item
|
||||
|
||||
|
@ -1,10 +1,20 @@
|
||||
// Validate AST before lowering it to HIR.
|
||||
//
|
||||
// This pass is supposed to catch things that fit into AST data structures,
|
||||
// but not permitted by the language. It runs after expansion when AST is frozen,
|
||||
// so it can check for erroneous constructions produced by syntax extensions.
|
||||
// This pass is supposed to perform only simple checks not requiring name resolution
|
||||
// or type checking or some other kind of complex analysis.
|
||||
//! Validate AST before lowering it to HIR.
|
||||
//!
|
||||
//! This pass intends to check that the constructed AST is *syntactically valid* to allow the rest
|
||||
//! of the compiler to assume that the AST is valid. These checks cannot be performed during parsing
|
||||
//! because attribute macros are allowed to accept certain pieces of invalid syntax such as a
|
||||
//! function without body outside of a trait definition:
|
||||
//!
|
||||
//! ```ignore (illustrative)
|
||||
//! #[my_attribute]
|
||||
//! mod foo {
|
||||
//! fn missing_body();
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! These checks are run post-expansion, after AST is frozen, to be able to check for erroneous
|
||||
//! constructions produced by proc macros. This pass is only intended for simple checks that do not
|
||||
//! require name resolution or type checking, or other kinds of complex analysis.
|
||||
|
||||
use itertools::{Either, Itertools};
|
||||
use rustc_ast::ptr::P;
|
||||
@ -456,15 +466,34 @@ impl<'a> AstValidator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_foreign_item_safety(&self, item_span: Span, safety: Safety) {
|
||||
if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_))
|
||||
&& (self.extern_mod_safety == Some(Safety::Default)
|
||||
|| !self.features.unsafe_extern_blocks)
|
||||
{
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||
item_span,
|
||||
block: self.current_extern_span(),
|
||||
});
|
||||
fn check_item_safety(&self, span: Span, safety: Safety) {
|
||||
match self.extern_mod_safety {
|
||||
Some(extern_safety) => {
|
||||
if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) {
|
||||
if extern_safety == Safety::Default {
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||
item_span: span,
|
||||
block: Some(self.current_extern_span().shrink_to_lo()),
|
||||
});
|
||||
} else if !self.features.unsafe_extern_blocks {
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||
item_span: span,
|
||||
block: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if matches!(safety, Safety::Safe(_)) {
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnItem { span });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_bare_fn_safety(&self, span: Span, safety: Safety) {
|
||||
if matches!(safety, Safety::Safe(_)) {
|
||||
self.dcx().emit_err(errors::InvalidSafetyOnBareFn { span });
|
||||
}
|
||||
}
|
||||
|
||||
@ -623,6 +652,7 @@ impl<'a> AstValidator<'a> {
|
||||
(Some(FnCtxt::Foreign), _) => return,
|
||||
(Some(FnCtxt::Free), Some(header)) => match header.ext {
|
||||
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _)
|
||||
| Extern::Explicit(StrLit { symbol_unescaped: sym::C_dash_unwind, .. }, _)
|
||||
| Extern::Implicit(_)
|
||||
if matches!(header.safety, Safety::Unsafe(_)) =>
|
||||
{
|
||||
@ -746,6 +776,7 @@ impl<'a> AstValidator<'a> {
|
||||
fn visit_ty_common(&mut self, ty: &'a Ty) {
|
||||
match &ty.kind {
|
||||
TyKind::BareFn(bfty) => {
|
||||
self.check_bare_fn_safety(bfty.decl_span, bfty.safety);
|
||||
self.check_fn_decl(&bfty.decl, SelfSemantic::No);
|
||||
Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
|
||||
self.dcx().emit_err(errors::PatternFnPointer { span });
|
||||
@ -883,7 +914,7 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara
|
||||
|
||||
impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
fn visit_attribute(&mut self, attr: &Attribute) {
|
||||
validate_attr::check_attr(&self.session.psess, attr);
|
||||
validate_attr::check_attr(&self.features, &self.session.psess, attr);
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'a Ty) {
|
||||
@ -1072,7 +1103,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
}
|
||||
}
|
||||
} else if let &Safety::Unsafe(span) = safety {
|
||||
this.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" });
|
||||
let mut diag = this
|
||||
.dcx()
|
||||
.create_err(errors::UnsafeItem { span, kind: "extern block" });
|
||||
rustc_session::parse::add_feature_diagnostics(
|
||||
&mut diag,
|
||||
self.session,
|
||||
sym::unsafe_extern_blocks,
|
||||
);
|
||||
diag.emit();
|
||||
}
|
||||
|
||||
if abi.is_none() {
|
||||
@ -1174,11 +1213,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
});
|
||||
}
|
||||
}
|
||||
ItemKind::Static(box StaticItem { expr: None, .. }) => {
|
||||
self.dcx().emit_err(errors::StaticWithoutBody {
|
||||
span: item.span,
|
||||
replace_span: self.ending_semi_or_hi(item.span),
|
||||
});
|
||||
ItemKind::Static(box StaticItem { expr, safety, .. }) => {
|
||||
self.check_item_safety(item.span, *safety);
|
||||
|
||||
if expr.is_none() {
|
||||
self.dcx().emit_err(errors::StaticWithoutBody {
|
||||
span: item.span,
|
||||
replace_span: self.ending_semi_or_hi(item.span),
|
||||
});
|
||||
}
|
||||
}
|
||||
ItemKind::TyAlias(
|
||||
ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. },
|
||||
@ -1212,7 +1255,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
||||
match &fi.kind {
|
||||
ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
|
||||
self.check_foreign_item_safety(fi.span, sig.header.safety);
|
||||
self.check_defaultness(fi.span, *defaultness);
|
||||
self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
|
||||
self.check_foreign_fn_headerless(sig.header);
|
||||
@ -1232,8 +1274,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
self.check_foreign_ty_genericless(generics, where_clauses);
|
||||
self.check_foreign_item_ascii_only(fi.ident);
|
||||
}
|
||||
ForeignItemKind::Static(box StaticForeignItem { expr, safety, .. }) => {
|
||||
self.check_foreign_item_safety(fi.span, *safety);
|
||||
ForeignItemKind::Static(box StaticItem { expr, safety, .. }) => {
|
||||
self.check_item_safety(fi.span, *safety);
|
||||
self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span));
|
||||
self.check_foreign_item_ascii_only(fi.ident);
|
||||
}
|
||||
@ -1270,6 +1312,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
self.with_impl_trait(None, |this| this.visit_ty(ty));
|
||||
}
|
||||
}
|
||||
GenericArgs::ParenthesizedElided(_span) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1426,7 +1469,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
span: args.span,
|
||||
});
|
||||
}
|
||||
None => {}
|
||||
Some(ast::GenericArgs::ParenthesizedElided(_)) | None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1453,6 +1496,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
};
|
||||
self.check_fn_decl(fk.decl(), self_semantic);
|
||||
|
||||
if let Some(&FnHeader { safety, .. }) = fk.header() {
|
||||
self.check_item_safety(span, safety);
|
||||
}
|
||||
|
||||
self.check_c_variadic_type(fk);
|
||||
|
||||
// Functions cannot both be `const async` or `const gen`
|
||||
@ -1670,7 +1717,9 @@ fn deny_equality_constraints(
|
||||
// Add `<Bar = RhsTy>` to `Foo`.
|
||||
match &mut assoc_path.segments[len].args {
|
||||
Some(args) => match args.deref_mut() {
|
||||
GenericArgs::Parenthesized(_) => continue,
|
||||
GenericArgs::Parenthesized(_) | GenericArgs::ParenthesizedElided(..) => {
|
||||
continue;
|
||||
}
|
||||
GenericArgs::AngleBracketed(args) => {
|
||||
args.args.push(arg);
|
||||
}
|
||||
|
@ -221,8 +221,22 @@ pub enum ExternBlockSuggestion {
|
||||
pub struct InvalidSafetyOnExtern {
|
||||
#[primary_span]
|
||||
pub item_span: Span,
|
||||
#[suggestion(code = "", applicability = "maybe-incorrect")]
|
||||
pub block: Span,
|
||||
#[suggestion(code = "unsafe ", applicability = "machine-applicable", style = "verbose")]
|
||||
pub block: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_item_invalid_safety)]
|
||||
pub struct InvalidSafetyOnItem {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_bare_fn_invalid_safety)]
|
||||
pub struct InvalidSafetyOnBareFn {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::{attr, AssocItemConstraint, AssocItemConstraintKind, NodeId};
|
||||
use rustc_ast::{attr, NodeId};
|
||||
use rustc_ast::{token, PatKind};
|
||||
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
|
||||
@ -445,23 +445,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
visit::walk_fn(self, fn_kind)
|
||||
}
|
||||
|
||||
fn visit_assoc_item_constraint(&mut self, constraint: &'a AssocItemConstraint) {
|
||||
if let AssocItemConstraintKind::Bound { .. } = constraint.kind
|
||||
&& let Some(ast::GenericArgs::Parenthesized(args)) = constraint.gen_args.as_ref()
|
||||
&& args.inputs.is_empty()
|
||||
&& let ast::FnRetTy::Default(..) = args.output
|
||||
{
|
||||
gate!(
|
||||
&self,
|
||||
return_type_notation,
|
||||
constraint.span,
|
||||
"return type notation is experimental"
|
||||
);
|
||||
}
|
||||
|
||||
visit::walk_assoc_item_constraint(self, constraint)
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
|
||||
let is_fn = match &i.kind {
|
||||
ast::AssocItemKind::Fn(_) => true,
|
||||
@ -562,6 +545,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||
gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
|
||||
gate_all!(global_registration, "global registration is experimental");
|
||||
gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental");
|
||||
gate_all!(
|
||||
unsafe_extern_blocks,
|
||||
"`unsafe extern {}` blocks and `safe` keyword are experimental"
|
||||
);
|
||||
gate_all!(return_type_notation, "return type notation is experimental");
|
||||
|
||||
if !visitor.features.never_patterns {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
@ -607,10 +595,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||
|
||||
gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
|
||||
gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental");
|
||||
// Despite being a new feature, `where T: Trait<Assoc(): Sized>`, which is RTN syntax now,
|
||||
// used to be gated under associated_type_bounds, which are right above, so RTN needs to
|
||||
// be too.
|
||||
gate_all_legacy_dont_use!(return_type_notation, "return type notation is experimental");
|
||||
gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental");
|
||||
gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable");
|
||||
gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable");
|
||||
|
@ -1060,6 +1060,11 @@ impl<'a> PrintState<'a> for State<'a> {
|
||||
self.word(")");
|
||||
self.print_fn_ret_ty(&data.output);
|
||||
}
|
||||
ast::GenericArgs::ParenthesizedElided(_) => {
|
||||
self.word("(");
|
||||
self.word("..");
|
||||
self.word(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ use ast::{ForLoopKind, MatchKind};
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::util::classify;
|
||||
use rustc_ast::util::literal::escape_byte_str_symbol;
|
||||
use rustc_ast::util::parser::{self, AssocOp, Fixity};
|
||||
use rustc_ast::{self as ast, BlockCheckMode};
|
||||
@ -217,7 +218,7 @@ impl<'a> State<'a> {
|
||||
fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) {
|
||||
let prec = match func.kind {
|
||||
ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
|
||||
_ => parser::PREC_POSTFIX,
|
||||
_ => parser::PREC_UNAMBIGUOUS,
|
||||
};
|
||||
|
||||
// Independent of parenthesization related to precedence, we must
|
||||
@ -257,7 +258,7 @@ impl<'a> State<'a> {
|
||||
// boundaries, `$receiver.method()` can be parsed back as a statement
|
||||
// containing an expression if and only if `$receiver` can be parsed as
|
||||
// a statement containing an expression.
|
||||
self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX, fixup);
|
||||
self.print_expr_maybe_paren(receiver, parser::PREC_UNAMBIGUOUS, fixup);
|
||||
|
||||
self.word(".");
|
||||
self.print_ident(segment.ident);
|
||||
@ -489,7 +490,7 @@ impl<'a> State<'a> {
|
||||
self.space();
|
||||
}
|
||||
MatchKind::Postfix => {
|
||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
|
||||
self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup);
|
||||
self.word_nbsp(".match");
|
||||
}
|
||||
}
|
||||
@ -540,7 +541,7 @@ impl<'a> State<'a> {
|
||||
self.ibox(0);
|
||||
self.print_block_with_attrs(blk, attrs);
|
||||
}
|
||||
ast::ExprKind::Gen(capture_clause, blk, kind) => {
|
||||
ast::ExprKind::Gen(capture_clause, blk, kind, _decl_span) => {
|
||||
self.word_nbsp(kind.modifier());
|
||||
self.print_capture_clause(*capture_clause);
|
||||
// cbox/ibox in analogy to the `ExprKind::Block` arm above
|
||||
@ -549,7 +550,7 @@ impl<'a> State<'a> {
|
||||
self.print_block_with_attrs(blk, attrs);
|
||||
}
|
||||
ast::ExprKind::Await(expr, _) => {
|
||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
|
||||
self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup);
|
||||
self.word(".await");
|
||||
}
|
||||
ast::ExprKind::Assign(lhs, rhs, _) => {
|
||||
@ -568,14 +569,14 @@ impl<'a> State<'a> {
|
||||
self.print_expr_maybe_paren(rhs, prec, fixup.subsequent_subexpression());
|
||||
}
|
||||
ast::ExprKind::Field(expr, ident) => {
|
||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
|
||||
self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup);
|
||||
self.word(".");
|
||||
self.print_ident(*ident);
|
||||
}
|
||||
ast::ExprKind::Index(expr, index, _) => {
|
||||
self.print_expr_maybe_paren(
|
||||
expr,
|
||||
parser::PREC_POSTFIX,
|
||||
parser::PREC_UNAMBIGUOUS,
|
||||
fixup.leftmost_subexpression(),
|
||||
);
|
||||
self.word("[");
|
||||
@ -610,9 +611,12 @@ impl<'a> State<'a> {
|
||||
}
|
||||
if let Some(expr) = opt_expr {
|
||||
self.space();
|
||||
self.print_expr_maybe_paren(
|
||||
self.print_expr_cond_paren(
|
||||
expr,
|
||||
parser::PREC_JUMP,
|
||||
// Parenthesize if required by precedence, or in the
|
||||
// case of `break 'inner: loop { break 'inner 1 } + 1`
|
||||
expr.precedence().order() < parser::PREC_JUMP
|
||||
|| (opt_label.is_none() && classify::leading_labeled_expr(expr)),
|
||||
fixup.subsequent_subexpression(),
|
||||
);
|
||||
}
|
||||
@ -713,7 +717,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Try(e) => {
|
||||
self.print_expr_maybe_paren(e, parser::PREC_POSTFIX, fixup);
|
||||
self.print_expr_maybe_paren(e, parser::PREC_UNAMBIGUOUS, fixup);
|
||||
self.word("?")
|
||||
}
|
||||
ast::ExprKind::TryBlock(blk) => {
|
||||
|
@ -37,12 +37,7 @@ impl<'a> State<'a> {
|
||||
ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
|
||||
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
|
||||
}
|
||||
ast::ForeignItemKind::Static(box ast::StaticForeignItem {
|
||||
ty,
|
||||
mutability,
|
||||
expr,
|
||||
safety,
|
||||
}) => {
|
||||
ast::ForeignItemKind::Static(box ast::StaticItem { ty, mutability, expr, safety }) => {
|
||||
self.print_safety(*safety);
|
||||
self.print_item_const(
|
||||
ident,
|
||||
|
@ -126,7 +126,7 @@ impl<'tcx> BorrowSet<'tcx> {
|
||||
) -> Self {
|
||||
let mut visitor = GatherBorrows {
|
||||
tcx,
|
||||
body: body,
|
||||
body,
|
||||
location_map: Default::default(),
|
||||
activation_map: Default::default(),
|
||||
local_map: Default::default(),
|
||||
|
@ -6,8 +6,8 @@ use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
|
||||
impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
pub fn dcx(&self) -> DiagCtxtHandle<'tcx> {
|
||||
impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
pub fn dcx(&self) -> DiagCtxtHandle<'infcx> {
|
||||
self.infcx.dcx()
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
place: &str,
|
||||
borrow_place: &str,
|
||||
value_place: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
self.dcx().create_err(crate::session_diagnostics::MoveBorrow {
|
||||
place,
|
||||
span,
|
||||
@ -34,7 +34,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
desc: &str,
|
||||
borrow_span: Span,
|
||||
borrow_desc: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
@ -54,7 +54,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
old_loan_span: Span,
|
||||
old_opt_via: &str,
|
||||
old_load_end_span: Option<Span>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
@ -101,7 +101,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
desc: &str,
|
||||
old_loan_span: Span,
|
||||
old_load_end_span: Option<Span>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
new_loan_span,
|
||||
@ -134,7 +134,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
noun_old: &str,
|
||||
old_opt_via: &str,
|
||||
previous_end_span: Option<Span>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
new_loan_span,
|
||||
@ -166,7 +166,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
old_opt_via: &str,
|
||||
previous_end_span: Option<Span>,
|
||||
second_borrow_desc: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
new_loan_span,
|
||||
@ -198,7 +198,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
kind_old: &str,
|
||||
msg_old: &str,
|
||||
old_load_end_span: Option<Span>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
@ -213,7 +213,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
via(msg_old),
|
||||
);
|
||||
|
||||
if msg_new == "" {
|
||||
if msg_new.is_empty() {
|
||||
// If `msg_new` is empty, then this isn't a borrow of a union field.
|
||||
err.span_label(span, format!("{kind_new} borrow occurs here"));
|
||||
err.span_label(old_span, format!("{kind_old} borrow occurs here"));
|
||||
@ -239,7 +239,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
span: Span,
|
||||
borrow_span: Span,
|
||||
desc: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
@ -256,12 +256,12 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
span: Span,
|
||||
desc: &str,
|
||||
is_arg: bool,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" };
|
||||
struct_span_code_err!(self.dcx(), span, E0384, "cannot assign {} {}", msg, desc)
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_assign(&self, span: Span, desc: &str) -> Diag<'tcx> {
|
||||
pub(crate) fn cannot_assign(&self, span: Span, desc: &str) -> Diag<'infcx> {
|
||||
struct_span_code_err!(self.dcx(), span, E0594, "cannot assign to {}", desc)
|
||||
}
|
||||
|
||||
@ -269,7 +269,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&self,
|
||||
move_from_span: Span,
|
||||
move_from_desc: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
move_from_span,
|
||||
@ -287,7 +287,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
move_from_span: Span,
|
||||
ty: Ty<'_>,
|
||||
is_index: Option<bool>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let type_name = match (&ty.kind(), is_index) {
|
||||
(&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
|
||||
(&ty::Slice(_), _) => "slice",
|
||||
@ -308,7 +308,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&self,
|
||||
move_from_span: Span,
|
||||
container_ty: Ty<'_>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
move_from_span,
|
||||
@ -325,7 +325,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
verb: &str,
|
||||
optional_adverb_for_moved: &str,
|
||||
moved_path: Option<String>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let moved_path = moved_path.map(|mp| format!(": `{mp}`")).unwrap_or_default();
|
||||
|
||||
struct_span_code_err!(
|
||||
@ -344,7 +344,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
span: Span,
|
||||
path: &str,
|
||||
reason: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
@ -362,7 +362,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
immutable_place: &str,
|
||||
immutable_section: &str,
|
||||
action: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
mutate_span,
|
||||
@ -380,7 +380,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&self,
|
||||
span: Span,
|
||||
yield_span: Span,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
@ -391,7 +391,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
.with_span_label(yield_span, "possible yield occurs here")
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'tcx> {
|
||||
pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
borrow_span,
|
||||
@ -400,7 +400,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn path_does_not_live_long_enough(&self, span: Span, path: &str) -> Diag<'tcx> {
|
||||
pub(crate) fn path_does_not_live_long_enough(&self, span: Span, path: &str) -> Diag<'infcx> {
|
||||
struct_span_code_err!(self.dcx(), span, E0597, "{} does not live long enough", path,)
|
||||
}
|
||||
|
||||
@ -410,7 +410,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
return_kind: &str,
|
||||
reference_desc: &str,
|
||||
path_desc: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
@ -433,7 +433,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
borrowed_path: &str,
|
||||
capture_span: Span,
|
||||
scope: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
closure_span,
|
||||
@ -445,7 +445,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
.with_span_label(closure_span, format!("may outlive borrowed value {borrowed_path}"))
|
||||
}
|
||||
|
||||
pub(crate) fn thread_local_value_does_not_live_long_enough(&self, span: Span) -> Diag<'tcx> {
|
||||
pub(crate) fn thread_local_value_does_not_live_long_enough(&self, span: Span) -> Diag<'infcx> {
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
@ -454,7 +454,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn temporary_value_borrowed_for_too_long(&self, span: Span) -> Diag<'tcx> {
|
||||
pub(crate) fn temporary_value_borrowed_for_too_long(&self, span: Span) -> Diag<'infcx> {
|
||||
struct_span_code_err!(self.dcx(), span, E0716, "temporary value dropped while borrowed",)
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
use crate::region_infer::{ConstraintSccs, RegionDefinition, RegionTracker};
|
||||
use crate::type_check::Locations;
|
||||
use crate::universal_regions::UniversalRegions;
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt, VarianceDiagInfo};
|
||||
@ -48,6 +50,110 @@ impl<'tcx> OutlivesConstraintSet<'tcx> {
|
||||
) -> &IndexSlice<OutlivesConstraintIndex, OutlivesConstraint<'tcx>> {
|
||||
&self.outlives
|
||||
}
|
||||
|
||||
/// Computes cycles (SCCs) in the graph of regions. In particular,
|
||||
/// find all regions R1, R2 such that R1: R2 and R2: R1 and group
|
||||
/// them into an SCC, and find the relationships between SCCs.
|
||||
pub(crate) fn compute_sccs(
|
||||
&self,
|
||||
static_region: RegionVid,
|
||||
definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
|
||||
) -> ConstraintSccs {
|
||||
let constraint_graph = self.graph(definitions.len());
|
||||
let region_graph = &constraint_graph.region_graph(self, static_region);
|
||||
ConstraintSccs::new_with_annotation(®ion_graph, |r| {
|
||||
RegionTracker::new(r, &definitions[r])
|
||||
})
|
||||
}
|
||||
|
||||
/// This method handles Universe errors by rewriting the constraint
|
||||
/// graph. For each strongly connected component in the constraint
|
||||
/// graph such that there is a series of constraints
|
||||
/// A: B: C: ... : X where
|
||||
/// A's universe is smaller than X's and A is a placeholder,
|
||||
/// add a constraint that A: 'static. This is a safe upper bound
|
||||
/// in the face of borrow checker/trait solver limitations that will
|
||||
/// eventually go away.
|
||||
///
|
||||
/// For a more precise definition, see the documentation for
|
||||
/// [`RegionTracker::has_incompatible_universes()`].
|
||||
///
|
||||
/// This edge case used to be handled during constraint propagation
|
||||
/// by iterating over the strongly connected components in the constraint
|
||||
/// graph while maintaining a set of bookkeeping mappings similar
|
||||
/// to what is stored in `RegionTracker` and manually adding 'sttaic as
|
||||
/// needed.
|
||||
///
|
||||
/// It was rewritten as part of the Polonius project with the goal of moving
|
||||
/// higher-kindedness concerns out of the path of the borrow checker,
|
||||
/// for two reasons:
|
||||
///
|
||||
/// 1. Implementing Polonius is difficult enough without also
|
||||
/// handling them.
|
||||
/// 2. The long-term goal is to handle higher-kinded concerns
|
||||
/// in the trait solver, where they belong. This avoids
|
||||
/// logic duplication and allows future trait solvers
|
||||
/// to compute better bounds than for example our
|
||||
/// "must outlive 'static" here.
|
||||
///
|
||||
/// This code is a stop-gap measure in preparation for the future trait solver.
|
||||
///
|
||||
/// Every constraint added by this method is an
|
||||
/// internal `IllegalUniverse` constraint.
|
||||
#[instrument(skip(self, universal_regions, definitions))]
|
||||
pub(crate) fn add_outlives_static(
|
||||
&mut self,
|
||||
universal_regions: &UniversalRegions<'tcx>,
|
||||
definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
|
||||
) -> ConstraintSccs {
|
||||
let fr_static = universal_regions.fr_static;
|
||||
let sccs = self.compute_sccs(fr_static, definitions);
|
||||
|
||||
// Changed to `true` if we added any constraints to `self` and need to
|
||||
// recompute SCCs.
|
||||
let mut added_constraints = false;
|
||||
|
||||
for scc in sccs.all_sccs() {
|
||||
// No point in adding 'static: 'static!
|
||||
// This micro-optimisation makes somewhat sense
|
||||
// because static outlives *everything*.
|
||||
if scc == sccs.scc(fr_static) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let annotation = sccs.annotation(scc);
|
||||
|
||||
// If this SCC participates in a universe violation,
|
||||
// e.g. if it reaches a region with a universe smaller than
|
||||
// the largest region reached, add a requirement that it must
|
||||
// outlive `'static`.
|
||||
if annotation.has_incompatible_universes() {
|
||||
// Optimisation opportunity: this will add more constraints than
|
||||
// needed for correctness, since an SCC upstream of another with
|
||||
// a universe violation will "infect" its downstream SCCs to also
|
||||
// outlive static.
|
||||
added_constraints = true;
|
||||
let scc_representative_outlives_static = OutlivesConstraint {
|
||||
sup: annotation.representative,
|
||||
sub: fr_static,
|
||||
category: ConstraintCategory::IllegalUniverse,
|
||||
locations: Locations::All(rustc_span::DUMMY_SP),
|
||||
span: rustc_span::DUMMY_SP,
|
||||
variance_info: VarianceDiagInfo::None,
|
||||
from_closure: false,
|
||||
};
|
||||
self.push(scc_representative_outlives_static);
|
||||
}
|
||||
}
|
||||
|
||||
if added_constraints {
|
||||
// We changed the constraint set and so must recompute SCCs.
|
||||
self.compute_sccs(fr_static, definitions)
|
||||
} else {
|
||||
// If we didn't add any back-edges; no more work needs doing
|
||||
sccs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Index<OutlivesConstraintIndex> for OutlivesConstraintSet<'tcx> {
|
||||
|
@ -15,24 +15,24 @@ use std::fmt;
|
||||
use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext};
|
||||
|
||||
/// The results of the dataflow analyses used by the borrow checker.
|
||||
pub struct BorrowckResults<'mir, 'tcx> {
|
||||
pub(crate) borrows: Results<'tcx, Borrows<'mir, 'tcx>>,
|
||||
pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
|
||||
pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
|
||||
pub struct BorrowckResults<'a, 'mir, 'tcx> {
|
||||
pub(crate) borrows: Results<'tcx, Borrows<'a, 'mir, 'tcx>>,
|
||||
pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>,
|
||||
pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'mir, 'tcx>>,
|
||||
}
|
||||
|
||||
/// The transient state of the dataflow analyses used by the borrow checker.
|
||||
#[derive(Debug)]
|
||||
pub struct BorrowckFlowState<'mir, 'tcx> {
|
||||
pub(crate) borrows: <Borrows<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) uninits: <MaybeUninitializedPlaces<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) ever_inits: <EverInitializedPlaces<'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub struct BorrowckFlowState<'a, 'mir, 'tcx> {
|
||||
pub(crate) borrows: <Borrows<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
pub(crate) ever_inits: <EverInitializedPlaces<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'mir, 'tcx> {
|
||||
impl<'a, 'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'mir, 'tcx> {
|
||||
// All three analyses are forward, but we have to use just one here.
|
||||
type Direction = <Borrows<'mir, 'tcx> as AnalysisDomain<'tcx>>::Direction;
|
||||
type FlowState = BorrowckFlowState<'mir, 'tcx>;
|
||||
type Direction = <Borrows<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Direction;
|
||||
type FlowState = BorrowckFlowState<'a, 'mir, 'tcx>;
|
||||
|
||||
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
|
||||
BorrowckFlowState {
|
||||
@ -43,9 +43,9 @@ impl<'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'mir, 'tcx> {
|
||||
}
|
||||
|
||||
fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) {
|
||||
state.borrows.clone_from(&self.borrows.entry_set_for_block(block));
|
||||
state.uninits.clone_from(&self.uninits.entry_set_for_block(block));
|
||||
state.ever_inits.clone_from(&self.ever_inits.entry_set_for_block(block));
|
||||
state.borrows.clone_from(self.borrows.entry_set_for_block(block));
|
||||
state.uninits.clone_from(self.uninits.entry_set_for_block(block));
|
||||
state.ever_inits.clone_from(self.ever_inits.entry_set_for_block(block));
|
||||
}
|
||||
|
||||
fn reconstruct_before_statement_effect(
|
||||
@ -106,11 +106,11 @@ rustc_index::newtype_index! {
|
||||
/// `BorrowIndex`, and maps each such index to a `BorrowData`
|
||||
/// describing the borrow. These indexes are used for representing the
|
||||
/// borrows in compact bitvectors.
|
||||
pub struct Borrows<'mir, 'tcx> {
|
||||
pub struct Borrows<'a, 'mir, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'mir Body<'tcx>,
|
||||
|
||||
borrow_set: &'mir BorrowSet<'tcx>,
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
|
||||
}
|
||||
|
||||
@ -389,12 +389,12 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> Borrows<'mir, 'tcx> {
|
||||
impl<'a, 'mir, 'tcx> Borrows<'a, 'mir, 'tcx> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'mir Body<'tcx>,
|
||||
regioncx: &'mir RegionInferenceContext<'tcx>,
|
||||
borrow_set: &'mir BorrowSet<'tcx>,
|
||||
regioncx: &RegionInferenceContext<'tcx>,
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
) -> Self {
|
||||
let mut borrows_out_of_scope_at_location =
|
||||
calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set);
|
||||
@ -494,7 +494,7 @@ impl<'mir, 'tcx> Borrows<'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
|
||||
impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, '_, 'tcx> {
|
||||
type Domain = BitSet<BorrowIndex>;
|
||||
|
||||
const NAME: &'static str = "borrows";
|
||||
@ -517,7 +517,7 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
|
||||
/// region stops containing the CFG points reachable from the issuing location.
|
||||
/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
|
||||
/// `a.b.c` when `a` is overwritten.
|
||||
impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, '_, 'tcx> {
|
||||
type Idx = BorrowIndex;
|
||||
|
||||
fn domain_size(&self, _: &mir::Body<'tcx>) -> usize {
|
||||
@ -617,8 +617,8 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl DebugWithContext<Borrows<'_, '_>> for BorrowIndex {
|
||||
fn fmt_with(&self, ctxt: &Borrows<'_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl DebugWithContext<Borrows<'_, '_, '_>> for BorrowIndex {
|
||||
fn fmt_with(&self, ctxt: &Borrows<'_, '_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", ctxt.location(*self))
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ impl<'tcx> UniverseInfo<'tcx> {
|
||||
|
||||
pub(crate) fn report_error(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
placeholder: ty::PlaceholderRegion,
|
||||
error_element: RegionElement,
|
||||
cause: ObligationCause<'tcx>,
|
||||
@ -149,18 +149,18 @@ trait TypeOpInfo<'tcx> {
|
||||
|
||||
fn base_universe(&self) -> ty::UniverseIndex;
|
||||
|
||||
fn nice_error(
|
||||
fn nice_error<'infcx>(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>>;
|
||||
) -> Option<Diag<'infcx>>;
|
||||
|
||||
#[instrument(level = "debug", skip(self, mbcx))]
|
||||
fn report_error(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
placeholder: ty::PlaceholderRegion,
|
||||
error_element: RegionElement,
|
||||
cause: ObligationCause<'tcx>,
|
||||
@ -231,18 +231,25 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
||||
self.base_universe
|
||||
}
|
||||
|
||||
fn nice_error(
|
||||
fn nice_error<'infcx>(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'infcx>> {
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
type_op_prove_predicate_with_cause(&ocx, key, cause);
|
||||
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
|
||||
let diag = try_extract_error_from_fulfill_cx(
|
||||
&ocx,
|
||||
mbcx.mir_def_id(),
|
||||
placeholder_region,
|
||||
error_region,
|
||||
)?
|
||||
.with_dcx(mbcx.dcx());
|
||||
Some(diag)
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,13 +275,13 @@ where
|
||||
self.base_universe
|
||||
}
|
||||
|
||||
fn nice_error(
|
||||
fn nice_error<'infcx>(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'infcx>> {
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
@ -288,7 +295,14 @@ where
|
||||
let (param_env, value) = key.into_parts();
|
||||
let _ = ocx.normalize(&cause, param_env, value.value);
|
||||
|
||||
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
|
||||
let diag = try_extract_error_from_fulfill_cx(
|
||||
&ocx,
|
||||
mbcx.mir_def_id(),
|
||||
placeholder_region,
|
||||
error_region,
|
||||
)?
|
||||
.with_dcx(mbcx.dcx());
|
||||
Some(diag)
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,18 +322,25 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
||||
self.base_universe
|
||||
}
|
||||
|
||||
fn nice_error(
|
||||
fn nice_error<'infcx>(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'infcx>> {
|
||||
let (infcx, key, _) =
|
||||
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
|
||||
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
|
||||
let diag = try_extract_error_from_fulfill_cx(
|
||||
&ocx,
|
||||
mbcx.mir_def_id(),
|
||||
placeholder_region,
|
||||
error_region,
|
||||
)?
|
||||
.with_dcx(mbcx.dcx());
|
||||
Some(diag)
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,13 +355,13 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
||||
self.base_universe.unwrap()
|
||||
}
|
||||
|
||||
fn nice_error(
|
||||
fn nice_error<'infcx>(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
|
||||
_cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'infcx>> {
|
||||
try_extract_error_from_region_constraints(
|
||||
mbcx.infcx,
|
||||
mbcx.mir_def_id(),
|
||||
@ -358,12 +379,12 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
||||
}
|
||||
|
||||
#[instrument(skip(ocx), level = "debug")]
|
||||
fn try_extract_error_from_fulfill_cx<'tcx>(
|
||||
ocx: &ObligationCtxt<'_, 'tcx>,
|
||||
fn try_extract_error_from_fulfill_cx<'a, 'tcx>(
|
||||
ocx: &ObligationCtxt<'a, 'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'a>> {
|
||||
// We generally shouldn't have errors here because the query was
|
||||
// already run, but there's no point using `span_delayed_bug`
|
||||
// when we're going to emit an error here anyway.
|
||||
@ -381,15 +402,15 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))]
|
||||
fn try_extract_error_from_region_constraints<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
fn try_extract_error_from_region_constraints<'a, 'tcx>(
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
region_constraints: &RegionConstraintData<'tcx>,
|
||||
mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
|
||||
mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Option<Diag<'a>> {
|
||||
let placeholder_universe = match placeholder_region.kind() {
|
||||
ty::RePlaceholder(p) => p.universe,
|
||||
ty::ReVar(vid) => universe_of_region(vid),
|
||||
|
@ -34,11 +34,12 @@ use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
|
||||
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
|
||||
use std::iter;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use crate::borrow_set::TwoPhaseActivation;
|
||||
use crate::borrowck_errors;
|
||||
@ -73,7 +74,7 @@ enum StorageDeadOrDrop<'tcx> {
|
||||
Destructor(Ty<'tcx>),
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
pub(crate) fn report_use_of_moved_or_uninitialized(
|
||||
&mut self,
|
||||
location: Location,
|
||||
@ -341,7 +342,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn suggest_ref_or_clone(
|
||||
&self,
|
||||
mpi: MovePathIndex,
|
||||
err: &mut Diag<'tcx>,
|
||||
err: &mut Diag<'infcx>,
|
||||
in_pattern: &mut bool,
|
||||
move_spans: UseSpans<'tcx>,
|
||||
) {
|
||||
@ -517,7 +518,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
desired_action: InitializationRequiringAction,
|
||||
span: Span,
|
||||
use_spans: UseSpans<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
// We need all statements in the body where the binding was assigned to later find all
|
||||
// the branching code paths where the binding *wasn't* assigned to.
|
||||
let inits = &self.move_data.init_path_map[mpi];
|
||||
@ -784,20 +785,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// binding declaration within every scope we inspect.
|
||||
struct Finder {
|
||||
hir_id: hir::HirId,
|
||||
found: bool,
|
||||
}
|
||||
impl<'hir> Visitor<'hir> for Finder {
|
||||
fn visit_pat(&mut self, pat: &'hir hir::Pat<'hir>) {
|
||||
type Result = ControlFlow<()>;
|
||||
fn visit_pat(&mut self, pat: &'hir hir::Pat<'hir>) -> Self::Result {
|
||||
if pat.hir_id == self.hir_id {
|
||||
self.found = true;
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
hir::intravisit::walk_pat(self, pat);
|
||||
hir::intravisit::walk_pat(self, pat)
|
||||
}
|
||||
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
|
||||
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) -> Self::Result {
|
||||
if ex.hir_id == self.hir_id {
|
||||
self.found = true;
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
hir::intravisit::walk_expr(self, ex);
|
||||
hir::intravisit::walk_expr(self, ex)
|
||||
}
|
||||
}
|
||||
// The immediate HIR parent of the moved expression. We'll look for it to be a call.
|
||||
@ -822,9 +823,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
_ => continue,
|
||||
};
|
||||
if let Some(&hir_id) = local_hir_id {
|
||||
let mut finder = Finder { hir_id, found: false };
|
||||
finder.visit_expr(e);
|
||||
if finder.found {
|
||||
if (Finder { hir_id }).visit_expr(e).is_break() {
|
||||
// The current scope includes the declaration of the binding we're accessing, we
|
||||
// can't look up any further for loops.
|
||||
break;
|
||||
@ -839,9 +838,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::If(cond, ..), ..
|
||||
}) => {
|
||||
let mut finder = Finder { hir_id: expr.hir_id, found: false };
|
||||
finder.visit_expr(cond);
|
||||
if finder.found {
|
||||
if (Finder { hir_id: expr.hir_id }).visit_expr(cond).is_break() {
|
||||
// The expression where the move error happened is in a `while let`
|
||||
// condition Don't suggest clone as it will likely end in an
|
||||
// infinite loop.
|
||||
@ -1288,7 +1285,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||
let suggestion =
|
||||
let mut suggestion =
|
||||
if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
format!(": {symbol}.clone()")
|
||||
} else {
|
||||
@ -1296,6 +1293,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
};
|
||||
let mut sugg = Vec::with_capacity(2);
|
||||
let mut inner_expr = expr;
|
||||
let mut is_raw_ptr = false;
|
||||
let typeck_result = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
// Remove uses of `&` and `*` when suggesting `.clone()`.
|
||||
while let hir::ExprKind::AddrOf(.., inner) | hir::ExprKind::Unary(hir::UnOp::Deref, inner) =
|
||||
&inner_expr.kind
|
||||
@ -1306,14 +1305,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
inner_expr = inner;
|
||||
if let Some(inner_type) = typeck_result.node_type_opt(inner.hir_id) {
|
||||
if matches!(inner_type.kind(), ty::RawPtr(..)) {
|
||||
is_raw_ptr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if inner_expr.span.lo() != expr.span.lo() {
|
||||
// Cloning the raw pointer doesn't make sense in some cases and would cause a type mismatch error. (see #126863)
|
||||
if inner_expr.span.lo() != expr.span.lo() && !is_raw_ptr {
|
||||
// Remove "(*" or "(&"
|
||||
sugg.push((expr.span.with_hi(inner_expr.span.lo()), String::new()));
|
||||
}
|
||||
// Check whether `expr` is surrounded by parentheses or not.
|
||||
let span = if inner_expr.span.hi() != expr.span.hi() {
|
||||
// Account for `(*x)` to suggest `x.clone()`.
|
||||
expr.span.with_lo(inner_expr.span.hi())
|
||||
if is_raw_ptr {
|
||||
expr.span.shrink_to_hi()
|
||||
} else {
|
||||
// Remove the close parenthesis ")"
|
||||
expr.span.with_lo(inner_expr.span.hi())
|
||||
}
|
||||
} else {
|
||||
if is_raw_ptr {
|
||||
sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
|
||||
suggestion = ").clone()".to_string();
|
||||
}
|
||||
expr.span.shrink_to_hi()
|
||||
};
|
||||
sugg.push((span, suggestion));
|
||||
@ -1441,7 +1458,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
location: Location,
|
||||
(place, _span): (Place<'tcx>, Span),
|
||||
borrow: &BorrowData<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let borrow_spans = self.retrieve_borrow_spans(borrow);
|
||||
let borrow_span = borrow_spans.args_or_use();
|
||||
|
||||
@ -1491,7 +1508,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
(place, span): (Place<'tcx>, Span),
|
||||
gen_borrow_kind: BorrowKind,
|
||||
issued_borrow: &BorrowData<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let issued_spans = self.retrieve_borrow_spans(issued_borrow);
|
||||
let issued_span = issued_spans.args_or_use();
|
||||
|
||||
@ -1782,7 +1799,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
err
|
||||
}
|
||||
|
||||
fn suggest_copy_for_type_in_cloned_ref(&self, err: &mut Diag<'tcx>, place: Place<'tcx>) {
|
||||
fn suggest_copy_for_type_in_cloned_ref(&self, err: &mut Diag<'infcx>, place: Place<'tcx>) {
|
||||
let tcx = self.infcx.tcx;
|
||||
let hir = tcx.hir();
|
||||
let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
|
||||
@ -1817,7 +1834,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
pub struct Holds<'tcx> {
|
||||
ty: Ty<'tcx>,
|
||||
holds: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Holds<'tcx> {
|
||||
@ -1825,7 +1841,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
|
||||
if t == self.ty {
|
||||
self.holds = true;
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
@ -1843,9 +1859,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&& rcvr_ty == ty
|
||||
&& let ty::Ref(_, inner, _) = rcvr_ty.kind()
|
||||
&& let inner = inner.peel_refs()
|
||||
&& let mut v = (Holds { ty: inner, holds: false })
|
||||
&& let _ = v.visit_ty(local_ty)
|
||||
&& v.holds
|
||||
&& (Holds { ty: inner }).visit_ty(local_ty).is_break()
|
||||
&& let None = self.infcx.type_implements_trait_shallow(clone, inner, self.param_env)
|
||||
{
|
||||
err.span_label(
|
||||
@ -2841,7 +2855,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
drop_span: Span,
|
||||
borrow_spans: UseSpans<'tcx>,
|
||||
explanation: BorrowExplanation<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
debug!(
|
||||
"report_local_value_does_not_live_long_enough(\
|
||||
{:?}, {:?}, {:?}, {:?}, {:?}\
|
||||
@ -3016,7 +3030,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&self,
|
||||
drop_span: Span,
|
||||
borrow_span: Span,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
debug!(
|
||||
"report_thread_local_value_does_not_live_long_enough(\
|
||||
{:?}, {:?}\
|
||||
@ -3041,7 +3055,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
borrow_spans: UseSpans<'tcx>,
|
||||
proper_span: Span,
|
||||
explanation: BorrowExplanation<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
|
||||
explanation
|
||||
{
|
||||
@ -3206,7 +3220,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
return_span: Span,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
opt_place_desc: Option<&String>,
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'infcx>> {
|
||||
let return_kind = match category {
|
||||
ConstraintCategory::Return(_) => "return",
|
||||
ConstraintCategory::Yield => "yield",
|
||||
@ -3299,7 +3313,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
constraint_span: Span,
|
||||
captured_var: &str,
|
||||
scope: &str,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let args_span = use_span.args_or_use();
|
||||
|
||||
@ -3411,7 +3425,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
upvar_span: Span,
|
||||
upvar_name: Symbol,
|
||||
escape_span: Span,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id());
|
||||
@ -3713,7 +3727,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
if tcx.is_diagnostic_item(sym::deref_method, method_did) {
|
||||
let deref_target =
|
||||
tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
|
||||
Instance::resolve(tcx, self.param_env, deref_target, method_args)
|
||||
Instance::try_resolve(tcx, self.param_env, deref_target, method_args)
|
||||
.transpose()
|
||||
});
|
||||
if let Some(Ok(instance)) = deref_target {
|
||||
@ -3737,13 +3751,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
assigned_span: Span,
|
||||
err_place: Place<'tcx>,
|
||||
) {
|
||||
let (from_arg, local_decl, local_name) = match err_place.as_local() {
|
||||
Some(local) => (
|
||||
self.body.local_kind(local) == LocalKind::Arg,
|
||||
Some(&self.body.local_decls[local]),
|
||||
self.local_names[local],
|
||||
),
|
||||
None => (false, None, None),
|
||||
let (from_arg, local_decl) = match err_place.as_local() {
|
||||
Some(local) => {
|
||||
(self.body.local_kind(local) == LocalKind::Arg, Some(&self.body.local_decls[local]))
|
||||
}
|
||||
None => (false, None),
|
||||
};
|
||||
|
||||
// If root local is initialized immediately (everything apart from let
|
||||
@ -3775,13 +3787,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
err.span_label(assigned_span, format!("first assignment to {place_description}"));
|
||||
}
|
||||
if let Some(decl) = local_decl
|
||||
&& let Some(name) = local_name
|
||||
&& decl.can_be_made_mutable()
|
||||
{
|
||||
err.span_suggestion(
|
||||
decl.source_info.span,
|
||||
err.span_suggestion_verbose(
|
||||
decl.source_info.span.shrink_to_lo(),
|
||||
"consider making this binding mutable",
|
||||
format!("mut {name}"),
|
||||
"mut ".to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if !from_arg
|
||||
@ -3793,10 +3804,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}))
|
||||
)
|
||||
{
|
||||
err.span_suggestion(
|
||||
decl.source_info.span,
|
||||
err.span_suggestion_verbose(
|
||||
decl.source_info.span.shrink_to_lo(),
|
||||
"to modify the original value, take a borrow instead",
|
||||
format!("ref mut {name}"),
|
||||
"ref mut ".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
@ -4243,7 +4254,11 @@ enum AnnotatedBorrowFnSignature<'tcx> {
|
||||
impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
|
||||
/// Annotate the provided diagnostic with information about borrow from the fn signature that
|
||||
/// helps explain.
|
||||
pub(crate) fn emit(&self, cx: &MirBorrowckCtxt<'_, 'tcx>, diag: &mut Diag<'_>) -> String {
|
||||
pub(crate) fn emit(
|
||||
&self,
|
||||
cx: &MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
diag: &mut Diag<'_>,
|
||||
) -> String {
|
||||
match self {
|
||||
&AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => {
|
||||
diag.span_label(
|
||||
@ -4304,15 +4319,14 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
|
||||
}
|
||||
|
||||
/// Detect whether one of the provided spans is a statement nested within the top-most visited expr
|
||||
struct ReferencedStatementsVisitor<'a>(&'a [Span], bool);
|
||||
struct ReferencedStatementsVisitor<'a>(&'a [Span]);
|
||||
|
||||
impl<'a, 'v> Visitor<'v> for ReferencedStatementsVisitor<'a> {
|
||||
fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
|
||||
impl<'v> Visitor<'v> for ReferencedStatementsVisitor<'_> {
|
||||
type Result = ControlFlow<()>;
|
||||
fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) -> Self::Result {
|
||||
match s.kind {
|
||||
hir::StmtKind::Semi(expr) if self.0.contains(&expr.span) => {
|
||||
self.1 = true;
|
||||
}
|
||||
_ => {}
|
||||
hir::StmtKind::Semi(expr) if self.0.contains(&expr.span) => ControlFlow::Break(()),
|
||||
_ => ControlFlow::Continue(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4354,9 +4368,7 @@ impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
|
||||
hir::ExprKind::If(cond, body, None) => {
|
||||
// `if` expressions with no `else` that initialize the binding might be missing an
|
||||
// `else` arm.
|
||||
let mut v = ReferencedStatementsVisitor(self.spans, false);
|
||||
v.visit_expr(body);
|
||||
if v.1 {
|
||||
if ReferencedStatementsVisitor(self.spans).visit_expr(body).is_break() {
|
||||
self.errors.push((
|
||||
cond.span,
|
||||
format!(
|
||||
@ -4373,11 +4385,9 @@ impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
|
||||
hir::ExprKind::If(cond, body, Some(other)) => {
|
||||
// `if` expressions where the binding is only initialized in one of the two arms
|
||||
// might be missing a binding initialization.
|
||||
let mut a = ReferencedStatementsVisitor(self.spans, false);
|
||||
a.visit_expr(body);
|
||||
let mut b = ReferencedStatementsVisitor(self.spans, false);
|
||||
b.visit_expr(other);
|
||||
match (a.1, b.1) {
|
||||
let a = ReferencedStatementsVisitor(self.spans).visit_expr(body).is_break();
|
||||
let b = ReferencedStatementsVisitor(self.spans).visit_expr(other).is_break();
|
||||
match (a, b) {
|
||||
(true, true) | (false, false) => {}
|
||||
(true, false) => {
|
||||
if other.span.is_desugaring(DesugaringKind::WhileLoop) {
|
||||
@ -4416,11 +4426,7 @@ impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
|
||||
// arms might be missing an initialization.
|
||||
let results: Vec<bool> = arms
|
||||
.iter()
|
||||
.map(|arm| {
|
||||
let mut v = ReferencedStatementsVisitor(self.spans, false);
|
||||
v.visit_arm(arm);
|
||||
v.1
|
||||
})
|
||||
.map(|arm| ReferencedStatementsVisitor(self.spans).visit_arm(arm).is_break())
|
||||
.collect();
|
||||
if results.iter().any(|x| *x) && !results.iter().all(|x| *x) {
|
||||
for (arm, seen) in arms.iter().zip(results) {
|
||||
|
@ -17,7 +17,7 @@ use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::{sym, DesugaringKind, Span};
|
||||
use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
|
||||
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
|
||||
|
||||
use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
|
||||
use crate::{
|
||||
@ -389,7 +389,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
fn free_region_constraint_info(
|
||||
&self,
|
||||
borrow_region: RegionVid,
|
||||
|
@ -27,8 +27,8 @@ use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{
|
||||
type_known_to_meet_bound_modulo_regions, FulfillmentErrorCode,
|
||||
};
|
||||
@ -69,7 +69,7 @@ pub(super) struct DescribePlaceOpt {
|
||||
|
||||
pub(super) struct IncludingTupleField(pub(super) bool);
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
/// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure
|
||||
/// is moved after being invoked.
|
||||
///
|
||||
@ -86,7 +86,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&self,
|
||||
location: Location,
|
||||
place: PlaceRef<'tcx>,
|
||||
diag: &mut Diag<'_>,
|
||||
diag: &mut Diag<'infcx>,
|
||||
) -> bool {
|
||||
debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
|
||||
let mut target = place.local_or_deref_local();
|
||||
@ -771,7 +771,7 @@ struct CapturedMessageOpt {
|
||||
maybe_reinitialized_locations_is_empty: bool,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
/// Finds the spans associated to a move or copy of move_place at location.
|
||||
pub(super) fn move_spans(
|
||||
&self,
|
||||
|
@ -9,7 +9,7 @@ use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
|
||||
use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
|
||||
use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
|
||||
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
|
||||
|
||||
use crate::diagnostics::CapturedMessageOpt;
|
||||
use crate::diagnostics::{DescribePlaceOpt, UseSpans};
|
||||
@ -93,7 +93,7 @@ enum GroupedMoveError<'tcx> {
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
pub(crate) fn report_move_errors(&mut self) {
|
||||
let grouped_errors = self.group_move_errors();
|
||||
for error in grouped_errors {
|
||||
@ -291,7 +291,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
self.buffer_error(err);
|
||||
}
|
||||
|
||||
fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'tcx> {
|
||||
fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> {
|
||||
let description = if place.projection.len() == 1 {
|
||||
format!("static item {}", self.describe_any_place(place.as_ref()))
|
||||
} else {
|
||||
@ -428,7 +428,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
deref_target_place: Place<'tcx>,
|
||||
span: Span,
|
||||
use_spans: Option<UseSpans<'tcx>>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
// Inspect the type of the content behind the
|
||||
// borrow to provide feedback about why this
|
||||
@ -639,12 +639,27 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
fn add_borrow_suggestions(&self, err: &mut Diag<'_>, span: Span) {
|
||||
match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
|
||||
Ok(snippet) if snippet.starts_with('*') => {
|
||||
err.span_suggestion_verbose(
|
||||
span.with_hi(span.lo() + BytePos(1)),
|
||||
"consider removing the dereference here",
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
let sp = span.with_lo(span.lo() + BytePos(1));
|
||||
let inner = self.find_expr(sp);
|
||||
let mut is_raw_ptr = false;
|
||||
if let Some(inner) = inner {
|
||||
let typck_result = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
if let Some(inner_type) = typck_result.node_type_opt(inner.hir_id) {
|
||||
if matches!(inner_type.kind(), ty::RawPtr(..)) {
|
||||
is_raw_ptr = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the `inner` is a raw pointer, do not suggest removing the "*", see #126863
|
||||
// FIXME: need to check whether the assigned object can be a raw pointer, see `tests/ui/borrowck/issue-20801.rs`.
|
||||
if !is_raw_ptr {
|
||||
err.span_suggestion_verbose(
|
||||
span.with_hi(span.lo() + BytePos(1)),
|
||||
"consider removing the dereference here",
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
err.span_suggestion_verbose(
|
||||
|
@ -16,9 +16,9 @@ use rustc_middle::{
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::{sym, BytePos, DesugaringKind, Span};
|
||||
use rustc_target::abi::FieldIdx;
|
||||
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
||||
|
||||
use crate::diagnostics::BorrowedContentSource;
|
||||
use crate::util::FindAssignments;
|
||||
@ -30,7 +30,7 @@ pub(crate) enum AccessKind {
|
||||
Mutate,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
pub(crate) fn report_mutability_error(
|
||||
&mut self,
|
||||
access_place: Place<'tcx>,
|
||||
@ -408,10 +408,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
fn_decl.implicit_self,
|
||||
hir::ImplicitSelfKind::RefImm | hir::ImplicitSelfKind::RefMut
|
||||
) {
|
||||
err.span_suggestion(
|
||||
upvar_ident.span,
|
||||
err.span_suggestion_verbose(
|
||||
upvar_ident.span.shrink_to_lo(),
|
||||
"consider changing this to be mutable",
|
||||
format!("mut {}", upvar_ident.name),
|
||||
"mut ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
break;
|
||||
@ -419,10 +419,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err.span_suggestion(
|
||||
upvar_ident.span,
|
||||
err.span_suggestion_verbose(
|
||||
upvar_ident.span.shrink_to_lo(),
|
||||
"consider changing this to be mutable",
|
||||
format!("mut {}", upvar_ident.name),
|
||||
"mut ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
@ -449,8 +449,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
.is_ok_and(|snippet| snippet.starts_with("&mut ")) =>
|
||||
{
|
||||
err.span_label(span, format!("cannot {act}"));
|
||||
err.span_suggestion(
|
||||
span,
|
||||
err.span_suggestion_verbose(
|
||||
span.with_hi(span.lo() + BytePos(5)),
|
||||
"try removing `&mut` here",
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
@ -541,7 +541,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
/// Suggest `map[k] = v` => `map.insert(k, v)` and the like.
|
||||
fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diag<'tcx>, span: Span) {
|
||||
fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diag<'infcx>, span: Span) {
|
||||
let Some(adt) = ty.ty_adt_def() else { return };
|
||||
let did = adt.did();
|
||||
if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did)
|
||||
@ -550,13 +550,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
/// Walks through the HIR, looking for the corresponding span for this error.
|
||||
/// When it finds it, see if it corresponds to assignment operator whose LHS
|
||||
/// is an index expr.
|
||||
struct SuggestIndexOperatorAlternativeVisitor<'a, 'tcx> {
|
||||
struct SuggestIndexOperatorAlternativeVisitor<'a, 'infcx, 'tcx> {
|
||||
assign_span: Span,
|
||||
err: &'a mut Diag<'tcx>,
|
||||
err: &'a mut Diag<'infcx>,
|
||||
ty: Ty<'tcx>,
|
||||
suggested: bool,
|
||||
}
|
||||
impl<'a, 'tcx> Visitor<'tcx> for SuggestIndexOperatorAlternativeVisitor<'a, 'tcx> {
|
||||
impl<'a, 'cx, 'tcx> Visitor<'tcx> for SuggestIndexOperatorAlternativeVisitor<'a, 'cx, 'tcx> {
|
||||
fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
|
||||
hir::intravisit::walk_stmt(self, stmt);
|
||||
let expr = match stmt.kind {
|
||||
@ -755,13 +755,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
|
||||
..
|
||||
}) = node
|
||||
&& let Ok(name) =
|
||||
self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
|
||||
{
|
||||
err.span_suggestion(
|
||||
pat_span,
|
||||
err.multipart_suggestion(
|
||||
"consider changing this to be mutable",
|
||||
format!("&(mut {name})"),
|
||||
vec![
|
||||
(pat_span.until(local_decl.source_info.span), "&(mut ".to_string()),
|
||||
(
|
||||
local_decl.source_info.span.shrink_to_hi().with_hi(pat_span.hi()),
|
||||
")".to_string(),
|
||||
),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return;
|
||||
|
@ -75,7 +75,7 @@ impl OutlivesSuggestionBuilder {
|
||||
/// Returns a name for the region if it is suggestable. See `region_name_is_suggestable`.
|
||||
fn region_vid_to_name(
|
||||
&self,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_>,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
|
||||
region: RegionVid,
|
||||
) -> Option<RegionName> {
|
||||
mbcx.give_region_a_name(region).filter(Self::region_name_is_suggestable)
|
||||
@ -84,7 +84,7 @@ impl OutlivesSuggestionBuilder {
|
||||
/// Compiles a list of all suggestions to be printed in the final big suggestion.
|
||||
fn compile_all_suggestions(
|
||||
&self,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_>,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
|
||||
) -> SmallVec<[SuggestedConstraint; 2]> {
|
||||
let mut suggested = SmallVec::new();
|
||||
|
||||
@ -160,7 +160,7 @@ impl OutlivesSuggestionBuilder {
|
||||
/// Emit an intermediate note on the given `Diag` if the involved regions are suggestable.
|
||||
pub(crate) fn intermediate_suggestion(
|
||||
&mut self,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_>,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
|
||||
errci: &ErrorConstraintInfo<'_>,
|
||||
diag: &mut Diag<'_>,
|
||||
) {
|
||||
@ -179,7 +179,7 @@ impl OutlivesSuggestionBuilder {
|
||||
|
||||
/// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final
|
||||
/// suggestion including all collected constraints.
|
||||
pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_>) {
|
||||
pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_, '_>) {
|
||||
// No constraints to add? Done.
|
||||
if self.constraints_to_add.is_empty() {
|
||||
debug!("No constraints to suggest.");
|
||||
|
@ -10,14 +10,12 @@ use rustc_hir::GenericBound::Trait;
|
||||
use rustc_hir::QPath::Resolved;
|
||||
use rustc_hir::WherePredicate::BoundPredicate;
|
||||
use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate};
|
||||
use rustc_infer::infer::{
|
||||
error_reporting::nice_region_error::{
|
||||
self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
|
||||
HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor,
|
||||
},
|
||||
error_reporting::unexpected_hidden_region_diagnostic,
|
||||
NllRegionVariableOrigin, RelateParamBound,
|
||||
use rustc_infer::infer::error_reporting::nice_region_error::{
|
||||
self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
|
||||
HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor,
|
||||
};
|
||||
use rustc_infer::infer::error_reporting::region::unexpected_hidden_region_diagnostic;
|
||||
use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::hir::place::PlaceBase;
|
||||
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
|
||||
@ -66,7 +64,8 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
|
||||
ConstraintCategory::Predicate(_)
|
||||
| ConstraintCategory::Boring
|
||||
| ConstraintCategory::BoringNoLocation
|
||||
| ConstraintCategory::Internal => "",
|
||||
| ConstraintCategory::Internal
|
||||
| ConstraintCategory::IllegalUniverse => "",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -160,7 +159,7 @@ pub struct ErrorConstraintInfo<'tcx> {
|
||||
pub(super) span: Span,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
/// Converts a region inference variable into a `ty::Region` that
|
||||
/// we can use for error reporting. If `r` is universally bound,
|
||||
/// then we use the name that we have on record for it. If `r` is
|
||||
@ -360,7 +359,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
|
||||
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
||||
let diag = unexpected_hidden_region_diagnostic(
|
||||
self.infcx.tcx,
|
||||
self.infcx,
|
||||
self.mir_def_id(),
|
||||
span,
|
||||
named_ty,
|
||||
@ -589,7 +588,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
errci: &ErrorConstraintInfo<'tcx>,
|
||||
kind: ReturnConstraint,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'infcx> {
|
||||
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
|
||||
|
||||
let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
|
||||
@ -658,7 +657,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
/// | ^^^^^^^^^^ `x` escapes the function body here
|
||||
/// ```
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'tcx> {
|
||||
fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'infcx> {
|
||||
let ErrorConstraintInfo { span, category, .. } = errci;
|
||||
|
||||
let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
|
||||
@ -767,7 +766,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
/// | is returning data with lifetime `'b`
|
||||
/// ```
|
||||
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
|
||||
fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'tcx> {
|
||||
fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'infcx> {
|
||||
let ErrorConstraintInfo {
|
||||
fr,
|
||||
fr_is_local,
|
||||
@ -895,7 +894,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
for alias_ty in alias_tys {
|
||||
if alias_ty.span.desugaring_kind().is_some() {
|
||||
// Skip `async` desugaring `impl Future`.
|
||||
()
|
||||
}
|
||||
if let TyKind::TraitObject(_, lt, _) = alias_ty.kind {
|
||||
if lt.ident.name == kw::Empty {
|
||||
@ -949,7 +947,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Ok(Some(instance)) = ty::Instance::resolve(
|
||||
if let Ok(Some(instance)) = ty::Instance::try_resolve(
|
||||
tcx,
|
||||
self.param_env,
|
||||
*fn_did,
|
||||
@ -1152,7 +1150,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
// Get the arguments for the found method, only specifying that `Self` is the receiver type.
|
||||
let Some(possible_rcvr_ty) = typeck_results.node_type_opt(rcvr.hir_id) else { return };
|
||||
let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
|
||||
if param.index == 0 {
|
||||
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
||||
tcx.lifetimes.re_erased.into()
|
||||
} else if param.index == 0 && param.name == kw::SelfUpper {
|
||||
possible_rcvr_ty.into()
|
||||
} else if param.index == closure_param.index {
|
||||
closure_ty.into()
|
||||
@ -1169,7 +1169,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
Obligation::misc(tcx, span, self.mir_def_id(), self.param_env, pred)
|
||||
}));
|
||||
|
||||
if ocx.select_all_or_error().is_empty() {
|
||||
if ocx.select_all_or_error().is_empty() && count > 0 {
|
||||
diag.span_suggestion_verbose(
|
||||
tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(),
|
||||
"dereference the return value",
|
||||
|
@ -198,7 +198,7 @@ impl rustc_errors::IntoDiagArg for RegionName {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId {
|
||||
self.body.source.def_id().expect_local()
|
||||
}
|
||||
@ -519,7 +519,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
}
|
||||
|
||||
// Otherwise, let's descend into the referent types.
|
||||
search_stack.push((*referent_ty, &referent_hir_ty.ty));
|
||||
search_stack.push((*referent_ty, referent_hir_ty.ty));
|
||||
}
|
||||
|
||||
// Match up something like `Foo<'1>`
|
||||
@ -558,7 +558,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
}
|
||||
|
||||
(ty::RawPtr(mut_ty, _), hir::TyKind::Ptr(mut_hir_ty)) => {
|
||||
search_stack.push((*mut_ty, &mut_hir_ty.ty));
|
||||
search_stack.push((*mut_ty, mut_hir_ty.ty));
|
||||
}
|
||||
|
||||
_ => {
|
||||
@ -652,7 +652,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
|
||||
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
|
||||
self.infcx.tcx,
|
||||
&self.upvars,
|
||||
self.upvars,
|
||||
upvar_index,
|
||||
);
|
||||
let region_name = self.synthesize_region_name();
|
||||
@ -717,7 +717,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
.output;
|
||||
span = output.span();
|
||||
if let hir::FnRetTy::Return(ret) = output {
|
||||
hir_ty = Some(self.get_future_inner_return_ty(*ret));
|
||||
hir_ty = Some(self.get_future_inner_return_ty(ret));
|
||||
}
|
||||
" of async function"
|
||||
}
|
||||
@ -958,7 +958,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
{
|
||||
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
|
||||
self.infcx.tcx,
|
||||
&self.upvars,
|
||||
self.upvars,
|
||||
upvar_index,
|
||||
);
|
||||
let region_name = self.synthesize_region_name();
|
||||
|
@ -213,8 +213,32 @@ trait FactCell {
|
||||
fn to_string(&self, location_table: &LocationTable) -> String;
|
||||
}
|
||||
|
||||
impl<A: Debug> FactCell for A {
|
||||
default fn to_string(&self, _location_table: &LocationTable) -> String {
|
||||
impl FactCell for BorrowIndex {
|
||||
fn to_string(&self, _location_table: &LocationTable) -> String {
|
||||
format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
impl FactCell for Local {
|
||||
fn to_string(&self, _location_table: &LocationTable) -> String {
|
||||
format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
impl FactCell for MovePathIndex {
|
||||
fn to_string(&self, _location_table: &LocationTable) -> String {
|
||||
format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
impl FactCell for PoloniusRegionVid {
|
||||
fn to_string(&self, _location_table: &LocationTable) -> String {
|
||||
format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
impl FactCell for RegionVid {
|
||||
fn to_string(&self, _location_table: &LocationTable) -> String {
|
||||
format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
#![feature(box_patterns)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
@ -310,11 +309,11 @@ fn do_mir_borrowck<'tcx>(
|
||||
promoted_mbcx.report_move_errors();
|
||||
diags = promoted_mbcx.diags;
|
||||
|
||||
struct MoveVisitor<'a, 'cx, 'tcx> {
|
||||
ctxt: &'a mut MirBorrowckCtxt<'cx, 'tcx>,
|
||||
struct MoveVisitor<'a, 'b, 'mir, 'infcx, 'tcx> {
|
||||
ctxt: &'a mut MirBorrowckCtxt<'b, 'mir, 'infcx, 'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx> {
|
||||
impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, '_, 'tcx> {
|
||||
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
|
||||
if let Operand::Move(place) = operand {
|
||||
self.ctxt.check_movable_place(location, *place);
|
||||
@ -528,15 +527,15 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
struct MirBorrowckCtxt<'cx, 'tcx> {
|
||||
infcx: &'cx BorrowckInferCtxt<'tcx>,
|
||||
struct MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx> {
|
||||
infcx: &'infcx BorrowckInferCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
body: &'cx Body<'tcx>,
|
||||
move_data: &'cx MoveData<'tcx>,
|
||||
body: &'mir Body<'tcx>,
|
||||
move_data: &'a MoveData<'tcx>,
|
||||
|
||||
/// Map from MIR `Location` to `LocationIndex`; created
|
||||
/// when MIR borrowck begins.
|
||||
location_table: &'cx LocationTable,
|
||||
location_table: &'a LocationTable,
|
||||
|
||||
movable_coroutine: bool,
|
||||
/// This keeps track of whether local variables are free-ed when the function
|
||||
@ -596,7 +595,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// Results of Polonius analysis.
|
||||
polonius_output: Option<Rc<PoloniusOutput>>,
|
||||
|
||||
diags: diags::BorrowckDiags<'tcx>,
|
||||
diags: diags::BorrowckDiags<'infcx, 'tcx>,
|
||||
move_errors: Vec<MoveError<'tcx>>,
|
||||
}
|
||||
|
||||
@ -605,14 +604,16 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// 2. loans made in overlapping scopes do not conflict
|
||||
// 3. assignments do not affect things loaned out as immutable
|
||||
// 4. moves do not affect things loaned out in any way
|
||||
impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorrowckCtxt<'cx, 'tcx> {
|
||||
type FlowState = Flows<'cx, 'tcx>;
|
||||
impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
|
||||
for MirBorrowckCtxt<'a, 'mir, '_, 'tcx>
|
||||
{
|
||||
type FlowState = Flows<'a, 'mir, 'tcx>;
|
||||
|
||||
fn visit_statement_before_primary_effect(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
stmt: &'cx Statement<'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
stmt: &'mir Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {:?}", location, stmt, flow_state);
|
||||
@ -681,8 +682,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
|
||||
fn visit_terminator_before_primary_effect(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
term: &'cx Terminator<'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
term: &'mir Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
debug!("MirBorrowckCtxt::process_terminator({:?}, {:?}): {:?}", loc, term, flow_state);
|
||||
@ -726,6 +727,12 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
|
||||
}
|
||||
self.mutate_place(loc, (*destination, span), Deep, flow_state);
|
||||
}
|
||||
TerminatorKind::TailCall { func, args, fn_span: _ } => {
|
||||
self.consume_operand(loc, (func, span), flow_state);
|
||||
for arg in args {
|
||||
self.consume_operand(loc, (&arg.node, arg.span), flow_state);
|
||||
}
|
||||
}
|
||||
TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
|
||||
self.consume_operand(loc, (cond, span), flow_state);
|
||||
if let AssertKind::BoundsCheck { len, index } = &**msg {
|
||||
@ -792,8 +799,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
|
||||
fn visit_terminator_after_primary_effect(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
term: &'cx Terminator<'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
term: &'mir Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
let span = term.source_info.span;
|
||||
@ -812,9 +819,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
|
||||
|
||||
TerminatorKind::UnwindResume
|
||||
| TerminatorKind::Return
|
||||
| TerminatorKind::TailCall { .. }
|
||||
| TerminatorKind::CoroutineDrop => {
|
||||
// Returning from the function implicitly kills storage for all locals and statics.
|
||||
// Often, the storage will already have been killed by an explicit
|
||||
// StorageDead, but we don't always emit those (notably on unwind paths),
|
||||
// so this "extra check" serves as a kind of backup.
|
||||
let borrow_set = self.borrow_set.clone();
|
||||
@ -969,8 +975,8 @@ impl InitializationRequiringAction {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn body(&self) -> &'cx Body<'tcx> {
|
||||
impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
||||
fn body(&self) -> &'mir Body<'tcx> {
|
||||
self.body
|
||||
}
|
||||
|
||||
@ -986,7 +992,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
place_span: (Place<'tcx>, Span),
|
||||
kind: (AccessDepth, ReadOrWrite),
|
||||
is_local_mutation_allowed: LocalMutationIsAllowed,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
let (sd, rw) = kind;
|
||||
|
||||
@ -1036,7 +1042,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
place_span: (Place<'tcx>, Span),
|
||||
sd: AccessDepth,
|
||||
rw: ReadOrWrite,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) -> bool {
|
||||
let mut error_reported = false;
|
||||
let borrow_set = Rc::clone(&self.borrow_set);
|
||||
@ -1177,7 +1183,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
location: Location,
|
||||
place_span: (Place<'tcx>, Span),
|
||||
kind: AccessDepth,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
// Write of P[i] or *P requires P init'd.
|
||||
self.check_if_assigned_path_is_moved(location, place_span, flow_state);
|
||||
@ -1194,8 +1200,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn consume_rvalue(
|
||||
&mut self,
|
||||
location: Location,
|
||||
(rvalue, span): (&'cx Rvalue<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
(rvalue, span): (&'mir Rvalue<'tcx>, Span),
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
match rvalue {
|
||||
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
||||
@ -1452,8 +1458,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn consume_operand(
|
||||
&mut self,
|
||||
location: Location,
|
||||
(operand, span): (&'cx Operand<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
(operand, span): (&'mir Operand<'tcx>, Span),
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
match *operand {
|
||||
Operand::Copy(place) => {
|
||||
@ -1573,7 +1579,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_activations(&mut self, location: Location, span: Span, flow_state: &Flows<'cx, 'tcx>) {
|
||||
fn check_activations(
|
||||
&mut self,
|
||||
location: Location,
|
||||
span: Span,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
// Two-phase borrow support: For each activation that is newly
|
||||
// generated at this statement, check if it interferes with
|
||||
// another borrow.
|
||||
@ -1736,7 +1747,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
location: Location,
|
||||
desired_action: InitializationRequiringAction,
|
||||
place_span: (PlaceRef<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
let maybe_uninits = &flow_state.uninits;
|
||||
|
||||
@ -1841,7 +1852,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
location: Location,
|
||||
desired_action: InitializationRequiringAction,
|
||||
place_span: (PlaceRef<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
let maybe_uninits = &flow_state.uninits;
|
||||
|
||||
@ -1940,7 +1951,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&mut self,
|
||||
location: Location,
|
||||
(place, span): (Place<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
debug!("check_if_assigned_path_is_moved place: {:?}", place);
|
||||
|
||||
@ -2001,12 +2012,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_parent_of_field<'cx, 'tcx>(
|
||||
this: &mut MirBorrowckCtxt<'cx, 'tcx>,
|
||||
fn check_parent_of_field<'mir, 'tcx>(
|
||||
this: &mut MirBorrowckCtxt<'_, 'mir, '_, 'tcx>,
|
||||
location: Location,
|
||||
base: PlaceRef<'tcx>,
|
||||
span: Span,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) {
|
||||
// rust-lang/rust#21232: Until Rust allows reads from the
|
||||
// initialized parts of partially initialized structs, we
|
||||
@ -2097,7 +2108,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
(place, span): (Place<'tcx>, Span),
|
||||
kind: ReadOrWrite,
|
||||
is_local_mutation_allowed: LocalMutationIsAllowed,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
location: Location,
|
||||
) -> bool {
|
||||
debug!(
|
||||
@ -2213,7 +2224,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn is_local_ever_initialized(
|
||||
&self,
|
||||
local: Local,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'_, 'mir, 'tcx>,
|
||||
) -> Option<InitIndex> {
|
||||
let mpi = self.move_data.rev_lookup.find_local(local)?;
|
||||
let ii = &self.move_data.init_path_map[mpi];
|
||||
@ -2221,7 +2232,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
/// Adds the place into the used mutable variables set
|
||||
fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'cx, 'tcx>) {
|
||||
fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'_, 'mir, 'tcx>) {
|
||||
match root_place {
|
||||
RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
|
||||
// If the local may have been initialized, and it is now currently being
|
||||
@ -2421,12 +2432,12 @@ mod diags {
|
||||
|
||||
use super::*;
|
||||
|
||||
enum BufferedDiag<'tcx> {
|
||||
Error(Diag<'tcx>),
|
||||
NonError(Diag<'tcx, ()>),
|
||||
enum BufferedDiag<'infcx> {
|
||||
Error(Diag<'infcx>),
|
||||
NonError(Diag<'infcx, ()>),
|
||||
}
|
||||
|
||||
impl<'tcx> BufferedDiag<'tcx> {
|
||||
impl<'infcx> BufferedDiag<'infcx> {
|
||||
fn sort_span(&self) -> Span {
|
||||
match self {
|
||||
BufferedDiag::Error(diag) => diag.sort_span,
|
||||
@ -2435,7 +2446,7 @@ mod diags {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BorrowckDiags<'tcx> {
|
||||
pub struct BorrowckDiags<'infcx, 'tcx> {
|
||||
/// This field keeps track of move errors that are to be reported for given move indices.
|
||||
///
|
||||
/// There are situations where many errors can be reported for a single move out (see
|
||||
@ -2450,15 +2461,15 @@ mod diags {
|
||||
/// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
|
||||
/// when errors in the map are being re-added to the error buffer so that errors with the
|
||||
/// same primary span come out in a consistent order.
|
||||
buffered_move_errors: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, Diag<'tcx>)>,
|
||||
buffered_move_errors: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, Diag<'infcx>)>,
|
||||
|
||||
buffered_mut_errors: FxIndexMap<Span, (Diag<'tcx>, usize)>,
|
||||
buffered_mut_errors: FxIndexMap<Span, (Diag<'infcx>, usize)>,
|
||||
|
||||
/// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics.
|
||||
buffered_diags: Vec<BufferedDiag<'tcx>>,
|
||||
buffered_diags: Vec<BufferedDiag<'infcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> BorrowckDiags<'tcx> {
|
||||
impl<'infcx, 'tcx> BorrowckDiags<'infcx, 'tcx> {
|
||||
pub fn new() -> Self {
|
||||
BorrowckDiags {
|
||||
buffered_move_errors: BTreeMap::new(),
|
||||
@ -2467,28 +2478,28 @@ mod diags {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn buffer_error(&mut self, diag: Diag<'tcx>) {
|
||||
pub fn buffer_error(&mut self, diag: Diag<'infcx>) {
|
||||
self.buffered_diags.push(BufferedDiag::Error(diag));
|
||||
}
|
||||
|
||||
pub fn buffer_non_error(&mut self, diag: Diag<'tcx, ()>) {
|
||||
pub fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
|
||||
self.buffered_diags.push(BufferedDiag::NonError(diag));
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
pub fn buffer_error(&mut self, diag: Diag<'tcx>) {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
pub fn buffer_error(&mut self, diag: Diag<'infcx>) {
|
||||
self.diags.buffer_error(diag);
|
||||
}
|
||||
|
||||
pub fn buffer_non_error(&mut self, diag: Diag<'tcx, ()>) {
|
||||
pub fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
|
||||
self.diags.buffer_non_error(diag);
|
||||
}
|
||||
|
||||
pub fn buffer_move_error(
|
||||
&mut self,
|
||||
move_out_indices: Vec<MoveOutIndex>,
|
||||
place_and_err: (PlaceRef<'tcx>, Diag<'tcx>),
|
||||
place_and_err: (PlaceRef<'tcx>, Diag<'infcx>),
|
||||
) -> bool {
|
||||
if let Some((_, diag)) =
|
||||
self.diags.buffered_move_errors.insert(move_out_indices, place_and_err)
|
||||
@ -2501,12 +2512,12 @@ mod diags {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_buffered_mut_error(&mut self, span: Span) -> Option<(Diag<'tcx>, usize)> {
|
||||
pub fn get_buffered_mut_error(&mut self, span: Span) -> Option<(Diag<'infcx>, usize)> {
|
||||
// FIXME(#120456) - is `swap_remove` correct?
|
||||
self.diags.buffered_mut_errors.swap_remove(&span)
|
||||
}
|
||||
|
||||
pub fn buffer_mut_error(&mut self, span: Span, diag: Diag<'tcx>, count: usize) {
|
||||
pub fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) {
|
||||
self.diags.buffered_mut_errors.insert(span, (diag, count));
|
||||
}
|
||||
|
||||
@ -2547,7 +2558,7 @@ mod diags {
|
||||
pub fn has_move_error(
|
||||
&self,
|
||||
move_out_indices: &[MoveOutIndex],
|
||||
) -> Option<&(PlaceRef<'tcx>, Diag<'tcx>)> {
|
||||
) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> {
|
||||
self.diags.buffered_move_errors.get(move_out_indices)
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
||||
promoted: &IndexSlice<Promoted, Body<'tcx>>,
|
||||
location_table: &LocationTable,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
|
||||
flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'_, 'cx, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
upvars: &[&ty::CapturedPlace<'tcx>],
|
||||
@ -114,7 +114,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
||||
move_data,
|
||||
elements,
|
||||
upvars,
|
||||
polonius_input,
|
||||
);
|
||||
|
||||
// Create the region inference context, taking ownership of the
|
||||
@ -263,13 +262,13 @@ pub(super) fn dump_mir_results<'tcx>(
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
pub(super) fn dump_annotation<'tcx>(
|
||||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
pub(super) fn dump_annotation<'tcx, 'cx>(
|
||||
infcx: &'cx BorrowckInferCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
regioncx: &RegionInferenceContext<'tcx>,
|
||||
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
|
||||
opaque_type_values: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
|
||||
diags: &mut crate::diags::BorrowckDiags<'tcx>,
|
||||
diags: &mut crate::diags::BorrowckDiags<'cx, 'tcx>,
|
||||
) {
|
||||
let tcx = infcx.tcx;
|
||||
let base_def_id = tcx.typeck_root_def_id(body.source.def_id());
|
||||
@ -286,7 +285,7 @@ pub(super) fn dump_annotation<'tcx>(
|
||||
|
||||
let def_span = tcx.def_span(body.source.def_id());
|
||||
let mut err = if let Some(closure_region_requirements) = closure_region_requirements {
|
||||
let mut err = tcx.dcx().struct_span_note(def_span, "external requirements");
|
||||
let mut err = infcx.dcx().struct_span_note(def_span, "external requirements");
|
||||
|
||||
regioncx.annotate(tcx, &mut err);
|
||||
|
||||
@ -305,7 +304,7 @@ pub(super) fn dump_annotation<'tcx>(
|
||||
|
||||
err
|
||||
} else {
|
||||
let mut err = tcx.dcx().struct_span_note(def_span, "no external requirements");
|
||||
let mut err = infcx.dcx().struct_span_note(def_span, "no external requirements");
|
||||
regioncx.annotate(tcx, &mut err);
|
||||
|
||||
err
|
||||
|
@ -125,6 +125,12 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> {
|
||||
}
|
||||
self.mutate_place(location, *destination, Deep);
|
||||
}
|
||||
TerminatorKind::TailCall { func, args, .. } => {
|
||||
self.consume_operand(location, func);
|
||||
for arg in args {
|
||||
self.consume_operand(location, &arg.node);
|
||||
}
|
||||
}
|
||||
TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
|
||||
self.consume_operand(location, cond);
|
||||
use rustc_middle::mir::AssertKind;
|
||||
|
@ -43,8 +43,8 @@ pub(crate) fn emit_facts<'tcx>(
|
||||
emit_universal_region_facts(
|
||||
all_facts,
|
||||
borrow_set,
|
||||
&universal_regions,
|
||||
&universal_region_relations,
|
||||
universal_regions,
|
||||
universal_region_relations,
|
||||
);
|
||||
emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set);
|
||||
emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set);
|
||||
|
@ -34,7 +34,7 @@ pub(super) enum PrefixSet {
|
||||
Shallow,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
/// Returns an iterator over the prefixes of `place`
|
||||
/// (inclusive) from longest to smallest, potentially
|
||||
/// terminating the iteration early based on `kind`.
|
||||
|
@ -62,7 +62,7 @@ pub struct RegionTracker {
|
||||
/// The representative Region Variable Id for this SCC. We prefer
|
||||
/// placeholders over existentially quantified variables, otherwise
|
||||
/// it's the one with the smallest Region Variable ID.
|
||||
representative: RegionVid,
|
||||
pub(crate) representative: RegionVid,
|
||||
|
||||
/// Is the current representative a placeholder?
|
||||
representative_is_placeholder: bool,
|
||||
@ -97,7 +97,7 @@ impl scc::Annotation for RegionTracker {
|
||||
}
|
||||
|
||||
impl RegionTracker {
|
||||
fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
|
||||
pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
|
||||
let (representative_is_placeholder, representative_is_existential) = match definition.origin
|
||||
{
|
||||
rustc_infer::infer::NllRegionVariableOrigin::FreeRegion => (false, false),
|
||||
@ -116,7 +116,9 @@ impl RegionTracker {
|
||||
representative_is_existential,
|
||||
}
|
||||
}
|
||||
fn universe(self) -> UniverseIndex {
|
||||
|
||||
/// The smallest-indexed universe reachable from and/or in this SCC.
|
||||
fn min_universe(self) -> UniverseIndex {
|
||||
self.min_reachable_universe
|
||||
}
|
||||
|
||||
@ -132,8 +134,8 @@ impl RegionTracker {
|
||||
|
||||
/// Returns `true` if during the annotated SCC reaches a placeholder
|
||||
/// with a universe larger than the smallest reachable one, `false` otherwise.
|
||||
pub fn has_incompatible_universes(&self) -> bool {
|
||||
self.universe().cannot_name(self.max_placeholder_universe_reached)
|
||||
pub(crate) fn has_incompatible_universes(&self) -> bool {
|
||||
self.min_universe().cannot_name(self.max_placeholder_universe_reached)
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,7 +165,7 @@ pub struct RegionInferenceContext<'tcx> {
|
||||
/// The SCC computed from `constraints` and the constraint
|
||||
/// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
|
||||
/// compute the values of each region.
|
||||
constraint_sccs: Rc<ConstraintSccs>,
|
||||
constraint_sccs: ConstraintSccs,
|
||||
|
||||
/// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` exists if
|
||||
/// `B: A`. This is used to compute the universal regions that are required
|
||||
@ -344,7 +346,7 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) {
|
||||
|
||||
for (reg_var_idx, scc_idx) in sccs.scc_indices().iter().enumerate() {
|
||||
let reg_var = ty::RegionVid::from_usize(reg_var_idx);
|
||||
let origin = var_to_origin.get(®_var).unwrap_or_else(|| &RegionCtxt::Unknown);
|
||||
let origin = var_to_origin.get(®_var).unwrap_or(&RegionCtxt::Unknown);
|
||||
components[scc_idx.as_usize()].insert((reg_var, *origin));
|
||||
}
|
||||
|
||||
@ -401,7 +403,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
universal_regions: Rc<UniversalRegions<'tcx>>,
|
||||
placeholder_indices: Rc<PlaceholderIndices>,
|
||||
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||
outlives_constraints: OutlivesConstraintSet<'tcx>,
|
||||
mut outlives_constraints: OutlivesConstraintSet<'tcx>,
|
||||
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
|
||||
universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||
type_tests: Vec<TypeTest<'tcx>>,
|
||||
@ -419,17 +421,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
.map(|info| RegionDefinition::new(info.universe, info.origin))
|
||||
.collect();
|
||||
|
||||
let fr_static = universal_regions.fr_static;
|
||||
let constraint_sccs =
|
||||
outlives_constraints.add_outlives_static(&universal_regions, &definitions);
|
||||
let constraints = Frozen::freeze(outlives_constraints);
|
||||
let constraint_graph = Frozen::freeze(constraints.graph(definitions.len()));
|
||||
let constraint_sccs = {
|
||||
let constraint_graph = constraints.graph(definitions.len());
|
||||
let region_graph = &constraint_graph.region_graph(&constraints, fr_static);
|
||||
let sccs = ConstraintSccs::new_with_annotation(®ion_graph, |r| {
|
||||
RegionTracker::new(r, &definitions[r])
|
||||
});
|
||||
Rc::new(sccs)
|
||||
};
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
sccs_info(infcx, &constraint_sccs);
|
||||
@ -548,21 +543,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
}
|
||||
|
||||
NllRegionVariableOrigin::Placeholder(placeholder) => {
|
||||
// Each placeholder region is only visible from
|
||||
// its universe `ui` and its extensions. So we
|
||||
// can't just add it into `scc` unless the
|
||||
// universe of the scc can name this region.
|
||||
let scc_universe = self.scc_universe(scc);
|
||||
if scc_universe.can_name(placeholder.universe) {
|
||||
self.scc_values.add_element(scc, placeholder);
|
||||
} else {
|
||||
debug!(
|
||||
"init_free_and_bound_regions: placeholder {:?} is \
|
||||
not compatible with universe {:?} of its SCC {:?}",
|
||||
placeholder, scc_universe, scc,
|
||||
);
|
||||
self.add_incompatible_universe(scc);
|
||||
}
|
||||
self.scc_values.add_element(scc, placeholder);
|
||||
}
|
||||
|
||||
NllRegionVariableOrigin::Existential { .. } => {
|
||||
@ -744,23 +725,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// (which is assured by iterating over SCCs in dependency order).
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn compute_value_for_scc(&mut self, scc_a: ConstraintSccIndex) {
|
||||
let constraint_sccs = self.constraint_sccs.clone();
|
||||
|
||||
// Walk each SCC `B` such that `A: B`...
|
||||
for &scc_b in constraint_sccs.successors(scc_a) {
|
||||
for &scc_b in self.constraint_sccs.successors(scc_a) {
|
||||
debug!(?scc_b);
|
||||
|
||||
// ...and add elements from `B` into `A`. One complication
|
||||
// arises because of universes: If `B` contains something
|
||||
// that `A` cannot name, then `A` can only contain `B` if
|
||||
// it outlives static.
|
||||
if self.universe_compatible(scc_b, scc_a) {
|
||||
// `A` can name everything that is in `B`, so just
|
||||
// merge the bits.
|
||||
self.scc_values.add_region(scc_a, scc_b);
|
||||
} else {
|
||||
self.add_incompatible_universe(scc_a);
|
||||
}
|
||||
self.scc_values.add_region(scc_a, scc_b);
|
||||
}
|
||||
|
||||
// Now take member constraints into account.
|
||||
@ -814,7 +782,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// If the member region lives in a higher universe, we currently choose
|
||||
// the most conservative option by leaving it unchanged.
|
||||
|
||||
if !self.constraint_sccs().annotation(scc).universe().is_root() {
|
||||
if !self.constraint_sccs().annotation(scc).min_universe().is_root() {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -886,35 +854,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// in `scc_a`. Used during constraint propagation, and only once
|
||||
/// the value of `scc_b` has been computed.
|
||||
fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccIndex) -> bool {
|
||||
let universe_a = self.constraint_sccs().annotation(scc_a).universe();
|
||||
let universe_b = self.constraint_sccs().annotation(scc_b).universe();
|
||||
let a_annotation = self.constraint_sccs().annotation(scc_a);
|
||||
let b_annotation = self.constraint_sccs().annotation(scc_b);
|
||||
let a_universe = a_annotation.min_universe();
|
||||
|
||||
// Quick check: if scc_b's declared universe is a subset of
|
||||
// If scc_b's declared universe is a subset of
|
||||
// scc_a's declared universe (typically, both are ROOT), then
|
||||
// it cannot contain any problematic universe elements.
|
||||
if universe_a.can_name(universe_b) {
|
||||
if a_universe.can_name(b_annotation.min_universe()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, we have to iterate over the universe elements in
|
||||
// B's value, and check whether all of them are nameable
|
||||
// from universe_a
|
||||
self.scc_values.placeholders_contained_in(scc_b).all(|p| universe_a.can_name(p.universe))
|
||||
}
|
||||
|
||||
/// Extend `scc` so that it can outlive some placeholder region
|
||||
/// from a universe it can't name; at present, the only way for
|
||||
/// this to be true is if `scc` outlives `'static`. This is
|
||||
/// actually stricter than necessary: ideally, we'd support bounds
|
||||
/// like `for<'a: 'b>` that might then allow us to approximate
|
||||
/// `'a` with `'b` and not `'static`. But it will have to do for
|
||||
/// now.
|
||||
fn add_incompatible_universe(&mut self, scc: ConstraintSccIndex) {
|
||||
debug!("add_incompatible_universe(scc={:?})", scc);
|
||||
|
||||
let fr_static = self.universal_regions.fr_static;
|
||||
self.scc_values.add_all_points(scc);
|
||||
self.scc_values.add_element(scc, fr_static);
|
||||
// Otherwise, there can be no placeholder in `b` with a too high
|
||||
// universe index to name from `a`.
|
||||
a_universe.can_name(b_annotation.max_placeholder_universe_reached)
|
||||
}
|
||||
|
||||
/// Once regions have been propagated, this method is used to see
|
||||
@ -1022,7 +975,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
"lower_bound = {:?} r_scc={:?} universe={:?}",
|
||||
lower_bound,
|
||||
r_scc,
|
||||
self.constraint_sccs.annotation(r_scc).universe()
|
||||
self.constraint_sccs.annotation(r_scc).min_universe()
|
||||
);
|
||||
|
||||
// If the type test requires that `T: 'a` where `'a` is a
|
||||
@ -1110,7 +1063,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for OpaqueFolder<'tcx> {
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
fn cx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
@ -1539,7 +1492,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// The minimum universe of any variable reachable from this
|
||||
/// SCC, inside or outside of it.
|
||||
fn scc_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
|
||||
self.constraint_sccs().annotation(scc).universe()
|
||||
self.constraint_sccs().annotation(scc).min_universe()
|
||||
}
|
||||
/// Checks the final value for the free region `fr` to see if it
|
||||
/// grew too large. In particular, examine what `end(X)` points
|
||||
@ -1896,6 +1849,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
// This loop can be hot.
|
||||
for constraint in outgoing_edges_from_graph {
|
||||
if matches!(constraint.category, ConstraintCategory::IllegalUniverse) {
|
||||
debug!("Ignoring illegal universe constraint: {constraint:?}");
|
||||
continue;
|
||||
}
|
||||
handle_constraint(constraint);
|
||||
}
|
||||
|
||||
@ -2216,7 +2173,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// #114907 where this happens via liveness and dropck outlives results.
|
||||
// Therefore, we return a default value in case that happens, which should at worst emit a
|
||||
// suboptimal error, instead of the ICE.
|
||||
self.universe_causes.get(&universe).cloned().unwrap_or_else(|| UniverseInfo::other())
|
||||
self.universe_causes.get(&universe).cloned().unwrap_or_else(UniverseInfo::other)
|
||||
}
|
||||
|
||||
/// Tries to find the terminator of the loop in which the region 'r' resides.
|
||||
|
@ -11,7 +11,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{GenericArgKind, GenericArgs};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
|
||||
use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
|
||||
@ -285,7 +285,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
}
|
||||
|
||||
if let Err(guar) =
|
||||
check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span)
|
||||
check_opaque_type_parameter_valid(self, opaque_type_key, instantiated_ty.span)
|
||||
{
|
||||
return Ty::new_error(self.tcx, guar);
|
||||
}
|
||||
@ -294,6 +294,10 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
|
||||
.ty;
|
||||
|
||||
if let Err(e) = definition_ty.error_reported() {
|
||||
return Ty::new_error(self.tcx, e);
|
||||
}
|
||||
|
||||
// `definition_ty` does not live in of the current inference context,
|
||||
// so lets make sure that we don't accidentally misuse our current `infcx`.
|
||||
match check_opaque_type_well_formed(
|
||||
@ -387,10 +391,11 @@ fn check_opaque_type_well_formed<'tcx>(
|
||||
/// [rustc-dev-guide chapter]:
|
||||
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
|
||||
fn check_opaque_type_parameter_valid<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
span: Span,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = infcx.tcx;
|
||||
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
|
||||
let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
|
||||
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
|
||||
@ -418,11 +423,9 @@ fn check_opaque_type_parameter_valid<'tcx>(
|
||||
let opaque_param = opaque_generics.param_at(i, tcx);
|
||||
let kind = opaque_param.kind.descr();
|
||||
|
||||
if let Err(guar) = opaque_env.param_is_error(i) {
|
||||
return Err(guar);
|
||||
}
|
||||
opaque_env.param_is_error(i)?;
|
||||
|
||||
return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
|
||||
return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam {
|
||||
ty: arg,
|
||||
kind,
|
||||
span,
|
||||
@ -440,7 +443,7 @@ fn check_opaque_type_parameter_valid<'tcx>(
|
||||
.collect();
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
return Err(tcx
|
||||
return Err(infcx
|
||||
.dcx()
|
||||
.struct_span_err(span, "non-defining opaque type use in defining scope")
|
||||
.with_span_note(spans, format!("{descr} used multiple times"))
|
||||
|
@ -11,8 +11,8 @@ use rustc_middle::traits::query::OutlivesBound;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt};
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::solve::deeply_normalize;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
|
||||
use std::rc::Rc;
|
||||
use type_op::TypeOpOutput;
|
||||
|
@ -12,9 +12,7 @@ use rustc_mir_dataflow::ResultsCursor;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::{
|
||||
constraints::OutlivesConstraintSet,
|
||||
facts::{AllFacts, AllFactsExt},
|
||||
region_infer::values::LivenessValues,
|
||||
constraints::OutlivesConstraintSet, region_infer::values::LivenessValues,
|
||||
universal_regions::UniversalRegions,
|
||||
};
|
||||
|
||||
@ -36,9 +34,8 @@ pub(super) fn generate<'mir, 'tcx>(
|
||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
elements: &Rc<DenseLocationMap>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
use_polonius: bool,
|
||||
) {
|
||||
debug!("liveness::generate");
|
||||
|
||||
@ -49,11 +46,8 @@ pub(super) fn generate<'mir, 'tcx>(
|
||||
);
|
||||
let (relevant_live_locals, boring_locals) =
|
||||
compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
|
||||
let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx());
|
||||
|
||||
if facts_enabled {
|
||||
polonius::populate_access_facts(typeck, body, move_data);
|
||||
};
|
||||
polonius::populate_access_facts(typeck, body, move_data);
|
||||
|
||||
trace::trace(
|
||||
typeck,
|
||||
|
@ -87,10 +87,10 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
|
||||
body: &Body<'tcx>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
) {
|
||||
debug!("populate_access_facts()");
|
||||
let location_table = typeck.borrowck_context.location_table;
|
||||
|
||||
if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
|
||||
debug!("populate_access_facts()");
|
||||
let location_table = typeck.borrowck_context.location_table;
|
||||
|
||||
let mut extractor = UseFactsExtractor {
|
||||
var_defined_at: &mut facts.var_defined_at,
|
||||
var_used_at: &mut facts.var_used_at,
|
||||
|
@ -43,7 +43,7 @@ pub(super) fn trace<'mir, 'tcx>(
|
||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
elements: &Rc<DenseLocationMap>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
relevant_live_locals: Vec<Local>,
|
||||
boring_locals: Vec<Local>,
|
||||
@ -101,7 +101,7 @@ pub(super) fn trace<'mir, 'tcx>(
|
||||
}
|
||||
|
||||
/// Contextual state for the type-liveness coroutine.
|
||||
struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
|
||||
struct LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx> {
|
||||
/// Current type-checker, giving us our inference context etc.
|
||||
typeck: &'me mut TypeChecker<'typeck, 'tcx>,
|
||||
|
||||
@ -119,7 +119,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
|
||||
|
||||
/// Results of dataflow tracking which variables (and paths) have been
|
||||
/// initialized.
|
||||
flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'flow, 'tcx>>,
|
||||
flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'a, 'flow, 'tcx>>,
|
||||
|
||||
/// Index indicating where each variable is assigned, used, or
|
||||
/// dropped.
|
||||
@ -131,8 +131,8 @@ struct DropData<'tcx> {
|
||||
region_constraint_data: Option<&'tcx QueryRegionConstraints<'tcx>>,
|
||||
}
|
||||
|
||||
struct LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||
cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>,
|
||||
struct LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> {
|
||||
cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>,
|
||||
|
||||
/// Set of points that define the current local.
|
||||
defs: BitSet<PointIndex>,
|
||||
@ -153,8 +153,8 @@ struct LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||
stack: Vec<PointIndex>,
|
||||
}
|
||||
|
||||
impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||
fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>) -> Self {
|
||||
impl<'a, 'me, 'typeck, 'flow, 'tcx> LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> {
|
||||
fn new(cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>) -> Self {
|
||||
let num_points = cx.elements.num_points();
|
||||
LivenessResults {
|
||||
cx,
|
||||
@ -217,35 +217,52 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||
/// Add facts for all locals with free regions, since regions may outlive
|
||||
/// the function body only at certain nodes in the CFG.
|
||||
fn add_extra_drop_facts(&mut self, relevant_live_locals: &[Local]) -> Option<()> {
|
||||
let drop_used = self
|
||||
.cx
|
||||
.typeck
|
||||
.borrowck_context
|
||||
.all_facts
|
||||
.as_ref()
|
||||
.map(|facts| facts.var_dropped_at.clone())?;
|
||||
// This collect is more necessary than immediately apparent
|
||||
// because these facts go into `add_drop_live_facts_for()`,
|
||||
// which also writes to `all_facts`, and so this is genuinely
|
||||
// a simulatneous overlapping mutable borrow.
|
||||
// FIXME for future hackers: investigate whether this is
|
||||
// actually necessary; these facts come from Polonius
|
||||
// and probably maybe plausibly does not need to go back in.
|
||||
// It may be necessary to just pick out the parts of
|
||||
// `add_drop_live_facts_for()` that make sense.
|
||||
let facts_to_add: Vec<_> = {
|
||||
let drop_used = &self.cx.typeck.borrowck_context.all_facts.as_ref()?.var_dropped_at;
|
||||
|
||||
let relevant_live_locals: FxIndexSet<_> = relevant_live_locals.iter().copied().collect();
|
||||
let relevant_live_locals: FxIndexSet<_> =
|
||||
relevant_live_locals.iter().copied().collect();
|
||||
|
||||
let locations = IntervalSet::new(self.cx.elements.num_points());
|
||||
drop_used
|
||||
.iter()
|
||||
.filter_map(|(local, location_index)| {
|
||||
let local_ty = self.cx.body.local_decls[*local].ty;
|
||||
if relevant_live_locals.contains(local) || !local_ty.has_free_regions() {
|
||||
return None;
|
||||
}
|
||||
|
||||
for (local, location_index) in drop_used {
|
||||
if !relevant_live_locals.contains(&local) {
|
||||
let local_ty = self.cx.body.local_decls[local].ty;
|
||||
if local_ty.has_free_regions() {
|
||||
let location = match self
|
||||
.cx
|
||||
.typeck
|
||||
.borrowck_context
|
||||
.location_table
|
||||
.to_location(location_index)
|
||||
.to_location(*location_index)
|
||||
{
|
||||
RichLocation::Start(l) => l,
|
||||
RichLocation::Mid(l) => l,
|
||||
};
|
||||
self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
|
||||
}
|
||||
}
|
||||
|
||||
Some((*local, local_ty, location))
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
||||
// FIXME: these locations seem to have a special meaning (e.g. everywhere, at the end, ...), but I don't know which one. Please help me rename it to something descriptive!
|
||||
// Also, if this IntervalSet is used in many places, it maybe should have a newtype'd
|
||||
// name with a description of what it means for future mortals passing by.
|
||||
let locations = IntervalSet::new(self.cx.elements.num_points());
|
||||
|
||||
for (local, local_ty, location) in facts_to_add {
|
||||
self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
@ -490,7 +507,7 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||
impl<'tcx> LivenessContext<'_, '_, '_, '_, 'tcx> {
|
||||
/// Returns `true` if the local variable (or some part of it) is initialized at the current
|
||||
/// cursor position. Callers should call one of the `seek` methods immediately before to point
|
||||
/// the cursor to the desired location.
|
||||
|
@ -38,6 +38,7 @@ use rustc_span::def_id::CRATE_DEF_ID;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
|
||||
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
|
||||
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
||||
@ -49,6 +50,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||
use rustc_mir_dataflow::move_paths::MoveData;
|
||||
use rustc_mir_dataflow::ResultsCursor;
|
||||
|
||||
use crate::renumber::RegionCtxt;
|
||||
use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst};
|
||||
use crate::{
|
||||
borrow_set::BorrowSet,
|
||||
@ -129,11 +131,10 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
location_table: &LocationTable,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
all_facts: &mut Option<AllFacts>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
elements: &Rc<DenseLocationMap>,
|
||||
upvars: &[&ty::CapturedPlace<'tcx>],
|
||||
use_polonius: bool,
|
||||
) -> MirTypeckResults<'tcx> {
|
||||
let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
|
||||
let mut constraints = MirTypeckRegionConstraints {
|
||||
@ -189,7 +190,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
checker.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output);
|
||||
checker.check_signature_annotation(body);
|
||||
|
||||
liveness::generate(&mut checker, body, elements, flow_inits, move_data, use_polonius);
|
||||
liveness::generate(&mut checker, body, elements, flow_inits, move_data);
|
||||
|
||||
translate_outlives_facts(&mut checker);
|
||||
let opaque_type_values = infcx.take_opaque_types();
|
||||
@ -1353,7 +1354,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
// FIXME: check the values
|
||||
}
|
||||
TerminatorKind::Call { func, args, destination, call_source, target, .. } => {
|
||||
TerminatorKind::Call { func, args, .. }
|
||||
| TerminatorKind::TailCall { func, args, .. } => {
|
||||
let call_source = match term.kind {
|
||||
TerminatorKind::Call { call_source, .. } => call_source,
|
||||
TerminatorKind::TailCall { .. } => CallSource::Normal,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
self.check_operand(func, term_location);
|
||||
for arg in args {
|
||||
self.check_operand(&arg.node, term_location);
|
||||
@ -1426,7 +1434,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
self.check_call_dest(body, term, &sig, *destination, *target, term_location);
|
||||
if let TerminatorKind::Call { destination, target, .. } = term.kind {
|
||||
self.check_call_dest(body, term, &sig, destination, target, term_location);
|
||||
}
|
||||
|
||||
// The ordinary liveness rules will ensure that all
|
||||
// regions in the type of the callee are live here. We
|
||||
@ -1444,7 +1454,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
.add_location(region_vid, term_location);
|
||||
}
|
||||
|
||||
self.check_call_inputs(body, term, func, &sig, args, term_location, *call_source);
|
||||
self.check_call_inputs(body, term, func, &sig, args, term_location, call_source);
|
||||
}
|
||||
TerminatorKind::Assert { cond, msg, .. } => {
|
||||
self.check_operand(cond, term_location);
|
||||
@ -1676,6 +1686,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
span_mirbug!(self, block_data, "return on cleanup block")
|
||||
}
|
||||
}
|
||||
TerminatorKind::TailCall { .. } => {
|
||||
if is_cleanup {
|
||||
span_mirbug!(self, block_data, "tailcall on cleanup block")
|
||||
}
|
||||
}
|
||||
TerminatorKind::CoroutineDrop { .. } => {
|
||||
if is_cleanup {
|
||||
span_mirbug!(self, block_data, "coroutine_drop in cleanup block")
|
||||
@ -2320,7 +2335,57 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
let cast_ty_from = CastTy::from_ty(ty_from);
|
||||
let cast_ty_to = CastTy::from_ty(*ty);
|
||||
match (cast_ty_from, cast_ty_to) {
|
||||
(Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) => (),
|
||||
(Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => {
|
||||
let mut normalize = |t| self.normalize(t, location);
|
||||
let src_tail =
|
||||
tcx.struct_tail_with_normalize(src.ty, &mut normalize, || ());
|
||||
let dst_tail =
|
||||
tcx.struct_tail_with_normalize(dst.ty, &mut normalize, || ());
|
||||
|
||||
// This checks (lifetime part of) vtable validity for pointer casts,
|
||||
// which is irrelevant when there are aren't principal traits on both sides (aka only auto traits).
|
||||
//
|
||||
// Note that other checks (such as denying `dyn Send` -> `dyn Debug`) are in `rustc_hir_typeck`.
|
||||
if let ty::Dynamic(src_tty, ..) = src_tail.kind()
|
||||
&& let ty::Dynamic(dst_tty, ..) = dst_tail.kind()
|
||||
&& src_tty.principal().is_some()
|
||||
&& dst_tty.principal().is_some()
|
||||
{
|
||||
// Remove auto traits.
|
||||
// Auto trait checks are handled in `rustc_hir_typeck` as FCW.
|
||||
let src_obj = tcx.mk_ty_from_kind(ty::Dynamic(
|
||||
tcx.mk_poly_existential_predicates(
|
||||
&src_tty.without_auto_traits().collect::<Vec<_>>(),
|
||||
),
|
||||
tcx.lifetimes.re_static,
|
||||
ty::Dyn,
|
||||
));
|
||||
let dst_obj = tcx.mk_ty_from_kind(ty::Dynamic(
|
||||
tcx.mk_poly_existential_predicates(
|
||||
&dst_tty.without_auto_traits().collect::<Vec<_>>(),
|
||||
),
|
||||
tcx.lifetimes.re_static,
|
||||
ty::Dyn,
|
||||
));
|
||||
|
||||
// Replace trait object lifetimes with fresh vars, to allow casts like
|
||||
// `*mut dyn FnOnce() + 'a` -> `*mut dyn FnOnce() + 'static`,
|
||||
let src_obj =
|
||||
freshen_single_trait_object_lifetime(self.infcx, src_obj);
|
||||
let dst_obj =
|
||||
freshen_single_trait_object_lifetime(self.infcx, dst_obj);
|
||||
|
||||
debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
|
||||
|
||||
self.eq_types(
|
||||
src_obj,
|
||||
dst_obj,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
span_mirbug!(
|
||||
self,
|
||||
@ -2843,3 +2908,16 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
|
||||
Ok(output)
|
||||
}
|
||||
}
|
||||
|
||||
fn freshen_single_trait_object_lifetime<'tcx>(
|
||||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let &ty::Dynamic(tty, _, dyn_kind @ ty::Dyn) = ty.kind() else { bug!("expected trait object") };
|
||||
|
||||
let fresh = infcx
|
||||
.next_region_var(rustc_infer::infer::RegionVariableOrigin::MiscVariable(DUMMY_SP), || {
|
||||
RegionCtxt::Unknown
|
||||
});
|
||||
infcx.tcx.mk_ty_from_kind(ty::Dynamic(tty, fresh, dyn_kind))
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_infer::infer::relate::{PredicateEmittingRelation, StructurallyRelateAliases};
|
||||
use rustc_infer::infer::relate::{Relate, RelateResult, TypeRelation};
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_infer::infer::relate::{
|
||||
PredicateEmittingRelation, Relate, RelateResult, StructurallyRelateAliases, TypeRelation,
|
||||
};
|
||||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
|
||||
use rustc_infer::traits::solve::Goal;
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
@ -522,7 +523,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
|
||||
}
|
||||
}
|
||||
|
||||
impl<'bccx, 'tcx> PredicateEmittingRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
|
||||
impl<'bccx, 'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx> {
|
||||
fn span(&self) -> Span {
|
||||
self.locations.span(self.type_checker.body)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use rustc_middle::mir::{
|
||||
|
||||
use crate::MirBorrowckCtxt;
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
/// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes
|
||||
/// of the `unused_mut` lint.
|
||||
///
|
||||
@ -45,13 +45,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
/// MIR visitor for collecting used mutable variables.
|
||||
/// The 'visit lifetime represents the duration of the MIR walk.
|
||||
struct GatherUsedMutsVisitor<'visit, 'cx, 'tcx> {
|
||||
struct GatherUsedMutsVisitor<'visit, 'a, 'mir, 'infcx, 'tcx> {
|
||||
temporary_used_locals: FxIndexSet<Local>,
|
||||
never_initialized_mut_locals: &'visit mut FxIndexSet<Local>,
|
||||
mbcx: &'visit mut MirBorrowckCtxt<'cx, 'tcx>,
|
||||
mbcx: &'visit mut MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx>,
|
||||
}
|
||||
|
||||
impl GatherUsedMutsVisitor<'_, '_, '_> {
|
||||
impl GatherUsedMutsVisitor<'_, '_, '_, '_, '_> {
|
||||
fn remove_never_initialized_mut_locals(&mut self, into: Place<'_>) {
|
||||
// Remove any locals that we found were initialized from the
|
||||
// `never_initialized_mut_locals` set. At the end, the only remaining locals will
|
||||
@ -63,7 +63,7 @@ impl GatherUsedMutsVisitor<'_, '_, '_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tcx> {
|
||||
impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, '_, 'tcx> {
|
||||
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
||||
debug!("visit_terminator: terminator={:?}", terminator);
|
||||
match &terminator.kind {
|
||||
|
@ -17,6 +17,9 @@ builtin_macros_asm_expected_other = expected operand, {$is_global_asm ->
|
||||
*[false] clobber_abi, options
|
||||
}, or additional template string
|
||||
|
||||
builtin_macros_asm_expected_string_literal = expected string literal
|
||||
.label = not a string literal
|
||||
|
||||
builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
|
||||
|
||||
builtin_macros_asm_mayunwind = asm labels are not allowed with the `may_unwind` option
|
||||
@ -25,6 +28,8 @@ builtin_macros_asm_modifier_invalid = asm template modifier must be a single cha
|
||||
|
||||
builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive
|
||||
|
||||
builtin_macros_asm_no_matched_argument_name = there is no argument named `{$name}`
|
||||
|
||||
builtin_macros_asm_noreturn = asm outputs are not allowed with the `noreturn` option
|
||||
|
||||
builtin_macros_asm_opt_already_provided = the `{$symbol}` option was already provided
|
||||
@ -228,10 +233,16 @@ builtin_macros_only_one_argument = {$name} takes 1 argument
|
||||
|
||||
builtin_macros_proc_macro = `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
|
||||
|
||||
builtin_macros_proc_macro_attribute_only_be_used_on_bare_functions = the `#[{$path}]` attribute may only be used on bare functions
|
||||
|
||||
builtin_macros_proc_macro_attribute_only_usable_with_crate_type = the `#[{$path}]` attribute is only usable with crates of the `proc-macro` crate type
|
||||
|
||||
builtin_macros_requires_cfg_pattern =
|
||||
macro requires a cfg-pattern as an argument
|
||||
.label = cfg-pattern required
|
||||
|
||||
builtin_macros_source_uitls_expected_item = expected item, found `{$token}`
|
||||
|
||||
builtin_macros_takes_no_arguments = {$name} takes no arguments
|
||||
|
||||
builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
|
||||
|
@ -390,9 +390,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
|
||||
}
|
||||
Err(opt_lit) => {
|
||||
let span = opt_lit.map_or(p.token.span, |lit| lit.span);
|
||||
let mut err = p.dcx().struct_span_err(span, "expected string literal");
|
||||
err.span_label(span, "not a string literal");
|
||||
return Err(err);
|
||||
return Err(p.dcx().create_err(errors::AsmExpectedStringLiteral { span }));
|
||||
}
|
||||
};
|
||||
|
||||
@ -639,14 +637,13 @@ fn expand_preparsed_asm(
|
||||
match args.named_args.get(&Symbol::intern(name)) {
|
||||
Some(&idx) => Some(idx),
|
||||
None => {
|
||||
let msg = format!("there is no argument named `{name}`");
|
||||
let span = arg.position_span;
|
||||
ecx.dcx()
|
||||
.struct_span_err(
|
||||
template_span
|
||||
.create_err(errors::AsmNoMatchedArgumentName {
|
||||
name: name.to_owned(),
|
||||
span: template_span
|
||||
.from_inner(InnerSpan::new(span.start, span.end)),
|
||||
msg,
|
||||
)
|
||||
})
|
||||
.emit();
|
||||
None
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
// sync with the `rfc-2011-nicer-assert-messages/all-expr-kinds.rs` test.
|
||||
ExprKind::Assign(_, _, _)
|
||||
| ExprKind::AssignOp(_, _, _)
|
||||
| ExprKind::Gen(_, _, _)
|
||||
| ExprKind::Gen(_, _, _, _)
|
||||
| ExprKind::Await(_, _)
|
||||
| ExprKind::Block(_, _)
|
||||
| ExprKind::Break(_, _)
|
||||
|
@ -38,16 +38,14 @@ pub(crate) fn cfg_eval(
|
||||
lint_node_id: NodeId,
|
||||
) -> Annotatable {
|
||||
let features = Some(features);
|
||||
CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true, lint_node_id } }
|
||||
CfgEval(StripUnconfigured { sess, features, config_tokens: true, lint_node_id })
|
||||
.configure_annotatable(annotatable)
|
||||
// Since the item itself has already been configured by the `InvocationCollector`,
|
||||
// we know that fold result vector will contain exactly one element.
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
struct CfgEval<'a, 'b> {
|
||||
cfg: &'a mut StripUnconfigured<'b>,
|
||||
}
|
||||
struct CfgEval<'a>(StripUnconfigured<'a>);
|
||||
|
||||
fn flat_map_annotatable(
|
||||
vis: &mut impl MutVisitor,
|
||||
@ -125,9 +123,9 @@ fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool {
|
||||
res.is_break()
|
||||
}
|
||||
|
||||
impl CfgEval<'_, '_> {
|
||||
impl CfgEval<'_> {
|
||||
fn configure<T: HasAttrs + HasTokens>(&mut self, node: T) -> Option<T> {
|
||||
self.cfg.configure(node)
|
||||
self.0.configure(node)
|
||||
}
|
||||
|
||||
fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Annotatable> {
|
||||
@ -195,8 +193,8 @@ impl CfgEval<'_, '_> {
|
||||
|
||||
// Re-parse the tokens, setting the `capture_cfg` flag to save extra information
|
||||
// to the captured `AttrTokenStream` (specifically, we capture
|
||||
// `AttrTokenTree::AttributesData` for all occurrences of `#[cfg]` and `#[cfg_attr]`)
|
||||
let mut parser = Parser::new(&self.cfg.sess.psess, orig_tokens, None);
|
||||
// `AttrTokenTree::AttrsTarget` for all occurrences of `#[cfg]` and `#[cfg_attr]`)
|
||||
let mut parser = Parser::new(&self.0.sess.psess, orig_tokens, None);
|
||||
parser.capture_cfg = true;
|
||||
match parse_annotatable_with(&mut parser) {
|
||||
Ok(a) => annotatable = a,
|
||||
@ -212,16 +210,16 @@ impl CfgEval<'_, '_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl MutVisitor for CfgEval<'_, '_> {
|
||||
impl MutVisitor for CfgEval<'_> {
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||
self.cfg.configure_expr(expr, false);
|
||||
self.0.configure_expr(expr, false);
|
||||
mut_visit::noop_visit_expr(expr, self);
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||
self.cfg.configure_expr(expr, true);
|
||||
self.0.configure_expr(expr, true);
|
||||
mut_visit::noop_visit_expr(expr, self);
|
||||
}
|
||||
|
||||
|
@ -240,7 +240,7 @@ fn has_a_default_variant(item: &Annotatable) -> bool {
|
||||
if v.attrs.iter().any(|attr| attr.has_name(kw::Default)) {
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
// no need to subrecurse.
|
||||
// no need to walk the variant, we are only looking for top level variants
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ pub(crate) mod decodable;
|
||||
pub(crate) mod default;
|
||||
pub(crate) mod encodable;
|
||||
pub(crate) mod hash;
|
||||
pub(crate) mod smart_ptr;
|
||||
|
||||
#[path = "cmp/eq.rs"]
|
||||
pub(crate) mod eq;
|
||||
|
173
compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
Normal file
173
compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
Normal file
@ -0,0 +1,173 @@
|
||||
use std::mem::swap;
|
||||
|
||||
use ast::HasAttrs;
|
||||
use rustc_ast::{
|
||||
self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, MetaItem,
|
||||
TraitBoundModifiers, VariantData,
|
||||
};
|
||||
use rustc_attr as attr;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
macro_rules! path {
|
||||
($span:expr, $($part:ident)::*) => { vec![$(Ident::new(sym::$part, $span),)*] }
|
||||
}
|
||||
|
||||
pub fn expand_deriving_smart_ptr(
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
_mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
_is_const: bool,
|
||||
) {
|
||||
let (name_ident, generics) = if let Annotatable::Item(aitem) = item
|
||||
&& let ItemKind::Struct(struct_data, g) = &aitem.kind
|
||||
{
|
||||
let is_transparent = aitem.attrs.iter().any(|attr| {
|
||||
attr::find_repr_attrs(cx.sess, attr)
|
||||
.into_iter()
|
||||
.any(|r| matches!(r, attr::ReprTransparent))
|
||||
});
|
||||
if !is_transparent {
|
||||
cx.dcx()
|
||||
.struct_span_err(
|
||||
span,
|
||||
"`SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`",
|
||||
)
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
if !matches!(
|
||||
struct_data,
|
||||
VariantData::Struct { fields, recovered: _ } | VariantData::Tuple(fields, _)
|
||||
if !fields.is_empty())
|
||||
{
|
||||
cx.dcx()
|
||||
.struct_span_err(
|
||||
span,
|
||||
"`SmartPointer` can only be derived on `struct`s with at least one field",
|
||||
)
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
(aitem.ident, g)
|
||||
} else {
|
||||
cx.dcx()
|
||||
.struct_span_err(
|
||||
span,
|
||||
"`SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`",
|
||||
)
|
||||
.emit();
|
||||
return;
|
||||
};
|
||||
|
||||
// Convert generic parameters (from the struct) into generic args.
|
||||
let mut pointee_param = None;
|
||||
let mut multiple_pointee_diag: SmallVec<[_; 2]> = smallvec![];
|
||||
let self_params = generics
|
||||
.params
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, p)| match p.kind {
|
||||
GenericParamKind::Lifetime => GenericArg::Lifetime(cx.lifetime(p.span(), p.ident)),
|
||||
GenericParamKind::Type { .. } => {
|
||||
if p.attrs().iter().any(|attr| attr.has_name(sym::pointee)) {
|
||||
if pointee_param.is_some() {
|
||||
multiple_pointee_diag.push(cx.dcx().struct_span_err(
|
||||
p.span(),
|
||||
"`SmartPointer` can only admit one type as pointee",
|
||||
));
|
||||
} else {
|
||||
pointee_param = Some(idx);
|
||||
}
|
||||
}
|
||||
GenericArg::Type(cx.ty_ident(p.span(), p.ident))
|
||||
}
|
||||
GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(p.span(), p.ident)),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let Some(pointee_param_idx) = pointee_param else {
|
||||
cx.dcx().struct_span_err(
|
||||
span,
|
||||
"At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits",
|
||||
).emit();
|
||||
return;
|
||||
};
|
||||
if !multiple_pointee_diag.is_empty() {
|
||||
for diag in multiple_pointee_diag {
|
||||
diag.emit();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the type of `self`.
|
||||
let path = cx.path_all(span, false, vec![name_ident], self_params.clone());
|
||||
let self_type = cx.ty_path(path);
|
||||
|
||||
// Declare helper function that adds implementation blocks.
|
||||
// FIXME(dingxiangfei2009): Investigate the set of attributes on target struct to be propagated to impls
|
||||
let attrs = thin_vec![cx.attr_word(sym::automatically_derived, span),];
|
||||
let mut add_impl_block = |generics, trait_symbol, trait_args| {
|
||||
let mut parts = path!(span, core::ops);
|
||||
parts.push(Ident::new(trait_symbol, span));
|
||||
let trait_path = cx.path_all(span, true, parts, trait_args);
|
||||
let trait_ref = cx.trait_ref(trait_path);
|
||||
let item = cx.item(
|
||||
span,
|
||||
Ident::empty(),
|
||||
attrs.clone(),
|
||||
ast::ItemKind::Impl(Box::new(ast::Impl {
|
||||
safety: ast::Safety::Default,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
constness: ast::Const::No,
|
||||
generics,
|
||||
of_trait: Some(trait_ref),
|
||||
self_ty: self_type.clone(),
|
||||
items: ThinVec::new(),
|
||||
})),
|
||||
);
|
||||
push(Annotatable::Item(item));
|
||||
};
|
||||
|
||||
// Create unsized `self`, that is, one where the `#[pointee]` type arg is replaced with `__S`. For
|
||||
// example, instead of `MyType<'a, T>`, it will be `MyType<'a, __S>`.
|
||||
let s_ty = cx.ty_ident(span, Ident::new(sym::__S, span));
|
||||
let mut alt_self_params = self_params;
|
||||
alt_self_params[pointee_param_idx] = GenericArg::Type(s_ty.clone());
|
||||
let alt_self_type = cx.ty_path(cx.path_all(span, false, vec![name_ident], alt_self_params));
|
||||
|
||||
// Find the `#[pointee]` parameter and add an `Unsize<__S>` bound to it.
|
||||
let mut impl_generics = generics.clone();
|
||||
{
|
||||
let p = &mut impl_generics.params[pointee_param_idx];
|
||||
let arg = GenericArg::Type(s_ty.clone());
|
||||
let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]);
|
||||
p.bounds.push(cx.trait_bound(unsize, false));
|
||||
let mut attrs = thin_vec![];
|
||||
swap(&mut p.attrs, &mut attrs);
|
||||
p.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect();
|
||||
}
|
||||
|
||||
// Add the `__S: ?Sized` extra parameter to the impl block.
|
||||
let sized = cx.path_global(span, path!(span, core::marker::Sized));
|
||||
let bound = GenericBound::Trait(
|
||||
cx.poly_trait_ref(span, sized),
|
||||
TraitBoundModifiers {
|
||||
polarity: ast::BoundPolarity::Maybe(span),
|
||||
constness: ast::BoundConstness::Never,
|
||||
asyncness: ast::BoundAsyncness::Normal,
|
||||
},
|
||||
);
|
||||
let extra_param = cx.typaram(span, Ident::new(sym::__S, span), vec![bound], None);
|
||||
impl_generics.params.push(extra_param);
|
||||
|
||||
// Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`.
|
||||
let gen_args = vec![GenericArg::Type(alt_self_type.clone())];
|
||||
add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone());
|
||||
add_impl_block(impl_generics.clone(), sym::CoerceUnsized, gen_args.clone());
|
||||
}
|
@ -728,6 +728,14 @@ pub(crate) struct AsmExpectedComma {
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_expected_string_literal)]
|
||||
pub(crate) struct AsmExpectedStringLiteral {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_underscore_input)]
|
||||
pub(crate) struct AsmUnderscoreInput {
|
||||
@ -781,6 +789,14 @@ pub(crate) struct AsmNoReturn {
|
||||
pub(crate) outputs_sp: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_no_matched_argument_name)]
|
||||
pub(crate) struct AsmNoMatchedArgumentName {
|
||||
pub(crate) name: String,
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_asm_mayunwind)]
|
||||
pub(crate) struct AsmMayUnwind {
|
||||
@ -872,3 +888,27 @@ pub(crate) struct TakesNoArguments<'a> {
|
||||
pub span: Span,
|
||||
pub name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_proc_macro_attribute_only_be_used_on_bare_functions)]
|
||||
pub(crate) struct AttributeOnlyBeUsedOnBareFunctions<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub path: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_proc_macro_attribute_only_usable_with_crate_type)]
|
||||
pub(crate) struct AttributeOnlyUsableWithCrateType<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub path: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_source_uitls_expected_item)]
|
||||
pub(crate) struct ExpectedItem<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub token: &'a str,
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(lint_reasons))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
@ -12,7 +13,6 @@
|
||||
#![feature(decl_macro)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(lint_reasons)]
|
||||
#![feature(proc_macro_internals)]
|
||||
#![feature(proc_macro_quote)]
|
||||
#![feature(rustdoc_internals)]
|
||||
@ -127,6 +127,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
||||
PartialOrd: partial_ord::expand_deriving_partial_ord,
|
||||
RustcDecodable: decodable::expand_deriving_rustc_decodable,
|
||||
RustcEncodable: encodable::expand_deriving_rustc_encodable,
|
||||
SmartPointer: smart_ptr::expand_deriving_smart_ptr,
|
||||
}
|
||||
|
||||
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
|
||||
|
@ -214,12 +214,12 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
||||
};
|
||||
|
||||
if !is_fn {
|
||||
let msg = format!(
|
||||
"the `#[{}]` attribute may only be used on bare functions",
|
||||
pprust::path_to_string(&attr.get_normal_item().path),
|
||||
);
|
||||
|
||||
self.dcx.span_err(attr.span, msg);
|
||||
self.dcx
|
||||
.create_err(errors::AttributeOnlyBeUsedOnBareFunctions {
|
||||
span: attr.span,
|
||||
path: &pprust::path_to_string(&attr.get_normal_item().path),
|
||||
})
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -228,12 +228,12 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
||||
}
|
||||
|
||||
if !self.is_proc_macro_crate {
|
||||
let msg = format!(
|
||||
"the `#[{}]` attribute is only usable with crates of the `proc-macro` crate type",
|
||||
pprust::path_to_string(&attr.get_normal_item().path),
|
||||
);
|
||||
|
||||
self.dcx.span_err(attr.span, msg);
|
||||
self.dcx
|
||||
.create_err(errors::AttributeOnlyUsableWithCrateType {
|
||||
span: attr.span,
|
||||
path: &pprust::path_to_string(&attr.get_normal_item().path),
|
||||
})
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::errors;
|
||||
use crate::util::{
|
||||
check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
|
||||
};
|
||||
@ -165,9 +166,13 @@ pub(crate) fn expand_include<'cx>(
|
||||
Ok(Some(item)) => ret.push(item),
|
||||
Ok(None) => {
|
||||
if self.p.token != token::Eof {
|
||||
let token = pprust::token_to_string(&self.p.token);
|
||||
let msg = format!("expected item, found `{token}`");
|
||||
self.p.dcx().span_err(self.p.token.span, msg);
|
||||
self.p
|
||||
.dcx()
|
||||
.create_err(errors::ExpectedItem {
|
||||
span: self.p.token.span,
|
||||
token: &pprust::token_to_string(&self.p.token),
|
||||
})
|
||||
.emit();
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! 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 crate::errors;
|
||||
/// 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 crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, attr, GenericParamKind};
|
||||
|
@ -55,10 +55,6 @@ jobs:
|
||||
if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin'
|
||||
run: rustup set default-host x86_64-apple-darwin
|
||||
|
||||
- name: Select XCode version
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.sh prepare
|
||||
|
||||
|
@ -66,6 +66,9 @@ jobs:
|
||||
env:
|
||||
TARGET_TRIPLE: aarch64-unknown-linux-gnu
|
||||
apt_deps: gcc-aarch64-linux-gnu qemu-user
|
||||
- os: macos-latest
|
||||
env:
|
||||
TARGET_TRIPLE: aarch64-apple-darwin
|
||||
- os: ubuntu-latest
|
||||
env:
|
||||
TARGET_TRIPLE: s390x-unknown-linux-gnu
|
||||
@ -108,10 +111,6 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ${{ matrix.apt_deps }}
|
||||
|
||||
- name: Select XCode version
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.sh prepare
|
||||
|
||||
@ -214,6 +213,9 @@ jobs:
|
||||
- os: macos-latest
|
||||
env:
|
||||
TARGET_TRIPLE: x86_64-apple-darwin
|
||||
- os: macos-latest
|
||||
env:
|
||||
TARGET_TRIPLE: aarch64-apple-darwin
|
||||
# cross-compile from Linux to Windows using mingw
|
||||
- os: ubuntu-latest
|
||||
env:
|
||||
@ -248,10 +250,6 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gcc-mingw-w64-x86-64
|
||||
|
||||
- name: Select XCode version
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: ./y.sh prepare
|
||||
|
||||
@ -282,7 +280,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
if: ${{ github.ref == 'refs/heads/master' }}
|
||||
needs: [rustfmt, test, bench, dist]
|
||||
# FIXME add the bench job back to the dependency list once rust-lang/rust#125493 gets merged
|
||||
needs: [rustfmt, test, dist]
|
||||
|
||||
permissions:
|
||||
contents: write # for creating the dev tag and release
|
||||
|
@ -46,18 +46,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79b27922a6879b5b5361d0a084cb0b1941bf109a98540addcb932da13b68bed4"
|
||||
checksum = "0b6b33d7e757a887989eb18b35712b2a67d96171ec3149d1bfb657b29b7b367c"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "304c455b28bf56372729acb356afbb55d622f2b0f2f7837aa5e57c138acaac4d"
|
||||
checksum = "b9acf15cb22be42d07c3b57d7856329cb228b7315d385346149df2566ad5e4aa"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"cranelift-bforest",
|
||||
@ -70,45 +70,46 @@ dependencies = [
|
||||
"hashbrown 0.14.3",
|
||||
"log",
|
||||
"regalloc2",
|
||||
"rustc-hash",
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1653c56b99591d07f67c5ca7f9f25888948af3f4b97186bff838d687d666f613"
|
||||
checksum = "e934d301392b73b3f8b0540391fb82465a0f179a3cee7c726482ac4727efcc97"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5b6a9cf6b6eb820ee3f973a0db313c05dc12d370f37b4fe9630286e1672573f"
|
||||
checksum = "8afb2a2566b3d54b854dfb288b3b187f6d3d17d6f762c92898207eba302931da"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-control"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9d06e6bf30075fb6bed9e034ec046475093392eea1aff90eb5c44c4a033d19a"
|
||||
checksum = "0100f33b704cdacd01ad66ff41f8c5030d57cbff078e2a4e49ab1822591299fa"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29be04f931b73cdb9694874a295027471817f26f26d2f0ebe5454153176b6e3a"
|
||||
checksum = "a8cfdc315e5d18997093e040a8d234bea1ac1e118a716d3e30f40d449e78207b"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a07fd7393041d7faa2f37426f5dc7fc04003b70988810e8c063beefeff1cd8f9"
|
||||
checksum = "0f74b84f16af2e982b0c0c72233503d9d55cbfe3865dbe807ca28dc6642a28b5"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
@ -118,15 +119,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f341d7938caa6dff8149dac05bb2b53fc680323826b83b4cf175ab9f5139a3c9"
|
||||
checksum = "adf306d3dde705fb94bd48082f01d38c4ededc74293a4c007805f610bf08bc6e"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42733555e06433f1461570e09dbd756dafc228b4dac75c597cdbdc518de07522"
|
||||
checksum = "f5c5cfb8bbd3339cd25cca30e7516ff8fe5cb1feeddde6980cc4d5ef34df97bb"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@ -144,9 +145,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84950af02bb85f3da764d53a953b43bb29a732e793d4fe24637a61591be9a024"
|
||||
checksum = "7c9b0d4269b36fd858e6d8f20cd4938941186fb831488c361888cb2d6b33a9a6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@ -155,9 +156,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82af6066e6448d26eeabb7aa26a43f7ff79f8217b06bade4ee6ef230aecc8880"
|
||||
checksum = "1ea0ebdef7aff4a79bcbc8b6495f31315f16b3bf311152f472eaa8d679352581"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
@ -166,9 +167,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-object"
|
||||
version = "0.107.0"
|
||||
version = "0.109.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00af56107039ed150391df6f753298c7b08f2b6a2e0727d216b5fa599d684d8b"
|
||||
checksum = "19e33439ec20db058bc7cc3410f9748ab1ad90a35cef713d625c736f43e3820d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@ -278,9 +279,9 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.33.0"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d"
|
||||
checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"hashbrown 0.14.3",
|
||||
@ -410,10 +411,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-jit-icache-coherence"
|
||||
version = "20.0.0"
|
||||
version = "22.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a9f93a3289057b26dc75eb84d6e60d7694f7d169c7c09597495de6e016a13ff"
|
||||
checksum = "5afe2f0499542f9a4bcfa1b55bfdda803b6ade4e7c93c6b99e0f39dba44b0a91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
|
@ -8,15 +8,15 @@ crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
# These have to be in sync with each other
|
||||
cranelift-codegen = { version = "0.107.0", default-features = false, features = ["std", "unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.107.0" }
|
||||
cranelift-module = { version = "0.107.0" }
|
||||
cranelift-native = { version = "0.107.0" }
|
||||
cranelift-jit = { version = "0.107.0", optional = true }
|
||||
cranelift-object = { version = "0.107.0" }
|
||||
cranelift-codegen = { version = "0.109.0", default-features = false, features = ["std", "unwind", "all-arch"] }
|
||||
cranelift-frontend = { version = "0.109.0" }
|
||||
cranelift-module = { version = "0.109.0" }
|
||||
cranelift-native = { version = "0.109.0" }
|
||||
cranelift-jit = { version = "0.109.0", optional = true }
|
||||
cranelift-object = { version = "0.109.0" }
|
||||
target-lexicon = "0.12.0"
|
||||
gimli = { version = "0.28", default-features = false, features = ["write"]}
|
||||
object = { version = "0.33", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
|
||||
indexmap = "2.0.0"
|
||||
libloading = { version = "0.8.0", optional = true }
|
||||
|
@ -70,7 +70,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system
|
||||
|FreeBSD|✅[^no-rustup]|❓|❓|❓|
|
||||
|AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]|
|
||||
|Other unixes|❓|❓|❓|❓|
|
||||
|macOS|✅|❌[^apple-silicon]|N/A|N/A|
|
||||
|macOS|✅|✅[^no-rustup]|N/A|N/A|
|
||||
|Windows|✅[^no-rustup]|❌|N/A|N/A|
|
||||
|
||||
✅: Fully supported and tested
|
||||
@ -80,7 +80,6 @@ For more docs on how to build and test see [build_system/usage.txt](build_system
|
||||
Not all targets are available as rustup component for nightly. See notes in the platform support matrix.
|
||||
|
||||
[^xcoff]: XCOFF object file format is not supported.
|
||||
[^apple-silicon]: Tracked in [#1248](https://github.com/rust-lang/rustc_codegen_cranelift/issues/1248).
|
||||
[^no-rustup]: Not available as rustup component for nightly. You can build it yourself.
|
||||
|
||||
## Usage
|
||||
|
@ -267,10 +267,6 @@ fn build_clif_sysroot_for_triple(
|
||||
prefix.to_str().unwrap()
|
||||
));
|
||||
}
|
||||
rustflags.push("-Zunstable-options".to_owned());
|
||||
for (name, values) in EXTRA_CHECK_CFGS {
|
||||
rustflags.push(check_cfg_arg(name, *values));
|
||||
}
|
||||
compiler.rustflags.extend(rustflags);
|
||||
let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
|
||||
if channel == "release" {
|
||||
@ -330,34 +326,3 @@ fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
|
||||
|
||||
Some(target_libs)
|
||||
}
|
||||
|
||||
// Copied from https://github.com/rust-lang/rust/blob/4fd98a4b1b100f5329c6efae18031791f64372d2/src/bootstrap/src/utils/helpers.rs#L569-L585
|
||||
/// Create a `--check-cfg` argument invocation for a given name
|
||||
/// and it's values.
|
||||
fn check_cfg_arg(name: &str, values: Option<&[&str]>) -> String {
|
||||
// Creating a string of the values by concatenating each value:
|
||||
// ',values("tvos","watchos")' or '' (nothing) when there are no values.
|
||||
let next = match values {
|
||||
Some(values) => {
|
||||
let mut tmp = values.iter().flat_map(|val| [",", "\"", val, "\""]).collect::<String>();
|
||||
|
||||
tmp.insert_str(1, "values(");
|
||||
tmp.push(')');
|
||||
tmp
|
||||
}
|
||||
None => "".to_string(),
|
||||
};
|
||||
format!("--check-cfg=cfg({name}{next})")
|
||||
}
|
||||
|
||||
const EXTRA_CHECK_CFGS: &[(&str, Option<&[&str]>)] = &[
|
||||
("bootstrap", None),
|
||||
("stdarch_intel_sde", None),
|
||||
("no_fp_fmt_parse", None),
|
||||
("no_global_oom_handling", None),
|
||||
("no_rc", None),
|
||||
("no_sync", None),
|
||||
("netbsd10", None),
|
||||
("backtrace_in_libstd", None),
|
||||
("target_arch", Some(&["xtensa"])),
|
||||
];
|
||||
|
@ -329,7 +329,6 @@ pub(crate) fn run_tests(
|
||||
struct TestRunner<'a> {
|
||||
is_native: bool,
|
||||
jit_supported: bool,
|
||||
use_unstable_features: bool,
|
||||
skip_tests: &'a [&'a str],
|
||||
dirs: Dirs,
|
||||
target_compiler: Compiler,
|
||||
@ -361,15 +360,7 @@ impl<'a> TestRunner<'a> {
|
||||
&& target_compiler.triple.contains("x86_64")
|
||||
&& !target_compiler.triple.contains("windows");
|
||||
|
||||
Self {
|
||||
is_native,
|
||||
jit_supported,
|
||||
use_unstable_features,
|
||||
skip_tests,
|
||||
dirs,
|
||||
target_compiler,
|
||||
stdlib_source,
|
||||
}
|
||||
Self { is_native, jit_supported, skip_tests, dirs, target_compiler, stdlib_source }
|
||||
}
|
||||
|
||||
fn run_testsuite(&self, tests: &[TestCase]) {
|
||||
@ -393,31 +384,13 @@ impl<'a> TestRunner<'a> {
|
||||
match *cmd {
|
||||
TestCaseCmd::Custom { func } => func(self),
|
||||
TestCaseCmd::BuildLib { source, crate_types } => {
|
||||
if self.use_unstable_features {
|
||||
self.run_rustc([source, "--crate-type", crate_types]);
|
||||
} else {
|
||||
self.run_rustc([
|
||||
source,
|
||||
"--crate-type",
|
||||
crate_types,
|
||||
"--cfg",
|
||||
"no_unstable_features",
|
||||
]);
|
||||
}
|
||||
self.run_rustc([source, "--crate-type", crate_types]);
|
||||
}
|
||||
TestCaseCmd::BuildBin { source } => {
|
||||
if self.use_unstable_features {
|
||||
self.run_rustc([source]);
|
||||
} else {
|
||||
self.run_rustc([source, "--cfg", "no_unstable_features"]);
|
||||
}
|
||||
self.run_rustc([source]);
|
||||
}
|
||||
TestCaseCmd::BuildBinAndRun { source, args } => {
|
||||
if self.use_unstable_features {
|
||||
self.run_rustc([source]);
|
||||
} else {
|
||||
self.run_rustc([source, "--cfg", "no_unstable_features"]);
|
||||
}
|
||||
self.run_rustc([source]);
|
||||
self.run_out_command(
|
||||
source.split('/').last().unwrap().split('.').next().unwrap(),
|
||||
args,
|
||||
@ -472,7 +445,6 @@ impl<'a> TestRunner<'a> {
|
||||
cmd.arg(&self.target_compiler.triple);
|
||||
cmd.arg("-Cpanic=abort");
|
||||
cmd.arg("-Zunstable-options");
|
||||
cmd.arg("--check-cfg=cfg(no_unstable_features)");
|
||||
cmd.arg("--check-cfg=cfg(jit)");
|
||||
cmd.args(args);
|
||||
cmd
|
||||
|
@ -333,12 +333,7 @@ fn main() {
|
||||
#[cfg(all(not(jit), not(all(windows, target_env = "gnu"))))]
|
||||
test_tls();
|
||||
|
||||
#[cfg(all(
|
||||
not(jit),
|
||||
not(no_unstable_features),
|
||||
target_arch = "x86_64",
|
||||
any(target_os = "linux", target_os = "macos")
|
||||
))]
|
||||
#[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "macos")))]
|
||||
unsafe {
|
||||
global_asm_test();
|
||||
naked_test();
|
||||
@ -367,17 +362,12 @@ fn stack_val_align() {
|
||||
assert_eq!(&a as *const Foo as usize % 8192, 0);
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(jit),
|
||||
not(no_unstable_features),
|
||||
target_arch = "x86_64",
|
||||
any(target_os = "linux", target_os = "macos")
|
||||
))]
|
||||
#[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "macos")))]
|
||||
extern "C" {
|
||||
fn global_asm_test();
|
||||
}
|
||||
|
||||
#[cfg(all(not(jit), not(no_unstable_features), target_arch = "x86_64", target_os = "linux"))]
|
||||
#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
|
||||
global_asm! {
|
||||
"
|
||||
.global global_asm_test
|
||||
@ -387,7 +377,7 @@ global_asm! {
|
||||
"
|
||||
}
|
||||
|
||||
#[cfg(all(not(jit), not(no_unstable_features), target_arch = "x86_64", target_os = "macos"))]
|
||||
#[cfg(all(not(jit), target_arch = "x86_64", target_os = "macos"))]
|
||||
global_asm! {
|
||||
"
|
||||
.global _global_asm_test
|
||||
@ -397,7 +387,7 @@ global_asm! {
|
||||
"
|
||||
}
|
||||
|
||||
#[cfg(all(not(jit), not(no_unstable_features), target_arch = "x86_64"))]
|
||||
#[cfg(all(not(jit), target_arch = "x86_64"))]
|
||||
#[naked]
|
||||
extern "C" fn naked_test() {
|
||||
unsafe {
|
||||
|
@ -251,6 +251,9 @@ unsafe fn test_simd() {
|
||||
test_mm_add_epi8();
|
||||
test_mm_add_pd();
|
||||
test_mm_cvtepi8_epi16();
|
||||
#[cfg(not(jit))]
|
||||
test_mm_cvtps_epi32();
|
||||
test_mm_cvttps_epi32();
|
||||
test_mm_cvtsi128_si64();
|
||||
|
||||
test_mm_extract_epi8();
|
||||
@ -476,6 +479,41 @@ unsafe fn test_mm256_permutevar8x32_epi32() {
|
||||
assert_eq_m256i(r, e);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "avx2")]
|
||||
#[cfg(not(jit))]
|
||||
unsafe fn test_mm_cvtps_epi32() {
|
||||
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
|
||||
|
||||
let float_vec = _mm_loadu_ps(floats.as_ptr());
|
||||
let int_vec = _mm_cvtps_epi32(float_vec);
|
||||
|
||||
let mut ints: [i32; 4] = [0; 4];
|
||||
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
|
||||
|
||||
// this is very different from `floats.map(|f| f as i32)`!
|
||||
let expected_ints: [i32; 4] = [2, -2, i32::MIN, i32::MIN];
|
||||
|
||||
assert_eq!(ints, expected_ints);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "avx2")]
|
||||
unsafe fn test_mm_cvttps_epi32() {
|
||||
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
|
||||
|
||||
let float_vec = _mm_loadu_ps(floats.as_ptr());
|
||||
let int_vec = _mm_cvttps_epi32(float_vec);
|
||||
|
||||
let mut ints: [i32; 4] = [0; 4];
|
||||
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
|
||||
|
||||
// this is very different from `floats.map(|f| f as i32)`!
|
||||
let expected_ints: [i32; 4] = [1, -2, i32::MIN, i32::MIN];
|
||||
|
||||
assert_eq!(ints, expected_ints);
|
||||
}
|
||||
|
||||
fn test_checked_mul() {
|
||||
let u: Option<u8> = u8::from_str_radix("1000", 10).ok();
|
||||
assert_eq!(u, None);
|
||||
|
@ -4,12 +4,12 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.21.0"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
|
||||
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"gimli 0.29.0",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
@ -133,6 +133,17 @@ dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
@ -147,9 +158,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.9"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
@ -189,9 +200,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.1"
|
||||
version = "0.36.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
|
||||
checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"memchr",
|
||||
@ -286,9 +297,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
@ -396,8 +407,6 @@ dependencies = [
|
||||
"core",
|
||||
"getopts",
|
||||
"libc",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"std",
|
||||
]
|
||||
|
||||
@ -430,7 +439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"gimli 0.28.1",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2024-05-13"
|
||||
channel = "nightly-2024-06-30"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools"]
|
||||
|
@ -36,9 +36,8 @@ rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR
|
||||
rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic
|
||||
|
||||
# exotic linkages
|
||||
rm tests/ui/issues/issue-33992.rs # unsupported linkages
|
||||
rm tests/incremental/hashes/function_interfaces.rs # same
|
||||
rm tests/incremental/hashes/statics.rs # same
|
||||
rm tests/incremental/hashes/function_interfaces.rs
|
||||
rm tests/incremental/hashes/statics.rs
|
||||
|
||||
# variadic arguments
|
||||
rm tests/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs
|
||||
@ -60,13 +59,20 @@ rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported
|
||||
|
||||
# requires LTO
|
||||
rm -r tests/run-make/cdylib
|
||||
rm -r tests/run-make/issue-14500
|
||||
rm -r tests/run-make/issue-64153
|
||||
rm -r tests/run-make/codegen-options-parsing
|
||||
rm -r tests/run-make/lto-*
|
||||
rm -r tests/run-make/reproducible-build-2
|
||||
rm -r tests/run-make/issue-109934-lto-debuginfo
|
||||
rm -r tests/run-make/no-builtins-lto
|
||||
rm -r tests/run-make/reachable-extern-fn-available-lto
|
||||
|
||||
# coverage instrumentation
|
||||
rm tests/ui/consts/precise-drop-with-coverage.rs
|
||||
rm tests/ui/issues/issue-85461.rs
|
||||
rm -r tests/ui/instrument-coverage/
|
||||
|
||||
# missing f16/f128 support
|
||||
rm tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
|
||||
|
||||
# optimization tests
|
||||
# ==================
|
||||
@ -74,6 +80,7 @@ rm tests/ui/codegen/issue-28950.rs # depends on stack size optimizations
|
||||
rm tests/ui/codegen/init-large-type.rs # same
|
||||
rm tests/ui/issues/issue-40883.rs # same
|
||||
rm -r tests/run-make/fmt-write-bloat/ # tests an optimization
|
||||
rm tests/ui/statics/const_generics.rs # same
|
||||
|
||||
# backend specific tests
|
||||
# ======================
|
||||
@ -85,6 +92,7 @@ rm -r tests/run-make/sepcomp-cci-copies # same
|
||||
rm -r tests/run-make/volatile-intrinsics # same
|
||||
rm -r tests/run-make/llvm-ident # same
|
||||
rm -r tests/run-make/no-builtins-attribute # same
|
||||
rm -r tests/run-make/pgo-gen-no-imp-symbols # same
|
||||
rm tests/ui/abi/stack-protector.rs # requires stack protector support
|
||||
rm -r tests/run-make/emit-stack-sizes # requires support for -Z emit-stack-sizes
|
||||
rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific
|
||||
@ -93,13 +101,14 @@ rm -r tests/run-make/print-to-output # requires --print relocation-models
|
||||
# requires asm, llvm-ir and/or llvm-bc emit support
|
||||
# =============================================
|
||||
rm -r tests/run-make/emit-named-files
|
||||
rm -r tests/run-make/issue-30063
|
||||
rm -r tests/run-make/multiple-emits
|
||||
rm -r tests/run-make/output-type-permutations
|
||||
rm -r tests/run-make/emit-to-stdout
|
||||
rm -r tests/run-make/compressed-debuginfo
|
||||
rm -r tests/run-make/symbols-include-type-name
|
||||
|
||||
rm -r tests/run-make/notify-all-emit-artifacts
|
||||
rm -r tests/run-make/reset-codegen-1
|
||||
rm -r tests/run-make/inline-always-many-cgu
|
||||
|
||||
# giving different but possibly correct results
|
||||
# =============================================
|
||||
@ -118,6 +127,7 @@ rm -r tests/run-make/compiler-builtins # Expects lib/rustlib/src/rust to contain
|
||||
# ============
|
||||
rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported
|
||||
rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort
|
||||
rm tests/ui/deprecation/deprecated_inline_threshold.rs # missing deprecation warning for -Cinline-threshold
|
||||
|
||||
# bugs in the test suite
|
||||
# ======================
|
||||
@ -148,12 +158,12 @@ index 9607ff02f96..b7d97caf9a2 100644
|
||||
--- a/src/tools/run-make-support/src/rustdoc.rs
|
||||
+++ b/src/tools/run-make-support/src/rustdoc.rs
|
||||
@@ -34,8 +34,6 @@ pub fn bare() -> Self {
|
||||
/// Construct a \`rustdoc\` invocation with \`-L \$(TARGET_RPATH_DIR)\` set.
|
||||
#[track_caller]
|
||||
pub fn new() -> Self {
|
||||
let mut cmd = setup_common();
|
||||
- let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap();
|
||||
- let target_rpath_dir = env_var_os("TARGET_RPATH_DIR");
|
||||
- cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
|
||||
Self { cmd, stdin: None }
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
EOF
|
||||
|
@ -5,8 +5,9 @@ mod pass_mode;
|
||||
mod returning;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::mem;
|
||||
|
||||
use cranelift_codegen::ir::SigRef;
|
||||
use cranelift_codegen::ir::{ArgumentPurpose, SigRef};
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use cranelift_module::ModuleError;
|
||||
use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall;
|
||||
@ -17,7 +18,7 @@ use rustc_middle::ty::TypeVisitableExt;
|
||||
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::abi::call::{Conv, FnAbi};
|
||||
use rustc_target::abi::call::{Conv, FnAbi, PassMode};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use self::pass_mode::*;
|
||||
@ -370,9 +371,14 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||
|
||||
// Handle special calls like intrinsics and empty drop glue.
|
||||
let instance = if let ty::FnDef(def_id, fn_args) = *func.layout().ty.kind() {
|
||||
let instance =
|
||||
ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, fn_args)
|
||||
.polymorphize(fx.tcx);
|
||||
let instance = ty::Instance::expect_resolve(
|
||||
fx.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
def_id,
|
||||
fn_args,
|
||||
source_info.span,
|
||||
)
|
||||
.polymorphize(fx.tcx);
|
||||
|
||||
if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) {
|
||||
if target.is_some() {
|
||||
@ -487,6 +493,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||
let args = args;
|
||||
assert_eq!(fn_abi.args.len(), args.len());
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum CallTarget {
|
||||
Direct(FuncRef),
|
||||
Indirect(SigRef, Value),
|
||||
@ -532,7 +539,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||
};
|
||||
|
||||
self::returning::codegen_with_call_return_arg(fx, &fn_abi.ret, ret_place, |fx, return_ptr| {
|
||||
let call_args = return_ptr
|
||||
let mut call_args = return_ptr
|
||||
.into_iter()
|
||||
.chain(first_arg_override.into_iter())
|
||||
.chain(
|
||||
@ -545,40 +552,17 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||
)
|
||||
.collect::<Vec<Value>>();
|
||||
|
||||
let call_inst = match func_ref {
|
||||
// FIXME: Find a cleaner way to support varargs.
|
||||
if fn_abi.c_variadic {
|
||||
adjust_call_for_c_variadic(fx, &fn_abi, source_info, func_ref, &mut call_args);
|
||||
}
|
||||
|
||||
match func_ref {
|
||||
CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args),
|
||||
CallTarget::Indirect(sig, func_ptr) => {
|
||||
fx.bcx.ins().call_indirect(sig, func_ptr, &call_args)
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME find a cleaner way to support varargs
|
||||
if fn_sig.c_variadic() {
|
||||
if !matches!(fn_sig.abi(), Abi::C { .. }) {
|
||||
fx.tcx.dcx().span_fatal(
|
||||
source_info.span,
|
||||
format!("Variadic call for non-C abi {:?}", fn_sig.abi()),
|
||||
);
|
||||
}
|
||||
let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
|
||||
let abi_params = call_args
|
||||
.into_iter()
|
||||
.map(|arg| {
|
||||
let ty = fx.bcx.func.dfg.value_type(arg);
|
||||
if !ty.is_int() {
|
||||
// FIXME set %al to upperbound on float args once floats are supported
|
||||
fx.tcx.dcx().span_fatal(
|
||||
source_info.span,
|
||||
format!("Non int ty {:?} for variadic call", ty),
|
||||
);
|
||||
}
|
||||
AbiParam::new(ty)
|
||||
})
|
||||
.collect::<Vec<AbiParam>>();
|
||||
fx.bcx.func.dfg.signatures[sig_ref].params = abi_params;
|
||||
}
|
||||
|
||||
call_inst
|
||||
});
|
||||
|
||||
if let Some(dest) = target {
|
||||
@ -587,6 +571,100 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||
} else {
|
||||
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
|
||||
}
|
||||
|
||||
fn adjust_call_for_c_variadic<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
source_info: mir::SourceInfo,
|
||||
target: CallTarget,
|
||||
call_args: &mut Vec<Value>,
|
||||
) {
|
||||
if fn_abi.conv != Conv::C {
|
||||
fx.tcx.dcx().span_fatal(
|
||||
source_info.span,
|
||||
format!("Variadic call for non-C abi {:?}", fn_abi.conv),
|
||||
);
|
||||
}
|
||||
let sig_ref = match target {
|
||||
CallTarget::Direct(func_ref) => fx.bcx.func.dfg.ext_funcs[func_ref].signature,
|
||||
CallTarget::Indirect(sig_ref, _) => sig_ref,
|
||||
};
|
||||
// `mem::take()` the `params` so that `fx.bcx` can be used below.
|
||||
let mut abi_params = mem::take(&mut fx.bcx.func.dfg.signatures[sig_ref].params);
|
||||
|
||||
// Recalculate the parameters in the signature to ensure the signature contains the variadic arguments.
|
||||
let has_return_arg = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
// Drop everything except the return argument (if there is one).
|
||||
abi_params.truncate(if has_return_arg { 1 } else { 0 });
|
||||
// Add the fixed arguments.
|
||||
abi_params.extend(
|
||||
fn_abi.args[..fn_abi.fixed_count as usize]
|
||||
.iter()
|
||||
.flat_map(|arg_abi| arg_abi.get_abi_param(fx.tcx).into_iter()),
|
||||
);
|
||||
let fixed_arg_count = abi_params.len();
|
||||
// Add the variadic arguments.
|
||||
abi_params.extend(
|
||||
fn_abi.args[fn_abi.fixed_count as usize..]
|
||||
.iter()
|
||||
.flat_map(|arg_abi| arg_abi.get_abi_param(fx.tcx).into_iter()),
|
||||
);
|
||||
|
||||
if fx.tcx.sess.target.is_like_osx && fx.tcx.sess.target.arch == "aarch64" {
|
||||
// Add any padding arguments needed for Apple AArch64.
|
||||
// There's no need to pad the argument list unless variadic arguments are actually being
|
||||
// passed.
|
||||
if abi_params.len() > fixed_arg_count {
|
||||
// 128-bit integers take 2 registers, and everything else takes 1.
|
||||
// FIXME: Add support for non-integer types
|
||||
// This relies on the checks below to ensure all arguments are integer types and
|
||||
// that the ABI is "C".
|
||||
// The return argument isn't counted as it goes in its own dedicated register.
|
||||
let integer_registers_used: usize = abi_params
|
||||
[if has_return_arg { 1 } else { 0 }..fixed_arg_count]
|
||||
.iter()
|
||||
.map(|arg| if arg.value_type.bits() == 128 { 2 } else { 1 })
|
||||
.sum();
|
||||
// The ABI uses 8 registers before it starts pushing arguments to the stack. Pad out
|
||||
// the registers if needed to ensure the variadic arguments are passed on the stack.
|
||||
if integer_registers_used < 8 {
|
||||
abi_params.splice(
|
||||
fixed_arg_count..fixed_arg_count,
|
||||
(integer_registers_used..8).map(|_| AbiParam::new(types::I64)),
|
||||
);
|
||||
call_args.splice(
|
||||
fixed_arg_count..fixed_arg_count,
|
||||
(integer_registers_used..8).map(|_| fx.bcx.ins().iconst(types::I64, 0)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// `StructArgument` is not currently used by the `aarch64` ABI, and is therefore not
|
||||
// handled when calculating how many padding arguments to use. Assert that this remains
|
||||
// the case.
|
||||
assert!(abi_params.iter().all(|param| matches!(
|
||||
param.purpose,
|
||||
// The only purposes used are `Normal` and `StructReturn`.
|
||||
ArgumentPurpose::Normal | ArgumentPurpose::StructReturn
|
||||
)));
|
||||
}
|
||||
|
||||
// Check all parameters are integers.
|
||||
for param in abi_params.iter() {
|
||||
if !param.value_type.is_int() {
|
||||
// FIXME: Set %al to upperbound on float args once floats are supported.
|
||||
fx.tcx.dcx().span_fatal(
|
||||
source_info.span,
|
||||
format!("Non int ty {:?} for variadic call", param.value_type),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(abi_params.len(), call_args.len());
|
||||
|
||||
// Put the `AbiParam`s back in the signature.
|
||||
fx.bcx.func.dfg.signatures[sig_ref].params = abi_params;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn codegen_drop<'tcx>(
|
||||
|
@ -11,15 +11,10 @@ use rustc_session::config::OomStrategy;
|
||||
use crate::prelude::*;
|
||||
|
||||
/// Returns whether an allocator shim was created
|
||||
pub(crate) fn codegen(
|
||||
tcx: TyCtxt<'_>,
|
||||
module: &mut impl Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
) -> bool {
|
||||
pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
|
||||
let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
|
||||
codegen_inner(
|
||||
module,
|
||||
unwind_context,
|
||||
kind,
|
||||
tcx.alloc_error_handler_kind(()).unwrap(),
|
||||
tcx.sess.opts.unstable_opts.oom,
|
||||
@ -28,8 +23,7 @@ pub(crate) fn codegen(
|
||||
}
|
||||
|
||||
fn codegen_inner(
|
||||
module: &mut impl Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
module: &mut dyn Module,
|
||||
kind: AllocatorKind,
|
||||
alloc_error_handler_kind: AllocatorKind,
|
||||
oom_strategy: OomStrategy,
|
||||
@ -67,7 +61,6 @@ fn codegen_inner(
|
||||
};
|
||||
crate::common::create_wrapper_function(
|
||||
module,
|
||||
unwind_context,
|
||||
sig,
|
||||
&global_fn_name(method.name),
|
||||
&default_fn_name(method.name),
|
||||
@ -82,7 +75,6 @@ fn codegen_inner(
|
||||
};
|
||||
crate::common::create_wrapper_function(
|
||||
module,
|
||||
unwind_context,
|
||||
sig,
|
||||
"__rust_alloc_error_handler",
|
||||
&alloc_error_handler_name(alloc_error_handler_kind),
|
||||
|
@ -249,9 +249,7 @@ pub(crate) fn compile_fn(
|
||||
}
|
||||
|
||||
// Define debuginfo for function
|
||||
let isa = module.isa();
|
||||
let debug_context = &mut cx.debug_context;
|
||||
let unwind_context = &mut cx.unwind_context;
|
||||
cx.profiler.generic_activity("generate debug info").run(|| {
|
||||
if let Some(debug_context) = debug_context {
|
||||
codegened_func.func_debug_cx.unwrap().finalize(
|
||||
@ -260,7 +258,6 @@ pub(crate) fn compile_fn(
|
||||
context,
|
||||
);
|
||||
}
|
||||
unwind_context.add_function(codegened_func.func_id, &context, isa);
|
||||
});
|
||||
}
|
||||
|
||||
@ -494,6 +491,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
|
||||
)
|
||||
});
|
||||
}
|
||||
// FIXME(explicit_tail_calls): add support for tail calls to the cranelift backend, once cranelift supports tail calls
|
||||
TerminatorKind::TailCall { fn_span, .. } => span_bug!(
|
||||
*fn_span,
|
||||
"tail calls are not yet supported in `rustc_codegen_cranelift` backend"
|
||||
),
|
||||
TerminatorKind::InlineAsm {
|
||||
template,
|
||||
operands,
|
||||
@ -909,7 +911,7 @@ fn codegen_stmt<'tcx>(
|
||||
| StatementKind::PlaceMention(..)
|
||||
| StatementKind::AscribeUserType(..) => {}
|
||||
|
||||
StatementKind::Coverage { .. } => fx.tcx.dcx().fatal("-Zcoverage is unimplemented"),
|
||||
StatementKind::Coverage { .. } => unreachable!(),
|
||||
StatementKind::Intrinsic(ref intrinsic) => match &**intrinsic {
|
||||
// We ignore `assume` intrinsics, they are only useful for optimizations
|
||||
NonDivergingIntrinsic::Assume(_) => {}
|
||||
|
@ -247,7 +247,6 @@ pub(crate) fn type_sign(ty: Ty<'_>) -> bool {
|
||||
|
||||
pub(crate) fn create_wrapper_function(
|
||||
module: &mut dyn Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
sig: Signature,
|
||||
wrapper_name: &str,
|
||||
callee_name: &str,
|
||||
@ -280,7 +279,6 @@ pub(crate) fn create_wrapper_function(
|
||||
bcx.finalize();
|
||||
}
|
||||
module.define_function(wrapper_func_id, &mut ctx).unwrap();
|
||||
unwind_context.add_function(wrapper_func_id, &ctx, module.isa());
|
||||
}
|
||||
|
||||
pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
|
||||
@ -395,6 +393,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
||||
// FIXME Don't force the size to a multiple of <abi_align> bytes once Cranelift gets
|
||||
// a way to specify stack slot alignment.
|
||||
size: (size + abi_align - 1) / abi_align * abi_align,
|
||||
align_shift: 4,
|
||||
});
|
||||
Pointer::stack_slot(stack_slot)
|
||||
} else {
|
||||
@ -405,6 +404,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
||||
// FIXME Don't force the size to a multiple of <abi_align> bytes once Cranelift gets
|
||||
// a way to specify stack slot alignment.
|
||||
size: (size + align) / abi_align * abi_align,
|
||||
align_shift: 4,
|
||||
});
|
||||
let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0);
|
||||
let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align));
|
||||
|
@ -155,7 +155,7 @@ pub(crate) fn codegen_const_value<'tcx>(
|
||||
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
|
||||
}
|
||||
}
|
||||
GlobalAlloc::Function(instance) => {
|
||||
GlobalAlloc::Function { instance, .. } => {
|
||||
let func_id = crate::abi::import_function(fx.tcx, fx.module, instance);
|
||||
let local_func_id =
|
||||
fx.module.declare_func_in_func(func_id, &mut fx.bcx.func);
|
||||
@ -351,7 +351,9 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
||||
TodoItem::Alloc(alloc_id) => {
|
||||
let alloc = match tcx.global_alloc(alloc_id) {
|
||||
GlobalAlloc::Memory(alloc) => alloc,
|
||||
GlobalAlloc::Function(_) | GlobalAlloc::Static(_) | GlobalAlloc::VTable(..) => {
|
||||
GlobalAlloc::Function { .. }
|
||||
| GlobalAlloc::Static(_)
|
||||
| GlobalAlloc::VTable(..) => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
@ -415,7 +417,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
||||
|
||||
let reloc_target_alloc = tcx.global_alloc(alloc_id);
|
||||
let data_id = match reloc_target_alloc {
|
||||
GlobalAlloc::Function(instance) => {
|
||||
GlobalAlloc::Function { instance, .. } => {
|
||||
assert_eq!(addend, 0);
|
||||
let func_id =
|
||||
crate::abi::import_function(tcx, module, instance.polymorphize(tcx));
|
||||
@ -565,6 +567,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
|
||||
{
|
||||
return None;
|
||||
}
|
||||
TerminatorKind::TailCall { .. } => return None,
|
||||
TerminatorKind::Call { .. } => {}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ use rustc_session::Session;
|
||||
use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken};
|
||||
use crate::debuginfo::TypeDebugContext;
|
||||
use crate::global_asm::GlobalAsmConfig;
|
||||
use crate::unwind_module::UnwindModule;
|
||||
use crate::{prelude::*, BackendConfig};
|
||||
|
||||
struct ModuleCodegenResult {
|
||||
@ -318,7 +319,11 @@ fn produce_final_output_artifacts(
|
||||
// These are used in linking steps and will be cleaned up afterward.
|
||||
}
|
||||
|
||||
fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> ObjectModule {
|
||||
fn make_module(
|
||||
sess: &Session,
|
||||
backend_config: &BackendConfig,
|
||||
name: String,
|
||||
) -> UnwindModule<ObjectModule> {
|
||||
let isa = crate::build_isa(sess, backend_config);
|
||||
|
||||
let mut builder =
|
||||
@ -327,16 +332,15 @@ fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) ->
|
||||
// is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections
|
||||
// can easily double the amount of time necessary to perform linking.
|
||||
builder.per_function_section(sess.opts.unstable_opts.function_sections.unwrap_or(false));
|
||||
ObjectModule::new(builder)
|
||||
UnwindModule::new(ObjectModule::new(builder), true)
|
||||
}
|
||||
|
||||
fn emit_cgu(
|
||||
output_filenames: &OutputFilenames,
|
||||
prof: &SelfProfilerRef,
|
||||
name: String,
|
||||
module: ObjectModule,
|
||||
module: UnwindModule<ObjectModule>,
|
||||
debug: Option<DebugContext>,
|
||||
unwind_context: UnwindContext,
|
||||
global_asm_object_file: Option<PathBuf>,
|
||||
producer: &str,
|
||||
) -> Result<ModuleCodegenResult, String> {
|
||||
@ -346,8 +350,6 @@ fn emit_cgu(
|
||||
debug.emit(&mut product);
|
||||
}
|
||||
|
||||
unwind_context.emit(&mut product);
|
||||
|
||||
let module_regular = emit_module(
|
||||
output_filenames,
|
||||
prof,
|
||||
@ -494,7 +496,6 @@ fn module_codegen(
|
||||
|
||||
let mut cx = crate::CodegenCx::new(
|
||||
tcx,
|
||||
backend_config.clone(),
|
||||
module.isa(),
|
||||
tcx.sess.opts.debuginfo != DebugInfo::None,
|
||||
cgu_name,
|
||||
@ -531,13 +532,7 @@ fn module_codegen(
|
||||
}
|
||||
}
|
||||
}
|
||||
crate::main_shim::maybe_create_entry_wrapper(
|
||||
tcx,
|
||||
&mut module,
|
||||
&mut cx.unwind_context,
|
||||
false,
|
||||
cgu.is_primary(),
|
||||
);
|
||||
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, false, cgu.is_primary());
|
||||
|
||||
let cgu_name = cgu.name().as_str().to_owned();
|
||||
|
||||
@ -571,7 +566,6 @@ fn module_codegen(
|
||||
cgu_name,
|
||||
module,
|
||||
cx.debug_context,
|
||||
cx.unwind_context,
|
||||
global_asm_object_file,
|
||||
&producer,
|
||||
)
|
||||
@ -665,13 +659,10 @@ pub(crate) fn run_aot(
|
||||
});
|
||||
|
||||
let mut allocator_module = make_module(tcx.sess, &backend_config, "allocator_shim".to_string());
|
||||
let mut allocator_unwind_context = UnwindContext::new(allocator_module.isa(), true);
|
||||
let created_alloc_shim =
|
||||
crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context);
|
||||
let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module);
|
||||
|
||||
let allocator_module = if created_alloc_shim {
|
||||
let mut product = allocator_module.finish();
|
||||
allocator_unwind_context.emit(&mut product);
|
||||
let product = allocator_module.finish();
|
||||
|
||||
match emit_module(
|
||||
tcx.output_filenames(()),
|
||||
|
@ -14,12 +14,12 @@ use rustc_session::Session;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
use crate::debuginfo::TypeDebugContext;
|
||||
use crate::unwind_module::UnwindModule;
|
||||
use crate::{prelude::*, BackendConfig};
|
||||
use crate::{CodegenCx, CodegenMode};
|
||||
|
||||
struct JitState {
|
||||
backend_config: BackendConfig,
|
||||
jit_module: JITModule,
|
||||
jit_module: UnwindModule<JITModule>,
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
@ -63,7 +63,7 @@ fn create_jit_module(
|
||||
tcx: TyCtxt<'_>,
|
||||
backend_config: &BackendConfig,
|
||||
hotswap: bool,
|
||||
) -> (JITModule, CodegenCx) {
|
||||
) -> (UnwindModule<JITModule>, CodegenCx) {
|
||||
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
|
||||
|
||||
let isa = crate::build_isa(tcx.sess, backend_config);
|
||||
@ -72,17 +72,11 @@ fn create_jit_module(
|
||||
crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
|
||||
jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info));
|
||||
jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
|
||||
let mut jit_module = JITModule::new(jit_builder);
|
||||
let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false);
|
||||
|
||||
let mut cx = crate::CodegenCx::new(
|
||||
tcx,
|
||||
backend_config.clone(),
|
||||
jit_module.isa(),
|
||||
false,
|
||||
Symbol::intern("dummy_cgu_name"),
|
||||
);
|
||||
let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, Symbol::intern("dummy_cgu_name"));
|
||||
|
||||
crate::allocator::codegen(tcx, &mut jit_module, &mut cx.unwind_context);
|
||||
crate::allocator::codegen(tcx, &mut jit_module);
|
||||
|
||||
(jit_module, cx)
|
||||
}
|
||||
@ -128,7 +122,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
|
||||
);
|
||||
}
|
||||
CodegenMode::JitLazy => {
|
||||
codegen_shim(tcx, &mut cx, &mut cached_context, &mut jit_module, inst)
|
||||
codegen_shim(tcx, &mut cached_context, &mut jit_module, inst)
|
||||
}
|
||||
},
|
||||
MonoItem::Static(def_id) => {
|
||||
@ -146,18 +140,11 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
|
||||
tcx.dcx().fatal("Inline asm is not supported in JIT mode");
|
||||
}
|
||||
|
||||
crate::main_shim::maybe_create_entry_wrapper(
|
||||
tcx,
|
||||
&mut jit_module,
|
||||
&mut cx.unwind_context,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, true, true);
|
||||
|
||||
tcx.dcx().abort_if_errors();
|
||||
|
||||
jit_module.finalize_definitions().unwrap();
|
||||
unsafe { cx.unwind_context.register_jit(&jit_module) };
|
||||
jit_module.finalize_definitions();
|
||||
|
||||
println!(
|
||||
"Rustc codegen cranelift will JIT run the executable, because -Cllvm-args=mode=jit was passed"
|
||||
@ -177,12 +164,12 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
|
||||
call_conv: jit_module.target_config().default_call_conv,
|
||||
};
|
||||
let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap();
|
||||
let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id);
|
||||
let finalized_start: *const u8 = jit_module.module.get_finalized_function(start_func_id);
|
||||
|
||||
LAZY_JIT_STATE.with(|lazy_jit_state| {
|
||||
let mut lazy_jit_state = lazy_jit_state.borrow_mut();
|
||||
assert!(lazy_jit_state.is_none());
|
||||
*lazy_jit_state = Some(JitState { backend_config, jit_module });
|
||||
*lazy_jit_state = Some(JitState { jit_module });
|
||||
});
|
||||
|
||||
let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
|
||||
@ -268,7 +255,6 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
||||
let mut lazy_jit_state = lazy_jit_state.borrow_mut();
|
||||
let lazy_jit_state = lazy_jit_state.as_mut().unwrap();
|
||||
let jit_module = &mut lazy_jit_state.jit_module;
|
||||
let backend_config = lazy_jit_state.backend_config.clone();
|
||||
|
||||
let name = tcx.symbol_name(instance).name;
|
||||
let sig = crate::abi::get_function_sig(
|
||||
@ -278,7 +264,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
||||
);
|
||||
let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
|
||||
|
||||
let current_ptr = jit_module.read_got_entry(func_id);
|
||||
let current_ptr = jit_module.module.read_got_entry(func_id);
|
||||
|
||||
// If the function's GOT entry has already been updated to point at something other
|
||||
// than the shim trampoline, don't re-jit but just return the new pointer instead.
|
||||
@ -288,11 +274,10 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
||||
return current_ptr;
|
||||
}
|
||||
|
||||
jit_module.prepare_for_function_redefine(func_id).unwrap();
|
||||
jit_module.module.prepare_for_function_redefine(func_id).unwrap();
|
||||
|
||||
let mut cx = crate::CodegenCx::new(
|
||||
tcx,
|
||||
backend_config,
|
||||
jit_module.isa(),
|
||||
false,
|
||||
Symbol::intern("dummy_cgu_name"),
|
||||
@ -300,9 +285,8 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
||||
codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance);
|
||||
|
||||
assert!(cx.global_asm.is_empty());
|
||||
jit_module.finalize_definitions().unwrap();
|
||||
unsafe { cx.unwind_context.register_jit(&jit_module) };
|
||||
jit_module.get_finalized_function(func_id)
|
||||
jit_module.finalize_definitions();
|
||||
jit_module.module.get_finalized_function(func_id)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -310,7 +294,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
||||
fn dep_symbol_lookup_fn(
|
||||
sess: &Session,
|
||||
crate_info: CrateInfo,
|
||||
) -> Box<dyn Fn(&str) -> Option<*const u8>> {
|
||||
) -> Box<dyn Fn(&str) -> Option<*const u8> + Send> {
|
||||
use rustc_middle::middle::dependency_format::Linkage;
|
||||
|
||||
let mut dylib_paths = Vec::new();
|
||||
@ -362,9 +346,8 @@ fn dep_symbol_lookup_fn(
|
||||
|
||||
fn codegen_shim<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cx: &mut CodegenCx,
|
||||
cached_context: &mut Context,
|
||||
module: &mut JITModule,
|
||||
module: &mut UnwindModule<JITModule>,
|
||||
inst: Instance<'tcx>,
|
||||
) {
|
||||
let pointer_type = module.target_config().pointer_type();
|
||||
@ -413,5 +396,4 @@ fn codegen_shim<'tcx>(
|
||||
trampoline_builder.ins().return_(&ret_vals);
|
||||
|
||||
module.define_function(func_id, context).unwrap();
|
||||
cx.unwind_context.add_function(func_id, context, module.isa());
|
||||
}
|
||||
|
@ -113,13 +113,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
|
||||
);
|
||||
let sig =
|
||||
get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance);
|
||||
create_wrapper_function(
|
||||
fx.module,
|
||||
&mut fx.cx.unwind_context,
|
||||
sig,
|
||||
&wrapper_name,
|
||||
symbol.name,
|
||||
);
|
||||
create_wrapper_function(fx.module, sig, &wrapper_name, symbol.name);
|
||||
|
||||
CInlineAsmOperand::Symbol { symbol: wrapper_name }
|
||||
} else {
|
||||
@ -283,13 +277,7 @@ pub(crate) fn codegen_naked_asm<'tcx>(
|
||||
);
|
||||
let sig =
|
||||
get_function_sig(tcx, module.target_config().default_call_conv, instance);
|
||||
create_wrapper_function(
|
||||
module,
|
||||
&mut cx.unwind_context,
|
||||
sig,
|
||||
&wrapper_name,
|
||||
symbol.name,
|
||||
);
|
||||
create_wrapper_function(module, sig, &wrapper_name, symbol.name);
|
||||
|
||||
CInlineAsmOperand::Symbol { symbol: wrapper_name }
|
||||
} else {
|
||||
|
@ -459,11 +459,20 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
||||
intrinsic_args!(fx, args => (a); intrinsic);
|
||||
let a = a.load_scalar(fx);
|
||||
|
||||
let value = fx.bcx.ins().x86_cvtt2dq(types::I32X4, a);
|
||||
let cvalue = CValue::by_val(value, ret.layout());
|
||||
ret.write_cvalue(fx, cvalue);
|
||||
}
|
||||
"llvm.x86.sse2.cvtps2dq" => {
|
||||
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtps_epi32
|
||||
intrinsic_args!(fx, args => (a); intrinsic);
|
||||
let a = a.load_scalar(fx);
|
||||
|
||||
// Using inline asm instead of fcvt_to_sint_sat as unrepresentable values are turned
|
||||
// into 0x80000000 for which Cranelift doesn't have a native instruction.
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String(format!("cvttps2dq xmm0, xmm0"))],
|
||||
&[InlineAsmTemplatePiece::String(format!("cvtps2dq xmm0, xmm0"))],
|
||||
&[CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
_late: true,
|
||||
@ -1416,6 +1425,36 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
||||
ret.write_cvalue(fx, res);
|
||||
}
|
||||
|
||||
"llvm.x86.rdtsc" => {
|
||||
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_rdtsc&ig_expand=5273
|
||||
|
||||
let res_place = CPlace::new_stack_slot(
|
||||
fx,
|
||||
fx.layout_of(Ty::new_tup(fx.tcx, &[fx.tcx.types.u32, fx.tcx.types.u32])),
|
||||
);
|
||||
let eax_place = res_place.place_field(fx, FieldIdx::new(0));
|
||||
let edx_place = res_place.place_field(fx, FieldIdx::new(1));
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("rdtsc".to_string())],
|
||||
&[
|
||||
CInlineAsmOperand::Out {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
|
||||
late: true,
|
||||
place: Some(eax_place),
|
||||
},
|
||||
CInlineAsmOperand::Out {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
|
||||
late: true,
|
||||
place: Some(edx_place),
|
||||
},
|
||||
],
|
||||
InlineAsmOptions::NOSTACK | InlineAsmOptions::NOMEM,
|
||||
);
|
||||
let res = res_place.to_cvalue(fx);
|
||||
ret.write_cvalue_transmute(fx, res);
|
||||
}
|
||||
|
||||
_ => {
|
||||
fx.tcx
|
||||
.dcx()
|
||||
|
@ -79,6 +79,7 @@ mod pretty_clif;
|
||||
mod toolchain;
|
||||
mod trap;
|
||||
mod unsize;
|
||||
mod unwind_module;
|
||||
mod value_and_place;
|
||||
mod vtable;
|
||||
|
||||
@ -130,22 +131,13 @@ struct CodegenCx {
|
||||
global_asm: String,
|
||||
inline_asm_index: Cell<usize>,
|
||||
debug_context: Option<DebugContext>,
|
||||
unwind_context: UnwindContext,
|
||||
cgu_name: Symbol,
|
||||
}
|
||||
|
||||
impl CodegenCx {
|
||||
fn new(
|
||||
tcx: TyCtxt<'_>,
|
||||
backend_config: BackendConfig,
|
||||
isa: &dyn TargetIsa,
|
||||
debug_info: bool,
|
||||
cgu_name: Symbol,
|
||||
) -> Self {
|
||||
fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, debug_info: bool, cgu_name: Symbol) -> Self {
|
||||
assert_eq!(pointer_ty(tcx), isa.pointer_type());
|
||||
|
||||
let unwind_context =
|
||||
UnwindContext::new(isa, matches!(backend_config.codegen_mode, CodegenMode::Aot));
|
||||
let debug_context = if debug_info && !tcx.sess.target.options.is_like_windows {
|
||||
Some(DebugContext::new(tcx, isa, cgu_name.as_str()))
|
||||
} else {
|
||||
@ -158,7 +150,6 @@ impl CodegenCx {
|
||||
global_asm: String::new(),
|
||||
inline_asm_index: Cell::new(0),
|
||||
debug_context,
|
||||
unwind_context,
|
||||
cgu_name,
|
||||
}
|
||||
}
|
||||
@ -175,7 +166,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
||||
}
|
||||
|
||||
fn init(&self, sess: &Session) {
|
||||
use rustc_session::config::Lto;
|
||||
use rustc_session::config::{InstrumentCoverage, Lto};
|
||||
match sess.lto() {
|
||||
Lto::No | Lto::ThinLocal => {}
|
||||
Lto::Thin | Lto::Fat => {
|
||||
@ -183,6 +174,11 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
||||
}
|
||||
}
|
||||
|
||||
if sess.opts.cg.instrument_coverage() != InstrumentCoverage::No {
|
||||
sess.dcx()
|
||||
.fatal("`-Cinstrument-coverage` is LLVM specific and not supported by Cranelift");
|
||||
}
|
||||
|
||||
let mut config = self.config.borrow_mut();
|
||||
if config.is_none() {
|
||||
let new_config = BackendConfig::from_opts(&sess.opts.cg.llvm_args)
|
||||
@ -271,9 +267,9 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn TargetIs
|
||||
flags_builder.set("enable_verifier", enable_verifier).unwrap();
|
||||
flags_builder.set("regalloc_checker", enable_verifier).unwrap();
|
||||
|
||||
let preserve_frame_pointer = sess.target.options.frame_pointer
|
||||
!= rustc_target::spec::FramePointer::MayOmit
|
||||
|| matches!(sess.opts.cg.force_frame_pointers, Some(true));
|
||||
let mut frame_ptr = sess.target.options.frame_pointer.clone();
|
||||
frame_ptr.ratchet(sess.opts.cg.force_frame_pointers);
|
||||
let preserve_frame_pointer = frame_ptr != rustc_target::spec::FramePointer::MayOmit;
|
||||
flags_builder
|
||||
.set("preserve_frame_pointers", if preserve_frame_pointer { "true" } else { "false" })
|
||||
.unwrap();
|
||||
|
@ -4,6 +4,7 @@ use rustc_middle::ty::AssocKind;
|
||||
use rustc_middle::ty::GenericArg;
|
||||
use rustc_session::config::{sigpipe, EntryFnType};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
@ -11,8 +12,7 @@ use crate::prelude::*;
|
||||
/// users main function.
|
||||
pub(crate) fn maybe_create_entry_wrapper(
|
||||
tcx: TyCtxt<'_>,
|
||||
module: &mut impl Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
module: &mut dyn Module,
|
||||
is_jit: bool,
|
||||
is_primary_cgu: bool,
|
||||
) {
|
||||
@ -36,12 +36,11 @@ pub(crate) fn maybe_create_entry_wrapper(
|
||||
return;
|
||||
}
|
||||
|
||||
create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn, sigpipe);
|
||||
create_entry_fn(tcx, module, main_def_id, is_jit, is_main_fn, sigpipe);
|
||||
|
||||
fn create_entry_fn(
|
||||
tcx: TyCtxt<'_>,
|
||||
m: &mut impl Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
m: &mut dyn Module,
|
||||
rust_main_def_id: DefId,
|
||||
ignore_lang_start_wrapper: bool,
|
||||
is_main_fn: bool,
|
||||
@ -121,6 +120,7 @@ pub(crate) fn maybe_create_entry_wrapper(
|
||||
ParamEnv::reveal_all(),
|
||||
report.def_id,
|
||||
tcx.mk_args(&[GenericArg::from(main_ret_ty)]),
|
||||
DUMMY_SP,
|
||||
)
|
||||
.polymorphize(tcx);
|
||||
|
||||
@ -146,6 +146,7 @@ pub(crate) fn maybe_create_entry_wrapper(
|
||||
ParamEnv::reveal_all(),
|
||||
start_def_id,
|
||||
tcx.mk_args(&[main_ret_ty.into()]),
|
||||
DUMMY_SP,
|
||||
)
|
||||
.polymorphize(tcx);
|
||||
let start_func_id = import_function(tcx, m, start_instance);
|
||||
@ -170,7 +171,5 @@ pub(crate) fn maybe_create_entry_wrapper(
|
||||
if let Err(err) = m.define_function(cmain_func_id, &mut ctx) {
|
||||
tcx.dcx().fatal(format!("entry symbol `{entry_name}` defined multiple times: {err}"));
|
||||
}
|
||||
|
||||
unwind_context.add_function(cmain_func_id, &ctx, m.isa());
|
||||
}
|
||||
}
|
||||
|
115
compiler/rustc_codegen_cranelift/src/unwind_module.rs
Normal file
115
compiler/rustc_codegen_cranelift/src/unwind_module.rs
Normal file
@ -0,0 +1,115 @@
|
||||
use cranelift_codegen::control::ControlPlane;
|
||||
use cranelift_codegen::ir::{Function, Signature};
|
||||
use cranelift_codegen::isa::{TargetFrontendConfig, TargetIsa};
|
||||
use cranelift_codegen::{Context, FinalizedMachReloc};
|
||||
use cranelift_module::{
|
||||
DataDescription, DataId, FuncId, FuncOrDataId, Linkage, Module, ModuleDeclarations,
|
||||
ModuleResult,
|
||||
};
|
||||
use cranelift_object::{ObjectModule, ObjectProduct};
|
||||
|
||||
use crate::UnwindContext;
|
||||
|
||||
/// A wrapper around a [Module] which adds any defined function to the [UnwindContext].
|
||||
pub(crate) struct UnwindModule<T> {
|
||||
pub(crate) module: T,
|
||||
unwind_context: UnwindContext,
|
||||
}
|
||||
|
||||
impl<T: Module> UnwindModule<T> {
|
||||
pub(crate) fn new(module: T, pic_eh_frame: bool) -> Self {
|
||||
let unwind_context = UnwindContext::new(module.isa(), pic_eh_frame);
|
||||
UnwindModule { module, unwind_context }
|
||||
}
|
||||
}
|
||||
|
||||
impl UnwindModule<ObjectModule> {
|
||||
pub(crate) fn finish(self) -> ObjectProduct {
|
||||
let mut product = self.module.finish();
|
||||
self.unwind_context.emit(&mut product);
|
||||
product
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "jit")]
|
||||
impl UnwindModule<cranelift_jit::JITModule> {
|
||||
pub(crate) fn finalize_definitions(&mut self) {
|
||||
self.module.finalize_definitions().unwrap();
|
||||
let prev_unwind_context = std::mem::replace(
|
||||
&mut self.unwind_context,
|
||||
UnwindContext::new(self.module.isa(), false),
|
||||
);
|
||||
unsafe { prev_unwind_context.register_jit(&self.module) };
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Module> Module for UnwindModule<T> {
|
||||
fn isa(&self) -> &dyn TargetIsa {
|
||||
self.module.isa()
|
||||
}
|
||||
|
||||
fn declarations(&self) -> &ModuleDeclarations {
|
||||
self.module.declarations()
|
||||
}
|
||||
|
||||
fn get_name(&self, name: &str) -> Option<FuncOrDataId> {
|
||||
self.module.get_name(name)
|
||||
}
|
||||
|
||||
fn target_config(&self) -> TargetFrontendConfig {
|
||||
self.module.target_config()
|
||||
}
|
||||
|
||||
fn declare_function(
|
||||
&mut self,
|
||||
name: &str,
|
||||
linkage: Linkage,
|
||||
signature: &Signature,
|
||||
) -> ModuleResult<FuncId> {
|
||||
self.module.declare_function(name, linkage, signature)
|
||||
}
|
||||
|
||||
fn declare_anonymous_function(&mut self, signature: &Signature) -> ModuleResult<FuncId> {
|
||||
self.module.declare_anonymous_function(signature)
|
||||
}
|
||||
|
||||
fn declare_data(
|
||||
&mut self,
|
||||
name: &str,
|
||||
linkage: Linkage,
|
||||
writable: bool,
|
||||
tls: bool,
|
||||
) -> ModuleResult<DataId> {
|
||||
self.module.declare_data(name, linkage, writable, tls)
|
||||
}
|
||||
|
||||
fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {
|
||||
self.module.declare_anonymous_data(writable, tls)
|
||||
}
|
||||
|
||||
fn define_function_with_control_plane(
|
||||
&mut self,
|
||||
func: FuncId,
|
||||
ctx: &mut Context,
|
||||
ctrl_plane: &mut ControlPlane,
|
||||
) -> ModuleResult<()> {
|
||||
self.module.define_function_with_control_plane(func, ctx, ctrl_plane)?;
|
||||
self.unwind_context.add_function(func, ctx, self.module.isa());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn define_function_bytes(
|
||||
&mut self,
|
||||
_func_id: FuncId,
|
||||
_func: &Function,
|
||||
_alignment: u64,
|
||||
_bytes: &[u8],
|
||||
_relocs: &[FinalizedMachReloc],
|
||||
) -> ModuleResult<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> {
|
||||
self.module.define_data(data_id, data)
|
||||
}
|
||||
}
|
@ -49,11 +49,11 @@ jobs:
|
||||
# `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests.
|
||||
run: sudo apt-get install ninja-build ripgrep llvm-14-tools
|
||||
|
||||
- name: Install rustfmt
|
||||
run: rustup component add rustfmt
|
||||
- name: Install rustfmt & clippy
|
||||
run: rustup component add rustfmt clippy
|
||||
|
||||
- name: Download artifact
|
||||
run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/${{ matrix.libgccjit_version.gcc }}
|
||||
run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/${{ matrix.libgccjit_version.gcc }}
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
run: |
|
||||
@ -78,9 +78,16 @@ jobs:
|
||||
- name: Build
|
||||
run: |
|
||||
./y.sh prepare --only-libcore
|
||||
./y.sh build
|
||||
./y.sh build --sysroot
|
||||
cargo test
|
||||
./y.sh clean all
|
||||
|
||||
- name: Run y.sh cargo build
|
||||
run: |
|
||||
./y.sh cargo build --manifest-path tests/hello-world/Cargo.toml
|
||||
|
||||
- name: Clean
|
||||
run: |
|
||||
./y.sh clean all
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: |
|
||||
@ -96,7 +103,12 @@ jobs:
|
||||
./y.sh test --release --clean --build-sysroot ${{ matrix.commands }}
|
||||
|
||||
- name: Check formatting
|
||||
run: cargo fmt -- --check
|
||||
run: ./y.sh fmt --check
|
||||
|
||||
- name: clippy
|
||||
run: |
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
cargo clippy --all-targets --features master -- -D warnings
|
||||
|
||||
duplicates:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -56,7 +56,7 @@ jobs:
|
||||
|
||||
- name: Download artifact
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/gcc-13.deb
|
||||
run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-13.deb
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
@ -94,7 +94,20 @@ jobs:
|
||||
run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
# TODO: re-enable those tests for libgccjit 12.
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
id: tests
|
||||
run: |
|
||||
${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} | tee output_log
|
||||
rg --text "test result" output_log >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Run failing ui pattern tests for ICE
|
||||
# TODO: re-enable those tests for libgccjit 12.
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
id: ui-tests
|
||||
run: |
|
||||
${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --test-failing-ui-pattern-tests ${{ matrix.libgccjit_version.extra }} | tee output_log_ui
|
||||
if grep -q "the compiler unexpectedly panicked" output_log_ui; then
|
||||
echo "Error: 'the compiler unexpectedly panicked' found in output logs. CI Error!!"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -68,21 +68,23 @@ jobs:
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --libgccjit12-patches
|
||||
./y.sh build --no-default-features --sysroot-panic-abort
|
||||
cargo test --no-default-features
|
||||
./y.sh clean all
|
||||
# Uncomment when we no longer need to remove global variables.
|
||||
#./y.sh build --sysroot --no-default-features --sysroot-panic-abort
|
||||
#cargo test --no-default-features
|
||||
#./y.sh clean all
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: |
|
||||
git config --global user.email "user@example.com"
|
||||
git config --global user.name "User"
|
||||
./y.sh prepare --libgccjit12-patches
|
||||
#- name: Prepare dependencies
|
||||
#run: |
|
||||
#git config --global user.email "user@example.com"
|
||||
#git config --global user.name "User"
|
||||
#./y.sh prepare --libgccjit12-patches
|
||||
|
||||
- name: Add more failing tests for GCC 12
|
||||
run: cat tests/failing-ui-tests12.txt >> tests/failing-ui-tests.txt
|
||||
#- name: Add more failing tests for GCC 12
|
||||
#run: cat tests/failing-ui-tests12.txt >> tests/failing-ui-tests.txt
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt
|
||||
#- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
#run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features
|
||||
#- name: Run tests
|
||||
#run: |
|
||||
#./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user