New upstream version 1.57.0+dfsg1

This commit is contained in:
Ximin Luo 2022-03-06 21:55:47 +00:00
parent dc3f568640
commit c295e0f8f6
4720 changed files with 138136 additions and 44466 deletions

322
Cargo.lock generated
View File

@ -26,9 +26,9 @@ dependencies = [
[[package]]
name = "aho-corasick"
version = "0.7.13"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
@ -220,6 +220,18 @@ dependencies = [
name = "build_helper"
version = "0.1.0"
[[package]]
name = "bump-stage0"
version = "0.1.0"
dependencies = [
"anyhow",
"curl",
"indexmap",
"serde",
"serde_json",
"toml",
]
[[package]]
name = "byte-tools"
version = "0.3.1"
@ -255,7 +267,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da"
[[package]]
name = "cargo"
version = "0.57.0"
version = "0.58.0"
dependencies = [
"anyhow",
"atty",
@ -281,7 +293,7 @@ dependencies = [
"humantime 2.0.1",
"ignore",
"im-rc",
"itertools 0.10.0",
"itertools 0.10.1",
"jobserver",
"lazy_static",
"lazycell",
@ -292,6 +304,7 @@ dependencies = [
"num_cpus",
"opener",
"openssl",
"os_info",
"percent-encoding 2.1.0",
"pretty_env_logger",
"rustc-workspace-hack",
@ -348,7 +361,7 @@ version = "0.1.0"
dependencies = [
"directories",
"rustc-workspace-hack",
"rustc_version",
"rustc_version 0.3.3",
"serde",
"serde_json",
"vergen",
@ -376,7 +389,7 @@ dependencies = [
"flate2",
"git2",
"glob",
"itertools 0.10.0",
"itertools 0.10.1",
"lazy_static",
"remove_dir_all",
"serde_json",
@ -542,13 +555,16 @@ dependencies = [
[[package]]
name = "clippy"
version = "0.1.56"
version = "0.1.57"
dependencies = [
"cargo_metadata 0.12.0",
"clippy_lints",
"clippy_utils",
"compiletest_rs",
"derive-new",
"filetime",
"if_chain",
"itertools 0.10.1",
"quote",
"regex",
"rustc-workspace-hack",
@ -566,7 +582,7 @@ version = "0.0.1"
dependencies = [
"bytecount",
"clap",
"itertools 0.9.0",
"itertools 0.10.1",
"opener",
"regex",
"shell-escape",
@ -575,12 +591,12 @@ dependencies = [
[[package]]
name = "clippy_lints"
version = "0.1.56"
version = "0.1.57"
dependencies = [
"cargo_metadata 0.12.0",
"clippy_utils",
"if_chain",
"itertools 0.9.0",
"itertools 0.10.1",
"pulldown-cmark 0.8.0",
"quine-mc_cluskey",
"regex-syntax",
@ -596,14 +612,10 @@ dependencies = [
[[package]]
name = "clippy_utils"
version = "0.1.56"
version = "0.1.57"
dependencies = [
"if_chain",
"itertools 0.9.0",
"regex-syntax",
"rustc-semver",
"serde",
"unicode-normalization",
]
[[package]]
@ -678,9 +690,9 @@ dependencies = [
[[package]]
name = "compiletest_rs"
version = "0.6.0"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0086d6ad78cf409c3061618cd98e2789d5c9ce598fc9651611cf62eae0a599cb"
checksum = "64698e5e2435db061a85e6320af12c30c5fd88eb84b35d2c1e03ce4f143255ca"
dependencies = [
"diff",
"filetime",
@ -856,9 +868,9 @@ dependencies = [
[[package]]
name = "curl"
version = "0.4.38"
version = "0.4.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "003cb79c1c6d1c93344c7e1201bb51c2148f24ec2bd9c253709d6b2efb796515"
checksum = "aaa3b8db7f3341ddef15786d250106334d4a6c4b0ae4a46cd77082777d9849b9"
dependencies = [
"curl-sys",
"libc",
@ -1081,19 +1093,6 @@ dependencies = [
"termcolor",
]
[[package]]
name = "env_logger"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54532e3223c5af90a6a757c90b5c5521564b07e5e7a958681bcd2afad421cdcd"
dependencies = [
"atty",
"humantime 2.0.1",
"log",
"regex",
"termcolor",
]
[[package]]
name = "env_logger"
version = "0.9.0"
@ -1429,9 +1428,9 @@ dependencies = [
[[package]]
name = "git2"
version = "0.13.17"
version = "0.13.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d250f5f82326884bd39c2853577e70a121775db76818ffa452ed1e80de12986"
checksum = "2a8057932925d3a9d9e4434ea016570d37420ddb1ceed45a174d577f24ed6700"
dependencies = [
"bitflags",
"libc",
@ -1649,7 +1648,7 @@ checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f"
dependencies = [
"bitmaps",
"rand_core 0.5.1",
"rand_xoshiro",
"rand_xoshiro 0.4.0",
"sized-chunks",
"typenum",
"version_check",
@ -1663,6 +1662,7 @@ checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [
"autocfg",
"hashbrown",
"serde",
]
[[package]]
@ -1708,9 +1708,9 @@ dependencies = [
[[package]]
name = "itertools"
version = "0.10.0"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319"
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
dependencies = [
"either",
]
@ -1880,18 +1880,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.99"
version = "0.2.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
dependencies = [
"rustc-std-workspace-core",
]
[[package]]
name = "libgit2-sys"
version = "0.12.18+1.1.0"
version = "0.12.24+1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3da6a42da88fc37ee1ecda212ffa254c25713532980005d5f7c0b0fbe7e6e885"
checksum = "ddbd6021eef06fb289a8f54b3c2acfdd85ff2a585dfbb24b8576325373d2152c"
dependencies = [
"cc",
"libc",
@ -2242,15 +2242,15 @@ version = "0.1.0"
dependencies = [
"colored",
"compiletest_rs",
"env_logger 0.8.1",
"env_logger 0.9.0",
"getrandom 0.2.0",
"hex 0.4.2",
"libc",
"log",
"measureme",
"rand 0.8.3",
"rand 0.8.4",
"rustc-workspace-hack",
"rustc_version",
"rustc_version 0.4.0",
"shell-escape",
"smallvec",
]
@ -2313,6 +2313,15 @@ dependencies = [
"rustc-std-workspace-core",
]
[[package]]
name = "odht"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a518809ac14b25b569624d0268eba1e88498f71615893dca57982bed7621abb"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "once_cell"
version = "1.7.2"
@ -2399,6 +2408,17 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024"
[[package]]
name = "os_info"
version = "3.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac91020bfed8cc3f8aa450d4c3b5fa1d3373fc091c8a92009f3b27749d5a227"
dependencies = [
"log",
"serde",
"winapi",
]
[[package]]
name = "output_vt100"
version = "0.1.2"
@ -2835,9 +2855,9 @@ dependencies = [
[[package]]
name = "rand"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha 0.3.0",
@ -2928,6 +2948,15 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rand_xoshiro"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
dependencies = [
"rand_core 0.6.2",
]
[[package]]
name = "rayon"
version = "1.3.1"
@ -2974,9 +3003,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.4.6"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
@ -3589,6 +3618,33 @@ dependencies = [
"rustc_span",
]
[[package]]
name = "rustc_borrowck"
version = "0.0.0"
dependencies = [
"either",
"itertools 0.9.0",
"polonius-engine",
"rustc_const_eval",
"rustc_data_structures",
"rustc_errors",
"rustc_graphviz",
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_lexer",
"rustc_middle",
"rustc_mir_dataflow",
"rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"rustc_traits",
"smallvec",
"tracing",
]
[[package]]
name = "rustc_builtin_macros"
version = "0.0.0"
@ -3619,6 +3675,7 @@ dependencies = [
"libc",
"measureme",
"rustc-demangle",
"rustc_arena",
"rustc_ast",
"rustc_attr",
"rustc_codegen_ssa",
@ -3630,6 +3687,7 @@ dependencies = [
"rustc_llvm",
"rustc_metadata",
"rustc_middle",
"rustc_query_system",
"rustc_serialize",
"rustc_session",
"rustc_span",
@ -3661,7 +3719,9 @@ dependencies = [
"rustc_incremental",
"rustc_index",
"rustc_macros",
"rustc_metadata",
"rustc_middle",
"rustc_query_system",
"rustc_serialize",
"rustc_session",
"rustc_span",
@ -3672,6 +3732,29 @@ dependencies = [
"tracing",
]
[[package]]
name = "rustc_const_eval"
version = "0.0.0"
dependencies = [
"rustc_apfloat",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_macros",
"rustc_middle",
"rustc_mir_dataflow",
"rustc_query_system",
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"tracing",
]
[[package]]
name = "rustc_data_structures"
version = "0.0.0"
@ -3710,6 +3793,7 @@ dependencies = [
"rustc_ast",
"rustc_ast_pretty",
"rustc_codegen_ssa",
"rustc_const_eval",
"rustc_data_structures",
"rustc_error_codes",
"rustc_errors",
@ -3720,7 +3804,6 @@ dependencies = [
"rustc_lint",
"rustc_metadata",
"rustc_middle",
"rustc_mir",
"rustc_parse",
"rustc_plugin_impl",
"rustc_save_analysis",
@ -3799,6 +3882,7 @@ version = "0.0.0"
name = "rustc_hir"
version = "0.0.0"
dependencies = [
"odht",
"rustc_ast",
"rustc_data_structures",
"rustc_feature",
@ -3879,9 +3963,11 @@ dependencies = [
"rustc_ast_lowering",
"rustc_ast_passes",
"rustc_attr",
"rustc_borrowck",
"rustc_builtin_macros",
"rustc_codegen_llvm",
"rustc_codegen_ssa",
"rustc_const_eval",
"rustc_data_structures",
"rustc_errors",
"rustc_expand",
@ -3890,8 +3976,9 @@ dependencies = [
"rustc_lint",
"rustc_metadata",
"rustc_middle",
"rustc_mir",
"rustc_mir_build",
"rustc_mir_transform",
"rustc_monomorphize",
"rustc_parse",
"rustc_passes",
"rustc_plugin_impl",
@ -3982,6 +4069,7 @@ name = "rustc_metadata"
version = "0.0.0"
dependencies = [
"libc",
"odht",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
@ -4009,7 +4097,11 @@ version = "0.0.0"
dependencies = [
"bitflags",
"chalk-ir",
"either",
"gsgdt",
"polonius-engine",
"rand 0.8.4",
"rand_xoshiro 0.6.0",
"rustc-rayon-core",
"rustc_apfloat",
"rustc_arena",
@ -4018,6 +4110,7 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
"rustc_graphviz",
"rustc_hir",
"rustc_index",
"rustc_macros",
@ -4031,38 +4124,6 @@ dependencies = [
"tracing",
]
[[package]]
name = "rustc_mir"
version = "0.0.0"
dependencies = [
"coverage_test_macros",
"either",
"gsgdt",
"itertools 0.9.0",
"polonius-engine",
"regex",
"rustc_apfloat",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
"rustc_errors",
"rustc_graphviz",
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_lexer",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"rustc_traits",
"smallvec",
"tracing",
]
[[package]]
name = "rustc_mir_build"
version = "0.0.0"
@ -4086,6 +4147,67 @@ dependencies = [
"tracing",
]
[[package]]
name = "rustc_mir_dataflow"
version = "0.0.0"
dependencies = [
"polonius-engine",
"regex",
"rustc_ast",
"rustc_data_structures",
"rustc_graphviz",
"rustc_hir",
"rustc_index",
"rustc_middle",
"rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"smallvec",
"tracing",
]
[[package]]
name = "rustc_mir_transform"
version = "0.0.0"
dependencies = [
"coverage_test_macros",
"itertools 0.9.0",
"rustc_ast",
"rustc_attr",
"rustc_const_eval",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_index",
"rustc_middle",
"rustc_mir_dataflow",
"rustc_query_system",
"rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"smallvec",
"tracing",
]
[[package]]
name = "rustc_monomorphize"
version = "0.0.0"
dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_index",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
"smallvec",
"tracing",
]
[[package]]
name = "rustc_parse"
version = "0.0.0"
@ -4101,6 +4223,7 @@ dependencies = [
"rustc_span",
"tracing",
"unicode-normalization",
"unicode-width",
]
[[package]]
@ -4191,13 +4314,17 @@ dependencies = [
"parking_lot",
"rustc-rayon-core",
"rustc_arena",
"rustc_ast",
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"smallvec",
"tracing",
]
@ -4265,6 +4392,7 @@ dependencies = [
"rustc_errors",
"rustc_feature",
"rustc_fs_util",
"rustc_hir",
"rustc_lint_defs",
"rustc_macros",
"rustc_serialize",
@ -4300,6 +4428,7 @@ dependencies = [
"rustc_data_structures",
"rustc_hir",
"rustc_middle",
"rustc_query_system",
"rustc_session",
"rustc_span",
"rustc_target",
@ -4340,9 +4469,11 @@ dependencies = [
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_lint_defs",
"rustc_macros",
"rustc_middle",
"rustc_parse_format",
"rustc_query_system",
"rustc_session",
"rustc_span",
"rustc_target",
@ -4431,6 +4562,15 @@ dependencies = [
"semver 0.11.0",
]
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver 1.0.3",
]
[[package]]
name = "rustdoc"
version = "0.0.0"
@ -4791,9 +4931,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "smallvec"
version = "1.6.1"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "snap"
@ -4991,7 +5131,7 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if 1.0.0",
"libc",
"rand 0.8.3",
"rand 0.8.4",
"redox_syscall",
"remove_dir_all",
"winapi",
@ -5240,9 +5380,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
version = "0.1.25"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f"
checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8"
dependencies = [
"cfg-if 1.0.0",
"pin-project-lite",
@ -5252,9 +5392,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.13"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07"
checksum = "c4f915eb6abf914599c200260efced9203504c4c37380af10cdf3b7d36970650"
dependencies = [
"proc-macro2",
"quote",
@ -5263,9 +5403,9 @@ dependencies = [
[[package]]
name = "tracing-core"
version = "0.1.17"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f"
checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
dependencies = [
"lazy_static",
]

View File

@ -35,12 +35,14 @@ members = [
"src/tools/expand-yaml-anchors",
"src/tools/jsondocck",
"src/tools/html-checker",
"src/tools/bump-stage0",
"src/tools/lld-wrapper",
]
exclude = [
"build",
"compiler/rustc_codegen_cranelift",
"compiler/rustc_codegen_gcc",
"src/test/rustdoc-gui",
# HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`.
"obj",
@ -87,6 +89,15 @@ gimli.debug = 0
miniz_oxide.debug = 0
object.debug = 0
# The only package that ever uses debug builds is bootstrap.
# We care a lot about bootstrap's compile times, so don't include debug info for
# dependencies, only bootstrap itself.
[profile.dev]
debug = 0
[profile.dev.package]
# Only use debuginfo=1 to further reduce compile times.
bootstrap.debug = 1
# We want the RLS to use the version of Cargo that we've got vendored in this
# repository to ensure that the same exact version of Cargo is used by both the
# RLS and the Cargo binary itself. The RLS depends on Cargo as a git repository

View File

@ -1,3 +1,125 @@
Version 1.57.0 (2021-12-02)
==========================
Language
--------
- [Macro attributes may follow `#[derive]` and will see the original (pre-`cfg`) input.][87220]
- [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690]
- [Allow panicking in constant evaluation.][89508]
Compiler
--------
- [Create more accurate debuginfo for vtables.][89597]
- [Add `armv6k-nintendo-3ds` at Tier 3\*.][88529]
- [Add `armv7-unknown-linux-uclibceabihf` at Tier 3\*.][88952]
- [Add `m68k-unknown-linux-gnu` at Tier 3\*.][88321]
- [Add SOLID targets at Tier 3\*:][86191] `aarch64-kmc-solid_asp3`, `armv7a-kmc-solid_asp3-eabi`, `armv7a-kmc-solid_asp3-eabihf`
\* Refer to Rust's [platform support page][platform-support-doc] for more
information on Rust's tiered platform support.
Libraries
---------
- [Avoid allocations and copying in `Vec::leak`][89337]
- [Add `#[repr(i8)]` to `Ordering`][89507]
- [Optimize `File::read_to_end` and `read_to_string`][89582]
- [Update to Unicode 14.0][89614]
- [Many more functions are marked `#[must_use]`][89692], producing a warning
when ignoring their return value. This helps catch mistakes such as expecting
a function to mutate a value in place rather than return a new value.
Stabilised APIs
---------------
- [`[T; N]::as_mut_slice`][`array::as_mut_slice`]
- [`[T; N]::as_slice`][`array::as_slice`]
- [`collections::TryReserveError`]
- [`HashMap::try_reserve`]
- [`HashSet::try_reserve`]
- [`String::try_reserve`]
- [`String::try_reserve_exact`]
- [`Vec::try_reserve`]
- [`Vec::try_reserve_exact`]
- [`VecDeque::try_reserve`]
- [`VecDeque::try_reserve_exact`]
- [`Iterator::map_while`]
- [`iter::MapWhile`]
- [`proc_macro::is_available`]
- [`Command::get_program`]
- [`Command::get_args`]
- [`Command::get_envs`]
- [`Command::get_current_dir`]
- [`CommandArgs`]
- [`CommandEnvs`]
These APIs are now usable in const contexts:
- [`hint::unreachable_unchecked`]
Cargo
-----
- [Stabilize custom profiles][cargo/9943]
Compatibility notes
-------------------
Internal changes
----------------
These changes provide no direct user facing benefits, but represent significant
improvements to the internals and overall performance of rustc
and related tools.
- [Added an experimental backend for codegen with `libgccjit`.][87260]
[86191]: https://github.com/rust-lang/rust/pull/86191/
[87220]: https://github.com/rust-lang/rust/pull/87220/
[87260]: https://github.com/rust-lang/rust/pull/87260/
[88243]: https://github.com/rust-lang/rust/pull/88243/
[88321]: https://github.com/rust-lang/rust/pull/88321/
[88529]: https://github.com/rust-lang/rust/pull/88529/
[88690]: https://github.com/rust-lang/rust/pull/88690/
[88952]: https://github.com/rust-lang/rust/pull/88952/
[89337]: https://github.com/rust-lang/rust/pull/89337/
[89507]: https://github.com/rust-lang/rust/pull/89507/
[89508]: https://github.com/rust-lang/rust/pull/89508/
[89582]: https://github.com/rust-lang/rust/pull/89582/
[89597]: https://github.com/rust-lang/rust/pull/89597/
[89614]: https://github.com/rust-lang/rust/pull/89614/
[89692]: https://github.com/rust-lang/rust/issues/89692/
[cargo/9943]: https://github.com/rust-lang/cargo/pull/9943/
[`array::as_mut_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_mut_slice
[`array::as_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_slice
[`collections::TryReserveError`]: https://doc.rust-lang.org/std/collections/struct.TryReserveError.html
[`HashMap::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.try_reserve
[`HashSet::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.try_reserve
[`String::try_reserve`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve
[`String::try_reserve_exact`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve_exact
[`Vec::try_reserve`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve
[`Vec::try_reserve_exact`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve_exact
[`VecDeque::try_reserve`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve
[`VecDeque::try_reserve_exact`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve_exact
[`Iterator::map_while`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map_while
[`iter::MapWhile`]: https://doc.rust-lang.org/std/iter/struct.MapWhile.html
[`proc_macro::is_available`]: https://doc.rust-lang.org/proc_macro/fn.is_available.html
[`Command::get_program`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_program
[`Command::get_args`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_args
[`Command::get_envs`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_envs
[`Command::get_current_dir`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_current_dir
[`CommandArgs`]: https://doc.rust-lang.org/std/process/struct.CommandArgs.html
[`CommandEnvs`]: https://doc.rust-lang.org/std/process/struct.CommandEnvs.html
Version 1.56.1 (2021-11-01)
===========================
- New lints to detect the presence of bidirectional-override Unicode
codepoints in the compiled source code ([CVE-2021-42574])
[CVE-2021-42574]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-42574
Version 1.56.0 (2021-10-21)
========================
@ -77,7 +199,7 @@ Cargo
- [Cargo supports specifying a minimum supported Rust version in Cargo.toml.][`rust-version`]
This has no effect at present on dependency version selection.
We encourage crates to specify their minimum supported Rust version, and we encourage CI systems
that support Rust code to include a crate's specified minimum version in the text matrix for that
that support Rust code to include a crate's specified minimum version in the test matrix for that
crate by default.
Compatibility notes

View File

@ -1,7 +1,7 @@
[package]
name = "rustc-main"
version = "0.0.0"
edition = '2018'
edition = "2021"
[dependencies]
rustc_driver = { path = "../rustc_driver" }

View File

@ -1,7 +1,7 @@
[package]
name = "rustc_apfloat"
version = "0.0.0"
edition = "2018"
edition = "2021"
[dependencies]
bitflags = "1.2.1"

View File

@ -389,6 +389,7 @@ impl<S: Semantics> fmt::Display for IeeeFloat<S> {
let _: Loss = sig::shift_right(&mut sig, &mut exp, trailing_zeros as usize);
// Change the exponent from 2^e to 10^e.
#[allow(clippy::comparison_chain)]
if exp == 0 {
// Nothing to do.
} else if exp > 0 {
@ -2526,6 +2527,7 @@ mod sig {
if *a_sign ^ b_sign {
let (reverse, loss);
#[allow(clippy::comparison_chain)]
if bits == 0 {
reverse = cmp(a_sig, b_sig) == Ordering::Less;
loss = Loss::ExactlyZero;

View File

@ -1,7 +1,7 @@
[package]
name = "rustc_arena"
version = "0.0.0"
edition = "2018"
edition = "2021"
[dependencies]
rustc_data_structures = { path = "../rustc_data_structures" }

View File

@ -1,7 +1,7 @@
[package]
name = "rustc_ast"
version = "0.0.0"
edition = "2018"
edition = "2021"
[lib]
doctest = false

View File

@ -1211,6 +1211,8 @@ impl Expr {
}
}
ExprKind::Underscore => TyKind::Infer,
// This expression doesn't look like a type syntactically.
_ => return None,
};

View File

@ -367,7 +367,7 @@ impl MetaItem {
let is_first = i == 0;
if !is_first {
let mod_sep_span =
Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt());
Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt(), None);
idents.push(TokenTree::token(token::ModSep, mod_sep_span).into());
}
idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into());

View File

@ -9,29 +9,17 @@
test(attr(deny(warnings)))
)]
#![feature(box_patterns)]
#![cfg_attr(bootstrap, feature(const_fn_transmute))]
#![feature(crate_visibility_modifier)]
#![feature(if_let_guard)]
#![feature(iter_zip)]
#![feature(label_break_value)]
#![feature(nll)]
#![feature(min_specialization)]
#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
#![recursion_limit = "256"]
#[macro_use]
extern crate rustc_macros;
#[macro_export]
macro_rules! unwrap_or {
($opt:expr, $default:expr) => {
match $opt {
Some(x) => x,
None => $default,
}
};
}
pub mod util {
pub mod classify;
pub mod comments;

View File

@ -295,6 +295,7 @@ impl TokenKind {
match *self {
Comma => Some(vec![Dot, Lt, Semi]),
Semi => Some(vec![Colon, Comma]),
FatArrow => Some(vec![Eq, RArrow]),
_ => None,
}
}
@ -586,6 +587,13 @@ impl Token {
self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
}
pub fn is_numeric_lit(&self) -> bool {
matches!(
self.kind,
Literal(Lit { kind: LitKind::Integer, .. }) | Literal(Lit { kind: LitKind::Float, .. })
)
}
/// Returns `true` if the token is a non-raw identifier for which `pred` holds.
pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool {
match self.ident() {

View File

@ -1,7 +1,7 @@
[package]
name = "rustc_ast_lowering"
version = "0.0.0"
edition = "2018"
edition = "2021"
[lib]
doctest = false

View File

@ -202,39 +202,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let mut used_input_regs = FxHashMap::default();
let mut used_output_regs = FxHashMap::default();
let mut required_features: Vec<&str> = vec![];
for (idx, &(ref op, op_sp)) in operands.iter().enumerate() {
if let Some(reg) = op.reg() {
// Make sure we don't accidentally carry features from the
// previous iteration.
required_features.clear();
let reg_class = reg.reg_class();
if reg_class == asm::InlineAsmRegClass::Err {
continue;
}
// We ignore target feature requirements for clobbers: if the
// feature is disabled then the compiler doesn't care what we
// do with the registers.
//
// Note that this is only possible for explicit register
// operands, which cannot be used in the asm string.
let is_clobber = matches!(
op,
hir::InlineAsmOperand::Out {
reg: asm::InlineAsmRegOrRegClass::Reg(_),
late: _,
expr: None
}
);
// Some register classes can only be used as clobbers. This
// means that we disallow passing a value in/out of the asm and
// require that the operand name an explicit register, not a
// register class.
if reg_class.is_clobber_only(asm_arch.unwrap())
&& !(is_clobber && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_)))
&& !(op.is_clobber() && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_)))
{
let msg = format!(
"register class `{}` can only be used as a clobber, \
@ -245,47 +226,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
continue;
}
if !is_clobber {
// Validate register classes against currently enabled target
// features. We check that at least one type is available for
// the current target.
for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) {
if let Some(feature) = feature {
if self.sess.target_features.contains(&Symbol::intern(feature)) {
required_features.clear();
break;
} else {
required_features.push(feature);
}
} else {
required_features.clear();
break;
}
}
// We are sorting primitive strs here and can use unstable sort here
required_features.sort_unstable();
required_features.dedup();
match &required_features[..] {
[] => {}
[feature] => {
let msg = format!(
"register class `{}` requires the `{}` target feature",
reg_class.name(),
feature
);
sess.struct_span_err(op_sp, &msg).emit();
}
features => {
let msg = format!(
"register class `{}` requires at least one target feature: {}",
reg_class.name(),
features.join(", ")
);
sess.struct_span_err(op_sp, &msg).emit();
}
}
}
// Check for conflicts between explicit register operands.
if let asm::InlineAsmRegOrRegClass::Reg(reg) = reg {
let (input, output) = match op {

View File

@ -55,7 +55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
StmtKind::Item(ref it) => {
stmts.extend(self.lower_item_id(it).into_iter().enumerate().map(
stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map(
|(i, item_id)| {
let hir_id = match i {
0 => self.lower_node_id(s.id),

View File

@ -55,7 +55,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
0,
ParenthesizedGenericArgs::Err,
ImplTraitContext::disallowed(),
None,
));
let args = self.lower_exprs(args);
hir::ExprKind::MethodCall(
@ -101,10 +100,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::If(ref cond, ref then, ref else_opt) => {
self.lower_expr_if(cond, then, else_opt.as_deref())
}
ExprKind::While(ref cond, ref body, opt_label) => self
.with_loop_scope(e.id, |this| {
this.lower_expr_while_in_loop_scope(e.span, cond, body, opt_label)
}),
ExprKind::While(ref cond, ref body, opt_label) => {
self.with_loop_scope(e.id, |this| {
let span =
this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None);
this.lower_expr_while_in_loop_scope(span, cond, body, opt_label)
})
}
ExprKind::Loop(ref body, opt_label) => self.with_loop_scope(e.id, |this| {
hir::ExprKind::Loop(
this.lower_block(body, false),
@ -328,7 +330,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let mut generic_args = vec![];
for (idx, arg) in args.into_iter().enumerate() {
if legacy_args_idx.contains(&idx) {
let parent_def_id = self.current_hir_id_owner.0;
let parent_def_id = self.current_hir_id_owner;
let node_id = self.resolver.next_node_id();
// Add a definition for the in-band const def.
@ -422,7 +424,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
let if_expr = self.expr(span, if_kind, ThinVec::new());
let block = self.block_expr(self.arena.alloc(if_expr));
hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span.with_hi(cond.span.hi()))
let span = self.lower_span(span.with_hi(cond.span.hi()));
let opt_label = self.lower_label(opt_label);
hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span)
}
/// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,
@ -1186,9 +1190,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
None => self
.loop_scopes
.last()
.cloned()
.loop_scope
.map(|id| Ok(self.lower_node_id(id)))
.unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)),
};
@ -1208,18 +1210,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
fn with_catch_scope<T>(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
let len = self.catch_scopes.len();
self.catch_scopes.push(catch_id);
let old_scope = self.catch_scope.replace(catch_id);
let result = f(self);
assert_eq!(
len + 1,
self.catch_scopes.len(),
"catch scopes should be added and removed in stack order"
);
self.catch_scopes.pop().unwrap();
self.catch_scope = old_scope;
result
}
@ -1228,17 +1221,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
let was_in_loop_condition = self.is_in_loop_condition;
self.is_in_loop_condition = false;
let len = self.loop_scopes.len();
self.loop_scopes.push(loop_id);
let old_scope = self.loop_scope.replace(loop_id);
let result = f(self);
assert_eq!(
len + 1,
self.loop_scopes.len(),
"loop scopes should be added and removed in stack order"
);
self.loop_scopes.pop().unwrap();
self.loop_scope = old_scope;
self.is_in_loop_condition = was_in_loop_condition;
@ -1469,8 +1454,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
};
// #82462: to correctly diagnose borrow errors, the block that contains
// the iter expr needs to have a span that covers the loop body.
let desugared_full_span =
self.mark_span_with_reason(DesugaringKind::ForLoop(ForLoopLoc::Head), e.span, None);
let match_expr = self.arena.alloc(self.expr_match(
desugared_span,
desugared_full_span,
into_iter_expr,
arena_vec![self; iter_arm],
hir::MatchSource::ForLoopDesugar,
@ -1484,7 +1474,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// surrounding scope of the `match` since the `match` is not a terminating scope.
//
// Also, add the attributes to the outer returned expr node.
self.expr_drop_temps_mut(desugared_span, match_expr, attrs.into())
self.expr_drop_temps_mut(desugared_full_span, match_expr, attrs.into())
}
/// Desugar `ExprKind::Try` from: `<expr>?` into:
@ -1565,8 +1555,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
unstable_span,
);
let thin_attrs = ThinVec::from(attrs);
let catch_scope = self.catch_scopes.last().copied();
let ret_expr = if let Some(catch_node) = catch_scope {
let ret_expr = if let Some(catch_node) = self.catch_scope {
let target_id = Ok(self.lower_node_id(catch_node));
self.arena.alloc(self.expr(
try_span,

View File

@ -2,7 +2,6 @@ use super::{AnonymousLifetimeMode, LoweringContext, ParamMode};
use super::{ImplTraitContext, ImplTraitPosition};
use crate::Arena;
use rustc_ast::node_id::NodeMap;
use rustc_ast::ptr::P;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::*;
@ -42,21 +41,13 @@ impl ItemLowerer<'_, '_, '_> {
impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
fn visit_item(&mut self, item: &'a Item) {
let hir_id = self.lctx.with_hir_id_owner(item.id, |lctx| {
lctx.without_in_scope_lifetime_defs(|lctx| {
let hir_item = lctx.lower_item(item);
lctx.insert_item(hir_item)
})
let node = lctx.without_in_scope_lifetime_defs(|lctx| lctx.lower_item(item));
hir::OwnerNode::Item(node)
});
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
let this = &mut ItemLowerer { lctx: this };
match item.kind {
ItemKind::Mod(..) => {
let def_id = this.lctx.lower_node_id(item.id).expect_owner();
let old_current_module = mem::replace(&mut this.lctx.current_module, def_id);
visit::walk_item(this, item);
this.lctx.current_module = old_current_module;
}
ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
}
@ -79,24 +70,16 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
AssocCtxt::Trait => {
let hir_item = lctx.lower_trait_item(item);
lctx.insert_trait_item(hir_item);
}
AssocCtxt::Impl => {
let hir_item = lctx.lower_impl_item(item);
lctx.insert_impl_item(hir_item);
}
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)),
});
visit::walk_assoc_item(self, item, ctxt);
}
fn visit_foreign_item(&mut self, item: &'a ForeignItem) {
self.lctx.allocate_hir_id_counter(item.id);
self.lctx.with_hir_id_owner(item.id, |lctx| {
let hir_item = lctx.lower_foreign_item(item);
lctx.insert_foreign_item(hir_item);
hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))
});
visit::walk_foreign_item(self, item);
@ -111,12 +94,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
// only used when lowering a child item of a trait or impl.
fn with_parent_item_lifetime_defs<T>(
&mut self,
parent_hir_id: hir::ItemId,
parent_hir_id: LocalDefId,
f: impl FnOnce(&mut Self) -> T,
) -> T {
let old_len = self.in_scope_lifetimes.len();
let parent_generics = match self.owners[parent_hir_id.def_id].unwrap().expect_item().kind {
let parent_generics = match self.owners[parent_hir_id].unwrap().expect_item().kind {
hir::ItemKind::Impl(hir::Impl { ref generics, .. })
| hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params,
_ => &[],
@ -155,41 +138,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn lower_mod(&mut self, items: &[P<Item>], inner: Span) -> hir::Mod<'hir> {
hir::Mod {
inner: self.lower_span(inner),
item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_id(x))),
item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))),
}
}
pub(super) fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
let node_ids = match i.kind {
ItemKind::Use(ref use_tree) => {
let mut vec = smallvec![i.id];
self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
vec
}
ItemKind::Fn(..) | ItemKind::Impl(box ImplKind { of_trait: None, .. }) => {
smallvec![i.id]
}
_ => smallvec![i.id],
};
pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
let mut node_ids = smallvec![hir::ItemId { def_id: self.resolver.local_def_id(i.id) }];
if let ItemKind::Use(ref use_tree) = &i.kind {
self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids);
}
node_ids
.into_iter()
.map(|node_id| hir::ItemId {
def_id: self.allocate_hir_id_counter(node_id).expect_owner(),
})
.collect()
}
fn lower_item_id_use_tree(
&mut self,
tree: &UseTree,
base_id: NodeId,
vec: &mut SmallVec<[NodeId; 1]>,
vec: &mut SmallVec<[hir::ItemId; 1]>,
) {
match tree.kind {
UseTreeKind::Nested(ref nested_vec) => {
for &(ref nested, id) in nested_vec {
vec.push(id);
vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) });
self.lower_item_id_use_tree(nested, id, vec);
}
}
@ -198,25 +168,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
for (_, &id) in
iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2])
{
vec.push(id);
vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) });
}
}
}
}
pub fn lower_item(&mut self, i: &Item) -> hir::Item<'hir> {
fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
let mut ident = i.ident;
let mut vis = self.lower_visibility(&i.vis, None);
let mut vis = self.lower_visibility(&i.vis);
let hir_id = self.lower_node_id(i.id);
let attrs = self.lower_attrs(hir_id, &i.attrs);
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind);
hir::Item {
let item = hir::Item {
def_id: hir_id.expect_owner(),
ident: self.lower_ident(ident),
kind,
vis,
span: self.lower_span(i.span),
}
};
self.arena.alloc(item)
}
fn lower_item_kind(
@ -487,7 +458,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
let mut resolutions = self.expect_full_res_from_use(id);
let mut resolutions = self.expect_full_res_from_use(id).fuse();
// We want to return *something* from this function, so hold onto the first item
// for later.
let ret_res = self.lower_res(resolutions.next().unwrap_or(Res::Err));
@ -497,7 +468,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
// won't be dealing with macros in the rest of the compiler.
// Essentially a single `use` which imports two names is desugared into
// two imports.
for (res, &new_node_id) in iter::zip(resolutions, &[id1, id2]) {
for new_node_id in [id1, id2] {
let new_id = self.resolver.local_def_id(new_node_id);
let res = if let Some(res) = resolutions.next() {
res
} else {
// Associate an HirId to both ids even if there is no resolution.
let _old = self
.node_id_to_hir_id
.insert(new_node_id, hir::HirId::make_owner(new_id));
debug_assert!(_old.is_none());
continue;
};
let ident = *ident;
let mut path = path.clone();
for seg in &mut path.segments {
@ -506,26 +488,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
let span = path.span;
self.with_hir_id_owner(new_node_id, |this| {
let new_id = this.lower_node_id(new_node_id);
let res = this.lower_res(res);
let path = this.lower_path_extra(res, &path, ParamMode::Explicit, None);
let path = this.lower_path_extra(res, &path, ParamMode::Explicit);
let kind = hir::ItemKind::Use(path, hir::UseKind::Single);
let vis = this.rebuild_vis(&vis);
if let Some(attrs) = attrs {
this.attrs.insert(new_id, attrs);
this.attrs.insert(hir::HirId::make_owner(new_id), attrs);
}
this.insert_item(hir::Item {
def_id: new_id.expect_owner(),
let item = hir::Item {
def_id: new_id,
ident: this.lower_ident(ident),
kind,
vis,
span: this.lower_span(span),
});
};
hir::OwnerNode::Item(this.arena.alloc(item))
});
}
let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit, None);
let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit);
hir::ItemKind::Use(path, hir::UseKind::Single)
}
UseTreeKind::Glob => {
@ -565,7 +547,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Add all the nested `PathListItem`s to the HIR.
for &(ref use_tree, id) in trees {
let new_hir_id = self.lower_node_id(id);
let new_hir_id = self.resolver.local_def_id(id);
let mut prefix = prefix.clone();
@ -586,16 +568,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
let kind =
this.lower_use_tree(use_tree, &prefix, id, &mut vis, &mut ident, attrs);
if let Some(attrs) = attrs {
this.attrs.insert(new_hir_id, attrs);
this.attrs.insert(hir::HirId::make_owner(new_hir_id), attrs);
}
this.insert_item(hir::Item {
def_id: new_hir_id.expect_owner(),
let item = hir::Item {
def_id: new_hir_id,
ident: this.lower_ident(ident),
kind,
vis,
span: this.lower_span(use_tree.span),
});
};
hir::OwnerNode::Item(this.arena.alloc(item))
});
}
@ -625,7 +608,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err);
let res = self.lower_res(res);
let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit, None);
let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit);
hir::ItemKind::Use(path, hir::UseKind::ListStem)
}
}
@ -662,11 +645,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
respan(self.lower_span(vis.span), vis_kind)
}
fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
let hir_id = self.lower_node_id(i.id);
let def_id = hir_id.expect_owner();
self.lower_attrs(hir_id, &i.attrs);
hir::ForeignItem {
let item = hir::ForeignItem {
def_id,
ident: self.lower_ident(i.ident),
kind: match i.kind {
@ -694,17 +677,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
},
vis: self.lower_visibility(&i.vis, None),
vis: self.lower_visibility(&i.vis),
span: self.lower_span(i.span),
}
};
self.arena.alloc(item)
}
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> {
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
hir::ForeignItemRef {
id: hir::ForeignItemId { def_id: self.lower_node_id(i.id).expect_owner() },
id: hir::ForeignItemId { def_id: self.resolver.local_def_id(i.id) },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
vis: self.lower_visibility(&i.vis, Some(i.id)),
}
}
@ -772,12 +755,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
// FIXME(jseyfried): positional field hygiene.
None => Ident::new(sym::integer(index), self.lower_span(f.span)),
},
vis: self.lower_visibility(&f.vis, None),
vis: self.lower_visibility(&f.vis),
ty,
}
}
fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
let hir_id = self.lower_node_id(i.id);
let trait_item_def_id = hir_id.expect_owner();
@ -820,13 +803,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
};
self.lower_attrs(hir_id, &i.attrs);
hir::TraitItem {
let item = hir::TraitItem {
def_id: trait_item_def_id,
ident: self.lower_ident(i.ident),
generics,
kind,
span: self.lower_span(i.span),
}
};
self.arena.alloc(item)
}
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
@ -840,7 +824,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
AssocItemKind::MacCall(..) => unimplemented!(),
};
let id = hir::TraitItemId { def_id: self.lower_node_id(i.id).expect_owner() };
let id = hir::TraitItemId { def_id: self.resolver.local_def_id(i.id) };
let defaultness = hir::Defaultness::Default { has_value: has_default };
hir::TraitItemRef {
id,
@ -856,7 +840,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.expr(span, hir::ExprKind::Err, AttrVec::new())
}
fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
let impl_item_def_id = self.resolver.local_def_id(i.id);
let (generics, kind) = match &i.kind {
@ -910,26 +894,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
let hir_id = self.lower_node_id(i.id);
self.lower_attrs(hir_id, &i.attrs);
hir::ImplItem {
let item = hir::ImplItem {
def_id: hir_id.expect_owner(),
ident: self.lower_ident(i.ident),
generics,
vis: self.lower_visibility(&i.vis, None),
vis: self.lower_visibility(&i.vis),
defaultness,
kind,
span: self.lower_span(i.span),
}
};
self.arena.alloc(item)
}
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> {
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
// 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);
hir::ImplItemRef {
id: hir::ImplItemId { def_id: self.lower_node_id(i.id).expect_owner() },
id: hir::ImplItemId { def_id: self.resolver.local_def_id(i.id) },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
vis: self.lower_visibility(&i.vis, Some(i.id)),
defaultness,
kind: match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
@ -947,25 +931,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// lowered. This can happen during `lower_impl_item_ref()` where we need to
/// lower a `Visibility` value although we haven't lowered the owning
/// `ImplItem` in question yet.
fn lower_visibility(
&mut self,
v: &Visibility,
explicit_owner: Option<NodeId>,
) -> hir::Visibility<'hir> {
fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility<'hir> {
let node = match v.kind {
VisibilityKind::Public => hir::VisibilityKind::Public,
VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
VisibilityKind::Restricted { ref path, id } => {
debug!("lower_visibility: restricted path id = {:?}", id);
let lowered_id = if let Some(owner) = explicit_owner {
self.lower_node_id_with_owner(id, owner)
} else {
self.lower_node_id(id)
};
let res = self.expect_full_res(id);
let res = self.lower_res(res);
let lowered_id = self.lower_node_id(id);
hir::VisibilityKind::Restricted {
path: self.lower_path_extra(res, path, ParamMode::Explicit, explicit_owner),
path: self.lower_path(id, path, ParamMode::Explicit),
hir_id: lowered_id,
}
}
@ -1348,42 +1322,56 @@ impl<'hir> LoweringContext<'_, 'hir> {
generics: &Generics,
itctx: ImplTraitContext<'_, 'hir>,
) -> GenericsCtor<'hir> {
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
let mut add_bounds: NodeMap<Vec<_>> = Default::default();
// Error if `?Trait` bounds in where clauses don't refer directly to type paramters.
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
// these into hir when we lower thee where clauses), but this makes it quite difficult to
// keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and
// where clauses for `?Sized`.
for pred in &generics.where_clause.predicates {
if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
'next_bound: for bound in &bound_pred.bounds {
if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound {
// Check if the where clause type is a plain type parameter.
match self
.resolver
.get_partial_res(bound_pred.bounded_ty.id)
.map(|d| (d.base_res(), d.unresolved_segments()))
{
Some((Res::Def(DefKind::TyParam, def_id), 0))
if bound_pred.bound_generic_params.is_empty() =>
{
for param in &generics.params {
if def_id == self.resolver.local_def_id(param.id).to_def_id() {
add_bounds.entry(param.id).or_default().push(bound.clone());
continue 'next_bound;
}
}
}
_ => {}
}
self.diagnostic().span_err(
bound_pred.bounded_ty.span,
"`?Trait` bounds are only permitted at the \
point where a type parameter is declared",
);
let bound_pred = match *pred {
WherePredicate::BoundPredicate(ref bound_pred) => bound_pred,
_ => continue,
};
let compute_is_param = || {
// Check if the where clause type is a plain type parameter.
match self
.resolver
.get_partial_res(bound_pred.bounded_ty.id)
.map(|d| (d.base_res(), d.unresolved_segments()))
{
Some((Res::Def(DefKind::TyParam, def_id), 0))
if bound_pred.bound_generic_params.is_empty() =>
{
generics
.params
.iter()
.any(|p| def_id == self.resolver.local_def_id(p.id).to_def_id())
}
// Either the `bounded_ty` is not a plain type parameter, or
// it's not found in the generic type parameters list.
_ => false,
}
};
// We only need to compute this once per `WherePredicate`, but don't
// need to compute this at all unless there is a Maybe bound.
let mut is_param: Option<bool> = None;
for bound in &bound_pred.bounds {
if !matches!(*bound, GenericBound::Trait(_, TraitBoundModifier::Maybe)) {
continue;
}
let is_param = *is_param.get_or_insert_with(compute_is_param);
if !is_param {
self.diagnostic().span_err(
bound.span(),
"`?Trait` bounds are only permitted at the \
point where a type parameter is declared",
);
}
}
}
GenericsCtor {
params: self.lower_generic_params_mut(&generics.params, &add_bounds, itctx).collect(),
params: self.lower_generic_params_mut(&generics.params, itctx).collect(),
where_clause: self.lower_where_clause(&generics.where_clause),
span: self.lower_span(generics.span),
}
@ -1416,32 +1404,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
ref bounded_ty,
ref bounds,
span,
}) => {
self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
bound_generic_params: this.lower_generic_params(
bound_generic_params,
&NodeMap::default(),
ImplTraitContext::disallowed(),
),
bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
bounds: this.arena.alloc_from_iter(bounds.iter().map(
|bound| match bound {
// We used to ignore `?Trait` bounds, as they were copied into type
// parameters already, but we need to keep them around only for
// diagnostics when we suggest removal of `?Sized` bounds. See
// `suggest_constraining_type_param`. This will need to change if
// we ever allow something *other* than `?Sized`.
GenericBound::Trait(p, TraitBoundModifier::Maybe) => {
hir::GenericBound::Unsized(this.lower_span(p.span))
}
_ => this.lower_param_bound(bound, ImplTraitContext::disallowed()),
},
)),
span: this.lower_span(span),
})
}) => self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
bound_generic_params: this
.lower_generic_params(bound_generic_params, ImplTraitContext::disallowed()),
bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| {
this.lower_param_bound(bound, ImplTraitContext::disallowed())
})),
span: this.lower_span(span),
})
}
}),
WherePredicate::RegionPredicate(WhereRegionPredicate {
ref lifetime,
ref bounds,

View File

@ -38,7 +38,7 @@
use rustc_ast::node_id::NodeMap;
use rustc_ast::token::{self, Token};
use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree};
use rustc_ast::visit::{self, AssocCtxt, Visitor};
use rustc_ast::visit;
use rustc_ast::{self as ast, *};
use rustc_ast_pretty::pprust;
use rustc_data_structures::captures::Captures;
@ -64,7 +64,6 @@ use rustc_span::{Span, DUMMY_SP};
use smallvec::SmallVec;
use std::collections::BTreeMap;
use std::mem;
use tracing::{debug, trace};
macro_rules! arena_vec {
@ -81,8 +80,6 @@ mod item;
mod pat;
mod path;
const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
rustc_hir::arena_types!(rustc_arena::declare_arena, 'tcx);
struct LoweringContext<'a, 'hir: 'a> {
@ -103,8 +100,6 @@ struct LoweringContext<'a, 'hir: 'a> {
owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>,
bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
modules: BTreeMap<LocalDefId, hir::ModuleItems>,
generator_kind: Option<hir::GeneratorKind>,
attrs: BTreeMap<hir::HirId, &'hir [Attribute]>,
@ -117,8 +112,8 @@ struct LoweringContext<'a, 'hir: 'a> {
/// outside of an `async fn`.
current_item: Option<Span>,
catch_scopes: Vec<NodeId>,
loop_scopes: Vec<NodeId>,
catch_scope: Option<NodeId>,
loop_scope: Option<NodeId>,
is_in_loop_condition: bool,
is_in_trait_impl: bool,
is_in_dyn_type: bool,
@ -153,10 +148,8 @@ struct LoweringContext<'a, 'hir: 'a> {
/// vector.
in_scope_lifetimes: Vec<ParamName>,
current_module: LocalDefId,
current_hir_id_owner: (LocalDefId, u32),
item_local_id_counters: NodeMap<u32>,
current_hir_id_owner: LocalDefId,
item_local_id_counter: hir::ItemLocalId,
node_id_to_hir_id: IndexVec<NodeId, Option<hir::HirId>>,
allow_try_trait: Option<Lrc<[Symbol]>>,
@ -166,12 +159,14 @@ struct LoweringContext<'a, 'hir: 'a> {
pub trait ResolverAstLowering {
fn def_key(&mut self, id: DefId) -> DefKey;
fn def_span(&self, id: LocalDefId) -> Span;
fn item_generics_num_lifetimes(&self, def: DefId) -> usize;
fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>>;
/// Obtains resolution for a `NodeId` with a single resolution.
fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes>;
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
/// Obtains per-namespace resolutions for `use` statement with the given `NodeId`.
fn get_import_res(&mut self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
@ -216,6 +211,11 @@ impl<'a> rustc_span::HashStableContext for LoweringHasher<'a> {
true
}
#[inline]
fn def_span(&self, id: LocalDefId) -> Span {
self.resolver.def_span(id)
}
#[inline]
fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
self.resolver.def_path_hash(def_id)
@ -321,17 +321,15 @@ pub fn lower_crate<'a, 'hir>(
arena,
owners: IndexVec::default(),
bodies: BTreeMap::new(),
modules: BTreeMap::new(),
attrs: BTreeMap::default(),
catch_scopes: Vec::new(),
loop_scopes: Vec::new(),
catch_scope: None,
loop_scope: None,
is_in_loop_condition: false,
is_in_trait_impl: false,
is_in_dyn_type: false,
anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
current_module: CRATE_DEF_ID,
current_hir_id_owner: (CRATE_DEF_ID, 0),
item_local_id_counters: Default::default(),
current_hir_id_owner: CRATE_DEF_ID,
item_local_id_counter: hir::ItemLocalId::new(0),
node_id_to_hir_id: IndexVec::new(),
generator_kind: None,
task_context: None,
@ -412,66 +410,15 @@ enum AnonymousLifetimeMode {
impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> {
/// Full-crate AST visitor that inserts into a fresh
/// `LoweringContext` any information that may be
/// needed from arbitrary locations in the crate,
/// e.g., the number of lifetime generic parameters
/// declared for every type and trait definition.
struct MiscCollector<'tcx, 'lowering, 'hir> {
lctx: &'tcx mut LoweringContext<'lowering, 'hir>,
}
debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID);
impl MiscCollector<'_, '_, '_> {
fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree) {
match tree.kind {
UseTreeKind::Simple(_, id1, id2) => {
for id in [id1, id2] {
self.lctx.allocate_hir_id_counter(id);
}
}
UseTreeKind::Glob => (),
UseTreeKind::Nested(ref trees) => {
for &(ref use_tree, id) in trees {
self.lctx.allocate_hir_id_counter(id);
self.allocate_use_tree_hir_id_counters(use_tree);
}
}
}
}
}
impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> {
fn visit_item(&mut self, item: &'tcx Item) {
self.lctx.allocate_hir_id_counter(item.id);
if let ItemKind::Use(ref use_tree) = item.kind {
self.allocate_use_tree_hir_id_counters(use_tree);
}
visit::walk_item(self, item);
}
fn visit_assoc_item(&mut self, item: &'tcx AssocItem, ctxt: AssocCtxt) {
self.lctx.allocate_hir_id_counter(item.id);
visit::walk_assoc_item(self, item, ctxt);
}
fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) {
self.lctx.allocate_hir_id_counter(item.id);
visit::walk_foreign_item(self, item);
}
}
self.lower_node_id(CRATE_NODE_ID);
debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == Some(hir::CRATE_HIR_ID));
visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
let module = self.arena.alloc(self.lower_mod(&c.items, c.span));
self.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
self.owners.ensure_contains_elem(CRATE_DEF_ID, || None);
self.owners[CRATE_DEF_ID] = Some(hir::OwnerNode::Crate(module));
self.with_hir_id_owner(CRATE_NODE_ID, |lctx| {
let module = lctx.lower_mod(&c.items, c.span);
lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
hir::OwnerNode::Crate(lctx.arena.alloc(module))
});
let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
for (k, v) in self.resolver.take_trait_map().into_iter() {
@ -502,61 +449,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
let krate = hir::Crate {
owners: self.owners,
bodies: self.bodies,
modules: self.modules,
trait_map,
attrs: self.attrs,
};
let krate =
hir::Crate { owners: self.owners, bodies: self.bodies, trait_map, attrs: self.attrs };
self.arena.alloc(krate)
}
fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId {
let id = item.item_id();
let item = self.arena.alloc(item);
self.owners.ensure_contains_elem(id.def_id, || None);
self.owners[id.def_id] = Some(hir::OwnerNode::Item(item));
self.modules.entry(self.current_module).or_default().items.insert(id);
id
}
fn insert_foreign_item(&mut self, item: hir::ForeignItem<'hir>) -> hir::ForeignItemId {
let id = item.foreign_item_id();
let item = self.arena.alloc(item);
self.owners.ensure_contains_elem(id.def_id, || None);
self.owners[id.def_id] = Some(hir::OwnerNode::ForeignItem(item));
self.modules.entry(self.current_module).or_default().foreign_items.insert(id);
id
}
fn insert_impl_item(&mut self, item: hir::ImplItem<'hir>) -> hir::ImplItemId {
let id = item.impl_item_id();
let item = self.arena.alloc(item);
self.owners.ensure_contains_elem(id.def_id, || None);
self.owners[id.def_id] = Some(hir::OwnerNode::ImplItem(item));
self.modules.entry(self.current_module).or_default().impl_items.insert(id);
id
}
fn insert_trait_item(&mut self, item: hir::TraitItem<'hir>) -> hir::TraitItemId {
let id = item.trait_item_id();
let item = self.arena.alloc(item);
self.owners.ensure_contains_elem(id.def_id, || None);
self.owners[id.def_id] = Some(hir::OwnerNode::TraitItem(item));
self.modules.entry(self.current_module).or_default().trait_items.insert(id);
id
}
fn allocate_hir_id_counter(&mut self, owner: NodeId) -> hir::HirId {
// Set up the counter if needed.
self.item_local_id_counters.entry(owner).or_insert(0);
// Always allocate the first `HirId` for the owner itself.
let lowered = self.lower_node_id_with_owner(owner, owner);
debug_assert_eq!(lowered.local_id.as_u32(), 0);
lowered
}
fn create_stable_hashing_context(&self) -> LoweringHasher<'_> {
LoweringHasher {
source_map: CachingSourceMapView::new(self.sess.source_map()),
@ -564,47 +461,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
fn lower_node_id_generic(
fn with_hir_id_owner(
&mut self,
ast_node_id: NodeId,
alloc_hir_id: impl FnOnce(&mut Self) -> hir::HirId,
) -> hir::HirId {
assert_ne!(ast_node_id, DUMMY_NODE_ID);
let min_size = ast_node_id.as_usize() + 1;
if min_size > self.node_id_to_hir_id.len() {
self.node_id_to_hir_id.resize(min_size, None);
}
if let Some(existing_hir_id) = self.node_id_to_hir_id[ast_node_id] {
existing_hir_id
} else {
// Generate a new `HirId`.
let hir_id = alloc_hir_id(self);
self.node_id_to_hir_id[ast_node_id] = Some(hir_id);
hir_id
}
}
fn with_hir_id_owner<T>(&mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
let counter = self
.item_local_id_counters
.insert(owner, HIR_ID_COUNTER_LOCKED)
.unwrap_or_else(|| panic!("no `item_local_id_counters` entry for {:?}", owner));
owner: NodeId,
f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>,
) -> LocalDefId {
let def_id = self.resolver.local_def_id(owner);
let old_owner = std::mem::replace(&mut self.current_hir_id_owner, (def_id, counter));
let ret = f(self);
let (new_def_id, new_counter) =
std::mem::replace(&mut self.current_hir_id_owner, old_owner);
debug_assert!(def_id == new_def_id);
debug_assert!(new_counter >= counter);
// Always allocate the first `HirId` for the owner itself.
let _old = self.node_id_to_hir_id.insert(owner, hir::HirId::make_owner(def_id));
debug_assert_eq!(_old, None);
let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap();
debug_assert!(prev == HIR_ID_COUNTER_LOCKED);
ret
let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id);
let current_local_counter =
std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
let item = f(self);
self.current_hir_id_owner = current_owner;
self.item_local_id_counter = current_local_counter;
let _old = self.owners.insert(def_id, item);
debug_assert!(_old.is_none());
def_id
}
/// This method allocates a new `HirId` for the given `NodeId` and stores it in
@ -614,34 +494,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped
/// properly. Calling the method twice with the same `NodeId` is fine though.
fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId {
self.lower_node_id_generic(ast_node_id, |this| {
let &mut (owner, ref mut local_id_counter) = &mut this.current_hir_id_owner;
let local_id = *local_id_counter;
*local_id_counter += 1;
hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
})
}
assert_ne!(ast_node_id, DUMMY_NODE_ID);
fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hir::HirId {
self.lower_node_id_generic(ast_node_id, |this| {
let local_id_counter = this
.item_local_id_counters
.get_mut(&owner)
.expect("called `lower_node_id_with_owner` before `allocate_hir_id_counter`");
let local_id = *local_id_counter;
// We want to be sure not to modify the counter in the map while it
// is also on the stack. Otherwise we'll get lost updates when writing
// back from the stack to the map.
debug_assert!(local_id != HIR_ID_COUNTER_LOCKED);
*local_id_counter += 1;
let owner = this.resolver.opt_local_def_id(owner).expect(
"you forgot to call `create_def` or are lowering node-IDs \
that do not belong to the current owner",
);
hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
*self.node_id_to_hir_id.get_or_insert_with(ast_node_id, || {
// Generate a new `HirId`.
let owner = self.current_hir_id_owner;
let local_id = self.item_local_id_counter;
self.item_local_id_counter.increment_by(1);
hir::HirId { owner, local_id }
})
}
@ -652,7 +512,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_res(&mut self, res: Res<NodeId>) -> Res {
res.map_id(|id| {
self.lower_node_id_generic(id, |_| {
self.node_id_to_hir_id.get(id).copied().flatten().unwrap_or_else(|| {
panic!("expected `NodeId` to be lowered already for res {:#?}", res);
})
})
@ -712,9 +572,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
/// Intercept all spans entering HIR.
/// For now we are not doing anything with the intercepted spans.
/// Mark a span as relative to the current owning item.
fn lower_span(&self, span: Span) -> Span {
span
if self.sess.opts.debugging_opts.incremental_relative_spans {
span.with_parent(Some(self.current_hir_id_owner))
} else {
// Do not make spans relative when not using incremental compilation.
span
}
}
fn lower_ident(&self, ident: Ident) -> Ident {
@ -782,7 +647,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
node_id,
DefPathData::LifetimeNs(str_name),
ExpnId::root(),
span,
span.with_parent(None),
);
hir::GenericParam {
@ -883,7 +748,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// wouldn't have been added yet.
let generics = this.lower_generics_mut(
generics,
ImplTraitContext::Universal(&mut params, this.current_hir_id_owner.0),
ImplTraitContext::Universal(&mut params, this.current_hir_id_owner),
);
let res = f(this, &mut params);
(params, (generics, res))
@ -911,11 +776,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let was_in_loop_condition = self.is_in_loop_condition;
self.is_in_loop_condition = false;
let catch_scopes = mem::take(&mut self.catch_scopes);
let loop_scopes = mem::take(&mut self.loop_scopes);
let catch_scope = self.catch_scope.take();
let loop_scope = self.loop_scope.take();
let ret = f(self);
self.catch_scopes = catch_scopes;
self.loop_scopes = loop_scopes;
self.catch_scope = catch_scope;
self.loop_scope = loop_scope;
self.is_in_loop_condition = was_in_loop_condition;
@ -1089,7 +954,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
AssocTyConstraintKind::Bound { ref bounds } => {
let mut capturable_lifetimes;
let mut parent_def_id = self.current_hir_id_owner.0;
let mut parent_def_id = self.current_hir_id_owner;
// Piggy-back on the `impl Trait` context to figure out the correct behavior.
let (desugar_to_impl_trait, itctx) = match itctx {
// We are in the return position:
@ -1217,7 +1082,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Construct an AnonConst where the expr is the "ty"'s path.
let parent_def_id = self.current_hir_id_owner.0;
let parent_def_id = self.current_hir_id_owner;
let node_id = self.resolver.next_node_id();
// Add a definition for the in-band const def.
@ -1305,7 +1170,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
generic_params: this.lower_generic_params(
&f.generic_params,
&NodeMap::default(),
ImplTraitContext::disallowed(),
),
unsafety: this.lower_unsafety(f.unsafety),
@ -1486,198 +1350,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id);
self.allocate_hir_id_counter(opaque_ty_node_id);
let mut collected_lifetimes = Vec::new();
self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
let hir_bounds = lower_bounds(lctx);
let hir_bounds = self.with_hir_id_owner(opaque_ty_node_id, lower_bounds);
collected_lifetimes = lifetimes_from_impl_trait_bounds(
opaque_ty_node_id,
&hir_bounds,
capturable_lifetimes,
);
let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
opaque_ty_node_id,
opaque_ty_def_id,
&hir_bounds,
capturable_lifetimes,
);
debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes);
debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs);
self.with_hir_id_owner(opaque_ty_node_id, move |lctx| {
let opaque_ty_item = hir::OpaqueTy {
generics: hir::Generics {
params: lifetime_defs,
where_clause: hir::WhereClause { predicates: &[], span: lctx.lower_span(span) },
span: lctx.lower_span(span),
},
bounds: hir_bounds,
impl_trait_fn: fn_def_id,
origin,
};
trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id);
lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span);
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
})
}
/// Registers a new opaque type with the proper `NodeId`s and
/// returns the lowered node-ID for the opaque type.
fn generate_opaque_type(
&mut self,
opaque_ty_id: LocalDefId,
opaque_ty_item: hir::OpaqueTy<'hir>,
span: Span,
opaque_ty_span: Span,
) {
let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item);
// Generate an `type Foo = impl Trait;` declaration.
trace!("registering opaque type with id {:#?}", opaque_ty_id);
let opaque_ty_item = hir::Item {
def_id: opaque_ty_id,
ident: Ident::invalid(),
kind: opaque_ty_item_kind,
vis: respan(self.lower_span(span.shrink_to_lo()), hir::VisibilityKind::Inherited),
span: self.lower_span(opaque_ty_span),
};
// Insert the item into the global item list. This usually happens
// automatically for all AST items. But this opaque type item
// does not actually exist in the AST.
self.insert_item(opaque_ty_item);
}
fn lifetimes_from_impl_trait_bounds(
&mut self,
opaque_ty_id: NodeId,
parent_def_id: LocalDefId,
bounds: hir::GenericBounds<'hir>,
lifetimes_to_include: Option<&FxHashSet<hir::LifetimeName>>,
) -> (&'hir [hir::GenericArg<'hir>], &'hir [hir::GenericParam<'hir>]) {
debug!(
"lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
parent_def_id={:?}, \
bounds={:#?})",
opaque_ty_id, parent_def_id, bounds,
);
// This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
// appear in the bounds, excluding lifetimes that are created within the bounds.
// E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
struct ImplTraitLifetimeCollector<'r, 'a, 'hir> {
context: &'r mut LoweringContext<'a, 'hir>,
parent: LocalDefId,
opaque_ty_id: NodeId,
collect_elided_lifetimes: bool,
currently_bound_lifetimes: Vec<hir::LifetimeName>,
already_defined_lifetimes: FxHashSet<hir::LifetimeName>,
output_lifetimes: Vec<hir::GenericArg<'hir>>,
output_lifetime_params: Vec<hir::GenericParam<'hir>>,
lifetimes_to_include: Option<&'r FxHashSet<hir::LifetimeName>>,
}
impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
type Map = intravisit::ErasedMap<'v>;
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
intravisit::NestedVisitorMap::None
}
fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs<'v>) {
// Don't collect elided lifetimes used inside of `Fn()` syntax.
if parameters.parenthesized {
let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
self.collect_elided_lifetimes = false;
intravisit::walk_generic_args(self, span, parameters);
self.collect_elided_lifetimes = old_collect_elided_lifetimes;
} else {
intravisit::walk_generic_args(self, span, parameters);
}
}
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
// Don't collect elided lifetimes used inside of `fn()` syntax.
if let hir::TyKind::BareFn(_) = t.kind {
let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
self.collect_elided_lifetimes = false;
// Record the "stack height" of `for<'a>` lifetime bindings
// to be able to later fully undo their introduction.
let old_len = self.currently_bound_lifetimes.len();
intravisit::walk_ty(self, t);
self.currently_bound_lifetimes.truncate(old_len);
self.collect_elided_lifetimes = old_collect_elided_lifetimes;
} else {
intravisit::walk_ty(self, t)
}
}
fn visit_poly_trait_ref(
&mut self,
trait_ref: &'v hir::PolyTraitRef<'v>,
modifier: hir::TraitBoundModifier,
) {
// Record the "stack height" of `for<'a>` lifetime bindings
// to be able to later fully undo their introduction.
let old_len = self.currently_bound_lifetimes.len();
intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
self.currently_bound_lifetimes.truncate(old_len);
}
fn visit_generic_param(&mut self, param: &'v hir::GenericParam<'v>) {
// Record the introduction of 'a in `for<'a> ...`.
if let hir::GenericParamKind::Lifetime { .. } = param.kind {
// Introduce lifetimes one at a time so that we can handle
// cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`.
let lt_name = hir::LifetimeName::Param(param.name);
self.currently_bound_lifetimes.push(lt_name);
}
intravisit::walk_generic_param(self, param);
}
fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
let name = match lifetime.name {
hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
if self.collect_elided_lifetimes {
// Use `'_` for both implicit and underscore lifetimes in
// `type Foo<'_> = impl SomeTrait<'_>;`.
hir::LifetimeName::Underscore
} else {
return;
}
}
hir::LifetimeName::Param(_) => lifetime.name,
// Refers to some other lifetime that is "in
// scope" within the type.
hir::LifetimeName::ImplicitObjectLifetimeDefault => return,
hir::LifetimeName::Error | hir::LifetimeName::Static => return,
};
if !self.currently_bound_lifetimes.contains(&name)
&& !self.already_defined_lifetimes.contains(&name)
&& self.lifetimes_to_include.map_or(true, |lifetimes| lifetimes.contains(&name))
{
self.already_defined_lifetimes.insert(name);
self.output_lifetimes.push(hir::GenericArg::Lifetime(hir::Lifetime {
hir_id: self.context.next_id(),
span: self.context.lower_span(lifetime.span),
name,
}));
let def_node_id = self.context.resolver.next_node_id();
let hir_id =
self.context.lower_node_id_with_owner(def_node_id, self.opaque_ty_id);
self.context.resolver.create_def(
self.parent,
let lifetime_defs =
lctx.arena.alloc_from_iter(collected_lifetimes.iter().map(|&(name, span)| {
let def_node_id = lctx.resolver.next_node_id();
let hir_id = lctx.lower_node_id(def_node_id);
lctx.resolver.create_def(
opaque_ty_def_id,
def_node_id,
DefPathData::LifetimeNs(name.ident().name),
ExpnId::root(),
lifetime.span,
span.with_parent(None),
);
let (name, kind) = match name {
@ -1690,48 +1382,65 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
_ => panic!("expected `LifetimeName::Param` or `ParamName::Plain`"),
};
let name = match name {
hir::ParamName::Plain(ident) => {
hir::ParamName::Plain(self.context.lower_ident(ident))
}
name => name,
};
self.output_lifetime_params.push(hir::GenericParam {
hir::GenericParam {
hir_id,
name,
span: self.context.lower_span(lifetime.span),
span,
pure_wrt_drop: false,
bounds: &[],
kind: hir::GenericParamKind::Lifetime { kind },
});
}
}
}
}
}));
let mut lifetime_collector = ImplTraitLifetimeCollector {
context: self,
parent: parent_def_id,
opaque_ty_id,
collect_elided_lifetimes: true,
currently_bound_lifetimes: Vec::new(),
already_defined_lifetimes: FxHashSet::default(),
output_lifetimes: Vec::new(),
output_lifetime_params: Vec::new(),
lifetimes_to_include,
debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs);
let opaque_ty_item = hir::OpaqueTy {
generics: hir::Generics {
params: lifetime_defs,
where_clause: hir::WhereClause { predicates: &[], span: lctx.lower_span(span) },
span: lctx.lower_span(span),
},
bounds: hir_bounds,
impl_trait_fn: fn_def_id,
origin,
};
trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id);
lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span)
});
let lifetimes =
self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(name, span)| {
hir::GenericArg::Lifetime(hir::Lifetime { hir_id: self.next_id(), span, name })
}));
debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes);
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
}
/// Registers a new opaque type with the proper `NodeId`s and
/// returns the lowered node-ID for the opaque type.
fn generate_opaque_type(
&mut self,
opaque_ty_id: LocalDefId,
opaque_ty_item: hir::OpaqueTy<'hir>,
span: Span,
opaque_ty_span: Span,
) -> hir::OwnerNode<'hir> {
let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item);
// Generate an `type Foo = impl Trait;` declaration.
trace!("registering opaque type with id {:#?}", opaque_ty_id);
let opaque_ty_item = hir::Item {
def_id: opaque_ty_id,
ident: Ident::invalid(),
kind: opaque_ty_item_kind,
vis: respan(self.lower_span(span.shrink_to_lo()), hir::VisibilityKind::Inherited),
span: self.lower_span(opaque_ty_span),
};
for bound in bounds {
intravisit::walk_param_bound(&mut lifetime_collector, &bound);
}
let ImplTraitLifetimeCollector { output_lifetimes, output_lifetime_params, .. } =
lifetime_collector;
(
self.arena.alloc_from_iter(output_lifetimes),
self.arena.alloc_from_iter(output_lifetime_params),
)
hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
}
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
@ -1800,7 +1509,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
if let Some((_, ibty)) = &mut in_band_ty_params {
this.lower_ty_direct(
&param.ty,
ImplTraitContext::Universal(ibty, this.current_hir_id_owner.0),
ImplTraitContext::Universal(ibty, this.current_hir_id_owner),
)
} else {
this.lower_ty_direct(&param.ty, ImplTraitContext::disallowed())
@ -1893,8 +1602,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id);
self.allocate_hir_id_counter(opaque_ty_node_id);
// When we create the opaque type for this async fn, it is going to have
// to capture all the lifetimes involved in the signature (including in the
// return type). This is done by introducing lifetime parameters for:
@ -1943,7 +1650,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// grow.
let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len();
let lifetime_params = self.with_hir_id_owner(opaque_ty_node_id, |this| {
let mut lifetime_params = Vec::new();
self.with_hir_id_owner(opaque_ty_node_id, |this| {
// We have to be careful to get elision right here. The
// idea is that we create a lifetime parameter for each
// lifetime in the return type. So, given a return type
@ -1965,7 +1673,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
//
// Note: this must be done after lowering the output type,
// as the output type may introduce new in-band lifetimes.
let lifetime_params: Vec<(Span, ParamName)> = this
lifetime_params = this
.in_scope_lifetimes
.iter()
.cloned()
@ -1994,9 +1702,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
};
trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span);
lifetime_params
this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span)
});
// As documented above on the variable
@ -2138,30 +1844,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_generic_params_mut<'s>(
&'s mut self,
params: &'s [GenericParam],
add_bounds: &'s NodeMap<Vec<GenericBound>>,
mut itctx: ImplTraitContext<'s, 'hir>,
) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
params
.iter()
.map(move |param| self.lower_generic_param(param, add_bounds, itctx.reborrow()))
params.iter().map(move |param| self.lower_generic_param(param, itctx.reborrow()))
}
fn lower_generic_params(
&mut self,
params: &[GenericParam],
add_bounds: &NodeMap<Vec<GenericBound>>,
itctx: ImplTraitContext<'_, 'hir>,
) -> &'hir [hir::GenericParam<'hir>] {
self.arena.alloc_from_iter(self.lower_generic_params_mut(params, add_bounds, itctx))
self.arena.alloc_from_iter(self.lower_generic_params_mut(params, itctx))
}
fn lower_generic_param(
&mut self,
param: &GenericParam,
add_bounds: &NodeMap<Vec<GenericBound>>,
mut itctx: ImplTraitContext<'_, 'hir>,
) -> hir::GenericParam<'hir> {
let mut bounds: Vec<_> = self
let bounds: Vec<_> = self
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
this.lower_param_bounds_mut(&param.bounds, itctx.reborrow()).collect()
});
@ -2197,12 +1898,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
(param_name, kind)
}
GenericParamKind::Type { ref default, .. } => {
let add_bounds = add_bounds.get(&param.id).map_or(&[][..], |x| &x);
if !add_bounds.is_empty() {
let params = self.lower_param_bounds_mut(add_bounds, itctx.reborrow());
bounds.extend(params);
}
let kind = hir::GenericParamKind::Type {
default: default.as_ref().map(|x| {
self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other))
@ -2263,11 +1958,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
p: &PolyTraitRef,
mut itctx: ImplTraitContext<'_, 'hir>,
) -> hir::PolyTraitRef<'hir> {
let bound_generic_params = self.lower_generic_params(
&p.bound_generic_params,
&NodeMap::default(),
itctx.reborrow(),
);
let bound_generic_params =
self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
// Any impl Trait types defined within this scope can capture
@ -2714,3 +2406,132 @@ impl<'hir> GenericArgsCtor<'hir> {
this.arena.alloc(ga)
}
}
fn lifetimes_from_impl_trait_bounds(
opaque_ty_id: NodeId,
bounds: hir::GenericBounds<'_>,
lifetimes_to_include: Option<&FxHashSet<hir::LifetimeName>>,
) -> Vec<(hir::LifetimeName, Span)> {
debug!(
"lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
bounds={:#?})",
opaque_ty_id, bounds,
);
// This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
// appear in the bounds, excluding lifetimes that are created within the bounds.
// E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
struct ImplTraitLifetimeCollector<'r> {
collect_elided_lifetimes: bool,
currently_bound_lifetimes: Vec<hir::LifetimeName>,
already_defined_lifetimes: FxHashSet<hir::LifetimeName>,
lifetimes: Vec<(hir::LifetimeName, Span)>,
lifetimes_to_include: Option<&'r FxHashSet<hir::LifetimeName>>,
}
impl<'r, 'v> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r> {
type Map = intravisit::ErasedMap<'v>;
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
intravisit::NestedVisitorMap::None
}
fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs<'v>) {
// Don't collect elided lifetimes used inside of `Fn()` syntax.
if parameters.parenthesized {
let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
self.collect_elided_lifetimes = false;
intravisit::walk_generic_args(self, span, parameters);
self.collect_elided_lifetimes = old_collect_elided_lifetimes;
} else {
intravisit::walk_generic_args(self, span, parameters);
}
}
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
// Don't collect elided lifetimes used inside of `fn()` syntax.
if let hir::TyKind::BareFn(_) = t.kind {
let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
self.collect_elided_lifetimes = false;
// Record the "stack height" of `for<'a>` lifetime bindings
// to be able to later fully undo their introduction.
let old_len = self.currently_bound_lifetimes.len();
intravisit::walk_ty(self, t);
self.currently_bound_lifetimes.truncate(old_len);
self.collect_elided_lifetimes = old_collect_elided_lifetimes;
} else {
intravisit::walk_ty(self, t)
}
}
fn visit_poly_trait_ref(
&mut self,
trait_ref: &'v hir::PolyTraitRef<'v>,
modifier: hir::TraitBoundModifier,
) {
// Record the "stack height" of `for<'a>` lifetime bindings
// to be able to later fully undo their introduction.
let old_len = self.currently_bound_lifetimes.len();
intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
self.currently_bound_lifetimes.truncate(old_len);
}
fn visit_generic_param(&mut self, param: &'v hir::GenericParam<'v>) {
// Record the introduction of 'a in `for<'a> ...`.
if let hir::GenericParamKind::Lifetime { .. } = param.kind {
// Introduce lifetimes one at a time so that we can handle
// cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`.
let lt_name = hir::LifetimeName::Param(param.name);
self.currently_bound_lifetimes.push(lt_name);
}
intravisit::walk_generic_param(self, param);
}
fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
let name = match lifetime.name {
hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
if self.collect_elided_lifetimes {
// Use `'_` for both implicit and underscore lifetimes in
// `type Foo<'_> = impl SomeTrait<'_>;`.
hir::LifetimeName::Underscore
} else {
return;
}
}
hir::LifetimeName::Param(_) => lifetime.name,
// Refers to some other lifetime that is "in
// scope" within the type.
hir::LifetimeName::ImplicitObjectLifetimeDefault => return,
hir::LifetimeName::Error | hir::LifetimeName::Static => return,
};
if !self.currently_bound_lifetimes.contains(&name)
&& !self.already_defined_lifetimes.contains(&name)
&& self.lifetimes_to_include.map_or(true, |lifetimes| lifetimes.contains(&name))
{
self.already_defined_lifetimes.insert(name);
self.lifetimes.push((name, lifetime.span));
}
}
}
let mut lifetime_collector = ImplTraitLifetimeCollector {
collect_elided_lifetimes: true,
currently_bound_lifetimes: Vec::new(),
already_defined_lifetimes: FxHashSet::default(),
lifetimes: Vec::new(),
lifetimes_to_include,
};
for bound in bounds {
intravisit::walk_param_bound(&mut lifetime_collector, &bound);
}
lifetime_collector.lifetimes
}

View File

@ -99,7 +99,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
num_lifetimes,
parenthesized_generic_args,
itctx.reborrow(),
None,
)
},
)),
@ -147,7 +146,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
0,
ParenthesizedGenericArgs::Err,
itctx.reborrow(),
None,
));
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
@ -178,7 +176,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
res: Res,
p: &Path,
param_mode: ParamMode,
explicit_owner: Option<NodeId>,
) -> &'hir hir::Path<'hir> {
self.arena.alloc(hir::Path {
res,
@ -190,7 +187,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
0,
ParenthesizedGenericArgs::Err,
ImplTraitContext::disallowed(),
explicit_owner,
)
})),
span: self.lower_span(p.span),
@ -205,7 +201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) -> &'hir hir::Path<'hir> {
let res = self.expect_full_res(id);
let res = self.lower_res(res);
self.lower_path_extra(res, p, param_mode, None)
self.lower_path_extra(res, p, param_mode)
}
crate fn lower_path_segment(
@ -216,7 +212,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
expected_lifetimes: usize,
parenthesized_generic_args: ParenthesizedGenericArgs,
itctx: ImplTraitContext<'_, 'hir>,
explicit_owner: Option<NodeId>,
) -> hir::PathSegment<'hir> {
debug!(
"path_span: {:?}, lower_path_segment(segment: {:?}, expected_lifetimes: {:?})",
@ -354,11 +349,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
let res = self.expect_full_res(segment.id);
let id = if let Some(owner) = explicit_owner {
self.lower_node_id_with_owner(segment.id, owner)
} else {
self.lower_node_id(segment.id)
};
let id = self.lower_node_id(segment.id);
debug!(
"lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
segment.ident, segment.id, id,

View File

@ -1,7 +1,7 @@
[package]
name = "rustc_ast_passes"
version = "0.0.0"
edition = "2018"
edition = "2021"
[dependencies]
itertools = "0.9"

View File

@ -356,11 +356,25 @@ impl<'a> AstValidator<'a> {
}
fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
self.check_decl_num_args(fn_decl);
self.check_decl_cvaradic_pos(fn_decl);
self.check_decl_attrs(fn_decl);
self.check_decl_self_param(fn_decl, self_semantic);
}
/// Emits fatal error if function declaration has more than `u16::MAX` arguments
/// Error is fatal to prevent errors during typechecking
fn check_decl_num_args(&self, fn_decl: &FnDecl) {
let max_num_args: usize = u16::MAX.into();
if fn_decl.inputs.len() > max_num_args {
let Param { span, .. } = fn_decl.inputs[0];
self.err_handler().span_fatal(
span,
&format!("function can not have more than {} arguments", max_num_args),
);
}
}
fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) {
match &*fn_decl.inputs {
[Param { ty, span, .. }] => {
@ -576,7 +590,7 @@ impl<'a> AstValidator<'a> {
)
.span_label(self.current_extern_span(), "in this `extern` block")
.note(&format!(
"This limitation may be lifted in the future; see issue #{} <https://github.com/rust-lang/rust/issues/{}> for more information",
"this limitation may be lifted in the future; see issue #{} <https://github.com/rust-lang/rust/issues/{}> for more information",
n, n,
))
.emit();
@ -669,31 +683,53 @@ impl<'a> AstValidator<'a> {
}
}
fn emit_e0568(&self, span: Span, ident_span: Span) {
struct_span_err!(
self.session,
span,
E0568,
"auto traits cannot have super traits or lifetime bounds"
)
.span_label(ident_span, "auto trait cannot have super traits or lifetime bounds")
.span_suggestion(
span,
"remove the super traits or lifetime bounds",
String::new(),
Applicability::MachineApplicable,
)
.emit();
}
fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
if let [first @ last] | [first, .., last] = &bounds[..] {
let span = first.span().to(last.span());
struct_span_err!(self.session, span, E0568, "auto traits cannot have super traits")
.span_label(ident_span, "auto trait cannot have super traits")
.span_suggestion(
span,
"remove the super traits",
String::new(),
Applicability::MachineApplicable,
)
.emit();
if let [.., last] = &bounds[..] {
let span = ident_span.shrink_to_hi().to(last.span());
self.emit_e0568(span, ident_span);
}
}
fn deny_where_clause(&self, where_clause: &WhereClause, ident_span: Span) {
if !where_clause.predicates.is_empty() {
self.emit_e0568(where_clause.span, ident_span);
}
}
fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
if !trait_items.is_empty() {
let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
let total_span = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
struct_span_err!(
self.session,
spans,
E0380,
"auto traits cannot have methods or associated items"
"auto traits cannot have associated items"
)
.span_label(ident_span, "auto trait cannot have items")
.span_suggestion(
total_span,
"remove these associated items",
String::new(),
Applicability::MachineApplicable,
)
.span_label(ident_span, "auto trait cannot have associated items")
.emit();
}
}
@ -1170,6 +1206,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
// Auto traits cannot have generics, super traits nor contain items.
self.deny_generic_params(generics, item.ident.span);
self.deny_super_traits(bounds, item.ident.span);
self.deny_where_clause(&generics.where_clause, item.ident.span);
self.deny_items(trait_items, item.ident.span);
}
self.no_questions_in_bounds(bounds, "supertraits", true);
@ -1587,7 +1624,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
walk_list!(self, visit_ty, ty);
}
AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body))
if self.in_const_trait_impl || ctxt == AssocCtxt::Trait =>
if self.in_const_trait_impl
|| ctxt == AssocCtxt::Trait
|| matches!(sig.header.constness, Const::Yes(_)) =>
{
self.visit_vis(&item.vis);
self.visit_ident(item.ident);

View File

@ -319,6 +319,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
gate_doc!(
cfg => doc_cfg
cfg_hide => doc_cfg_hide
masked => doc_masked
notable_trait => doc_notable_trait
keyword => doc_keyword
@ -762,10 +763,16 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
}
fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
// checks if `#![feature]` has been used to enable any lang feature
// does not check the same for lib features unless there's at least one
// declared lang feature
use rustc_errors::Applicability;
if !sess.opts.unstable_features.is_nightly_build() {
let lang_features = &sess.features_untracked().declared_lang_features;
if lang_features.len() == 0 {
return;
}
for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) {
let mut err = struct_span_err!(
sess.parse_sess.span_diagnostic,

View File

@ -4,7 +4,6 @@
//!
//! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`.
#![cfg_attr(bootstrap, feature(bindings_after_at))]
#![feature(iter_is_partitioned)]
#![feature(box_patterns)]
#![recursion_limit = "256"]

View File

@ -1,7 +1,7 @@
[package]
name = "rustc_ast_pretty"
version = "0.0.0"
edition = "2018"
edition = "2021"
[lib]
doctest = false

View File

@ -1,7 +1,7 @@
[package]
name = "rustc_attr"
version = "0.0.0"
edition = "2018"
edition = "2021"
[lib]
doctest = false

View File

@ -66,7 +66,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
}
}
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)]
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum InlineAttr {
None,
Hint,
@ -74,13 +74,13 @@ pub enum InlineAttr {
Never,
}
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, HashStable_Generic)]
pub enum InstructionSetAttr {
ArmA32,
ArmT32,
}
#[derive(Clone, Encodable, Decodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum OptimizeAttr {
None,
Speed,
@ -802,7 +802,7 @@ impl IntType {
/// Valid repr contents: any of the primitive integral type names (see
/// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
/// the same discriminant size that the corresponding C enum would or C
/// structure layout, `packed` to remove padding, and `transparent` to elegate representation
/// structure layout, `packed` to remove padding, and `transparent` to delegate representation
/// concerns to the only non-ZST field.
pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
use ReprAttr::*;

View File

@ -1,37 +1,30 @@
[package]
name = "rustc_mir"
name = "rustc_borrowck"
version = "0.0.0"
edition = "2018"
edition = "2021"
[lib]
doctest = false
[dependencies]
either = "1.5.0"
rustc_graphviz = { path = "../rustc_graphviz" }
gsgdt = "0.1.2"
itertools = "0.9"
tracing = "0.1"
polonius-engine = "0.13.0"
regex = "1"
rustc_middle = { path = "../rustc_middle" }
rustc_attr = { path = "../rustc_attr" }
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_graphviz = { path = "../rustc_graphviz" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_const_eval = { path = "../rustc_const_eval" }
rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_traits = { path = "../rustc_traits" }
rustc_ast = { path = "../rustc_ast" }
rustc_span = { path = "../rustc_span" }
rustc_apfloat = { path = "../rustc_apfloat" }
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
[dev-dependencies]
coverage_test_macros = { path = "src/transform/coverage/test_macros" }

View File

@ -1,14 +1,14 @@
use crate::borrow_check::nll::ToRegionVid;
use crate::borrow_check::path_utils::allow_two_phase_borrow;
use crate::borrow_check::place_ext::PlaceExt;
use crate::dataflow::indexes::BorrowIndex;
use crate::dataflow::move_paths::MoveData;
use crate::nll::ToRegionVid;
use crate::path_utils::allow_two_phase_borrow;
use crate::place_ext::PlaceExt;
use crate::BorrowIndex;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::traversal;
use rustc_middle::mir::visit::{MutatingUseContext, NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{self, Body, Local, Location};
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_mir_dataflow::move_paths::MoveData;
use std::fmt;
use std::ops::Index;

View File

@ -2,7 +2,7 @@ use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::{MultiSpan, Span};
impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> {
impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
crate fn cannot_move_when_borrowed(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> {
struct_span_err!(self, span, E0505, "cannot move out of {} because it is borrowed", desc,)
}

View File

@ -9,7 +9,7 @@ use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, RegionVid, Ty};
use crate::borrow_check::{
use crate::{
borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, nll::ToRegionVid,
places_conflict, region_infer::values::LivenessValues,
};

View File

@ -4,7 +4,7 @@ use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
use rustc_span::DUMMY_SP;
use crate::borrow_check::{
use crate::{
constraints::OutlivesConstraintIndex,
constraints::{OutlivesConstraint, OutlivesConstraintSet},
type_check::Locations,

View File

@ -5,7 +5,7 @@ use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
use std::fmt;
use std::ops::Index;
use crate::borrow_check::type_check::Locations;
use crate::type_check::Locations;
crate mod graph;

View File

@ -14,7 +14,9 @@ pub use super::{
};
/// This function computes Polonius facts for the given body. It makes a copy of
/// the body because it needs to regenerate the region identifiers.
/// the body because it needs to regenerate the region identifiers. This function
/// should never be invoked during a typical compilation session due to performance
/// issues with Polonius.
///
/// Note:
/// * This function will panic if the required body was already stolen. This
@ -22,8 +24,6 @@ pub use super::{
/// because they are evaluated during typechecking. The panic can be avoided
/// by overriding the `mir_borrowck` query. You can find a complete example
/// that shows how to do this at `src/test/run-make/obtain-borrowck/`.
/// * This function will also panic if computation of Polonius facts
/// (`-Zpolonius` flag) is not enabled.
///
/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
pub fn get_body_with_borrowck_facts<'tcx>(
@ -31,7 +31,7 @@ pub fn get_body_with_borrowck_facts<'tcx>(
def: ty::WithOptConstParam<LocalDefId>,
) -> BodyWithBorrowckFacts<'tcx> {
let (input_body, promoted) = tcx.mir_promoted(def);
tcx.infer_ctxt().enter(|infcx| {
tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| {
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexVec<_, _> = &promoted.borrow();
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()

View File

@ -1,18 +1,111 @@
use rustc_middle::mir::{self, Body, Location, Place};
use rustc_middle::ty::RegionVid;
use rustc_middle::ty::TyCtxt;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::bit_set::BitSet;
use crate::borrow_check::{
places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, ToRegionVid,
};
use crate::dataflow::{self, fmt::DebugWithContext, GenKill};
use rustc_middle::mir::{self, BasicBlock, Body, Location, Place};
use rustc_middle::ty::RegionVid;
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
use rustc_mir_dataflow::ResultsVisitable;
use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill};
use rustc_mir_dataflow::{Analysis, Direction, Results};
use std::fmt;
use std::iter;
use crate::{
places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, ToRegionVid,
};
/// A tuple with named fields that can hold either the results or the transient state of the
/// dataflow analyses used by the borrow checker.
#[derive(Debug)]
pub struct BorrowckAnalyses<B, U, E> {
pub borrows: B,
pub uninits: U,
pub ever_inits: E,
}
/// The results of the dataflow analyses used by the borrow checker.
pub type BorrowckResults<'mir, 'tcx> = BorrowckAnalyses<
Results<'tcx, Borrows<'mir, 'tcx>>,
Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
>;
/// The transient state of the dataflow analyses used by the borrow checker.
pub type BorrowckFlowState<'mir, 'tcx> =
<BorrowckResults<'mir, 'tcx> as ResultsVisitable<'tcx>>::FlowState;
macro_rules! impl_visitable {
( $(
$T:ident { $( $field:ident : $A:ident ),* $(,)? }
)* ) => { $(
impl<'tcx, $($A),*, D: Direction> ResultsVisitable<'tcx> for $T<$( Results<'tcx, $A> ),*>
where
$( $A: Analysis<'tcx, Direction = D>, )*
{
type Direction = D;
type FlowState = $T<$( $A::Domain ),*>;
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
$T {
$( $field: self.$field.analysis.bottom_value(body) ),*
}
}
fn reset_to_block_entry(
&self,
state: &mut Self::FlowState,
block: BasicBlock,
) {
$( state.$field.clone_from(&self.$field.entry_set_for_block(block)); )*
}
fn reconstruct_before_statement_effect(
&self,
state: &mut Self::FlowState,
stmt: &mir::Statement<'tcx>,
loc: Location,
) {
$( self.$field.analysis
.apply_before_statement_effect(&mut state.$field, stmt, loc); )*
}
fn reconstruct_statement_effect(
&self,
state: &mut Self::FlowState,
stmt: &mir::Statement<'tcx>,
loc: Location,
) {
$( self.$field.analysis
.apply_statement_effect(&mut state.$field, stmt, loc); )*
}
fn reconstruct_before_terminator_effect(
&self,
state: &mut Self::FlowState,
term: &mir::Terminator<'tcx>,
loc: Location,
) {
$( self.$field.analysis
.apply_before_terminator_effect(&mut state.$field, term, loc); )*
}
fn reconstruct_terminator_effect(
&self,
state: &mut Self::FlowState,
term: &mir::Terminator<'tcx>,
loc: Location,
) {
$( self.$field.analysis
.apply_terminator_effect(&mut state.$field, term, loc); )*
}
}
)* }
}
impl_visitable! {
BorrowckAnalyses { borrows: B, uninits: U, ever_inits: E }
}
rustc_index::newtype_index! {
pub struct BorrowIndex {
DEBUG_FORMAT = "bw{}"
@ -108,7 +201,7 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
let bb_data = &self.body[bb];
debug_assert!(hi == bb_data.statements.len());
for &succ_bb in bb_data.terminator().successors() {
if self.visited.insert(succ_bb) == false {
if !self.visited.insert(succ_bb) {
if succ_bb == location.block && first_lo > 0 {
// `succ_bb` has been seen before. If it wasn't
// fully processed, add its first part to `stack`
@ -230,7 +323,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
}
}
impl<'tcx> 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";
@ -246,7 +339,7 @@ impl<'tcx> dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
}
}
impl<'tcx> dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
type Idx = BorrowIndex;
fn before_statement_effect(

View File

@ -9,13 +9,13 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op;
use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _};
use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_span};
use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
use std::fmt;
use std::rc::Rc;
use crate::borrow_check::region_infer::values::RegionElement;
use crate::borrow_check::MirBorrowckCtxt;
use crate::region_infer::values::RegionElement;
use crate::MirBorrowckCtxt;
#[derive(Clone)]
crate struct UniverseInfo<'tcx>(UniverseInfoInner<'tcx>);
@ -45,13 +45,12 @@ impl UniverseInfo<'tcx> {
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
placeholder: ty::PlaceholderRegion,
error_element: RegionElement,
span: Span,
cause: ObligationCause<'tcx>,
) {
match self.0 {
UniverseInfoInner::RelateTys { expected, found } => {
let body_id = mbcx.infcx.tcx.hir().local_def_id_to_hir_id(mbcx.mir_def_id());
let err = mbcx.infcx.report_mismatched_types(
&ObligationCause::misc(span, body_id),
&cause,
expected,
found,
TypeError::RegionsPlaceholderMismatch,
@ -59,7 +58,7 @@ impl UniverseInfo<'tcx> {
err.buffer(&mut mbcx.errors_buffer);
}
UniverseInfoInner::TypeOp(ref type_op_info) => {
type_op_info.report_error(mbcx, placeholder, error_element, span);
type_op_info.report_error(mbcx, placeholder, error_element, cause);
}
UniverseInfoInner::Other => {
// FIXME: This error message isn't great, but it doesn't show
@ -68,7 +67,7 @@ impl UniverseInfo<'tcx> {
mbcx.infcx
.tcx
.sess
.struct_span_err(span, "higher-ranked subtype error")
.struct_span_err(cause.span, "higher-ranked subtype error")
.buffer(&mut mbcx.errors_buffer);
}
}
@ -130,7 +129,7 @@ trait TypeOpInfo<'tcx> {
fn nice_error(
&self,
tcx: TyCtxt<'tcx>,
span: Span,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>>;
@ -140,7 +139,7 @@ trait TypeOpInfo<'tcx> {
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
placeholder: ty::PlaceholderRegion,
error_element: RegionElement,
span: Span,
cause: ObligationCause<'tcx>,
) {
let tcx = mbcx.infcx.tcx;
let base_universe = self.base_universe();
@ -150,7 +149,7 @@ trait TypeOpInfo<'tcx> {
{
adjusted
} else {
self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer);
self.fallback_error(tcx, cause.span).buffer(&mut mbcx.errors_buffer);
return;
};
@ -175,7 +174,8 @@ trait TypeOpInfo<'tcx> {
debug!(?placeholder_region);
let nice_error = self.nice_error(tcx, span, placeholder_region, error_region);
let span = cause.span;
let nice_error = self.nice_error(tcx, cause, placeholder_region, error_region);
if let Some(nice_error) = nice_error {
nice_error.buffer(&mut mbcx.errors_buffer);
@ -205,15 +205,24 @@ impl TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
fn nice_error(
&self,
tcx: TyCtxt<'tcx>,
span: Span,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> {
tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
type_op_prove_predicate_with_span(infcx, &mut *fulfill_cx, key, Some(span));
try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
})
tcx.infer_ctxt().enter_with_canonical(
cause.span,
&self.canonical_query,
|ref infcx, key, _| {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
try_extract_error_from_fulfill_cx(
fulfill_cx,
infcx,
placeholder_region,
error_region,
)
},
)
}
}
@ -239,32 +248,41 @@ where
fn nice_error(
&self,
tcx: TyCtxt<'tcx>,
span: Span,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> {
tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
tcx.infer_ctxt().enter_with_canonical(
cause.span,
&self.canonical_query,
|ref infcx, key, _| {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
let mut selcx = SelectionContext::new(infcx);
let mut selcx = SelectionContext::new(infcx);
// FIXME(lqd): Unify and de-duplicate the following with the actual
// `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
// `ObligationCause`. The normalization results are currently different between
// `AtExt::normalize` used in the query and `normalize` called below: the former fails
// to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
// after #85499 lands to see if its fixes have erased this difference.
let (param_env, value) = key.into_parts();
let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize(
&mut selcx,
param_env,
ObligationCause::dummy_with_span(span),
value.value,
);
fulfill_cx.register_predicate_obligations(infcx, obligations);
// FIXME(lqd): Unify and de-duplicate the following with the actual
// `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
// `ObligationCause`. The normalization results are currently different between
// `AtExt::normalize` used in the query and `normalize` called below: the former fails
// to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
// after #85499 lands to see if its fixes have erased this difference.
let (param_env, value) = key.into_parts();
let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize(
&mut selcx,
param_env,
cause,
value.value,
);
fulfill_cx.register_predicate_obligations(infcx, obligations);
try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
})
try_extract_error_from_fulfill_cx(
fulfill_cx,
infcx,
placeholder_region,
error_region,
)
},
)
}
}
@ -287,18 +305,29 @@ impl TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
fn nice_error(
&self,
tcx: TyCtxt<'tcx>,
span: Span,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> {
tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(span)).ok()?;
try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
})
tcx.infer_ctxt().enter_with_canonical(
cause.span,
&self.canonical_query,
|ref infcx, key, _| {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span))
.ok()?;
try_extract_error_from_fulfill_cx(
fulfill_cx,
infcx,
placeholder_region,
error_region,
)
},
)
}
}
#[instrument(skip(fulfill_cx, infcx), level = "debug")]
fn try_extract_error_from_fulfill_cx<'tcx>(
mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
infcx: &InferCtxt<'_, 'tcx>,
@ -313,7 +342,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
let _errors = fulfill_cx.select_all_or_error(infcx).err().unwrap_or_else(Vec::new);
let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| {
debug!(?region_constraints);
debug!("{:#?}", region_constraints);
region_constraints.constraints.iter().find_map(|(constraint, cause)| {
match *constraint {
Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => {
@ -328,7 +357,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
})
})?;
debug!(?sub_region, ?cause);
debug!(?sub_region, "cause = {:#?}", cause);
let nice_error = match (error_region, sub_region) {
(Some(error_region), &ty::ReVar(vid)) => NiceRegionError::new(
infcx,

View File

@ -10,16 +10,15 @@ use rustc_middle::mir::{
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
};
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::sym;
use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtExt;
use crate::dataflow::drop_flag_effects;
use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex};
use crate::util::borrowck_errors;
use crate::borrowck_errors;
use crate::borrow_check::{
use crate::{
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
};
@ -49,7 +48,7 @@ enum StorageDeadOrDrop<'tcx> {
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
pub(crate) fn report_use_of_moved_or_uninitialized(
&mut self,
location: Location,
desired_action: InitializationRequiringAction,
@ -218,7 +217,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
if self.fn_self_span_reported.insert(fn_span) {
err.span_note(
self_arg.span,
// Check whether the source is accessible
if self
.infcx
.tcx
.sess
.source_map()
.span_to_snippet(self_arg.span)
.is_ok()
{
self_arg.span
} else {
fn_call_span
},
"calling this operator moves the left-hand side",
);
}
@ -429,7 +440,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
deref_target_ty
));
err.span_note(deref_target, "deref defined here");
// Check first whether the source is accessible (issue #87060)
if self.infcx.tcx.sess.source_map().span_to_snippet(deref_target).is_ok() {
err.span_note(deref_target, "deref defined here");
}
}
if let Some((_, mut old_err)) =
@ -441,7 +455,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
pub(in crate::borrow_check) fn report_move_out_while_borrowed(
pub(crate) fn report_move_out_while_borrowed(
&mut self,
location: Location,
(place, span): (Place<'tcx>, Span),
@ -489,7 +503,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.buffer(&mut self.errors_buffer);
}
pub(in crate::borrow_check) fn report_use_while_mutably_borrowed(
pub(crate) fn report_use_while_mutably_borrowed(
&mut self,
location: Location,
(place, _span): (Place<'tcx>, Span),
@ -535,7 +549,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err
}
pub(in crate::borrow_check) fn report_conflicting_borrow(
pub(crate) fn report_conflicting_borrow(
&mut self,
location: Location,
(place, span): (Place<'tcx>, Span),
@ -798,7 +812,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as
/// mutable (via `a.u.s.b`) [E0502]
/// ```
pub(in crate::borrow_check) fn describe_place_for_conflicting_borrow(
pub(crate) fn describe_place_for_conflicting_borrow(
&self,
first_borrowed_place: Place<'tcx>,
second_borrowed_place: Place<'tcx>,
@ -875,7 +889,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// short a lifetime. (But sometimes it is more useful to report
/// it as a more direct conflict between the execution of a
/// `Drop::drop` with an aliasing borrow.)
pub(in crate::borrow_check) fn report_borrowed_value_does_not_live_long_enough(
pub(crate) fn report_borrowed_value_does_not_live_long_enough(
&mut self,
location: Location,
borrow: &BorrowData<'tcx>,
@ -1516,25 +1530,45 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
let mut mpis = vec![mpi];
let move_paths = &self.move_data.move_paths;
mpis.extend(move_paths[mpi].parents(move_paths).map(|(mpi, _)| mpi));
let mut stack = Vec::new();
stack.extend(predecessor_locations(self.body, location).map(|predecessor| {
let is_back_edge = location.dominates(predecessor, &self.dominators);
(predecessor, is_back_edge)
}));
let mut back_edge_stack = Vec::new();
predecessor_locations(self.body, location).for_each(|predecessor| {
if location.dominates(predecessor, &self.dominators) {
back_edge_stack.push(predecessor)
} else {
stack.push(predecessor);
}
});
let mut reached_start = false;
/* Check if the mpi is initialized as an argument */
let mut is_argument = false;
for arg in self.body.args_iter() {
let path = self.move_data.rev_lookup.find_local(arg);
if mpis.contains(&path) {
is_argument = true;
}
}
let mut visited = FxHashSet::default();
let mut move_locations = FxHashSet::default();
let mut reinits = vec![];
let mut result = vec![];
'dfs: while let Some((location, is_back_edge)) = stack.pop() {
let mut dfs_iter = |result: &mut Vec<MoveSite>, location: Location, is_back_edge: bool| {
debug!(
"report_use_of_moved_or_uninitialized: (current_location={:?}, back_edge={})",
location, is_back_edge
);
if !visited.insert(location) {
continue;
return true;
}
// check for moves
@ -1553,10 +1587,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// worry about the other case: that is, if there is a move of a.b.c, it is already
// marked as a move of a.b and a as well, so we will generate the correct errors
// there.
let mut mpis = vec![mpi];
let move_paths = &self.move_data.move_paths;
mpis.extend(move_paths[mpi].parents(move_paths).map(|(mpi, _)| mpi));
for moi in &self.move_data.loc_map[location] {
debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi);
let path = self.move_data.moves[*moi].path;
@ -1584,33 +1614,70 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Because we stop the DFS here, we only highlight `let c = a`,
// and not `let b = a`. We will of course also report an error at
// `let c = a` which highlights `let b = a` as the move.
continue 'dfs;
return true;
}
}
}
// check for inits
let mut any_match = false;
drop_flag_effects::for_location_inits(
self.infcx.tcx,
&self.body,
self.move_data,
location,
|m| {
if m == mpi {
any_match = true;
for ii in &self.move_data.init_loc_map[location] {
let init = self.move_data.inits[*ii];
match init.kind {
InitKind::Deep | InitKind::NonPanicPathOnly => {
if mpis.contains(&init.path) {
any_match = true;
}
}
},
);
InitKind::Shallow => {
if mpi == init.path {
any_match = true;
}
}
}
}
if any_match {
reinits.push(location);
continue 'dfs;
return true;
}
return false;
};
while let Some(location) = stack.pop() {
if dfs_iter(&mut result, location, false) {
continue;
}
stack.extend(predecessor_locations(self.body, location).map(|predecessor| {
let back_edge = location.dominates(predecessor, &self.dominators);
(predecessor, is_back_edge || back_edge)
}));
let mut has_predecessor = false;
predecessor_locations(self.body, location).for_each(|predecessor| {
if location.dominates(predecessor, &self.dominators) {
back_edge_stack.push(predecessor)
} else {
stack.push(predecessor);
}
has_predecessor = true;
});
if !has_predecessor {
reached_start = true;
}
}
if (is_argument || !reached_start) && result.is_empty() {
/* Process back edges (moves in future loop iterations) only if
the move path is definitely initialized upon loop entry,
to avoid spurious "in previous iteration" errors.
During DFS, if there's a path from the error back to the start
of the function with no intervening init or move, then the
move path may be uninitialized at loop entry.
*/
while let Some(location) = back_edge_stack.pop() {
if dfs_iter(&mut result, location, true) {
continue;
}
predecessor_locations(self.body, location)
.for_each(|predecessor| back_edge_stack.push(predecessor));
}
}
// Check if we can reach these reinits from a move location.
@ -1634,7 +1701,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(result, reinits_reachable)
}
pub(in crate::borrow_check) fn report_illegal_mutation_of_borrowed(
pub(crate) fn report_illegal_mutation_of_borrowed(
&mut self,
location: Location,
(place, span): (Place<'tcx>, Span),
@ -1695,7 +1762,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Some((method_did, method_substs)),
) = (
&self.body[loan.reserve_location.block].terminator,
crate::util::find_self_call(
rustc_const_eval::util::find_self_call(
tcx,
self.body,
loan.assigned_place.local,
@ -1726,7 +1793,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// assigned; `err_place` is a place providing a reason why
/// `place` is not mutable (e.g., the non-`mut` local `x` in an
/// assignment to `x.f`).
pub(in crate::borrow_check) fn report_illegal_reassignment(
pub(crate) fn report_illegal_reassignment(
&mut self,
_location: Location,
(place, span): (Place<'tcx>, Span),
@ -2226,7 +2293,7 @@ enum AnnotatedBorrowFnSignature<'tcx> {
impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
/// Annotate the provided diagnostic with information about borrow from the fn signature that
/// helps explain.
pub(in crate::borrow_check) fn emit(
pub(crate) fn emit(
&self,
cx: &mut MirBorrowckCtxt<'_, 'tcx>,
diag: &mut DiagnosticBuilder<'_>,

View File

@ -15,8 +15,8 @@ use rustc_middle::ty::{self, RegionVid, TyCtxt};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use crate::borrow_check::region_infer::BlameConstraint;
use crate::borrow_check::{
use crate::region_infer::BlameConstraint;
use crate::{
borrow_set::BorrowData, nll::ConstraintDescription, region_infer::Cause, MirBorrowckCtxt,
WriteKind,
};
@ -24,7 +24,7 @@ use crate::borrow_check::{
use super::{find_use, RegionName, UseSpans};
#[derive(Debug)]
pub(in crate::borrow_check) enum BorrowExplanation {
pub(crate) enum BorrowExplanation {
UsedLater(LaterUseKind, Span, Option<Span>),
UsedLaterInLoop(LaterUseKind, Span, Option<Span>),
UsedLaterWhenDropped {
@ -43,7 +43,7 @@ pub(in crate::borrow_check) enum BorrowExplanation {
}
#[derive(Clone, Copy, Debug)]
pub(in crate::borrow_check) enum LaterUseKind {
pub(crate) enum LaterUseKind {
TraitCapture,
ClosureCapture,
Call,
@ -52,13 +52,13 @@ pub(in crate::borrow_check) enum LaterUseKind {
}
impl BorrowExplanation {
pub(in crate::borrow_check) fn is_explained(&self) -> bool {
pub(crate) fn is_explained(&self) -> bool {
match self {
BorrowExplanation::Unexplained => false,
_ => true,
}
}
pub(in crate::borrow_check) fn add_explanation_to_diagnostic<'tcx>(
pub(crate) fn add_explanation_to_diagnostic<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
@ -267,7 +267,7 @@ impl BorrowExplanation {
_ => {}
}
}
pub(in crate::borrow_check) fn add_lifetime_bound_suggestion_to_diagnostic(
pub(crate) fn add_lifetime_bound_suggestion_to_diagnostic(
&self,
err: &mut DiagnosticBuilder<'_>,
category: &ConstraintCategory,
@ -300,7 +300,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow_region: RegionVid,
outlived_region: RegionVid,
) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
let BlameConstraint { category, from_closure, span, variance_info: _ } =
let BlameConstraint { category, from_closure, cause, variance_info: _ } =
self.regioncx.best_blame_constraint(
&self.body,
borrow_region,
@ -310,7 +310,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let outlived_fr_name = self.give_region_a_name(outlived_region);
(category, from_closure, span, outlived_fr_name)
(category, from_closure, cause.span, outlived_fr_name)
}
/// Returns structured explanation for *why* the borrow contains the
@ -326,7 +326,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// - second half is the place being accessed
///
/// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points
pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
pub(crate) fn explain_why_borrow_contains_point(
&self,
location: Location,
borrow: &BorrowData<'tcx>,

View File

@ -1,7 +1,7 @@
use std::collections::VecDeque;
use std::rc::Rc;
use crate::borrow_check::{
use crate::{
def_use::{self, DefUse},
nll::ToRegionVid,
region_infer::{Cause, RegionInferenceContext},

View File

@ -12,6 +12,7 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
use rustc_span::{
hygiene::{DesugaringKind, ForLoopLoc},
symbol::sym,
@ -21,7 +22,6 @@ use rustc_target::abi::VariantIdx;
use super::borrow_set::BorrowData;
use super::MirBorrowckCtxt;
use crate::dataflow::move_paths::{InitLocation, LookupResult};
mod find_use;
mod outlives_suggestion;
@ -900,8 +900,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}) = &self.body[location.block].terminator
{
let (method_did, method_substs) = if let Some(info) =
crate::util::find_self_call(self.infcx.tcx, &self.body, target_temp, location.block)
{
rustc_const_eval::util::find_self_call(
self.infcx.tcx,
&self.body,
target_temp,
location.block,
) {
info
} else {
return normal_ret;
@ -962,8 +966,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
_ => None,
});
let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
tcx.is_diagnostic_item(sym::option_type, def_id)
|| tcx.is_diagnostic_item(sym::result_type, def_id)
tcx.is_diagnostic_item(sym::Option, def_id)
|| tcx.is_diagnostic_item(sym::Result, def_id)
});
FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result }
});

View File

@ -2,16 +2,16 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::*;
use rustc_middle::ty;
use rustc_mir_dataflow::move_paths::{
IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
};
use rustc_span::source_map::DesugaringKind;
use rustc_span::{sym, Span, DUMMY_SP};
use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
use crate::borrow_check::diagnostics::UseSpans;
use crate::borrow_check::prefixes::PrefixSet;
use crate::borrow_check::MirBorrowckCtxt;
use crate::dataflow::move_paths::{
IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
};
use crate::diagnostics::UseSpans;
use crate::prefixes::PrefixSet;
use crate::MirBorrowckCtxt;
// Often when desugaring a pattern match we may have many individual moves in
// MIR that are all part of one operation from the user's point-of-view. For
@ -336,15 +336,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if def_id.as_local() == Some(self.mir_def_id()) && upvar_field.is_some() =>
{
let closure_kind_ty = closure_substs.as_closure().kind_ty();
let closure_kind = closure_kind_ty.to_opt_closure_kind();
let capture_description = match closure_kind {
Some(ty::ClosureKind::Fn) => "captured variable in an `Fn` closure",
Some(ty::ClosureKind::FnMut) => "captured variable in an `FnMut` closure",
let closure_kind = match closure_kind_ty.to_opt_closure_kind() {
Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind,
Some(ty::ClosureKind::FnOnce) => {
bug!("closure kind does not match first argument type")
}
None => bug!("closure kind not inferred by borrowck"),
};
let capture_description =
format!("captured variable in an `{}` closure", closure_kind);
let upvar = &self.upvars[upvar_field.unwrap().index()];
let upvar_hir_id = upvar.place.get_root_variable();
@ -368,6 +368,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let mut diag = self.cannot_move_out_of(span, &place_description);
diag.span_label(upvar_span, "captured outer variable");
diag.span_label(
self.body.span,
format!("captured by this `{}` closure", closure_kind),
);
diag
}
@ -396,8 +400,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
| ty::Opaque(def_id, _) => def_id,
_ => return err,
};
let is_option = self.infcx.tcx.is_diagnostic_item(sym::option_type, def_id);
let is_result = self.infcx.tcx.is_diagnostic_item(sym::result_type, def_id);
let is_option = self.infcx.tcx.is_diagnostic_item(sym::Option, def_id);
let is_result = self.infcx.tcx.is_diagnostic_item(sym::Result, def_id);
if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) {
err.span_suggestion_verbose(
span.shrink_to_hi(),

View File

@ -14,9 +14,9 @@ use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{BytePos, Span};
use crate::borrow_check::diagnostics::BorrowedContentSource;
use crate::borrow_check::MirBorrowckCtxt;
use crate::util::collect_writes::FindAssignments;
use crate::diagnostics::BorrowedContentSource;
use crate::MirBorrowckCtxt;
use rustc_const_eval::util::collect_writes::FindAssignments;
use rustc_errors::{Applicability, DiagnosticBuilder};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -972,8 +972,7 @@ fn suggest_ampmut<'tcx>(
if let Some(assignment_rhs_span) = opt_assignment_rhs_span {
if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) {
let is_mutbl = |ty: &str| -> bool {
if ty.starts_with("mut") {
let rest = &ty[3..];
if let Some(rest) = ty.strip_prefix("mut") {
match rest.chars().next() {
// e.g. `&mut x`
Some(c) if c.is_whitespace() => true,

View File

@ -1,16 +1,14 @@
//! Contains utilities for generating suggestions for borrowck errors related to unsatisfied
//! outlives constraints.
use std::collections::BTreeMap;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::DiagnosticBuilder;
use rustc_middle::ty::RegionVid;
use smallvec::SmallVec;
use std::collections::BTreeMap;
use tracing::debug;
use smallvec::SmallVec;
use crate::borrow_check::MirBorrowckCtxt;
use crate::MirBorrowckCtxt;
use super::{ErrorConstraintInfo, RegionName, RegionNameSource};
@ -173,9 +171,7 @@ impl OutlivesSuggestionBuilder {
let outlived_fr_name = self.region_vid_to_name(mbcx, errci.outlived_fr);
if let (Some(fr_name), Some(outlived_fr_name)) = (fr_name, outlived_fr_name) {
if let RegionNameSource::Static = outlived_fr_name.source {
diag.help(&format!("consider replacing `{}` with `'static`", fr_name));
} else {
if !matches!(outlived_fr_name.source, RegionNameSource::Static) {
diag.help(&format!(
"consider adding the following bound: `{}: {}`",
fr_name, outlived_fr_name

View File

@ -11,18 +11,17 @@ use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_span::symbol::{kw, sym};
use rustc_span::{BytePos, Span};
use crate::util::borrowck_errors;
use crate::borrowck_errors;
use crate::borrow_check::region_infer::BlameConstraint;
use crate::borrow_check::{
use super::{OutlivesSuggestionBuilder, RegionName};
use crate::region_infer::BlameConstraint;
use crate::{
nll::ConstraintDescription,
region_infer::{values::RegionElement, TypeTest},
universal_regions::DefiningTy,
MirBorrowckCtxt,
};
use super::{OutlivesSuggestionBuilder, RegionName};
impl ConstraintDescription for ConstraintCategory {
fn description(&self) -> &'static str {
// Must end with a space. Allows for empty names to be provided.
@ -40,7 +39,9 @@ impl ConstraintDescription for ConstraintCategory {
ConstraintCategory::CopyBound => "copying this value ",
ConstraintCategory::OpaqueType => "opaque type ",
ConstraintCategory::ClosureUpvar(_) => "closure capture ",
ConstraintCategory::Boring
ConstraintCategory::Usage => "this usage ",
ConstraintCategory::Predicate(_)
| ConstraintCategory::Boring
| ConstraintCategory::BoringNoLocation
| ConstraintCategory::Internal => "",
}
@ -152,7 +153,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
/// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`.
pub(in crate::borrow_check) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
pub(crate) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
// Iterate through all the errors, producing a diagnostic for each one. The diagnostics are
// buffered in the `MirBorrowckCtxt`.
@ -216,7 +217,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let error_vid = self.regioncx.region_from_element(longer_fr, &error_element);
// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
let (_, span) = self.regioncx.find_outlives_blame_span(
let (_, cause) = self.regioncx.find_outlives_blame_span(
&self.body,
longer_fr,
NllRegionVariableOrigin::Placeholder(placeholder),
@ -226,7 +227,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let universe = placeholder.universe;
let universe_info = self.regioncx.universe_info(universe);
universe_info.report_error(self, placeholder, error_element, span);
universe_info.report_error(self, placeholder, error_element, cause);
}
RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
@ -265,7 +266,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// ```
///
/// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
pub(in crate::borrow_check) fn report_region_error(
pub(crate) fn report_region_error(
&mut self,
fr: RegionVid,
fr_origin: NllRegionVariableOrigin,
@ -274,15 +275,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
) {
debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
let BlameConstraint { category, span, variance_info, from_closure: _ } =
let BlameConstraint { category, cause, variance_info, from_closure: _ } =
self.regioncx.best_blame_constraint(&self.body, fr, fr_origin, |r| {
self.regioncx.provides_universal_region(r, fr, outlived_fr)
});
debug!("report_region_error: category={:?} {:?} {:?}", category, span, variance_info);
debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);
// Check if we can use one of the "nice region errors".
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
let nice = NiceRegionError::new_from_span(self.infcx, span, o, f);
let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f);
if let Some(diag) = nice.try_report_from_nll() {
diag.buffer(&mut self.errors_buffer);
return;
@ -305,7 +306,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
fr_is_local,
outlived_fr_is_local,
category,
span,
span: cause.span,
};
let mut diag = match (category, fr_is_local, outlived_fr_is_local) {
@ -497,6 +498,27 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
diag.span_label(*span, format!("`{}` escapes the {} body here", fr_name, escapes_from));
}
// Only show an extra note if we can find an 'error region' for both of the region
// variables. This avoids showing a noisy note that just mentions 'synthetic' regions
// that don't help the user understand the error.
if self.to_error_region(errci.fr).is_some()
&& self.to_error_region(errci.outlived_fr).is_some()
{
let fr_region_name = self.give_region_a_name(errci.fr).unwrap();
fr_region_name.highlight_region_name(&mut diag);
let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap();
outlived_fr_region_name.highlight_region_name(&mut diag);
diag.span_label(
*span,
format!(
"{}requires that `{}` must outlive `{}`",
category.description(),
fr_region_name,
outlived_fr_region_name,
),
);
}
diag
}

View File

@ -10,7 +10,7 @@ use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use crate::borrow_check::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt};
use crate::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt};
/// A name for a particular region used in emitting diagnostics. This name could be a generated
/// name like `'1`, a name used by the user like `'a`, or a name like `'static`.

View File

@ -1,5 +1,5 @@
use crate::borrow_check::Upvar;
use crate::borrow_check::{nll::ToRegionVid, region_infer::RegionInferenceContext};
use crate::Upvar;
use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext};
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir::{Body, Local};
use rustc_middle::ty::{RegionVid, TyCtxt};

View File

@ -1,10 +1,11 @@
use crate::borrow_check::location::{LocationIndex, LocationTable};
use crate::dataflow::indexes::{BorrowIndex, MovePathIndex};
use crate::location::{LocationIndex, LocationTable};
use crate::BorrowIndex;
use polonius_engine::AllFacts as PoloniusFacts;
use polonius_engine::Atom;
use rustc_index::vec::Idx;
use rustc_middle::mir::Local;
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_mir_dataflow::move_paths::MovePathIndex;
use std::error::Error;
use std::fmt::Debug;
use std::fs::{self, File};
@ -100,12 +101,6 @@ impl Atom for LocationIndex {
}
}
impl Atom for MovePathIndex {
fn index(self) -> usize {
Idx::index(self)
}
}
struct FactWriter<'w> {
location_table: &'w LocationTable,
dir: &'w Path,

View File

@ -7,12 +7,10 @@ use rustc_middle::mir::{Statement, StatementKind};
use rustc_middle::ty::TyCtxt;
use std::iter;
use crate::dataflow::indexes::BorrowIndex;
use crate::borrow_check::{
use crate::{
borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, path_utils::*, AccessDepth,
Activation, ArtificialField, Deep, JustWrite, LocalMutationIsAllowed, MutateMode, Read,
ReadKind, ReadOrWrite, Reservation, Shallow, Write, WriteAndRead, WriteKind,
Activation, ArtificialField, BorrowIndex, Deep, JustWrite, LocalMutationIsAllowed, MutateMode,
Read, ReadKind, ReadOrWrite, Reservation, Shallow, Write, WriteAndRead, WriteKind,
};
pub(super) fn generate_invalidates<'tcx>(
@ -318,7 +316,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
Rvalue::Use(ref operand)
| Rvalue::Repeat(ref operand, _)
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => {
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
| Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
self.consume_operand(location, operand)
}

View File

@ -1,5 +1,23 @@
//! This query borrow-checks the MIR to (further) ensure it is not broken.
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![cfg_attr(bootstrap, feature(const_panic))]
#![feature(crate_visibility_modifier)]
#![feature(format_args_capture)]
#![feature(in_band_lifetimes)]
#![feature(iter_zip)]
#![feature(min_specialization)]
#![feature(stmt_expr_attributes)]
#![feature(trusted_step)]
#![feature(try_blocks)]
#![recursion_limit = "256"]
#[macro_use]
extern crate rustc_middle;
#[macro_use]
extern crate tracing;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
@ -29,14 +47,13 @@ use std::iter;
use std::mem;
use std::rc::Rc;
use crate::dataflow;
use crate::dataflow::impls::{
Borrows, EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
use rustc_mir_dataflow::impls::{
EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
};
use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex};
use crate::dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveError};
use crate::dataflow::MoveDataParamEnv;
use crate::dataflow::{Analysis, BorrowckFlowState as Flows, BorrowckResults};
use rustc_mir_dataflow::move_paths::{InitIndex, MoveOutIndex, MovePathIndex};
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveError};
use rustc_mir_dataflow::Analysis;
use rustc_mir_dataflow::MoveDataParamEnv;
use self::diagnostics::{AccessKind, RegionName};
use self::location::LocationTable;
@ -47,9 +64,10 @@ use facts::AllFacts;
use self::path_utils::*;
mod borrow_set;
mod borrowck_errors;
mod constraint_generation;
mod constraints;
pub mod consumers;
mod dataflow;
mod def_use;
mod diagnostics;
mod facts;
@ -67,15 +85,19 @@ mod type_check;
mod universal_regions;
mod used_muts;
crate use borrow_set::{BorrowData, BorrowSet};
crate use nll::{PoloniusOutput, ToRegionVid};
crate use place_ext::PlaceExt;
crate use places_conflict::{places_conflict, PlaceConflictBias};
crate use region_infer::RegionInferenceContext;
// A public API provided for the Rust compiler consumers.
pub mod consumers;
use borrow_set::{BorrowData, BorrowSet};
use dataflow::{BorrowIndex, BorrowckFlowState as Flows, BorrowckResults, Borrows};
use nll::{PoloniusOutput, ToRegionVid};
use place_ext::PlaceExt;
use places_conflict::{places_conflict, PlaceConflictBias};
use region_infer::RegionInferenceContext;
// FIXME(eddyb) perhaps move this somewhere more centrally.
#[derive(Debug)]
crate struct Upvar<'tcx> {
struct Upvar<'tcx> {
place: CapturedPlace<'tcx>,
/// If true, the capture is behind a reference.
@ -122,6 +144,7 @@ fn mir_borrowck<'tcx>(
/// If `return_body_with_facts` is true, then return the body with non-erased
/// region ids on which the borrow checking was performed together with Polonius
/// facts.
#[instrument(skip(infcx, input_body, input_promoted), level = "debug")]
fn do_mir_borrowck<'a, 'tcx>(
infcx: &InferCtxt<'a, 'tcx>,
input_body: &Body<'tcx>,
@ -130,12 +153,7 @@ fn do_mir_borrowck<'a, 'tcx>(
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
let def = input_body.source.with_opt_param().as_local().unwrap();
debug!("do_mir_borrowck(def = {:?})", def);
assert!(
!return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius,
"borrowck facts can be requested only when Polonius is enabled"
);
debug!(?def);
let tcx = infcx.tcx;
let param_env = tcx.param_env(def.did);
@ -213,6 +231,8 @@ fn do_mir_borrowck<'a, 'tcx>(
let borrow_set =
Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
let use_polonius = return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius;
// Compute non-lexical lifetimes.
let nll::NllOutput {
regioncx,
@ -232,6 +252,7 @@ fn do_mir_borrowck<'a, 'tcx>(
&mdpe.move_data,
&borrow_set,
&upvars,
use_polonius,
);
// Dump MIR results into a file, if that is enabled. This let us
@ -256,26 +277,26 @@ fn do_mir_borrowck<'a, 'tcx>(
let regioncx = Rc::new(regioncx);
let flow_borrows = Borrows::new(tcx, &body, &regioncx, &borrow_set)
.into_engine(tcx, &body)
let flow_borrows = Borrows::new(tcx, body, &regioncx, &borrow_set)
.into_engine(tcx, body)
.pass_name("borrowck")
.iterate_to_fixpoint();
let flow_uninits = MaybeUninitializedPlaces::new(tcx, &body, &mdpe)
.into_engine(tcx, &body)
let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &mdpe)
.into_engine(tcx, body)
.pass_name("borrowck")
.iterate_to_fixpoint();
let flow_ever_inits = EverInitializedPlaces::new(tcx, &body, &mdpe)
.into_engine(tcx, &body)
let flow_ever_inits = EverInitializedPlaces::new(tcx, body, &mdpe)
.into_engine(tcx, body)
.pass_name("borrowck")
.iterate_to_fixpoint();
let movable_generator = match tcx.hir().get(id) {
let movable_generator = !matches!(
tcx.hir().get(id),
Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure(.., Some(hir::Movability::Static)),
..
}) => false,
_ => true,
};
})
);
for (idx, move_data_results) in promoted_errors {
let promoted_body = &promoted[idx];
@ -352,9 +373,9 @@ fn do_mir_borrowck<'a, 'tcx>(
mbcx.report_move_errors(move_errors);
dataflow::visit_results(
&body,
traversal::reverse_postorder(&body).map(|(bb, _)| bb),
rustc_mir_dataflow::visit_results(
body,
traversal::reverse_postorder(body).map(|(bb, _)| bb),
&results,
&mut mbcx,
);
@ -495,8 +516,8 @@ pub struct BodyWithBorrowckFacts<'tcx> {
pub location_table: LocationTable,
}
crate struct MirBorrowckCtxt<'cx, 'tcx> {
crate infcx: &'cx InferCtxt<'cx, 'tcx>,
struct MirBorrowckCtxt<'cx, 'tcx> {
infcx: &'cx InferCtxt<'cx, 'tcx>,
param_env: ParamEnv<'tcx>,
body: &'cx Body<'tcx>,
move_data: &'cx MoveData<'tcx>,
@ -594,7 +615,7 @@ crate 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> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx> {
impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx> {
type FlowState = Flows<'cx, 'tcx>;
fn visit_statement_before_primary_effect(
@ -1341,7 +1362,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Rvalue::Use(ref operand)
| Rvalue::Repeat(ref operand, _)
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => {
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
| Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
self.consume_operand(location, (operand, span), flow_state)
}
@ -2344,7 +2366,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// then returns the index of the field being projected. Note that this closure will always
/// be `self` in the current MIR, because that is the only time we directly access the fields
/// of a closure type.
pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field> {
fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field> {
path_utils::is_upvar_field_projection(self.infcx.tcx, &self.upvars, place_ref, self.body())
}
}

View File

@ -144,7 +144,7 @@ impl<R> MemberConstraintSet<'tcx, R>
where
R: Copy + Hash + Eq,
{
crate fn all_indices(&self) -> impl Iterator<Item = NllMemberConstraintIndex> {
crate fn all_indices(&self) -> impl Iterator<Item = NllMemberConstraintIndex> + '_ {
self.constraints.indices()
}

View File

@ -4,6 +4,7 @@ use rustc_data_structures::vec_map::VecMap;
use rustc_errors::Diagnostic;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
use rustc_middle::mir::{
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
Promoted,
@ -17,16 +18,13 @@ use std::path::PathBuf;
use std::rc::Rc;
use std::str::FromStr;
use self::mir_util::PassWhere;
use polonius_engine::{Algorithm, Output};
use crate::dataflow::impls::MaybeInitializedPlaces;
use crate::dataflow::move_paths::{InitKind, InitLocation, MoveData};
use crate::dataflow::ResultsCursor;
use crate::util as mir_util;
use crate::util::pretty;
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
use rustc_mir_dataflow::ResultsCursor;
use crate::borrow_check::{
use crate::{
borrow_set::BorrowSet,
constraint_generation,
diagnostics::RegionErrors,
@ -56,7 +54,8 @@ crate struct NllOutput<'tcx> {
/// Rewrites the regions in the MIR to use NLL variables, also scraping out the set of universal
/// regions (e.g., region parameters) declared on the function. That set will need to be given to
/// `compute_regions`.
pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
#[instrument(skip(infcx, param_env, body, promoted), level = "debug")]
pub(crate) fn replace_regions_in_mir<'cx, 'tcx>(
infcx: &InferCtxt<'cx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &mut Body<'tcx>,
@ -64,7 +63,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
) -> UniversalRegions<'tcx> {
let def = body.source.with_opt_param().as_local().unwrap();
debug!("replace_regions_in_mir(def={:?})", def);
debug!(?def);
// Compute named region information. This also renumbers the inputs/outputs.
let universal_regions = UniversalRegions::new(infcx, def, param_env);
@ -72,7 +71,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
// Replace all remaining regions with fresh inference variables.
renumber::renumber_mir(infcx, body, promoted);
mir_util::dump_mir(infcx.tcx, None, "renumber", &0, body, |_, _| Ok(()));
dump_mir(infcx.tcx, None, "renumber", &0, body, |_, _| Ok(()));
universal_regions
}
@ -155,7 +154,7 @@ fn populate_polonius_move_facts(
/// Computes the (non-lexical) regions from the input MIR.
///
/// This may result in errors being reported.
pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
pub(crate) fn compute_regions<'cx, 'tcx>(
infcx: &InferCtxt<'cx, 'tcx>,
universal_regions: UniversalRegions<'tcx>,
body: &Body<'tcx>,
@ -166,8 +165,10 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
move_data: &MoveData<'tcx>,
borrow_set: &BorrowSet<'tcx>,
upvars: &[Upvar<'tcx>],
use_polonius: bool,
) -> NllOutput<'tcx> {
let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default());
let mut all_facts =
(use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
let universal_regions = Rc::new(universal_regions);
@ -283,7 +284,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
all_facts.write_to_dir(dir_path, location_table).unwrap();
}
if infcx.tcx.sess.opts.debugging_opts.polonius {
if use_polonius {
let algorithm =
env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid"));
let algorithm = Algorithm::from_str(&algorithm).unwrap();
@ -322,11 +323,11 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
) {
if !mir_util::dump_enabled(infcx.tcx, "nll", body.source.def_id()) {
if !dump_enabled(infcx.tcx, "nll", body.source.def_id()) {
return;
}
mir_util::dump_mir(infcx.tcx, None, "nll", &0, body, |pass_where, out| {
dump_mir(infcx.tcx, None, "nll", &0, body, |pass_where, out| {
match pass_where {
// Before the CFG, dump out the values for each region variable.
PassWhere::BeforeCFG => {
@ -354,14 +355,14 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
// Also dump the inference graph constraints as a graphviz file.
let _: io::Result<()> = try {
let mut file =
pretty::create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, body.source)?;
create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, body.source)?;
regioncx.dump_graphviz_raw_constraints(&mut file)?;
};
// Also dump the inference graph constraints as a graphviz file.
let _: io::Result<()> = try {
let mut file =
pretty::create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, body.source)?;
create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, body.source)?;
regioncx.dump_graphviz_scc_constraints(&mut file)?;
};
}

View File

@ -1,8 +1,8 @@
use crate::borrow_check::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
use crate::borrow_check::places_conflict;
use crate::borrow_check::AccessDepth;
use crate::borrow_check::Upvar;
use crate::dataflow::indexes::BorrowIndex;
use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
use crate::places_conflict;
use crate::AccessDepth;
use crate::BorrowIndex;
use crate::Upvar;
use rustc_data_structures::graph::dominators::Dominators;
use rustc_middle::mir::BorrowKind;
use rustc_middle::mir::{BasicBlock, Body, Field, Location, Place, PlaceRef, ProjectionElem};

View File

@ -1,4 +1,4 @@
use crate::borrow_check::borrow_set::LocalsStateAtExit;
use crate::borrow_set::LocalsStateAtExit;
use rustc_hir as hir;
use rustc_middle::mir::ProjectionElem;
use rustc_middle::mir::{Body, Mutability, Place};

View File

@ -1,6 +1,6 @@
use crate::borrow_check::ArtificialField;
use crate::borrow_check::Overlap;
use crate::borrow_check::{AccessDepth, Deep, Shallow};
use crate::ArtificialField;
use crate::Overlap;
use crate::{AccessDepth, Deep, Shallow};
use rustc_hir as hir;
use rustc_middle::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem};
use rustc_middle::ty::{self, TyCtxt};

View File

@ -4,7 +4,7 @@
//! context internal state.
use super::{OutlivesConstraint, RegionInferenceContext};
use crate::borrow_check::type_check::Locations;
use crate::type_check::Locations;
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::ty::TyCtxt;
use std::io::{self, Write};

View File

@ -6,7 +6,7 @@ use std::borrow::Cow;
use std::io::{self, Write};
use super::*;
use crate::borrow_check::constraints::OutlivesConstraint;
use crate::constraints::OutlivesConstraint;
use rustc_graphviz as dot;
impl<'tcx> RegionInferenceContext<'tcx> {

View File

@ -5,7 +5,8 @@ use rustc_data_structures::binary_search_util;
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::scc::Sccs;
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::CRATE_HIR_ID;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
@ -14,10 +15,12 @@ use rustc_middle::mir::{
Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
ConstraintCategory, Local, Location, ReturnConstraint,
};
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use crate::borrow_check::{
use crate::{
constraints::{
graph::NormalConstraintGraph, ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
},
@ -85,7 +88,7 @@ pub struct RegionInferenceContext<'tcx> {
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
/// Map universe indexes to information on why we created it.
universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
/// Contains the minimum universe of any variable within the same
/// SCC. We will ensure that no SCC contains values that are not
@ -132,33 +135,33 @@ pub(crate) struct AppliedMemberConstraint {
///
/// The vector if `AppliedMemberConstraint` elements is kept sorted
/// by this field.
pub(in crate::borrow_check) member_region_scc: ConstraintSccIndex,
pub(crate) member_region_scc: ConstraintSccIndex,
/// The "best option" that `apply_member_constraint` found -- this was
/// added as an "ad-hoc" lower-bound to `member_region_scc`.
pub(in crate::borrow_check) min_choice: ty::RegionVid,
pub(crate) min_choice: ty::RegionVid,
/// The "member constraint index" -- we can find out details about
/// the constraint from
/// `set.member_constraints[member_constraint_index]`.
pub(in crate::borrow_check) member_constraint_index: NllMemberConstraintIndex,
pub(crate) member_constraint_index: NllMemberConstraintIndex,
}
pub(crate) struct RegionDefinition<'tcx> {
/// What kind of variable is this -- a free region? existential
/// variable? etc. (See the `NllRegionVariableOrigin` for more
/// info.)
pub(in crate::borrow_check) origin: NllRegionVariableOrigin,
pub(crate) origin: NllRegionVariableOrigin,
/// Which universe is this region variable defined in? This is
/// most often `ty::UniverseIndex::ROOT`, but when we encounter
/// forall-quantifiers like `for<'a> { 'a = 'b }`, we would create
/// the variable for `'a` in a fresh universe that extends ROOT.
pub(in crate::borrow_check) universe: ty::UniverseIndex,
pub(crate) universe: ty::UniverseIndex,
/// If this is 'static or an early-bound region, then this is
/// `Some(X)` where `X` is the name of the region.
pub(in crate::borrow_check) external_name: Option<ty::Region<'tcx>>,
pub(crate) external_name: Option<ty::Region<'tcx>>,
}
/// N.B., the variants in `Cause` are intentionally ordered. Lower
@ -245,7 +248,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
///
/// The `outlives_constraints` and `type_tests` are an initial set
/// of constraints produced by the MIR type check.
pub(in crate::borrow_check) fn new(
pub(crate) fn new(
var_infos: VarInfos,
universal_regions: Rc<UniversalRegions<'tcx>>,
placeholder_indices: Rc<PlaceholderIndices>,
@ -256,7 +259,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
Location,
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
>,
universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
type_tests: Vec<TypeTest<'tcx>>,
liveness_constraints: LivenessValues<RegionVid>,
elements: &Rc<RegionValueElements>,
@ -494,7 +497,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
/// Returns an iterator over all the region indices.
pub fn regions(&self) -> impl Iterator<Item = RegionVid> {
pub fn regions(&self) -> impl Iterator<Item = RegionVid> + '_ {
self.definitions.indices()
}
@ -534,7 +537,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// Once region solving has completed, this function will return
/// the member constraints that were applied to the value of a given
/// region `r`. See `AppliedMemberConstraint`.
pub(in crate::borrow_check) fn applied_member_constraints(
pub(crate) fn applied_member_constraints(
&self,
r: impl ToRegionVid,
) -> &[AppliedMemberConstraint] {
@ -549,6 +552,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// Performs region inference and report errors if we see any
/// unsatisfiable constraints. If this is a closure, returns the
/// region requirements to propagate to our creator, if any.
#[instrument(skip(self, infcx, body, polonius_output), level = "debug")]
pub(super) fn solve(
&mut self,
infcx: &InferCtxt<'_, 'tcx>,
@ -604,10 +608,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// for each region variable until all the constraints are
/// satisfied. Note that some values may grow **too** large to be
/// feasible, but we check this later.
#[instrument(skip(self, _body), level = "debug")]
fn propagate_constraints(&mut self, _body: &Body<'tcx>) {
debug!("propagate_constraints()");
debug!("propagate_constraints: constraints={:#?}", {
debug!("constraints={:#?}", {
let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
constraints.sort();
constraints
@ -634,12 +637,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// computed, by unioning the values of its successors.
/// Assumes that all successors have been computed already
/// (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) {
debug!("propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}", scc_a, scc_b);
debug!(?scc_b);
// ...and add elements from `B` into `A`. One complication
// arises because of universes: If `B` contains something
@ -660,11 +664,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.apply_member_constraint(scc_a, m_c_i, member_constraints.choice_regions(m_c_i));
}
debug!(
"propagate_constraint_sccs: scc_a = {:?} has value {:?}",
scc_a,
self.scc_values.region_value_str(scc_a),
);
debug!(value = ?self.scc_values.region_value_str(scc_a));
}
/// Invoked for each `R0 member of [R1..Rn]` constraint.
@ -678,14 +678,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// is considered a *lower bound*. If possible, we will modify
/// the constraint to set it equal to one of the option regions.
/// If we make any changes, returns true, else false.
#[instrument(skip(self, member_constraint_index), level = "debug")]
fn apply_member_constraint(
&mut self,
scc: ConstraintSccIndex,
member_constraint_index: NllMemberConstraintIndex,
choice_regions: &[ty::RegionVid],
) -> bool {
debug!("apply_member_constraint(scc={:?}, choice_regions={:#?})", scc, choice_regions,);
// Create a mutable vector of the options. We'll try to winnow
// them down.
let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec();
@ -711,7 +710,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.universal_regions_outlived_by(scc)
.all(|lb| self.universal_region_relations.outlives(o_r, lb))
});
debug!("apply_member_constraint: after lb, choice_regions={:?}", choice_regions);
debug!(?choice_regions, "after lb");
// Now find all the *upper bounds* -- that is, each UB is a
// free region that must outlive the member region `R0` (`UB:
@ -720,10 +719,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let rev_scc_graph = self.reverse_scc_graph();
let universal_region_relations = &self.universal_region_relations;
for ub in rev_scc_graph.upper_bounds(scc) {
debug!("apply_member_constraint: ub={:?}", ub);
debug!(?ub);
choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
}
debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions);
debug!(?choice_regions, "after ub");
// If we ruled everything out, we're done.
if choice_regions.is_empty() {
@ -732,7 +731,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Otherwise, we need to find the minimum remaining choice, if
// any, and take that.
debug!("apply_member_constraint: choice_regions remaining are {:#?}", choice_regions);
debug!("choice_regions remaining are {:#?}", choice_regions);
let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
@ -745,27 +744,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
};
let mut min_choice = choice_regions[0];
for &other_option in &choice_regions[1..] {
debug!(
"apply_member_constraint: min_choice={:?} other_option={:?}",
min_choice, other_option,
);
debug!(?min_choice, ?other_option,);
match min(min_choice, other_option) {
Some(m) => min_choice = m,
None => {
debug!(
"apply_member_constraint: {:?} and {:?} are incomparable; no min choice",
min_choice, other_option,
);
debug!(?min_choice, ?other_option, "incomparable; no min choice",);
return false;
}
}
}
let min_choice_scc = self.constraint_sccs.scc(min_choice);
debug!(
"apply_member_constraint: min_choice={:?} best_choice_scc={:?}",
min_choice, min_choice_scc,
);
debug!(?min_choice, ?min_choice_scc);
if self.scc_values.add_region(scc, min_choice_scc) {
self.member_constraints_applied.push(AppliedMemberConstraint {
member_region_scc: scc,
@ -1088,8 +1078,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// include the CFG anyhow.
/// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
/// a result `'y`.
pub(in crate::borrow_check) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
debug!("universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
#[instrument(skip(self), level = "debug")]
pub(crate) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
debug!(r = %self.region_value_str(r));
// Find the smallest universal region that contains all other
// universal regions within `region`.
@ -1099,7 +1090,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
}
debug!("universal_upper_bound: r={:?} lub={:?}", r, lub);
debug!(?lub);
lub
}
@ -1115,7 +1106,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// Therefore, this method should only be used in diagnostic code,
/// where displaying *some* named universal region is better than
/// falling back to 'static.
pub(in crate::borrow_check) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
pub(crate) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
debug!("approx_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
// Find the smallest universal region that contains all other
@ -1259,9 +1250,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
// Evaluate whether `sup_region: sub_region`.
#[instrument(skip(self), level = "debug")]
fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
debug!("eval_outlives({:?}: {:?})", sup_region, sub_region);
debug!(
"eval_outlives: sup_region's value = {:?} universal={:?}",
self.region_value_str(sup_region),
@ -1464,6 +1454,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
///
/// Things that are to be propagated are accumulated into the
/// `outlives_requirements` vector.
#[instrument(
skip(self, body, propagated_outlives_requirements, errors_buffer),
level = "debug"
)]
fn check_universal_region(
&self,
body: &Body<'tcx>,
@ -1471,8 +1465,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
errors_buffer: &mut RegionErrors<'tcx>,
) {
debug!("check_universal_region(fr={:?})", longer_fr);
let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
// Because this free region must be in the ROOT universe, we
@ -1596,7 +1588,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
subject: ClosureOutlivesSubject::Region(fr_minus),
outlived_free_region: fr,
blame_span: blame_span_category.1,
blame_span: blame_span_category.1.span,
category: blame_span_category.0,
});
}
@ -1738,8 +1730,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
return BlameConstraint {
category: constraint.category,
from_closure: false,
span,
variance_info: constraint.variance_info.clone(),
cause: ObligationCause::dummy_with_span(span),
variance_info: constraint.variance_info,
};
}
Locations::Single(loc) => loc,
@ -1751,30 +1743,30 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.map(|&(category, span)| BlameConstraint {
category,
from_closure: true,
span: span,
variance_info: constraint.variance_info.clone(),
cause: ObligationCause::dummy_with_span(span),
variance_info: constraint.variance_info,
})
.unwrap_or(BlameConstraint {
category: constraint.category,
from_closure: false,
span: body.source_info(loc).span,
variance_info: constraint.variance_info.clone(),
cause: ObligationCause::dummy_with_span(body.source_info(loc).span),
variance_info: constraint.variance_info,
})
}
/// Finds a good span to blame for the fact that `fr1` outlives `fr2`.
/// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
crate fn find_outlives_blame_span(
&self,
body: &Body<'tcx>,
fr1: RegionVid,
fr1_origin: NllRegionVariableOrigin,
fr2: RegionVid,
) -> (ConstraintCategory, Span) {
let BlameConstraint { category, span, .. } =
) -> (ConstraintCategory, ObligationCause<'tcx>) {
let BlameConstraint { category, cause, .. } =
self.best_blame_constraint(body, fr1, fr1_origin, |r| {
self.provides_universal_region(r, fr1, fr2)
});
(category, span)
(category, cause)
}
/// Walks the graph of constraints (where `'a: 'b` is considered
@ -1877,21 +1869,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
/// Finds some region R such that `fr1: R` and `R` is live at `elem`.
#[instrument(skip(self), level = "trace")]
crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
debug!("find_sub_region_live_at: {:?} is in scc {:?}", fr1, self.constraint_sccs.scc(fr1));
debug!(
"find_sub_region_live_at: {:?} is in universe {:?}",
fr1,
self.scc_universes[self.constraint_sccs.scc(fr1)]
);
trace!(scc = ?self.constraint_sccs.scc(fr1));
trace!(universe = ?self.scc_universes[self.constraint_sccs.scc(fr1)]);
self.find_constraint_paths_between_regions(fr1, |r| {
// First look for some `r` such that `fr1: r` and `r` is live at `elem`
debug!(
"find_sub_region_live_at: liveness_constraints for {:?} are {:?}",
r,
self.liveness_constraints.region_value_str(r),
);
trace!(?r, liveness_constraints=?self.liveness_constraints.region_value_str(r));
self.liveness_constraints.contains(r, elem)
})
.or_else(|| {
@ -1990,6 +1974,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.collect::<Vec<_>>()
);
// We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint.
// Instead, we use it to produce an improved `ObligationCauseCode`.
// FIXME - determine what we should do if we encounter multiple `ConstraintCategory::Predicate`
// constraints. Currently, we just pick the first one.
let cause_code = path
.iter()
.find_map(|constraint| {
if let ConstraintCategory::Predicate(predicate_span) = constraint.category {
// We currentl'y doesn't store the `DefId` in the `ConstraintCategory`
// for perforamnce reasons. The error reporting code used by NLL only
// uses the span, so this doesn't cause any problems at the moment.
Some(ObligationCauseCode::BindingObligation(
CRATE_DEF_ID.to_def_id(),
predicate_span,
))
} else {
None
}
})
.unwrap_or_else(|| ObligationCauseCode::MiscObligation);
// Classify each of the constraints along the path.
let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
.iter()
@ -2000,8 +2005,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
BlameConstraint {
category: constraint.category,
from_closure: false,
span: constraint.locations.span(body),
variance_info: constraint.variance_info.clone(),
cause: ObligationCause::new(
constraint.locations.span(body),
CRATE_HIR_ID,
cause_code.clone(),
),
variance_info: constraint.variance_info,
}
}
})
@ -2083,7 +2092,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
ConstraintCategory::OpaqueType
| ConstraintCategory::Boring
| ConstraintCategory::BoringNoLocation
| ConstraintCategory::Internal => false,
| ConstraintCategory::Internal
| ConstraintCategory::Predicate(_) => false,
ConstraintCategory::TypeAnnotation
| ConstraintCategory::Return(_)
| ConstraintCategory::Yield => true,
@ -2094,7 +2104,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
ConstraintCategory::OpaqueType
| ConstraintCategory::Boring
| ConstraintCategory::BoringNoLocation
| ConstraintCategory::Internal => false,
| ConstraintCategory::Internal
| ConstraintCategory::Predicate(_) => false,
_ => true,
}
}
@ -2143,13 +2154,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// appears to be the most interesting point to report to the
// user via an even more ad-hoc guess.
categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category));
debug!("`: sorted_path={:#?}", categorized_path);
debug!("best_blame_constraint: sorted_path={:#?}", categorized_path);
categorized_path.remove(0)
}
crate fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
self.universe_causes[universe].clone()
self.universe_causes[&universe].clone()
}
}
@ -2249,6 +2260,6 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx
pub struct BlameConstraint<'tcx> {
pub category: ConstraintCategory,
pub from_closure: bool,
pub span: Span,
pub cause: ObligationCause<'tcx>,
pub variance_info: ty::VarianceDiagInfo<'tcx>,
}

View File

@ -1,5 +1,9 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::vec_map::VecMap;
use rustc_hir::OpaqueTyOrigin;
use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
use rustc_infer::infer::InferCtxt;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::opaque_types::InferCtxtExt;
@ -46,17 +50,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// Calling `universal_upper_bound` for such a region gives `fr_fn_body`,
/// which has no `external_name` in which case we use `'empty` as the
/// region to pass to `infer_opaque_definition_from_instantiation`.
#[instrument(skip(self, infcx))]
pub(in crate::borrow_check) fn infer_opaque_types(
#[instrument(level = "debug", skip(self, infcx))]
pub(crate) fn infer_opaque_types(
&self,
infcx: &InferCtxt<'_, 'tcx>,
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
span: Span,
) -> VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>> {
opaque_ty_decls
.into_iter()
.map(|(opaque_type_key, concrete_type)| {
.filter_map(|(opaque_type_key, decl)| {
let substs = opaque_type_key.substs;
let concrete_type = decl.concrete_ty;
debug!(?concrete_type, ?substs);
let mut subst_regions = vec![self.universal_regions.fr_static];
@ -94,7 +99,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
universal_concrete_type,
span,
);
(opaque_type_key, remapped_type)
check_opaque_type_parameter_valid(
infcx.tcx,
opaque_type_key,
OpaqueTypeDecl { concrete_ty: remapped_type, ..decl },
)
.then_some((opaque_type_key, remapped_type))
})
.collect()
}
@ -105,7 +116,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// that the regions produced are in fact equal to the named region they are
/// replaced with. This is fine because this function is only to improve the
/// region names in error messages.
pub(in crate::borrow_check) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
pub(crate) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
where
T: TypeFoldable<'tcx>,
{
@ -113,9 +124,116 @@ impl<'tcx> RegionInferenceContext<'tcx> {
ty::ReVar(vid) => {
// Find something that we can name
let upper_bound = self.approx_universal_upper_bound(vid);
self.definitions[upper_bound].external_name.unwrap_or(region)
let upper_bound = &self.definitions[upper_bound];
match upper_bound.external_name {
Some(reg) => reg,
None => {
// Nothing exact found, so we pick the first one that we find.
let scc = self.constraint_sccs.scc(vid);
for vid in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) {
match self.definitions[vid].external_name {
None => {}
Some(&ty::ReStatic) => {}
Some(region) => return region,
}
}
region
}
}
}
_ => region,
})
}
}
fn check_opaque_type_parameter_valid(
tcx: TyCtxt<'_>,
opaque_type_key: OpaqueTypeKey<'_>,
decl: OpaqueTypeDecl<'_>,
) -> bool {
match decl.origin {
// No need to check return position impl trait (RPIT)
// because for type and const parameters they are correct
// by construction: we convert
//
// fn foo<P0..Pn>() -> impl Trait
//
// into
//
// type Foo<P0...Pn>
// fn foo<P0..Pn>() -> Foo<P0...Pn>.
//
// For lifetime parameters we convert
//
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
//
// into
//
// type foo::<'p0..'pn>::Foo<'q0..'qm>
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
//
// which would error here on all of the `'static` args.
OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true,
// Check these
OpaqueTyOrigin::TyAlias => {}
}
let span = decl.definition_span;
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
for (i, arg) in opaque_type_key.substs.iter().enumerate() {
let arg_is_param = match arg.unpack() {
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
GenericArgKind::Lifetime(ty::ReStatic) => {
tcx.sess
.struct_span_err(span, "non-defining opaque type use in defining scope")
.span_label(
tcx.def_span(opaque_generics.param_at(i, tcx).def_id),
"cannot use static lifetime; use a bound lifetime \
instead or remove the lifetime parameter from the \
opaque type",
)
.emit();
return false;
}
GenericArgKind::Lifetime(lt) => {
matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_))
}
GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
};
if arg_is_param {
seen_params.entry(arg).or_default().push(i);
} else {
// Prevent `fn foo() -> Foo<u32>` from being defining.
let opaque_param = opaque_generics.param_at(i, tcx);
tcx.sess
.struct_span_err(span, "non-defining opaque type use in defining scope")
.span_note(
tcx.def_span(opaque_param.def_id),
&format!(
"used non-generic {} `{}` for generic parameter",
opaque_param.kind.descr(),
arg,
),
)
.emit();
return false;
}
}
for (_, indices) in seen_params {
if indices.len() > 1 {
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
let spans: Vec<_> = indices
.into_iter()
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
.collect();
tcx.sess
.struct_span_err(span, "non-defining opaque type use in defining scope")
.span_note(spans, &format!("{} used multiple times", descr))
.emit();
return false;
}
}
true
}

View File

@ -1,5 +1,5 @@
use crate::borrow_check::constraints::ConstraintSccIndex;
use crate::borrow_check::RegionInferenceContext;
use crate::constraints::ConstraintSccIndex;
use crate::RegionInferenceContext;
use itertools::Itertools;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::vec_graph::VecGraph;

View File

@ -174,17 +174,19 @@ impl<N: Idx> LivenessValues<N> {
self.points.contains(row, index)
}
/// Returns an iterator of all the elements contained by the region `r`
crate fn get_elements(&self, row: N) -> impl Iterator<Item = Location> + '_ {
self.points
.row(row)
.into_iter()
.flat_map(|set| set.iter())
.take_while(move |&p| self.elements.point_in_range(p))
.map(move |p| self.elements.to_location(p))
}
/// Returns a "pretty" string value of the region. Meant for debugging.
crate fn region_value_str(&self, r: N) -> String {
region_value_str(
self.points
.row(r)
.into_iter()
.flat_map(|set| set.iter())
.take_while(|&p| self.elements.point_in_range(p))
.map(|p| self.elements.to_location(p))
.map(RegionElement::Location),
)
region_value_str(self.get_elements(r).map(RegionElement::Location))
}
}

View File

@ -7,13 +7,13 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
/// Replaces all free regions appearing in the MIR with fresh
/// inference variables, returning the number of variables created.
#[instrument(skip(infcx, body, promoted), level = "debug")]
pub fn renumber_mir<'tcx>(
infcx: &InferCtxt<'_, 'tcx>,
body: &mut Body<'tcx>,
promoted: &mut IndexVec<Promoted, Body<'tcx>>,
) {
debug!("renumber_mir()");
debug!("renumber_mir: body.arg_count={:?}", body.arg_count);
debug!(?body.arg_count);
let mut visitor = NllVisitor { infcx };
@ -26,12 +26,11 @@ pub fn renumber_mir<'tcx>(
/// Replaces all regions appearing in `value` with fresh inference
/// variables.
#[instrument(skip(infcx), level = "debug")]
pub fn renumber_regions<'tcx, T>(infcx: &InferCtxt<'_, 'tcx>, value: T) -> T
where
T: TypeFoldable<'tcx>,
{
debug!("renumber_regions(value={:?})", value);
infcx.tcx.fold_regions(value, &mut false, |_region, _depth| {
let origin = NllRegionVariableOrigin::Existential { from_forall: false };
infcx.next_nll_region_var(origin)
@ -56,12 +55,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
self.infcx.tcx
}
#[instrument(skip(self), level = "debug")]
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context);
*ty = self.renumber_regions(ty);
debug!("visit_ty: ty={:?}", ty);
debug!(?ty);
}
fn process_projection_elem(
@ -80,21 +78,19 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
None
}
#[instrument(skip(self), level = "debug")]
fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) {
debug!("visit_substs(substs={:?}, location={:?})", substs, location);
*substs = self.renumber_regions(*substs);
debug!("visit_substs: substs={:?}", substs);
debug!(?substs);
}
#[instrument(skip(self), level = "debug")]
fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) {
debug!("visit_region(region={:?}, location={:?})", region, location);
let old_region = *region;
*region = self.renumber_regions(&old_region);
debug!("visit_region: region={:?}", region);
debug!(?region);
}
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _location: Location) {

View File

@ -4,11 +4,12 @@ use rustc_infer::infer::canonical::Canonical;
use rustc_infer::traits::query::NoSolution;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{self, ToPredicate, TypeFoldable};
use rustc_span::def_id::DefId;
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
use rustc_trait_selection::traits::query::Fallible;
use crate::borrow_check::diagnostics::{ToUniverseInfo, UniverseInfo};
use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
use super::{Locations, NormalizeLocation, TypeChecker};
@ -23,6 +24,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
/// **Any `rustc_infer::infer` operations that might generate region
/// constraints should occur within this method so that those
/// constraints can be properly localized!**
#[instrument(skip(self, category, op), level = "trace")]
pub(super) fn fully_perform_op<R, Op>(
&mut self,
locations: Locations,
@ -50,9 +52,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
None => UniverseInfo::other(),
};
for u in old_universe..universe {
let info_universe =
self.borrowck_context.constraints.universe_causes.push(universe_info.clone());
assert_eq!(u.as_u32() + 1, info_universe.as_u32());
self.borrowck_context
.constraints
.universe_causes
.insert(u + 1, universe_info.clone());
}
}
@ -70,9 +73,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let (instantiated, _) =
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
for _ in 0..canonical.max_universe.as_u32() {
for u in 0..canonical.max_universe.as_u32() {
let info = UniverseInfo::other();
self.borrowck_context.constraints.universe_causes.push(info);
self.borrowck_context
.constraints
.universe_causes
.insert(ty::UniverseIndex::from_u32(u), info);
}
instantiated
@ -85,10 +91,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
category: ConstraintCategory,
) {
self.prove_predicates(
Some(ty::PredicateKind::Trait(ty::TraitPredicate {
Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
})),
}))),
locations,
category,
);
@ -96,12 +102,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
pub(super) fn normalize_and_prove_instantiated_predicates(
&mut self,
// Keep this parameter for now, in case we start using
// it in `ConstraintCategory` at some point.
_def_id: DefId,
instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
locations: Locations,
) {
for predicate in instantiated_predicates.predicates {
for (predicate, span) in instantiated_predicates
.predicates
.into_iter()
.zip(instantiated_predicates.spans.into_iter())
{
let predicate = self.normalize(predicate, locations);
self.prove_predicate(predicate, locations, ConstraintCategory::Boring);
self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span));
}
}
@ -119,14 +132,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
#[instrument(skip(self), level = "debug")]
pub(super) fn prove_predicate(
&mut self,
predicate: ty::Predicate<'tcx>,
locations: Locations,
category: ConstraintCategory,
) {
debug!("prove_predicate(predicate={:?}, location={:?})", predicate, locations,);
let param_env = self.param_env;
self.fully_perform_op(
locations,
@ -138,11 +150,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
})
}
#[instrument(skip(self), level = "debug")]
pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
where
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
{
debug!("normalize(value={:?}, location={:?})", value, location);
let param_env = self.param_env;
self.fully_perform_op(
location.to_locations(),

View File

@ -9,7 +9,7 @@ use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::DUMMY_SP;
use crate::borrow_check::{
use crate::{
constraints::OutlivesConstraint,
nll::ToRegionVid,
region_infer::TypeTest,
@ -53,9 +53,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
}
}
#[instrument(skip(self), level = "debug")]
pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
debug!("convert_all(query_constraints={:#?})", query_constraints);
let QueryRegionConstraints { outlives, member_constraints } = query_constraints;
// Annoying: to invoke `self.to_region_vid`, we need access to

View File

@ -13,7 +13,7 @@ use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc;
use type_op::TypeOpOutput;
use crate::borrow_check::{
use crate::{
nll::ToRegionVid,
type_check::constraint_conversion,
type_check::{Locations, MirTypeckRegionConstraints},
@ -55,7 +55,7 @@ type RegionBoundPairs<'tcx> = Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>;
type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
crate struct CreateResult<'tcx> {
pub(in crate::borrow_check) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
crate universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
crate region_bound_pairs: RegionBoundPairs<'tcx>,
crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
}
@ -258,8 +258,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
debug!("build: input_or_output={:?}", ty);
// We add implied bounds from both the unnormalized and normalized ty
// See issue #87748
let constraints_implied_1 = self.add_implied_bounds(ty);
let TypeOpOutput { output: ty, constraints: constraints1, .. } = self
let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
.param_env
.and(type_op::normalize::Normalize::new(ty))
.fully_perform(self.infcx)
@ -286,9 +285,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
// }
// ```
// Both &Self::Bar and &() are WF
let constraints_implied_2 = self.add_implied_bounds(ty);
normalized_inputs_and_output.push(ty);
constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2)
let constraints_implied = self.add_implied_bounds(norm_ty);
normalized_inputs_and_output.push(norm_ty);
constraints1.into_iter().chain(constraints_implied)
})
.collect();

View File

@ -7,20 +7,20 @@
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values).
use rustc_index::vec::Idx;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use rustc_trait_selection::traits::query::normalize::AtExt;
use rustc_index::vec::Idx;
use rustc_span::Span;
use crate::borrow_check::universal_regions::UniversalRegions;
use crate::universal_regions::UniversalRegions;
use super::{Locations, TypeChecker};
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
#[instrument(skip(self, body, universal_regions), level = "debug")]
pub(super) fn equate_inputs_and_outputs(
&mut self,
body: &Body<'tcx>,
@ -65,10 +65,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
}
debug!(
"equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}",
normalized_input_tys, body.local_decls
);
debug!(?normalized_input_tys, ?body.local_decls);
// Equate expected input tys with those in the MIR.
for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
@ -161,9 +158,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
#[instrument(skip(self, span), level = "debug")]
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);
if let Err(_) =
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
{
@ -195,6 +191,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
b
}
};
// Note: if we have to introduce new placeholders during normalization above, then we won't have
// added those universes to the universe info, which we would want in `relate_tys`.
if let Err(terr) =
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
{

View File

@ -3,8 +3,8 @@ use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location};
use crate::borrow_check::def_use::{self, DefUse};
use crate::borrow_check::region_infer::values::{PointIndex, RegionValueElements};
use crate::def_use::{self, DefUse};
use crate::region_infer::values::{PointIndex, RegionValueElements};
/// A map that cross references each local with the locations where it
/// is defined (assigned), used, or dropped. Used during liveness

View File

@ -3,11 +3,11 @@ use rustc_middle::mir::{Body, Local};
use rustc_middle::ty::{RegionVid, TyCtxt};
use std::rc::Rc;
use crate::dataflow::impls::MaybeInitializedPlaces;
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::ResultsCursor;
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::MoveData;
use rustc_mir_dataflow::ResultsCursor;
use crate::borrow_check::{
use crate::{
constraints::OutlivesConstraintSet,
facts::{AllFacts, AllFactsExt},
location::LocationTable,

View File

@ -1,10 +1,9 @@
use crate::borrow_check::def_use::{self, DefUse};
use crate::borrow_check::location::{LocationIndex, LocationTable};
use crate::dataflow::indexes::MovePathIndex;
use crate::dataflow::move_paths::{LookupResult, MoveData};
use crate::def_use::{self, DefUse};
use crate::location::{LocationIndex, LocationTable};
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location, Place};
use rustc_middle::ty::subst::GenericArg;
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
use super::TypeChecker;

View File

@ -8,12 +8,11 @@ use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
use std::rc::Rc;
use crate::dataflow::impls::MaybeInitializedPlaces;
use crate::dataflow::indexes::MovePathIndex;
use crate::dataflow::move_paths::{HasMoveData, MoveData};
use crate::dataflow::ResultsCursor;
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
use rustc_mir_dataflow::ResultsCursor;
use crate::borrow_check::{
use crate::{
region_infer::values::{self, PointIndex, RegionValueElements},
type_check::liveness::local_use_map::LocalUseMap,
type_check::liveness::polonius,

View File

@ -14,6 +14,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_hir::lang_items::LangItem;
use rustc_index::vec::{Idx, IndexVec};
use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{
@ -31,6 +32,7 @@ use rustc_middle::ty::{
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid,
ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness,
};
use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::VariantIdx;
use rustc_trait_selection::infer::InferCtxtExt as _;
@ -41,14 +43,14 @@ use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
use rustc_trait_selection::traits::query::Fallible;
use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations};
use crate::dataflow::impls::MaybeInitializedPlaces;
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::ResultsCursor;
use crate::transform::{
use rustc_const_eval::transform::{
check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression,
};
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::MoveData;
use rustc_mir_dataflow::ResultsCursor;
use crate::borrow_check::{
use crate::{
borrow_set::BorrowSet,
constraints::{OutlivesConstraint, OutlivesConstraintSet},
diagnostics::UniverseInfo,
@ -68,7 +70,7 @@ use crate::borrow_check::{
macro_rules! span_mirbug {
($context:expr, $elem:expr, $($message:tt)*) => ({
$crate::borrow_check::type_check::mirbug(
$crate::type_check::mirbug(
$context.tcx(),
$context.last_span,
&format!(
@ -136,6 +138,8 @@ pub(crate) fn type_check<'mir, 'tcx>(
upvars: &[Upvar<'tcx>],
) -> MirTypeckResults<'tcx> {
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
let mut universe_causes = FxHashMap::default();
universe_causes.insert(ty::UniverseIndex::from_u32(0), UniverseInfo::other());
let mut constraints = MirTypeckRegionConstraints {
placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(),
@ -144,7 +148,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
member_constraints: MemberConstraintSet::default(),
closure_bounds_mapping: Default::default(),
type_tests: Vec::default(),
universe_causes: IndexVec::from_elem_n(UniverseInfo::other(), 1),
universe_causes,
};
let CreateResult {
@ -159,9 +163,9 @@ pub(crate) fn type_check<'mir, 'tcx>(
&mut constraints,
);
for _ in ty::UniverseIndex::ROOT..infcx.universe() {
for u in ty::UniverseIndex::ROOT..infcx.universe() {
let info = UniverseInfo::other();
constraints.universe_causes.push(info);
constraints.universe_causes.insert(u, info);
}
let mut borrowck_context = BorrowCheckContext {
@ -191,16 +195,22 @@ pub(crate) fn type_check<'mir, 'tcx>(
opaque_type_values
.into_iter()
.filter_map(|(opaque_type_key, decl)| {
let mut revealed_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
if revealed_ty.has_infer_types_or_consts() {
.filter_map(|(opaque_type_key, mut decl)| {
decl.concrete_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
trace!(
"finalized opaque type {:?} to {:#?}",
opaque_type_key,
decl.concrete_ty.kind()
);
if decl.concrete_ty.has_infer_types_or_consts() {
infcx.tcx.sess.delay_span_bug(
body.span,
&format!("could not resolve {:#?}", revealed_ty.kind()),
&format!("could not resolve {:#?}", decl.concrete_ty.kind()),
);
revealed_ty = infcx.tcx.ty_error();
decl.concrete_ty = infcx.tcx.ty_error();
}
let concrete_is_opaque = if let ty::Opaque(def_id, _) = revealed_ty.kind() {
let concrete_is_opaque = if let ty::Opaque(def_id, _) = decl.concrete_ty.kind()
{
*def_id == opaque_type_key.def_id
} else {
false
@ -232,7 +242,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
);
None
} else {
Some((opaque_type_key, revealed_ty))
Some((opaque_type_key, decl))
}
})
.collect()
@ -242,6 +252,18 @@ pub(crate) fn type_check<'mir, 'tcx>(
MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
}
#[instrument(
skip(
infcx,
body,
promoted,
region_bound_pairs,
borrowck_context,
universal_region_relations,
extra
),
level = "debug"
)]
fn type_check_internal<'a, 'tcx, R>(
infcx: &'a InferCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
@ -445,6 +467,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() {
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
self.cx.normalize_and_prove_instantiated_predicates(
def_id,
instantiated_predicates,
location.to_locations(),
);
@ -640,12 +663,17 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}
self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
}
for live_region in liveness_constraints.rows() {
self.cx
.borrowck_context
.constraints
.liveness_constraints
.add_element(live_region, location);
for region in liveness_constraints.rows() {
// If the region is live at at least one location in the promoted MIR,
// then add a liveness constraint to the main MIR for this region
// at the location provided as an argument to this method
if let Some(_) = liveness_constraints.get_elements(region).next() {
self.cx
.borrowck_context
.constraints
.liveness_constraints
.add_element(region, location);
}
}
if !closure_bounds.is_empty() {
@ -887,8 +915,8 @@ struct BorrowCheckContext<'a, 'tcx> {
crate struct MirTypeckResults<'tcx> {
crate constraints: MirTypeckRegionConstraints<'tcx>,
pub(in crate::borrow_check) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
crate universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
}
/// A collection of region constraints that must be satisfied for the
@ -924,7 +952,7 @@ crate struct MirTypeckRegionConstraints<'tcx> {
crate closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
crate universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
crate universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
crate type_tests: Vec<TypeTest<'tcx>>,
}
@ -1076,7 +1104,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
self.prove_predicate(
ty::PredicateKind::WellFormed(inferred_ty.into()).to_predicate(self.tcx()),
ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into()))
.to_predicate(self.tcx()),
Locations::All(span),
ConstraintCategory::TypeAnnotation,
);
@ -1107,13 +1136,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
#[instrument(skip(self, data), level = "debug")]
fn push_region_constraints(
&mut self,
locations: Locations,
category: ConstraintCategory,
data: &QueryRegionConstraints<'tcx>,
) {
debug!("push_region_constraints: constraints generated at {:?} are {:#?}", locations, data);
debug!("constraints generated: {:#?}", data);
constraint_conversion::ConstraintConversion::new(
self.infcx,
@ -1128,28 +1158,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.convert_all(data);
}
/// Convenient wrapper around `relate_tys::relate_types` -- see
/// that fn for docs.
fn relate_types(
&mut self,
a: Ty<'tcx>,
v: ty::Variance,
b: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory,
) -> Fallible<()> {
relate_tys::relate_types(
self.infcx,
self.param_env,
a,
v,
b,
locations,
category,
self.borrowck_context,
)
}
/// Try to relate `sub <: sup`
fn sub_types(
&mut self,
@ -1173,6 +1181,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
}
#[instrument(skip(self), level = "debug")]
fn relate_type_and_user_type(
&mut self,
a: Ty<'tcx>,
@ -1181,11 +1190,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
locations: Locations,
category: ConstraintCategory,
) -> Fallible<()> {
debug!(
"relate_type_and_user_type(a={:?}, v={:?}, user_ty={:?}, locations={:?})",
a, v, user_ty, locations,
);
let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
@ -1243,6 +1247,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
/// generics of `foo`). Note that `anon_ty` is not just the opaque type,
/// but the entire return type (which may contain opaque types within it).
/// * `revealed_ty` would be `Box<(T, u32)>`
#[instrument(skip(self), level = "debug")]
fn eq_opaque_type_and_type(
&mut self,
revealed_ty: Ty<'tcx>,
@ -1250,13 +1255,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
locations: Locations,
category: ConstraintCategory,
) -> Fallible<()> {
debug!(
"eq_opaque_type_and_type( \
revealed_ty={:?}, \
anon_ty={:?})",
revealed_ty, anon_ty
);
// Fast path for the common case.
if !anon_ty.has_opaque_types() {
if let Err(terr) = self.eq_types(anon_ty, revealed_ty, locations, category) {
@ -1276,7 +1274,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let body = self.body;
let mir_def_id = body.source.def_id().expect_local();
debug!("eq_opaque_type_and_type: mir_def_id={:?}", mir_def_id);
debug!(?mir_def_id);
self.fully_perform_op(
locations,
category,
@ -1298,12 +1296,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
anon_ty,
locations.span(body),
));
debug!(
"eq_opaque_type_and_type: \
instantiated output_ty={:?} \
revealed_ty={:?}",
output_ty, revealed_ty
);
debug!(?output_ty, ?revealed_ty);
// Make sure that the inferred types are well-formed. I'm
// not entirely sure this is needed (the HIR type check
@ -1312,7 +1305,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
obligations.obligations.push(traits::Obligation::new(
ObligationCause::dummy(),
param_env,
ty::PredicateKind::WellFormed(revealed_ty.into()).to_predicate(infcx.tcx),
ty::Binder::dummy(ty::PredicateKind::WellFormed(revealed_ty.into()))
.to_predicate(infcx.tcx),
));
obligations.add(
infcx
@ -1320,7 +1314,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.eq(output_ty, revealed_ty)?,
);
debug!("eq_opaque_type_and_type: equated");
debug!("equated");
Ok(InferOk { value: (), obligations: obligations.into_vec() })
},
@ -1360,8 +1354,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.infcx.tcx
}
#[instrument(skip(self, body, location), level = "debug")]
fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
debug!("check_stmt: {:?}", stmt);
let tcx = self.tcx();
match stmt.kind {
StatementKind::Assign(box (ref place, ref rv)) => {
@ -1386,11 +1380,24 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ConstraintCategory::Return(ReturnConstraint::Normal)
}
}
Some(l)
if matches!(
body.local_decls[l].local_info,
Some(box LocalInfo::AggregateTemp)
) =>
{
ConstraintCategory::Usage
}
Some(l) if !body.local_decls[l].is_user_variable() => {
ConstraintCategory::Boring
}
_ => ConstraintCategory::Assignment,
};
debug!(
"assignment category: {:?} {:?}",
category,
place.as_local().map(|l| &body.local_decls[l])
);
let place_ty = place.ty(body, tcx).ty;
let place_ty = self.normalize(place_ty, location);
@ -1501,13 +1508,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
#[instrument(skip(self, body, term_location), level = "debug")]
fn check_terminator(
&mut self,
body: &Body<'tcx>,
term: &Terminator<'tcx>,
term_location: Location,
) {
debug!("check_terminator: {:?}", term);
let tcx = self.tcx();
match term.kind {
TerminatorKind::Goto { .. }
@ -1582,7 +1589,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.check_call_dest(body, term, &sig, destination, term_location);
self.prove_predicates(
sig.inputs_and_output.iter().map(|ty| ty::PredicateKind::WellFormed(ty.into())),
sig.inputs_and_output
.iter()
.map(|ty| ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()))),
term_location.to_locations(),
ConstraintCategory::Boring,
);
@ -1996,7 +2005,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
&obligation,
&traits::SelectionError::Unimplemented,
false,
false,
);
}
}
@ -2004,13 +2012,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
Rvalue::NullaryOp(_, ty) => {
// Even with unsized locals cannot box an unsized value.
if self.unsized_feature_enabled() {
let span = body.source_info(location).span;
self.ensure_place_sized(ty, span);
}
Rvalue::NullaryOp(_, ty) | Rvalue::ShallowInitBox(_, ty) => {
let trait_ref = ty::TraitRef {
def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
substs: tcx.mk_substs_trait(ty, &[]),
@ -2343,6 +2345,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
| Rvalue::AddressOf(..)
| Rvalue::Len(..)
| Rvalue::Cast(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::BinaryOp(..)
| Rvalue::CheckedBinaryOp(..)
| Rvalue::NullaryOp(..)
@ -2557,9 +2560,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
aggregate_kind, location
);
let instantiated_predicates = match aggregate_kind {
let (def_id, instantiated_predicates) = match aggregate_kind {
AggregateKind::Adt(def, _, substs, _, _) => {
tcx.predicates_of(def.did).instantiate(tcx, substs)
(def.did, tcx.predicates_of(def.did).instantiate(tcx, substs))
}
// For closures, we have some **extra requirements** we
@ -2584,13 +2587,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// clauses on the struct.
AggregateKind::Closure(def_id, substs)
| AggregateKind::Generator(def_id, substs, _) => {
self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location)
(*def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location))
}
AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(),
AggregateKind::Array(_) | AggregateKind::Tuple => {
(CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty())
}
};
self.normalize_and_prove_instantiated_predicates(
def_id,
instantiated_predicates,
location.to_locations(),
);
@ -2665,9 +2671,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
tcx.predicates_of(def_id).instantiate(tcx, substs)
}
#[instrument(skip(self, body), level = "debug")]
fn typeck_mir(&mut self, body: &Body<'tcx>) {
self.last_span = body.span;
debug!("run_on_mir: {:?}", body.span);
debug!(?body.span);
for (local, local_decl) in body.local_decls.iter_enumerated() {
self.check_local(&body, local, local_decl);

View File

@ -0,0 +1,129 @@
use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::{self, Const, Ty};
use rustc_trait_selection::traits::query::Fallible;
use crate::constraints::OutlivesConstraint;
use crate::diagnostics::UniverseInfo;
use crate::type_check::{Locations, TypeChecker};
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
/// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
///
/// - "Covariant" `a <: b`
/// - "Invariant" `a == b`
/// - "Contravariant" `a :> b`
///
/// N.B., the type `a` is permitted to have unresolved inference
/// variables, but not the type `b`.
#[instrument(skip(self), level = "debug")]
pub(super) fn relate_types(
&mut self,
a: Ty<'tcx>,
v: ty::Variance,
b: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory,
) -> Fallible<()> {
TypeRelating::new(
self.infcx,
NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)),
v,
)
.relate(a, b)?;
Ok(())
}
}
struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
/// Where (and why) is this relation taking place?
locations: Locations,
/// What category do we assign the resulting `'a: 'b` relationships?
category: ConstraintCategory,
/// Information so that error reporting knows what types we are relating
/// when reporting a bound region error.
universe_info: UniverseInfo<'tcx>,
}
impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
fn new(
type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
locations: Locations,
category: ConstraintCategory,
universe_info: UniverseInfo<'tcx>,
) -> Self {
Self { type_checker, locations, category, universe_info }
}
}
impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.type_checker.param_env
}
fn create_next_universe(&mut self) -> ty::UniverseIndex {
let universe = self.type_checker.infcx.create_next_universe();
self.type_checker
.borrowck_context
.constraints
.universe_causes
.insert(universe, self.universe_info.clone());
universe
}
fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> {
let origin = NllRegionVariableOrigin::Existential { from_forall };
self.type_checker.infcx.next_nll_region_var(origin)
}
fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
self.type_checker
.borrowck_context
.constraints
.placeholder_region(self.type_checker.infcx, placeholder)
}
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
self.type_checker.infcx.next_nll_region_var_in_universe(
NllRegionVariableOrigin::Existential { from_forall: false },
universe,
)
}
fn push_outlives(
&mut self,
sup: ty::Region<'tcx>,
sub: ty::Region<'tcx>,
info: ty::VarianceDiagInfo<'tcx>,
) {
let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub);
let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup);
self.type_checker.borrowck_context.constraints.outlives_constraints.push(
OutlivesConstraint {
sup,
sub,
locations: self.locations,
category: self.category,
variance_info: info,
},
);
}
// We don't have to worry about the equality of consts during borrow checking
// as consts always have a static lifetime.
fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) {}
fn normalization() -> NormalizationStrategy {
NormalizationStrategy::Eager
}
fn forbid_inference_vars() -> bool {
true
}
}

View File

@ -26,7 +26,7 @@ use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
use std::iter;
use crate::borrow_check::nll::ToRegionVid;
use crate::nll::ToRegionVid;
#[derive(Debug)]
pub struct UniversalRegions<'tcx> {

View File

@ -1,11 +1,10 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{
Local, Location, Place, Statement, StatementKind, Terminator, TerminatorKind,
};
use rustc_data_structures::fx::FxHashSet;
use crate::borrow_check::MirBorrowckCtxt;
use crate::MirBorrowckCtxt;
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes

View File

@ -1,7 +1,7 @@
[package]
name = "rustc_builtin_macros"
version = "0.0.0"
edition = "2018"
edition = "2021"
[lib]
doctest = false

View File

@ -117,6 +117,10 @@ fn parse_args<'a>(
let mut explicit_reg = false;
let op = if !is_global_asm && p.eat_keyword(kw::In) {
let reg = parse_reg(&mut p, &mut explicit_reg)?;
if p.eat_keyword(kw::Underscore) {
let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
return Err(err);
}
let expr = p.parse_expr()?;
ast::InlineAsmOperand::In { reg, expr }
} else if !is_global_asm && p.eat_keyword(sym::out) {
@ -129,6 +133,10 @@ fn parse_args<'a>(
ast::InlineAsmOperand::Out { reg, expr, late: true }
} else if !is_global_asm && p.eat_keyword(sym::inout) {
let reg = parse_reg(&mut p, &mut explicit_reg)?;
if p.eat_keyword(kw::Underscore) {
let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
return Err(err);
}
let expr = p.parse_expr()?;
if p.eat(&token::FatArrow) {
let out_expr =
@ -139,6 +147,10 @@ fn parse_args<'a>(
}
} else if !is_global_asm && p.eat_keyword(sym::inlateout) {
let reg = parse_reg(&mut p, &mut explicit_reg)?;
if p.eat_keyword(kw::Underscore) {
let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
return Err(err);
}
let expr = p.parse_expr()?;
if p.eat(&token::FatArrow) {
let out_expr =
@ -510,7 +522,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
match expr_to_spanned_string(ecx, template_expr, msg) {
Ok(template_part) => template_part,
Err(err) => {
if let Some(mut err) = err {
if let Some((mut err, _)) = err {
err.emit();
}
return None;

View File

@ -2,6 +2,7 @@ use crate::util::check_builtin_macro_attribute;
use rustc_ast as ast;
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::ptr::P;
use rustc_ast::tokenstream::CanSynthesizeMissingTokens;
use rustc_ast::visit::Visitor;
use rustc_ast::{mut_visit, visit};
@ -9,10 +10,10 @@ use rustc_ast::{AstLike, Attribute};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_expand::config::StripUnconfigured;
use rustc_expand::configure;
use rustc_feature::Features;
use rustc_parse::parser::ForceCollect;
use rustc_session::utils::FlattenNonterminals;
use rustc_ast::ptr::P;
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::Span;
use smallvec::SmallVec;
@ -24,21 +25,19 @@ crate fn expand(
annotatable: Annotatable,
) -> Vec<Annotatable> {
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
vec![cfg_eval(ecx, annotatable)]
vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable)]
}
crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Annotatable {
CfgEval {
cfg: &mut StripUnconfigured {
sess: ecx.sess,
features: ecx.ecfg.features,
config_tokens: true,
},
}
.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()
crate fn cfg_eval(
sess: &Session,
features: Option<&Features>,
annotatable: Annotatable,
) -> Annotatable {
CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true } }
.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> {

View File

@ -12,7 +12,7 @@ pub fn expand_concat_idents<'cx>(
tts: TokenStream,
) -> Box<dyn base::MacResult + 'cx> {
if tts.is_empty() {
cx.span_err(sp, "concat_idents! takes 1 or more arguments.");
cx.span_err(sp, "concat_idents! takes 1 or more arguments");
return DummyResult::any(sp);
}
@ -22,7 +22,7 @@ pub fn expand_concat_idents<'cx>(
match e {
TokenTree::Token(Token { kind: token::Comma, .. }) => {}
_ => {
cx.span_err(sp, "concat_idents! expecting comma.");
cx.span_err(sp, "concat_idents! expecting comma");
return DummyResult::any(sp);
}
}
@ -34,7 +34,7 @@ pub fn expand_concat_idents<'cx>(
}
}
cx.span_err(sp, "concat_idents! requires ident args.");
cx.span_err(sp, "concat_idents! requires ident args");
return DummyResult::any(sp);
}
}

View File

@ -1,12 +1,13 @@
use crate::cfg_eval::cfg_eval;
use rustc_ast::{self as ast, attr, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
use rustc_ast as ast;
use rustc_ast::{attr, token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
use rustc_errors::{struct_span_err, Applicability};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
use rustc_feature::AttributeTemplate;
use rustc_parse::validate_attr;
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
crate struct Expander;
@ -26,8 +27,7 @@ impl MultiItemModifier for Expander {
return ExpandResult::Ready(vec![item]);
}
let item = cfg_eval(ecx, item);
let (sess, features) = (ecx.sess, ecx.ecfg.features);
let result =
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
let template =
@ -40,7 +40,8 @@ impl MultiItemModifier for Expander {
template,
);
attr.meta_item_list()
let mut resolutions: Vec<_> = attr
.meta_item_list()
.unwrap_or_default()
.into_iter()
.filter_map(|nested_meta| match nested_meta {
@ -56,8 +57,21 @@ impl MultiItemModifier for Expander {
report_path_args(sess, &meta);
meta.path
})
.map(|path| (path, item.clone(), None))
.collect()
.map(|path| (path, dummy_annotatable(), None))
.collect();
// Do not configure or clone items unless necessary.
match &mut resolutions[..] {
[] => {}
[(_, first_item, _), others @ ..] => {
*first_item = cfg_eval(sess, features, item.clone());
for (_, item, _) in others {
*item = first_item.clone();
}
}
}
resolutions
});
match result {
@ -67,6 +81,18 @@ impl MultiItemModifier for Expander {
}
}
// The cheapest `Annotatable` to construct.
fn dummy_annotatable() -> Annotatable {
Annotatable::GenericParam(ast::GenericParam {
id: ast::DUMMY_NODE_ID,
ident: Ident::invalid(),
attrs: Default::default(),
bounds: Default::default(),
is_placeholder: false,
kind: GenericParamKind::Lifetime,
})
}
fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
let item_kind = match item {
Annotatable::Item(item) => Some(&item.kind),

View File

@ -65,15 +65,29 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
// We want to make sure we have the ctxt set so that we can use unstable methods
let span = cx.with_def_site_ctxt(span);
let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
let fmt = substr.nonself_args[0].clone();
// Special fast path for unit variants. In the common case of an enum that is entirely unit
// variants (i.e. a C-like enum), this fast path allows LLVM to eliminate the entire switch in
// favor of a lookup table.
if let ast::VariantData::Unit(..) = vdata {
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
let expr = cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]);
let stmts = vec![cx.stmt_expr(expr)];
let block = cx.block(span, stmts);
return cx.expr_block(block);
}
let builder = Ident::new(sym::debug_trait_builder, span);
let builder_expr = cx.expr_ident(span, builder);
let fmt = substr.nonself_args[0].clone();
let mut stmts = Vec::with_capacity(fields.len() + 2);
let fn_path_finish;
match vdata {
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
ast::VariantData::Unit(..) => {
cx.span_bug(span, "unit variants should have been handled above");
}
ast::VariantData::Tuple(..) => {
// tuple struct/"normal" variant
let fn_path_debug_tuple = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_tuple]);
let expr = cx.expr_call_global(span, fn_path_debug_tuple, vec![fmt, name]);

View File

@ -332,20 +332,27 @@ pub fn combine_substructure(
RefCell::new(f)
}
struct TypeParameter {
bound_generic_params: Vec<ast::GenericParam>,
ty: P<ast::Ty>,
}
/// This method helps to extract all the type parameters referenced from a
/// type. For a type parameter `<T>`, it looks for either a `TyPath` that
/// is not global and starts with `T`, or a `TyQPath`.
/// Also include bound generic params from the input type.
fn find_type_parameters(
ty: &ast::Ty,
ty_param_names: &[Symbol],
cx: &ExtCtxt<'_>,
) -> Vec<P<ast::Ty>> {
) -> Vec<TypeParameter> {
use rustc_ast::visit;
struct Visitor<'a, 'b> {
cx: &'a ExtCtxt<'b>,
ty_param_names: &'a [Symbol],
types: Vec<P<ast::Ty>>,
bound_generic_params_stack: Vec<ast::GenericParam>,
type_params: Vec<TypeParameter>,
}
impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
@ -353,7 +360,10 @@ fn find_type_parameters(
if let ast::TyKind::Path(_, ref path) = ty.kind {
if let Some(segment) = path.segments.first() {
if self.ty_param_names.contains(&segment.ident.name) {
self.types.push(P(ty.clone()));
self.type_params.push(TypeParameter {
bound_generic_params: self.bound_generic_params_stack.clone(),
ty: P(ty.clone()),
});
}
}
}
@ -361,15 +371,35 @@ fn find_type_parameters(
visit::walk_ty(self, ty)
}
// Place bound generic params on a stack, to extract them when a type is encountered.
fn visit_poly_trait_ref(
&mut self,
trait_ref: &'a ast::PolyTraitRef,
modifier: &'a ast::TraitBoundModifier,
) {
let stack_len = self.bound_generic_params_stack.len();
self.bound_generic_params_stack
.extend(trait_ref.bound_generic_params.clone().into_iter());
visit::walk_poly_trait_ref(self, trait_ref, modifier);
self.bound_generic_params_stack.truncate(stack_len);
}
fn visit_mac_call(&mut self, mac: &ast::MacCall) {
self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros");
}
}
let mut visitor = Visitor { cx, ty_param_names, types: Vec::new() };
let mut visitor = Visitor {
cx,
ty_param_names,
bound_generic_params_stack: Vec::new(),
type_params: Vec::new(),
};
visit::Visitor::visit_ty(&mut visitor, ty);
visitor.types
visitor.type_params
}
impl<'a> TraitDef<'a> {
@ -564,7 +594,7 @@ impl<'a> TraitDef<'a> {
GenericParamKind::Const { ty, kw_span, .. } => {
let const_nodefault_kind = GenericParamKind::Const {
ty: ty.clone(),
kw_span: kw_span.clone(),
kw_span: *kw_span,
// We can't have default values inside impl block
default: None,
@ -617,11 +647,11 @@ impl<'a> TraitDef<'a> {
ty_params.map(|ty_param| ty_param.ident.name).collect();
for field_ty in field_tys {
let tys = find_type_parameters(&field_ty, &ty_param_names, cx);
let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx);
for ty in tys {
for field_ty_param in field_ty_params {
// if we have already handled this type, skip it
if let ast::TyKind::Path(_, ref p) = ty.kind {
if let ast::TyKind::Path(_, ref p) = field_ty_param.ty.kind {
if p.segments.len() == 1
&& ty_param_names.contains(&p.segments[0].ident.name)
{
@ -639,8 +669,8 @@ impl<'a> TraitDef<'a> {
let predicate = ast::WhereBoundPredicate {
span: self.span,
bound_generic_params: Vec::new(),
bounded_ty: ty,
bound_generic_params: field_ty_param.bound_generic_params,
bounded_ty: field_ty_param.ty,
bounds,
};

View File

@ -164,23 +164,22 @@ fn parse_args<'a>(
p.clear_expected_tokens();
}
// `Parser::expect` tries to recover using the
// `Parser::unexpected_try_recover` function. This function is able
// to recover if the expected token is a closing delimiter.
//
// As `,` is not a closing delimiter, it will always return an `Err`
// variant.
let mut err = p.expect(&token::Comma).unwrap_err();
match token::TokenKind::Comma.similar_tokens() {
Some(tks) if tks.contains(&p.token.kind) => {
// If a similar token is found, then it may be a typo. We
// consider it as a comma, and continue parsing.
err.emit();
p.bump();
match p.expect(&token::Comma) {
Err(mut err) => {
match token::TokenKind::Comma.similar_tokens() {
Some(tks) if tks.contains(&p.token.kind) => {
// If a similar token is found, then it may be a typo. We
// consider it as a comma, and continue parsing.
err.emit();
p.bump();
}
// Otherwise stop the parsing and return the error.
_ => return Err(err),
}
}
Ok(recovered) => {
assert!(recovered);
}
// Otherwise stop the parsing and return the error.
_ => return Err(err),
}
}
first = false;
@ -845,8 +844,7 @@ impl<'a, 'b> Context<'a, 'b> {
self.ecx.expr_match(self.macsp, head, vec![arm])
};
let ident = Ident::from_str_and_span("args", self.macsp);
let args_slice = self.ecx.expr_ident(self.macsp, ident);
let args_slice = self.ecx.expr_addr_of(self.macsp, args_match);
// Now create the fmt::Arguments struct with all our locals we created.
let (fn_name, fn_args) = if self.all_pieces_simple {
@ -856,25 +854,22 @@ impl<'a, 'b> Context<'a, 'b> {
// nonstandard placeholders, if there are any.
let fmt = self.ecx.expr_vec_slice(self.macsp, self.pieces);
("new_v1_formatted", vec![pieces, args_slice, fmt])
let path = self.ecx.std_path(&[sym::fmt, sym::UnsafeArg, sym::new]);
let unsafe_arg = self.ecx.expr_call_global(self.macsp, path, Vec::new());
let unsafe_expr = self.ecx.expr_block(P(ast::Block {
stmts: vec![self.ecx.stmt_expr(unsafe_arg)],
id: ast::DUMMY_NODE_ID,
rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
span: self.macsp,
tokens: None,
could_be_bare_literal: false,
}));
("new_v1_formatted", vec![pieces, args_slice, fmt, unsafe_expr])
};
let path = self.ecx.std_path(&[sym::fmt, sym::Arguments, Symbol::intern(fn_name)]);
let arguments = self.ecx.expr_call_global(self.macsp, path, fn_args);
let body = self.ecx.expr_block(P(ast::Block {
stmts: vec![self.ecx.stmt_expr(arguments)],
id: ast::DUMMY_NODE_ID,
rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
span: self.macsp,
tokens: None,
could_be_bare_literal: false,
}));
let ident = Ident::from_str_and_span("args", self.macsp);
let binding_mode = ast::BindingMode::ByRef(ast::Mutability::Not);
let pat = self.ecx.pat_ident_binding_mode(self.macsp, ident, binding_mode);
let arm = self.ecx.arm(self.macsp, pat, body);
self.ecx.expr_match(self.macsp, args_match, vec![arm])
self.ecx.expr_call_global(self.macsp, path, fn_args)
}
fn format_arg(
@ -964,17 +959,19 @@ pub fn expand_preparsed_format_args(
}
Ok(fmt) => fmt,
Err(err) => {
if let Some(mut err) = err {
if let Some((mut err, suggested)) = err {
let sugg_fmt = match args.len() {
0 => "{}".to_string(),
_ => format!("{}{{}}", "{} ".repeat(args.len())),
};
err.span_suggestion(
fmt_sp.shrink_to_lo(),
"you might be missing a string literal to format with",
format!("\"{}\", ", sugg_fmt),
Applicability::MaybeIncorrect,
);
if !suggested {
err.span_suggestion(
fmt_sp.shrink_to_lo(),
"you might be missing a string literal to format with",
format!("\"{}\", ", sugg_fmt),
Applicability::MaybeIncorrect,
);
}
err.emit();
}
return DummyResult::raw_expr(sp, true);
@ -1157,11 +1154,12 @@ pub fn expand_preparsed_format_args(
// account for `"` and account for raw strings `r#`
let padding = str_style.map(|i| i + 2).unwrap_or(1);
for sub in foreign::$kind::iter_subs(fmt_str, padding) {
let trn = match sub.translate() {
Some(trn) => trn,
let (trn, success) = match sub.translate() {
Ok(trn) => (trn, true),
Err(Some(msg)) => (msg, false),
// If it has no translation, don't call it out specifically.
None => continue,
_ => continue,
};
let pos = sub.position();
@ -1178,9 +1176,24 @@ pub fn expand_preparsed_format_args(
if let Some(inner_sp) = pos {
let sp = fmt_sp.from_inner(inner_sp);
suggestions.push((sp, trn));
if success {
suggestions.push((sp, trn));
} else {
diag.span_note(
sp,
&format!("format specifiers use curly braces, and {}", trn),
);
}
} else {
diag.help(&format!("`{}` should be written as `{}`", sub, trn));
if success {
diag.help(&format!("`{}` should be written as `{}`", sub, trn));
} else {
diag.note(&format!(
"`{}` should use curly braces, and {}",
sub, trn
));
}
}
}

View File

@ -1,4 +1,4 @@
pub mod printf {
pub(crate) mod printf {
use super::strcursor::StrCursor as Cur;
use rustc_span::InnerSpan;
@ -36,10 +36,10 @@ pub mod printf {
///
/// This ignores cases where the substitution does not have an exact equivalent, or where
/// the substitution would be unnecessary.
pub fn translate(&self) -> Option<String> {
pub fn translate(&self) -> Result<String, Option<String>> {
match *self {
Substitution::Format(ref fmt) => fmt.translate(),
Substitution::Escape => None,
Substitution::Escape => Err(None),
}
}
}
@ -68,9 +68,9 @@ pub mod printf {
impl Format<'_> {
/// Translate this directive into an equivalent Rust formatting directive.
///
/// Returns `None` in cases where the `printf` directive does not have an exact Rust
/// Returns `Err` in cases where the `printf` directive does not have an exact Rust
/// equivalent, rather than guessing.
pub fn translate(&self) -> Option<String> {
pub fn translate(&self) -> Result<String, Option<String>> {
use std::fmt::Write;
let (c_alt, c_zero, c_left, c_plus) = {
@ -84,7 +84,12 @@ pub mod printf {
'0' => c_zero = true,
'-' => c_left = true,
'+' => c_plus = true,
_ => return None,
_ => {
return Err(Some(format!(
"the flag `{}` is unknown or unsupported",
c
)));
}
}
}
(c_alt, c_zero, c_left, c_plus)
@ -104,7 +109,9 @@ pub mod printf {
let width = match self.width {
Some(Num::Next) => {
// NOTE: Rust doesn't support this.
return None;
return Err(Some(
"you have to use a positional or named parameter for the width".to_string(),
));
}
w @ Some(Num::Arg(_)) => w,
w @ Some(Num::Num(_)) => w,
@ -125,13 +132,21 @@ pub mod printf {
"p" => (Some(self.type_), false, true),
"g" => (Some("e"), true, false),
"G" => (Some("E"), true, false),
_ => return None,
_ => {
return Err(Some(format!(
"the conversion specifier `{}` is unknown or unsupported",
self.type_
)));
}
};
let (fill, width, precision) = match (is_int, width, precision) {
(true, Some(_), Some(_)) => {
// Rust can't duplicate this insanity.
return None;
return Err(Some(
"width and precision cannot both be specified for integer conversions"
.to_string(),
));
}
(true, None, Some(p)) => (Some("0"), Some(p), None),
(true, w, None) => (fill, w, None),
@ -169,7 +184,17 @@ pub mod printf {
s.push('{');
if let Some(arg) = self.parameter {
write!(s, "{}", arg.checked_sub(1)?).ok()?;
match write!(
s,
"{}",
match arg.checked_sub(1) {
Some(a) => a,
None => return Err(None),
}
) {
Err(_) => return Err(None),
_ => {}
}
}
if has_options {
@ -199,12 +224,18 @@ pub mod printf {
}
if let Some(width) = width {
width.translate(&mut s).ok()?;
match width.translate(&mut s) {
Err(_) => return Err(None),
_ => {}
}
}
if let Some(precision) = precision {
s.push('.');
precision.translate(&mut s).ok()?;
match precision.translate(&mut s) {
Err(_) => return Err(None),
_ => {}
}
}
if let Some(type_) = type_ {
@ -213,7 +244,7 @@ pub mod printf {
}
s.push('}');
Some(s)
Ok(s)
}
}
@ -623,11 +654,11 @@ pub mod shell {
}
}
pub fn translate(&self) -> Option<String> {
pub fn translate(&self) -> Result<String, Option<String>> {
match *self {
Substitution::Ordinal(n, _) => Some(format!("{{{}}}", n)),
Substitution::Name(n, _) => Some(format!("{{{}}}", n)),
Substitution::Escape(_) => None,
Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)),
Substitution::Name(n, _) => Ok(format!("{{{}}}", n)),
Substitution::Escape(_) => Err(None),
}
}
}

View File

@ -3,7 +3,7 @@ use super::{iter_subs, parse_next_substitution as pns, Format as F, Num as N, Su
macro_rules! assert_eq_pnsat {
($lhs:expr, $rhs:expr) => {
assert_eq!(
pns($lhs).and_then(|(s, _)| s.translate()),
pns($lhs).and_then(|(s, _)| s.translate().ok()),
$rhs.map(<String as From<&str>>::from)
)
};
@ -98,7 +98,7 @@ fn test_parse() {
#[test]
fn test_iter() {
let s = "The %d'th word %% is: `%.*s` %!\n";
let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect();
let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect();
assert_eq!(
subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(),
vec![Some("{}"), None, Some("{:.*}"), None]

View File

@ -3,7 +3,7 @@ use super::{parse_next_substitution as pns, Substitution as S};
macro_rules! assert_eq_pnsat {
($lhs:expr, $rhs:expr) => {
assert_eq!(
pns($lhs).and_then(|(f, _)| f.translate()),
pns($lhs).and_then(|(f, _)| f.translate().ok()),
$rhs.map(<String as From<&str>>::from)
)
};
@ -37,7 +37,7 @@ fn test_parse() {
fn test_iter() {
use super::iter_subs;
let s = "The $0'th word $$ is: `$WORD` $!\n";
let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect();
let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect();
assert_eq!(
subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(),
vec![Some("{0}"), None, Some("{WORD}")]

View File

@ -382,7 +382,7 @@ fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
.note(
"errors in this attribute were erroneously \
allowed and will become a hard error in a \
future release.",
future release",
)
.emit();
ShouldPanic::Yes(None)

View File

@ -33,16 +33,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cranelift-bforest"
version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b"
version = "0.76.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b"
version = "0.76.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b"
dependencies = [
"cranelift-bforest",
"cranelift-codegen-meta",
@ -57,8 +57,8 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b"
version = "0.76.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b"
dependencies = [
"cranelift-codegen-shared",
"cranelift-entity",
@ -66,18 +66,18 @@ dependencies = [
[[package]]
name = "cranelift-codegen-shared"
version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b"
version = "0.76.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b"
[[package]]
name = "cranelift-entity"
version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b"
version = "0.76.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b"
[[package]]
name = "cranelift-frontend"
version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b"
version = "0.76.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b"
dependencies = [
"cranelift-codegen",
"log",
@ -87,8 +87,8 @@ dependencies = [
[[package]]
name = "cranelift-jit"
version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b"
version = "0.76.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -104,8 +104,8 @@ dependencies = [
[[package]]
name = "cranelift-module"
version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b"
version = "0.76.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -115,8 +115,8 @@ dependencies = [
[[package]]
name = "cranelift-native"
version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b"
version = "0.76.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b"
dependencies = [
"cranelift-codegen",
"libc",
@ -125,8 +125,8 @@ dependencies = [
[[package]]
name = "cranelift-object"
version = "0.75.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b"
version = "0.76.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b"
dependencies = [
"anyhow",
"cranelift-codegen",

View File

@ -1,7 +1,7 @@
[package]
name = "rustc_codegen_cranelift"
version = "0.1.0"
edition = "2018"
edition = "2021"
[lib]
crate-type = ["dylib"]

View File

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "addr2line"
version = "0.14.1"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7"
checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
dependencies = [
"compiler_builtins",
"gimli",
@ -40,9 +40,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "cc"
version = "1.0.69"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
[[package]]
name = "cfg-if"
@ -56,7 +56,7 @@ dependencies = [
[[package]]
name = "compiler_builtins"
version = "0.1.46"
version = "0.1.50"
dependencies = [
"rustc-std-workspace-core",
]
@ -99,9 +99,9 @@ dependencies = [
[[package]]
name = "gimli"
version = "0.23.0"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-alloc",
@ -132,13 +132,23 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.98"
version = "0.2.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103"
dependencies = [
"rustc-std-workspace-core",
]
[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
]
[[package]]
name = "miniz_oxide"
version = "0.4.4"
@ -154,11 +164,12 @@ dependencies = [
[[package]]
name = "object"
version = "0.22.0"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
dependencies = [
"compiler_builtins",
"memchr",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
@ -195,9 +206,9 @@ dependencies = [
[[package]]
name = "rustc-demangle"
version = "0.1.20"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
@ -286,9 +297,9 @@ dependencies = [
[[package]]
name = "unicode-width"
version = "0.1.8"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",

View File

@ -28,11 +28,11 @@ pub(crate) fn prepare() {
);
clone_repo(
"stdsimd",
"https://github.com/rust-lang/stdsimd",
"be96995d8ddec03fac9a0caf4d4c51c7fbc33507",
"portable-simd",
"https://github.com/rust-lang/portable-simd",
"8cf7a62e5d2552961df51e5200aaa5b7c890a4bf",
);
apply_patches("stdsimd", Path::new("stdsimd"));
apply_patches("portable-simd", Path::new("portable-simd"));
clone_repo(
"simple-raytracer",
@ -92,7 +92,7 @@ fn prepare_sysroot() {
clone_repo(
"build_sysroot/compiler-builtins",
"https://github.com/rust-lang/compiler-builtins.git",
"0.1.46",
"0.1.50",
);
apply_patches("compiler-builtins", Path::new("build_sysroot/compiler-builtins"));
}

View File

@ -3,4 +3,4 @@ set -e
rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
rm -rf target/ build/ perf.data{,.old}
rm -rf rand/ regex/ simple-raytracer/ stdsimd/
rm -rf rand/ regex/ simple-raytracer/ portable-simd/

View File

@ -24,6 +24,8 @@ $ $cg_clif_dir/build/bin/cg_clif my_crate.rs
## Jit mode
> ⚠⚠⚠ The JIT mode is highly experimental. It may be slower than AOT compilation due to lack of incremental compilation. It may also be hard to setup if you have cargo dependencies. ⚠⚠⚠
In jit mode cg_clif will immediately execute your code without creating an executable file.
> This requires all dependencies to be available as dynamic library.

View File

@ -1,10 +1,10 @@
#![feature(start, core_intrinsics, alloc_prelude, alloc_error_handler)]
#![feature(start, core_intrinsics, alloc_error_handler, box_syntax)]
#![no_std]
extern crate alloc;
extern crate alloc_system;
use alloc::prelude::v1::*;
use alloc::boxed::Box;
use alloc_system::System;

View File

@ -1,4 +1,4 @@
#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local)]
#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local, box_syntax)]
#![no_core]
#![allow(dead_code, non_camel_case_types)]

View File

@ -4,21 +4,20 @@ Date: Sun, 25 Jul 2021 18:39:31 +0200
Subject: [PATCH] Disable unsupported tests
---
crates/core_simd/src/array.rs | 2 ++
crates/core_simd/src/lib.rs | 2 +-
crates/core_simd/src/vector.rs | 2 ++
crates/core_simd/src/math.rs | 4 ++++
crates/core_simd/tests/masks.rs | 12 ------------
crates/core_simd/tests/ops_macros.rs | 6 ++++++
crates/core_simd/tests/round.rs | 2 ++
6 files changed, 15 insertions(+), 13 deletions(-)
diff --git a/crates/core_simd/src/array.rs b/crates/core_simd/src/array.rs
diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs
index 25c5309..2b3d819 100644
--- a/crates/core_simd/src/array.rs
+++ b/crates/core_simd/src/array.rs
--- a/crates/core_simd/src/vector.rs
+++ b/crates/core_simd/src/vector.rs
@@ -22,6 +22,7 @@ where
#[must_use]
fn splat(val: Self::Scalar) -> Self;
self.0
}
+ /*
/// SIMD gather: construct a SIMD vector by reading from a slice, using potentially discontiguous indices.
@ -31,27 +30,14 @@ index 25c5309..2b3d819 100644
+ */
}
macro_rules! impl_simdarray_for {
diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs
index a64904d..299eb11 100644
--- a/crates/core_simd/src/lib.rs
+++ b/crates/core_simd/src/lib.rs
@@ -1,7 +1,7 @@
#![no_std]
#![allow(incomplete_features)]
#![feature(
- const_generics,
+ const_generics,
platform_intrinsics,
repr_simd,
simd_ffi,
impl<T, const LANES: usize> Copy for Simd<T, LANES>
diff --git a/crates/core_simd/src/math.rs b/crates/core_simd/src/math.rs
index 7290a28..e394730 100644
--- a/crates/core_simd/src/math.rs
+++ b/crates/core_simd/src/math.rs
@@ -2,6 +2,7 @@ macro_rules! impl_uint_arith {
($(($name:ident, $n:ident)),+) => {
$( impl<const LANES: usize> $name<LANES> where Self: crate::LanesAtMost32 {
($($ty:ty),+) => {
$( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
+ /*
/// Lanewise saturating add.
@ -66,8 +52,8 @@ index 7290a28..e394730 100644
}
}
@@ -46,6 +48,7 @@ macro_rules! impl_int_arith {
($(($name:ident, $n:ident)),+) => {
$( impl<const LANES: usize> $name<LANES> where Self: crate::LanesAtMost32 {
($($ty:ty),+) => {
$( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
+ /*
/// Lanewise saturating add.
@ -85,21 +71,22 @@ diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs
index 61d8e44..2bccae2 100644
--- a/crates/core_simd/tests/masks.rs
+++ b/crates/core_simd/tests/masks.rs
@@ -67,18 +67,6 @@ macro_rules! test_mask_api {
@@ -67,19 +67,6 @@ macro_rules! test_mask_api {
assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]);
assert_eq!(core_simd::$name::<8>::from_int(int), mask);
assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask);
}
-
- #[cfg(feature = "generic_const_exprs")]
- #[test]
- fn roundtrip_bitmask_conversion() {
- let values = [
- true, false, false, true, false, false, true, false,
- true, true, false, false, false, false, false, true,
- ];
- let mask = core_simd::$name::<16>::from_array(values);
- let mask = core_simd::Mask::<$type, 16>::from_array(values);
- let bitmask = mask.to_bitmask();
- assert_eq!(bitmask, [0b01001001, 0b10000011]);
- assert_eq!(core_simd::$name::<16>::from_bitmask(bitmask), mask);
- assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask);
- }
}
}
@ -122,7 +109,7 @@ index cb39e73..fc0ebe1 100644
}
+ */
fn sqrt<const LANES: usize>() {
fn recip<const LANES: usize>() {
test_helpers::test_unary_elementwise(
@@ -581,6 +585,7 @@ macro_rules! impl_float_tests {
});
@ -138,8 +125,8 @@ index cb39e73..fc0ebe1 100644
}
+ */
}
}
}
#[cfg(feature = "std")]
diff --git a/crates/core_simd/tests/round.rs b/crates/core_simd/tests/round.rs
index 37044a7..4cdc6b7 100644
--- a/crates/core_simd/tests/round.rs

View File

@ -1,4 +1,4 @@
From 6a4e6f5dc8c8a529a822eb9b57f9e57519595439 Mon Sep 17 00:00:00 2001
From ad7ffe71baba46865f2e65266ab025920dfdc20b Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Thu, 18 Feb 2021 18:45:28 +0100
Subject: [PATCH] Disable 128bit atomic operations
@ -8,7 +8,8 @@ Cranelift doesn't support them yet
library/core/src/panic/unwind_safe.rs | 6 -----
library/core/src/sync/atomic.rs | 38 ---------------------------
library/core/tests/atomic.rs | 4 ---
3 files changed, 48 deletions(-)
library/std/src/time/monotonic.rs | 6 +++--
4 files changed, 4 insertions(+), 50 deletions(-)
diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs
index 092b7cf..158cf71 100644
@ -35,10 +36,10 @@ index 092b7cf..158cf71 100644
#[cfg(target_has_atomic_load_store = "8")]
#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 0194c58..25a0038 100644
index d9de37e..8293fce 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -2229,44 +2229,6 @@ atomic_int! {
@@ -2234,44 +2234,6 @@ atomic_int! {
"AtomicU64::new(0)",
u64 AtomicU64 ATOMIC_U64_INIT
}
@ -98,6 +99,38 @@ index b735957..ea728b6 100644
#[cfg(target_has_atomic = "ptr")]
assert_eq!(align_of::<AtomicUsize>(), size_of::<AtomicUsize>());
#[cfg(target_has_atomic = "ptr")]
diff --git a/library/std/src/time/monotonic.rs b/library/std/src/time/monotonic.rs
index fa96b7a..2854f9c 100644
--- a/library/std/src/time/monotonic.rs
+++ b/library/std/src/time/monotonic.rs
@@ -5,7 +5,7 @@ pub(super) fn monotonize(raw: time::Instant) -> time::Instant {
inner::monotonize(raw)
}
-#[cfg(all(target_has_atomic = "64", not(target_has_atomic = "128")))]
+#[cfg(target_has_atomic = "64")]
pub mod inner {
use crate::sync::atomic::AtomicU64;
use crate::sync::atomic::Ordering::*;
@@ -70,6 +70,7 @@ pub mod inner {
}
}
+/*
#[cfg(target_has_atomic = "128")]
pub mod inner {
use crate::sync::atomic::AtomicU128;
@@ -94,8 +95,9 @@ pub mod inner {
ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap()
}
}
+*/
-#[cfg(not(any(target_has_atomic = "64", target_has_atomic = "128")))]
+#[cfg(not(target_has_atomic = "64"))]
pub mod inner {
use crate::cmp;
use crate::sys::time;
--
2.26.2.7.g19db9cfb68

View File

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2021-08-05"
channel = "nightly-2021-09-19"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View File

@ -42,7 +42,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
continue;
}
if stack.contains("rustc_mir::monomorphize::partitioning::collect_and_partition_mono_items")
if stack.contains("rustc_monomorphize::partitioning::collect_and_partition_mono_items")
|| stack.contains("rustc_incremental::assert_dep_graph::assert_dep_graph")
|| stack.contains("rustc_symbol_mangling::test::report_symbol_names")
{
@ -81,7 +81,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}
const COLLECT_AND_PARTITION_MONO_ITEMS: &str =
"rustc_mir::monomorphize::partitioning::collect_and_partition_mono_items";
"rustc_monomorphize::partitioning::collect_and_partition_mono_items";
if let Some(index) = stack.find(COLLECT_AND_PARTITION_MONO_ITEMS) {
stack = &stack[..index + COLLECT_AND_PARTITION_MONO_ITEMS.len()];
}
@ -96,7 +96,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
stack = &stack[..index + REPORT_SYMBOL_NAMES.len()];
}
const ENCODE_METADATA: &str = "rustc_middle::ty::context::TyCtxt::encode_metadata";
const ENCODE_METADATA: &str = "rustc_metadata::rmeta::encoder::encode_metadata";
if let Some(index) = stack.find(ENCODE_METADATA) {
stack = &stack[..index + ENCODE_METADATA.len()];
}

View File

@ -11,7 +11,7 @@ pushd rust
cargo install ripgrep
rm -r src/test/ui/{extern/,panics/,unsized-locals/,thinlto/,simd*,*lto*.rs,linkage*,unwind-*.rs} || true
for test in $(rg --files-with-matches "asm!|catch_unwind|should_panic|lto" src/test/ui); do
for test in $(rg --files-with-matches "asm!|catch_unwind|should_panic|lto|// needs-asm-support" src/test/ui); do
rm $test
done

Some files were not shown because too many files have changed in this diff Show More