diff --git a/.gitmodules b/.gitmodules
index f9bd42edab3f..97a0c0c54cf9 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -29,7 +29,7 @@
[submodule "src/llvm-project"]
path = src/llvm-project
url = https://github.com/rust-lang/llvm-project.git
- branch = rustc/19.1-2024-12-03
+ branch = rustc/20.1-2025-02-13
shallow = true
[submodule "src/doc/embedded-book"]
path = src/doc/embedded-book
diff --git a/Cargo.lock b/Cargo.lock
index 38a861727a9d..22a349b2d32a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -61,19 +61,6 @@ version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
-[[package]]
-name = "ammonia"
-version = "4.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459"
-dependencies = [
- "html5ever",
- "maplit",
- "once_cell",
- "tendril",
- "url",
-]
-
[[package]]
name = "android-tzdata"
version = "0.1.1"
@@ -513,16 +500,6 @@ dependencies = [
"anstyle",
"clap_lex",
"strsim",
- "terminal_size",
-]
-
-[[package]]
-name = "clap_complete"
-version = "4.5.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33a7e468e750fa4b6be660e8b5651ad47372e8fb114030b594c2d75d48c5ffd0"
-dependencies = [
- "clap",
]
[[package]]
@@ -1084,18 +1061,6 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
-[[package]]
-name = "elasticlunr-rs"
-version = "3.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41e83863a500656dfa214fee6682de9c5b9f03de6860fec531235ed2ae9f6571"
-dependencies = [
- "regex",
- "serde",
- "serde_derive",
- "serde_json",
-]
-
[[package]]
name = "elsa"
version = "1.11.0"
@@ -1159,13 +1124,6 @@ dependencies = [
"windows-sys 0.59.0",
]
-[[package]]
-name = "error_index_generator"
-version = "0.0.0"
-dependencies = [
- "mdbook",
-]
-
[[package]]
name = "expect-test"
version = "1.5.1"
@@ -1517,22 +1475,6 @@ dependencies = [
"serde",
]
-[[package]]
-name = "handlebars"
-version = "6.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6b224b95c1e668ac0270325ad563b2eef1469fbbb8959bc7c692c844b813d9"
-dependencies = [
- "derive_builder",
- "log",
- "num-order",
- "pest",
- "pest_derive",
- "serde",
- "serde_json",
- "thiserror 2.0.11",
-]
-
[[package]]
name = "hashbrown"
version = "0.14.5"
@@ -2189,12 +2131,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
-[[package]]
-name = "maplit"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
-
[[package]]
name = "markup5ever"
version = "0.12.1"
@@ -2228,34 +2164,6 @@ dependencies = [
"digest",
]
-[[package]]
-name = "mdbook"
-version = "0.4.43"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe1f98b8d66e537d2f0ba06e7dec4f44001deec539a2d18bfc102d6a86189148"
-dependencies = [
- "ammonia",
- "anyhow",
- "chrono",
- "clap",
- "clap_complete",
- "elasticlunr-rs",
- "env_logger",
- "handlebars",
- "log",
- "memchr",
- "once_cell",
- "opener",
- "pulldown-cmark 0.10.3",
- "regex",
- "serde",
- "serde_json",
- "shlex",
- "tempfile",
- "toml 0.5.11",
- "topological-sort",
-]
-
[[package]]
name = "measureme"
version = "11.0.1"
@@ -2303,9 +2211,9 @@ dependencies = [
[[package]]
name = "minifier"
-version = "0.3.4"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cf47565b1430f5fe6c81d3afcb4b835271348d7eb35294a4d592e38dd09ea22"
+checksum = "9bfdc64e2f805f3d12965f10522000bae36e88d2cfea44112331f467d4f4bf68"
[[package]]
name = "minimal-lexical"
@@ -2483,21 +2391,6 @@ dependencies = [
"num-traits",
]
-[[package]]
-name = "num-modular"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f"
-
-[[package]]
-name = "num-order"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6"
-dependencies = [
- "num-modular",
-]
-
[[package]]
name = "num-rational"
version = "0.4.2"
@@ -2718,51 +2611,6 @@ dependencies = [
"libc",
]
-[[package]]
-name = "pest"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc"
-dependencies = [
- "memchr",
- "thiserror 2.0.11",
- "ucd-trie",
-]
-
-[[package]]
-name = "pest_derive"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e"
-dependencies = [
- "pest",
- "pest_generator",
-]
-
-[[package]]
-name = "pest_generator"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b"
-dependencies = [
- "pest",
- "pest_meta",
- "proc-macro2",
- "quote",
- "syn 2.0.96",
-]
-
-[[package]]
-name = "pest_meta"
-version = "2.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea"
-dependencies = [
- "once_cell",
- "pest",
- "sha2",
-]
-
[[package]]
name = "phf"
version = "0.11.3"
@@ -2921,18 +2769,6 @@ dependencies = [
"unicase",
]
-[[package]]
-name = "pulldown-cmark"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
-dependencies = [
- "bitflags",
- "memchr",
- "pulldown-cmark-escape 0.10.1",
- "unicase",
-]
-
[[package]]
name = "pulldown-cmark"
version = "0.11.3"
@@ -2941,16 +2777,10 @@ checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625"
dependencies = [
"bitflags",
"memchr",
- "pulldown-cmark-escape 0.11.0",
+ "pulldown-cmark-escape",
"unicase",
]
-[[package]]
-name = "pulldown-cmark-escape"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3"
-
[[package]]
name = "pulldown-cmark-escape"
version = "0.11.0"
@@ -3317,6 +3147,7 @@ dependencies = [
"rand 0.8.5",
"rand_xoshiro",
"rustc_data_structures",
+ "rustc_hashes",
"rustc_index",
"rustc_macros",
"rustc_serialize",
@@ -3544,6 +3375,7 @@ dependencies = [
"rustc_errors",
"rustc_fluent_macro",
"rustc_fs_util",
+ "rustc_hashes",
"rustc_hir",
"rustc_index",
"rustc_llvm",
@@ -3586,6 +3418,7 @@ dependencies = [
"rustc_errors",
"rustc_fluent_macro",
"rustc_fs_util",
+ "rustc_hashes",
"rustc_hir",
"rustc_hir_pretty",
"rustc_incremental",
@@ -3658,6 +3491,7 @@ dependencies = [
"rustc-stable-hash",
"rustc_arena",
"rustc_graphviz",
+ "rustc_hashes",
"rustc_index",
"rustc_macros",
"rustc_serialize",
@@ -3768,6 +3602,7 @@ dependencies = [
"rustc_error_codes",
"rustc_error_messages",
"rustc_fluent_macro",
+ "rustc_hashes",
"rustc_hir",
"rustc_index",
"rustc_lexer",
@@ -3840,6 +3675,13 @@ version = "0.0.0"
name = "rustc_graphviz"
version = "0.0.0"
+[[package]]
+name = "rustc_hashes"
+version = "0.0.0"
+dependencies = [
+ "rustc-stable-hash",
+]
+
[[package]]
name = "rustc_hir"
version = "0.0.0"
@@ -3849,6 +3691,7 @@ dependencies = [
"rustc_arena",
"rustc_ast",
"rustc_data_structures",
+ "rustc_hashes",
"rustc_index",
"rustc_macros",
"rustc_serialize",
@@ -4169,6 +4012,7 @@ dependencies = [
"rustc_feature",
"rustc_fluent_macro",
"rustc_graphviz",
+ "rustc_hashes",
"rustc_hir",
"rustc_hir_pretty",
"rustc_index",
@@ -4405,6 +4249,7 @@ dependencies = [
"measureme",
"rustc_data_structures",
"rustc_errors",
+ "rustc_hashes",
"rustc_hir",
"rustc_index",
"rustc_middle",
@@ -4428,6 +4273,7 @@ dependencies = [
"rustc_errors",
"rustc_feature",
"rustc_fluent_macro",
+ "rustc_hashes",
"rustc_hir",
"rustc_index",
"rustc_macros",
@@ -4488,6 +4334,7 @@ name = "rustc_serialize"
version = "0.0.0"
dependencies = [
"indexmap",
+ "rustc_hashes",
"rustc_macros",
"smallvec",
"tempfile",
@@ -4508,6 +4355,7 @@ dependencies = [
"rustc_feature",
"rustc_fluent_macro",
"rustc_fs_util",
+ "rustc_hashes",
"rustc_hir",
"rustc_lint_defs",
"rustc_macros",
@@ -4549,6 +4397,7 @@ dependencies = [
"md-5",
"rustc_arena",
"rustc_data_structures",
+ "rustc_hashes",
"rustc_index",
"rustc_macros",
"rustc_serialize",
@@ -4568,6 +4417,7 @@ dependencies = [
"rustc_abi",
"rustc_data_structures",
"rustc_errors",
+ "rustc_hashes",
"rustc_hir",
"rustc_middle",
"rustc_session",
@@ -4663,6 +4513,7 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_fluent_macro",
+ "rustc_hashes",
"rustc_hir",
"rustc_index",
"rustc_infer",
@@ -5289,16 +5140,6 @@ dependencies = [
"winapi-util",
]
-[[package]]
-name = "terminal_size"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9"
-dependencies = [
- "rustix",
- "windows-sys 0.59.0",
-]
-
[[package]]
name = "termize"
version = "0.1.1"
@@ -5539,12 +5380,6 @@ dependencies = [
"winnow",
]
-[[package]]
-name = "topological-sort"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
-
[[package]]
name = "tracing"
version = "0.1.37"
@@ -5665,12 +5500,6 @@ dependencies = [
"regex-lite",
]
-[[package]]
-name = "ucd-trie"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
-
[[package]]
name = "ui_test"
version = "0.26.5"
diff --git a/Cargo.toml b/Cargo.toml
index 97e782d0df02..20a43aaaeeb3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,6 @@ members = [
"src/tools/clippy/clippy_dev",
"src/tools/compiletest",
"src/tools/run-make-support",
- "src/tools/error_index_generator",
"src/tools/linkchecker",
"src/tools/lint-docs",
"src/tools/miropt-test-tools",
diff --git a/RELEASES.md b/RELEASES.md
index f0def1a0e423..038d7ca639f2 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -34,7 +34,8 @@ Libraries
---------
- [Panics in the standard library now have a leading `library/` in their path](https://github.com/rust-lang/rust/pull/132390)
- [`std::env::home_dir()` on Windows now ignores the non-standard `$HOME` environment variable](https://github.com/rust-lang/rust/pull/132515)
- It will be un-deprecated in a subsequent release.
+
+ It will be un-deprecated in a subsequent release.
- [Add `AsyncFn*` to the prelude in all editions.](https://github.com/rust-lang/rust/pull/132611)
@@ -98,15 +99,18 @@ Rustdoc
Compatibility Notes
-------------------
- [`rustc` no longer treats the `test` cfg as a well known check-cfg](https://github.com/rust-lang/rust/pull/131729), instead it is up to the build systems and users of `--check-cfg`[^check-cfg] to set it as a well known cfg using `--check-cfg=cfg(test)`.
+
This is done to enable build systems like Cargo to set it conditionally, as not all source files are suitable for unit tests.
[Cargo (for now) unconditionally sets the `test` cfg as a well known cfg](https://github.com/rust-lang/cargo/pull/14963).
-[^check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html
+ [^check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html
- [Disable potentially incorrect type inference if there are trivial and non-trivial where-clauses](https://github.com/rust-lang/rust/pull/132325)
- `std::env::home_dir()` has been deprecated for years, because it can give surprising results in some Windows configurations if the `HOME` environment variable is set (which is not the normal configuration on Windows). We had previously avoided changing its behavior, out of concern for compatibility with code depending on this non-standard configuration. Given how long this function has been deprecated, we're now fixing its behavior as a bugfix. A subsequent release will remove the deprecation for this function.
- [Make `core::ffi::c_char` signedness more closely match that of the platform-default `char`](https://github.com/rust-lang/rust/pull/132975)
+
This changed `c_char` from an `i8` to `u8` or vice versa on many Tier 2 and 3
targets (mostly Arm and RISC-V embedded targets). The new definition may
result in compilation failures but fixes compatibility issues with C.
+
The `libc` crate matches this change as of its 0.2.169 release.
- [When compiling a nested `macro_rules` macro from an external crate, the content of the inner `macro_rules` is now built with the edition of the external crate, not the local crate.](https://github.com/rust-lang/rust/pull/133274)
- [Increase `sparcv9-sun-solaris` and `x86_64-pc-solaris` Solaris baseline to 11.4.](https://github.com/rust-lang/rust/pull/133293)
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index 1013f1d3958d..3d6f4a6a1092 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -9,6 +9,7 @@ bitflags = "2.4.1"
rand = { version = "0.8.4", default-features = false, optional = true }
rand_xoshiro = { version = "0.6.0", optional = true }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
+rustc_hashes = { path = "../rustc_hashes" }
rustc_index = { path = "../rustc_index", default-features = false }
rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true }
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index b8773f9ff38f..45cd0b517f6c 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -2,6 +2,7 @@ use std::fmt::{self, Write};
use std::ops::{Bound, Deref};
use std::{cmp, iter};
+use rustc_hashes::Hash64;
use rustc_index::Idx;
use tracing::debug;
@@ -133,7 +134,7 @@ impl LayoutCalculator {
size,
max_repr_align: None,
unadjusted_abi_align: align.abi,
- randomization_seed: combined_seed,
+ randomization_seed: Hash64::new(combined_seed),
}
}
@@ -226,7 +227,7 @@ impl LayoutCalculator {
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align.abi,
- randomization_seed: 0,
+ randomization_seed: Hash64::ZERO,
}
}
@@ -1058,7 +1059,7 @@ impl LayoutCalculator {
// unsizable tail fields are excluded so that we use the same seed for the sized and unsized layouts.
let field_seed = fields_excluding_tail
.iter()
- .fold(0u64, |acc, f| acc.wrapping_add(f.randomization_seed));
+ .fold(Hash64::ZERO, |acc, f| acc.wrapping_add(f.randomization_seed));
if optimize_field_order && fields.len() > 1 {
// If `-Z randomize-layout` was enabled for the type definition we can shuffle
@@ -1072,7 +1073,7 @@ impl LayoutCalculator {
// `ReprOptions.field_shuffle_seed` is a deterministic seed we can use to randomize field
// ordering.
let mut rng = rand_xoshiro::Xoshiro128StarStar::seed_from_u64(
- field_seed.wrapping_add(repr.field_shuffle_seed),
+ field_seed.wrapping_add(repr.field_shuffle_seed).as_u64(),
);
// Shuffle the ordering of the fields.
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index da1c706d67cc..dbb4bed5cdd9 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -50,6 +50,7 @@ use std::str::FromStr;
use bitflags::bitflags;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::StableOrd;
+use rustc_hashes::Hash64;
use rustc_index::{Idx, IndexSlice, IndexVec};
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable_Generic, Encodable_Generic, HashStable_Generic};
@@ -140,7 +141,7 @@ pub struct ReprOptions {
/// hash without loss, but it does pay the price of being larger.
/// Everything's a tradeoff, a 64-bit seed should be sufficient for our
/// purposes (primarily `-Z randomize-layout`)
- pub field_shuffle_seed: u64,
+ pub field_shuffle_seed: Hash64,
}
impl ReprOptions {
@@ -1727,7 +1728,7 @@ pub struct LayoutData {
/// transmuted to `Foo` we aim to create probalistically distinct seeds so that Foo can choose
/// to reorder its fields based on that information. The current implementation is a conservative
/// approximation of this goal.
- pub randomization_seed: u64,
+ pub randomization_seed: Hash64,
}
impl LayoutData {
@@ -1781,7 +1782,7 @@ impl LayoutData {
align,
max_repr_align: None,
unadjusted_abi_align: align.abi,
- randomization_seed,
+ randomization_seed: Hash64::new(randomization_seed),
}
}
}
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 60f8c6e10481..346edc87c86b 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -203,10 +203,8 @@ impl HasTokens for Nonterminal {
Nonterminal::NtStmt(stmt) => stmt.tokens(),
Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(),
Nonterminal::NtPat(pat) => pat.tokens(),
- Nonterminal::NtTy(ty) => ty.tokens(),
Nonterminal::NtMeta(attr_item) => attr_item.tokens(),
Nonterminal::NtPath(path) => path.tokens(),
- Nonterminal::NtVis(vis) => vis.tokens(),
Nonterminal::NtBlock(block) => block.tokens(),
}
}
@@ -216,10 +214,8 @@ impl HasTokens for Nonterminal {
Nonterminal::NtStmt(stmt) => stmt.tokens_mut(),
Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(),
Nonterminal::NtPat(pat) => pat.tokens_mut(),
- Nonterminal::NtTy(ty) => ty.tokens_mut(),
Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(),
Nonterminal::NtPath(path) => path.tokens_mut(),
- Nonterminal::NtVis(vis) => vis.tokens_mut(),
Nonterminal::NtBlock(block) => block.tokens_mut(),
}
}
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index de9f049704a4..40b29fdba250 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -907,7 +907,6 @@ fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) {
}),
token::NtPat(pat) => vis.visit_pat(pat),
token::NtExpr(expr) => vis.visit_expr(expr),
- token::NtTy(ty) => vis.visit_ty(ty),
token::NtLiteral(expr) => vis.visit_expr(expr),
token::NtMeta(item) => {
let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut();
@@ -916,7 +915,6 @@ fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) {
visit_lazy_tts(vis, tokens);
}
token::NtPath(path) => vis.visit_path(path),
- token::NtVis(visib) => vis.visit_vis(visib),
}
}
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 36a7b7d87892..97d121909f8d 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -84,7 +84,9 @@ pub enum MetaVarKind {
// This field is needed for `Token::can_begin_string_literal`.
can_begin_string_literal: bool,
},
- Ty,
+ Ty {
+ is_path: bool,
+ },
Ident,
Lifetime,
Literal,
@@ -104,7 +106,7 @@ impl fmt::Display for MetaVarKind {
MetaVarKind::Pat(PatParam { inferred: false }) => sym::pat_param,
MetaVarKind::Expr { kind: Expr2021 { inferred: true } | Expr, .. } => sym::expr,
MetaVarKind::Expr { kind: Expr2021 { inferred: false }, .. } => sym::expr_2021,
- MetaVarKind::Ty => sym::ty,
+ MetaVarKind::Ty { .. } => sym::ty,
MetaVarKind::Ident => sym::ident,
MetaVarKind::Lifetime => sym::lifetime,
MetaVarKind::Literal => sym::literal,
@@ -659,7 +661,6 @@ impl Token {
| NtMeta(..)
| NtPat(..)
| NtPath(..)
- | NtTy(..)
),
OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
MetaVarKind::Expr { .. } |
@@ -667,7 +668,7 @@ impl Token {
MetaVarKind::Meta |
MetaVarKind::Pat(_) |
MetaVarKind::Path |
- MetaVarKind::Ty
+ MetaVarKind::Ty { .. }
))) => true,
_ => false,
}
@@ -688,9 +689,9 @@ impl Token {
Lifetime(..) | // lifetime bound in trait object
Lt | BinOp(Shl) | // associated path
PathSep => true, // global path
- Interpolated(ref nt) => matches!(&**nt, NtTy(..) | NtPath(..)),
+ Interpolated(ref nt) => matches!(&**nt, NtPath(..)),
OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
- MetaVarKind::Ty |
+ MetaVarKind::Ty { .. } |
MetaVarKind::Path
))) => true,
// For anonymous structs or unions, which only appear in specific positions
@@ -969,6 +970,15 @@ impl Token {
}
}
+ /// Is this an invisible open delimiter at the start of a token sequence
+ /// from an expanded metavar?
+ pub fn is_metavar_seq(&self) -> Option {
+ match self.kind {
+ OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => Some(kind),
+ _ => None,
+ }
+ }
+
pub fn glue(&self, joint: &Token) -> Option {
let kind = match self.kind {
Eq => match joint.kind {
@@ -1067,12 +1077,10 @@ pub enum Nonterminal {
NtStmt(P),
NtPat(P),
NtExpr(P),
- NtTy(P),
NtLiteral(P),
/// Stuff inside brackets for attributes
NtMeta(P),
NtPath(P),
- NtVis(P),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
@@ -1166,10 +1174,8 @@ impl Nonterminal {
NtStmt(stmt) => stmt.span,
NtPat(pat) => pat.span,
NtExpr(expr) | NtLiteral(expr) => expr.span,
- NtTy(ty) => ty.span,
NtMeta(attr_item) => attr_item.span(),
NtPath(path) => path.span,
- NtVis(vis) => vis.span,
}
}
@@ -1181,10 +1187,8 @@ impl Nonterminal {
NtPat(..) => "pattern",
NtExpr(..) => "expression",
NtLiteral(..) => "literal",
- NtTy(..) => "type",
NtMeta(..) => "attribute",
NtPath(..) => "path",
- NtVis(..) => "visibility",
}
}
}
@@ -1207,11 +1211,9 @@ impl fmt::Debug for Nonterminal {
NtStmt(..) => f.pad("NtStmt(..)"),
NtPat(..) => f.pad("NtPat(..)"),
NtExpr(..) => f.pad("NtExpr(..)"),
- NtTy(..) => f.pad("NtTy(..)"),
NtLiteral(..) => f.pad("NtLiteral(..)"),
NtMeta(..) => f.pad("NtMeta(..)"),
NtPath(..) => f.pad("NtPath(..)"),
- NtVis(..) => f.pad("NtVis(..)"),
}
}
}
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 50f10d083a04..1123ea3a449b 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -469,10 +469,8 @@ impl TokenStream {
}
Nonterminal::NtStmt(stmt) => TokenStream::from_ast(stmt),
Nonterminal::NtPat(pat) => TokenStream::from_ast(pat),
- Nonterminal::NtTy(ty) => TokenStream::from_ast(ty),
Nonterminal::NtMeta(attr) => TokenStream::from_ast(attr),
Nonterminal::NtPath(path) => TokenStream::from_ast(path),
- Nonterminal::NtVis(vis) => TokenStream::from_ast(vis),
Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr),
}
}
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index facc9414b20d..1c777111896d 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -407,7 +407,7 @@ fn compute_hir_hash(
.iter_enumerated()
.filter_map(|(def_id, info)| {
let info = info.as_owner()?;
- let def_path_hash = tcx.hir().def_path_hash(def_id);
+ let def_path_hash = tcx.hir_def_path_hash(def_id);
Some((def_path_hash, info))
})
.collect();
@@ -497,7 +497,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
"adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}",
node_id,
def_kind,
- self.tcx.hir().def_key(self.local_def_id(node_id)),
+ self.tcx.hir_def_key(self.local_def_id(node_id)),
);
let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id();
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 6269728e67f7..b2cc58fbe116 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -14,16 +14,15 @@ use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, MultiSpan, struct_span_code_err};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{Map, Visitor, walk_block, walk_expr};
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr};
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, LangItem, PatField};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter::OnlyBodies;
-use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
FakeBorrowKind, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind,
- Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
- TerminatorKind, VarBindingForm, VarDebugInfoContents,
+ Operand, Place, PlaceRef, PlaceTy, ProjectionElem, Rvalue, Statement, StatementKind,
+ Terminator, TerminatorKind, VarBindingForm, VarDebugInfoContents,
};
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{
@@ -348,13 +347,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
expr: Option<&'hir hir::Expr<'hir>>,
pat: Option<&'hir hir::Pat<'hir>>,
parent_pat: Option<&'hir hir::Pat<'hir>>,
- hir: rustc_middle::hir::map::Map<'hir>,
+ tcx: TyCtxt<'hir>,
}
impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
type NestedFilter = OnlyBodies;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.hir
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
@@ -386,8 +385,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
hir::intravisit::walk_pat(self, p);
}
}
+ let tcx = self.infcx.tcx;
let hir = self.infcx.tcx.hir();
- if let Some(body) = hir.maybe_body_owned_by(self.mir_def_id()) {
+ if let Some(body) = tcx.hir_maybe_body_owned_by(self.mir_def_id()) {
let expr = body.value;
let place = &self.move_data.move_paths[mpi].place;
let span = place.as_local().map(|local| self.body.local_decls[local].source_info.span);
@@ -396,7 +396,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
expr: None,
pat: None,
parent_pat: None,
- hir,
+ tcx,
};
finder.visit_expr(expr);
if let Some(span) = span
@@ -782,9 +782,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// We use the statements were the binding was initialized, and inspect the HIR to look
// for the branching codepaths that aren't covered, to point at them.
- let map = self.infcx.tcx.hir();
- let body = map.body_owned_by(self.mir_def_id());
- let mut visitor = ConditionVisitor { tcx: self.infcx.tcx, spans, name, errors: vec![] };
+ let tcx = self.infcx.tcx;
+ let body = tcx.hir_body_owned_by(self.mir_def_id());
+ let mut visitor = ConditionVisitor { tcx, spans, name, errors: vec![] };
visitor.visit_body(&body);
let spans = visitor.spans;
@@ -1082,7 +1082,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
] {
for (destination, sp) in elements {
if let Ok(hir_id) = destination.target_id
- && let hir::Node::Expr(expr) = tcx.hir().hir_node(hir_id)
+ && let hir::Node::Expr(expr) = tcx.hir_node(hir_id)
&& !matches!(
sp.desugaring_kind(),
Some(DesugaringKind::ForLoop | DesugaringKind::WhileLoop)
@@ -1437,7 +1437,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let Some(hir_generics) = tcx
.typeck_root_def_id(self.mir_def_id().to_def_id())
.as_local()
- .and_then(|def_id| tcx.hir().get_generics(def_id))
+ .and_then(|def_id| tcx.hir_get_generics(def_id))
else {
return;
};
@@ -1889,7 +1889,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
fn suggest_copy_for_type_in_cloned_ref(&self, err: &mut Diag<'infcx>, place: Place<'tcx>) {
let tcx = self.infcx.tcx;
- let hir = tcx.hir();
let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
struct FindUselessClone<'tcx> {
@@ -1917,7 +1916,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let mut expr_finder = FindUselessClone::new(tcx, self.mir_def_id());
- let body = hir.body(body_id).value;
+ let body = tcx.hir_body(body_id).value;
expr_finder.visit_expr(body);
struct Holds<'tcx> {
@@ -2106,7 +2105,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let tcx = self.infcx.tcx;
let body_id = tcx.hir_node(self.mir_hir_id()).body_id()?;
let mut expr_finder = FindExprBySpan::new(span, tcx);
- expr_finder.visit_expr(tcx.hir().body(body_id).value);
+ expr_finder.visit_expr(tcx.hir_body(body_id).value);
expr_finder.result
}
@@ -2258,7 +2257,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
) {
let issue_span = issued_spans.args_or_use();
let tcx = self.infcx.tcx;
- let hir = tcx.hir();
let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
let typeck_results = tcx.typeck(self.mir_def_id());
@@ -2346,7 +2344,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
pat_span: None,
head: None,
};
- finder.visit_expr(hir.body(body_id).value);
+ finder.visit_expr(tcx.hir_body(body_id).value);
if let Some(body_expr) = finder.body_expr
&& let Some(loop_span) = finder.loop_span
@@ -2445,7 +2443,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
) {
let &UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
let tcx = self.infcx.tcx;
- let hir = tcx.hir();
// Get the type of the local that we are trying to borrow
let local = borrowed_place.local;
@@ -2454,10 +2451,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// Get the body the error happens in
let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
- let body_expr = hir.body(body_id).value;
+ let body_expr = tcx.hir_body(body_id).value;
struct ClosureFinder<'hir> {
- hir: rustc_middle::hir::map::Map<'hir>,
+ tcx: TyCtxt<'hir>,
borrow_span: Span,
res: Option<(&'hir hir::Expr<'hir>, &'hir hir::Closure<'hir>)>,
/// The path expression with the `borrow_span` span
@@ -2466,8 +2463,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
impl<'hir> Visitor<'hir> for ClosureFinder<'hir> {
type NestedFilter = OnlyBodies;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.hir
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
@@ -2493,7 +2490,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// Find the closure that most tightly wraps `capture_kind_span`
let mut finder =
- ClosureFinder { hir, borrow_span: capture_kind_span, res: None, error_path: None };
+ ClosureFinder { tcx, borrow_span: capture_kind_span, res: None, error_path: None };
finder.visit_expr(body_expr);
let Some((closure_expr, closure)) = finder.res else { return };
@@ -2524,7 +2521,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// Find the first argument with a matching type, get its name
let Some((_, this_name)) =
- params.iter().zip(hir.body_param_names(closure.body)).find(|(param_ty, name)| {
+ params.iter().zip(tcx.hir_body_param_names(closure.body)).find(|(param_ty, name)| {
// FIXME: also support deref for stuff like `Rc` arguments
param_ty.peel_refs() == local_ty && name != &Ident::empty()
})
@@ -2558,7 +2555,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
let mut finder = VariableUseFinder { local_id, spans: Vec::new() };
- finder.visit_expr(hir.body(closure.body).value);
+ finder.visit_expr(tcx.hir_body(closure.body).value);
spans = finder.spans;
} else {
@@ -3211,7 +3208,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
if let Some(scope) = self.body.source_scopes.get(source_info.scope)
&& let ClearCrossCrate::Set(scope_data) = &scope.local_data
&& let Some(id) = self.infcx.tcx.hir_node(scope_data.lint_root).body_id()
- && let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir().body(id).value.kind
+ && let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir_body(id).value.kind
{
for stmt in block.stmts {
let mut visitor = NestedStatementVisitor {
@@ -4180,7 +4177,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
let is_closure = self.infcx.tcx.is_closure_like(did.to_def_id());
let fn_hir_id = self.infcx.tcx.local_def_id_to_hir_id(did);
- let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?;
+ let fn_decl = self.infcx.tcx.hir_fn_decl_by_hir_id(fn_hir_id)?;
// We need to work out which arguments to highlight. We do this by looking
// at the return type, where there are three cases:
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 3e474225afdf..a88b27f24767 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -75,10 +75,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
if let Some(span) = borrow_span {
let def_id = body.source.def_id();
- if let Some(node) = tcx.hir().get_if_local(def_id)
+ if let Some(node) = tcx.hir_get_if_local(def_id)
&& let Some(body_id) = node.body_id()
{
- let body = tcx.hir().body(body_id);
+ let body = tcx.hir_body(body_id);
let mut expr_finder = FindExprBySpan::new(span, tcx);
expr_finder.visit_expr(body.value);
if let Some(mut expr) = expr_finder.result {
@@ -256,8 +256,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
impl<'hir> rustc_hir::intravisit::Visitor<'hir> for FindLetExpr<'hir> {
type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
if let hir::ExprKind::If(cond, _conseq, _alt)
@@ -308,9 +308,9 @@ impl<'tcx> BorrowExplanation<'tcx> {
suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err);
} else if let Some((old, new)) = multiple_borrow_span
&& let def_id = body.source.def_id()
- && let Some(node) = tcx.hir().get_if_local(def_id)
+ && let Some(node) = tcx.hir_get_if_local(def_id)
&& let Some(body_id) = node.body_id()
- && let hir_body = tcx.hir().body(body_id)
+ && let hir_body = tcx.hir_body(body_id)
&& let mut expr_finder = (FindLetExpr { span: old, result: None, tcx })
&& let Some((let_expr_span, let_expr_pat, let_expr_init)) = {
expr_finder.visit_expr(hir_body.value);
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index df83ac985c65..7da089c5e8c6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -13,10 +13,9 @@ use rustc_infer::infer::{
};
use rustc_infer::traits::SelectionError;
use rustc_middle::bug;
-use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo,
- LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement,
+ LocalKind, Location, Operand, Place, PlaceRef, PlaceTy, ProjectionElem, Rvalue, Statement,
StatementKind, Terminator, TerminatorKind, find_self_call,
};
use rustc_middle::ty::print::Print;
@@ -1220,7 +1219,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
.tcx
.typeck_root_def_id(self.mir_def_id().to_def_id())
.as_local()
- .and_then(|def_id| self.infcx.tcx.hir().get_generics(def_id))
+ .and_then(|def_id| self.infcx.tcx.hir_get_generics(def_id))
&& let spans = hir_generics
.predicates
.iter()
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 58c5c2fd7742..ddf6187a662e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -7,7 +7,7 @@ use rustc_hir::intravisit::Visitor;
use rustc_hir::{self as hir, CaptureBy, ExprKind, HirId, Node};
use rustc_middle::bug;
use rustc_middle::mir::*;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
@@ -347,7 +347,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// Find the closure that captured the binding.
let mut expr_finder = FindExprBySpan::new(args_span, tcx);
expr_finder.include_closures = true;
- expr_finder.visit_expr(tcx.hir().body(body_id).value);
+ expr_finder.visit_expr(tcx.hir_body(body_id).value);
let Some(closure_expr) = expr_finder.result else { return };
let ExprKind::Closure(closure) = closure_expr.kind else { return };
// We'll only suggest cloning the binding if it's a `move` closure.
@@ -357,7 +357,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let use_span = use_spans.var_or_use();
let mut expr_finder = FindExprBySpan::new(use_span, tcx);
expr_finder.include_closures = true;
- expr_finder.visit_expr(tcx.hir().body(body_id).value);
+ expr_finder.visit_expr(tcx.hir_body(body_id).value);
let Some(use_expr) = expr_finder.result else { return };
let parent = tcx.parent_hir_node(use_expr.hir_id);
if let Node::Expr(expr) = parent
@@ -690,7 +690,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
/// make it bind by reference instead (if possible)
struct BindingFinder<'tcx> {
typeck_results: &'tcx ty::TypeckResults<'tcx>,
- hir: rustc_middle::hir::map::Map<'tcx>,
+ tcx: TyCtxt<'tcx>,
/// Input: the span of the pattern we're finding bindings in
pat_span: Span,
/// Input: the spans of the bindings we're providing suggestions for
@@ -709,8 +709,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
impl<'tcx> Visitor<'tcx> for BindingFinder<'tcx> {
type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.hir
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result {
@@ -777,12 +777,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
let Some(pat_span) = pat_span else { return };
- let hir = self.infcx.tcx.hir();
- let Some(body) = hir.maybe_body_owned_by(self.mir_def_id()) else { return };
+ let tcx = self.infcx.tcx;
+ let Some(body) = tcx.hir_maybe_body_owned_by(self.mir_def_id()) else { return };
let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
let mut finder = BindingFinder {
typeck_results,
- hir,
+ tcx,
pat_span,
binding_spans,
found_pat: false,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 706dd7135f73..be83e61f75d8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -648,10 +648,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
}
}
- let hir_map = self.infcx.tcx.hir();
let def_id = self.body.source.def_id();
let Some(local_def_id) = def_id.as_local() else { return };
- let Some(body) = hir_map.maybe_body_owned_by(local_def_id) else { return };
+ let Some(body) = self.infcx.tcx.hir_maybe_body_owned_by(local_def_id) else { return };
let mut v = SuggestIndexOperatorAlternativeVisitor {
assign_span: span,
@@ -749,7 +748,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// `fn foo(&x: &i32)` -> `fn foo(&(mut x): &i32)`
let def_id = self.body.source.def_id();
if let Some(local_def_id) = def_id.as_local()
- && let Some(body) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
+ && let Some(body) = self.infcx.tcx.hir_maybe_body_owned_by(local_def_id)
&& let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(&body).break_value()
&& let node = self.infcx.tcx.hir_node(hir_id)
&& let hir::Node::LetStmt(hir::LetStmt {
@@ -856,7 +855,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
use hir::ExprKind::{AddrOf, Block, Call, MethodCall};
use hir::{BorrowKind, Expr};
- let hir_map = self.infcx.tcx.hir();
+ let tcx = self.infcx.tcx;
struct Finder {
span: Span,
}
@@ -871,7 +870,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
}
}
- if let Some(body) = hir_map.maybe_body_owned_by(self.mir_def_id())
+ if let Some(body) = tcx.hir_maybe_body_owned_by(self.mir_def_id())
&& let Block(block, _) = body.value.kind
{
// `span` corresponds to the expression being iterated, find the `for`-loop desugared
@@ -884,17 +883,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
MethodCall(path_segment, _, _, span) => {
// We have `for _ in iter.read_only_iter()`, try to
// suggest `for _ in iter.mutable_iter()` instead.
- let opt_suggestions = self
- .infcx
- .tcx
+ let opt_suggestions = tcx
.typeck(path_segment.hir_id.owner.def_id)
.type_dependent_def_id(expr.hir_id)
- .and_then(|def_id| self.infcx.tcx.impl_of_method(def_id))
- .map(|def_id| self.infcx.tcx.associated_items(def_id))
+ .and_then(|def_id| tcx.impl_of_method(def_id))
+ .map(|def_id| tcx.associated_items(def_id))
.map(|assoc_items| {
assoc_items
.in_definition_order()
- .map(|assoc_item_def| assoc_item_def.ident(self.infcx.tcx))
+ .map(|assoc_item_def| assoc_item_def.ident(tcx))
.filter(|&ident| {
let original_method_ident = path_segment.ident;
original_method_ident != ident
@@ -936,12 +933,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
fn expected_fn_found_fn_mut_call(&self, err: &mut Diag<'_>, sp: Span, act: &str) {
err.span_label(sp, format!("cannot {act}"));
- let hir = self.infcx.tcx.hir();
+ let tcx = self.infcx.tcx;
+ let hir = tcx.hir();
let closure_id = self.mir_hir_id();
- let closure_span = self.infcx.tcx.def_span(self.mir_def_id());
- let fn_call_id = self.infcx.tcx.parent_hir_id(closure_id);
- let node = self.infcx.tcx.hir_node(fn_call_id);
- let def_id = hir.enclosing_body_owner(fn_call_id);
+ let closure_span = tcx.def_span(self.mir_def_id());
+ let fn_call_id = tcx.parent_hir_id(closure_id);
+ let node = tcx.hir_node(fn_call_id);
+ let def_id = tcx.hir_enclosing_body_owner(fn_call_id);
let mut look_at_return = true;
// If the HIR node is a function or method call gets the def ID
@@ -951,7 +949,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
return None;
};
- let typeck_results = self.infcx.tcx.typeck(def_id);
+ let typeck_results = tcx.typeck(def_id);
match kind {
hir::ExprKind::Call(expr, args) => {
@@ -980,7 +978,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
.map(|(pos, _)| pos)
.next();
- let arg = match hir.get_if_local(callee_def_id) {
+ let arg = match tcx.hir_get_if_local(callee_def_id) {
Some(
hir::Node::Item(hir::Item {
ident, kind: hir::ItemKind::Fn { sig, .. }, ..
@@ -1022,7 +1020,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
if look_at_return && hir.get_fn_id_for_return_block(closure_id).is_some() {
// ...otherwise we are probably in the tail expression of the function, point at the
// return type.
- match self.infcx.tcx.hir_node_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
+ match tcx.hir_node_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
hir::Node::Item(hir::Item {
ident, kind: hir::ItemKind::Fn { sig, .. }, ..
})
@@ -1050,9 +1048,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
fn suggest_using_iter_mut(&self, err: &mut Diag<'_>) {
let source = self.body.source;
- let hir = self.infcx.tcx.hir();
if let InstanceKind::Item(def_id) = source.instance
- && let Some(Node::Expr(hir::Expr { hir_id, kind, .. })) = hir.get_if_local(def_id)
+ && let Some(Node::Expr(hir::Expr { hir_id, kind, .. })) =
+ self.infcx.tcx.hir_get_if_local(def_id)
&& let ExprKind::Closure(hir::Closure { kind: hir::ClosureKind::Closure, .. }) = kind
&& let Node::Expr(expr) = self.infcx.tcx.parent_hir_node(*hir_id)
{
@@ -1274,7 +1272,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}) => {
let def_id = self.body.source.def_id();
let hir_id = if let Some(local_def_id) = def_id.as_local()
- && let Some(body) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
+ && let Some(body) = self.infcx.tcx.hir_maybe_body_owned_by(local_def_id)
{
BindingFinder { span: err_label_span }.visit_body(&body).break_value()
} else {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index df79da76bcea..55b6367f35ff 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -219,7 +219,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
lower_bound: RegionVid,
) {
let mut suggestions = vec![];
- let hir = self.infcx.tcx.hir();
+ let tcx = self.infcx.tcx;
// find generic associated types in the given region 'lower_bound'
let gat_id_and_generics = self
@@ -228,12 +228,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
.map(|placeholder| {
if let Some(id) = placeholder.bound.kind.get_id()
&& let Some(placeholder_id) = id.as_local()
- && let gat_hir_id = self.infcx.tcx.local_def_id_to_hir_id(placeholder_id)
- && let Some(generics_impl) = self
- .infcx
- .tcx
- .parent_hir_node(self.infcx.tcx.parent_hir_id(gat_hir_id))
- .generics()
+ && let gat_hir_id = tcx.local_def_id_to_hir_id(placeholder_id)
+ && let Some(generics_impl) =
+ tcx.parent_hir_node(tcx.parent_hir_id(gat_hir_id)).generics()
{
Some((gat_hir_id, generics_impl))
} else {
@@ -254,7 +251,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
};
if bound_generic_params
.iter()
- .rfind(|bgp| self.infcx.tcx.local_def_id_to_hir_id(bgp.def_id) == *gat_hir_id)
+ .rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == *gat_hir_id)
.is_some()
{
for bound in *bounds {
@@ -270,7 +267,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
return;
};
diag.span_note(*trait_span, fluent::borrowck_limitations_implies_static);
- let Some(generics_fn) = hir.get_generics(self.body.source.def_id().expect_local())
+ let Some(generics_fn) = tcx.hir_get_generics(self.body.source.def_id().expect_local())
else {
return;
};
@@ -1162,7 +1159,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
if ocx.select_all_or_error().is_empty() && count > 0 {
diag.span_suggestion_verbose(
- tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(),
+ tcx.hir_body(*body).value.peel_blocks().span.shrink_to_lo(),
fluent::borrowck_dereference_suggestion,
"*".repeat(count),
Applicability::MachineApplicable,
@@ -1172,8 +1169,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
#[allow(rustc::diagnostic_outside_of_impl)]
fn suggest_move_on_borrowing_closure(&self, diag: &mut Diag<'_>) {
- let map = self.infcx.tcx.hir();
- let body = map.body_owned_by(self.mir_def_id());
+ let body = self.infcx.tcx.hir_body_owned_by(self.mir_def_id());
let expr = &body.value.peel_blocks();
let mut closure_span = None::;
match expr.kind {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index ccd13badad74..b036e6e950b9 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -424,7 +424,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
&self,
argument_index: usize,
) -> Option<&hir::Ty<'tcx>> {
- let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(self.mir_hir_id())?;
+ let fn_decl = self.infcx.tcx.hir_fn_decl_by_hir_id(self.mir_hir_id())?;
let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?;
match argument_hir_ty.kind {
// This indicates a variable with no type annotation, like
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 53cf4f34ae79..a98984a4b4c7 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -33,7 +33,6 @@ use rustc_index::{IndexSlice, IndexVec};
use rustc_infer::infer::{
InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
};
-use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::*;
use rustc_middle::query::Providers;
use rustc_middle::ty::fold::fold_regions;
@@ -188,7 +187,7 @@ fn do_mir_borrowck<'tcx>(
.iterate_to_fixpoint(tcx, body, Some("borrowck"))
.into_results_cursor(body);
- let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure();
+ let locals_are_invalidated_at_exit = tcx.hir_body_owner_kind(def).is_fn_or_closure();
let borrow_set = BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &move_data);
// Compute non-lexical lifetimes.
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index d2268c4779d6..e0e3e028c612 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1267,6 +1267,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let sub_region_scc = self.constraint_sccs.scc(sub_region);
let sup_region_scc = self.constraint_sccs.scc(sup_region);
+ if sub_region_scc == sup_region_scc {
+ debug!("{sup_region:?}: {sub_region:?} holds trivially; they are in the same SCC");
+ return true;
+ }
+
// If we are checking that `'sup: 'sub`, and `'sub` contains
// some placeholder that `'sup` cannot name, then this is only
// true if `'sup` outlives static.
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 93081919ec79..84759a0ae04a 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -19,7 +19,6 @@ use rustc_infer::infer::{
BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin,
};
use rustc_infer::traits::PredicateObligations;
-use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::traits::query::NoSolution;
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index eb0079a3883f..9a68eeb3326e 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -21,6 +21,7 @@ use std::iter;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Diag;
use rustc_hir::BodyOwnerKind;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_index::IndexVec;
@@ -576,7 +577,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let tcx = self.infcx.tcx;
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
- match tcx.hir().body_owner_kind(self.mir_def) {
+ match tcx.hir_body_owner_kind(self.mir_def) {
BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
let defining_ty = tcx.type_of(self.mir_def).instantiate_identity();
@@ -603,7 +604,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => {
let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
- if self.mir_def.to_def_id() == typeck_root_def_id {
+ if self.mir_def.to_def_id() == typeck_root_def_id
+ // Do not ICE when checking default_field_values consts with lifetimes (#135649)
+ && DefKind::Field != tcx.def_kind(tcx.parent(typeck_root_def_id))
+ {
let args =
self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_args);
DefiningTy::Const(self.mir_def.to_def_id(), args)
diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
index 521a250ab82c..c74efeb59f3f 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/comments.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
@@ -65,7 +65,7 @@ pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, '_>) {
if fx.clif_comments.enabled() {
fx.add_global_comment(String::new());
fx.add_global_comment(
- "kind local ty size align (abi,pref)".to_string(),
+ "kind local ty size align (abi)".to_string(),
);
}
}
@@ -84,14 +84,13 @@ pub(super) fn add_local_place_comments<'tcx>(
let (kind, extra) = place.debug_comment();
fx.add_global_comment(format!(
- "{:<5} {:5} {:30} {:4}b {}, {}{}{}",
+ "{:<5} {:5} {:30} {:4}b {}{}{}",
kind,
format!("{:?}", local),
format!("{:?}", ty),
size.bytes(),
align.abi.bytes(),
- align.pref.bytes(),
- if extra.is_empty() { "" } else { " " },
+ if extra.is_empty() { "" } else { " " },
extra,
));
}
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 425b2adf32a3..bcc70f4567fb 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -272,7 +272,7 @@ fn data_id_for_static(
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty))
.unwrap()
.align
- .pref
+ .abi
.bytes();
let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 2e713171ae06..57c88f4b0f9f 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -124,7 +124,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<
crate::constant::codegen_static(tcx, &mut jit_module, def_id);
}
MonoItem::GlobalAsm(item_id) => {
- let item = tcx.hir().item(item_id);
+ let item = tcx.hir_item(item_id);
tcx.dcx().span_fatal(item.span, "Global asm is not supported in JIT mode");
}
}
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index c0a3ce84d529..54745b0d8c10 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -15,7 +15,7 @@ use rustc_target::asm::InlineAsmArch;
use crate::prelude::*;
pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) {
- let item = tcx.hir().item(item_id);
+ let item = tcx.hir_item(item_id);
if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
let is_x86 =
matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64);
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 94f21ac5f574..a81722705488 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -25,6 +25,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_fs_util = { path = "../rustc_fs_util" }
+rustc_hashes = { path = "../rustc_hashes" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_llvm = { path = "../rustc_llvm" }
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 28f423efc214..8c75125e009b 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -2,19 +2,18 @@ use std::borrow::Borrow;
use std::cmp;
use libc::c_uint;
-use rustc_abi as abi;
-pub(crate) use rustc_abi::ExternAbi;
-use rustc_abi::{HasDataLayout, Primitive, Reg, RegKind, Size};
+use rustc_abi::{BackendRepr, HasDataLayout, Primitive, Reg, RegKind, Size};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
use rustc_codegen_ssa::traits::*;
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf;
-pub(crate) use rustc_middle::ty::layout::{WIDE_PTR_ADDR, WIDE_PTR_EXTRA};
use rustc_middle::{bug, ty};
use rustc_session::config;
-pub(crate) use rustc_target::callconv::*;
+use rustc_target::callconv::{
+ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, Conv, FnAbi, PassMode,
+};
use rustc_target::spec::SanitizerSet;
use smallvec::SmallVec;
@@ -458,7 +457,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
match &self.ret.mode {
PassMode::Direct(attrs) => {
attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
- if let abi::BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr {
+ if let BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr {
apply_range_attr(llvm::AttributePlace::ReturnValue, scalar);
}
}
@@ -499,7 +498,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
}
PassMode::Direct(attrs) => {
let i = apply(attrs);
- if let abi::BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
+ if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
apply_range_attr(llvm::AttributePlace::Argument(i), scalar);
}
}
@@ -514,9 +513,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
PassMode::Pair(a, b) => {
let i = apply(a);
let ii = apply(b);
- if let abi::BackendRepr::ScalarPair(scalar_a, scalar_b) =
- arg.layout.backend_repr
- {
+ if let BackendRepr::ScalarPair(scalar_a, scalar_b) = arg.layout.backend_repr {
apply_range_attr(llvm::AttributePlace::Argument(i), scalar_a);
apply_range_attr(llvm::AttributePlace::Argument(ii), scalar_b);
}
@@ -576,7 +573,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
}
if bx.cx.sess().opts.optimize != config::OptLevel::No
&& llvm_util::get_version() < (19, 0, 0)
- && let abi::BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr
+ && let BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr
&& matches!(scalar.primitive(), Primitive::Int(..))
// If the value is a boolean, the range is 0..2 and that ultimately
// become 0..0 when the type becomes i1, which would be rejected
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 78b3a7f85417..f17d98fa242b 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -7,7 +7,8 @@ use rustc_abi::{AddressSpace, HasDataLayout};
use rustc_ast::Mutability;
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::traits::*;
-use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hashes::Hash128;
use rustc_hir::def_id::DefId;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index 54c5d445f66b..4ffe551df09b 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -87,7 +87,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>(
pub(crate) fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool {
let omit_gdb_pretty_printer_section =
- attr::contains_name(cx.tcx.hir().krate_attrs(), sym::omit_gdb_pretty_printer_section);
+ attr::contains_name(cx.tcx.hir_krate_attrs(), sym::omit_gdb_pretty_printer_section);
// To ensure the section `__rustc_debug_gdb_scripts_section__` will not create
// ODR violations at link time, this section will not be emitted for rlibs since
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 59c3fe635d07..98d59f5a8ae0 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -11,7 +11,9 @@ use rustc_codegen_ssa::traits::*;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
-use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{
+ HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA,
+};
use rustc_middle::ty::{
self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
};
@@ -34,12 +36,12 @@ use crate::common::{AsCCharPtr, CodegenCx};
use crate::debuginfo::dwarf_const;
use crate::debuginfo::metadata::type_map::build_type_with_children;
use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind};
+use crate::llvm;
use crate::llvm::debuginfo::{
DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
DebugNameTableKind,
};
use crate::value::Value;
-use crate::{abi, llvm};
impl PartialEq for llvm::Metadata {
fn eq(&self, other: &Self) -> bool {
@@ -211,16 +213,16 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
};
let layout = cx.layout_of(layout_type);
- let addr_field = layout.field(cx, abi::WIDE_PTR_ADDR);
- let extra_field = layout.field(cx, abi::WIDE_PTR_EXTRA);
+ let addr_field = layout.field(cx, WIDE_PTR_ADDR);
+ let extra_field = layout.field(cx, WIDE_PTR_EXTRA);
let (addr_field_name, extra_field_name) = match wide_pointer_kind {
WidePtrKind::Dyn => ("pointer", "vtable"),
WidePtrKind::Slice => ("data_ptr", "length"),
};
- assert_eq!(abi::WIDE_PTR_ADDR, 0);
- assert_eq!(abi::WIDE_PTR_EXTRA, 1);
+ assert_eq!(WIDE_PTR_ADDR, 0);
+ assert_eq!(WIDE_PTR_EXTRA, 1);
// The data pointer type is a regular, thin pointer, regardless of whether this
// is a slice or a trait object.
@@ -242,7 +244,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
owner,
addr_field_name,
(addr_field.size, addr_field.align.abi),
- layout.fields.offset(abi::WIDE_PTR_ADDR),
+ layout.fields.offset(WIDE_PTR_ADDR),
DIFlags::FlagZero,
data_ptr_type_di_node,
None,
@@ -252,7 +254,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
owner,
extra_field_name,
(extra_field.size, extra_field.align.abi),
- layout.fields.offset(abi::WIDE_PTR_EXTRA),
+ layout.fields.offset(WIDE_PTR_EXTRA),
DIFlags::FlagZero,
type_di_node(cx, extra_field.ty),
None,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 17f2d5f4e731..10819a53b1df 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -22,6 +22,7 @@ use rustc_session::config::{self, DebugInfo};
use rustc_span::{
BytePos, Pos, SourceFile, SourceFileAndLine, SourceFileHash, Span, StableSourceFileId, Symbol,
};
+use rustc_target::callconv::FnAbi;
use rustc_target::spec::DebuginfoKind;
use smallvec::SmallVec;
use tracing::debug;
@@ -29,7 +30,6 @@ use tracing::debug;
use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, type_di_node};
use self::namespace::mangled_name_of_instance;
use self::utils::{DIB, create_DIArray, is_node_local_to_unit};
-use crate::abi::FnAbi;
use crate::builder::Builder;
use crate::common::{AsCCharPtr, CodegenCx};
use crate::llvm;
diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs
index cebceef1b93f..e79662ebc647 100644
--- a/compiler/rustc_codegen_llvm/src/declare.rs
+++ b/compiler/rustc_codegen_llvm/src/declare.rs
@@ -16,10 +16,11 @@ use rustc_codegen_ssa::traits::TypeMembershipCodegenMethods;
use rustc_data_structures::fx::FxIndexSet;
use rustc_middle::ty::{Instance, Ty};
use rustc_sanitizers::{cfi, kcfi};
+use rustc_target::callconv::FnAbi;
use smallvec::SmallVec;
use tracing::debug;
-use crate::abi::{FnAbi, FnAbiLlvmExt};
+use crate::abi::FnAbiLlvmExt;
use crate::common::AsCCharPtr;
use crate::context::{CodegenCx, SimpleCx};
use crate::llvm::AttributePlace::Function;
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 8b9768859045..7e1a9d361e6f 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -1,7 +1,7 @@
use std::assert_matches::assert_matches;
use std::cmp::Ordering;
-use rustc_abi::{self as abi, Align, Float, HasDataLayout, Primitive, Size};
+use rustc_abi::{Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size};
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization};
@@ -14,10 +14,11 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, GenericArgsRef, Ty};
use rustc_middle::{bug, span_bug};
use rustc_span::{Span, Symbol, sym};
+use rustc_target::callconv::{FnAbi, PassMode};
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
use tracing::debug;
-use crate::abi::{ExternAbi, FnAbi, FnAbiLlvmExt, LlvmType, PassMode};
+use crate::abi::{FnAbiLlvmExt, LlvmType};
use crate::builder::Builder;
use crate::context::CodegenCx;
use crate::llvm::{self, Metadata};
@@ -257,7 +258,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
}
sym::va_arg => {
match fn_abi.ret.layout.backend_repr {
- abi::BackendRepr::Scalar(scalar) => {
+ BackendRepr::Scalar(scalar) => {
match scalar.primitive() {
Primitive::Int(..) => {
if self.cx().size_of(ret_ty).bytes() < 4 {
@@ -470,7 +471,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
}
sym::raw_eq => {
- use abi::BackendRepr::*;
+ use BackendRepr::*;
let tp_ty = fn_args.type_at(0);
let layout = self.layout_of(tp_ty).layout;
let use_integer_compare = match layout.backend_repr() {
@@ -582,8 +583,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
}
let llret_ty = if ret_ty.is_simd()
- && let abi::BackendRepr::Memory { .. } =
- self.layout_of(ret_ty).layout.backend_repr
+ && let BackendRepr::Memory { .. } = self.layout_of(ret_ty).layout.backend_repr
{
let (size, elem_ty) = ret_ty.simd_size_and_type(self.tcx());
let elem_ll_ty = match elem_ty.kind() {
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 2afc1efc1b34..963d9258be67 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -25,6 +25,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_fs_util = { path = "../rustc_fs_util" }
+rustc_hashes = { path = "../rustc_hashes" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_incremental = { path = "../rustc_incremental" }
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 53953b089c61..84703a0a1569 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -15,7 +15,8 @@ use std::fmt::Write;
use rustc_abi::Integer;
use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hashes::Hash64;
use rustc_hir::def_id::DefId;
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Mutability};
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index eb4270ffe809..e32d298869be 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -1,7 +1,7 @@
use rustc_abi::Primitive::{Int, Pointer};
use rustc_abi::{Align, BackendRepr, FieldsShape, Size, TagEncoding, VariantIdx, Variants};
+use rustc_middle::mir::PlaceTy;
use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Ty};
use rustc_middle::{bug, mir};
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index 6749bc63327e..5f95b6615bd3 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -35,7 +35,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
cx.codegen_static(def_id);
}
MonoItem::GlobalAsm(item_id) => {
- let item = cx.tcx().hir().item(item_id);
+ let item = cx.tcx().hir_item(item_id);
if let hir::ItemKind::GlobalAsm(asm) = item.kind {
let operands: Vec<_> = asm
.operands
diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs
index bfa0a0319c34..52e000858b4c 100644
--- a/compiler/rustc_const_eval/src/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/check_consts/mod.rs
@@ -31,7 +31,7 @@ pub struct ConstCx<'mir, 'tcx> {
impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Self {
let typing_env = body.typing_env(tcx);
- let const_kind = tcx.hir().body_const_context(body.source.def_id().expect_local());
+ let const_kind = tcx.hir_body_const_context(body.source.def_id().expect_local());
ConstCx { body, tcx, typing_env, const_kind }
}
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index a8f83ca13e26..1705af1e210a 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -18,6 +18,7 @@ rustc-rayon = { version = "0.5.1", features = ["indexmap"] }
rustc-stable-hash = { version = "0.1.0", features = ["nightly"] }
rustc_arena = { path = "../rustc_arena" }
rustc_graphviz = { path = "../rustc_graphviz" }
+rustc_hashes = { path = "../rustc_hashes" }
rustc_index = { path = "../rustc_index", package = "rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index 16c66824c5ba..c7c0d0ab0725 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -1,10 +1,9 @@
use std::hash::{Hash, Hasher};
+use rustc_hashes::Hash64;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use crate::stable_hasher::{
- FromStableHash, Hash64, StableHasherHash, impl_stable_traits_for_trivial_type,
-};
+use crate::stable_hasher::{FromStableHash, StableHasherHash, impl_stable_traits_for_trivial_type};
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs
index 850b052f564b..8079212fac55 100644
--- a/compiler/rustc_data_structures/src/intern.rs
+++ b/compiler/rustc_data_structures/src/intern.rs
@@ -92,7 +92,10 @@ impl<'a, T: Ord> Ord for Interned<'a, T> {
}
}
-impl<'a, T> Hash for Interned<'a, T> {
+impl<'a, T> Hash for Interned<'a, T>
+where
+ T: Hash,
+{
#[inline]
fn hash(&self, s: &mut H) {
// Pointer hashing is sufficient, due to the uniqueness constraint.
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 6ef73debadd5..66d3834d8578 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -84,7 +84,6 @@ pub mod vec_cache;
pub mod work_queue;
mod atomic_ref;
-mod hashes;
/// This calls the passed function while ensuring it won't be inlined into the caller.
#[inline(never)]
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index 9cd0cc499ca3..ffbe54d62061 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -10,12 +10,11 @@ use smallvec::SmallVec;
#[cfg(test)]
mod tests;
+use rustc_hashes::{Hash64, Hash128};
pub use rustc_stable_hash::{
FromStableHash, SipHasher128Hash as StableHasherHash, StableSipHasher128 as StableHasher,
};
-pub use crate::hashes::{Hash64, Hash128};
-
/// Something that implements `HashStable` can be hashed in a way that is
/// stable across multiple compilation sessions.
///
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/tests.rs
index b1bdee18d6d4..9c1e4cefa692 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/tests.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/tests.rs
@@ -1,7 +1,8 @@
use std::ptr;
+use rustc_hashes::Hash128;
+
use super::*;
-use crate::hashes::Hash128;
use crate::stable_hasher::{HashStable, StableHasher};
/// A tag type used in [`TaggedRef`] tests.
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 576b1c76823f..828a14e707c5 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -164,8 +164,7 @@ impl<'tcx> pprust_hir::PpAnn for HirTypedAnn<'tcx> {
if let pprust_hir::AnnNode::Expr(expr) = node {
let typeck_results = self.maybe_typeck_results.get().or_else(|| {
self.tcx
- .hir()
- .maybe_body_owned_by(expr.hir_id.owner.def_id)
+ .hir_maybe_body_owned_by(expr.hir_id.owner.def_id)
.map(|body_id| self.tcx.typeck_body(body_id.id()))
});
@@ -273,7 +272,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
let attrs = |id| hir_map.attrs(id);
pprust_hir::print_crate(
sm,
- hir_map.root_module(),
+ tcx.hir_root_module(),
src_name,
src,
&attrs,
@@ -294,7 +293,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
}
HirTree => {
debug!("pretty printing HIR tree");
- format!("{:#?}", ex.tcx().hir().krate())
+ format!("{:#?}", ex.tcx().hir_crate(()))
}
Mir => {
let mut out = Vec::new();
@@ -317,7 +316,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
rustc_hir_analysis::check_crate(tcx);
tcx.dcx().abort_if_errors();
debug!("pretty printing THIR tree");
- for did in tcx.hir().body_owners() {
+ for did in tcx.hir_body_owners() {
let _ = writeln!(out, "{:?}:\n{}\n", did, thir_tree(tcx, did));
}
out
@@ -328,7 +327,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
rustc_hir_analysis::check_crate(tcx);
tcx.dcx().abort_if_errors();
debug!("pretty printing THIR flat");
- for did in tcx.hir().body_owners() {
+ for did in tcx.hir_body_owners() {
let _ = writeln!(out, "{:?}:\n{}\n", did, thir_flat(tcx, did));
}
out
diff --git a/compiler/rustc_driver_impl/src/signal_handler.rs b/compiler/rustc_driver_impl/src/signal_handler.rs
index 08b7d937661f..e7bc57c9749b 100644
--- a/compiler/rustc_driver_impl/src/signal_handler.rs
+++ b/compiler/rustc_driver_impl/src/signal_handler.rs
@@ -6,6 +6,15 @@ use std::{fmt, mem, ptr, slice};
use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE};
+/// Signals that represent that we have a bug, and our prompt termination has
+/// been ordered.
+#[rustfmt::skip]
+const KILL_SIGNALS: [(libc::c_int, &str); 3] = [
+ (libc::SIGILL, "SIGILL"),
+ (libc::SIGBUS, "SIGBUS"),
+ (libc::SIGSEGV, "SIGSEGV")
+];
+
unsafe extern "C" {
fn backtrace_symbols_fd(buffer: *const *mut libc::c_void, size: libc::c_int, fd: libc::c_int);
}
@@ -39,8 +48,19 @@ macro raw_errln($tokens:tt) {
/// # Safety
///
/// Caller must ensure that this function is not re-entered.
-unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
+unsafe extern "C" fn print_stack_trace(signum: libc::c_int) {
const MAX_FRAMES: usize = 256;
+
+ let signame = {
+ let mut signame = "";
+ for sig in KILL_SIGNALS {
+ if sig.0 == signum {
+ signame = sig.1;
+ }
+ }
+ signame
+ };
+
let stack = unsafe {
// Reserve data segment so we don't have to malloc in a signal handler, which might fail
// in incredibly undesirable and unexpected ways due to e.g. the allocator deadlocking
@@ -54,7 +74,8 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
};
// Just a stack trace is cryptic. Explain what we're doing.
- raw_errln!("error: rustc interrupted by SIGSEGV, printing backtrace\n");
+ raw_errln!("error: rustc interrupted by {signame}, printing backtrace\n");
+
let mut written = 1;
let mut consumed = 0;
// Begin elaborating return addrs into symbols and writing them directly to stderr
@@ -94,7 +115,7 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
written += rem.len() + 1;
let random_depth = || 8 * 16; // chosen by random diceroll (2d20)
- if cyclic || stack.len() > random_depth() {
+ if (cyclic || stack.len() > random_depth()) && signum == libc::SIGSEGV {
// technically speculation, but assert it with confidence anyway.
// rustc only arrived in this signal handler because bad things happened
// and this message is for explaining it's not the programmer's fault
@@ -106,17 +127,22 @@ unsafe extern "C" fn print_stack_trace(_: libc::c_int) {
written += 1;
}
raw_errln!("note: we would appreciate a report at https://github.com/rust-lang/rust");
- // get the current stack size WITHOUT blocking and double it
- let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2;
- raw_errln!("help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}");
- written += 2;
+ written += 1;
+ if signum == libc::SIGSEGV {
+ // get the current stack size WITHOUT blocking and double it
+ let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2;
+ raw_errln!(
+ "help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}"
+ );
+ written += 1;
+ }
if written > 24 {
- // We probably just scrolled the earlier "we got SIGSEGV" message off the terminal
- raw_errln!("note: backtrace dumped due to SIGSEGV! resuming signal");
+ // We probably just scrolled the earlier "interrupted by {signame}" message off the terminal
+ raw_errln!("note: backtrace dumped due to {signame}! resuming signal");
};
}
-/// When SIGSEGV is delivered to the process, print a stack trace and then exit.
+/// When one of the KILL signals is delivered to the process, print a stack trace and then exit.
pub(super) fn install() {
unsafe {
let alt_stack_size: usize = min_sigstack_size() + 64 * 1024;
@@ -129,7 +155,9 @@ pub(super) fn install() {
sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
libc::sigemptyset(&mut sa.sa_mask);
- libc::sigaction(libc::SIGSEGV, &sa, ptr::null_mut());
+ for (signum, _signame) in KILL_SIGNALS {
+ libc::sigaction(signum, &sa, ptr::null_mut());
+ }
}
}
diff --git a/compiler/rustc_error_codes/src/error_codes/E0803.md b/compiler/rustc_error_codes/src/error_codes/E0803.md
new file mode 100644
index 000000000000..4c022688a2de
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0803.md
@@ -0,0 +1,46 @@
+A trait implementation returns a reference without an
+explicit lifetime linking it to `self`.
+It commonly arises in generic trait implementations
+requiring explicit lifetime bounds.
+
+Erroneous code example:
+
+```compile_fail,E0803
+trait DataAccess {
+ fn get_ref(&self) -> T;
+}
+
+struct Container<'a> {
+ value: &'a f64,
+}
+
+// Attempting to implement reference return
+impl<'a> DataAccess<&f64> for Container<'a> {
+ fn get_ref(&self) -> &f64 { // Error: Lifetime mismatch
+ self.value
+ }
+}
+```
+
+The trait method returns &f64 requiring an independent lifetime
+The struct Container<'a> carries lifetime parameter 'a
+The compiler cannot verify if the returned reference satisfies 'a constraints
+Solution
+Explicitly bind lifetimes to clarify constraints:
+```
+// Modified trait with explicit lifetime binding
+trait DataAccess<'a, T> {
+ fn get_ref(&'a self) -> T;
+}
+
+struct Container<'a> {
+ value: &'a f64,
+}
+
+// Correct implementation (bound lifetimes)
+impl<'a> DataAccess<'a, &'a f64> for Container<'a> {
+ fn get_ref(&'a self) -> &'a f64 {
+ self.value
+ }
+}
+```
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index e970b16f6106..098ca42be2b4 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -546,6 +546,7 @@ E0799: 0799,
E0800: 0800,
E0801: 0801,
E0802: 0802,
+E0803: 0803,
);
)
}
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index fbb6a1cc4755..434f8c1c7675 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -14,6 +14,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_error_codes = { path = "../rustc_error_codes" }
rustc_error_messages = { path = "../rustc_error_messages" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_hashes = { path = "../rustc_hashes" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_lexer = { path = "../rustc_lexer" }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 8ff5dc125969..6fce1fade266 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -58,12 +58,13 @@ pub use emitter::ColorConfig;
use emitter::{DynEmitter, Emitter, is_case_difference, is_different};
use rustc_data_structures::AtomicRef;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
+use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::{DynSend, Lock};
pub use rustc_error_messages::{
DiagMessage, FluentBundle, LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel,
SubdiagMessage, fallback_fluent_bundle, fluent_bundle,
};
+use rustc_hashes::Hash128;
use rustc_lint_defs::LintExpectationId;
pub use rustc_lint_defs::{Applicability, listify, pluralize};
use rustc_macros::{Decodable, Encodable};
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 595c8c3279f4..721798b0ce46 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -1,10 +1,13 @@
use std::mem;
use std::sync::Arc;
-use rustc_ast::ExprKind;
use rustc_ast::mut_visit::{self, MutVisitor};
-use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, LitKind, Nonterminal, Token, TokenKind};
+use rustc_ast::token::{
+ self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Nonterminal, Token,
+ TokenKind,
+};
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
+use rustc_ast::{ExprKind, TyKind};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize};
use rustc_parse::lexer::nfc_normalize;
@@ -274,6 +277,33 @@ pub(super) fn transcribe<'a>(
// some of the unnecessary whitespace.
let ident = MacroRulesNormalizedIdent::new(original_ident);
if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
+ // We wrap the tokens in invisible delimiters, unless they are already wrapped
+ // in invisible delimiters with the same `MetaVarKind`. Because some proc
+ // macros can't multiple layers of invisible delimiters of the same
+ // `MetaVarKind`. This loses some span info, though it hopefully won't matter.
+ let mut mk_delimited = |mv_kind, mut stream: TokenStream| {
+ if stream.len() == 1 {
+ let tree = stream.iter().next().unwrap();
+ if let TokenTree::Delimited(_, _, delim, inner) = tree
+ && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mvk)) = delim
+ && mv_kind == *mvk
+ {
+ stream = inner.clone();
+ }
+ }
+
+ // Emit as a token stream within `Delimiter::Invisible` to maintain
+ // parsing priorities.
+ marker.visit_span(&mut sp);
+ // Both the open delim and close delim get the same span, which covers the
+ // `$foo` in the decl macro RHS.
+ TokenTree::Delimited(
+ DelimSpan::from_single(sp),
+ DelimSpacing::new(Spacing::Alone, Spacing::Alone),
+ Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)),
+ stream,
+ )
+ };
let tt = match cur_matched {
MatchedSingle(ParseNtResult::Tt(tt)) => {
// `tt`s are emitted into the output stream directly as "raw tokens",
@@ -292,6 +322,13 @@ pub(super) fn transcribe<'a>(
let kind = token::NtLifetime(*ident, *is_raw);
TokenTree::token_alone(kind, sp)
}
+ MatchedSingle(ParseNtResult::Ty(ty)) => {
+ let is_path = matches!(&ty.kind, TyKind::Path(None, _path));
+ mk_delimited(MetaVarKind::Ty { is_path }, TokenStream::from_ast(ty))
+ }
+ MatchedSingle(ParseNtResult::Vis(vis)) => {
+ mk_delimited(MetaVarKind::Vis, TokenStream::from_ast(vis))
+ }
MatchedSingle(ParseNtResult::Nt(nt)) => {
// Other variables are emitted into the output stream as groups with
// `Delimiter::Invisible` to maintain parsing priorities.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index eb5fac96af27..8eb9bf158290 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -1149,7 +1149,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
"the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite",
),
rustc_attr!(
- TEST, pattern_complexity, CrateLevel, template!(NameValueStr: "N"),
+ TEST, pattern_complexity_limit, CrateLevel, template!(NameValueStr: "N"),
ErrorFollowing, EncodeCrossCrate::No,
),
];
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index a638a845c07e..e852f239aa27 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -227,7 +227,7 @@ declare_features! (
/// Allows using `#[omit_gdb_pretty_printer_section]`.
(internal, omit_gdb_pretty_printer_section, "1.5.0", None),
/// Set the maximum pattern complexity allowed (not limited by default).
- (internal, pattern_complexity, "1.78.0", None),
+ (internal, pattern_complexity_limit, "1.78.0", None),
/// Allows using pattern types.
(internal, pattern_types, "1.79.0", Some(123646)),
/// Allows using `#[prelude_import]` on glob `use` items.
diff --git a/compiler/rustc_hashes/Cargo.toml b/compiler/rustc_hashes/Cargo.toml
new file mode 100644
index 000000000000..c2bae2fe8cb0
--- /dev/null
+++ b/compiler/rustc_hashes/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "rustc_hashes"
+version = "0.0.0"
+edition = "2021"
+
+[dependencies]
+# tidy-alphabetical-start
+rustc-stable-hash = { version = "0.1.0" }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_hashes/src/lib.rs
similarity index 79%
rename from compiler/rustc_data_structures/src/hashes.rs
rename to compiler/rustc_hashes/src/lib.rs
index 8f4639fc2e66..3755caaaa296 100644
--- a/compiler/rustc_data_structures/src/hashes.rs
+++ b/compiler/rustc_hashes/src/lib.rs
@@ -1,6 +1,8 @@
//! rustc encodes a lot of hashes. If hashes are stored as `u64` or `u128`, a `derive(Encodable)`
//! will apply varint encoding to the hashes, which is less efficient than directly encoding the 8
-//! or 16 bytes of the hash.
+//! or 16 bytes of the hash. And if that hash depends on the `StableCrateHash` (which most in rustc
+//! do), the varint encoding will make the number of bytes encoded fluctuate between compiler
+//! versions.
//!
//! The types in this module represent 64-bit or 128-bit hashes produced by a `StableHasher`.
//! `Hash64` and `Hash128` expose some utility functions to encourage users to not extract the inner
@@ -14,10 +16,9 @@
use std::fmt;
use std::ops::BitXorAssign;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-
-use crate::stable_hasher::{FromStableHash, StableHasherHash};
+use rustc_stable_hash::{FromStableHash, SipHasher128Hash as StableHasherHash};
+/// A `u64` but encoded with a fixed size; for hashes this encoding is more compact than `u64`.
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
pub struct Hash64 {
inner: u64,
@@ -35,6 +36,11 @@ impl Hash64 {
pub fn as_u64(self) -> u64 {
self.inner
}
+
+ #[inline]
+ pub fn wrapping_add(self, other: Self) -> Self {
+ Self { inner: self.inner.wrapping_add(other.inner) }
+ }
}
impl BitXorAssign for Hash64 {
@@ -44,20 +50,6 @@ impl BitXorAssign for Hash64 {
}
}
-impl Encodable for Hash64 {
- #[inline]
- fn encode(&self, s: &mut S) {
- s.emit_raw_bytes(&self.inner.to_le_bytes());
- }
-}
-
-impl Decodable for Hash64 {
- #[inline]
- fn decode(d: &mut D) -> Self {
- Self { inner: u64::from_le_bytes(d.read_raw_bytes(8).try_into().unwrap()) }
- }
-}
-
impl FromStableHash for Hash64 {
type Hash = StableHasherHash;
@@ -79,6 +71,7 @@ impl fmt::LowerHex for Hash64 {
}
}
+/// A `u128` but encoded with a fixed size; for hashes this encoding is more compact than `u128`.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct Hash128 {
inner: u128,
@@ -95,6 +88,11 @@ impl std::hash::Hash for Hash128 {
}
impl Hash128 {
+ #[inline]
+ pub fn new(n: u128) -> Self {
+ Self { inner: n }
+ }
+
#[inline]
pub fn truncate(self) -> Hash64 {
Hash64 { inner: self.inner as u64 }
@@ -111,20 +109,6 @@ impl Hash128 {
}
}
-impl Encodable for Hash128 {
- #[inline]
- fn encode(&self, s: &mut S) {
- s.emit_raw_bytes(&self.inner.to_le_bytes());
- }
-}
-
-impl Decodable for Hash128 {
- #[inline]
- fn decode(d: &mut D) -> Self {
- Self { inner: u128::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap()) }
- }
-}
-
impl FromStableHash for Hash128 {
type Hash = StableHasherHash;
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml
index 5bfc4756ec6a..b1516e53173b 100644
--- a/compiler/rustc_hir/Cargo.toml
+++ b/compiler/rustc_hir/Cargo.toml
@@ -10,6 +10,7 @@ rustc_abi = { path = "../rustc_abi" }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_hashes = { path = "../rustc_hashes" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_hir/src/def_path_hash_map.rs b/compiler/rustc_hir/src/def_path_hash_map.rs
index 9a6dee1e511d..35c6e57b8770 100644
--- a/compiler/rustc_hir/src/def_path_hash_map.rs
+++ b/compiler/rustc_hir/src/def_path_hash_map.rs
@@ -1,4 +1,4 @@
-use rustc_data_structures::stable_hasher::Hash64;
+use rustc_hashes::Hash64;
use rustc_span::def_id::DefIndex;
#[derive(Clone, Default)]
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index dc527240f742..08a0a5225e74 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -7,8 +7,9 @@
use std::fmt::{self, Write};
use std::hash::Hash;
-use rustc_data_structures::stable_hasher::{Hash64, StableHasher};
+use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::unord::UnordMap;
+use rustc_hashes::Hash64;
use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable};
use rustc_span::{Symbol, kw, sym};
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index f632041dba9f..bd96fe9ee32c 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -18,8 +18,8 @@
//! within one another.
//! - Example: Examine each expression to look for its type and do some check or other.
//! - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to
-//! `nested_filter::OnlyBodies` (and implement `nested_visit_map`), and use
-//! `tcx.hir().visit_all_item_likes_in_crate(&mut visitor)`. Within your
+//! `nested_filter::OnlyBodies` (and implement `maybe_tcx`), and use
+//! `tcx.hir_visit_all_item_likes_in_crate(&mut visitor)`. Within your
//! `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget to invoke
//! `intravisit::walk_expr()` to keep walking the subparts).
//! - Pro: Visitor methods for any kind of HIR node, not just item-like things.
@@ -30,8 +30,8 @@
//! - Example: Lifetime resolution, which wants to bring lifetimes declared on the
//! impl into scope while visiting the impl-items, and then back out again.
//! - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to
-//! `nested_filter::All` (and implement `nested_visit_map`). Walk your crate with
-//! `tcx.hir().walk_toplevel_module(visitor)` invoked on `tcx.hir().krate()`.
+//! `nested_filter::All` (and implement `maybe_tcx`). Walk your crate with
+//! `tcx.hir_walk_toplevel_module(visitor)`.
//! - Pro: Visitor methods for any kind of HIR node, not just item-like things.
//! - Pro: Preserves nesting information
//! - Con: Does not integrate well into dependency tracking.
@@ -106,45 +106,43 @@ impl<'a> FnKind<'a> {
}
}
-/// An abstract representation of the HIR `rustc_middle::hir::map::Map`.
-pub trait Map<'hir> {
+/// HIR things retrievable from `TyCtxt`, avoiding an explicit dependence on
+/// `TyCtxt`. The only impls are for `!` (where these functions are never
+/// called) and `TyCtxt` (in `rustc_middle`).
+pub trait HirTyCtxt<'hir> {
/// Retrieves the `Node` corresponding to `id`.
fn hir_node(&self, hir_id: HirId) -> Node<'hir>;
- fn hir_node_by_def_id(&self, def_id: LocalDefId) -> Node<'hir>;
- fn body(&self, id: BodyId) -> &'hir Body<'hir>;
- fn item(&self, id: ItemId) -> &'hir Item<'hir>;
- fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
- fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
- fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
+ fn hir_body(&self, id: BodyId) -> &'hir Body<'hir>;
+ fn hir_item(&self, id: ItemId) -> &'hir Item<'hir>;
+ fn hir_trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
+ fn hir_impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
+ fn hir_foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
}
-// Used when no map is actually available, forcing manual implementation of nested visitors.
-impl<'hir> Map<'hir> for ! {
+// Used when no tcx is actually available, forcing manual implementation of nested visitors.
+impl<'hir> HirTyCtxt<'hir> for ! {
fn hir_node(&self, _: HirId) -> Node<'hir> {
- *self;
+ unreachable!();
}
- fn hir_node_by_def_id(&self, _: LocalDefId) -> Node<'hir> {
- *self;
+ fn hir_body(&self, _: BodyId) -> &'hir Body<'hir> {
+ unreachable!();
}
- fn body(&self, _: BodyId) -> &'hir Body<'hir> {
- *self;
+ fn hir_item(&self, _: ItemId) -> &'hir Item<'hir> {
+ unreachable!();
}
- fn item(&self, _: ItemId) -> &'hir Item<'hir> {
- *self;
+ fn hir_trait_item(&self, _: TraitItemId) -> &'hir TraitItem<'hir> {
+ unreachable!();
}
- fn trait_item(&self, _: TraitItemId) -> &'hir TraitItem<'hir> {
- *self;
+ fn hir_impl_item(&self, _: ImplItemId) -> &'hir ImplItem<'hir> {
+ unreachable!();
}
- fn impl_item(&self, _: ImplItemId) -> &'hir ImplItem<'hir> {
- *self;
- }
- fn foreign_item(&self, _: ForeignItemId) -> &'hir ForeignItem<'hir> {
- *self;
+ fn hir_foreign_item(&self, _: ForeignItemId) -> &'hir ForeignItem<'hir> {
+ unreachable!();
}
}
pub mod nested_filter {
- use super::Map;
+ use super::HirTyCtxt;
/// Specifies what nested things a visitor wants to visit. By "nested
/// things", we are referring to bits of HIR that are not directly embedded
@@ -159,7 +157,7 @@ pub mod nested_filter {
/// See the comments at [`rustc_hir::intravisit`] for more details on the overall
/// visit strategy.
pub trait NestedFilter<'hir> {
- type Map: Map<'hir>;
+ type MaybeTyCtxt: HirTyCtxt<'hir>;
/// Whether the visitor visits nested "item-like" things.
/// E.g., item, impl-item.
@@ -175,10 +173,10 @@ pub mod nested_filter {
///
/// Use this if you are only walking some particular kind of tree
/// (i.e., a type, or fn signature) and you don't want to thread a
- /// HIR map around.
+ /// `tcx` around.
pub struct None(());
impl NestedFilter<'_> for None {
- type Map = !;
+ type MaybeTyCtxt = !;
const INTER: bool = false;
const INTRA: bool = false;
}
@@ -195,7 +193,7 @@ use nested_filter::NestedFilter;
/// (this is why the module is called `intravisit`, to distinguish it
/// from the AST's `visit` module, which acts differently). If you
/// simply want to visit all items in the crate in some order, you
-/// should call `tcx.hir().visit_all_item_likes_in_crate`. Otherwise, see the comment
+/// should call `tcx.hir_visit_all_item_likes_in_crate`. Otherwise, see the comment
/// on `visit_nested_item` for details on how to visit nested items.
///
/// If you want to ensure that your code handles every variant
@@ -203,18 +201,18 @@ use nested_filter::NestedFilter;
/// to monitor future changes to `Visitor` in case a new method with a
/// new default implementation gets introduced.)
pub trait Visitor<'v>: Sized {
- // this type should not be overridden, it exists for convenient usage as `Self::Map`
- type Map: Map<'v> = >::Map;
+ // This type should not be overridden, it exists for convenient usage as `Self::MaybeTyCtxt`.
+ type MaybeTyCtxt: HirTyCtxt<'v> = >::MaybeTyCtxt;
///////////////////////////////////////////////////////////////////////////
// Nested items.
/// Override this type to control which nested HIR are visited; see
/// [`NestedFilter`] for details. If you override this type, you
- /// must also override [`nested_visit_map`](Self::nested_visit_map).
+ /// must also override [`maybe_tcx`](Self::maybe_tcx).
///
/// **If for some reason you want the nested behavior, but don't
- /// have a `Map` at your disposal:** then override the
+ /// have a `tcx` at your disposal:** then override the
/// `visit_nested_XXX` methods. If a new `visit_nested_XXX` variant is
/// added in the future, it will cause a panic which can be detected
/// and fixed appropriately.
@@ -226,9 +224,9 @@ pub trait Visitor<'v>: Sized {
/// If `type NestedFilter` is set to visit nested items, this method
/// must also be overridden to provide a map to retrieve nested items.
- fn nested_visit_map(&mut self) -> Self::Map {
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
panic!(
- "nested_visit_map must be implemented or consider using \
+ "maybe_tcx must be implemented or consider using \
`type NestedFilter = nested_filter::None` (the default)"
);
}
@@ -240,10 +238,10 @@ pub trait Visitor<'v>: Sized {
/// "deep" visit patterns described at
/// [`rustc_hir::intravisit`]. The only reason to override
/// this method is if you want a nested pattern but cannot supply a
- /// [`Map`]; see `nested_visit_map` for advice.
+ /// `TyCtxt`; see `maybe_tcx` for advice.
fn visit_nested_item(&mut self, id: ItemId) -> Self::Result {
if Self::NestedFilter::INTER {
- let item = self.nested_visit_map().item(id);
+ let item = self.maybe_tcx().hir_item(id);
try_visit!(self.visit_item(item));
}
Self::Result::output()
@@ -254,7 +252,7 @@ pub trait Visitor<'v>: Sized {
/// method.
fn visit_nested_trait_item(&mut self, id: TraitItemId) -> Self::Result {
if Self::NestedFilter::INTER {
- let item = self.nested_visit_map().trait_item(id);
+ let item = self.maybe_tcx().hir_trait_item(id);
try_visit!(self.visit_trait_item(item));
}
Self::Result::output()
@@ -265,7 +263,7 @@ pub trait Visitor<'v>: Sized {
/// method.
fn visit_nested_impl_item(&mut self, id: ImplItemId) -> Self::Result {
if Self::NestedFilter::INTER {
- let item = self.nested_visit_map().impl_item(id);
+ let item = self.maybe_tcx().hir_impl_item(id);
try_visit!(self.visit_impl_item(item));
}
Self::Result::output()
@@ -276,7 +274,7 @@ pub trait Visitor<'v>: Sized {
/// method.
fn visit_nested_foreign_item(&mut self, id: ForeignItemId) -> Self::Result {
if Self::NestedFilter::INTER {
- let item = self.nested_visit_map().foreign_item(id);
+ let item = self.maybe_tcx().hir_foreign_item(id);
try_visit!(self.visit_foreign_item(item));
}
Self::Result::output()
@@ -287,7 +285,7 @@ pub trait Visitor<'v>: Sized {
/// `Self::NestedFilter`.
fn visit_nested_body(&mut self, id: BodyId) -> Self::Result {
if Self::NestedFilter::INTRA {
- let body = self.nested_visit_map().body(id);
+ let body = self.maybe_tcx().hir_body(id);
try_visit!(self.visit_body(body));
}
Self::Result::output()
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index e0e63d183c63..0837444ffdbe 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -1,6 +1,6 @@
#![allow(rustc::symbol_intern_string_literal)]
-use rustc_data_structures::stable_hasher::Hash64;
+use rustc_hashes::Hash64;
use rustc_span::def_id::{DefPathHash, StableCrateId};
use rustc_span::edition::Edition;
use rustc_span::{Symbol, create_session_globals_then};
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 5560d087e96f..47d5976be09e 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -387,6 +387,8 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation
hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
+hir_analysis_no_variant_named = no variant named `{$ident}` found for enum `{$ty}`
+
hir_analysis_not_supported_delegation = {$descr}
.label = callee defined here
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
deleted file mode 100644
index 9b02651a8bdf..000000000000
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-//! Bounds are restrictions applied to some types after they've been lowered from the HIR to the
-//! [`rustc_middle::ty`] form.
-
-use rustc_hir::LangItem;
-use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
-use rustc_span::Span;
-
-/// Collects together a list of type bounds. These lists of bounds occur in many places
-/// in Rust's syntax:
-///
-/// ```text
-/// trait Foo: Bar + Baz { }
-/// ^^^^^^^^^ supertrait list bounding the `Self` type parameter
-///
-/// fn foo() { }
-/// ^^^^^^^^^ bounding the type parameter `T`
-///
-/// impl dyn Bar + Baz
-/// ^^^^^^^^^ bounding the type-erased dynamic type
-/// ```
-///
-/// Our representation is a bit mixed here -- in some cases, we
-/// include the self type (e.g., `trait_bounds`) but in others we do not
-#[derive(Default, PartialEq, Eq, Clone, Debug)]
-pub(crate) struct Bounds<'tcx> {
- clauses: Vec<(ty::Clause<'tcx>, Span)>,
-}
-
-impl<'tcx> Bounds<'tcx> {
- pub(crate) fn push_region_bound(
- &mut self,
- tcx: TyCtxt<'tcx>,
- region: ty::PolyTypeOutlivesPredicate<'tcx>,
- span: Span,
- ) {
- self.clauses
- .push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).upcast(tcx), span));
- }
-
- pub(crate) fn push_trait_bound(
- &mut self,
- tcx: TyCtxt<'tcx>,
- bound_trait_ref: ty::PolyTraitRef<'tcx>,
- span: Span,
- polarity: ty::PredicatePolarity,
- ) {
- let clause = (
- bound_trait_ref
- .map_bound(|trait_ref| {
- ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
- })
- .upcast(tcx),
- span,
- );
- // FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
- if tcx.is_lang_item(bound_trait_ref.def_id(), LangItem::Sized) {
- self.clauses.insert(0, clause);
- } else {
- self.clauses.push(clause);
- }
- }
-
- pub(crate) fn push_projection_bound(
- &mut self,
- tcx: TyCtxt<'tcx>,
- projection: ty::PolyProjectionPredicate<'tcx>,
- span: Span,
- ) {
- self.clauses.push((
- projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).upcast(tcx),
- span,
- ));
- }
-
- pub(crate) fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
- let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
- let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
- // Preferable to put this obligation first, since we report better errors for sized ambiguity.
- self.clauses.insert(0, (trait_ref.upcast(tcx), span));
- }
-
- /// Push a `const` or `~const` bound as a `HostEffect` predicate.
- pub(crate) fn push_const_bound(
- &mut self,
- tcx: TyCtxt<'tcx>,
- bound_trait_ref: ty::PolyTraitRef<'tcx>,
- constness: ty::BoundConstness,
- span: Span,
- ) {
- if tcx.is_const_trait(bound_trait_ref.def_id()) {
- self.clauses.push((bound_trait_ref.to_host_effect_clause(tcx, constness), span));
- } else {
- tcx.dcx().span_delayed_bug(span, "tried to lower {host:?} bound for non-const trait");
- }
- }
-
- pub(crate) fn clauses(&self) -> impl Iterator- , Span)> + '_ {
- self.clauses.iter().cloned()
- }
-}
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 71a10ad3a0c1..516ecbcfe0ef 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -124,7 +124,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
for field in &def.non_enum_variant().fields {
if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) {
- let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
+ let (field_span, ty_span) = match tcx.hir_get_if_local(field.did) {
// We are currently checking the type this field came from, so it must be local.
Some(Node::Field(field)) => (field.span, field.ty.span),
_ => unreachable!("mir field has to correspond to hir field"),
@@ -435,8 +435,8 @@ fn best_definition_site_of_opaque<'tcx>(
impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
type NestedFilter = nested_filter::All;
type Result = ControlFlow<(Span, LocalDefId)>;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result {
if let hir::ExprKind::Closure(closure) = ex.kind {
@@ -484,7 +484,7 @@ fn best_definition_site_of_opaque<'tcx>(
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
let scope = tcx.hir().get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id));
let found = if scope == hir::CRATE_HIR_ID {
- tcx.hir().walk_toplevel_module(&mut locator)
+ tcx.hir_walk_toplevel_module(&mut locator)
} else {
match tcx.hir_node(scope) {
Node::Item(it) => locator.visit_item(it),
@@ -880,7 +880,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
.emit();
}
- let item = tcx.hir().foreign_item(item.id);
+ let item = tcx.hir_foreign_item(item.id);
match &item.kind {
hir::ForeignItemKind::Fn(sig, _, _) => {
require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span);
@@ -1494,7 +1494,7 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
// In the case the discriminant is both a duplicate and overflowed, let the user know
if let hir::Node::AnonConst(expr) =
tcx.hir_node_by_def_id(discr_def_id.expect_local())
- && let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind
+ && let hir::ExprKind::Lit(lit) = &tcx.hir_body(expr.body).value.kind
&& let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
&& *lit_value != dis.val
{
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index bb5087e864cb..c193aad2afd0 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -501,7 +501,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id);
- let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
+ let return_span = tcx.hir_fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
let cause = ObligationCause::new(
return_span,
impl_m_def_id,
@@ -658,11 +658,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
"method `{}` has an incompatible return type for trait",
trait_m.name
);
- let hir = tcx.hir();
infcx.err_ctxt().note_type_err(
&mut diag,
&cause,
- hir.get_if_local(impl_m.def_id)
+ tcx.hir_get_if_local(impl_m.def_id)
.and_then(|node| node.fn_decl())
.map(|decl| (decl.output.span(), Cow::from("return type in trait"), false)),
Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound {
@@ -1034,8 +1033,7 @@ fn report_trait_method_mismatch<'tcx>(
// argument pattern and type.
let (sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
let span = tcx
- .hir()
- .body_param_names(body)
+ .hir_body_param_names(body)
.zip(sig.decl.inputs.iter())
.map(|(param, ty)| param.span.to(ty.span))
.next()
@@ -1123,15 +1121,14 @@ fn check_region_bounds_on_impl_item<'tcx>(
// the moment, give a kind of vague error message.
if trait_params != impl_params {
let span = tcx
- .hir()
- .get_generics(impl_m.def_id.expect_local())
+ .hir_get_generics(impl_m.def_id.expect_local())
.expect("expected impl item to have generics or else we can't compare them")
.span;
let mut generics_span = None;
let mut bounds_span = vec![];
let mut where_span = None;
- if let Some(trait_node) = tcx.hir().get_if_local(trait_m.def_id)
+ if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
&& let Some(trait_generics) = trait_node.generics()
{
generics_span = Some(trait_generics.span);
@@ -1146,7 +1143,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
}
}
}
- if let Some(impl_node) = tcx.hir().get_if_local(impl_m.def_id)
+ if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id)
&& let Some(impl_generics) = impl_node.generics()
{
let mut impl_bounds = 0;
@@ -2107,18 +2104,21 @@ pub(super) fn check_type_bounds<'tcx>(
ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
};
- let mut obligations: Vec<_> = tcx
- .explicit_item_bounds(trait_ty.def_id)
- .iter_instantiated_copied(tcx, rebased_args)
- .map(|(concrete_ty_bound, span)| {
- debug!(?concrete_ty_bound);
- traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
- })
- .collect();
+ let mut obligations: Vec<_> = util::elaborate(
+ tcx,
+ tcx.explicit_item_bounds(trait_ty.def_id).iter_instantiated_copied(tcx, rebased_args).map(
+ |(concrete_ty_bound, span)| {
+ debug!(?concrete_ty_bound);
+ traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
+ },
+ ),
+ )
+ .collect();
// Only in a const implementation do we need to check that the `~const` item bounds hold.
if tcx.is_conditionally_const(impl_ty_def_id) {
- obligations.extend(
+ obligations.extend(util::elaborate(
+ tcx,
tcx.explicit_implied_const_bounds(trait_ty.def_id)
.iter_instantiated_copied(tcx, rebased_args)
.map(|(c, span)| {
@@ -2129,7 +2129,7 @@ pub(super) fn check_type_bounds<'tcx>(
c.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
)
}),
- );
+ ));
}
debug!(item_bounds=?obligations);
@@ -2137,26 +2137,19 @@ pub(super) fn check_type_bounds<'tcx>(
// to its definition type. This should be the param-env we use to *prove* the
// predicate too, but we don't do that because of performance issues.
// See .
- let trait_projection_ty = Ty::new_projection_from_args(tcx, trait_ty.def_id, rebased_args);
- let impl_identity_ty = tcx.type_of(impl_ty.def_id).instantiate_identity();
let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
- for mut obligation in util::elaborate(tcx, obligations) {
- let normalized_predicate = if infcx.next_trait_solver() {
- obligation.predicate.fold_with(&mut ReplaceTy {
- tcx,
- from: trait_projection_ty,
- to: impl_identity_ty,
- })
- } else {
- ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate)
- };
- debug!(?normalized_predicate);
- obligation.predicate = normalized_predicate;
-
- ocx.register_obligation(obligation);
+ for obligation in &mut obligations {
+ match ocx.deeply_normalize(&normalize_cause, normalize_param_env, obligation.predicate) {
+ Ok(pred) => obligation.predicate = pred,
+ Err(e) => {
+ return Err(infcx.err_ctxt().report_fulfillment_errors(e));
+ }
+ }
}
+
// Check that all obligations are satisfied by the implementation's
// version.
+ ocx.register_obligations(obligations);
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
@@ -2168,22 +2161,6 @@ pub(super) fn check_type_bounds<'tcx>(
ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, assumed_wf_types)
}
-struct ReplaceTy<'tcx> {
- tcx: TyCtxt<'tcx>,
- from: Ty<'tcx>,
- to: Ty<'tcx>,
-}
-
-impl<'tcx> TypeFolder> for ReplaceTy<'tcx> {
- fn cx(&self) -> TyCtxt<'tcx> {
- self.tcx
- }
-
- fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- if self.from == ty { self.to } else { ty.super_fold_with(self) }
- }
-}
-
/// Install projection predicates that allow GATs to project to their own
/// definition types. This is not allowed in general in cases of default
/// associated types in trait definitions, or when specialization is involved,
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index 0e9e9b48ab30..4973d8489597 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -96,7 +96,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
// This opaque also needs to be from the impl method -- otherwise,
// it's a refinement to a TAIT.
- if !tcx.hir().get_if_local(impl_opaque.def_id).is_some_and(|node| {
+ if !tcx.hir_get_if_local(impl_opaque.def_id).is_some_and(|node| {
matches!(
node.expect_opaque_ty().origin,
hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::FnReturn { parent, .. }
@@ -327,7 +327,7 @@ fn report_mismatched_rpitit_signature<'tcx>(
hir::FnRetTy::Return(ty) => (ty.span, ty.span, "", ""),
};
let trait_return_span =
- tcx.hir().get_if_local(trait_m_def_id).map(|node| match node.fn_decl().unwrap().output {
+ tcx.hir_get_if_local(trait_m_def_id).map(|node| match node.fn_decl().unwrap().output {
hir::FnRetTy::DefaultReturn(_) => tcx.def_span(trait_m_def_id),
hir::FnRetTy::Return(ty) => ty.span,
});
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 96b33bdd2506..7b3c3ea2bb46 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -129,7 +129,7 @@ fn get_owner_return_paths(
let hir_id = tcx.local_def_id_to_hir_id(def_id);
let parent_id = tcx.hir().get_parent_item(hir_id).def_id;
tcx.hir_node_by_def_id(parent_id).body_id().map(|body_id| {
- let body = tcx.hir().body(body_id);
+ let body = tcx.hir_body(body_id);
let mut visitor = ReturnsVisitor::default();
visitor.visit_body(body);
(parent_id, visitor)
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index d43c65c0023b..255f5fee52a8 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -424,7 +424,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
// that share the parent environment. We handle const blocks in
// `visit_inline_const`.
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
- let body = visitor.tcx.hir().body(body);
+ let body = visitor.tcx.hir_body(body);
visitor.visit_body(body);
}
hir::ExprKind::AssignOp(_, left_expr, right_expr) => {
@@ -844,7 +844,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
fn visit_body(&mut self, body: &hir::Body<'tcx>) {
let body_id = body.id();
- let owner_id = self.tcx.hir().body_owner_def_id(body_id);
+ let owner_id = self.tcx.hir_body_owner_def_id(body_id);
debug!(
"visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})",
@@ -855,7 +855,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
);
self.enter_body(body.value.hir_id, |this| {
- if this.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() {
+ if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() {
// The arguments and `self` are parented to the fn.
this.cx.var_parent = this.cx.parent.take();
for param in body.params {
@@ -906,7 +906,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
resolve_local(self, Some(l.pat), l.init)
}
fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) {
- let body = self.tcx.hir().body(c.body);
+ let body = self.tcx.hir_body(c.body);
self.visit_body(body);
}
}
@@ -924,7 +924,7 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
return tcx.region_scope_tree(typeck_root_def_id);
}
- let scope_tree = if let Some(body) = tcx.hir().maybe_body_owned_by(def_id.expect_local()) {
+ let scope_tree = if let Some(body) = tcx.hir_maybe_body_owned_by(def_id.expect_local()) {
let mut visitor = ScopeResolutionVisitor {
tcx,
scope_tree: ScopeTree::default(),
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 4218f4ef0c15..edfa897860b7 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1163,7 +1163,7 @@ fn check_type_defn<'tcx>(
// be refactored to check the instantiate-ability of the code better.
if let Some(def_id) = def_id.as_local()
&& let hir::Node::AnonConst(anon) = tcx.hir_node_by_def_id(def_id)
- && let expr = &tcx.hir().body(anon.body).value
+ && let expr = &tcx.hir_body(anon.body).value
&& let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
&& let Res::Def(DefKind::ConstParam, _def_id) = path.res
{
@@ -1710,7 +1710,7 @@ fn check_sized_if_body<'tcx>(
maybe_span: Option,
) {
let tcx = wfcx.tcx();
- if let Some(body) = tcx.hir().maybe_body_owned_by(def_id) {
+ if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) {
let span = maybe_span.unwrap_or(body.value.span);
wfcx.register_bound(
diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs
index 68b7b44c36d6..750c09887a1e 100644
--- a/compiler/rustc_hir_analysis/src/check_unused.rs
+++ b/compiler/rustc_hir_analysis/src/check_unused.rs
@@ -13,11 +13,11 @@ pub(crate) fn provide(providers: &mut Providers) {
fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
let mut used_trait_imports = UnordSet::::default();
- // FIXME: Use `tcx.hir().par_body_owners()` when we implement creating `DefId`s
+ // FIXME: Use `tcx.hir_par_body_owners()` when we implement creating `DefId`s
// for anon constants during their parents' typeck.
// Doing so at current will produce queries cycle errors because it may typeck
// on anon constants directly.
- for item_def_id in tcx.hir().body_owners() {
+ for item_def_id in tcx.hir_body_owners() {
let imports = tcx.used_trait_imports(item_def_id);
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
used_trait_imports.extend_unord(imports.items().copied());
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 9da57c330c5e..b46b805f0a9d 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -679,7 +679,7 @@ fn infringing_fields_error<'tcx>(
suggest_constraining_type_params(
tcx,
- tcx.hir().get_generics(impl_did).expect("impls always have generics"),
+ tcx.hir_get_generics(impl_did).expect("impls always have generics"),
&mut err,
bounds
.iter()
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index a86dede48bff..c9a9180c5c9d 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -25,7 +25,7 @@ pub(crate) fn crate_inherent_impls(
let mut collect = InherentCollect { tcx, impls_map: Default::default() };
let mut res = Ok(());
- for id in tcx.hir().items() {
+ for id in tcx.hir_free_items() {
res = res.and(collect.check_item(id));
}
@@ -113,7 +113,7 @@ impl<'tcx> InherentCollect<'tcx> {
ty: Ty<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let items = self.tcx.associated_item_def_ids(impl_def_id);
- if !self.tcx.hir().rustc_coherence_is_core() {
+ if !self.tcx.hir_rustc_coherence_is_core() {
if self.tcx.features().rustc_attrs() {
for &impl_item in items {
if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index c72f6201831a..dc616576c9c1 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -18,7 +18,7 @@ pub(crate) fn crate_inherent_impls_overlap_check(
) -> Result<(), ErrorGuaranteed> {
let mut inherent_overlap_checker = InherentOverlapChecker { tcx };
let mut res = Ok(());
- for id in tcx.hir().items() {
+ for id in tcx.hir_free_items() {
res = res.and(inherent_overlap_checker.check_item(id));
}
res
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 126237799562..75ea207a06bb 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -277,8 +277,8 @@ fn reject_placeholder_type_signatures_in_item<'tcx>(
impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
@@ -669,7 +669,7 @@ fn get_new_lifetime_name<'tcx>(
#[instrument(level = "debug", skip_all)]
fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
- let it = tcx.hir().item(item_id);
+ let it = tcx.hir_item(item_id);
debug!(item = %it.ident, id = %it.hir_id());
let def_id = item_id.owner_id.def_id;
let icx = ItemCtxt::new(tcx, def_id);
@@ -683,7 +683,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
| hir::ItemKind::GlobalAsm(_) => {}
hir::ItemKind::ForeignMod { items, .. } => {
for item in *items {
- let item = tcx.hir().foreign_item(item.id);
+ let item = tcx.hir_foreign_item(item.id);
tcx.ensure_ok().generics_of(item.owner_id);
tcx.ensure_ok().type_of(item.owner_id);
tcx.ensure_ok().predicates_of(item.owner_id);
@@ -790,7 +790,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
}
fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
- let trait_item = tcx.hir().trait_item(trait_item_id);
+ let trait_item = tcx.hir_trait_item(trait_item_id);
let def_id = trait_item_id.owner_id;
tcx.ensure_ok().generics_of(def_id);
let icx = ItemCtxt::new(tcx, def_id.def_id);
@@ -865,7 +865,7 @@ fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
tcx.ensure_ok().generics_of(def_id);
tcx.ensure_ok().type_of(def_id);
tcx.ensure_ok().predicates_of(def_id);
- let impl_item = tcx.hir().impl_item(impl_item_id);
+ let impl_item = tcx.hir_impl_item(impl_item_id);
let icx = ItemCtxt::new(tcx, def_id.def_id);
match impl_item.kind {
hir::ImplItemKind::Fn(..) => {
@@ -1769,7 +1769,7 @@ fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
..
}),
..
- } = tcx.hir().body(body).value
+ } = tcx.hir_body(body).value
else {
bug!()
};
diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs
index 41f8465ae91f..63c445fa6a3d 100644
--- a/compiler/rustc_hir_analysis/src/collect/dump.rs
+++ b/compiler/rustc_hir_analysis/src/collect/dump.rs
@@ -52,7 +52,7 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
}
pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
- for iid in tcx.hir().items() {
+ for iid in tcx.hir_free_items() {
let did = iid.owner_id.def_id;
if tcx.has_attr(did, sym::rustc_dump_def_parents) {
struct AnonConstFinder<'tcx> {
@@ -63,8 +63,8 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> {
type NestedFilter = nested_filter::All;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_anon_const(&mut self, c: &'tcx rustc_hir::AnonConst) {
@@ -77,7 +77,7 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
// the `rustc_dump_def_parents` attribute to the anon const so it would not be possible
// to see what its def parent is.
let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] };
- intravisit::walk_item(&mut anon_ct_finder, tcx.hir().item(iid));
+ intravisit::walk_item(&mut anon_ct_finder, tcx.hir_item(iid));
for did in [did].into_iter().chain(anon_ct_finder.anon_consts) {
let span = tcx.def_span(did);
@@ -99,14 +99,14 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
}
pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
- for id in tcx.hir().items() {
+ for id in tcx.hir_free_items() {
let def_id = id.owner_id.def_id;
let Some(attr) = tcx.get_attr(def_id, sym::rustc_dump_vtable) else {
continue;
};
- let vtable_entries = match tcx.hir().item(id).kind {
+ let vtable_entries = match tcx.hir_item(id).kind {
hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => {
let trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate_identity();
if trait_ref.has_non_region_param() {
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 41c4cfbaa825..1c1a246cc151 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -13,7 +13,6 @@ use tracing::{debug, instrument};
use super::ItemCtxt;
use super::predicates_of::assert_only_contains_predicates_from;
-use crate::bounds::Bounds;
use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
/// For associated types we include both bounds written on the type
@@ -38,7 +37,7 @@ fn associated_type_bounds<'tcx>(
);
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
- let mut bounds = Bounds::default();
+ let mut bounds = Vec::new();
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
// Associated types are implicitly sized unless a `?Sized` bound is found
match filter {
@@ -68,7 +67,7 @@ fn associated_type_bounds<'tcx>(
)
});
- let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
+ let all_bounds = tcx.arena.alloc_from_iter(bounds.into_iter().chain(bounds_from_parent));
debug!(
"associated_type_bounds({}) = {:?}",
tcx.def_path_str(assoc_item_def_id.to_def_id()),
@@ -327,7 +326,7 @@ fn opaque_type_bounds<'tcx>(
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
ty::print::with_reduced_queries!({
let icx = ItemCtxt::new(tcx, opaque_def_id);
- let mut bounds = Bounds::default();
+ let mut bounds = Vec::new();
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
// Opaque types are implicitly sized unless a `?Sized` bound is found
match filter {
@@ -343,7 +342,7 @@ fn opaque_type_bounds<'tcx>(
}
debug!(?bounds);
- tcx.arena.alloc_from_iter(bounds.clauses())
+ tcx.arena.alloc_slice(&bounds)
})
}
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index d94383d6f3d8..7b1fff157b54 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -13,7 +13,6 @@ use rustc_span::{DUMMY_SP, Ident, Span};
use tracing::{debug, instrument, trace};
use super::item_bounds::explicit_item_bounds_with_filter;
-use crate::bounds::Bounds;
use crate::collect::ItemCtxt;
use crate::constrained_generic_params as cgp;
use crate::delegation::inherit_predicates_for_delegation_item;
@@ -178,7 +177,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// on a trait we must also consider the bounds that follow the trait's name,
// like `trait Foo: A + B + C`.
if let Some(self_bounds) = is_trait {
- let mut bounds = Bounds::default();
+ let mut bounds = Vec::new();
icx.lowerer().lower_bounds(
tcx.types.self_param,
self_bounds,
@@ -186,7 +185,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
ty::List::empty(),
PredicateFilter::All,
);
- predicates.extend(bounds.clauses());
+ predicates.extend(bounds);
}
// In default impls, we can assume that the self type implements
@@ -209,7 +208,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
GenericParamKind::Lifetime { .. } => (),
GenericParamKind::Type { .. } => {
let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
- let mut bounds = Bounds::default();
+ let mut bounds = Vec::new();
// Params are implicitly sized unless a `?Sized` bound is found
icx.lowerer().add_sized_bound(
&mut bounds,
@@ -219,7 +218,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
param.span,
);
trace!(?bounds);
- predicates.extend(bounds.clauses());
+ predicates.extend(bounds);
trace!(?predicates);
}
hir::GenericParamKind::Const { .. } => {
@@ -264,7 +263,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}
}
- let mut bounds = Bounds::default();
+ let mut bounds = Vec::new();
icx.lowerer().lower_bounds(
ty,
bound_pred.bounds,
@@ -272,7 +271,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
bound_vars,
PredicateFilter::All,
);
- predicates.extend(bounds.clauses());
+ predicates.extend(bounds);
}
hir::WherePredicateKind::RegionPredicate(region_pred) => {
@@ -436,7 +435,7 @@ fn const_evaluatable_predicates_of<'tcx>(
self_ty.instantiate_identity().visit_with(&mut collector);
}
- if let Some(_) = tcx.hir().fn_sig_by_hir_id(hir_id) {
+ if let Some(_) = tcx.hir_fn_sig_by_hir_id(hir_id) {
debug!("visit fn sig");
let fn_sig = tcx.fn_sig(def_id);
let fn_sig = fn_sig.instantiate_identity();
@@ -627,7 +626,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
let icx = ItemCtxt::new(tcx, trait_def_id);
let self_param_ty = tcx.types.self_param;
- let mut bounds = Bounds::default();
+ let mut bounds = Vec::new();
icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
let where_bounds_that_match =
@@ -635,7 +634,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
// Combine the two lists to form the complete set of superbounds:
let implied_bounds =
- &*tcx.arena.alloc_from_iter(bounds.clauses().chain(where_bounds_that_match));
+ &*tcx.arena.alloc_from_iter(bounds.into_iter().chain(where_bounds_that_match));
debug!(?implied_bounds);
// Now require that immediate supertraits are lowered, which will, in
@@ -826,7 +825,7 @@ pub(super) fn type_param_predicates<'tcx>(
// `where T: Foo`.
let param_id = tcx.local_def_id_to_hir_id(def_id);
- let param_owner = tcx.hir().ty_param_owner(def_id);
+ let param_owner = tcx.hir_ty_param_owner(def_id);
// Don't look for bounds where the type parameter isn't in scope.
let parent = if item_def_id == param_owner {
@@ -904,7 +903,7 @@ impl<'tcx> ItemCtxt<'tcx> {
param_def_id: LocalDefId,
filter: PredicateFilter,
) -> Vec<(ty::Clause<'tcx>, Span)> {
- let mut bounds = Bounds::default();
+ let mut bounds = Vec::new();
for predicate in hir_generics.predicates {
let hir_id = predicate.hir_id;
@@ -938,7 +937,7 @@ impl<'tcx> ItemCtxt<'tcx> {
);
}
- bounds.clauses().collect()
+ bounds
}
}
@@ -1007,7 +1006,7 @@ pub(super) fn const_conditions<'tcx>(
};
let icx = ItemCtxt::new(tcx, def_id);
- let mut bounds = Bounds::default();
+ let mut bounds = Vec::new();
for pred in generics.predicates {
match pred.kind {
@@ -1027,12 +1026,12 @@ pub(super) fn const_conditions<'tcx>(
}
if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
- bounds.push_const_bound(
- tcx,
- ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())),
- ty::BoundConstness::Maybe,
+ // We've checked above that the trait is conditionally const.
+ bounds.push((
+ ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
+ .to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
DUMMY_SP,
- );
+ ));
icx.lowerer().lower_bounds(
tcx.types.self_param,
@@ -1045,7 +1044,7 @@ pub(super) fn const_conditions<'tcx>(
ty::ConstConditions {
parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()),
- predicates: tcx.arena.alloc_from_iter(bounds.clauses().map(|(clause, span)| {
+ predicates: tcx.arena.alloc_from_iter(bounds.into_iter().map(|(clause, span)| {
(
clause.kind().map_bound(|clause| match clause {
ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index c03a1f6240fa..759c981a8f76 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -422,12 +422,12 @@ enum NonLifetimeBinderAllowed {
impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_nested_body(&mut self, body: hir::BodyId) {
- let body = self.tcx.hir().body(body);
+ let body = self.tcx.hir_body(body);
self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
this.visit_body(body);
});
@@ -1049,7 +1049,7 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectL
match param.source {
hir::GenericParamSource::Generics => {
let parent_def_id = tcx.local_parent(param_def_id);
- let generics = tcx.hir().get_generics(parent_def_id).unwrap();
+ let generics = tcx.hir_get_generics(parent_def_id).unwrap();
let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
@@ -1250,7 +1250,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
&& let hir::LifetimeName::Param(param_id) = lifetime_ref.res
&& let Some(generics) =
- self.tcx.hir().get_generics(self.tcx.local_parent(param_id))
+ self.tcx.hir_get_generics(self.tcx.local_parent(param_id))
&& let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
&& param.is_elided_lifetime()
&& !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
@@ -1264,7 +1264,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
);
if let Some(generics) =
- self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id)
+ self.tcx.hir_get_generics(lifetime_ref.hir_id.owner.def_id)
{
let new_param_sugg =
if let Some(span) = generics.span_for_lifetime_suggestion() {
@@ -1340,7 +1340,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
};
def = ResolvedArg::Error(guar);
} else if let Some(body_id) = outermost_body {
- let fn_id = self.tcx.hir().body_owner(body_id);
+ let fn_id = self.tcx.hir_body_owner(body_id);
match self.tcx.hir_node(fn_id) {
Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn { .. }, .. })
| Node::TraitItem(hir::TraitItem {
@@ -2265,8 +2265,8 @@ fn is_late_bound_map(
tcx: TyCtxt<'_>,
owner_id: hir::OwnerId,
) -> Option<&FxIndexSet> {
- let sig = tcx.hir().fn_sig_by_hir_id(owner_id.into())?;
- let generics = tcx.hir().get_generics(owner_id.def_id)?;
+ let sig = tcx.hir_fn_sig_by_hir_id(owner_id.into())?;
+ let generics = tcx.hir_get_generics(owner_id.def_id)?;
let mut late_bound = FxIndexSet::default();
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 4e12db190fd0..293a095b41d0 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -451,7 +451,7 @@ fn infer_placeholder_type<'tcx>(
);
} else {
with_forced_trimmed_paths!(err.span_note(
- tcx.hir().body(body_id).value.span,
+ tcx.hir_body(body_id).value.span,
format!("however, the inferred type `{ty}` cannot be named"),
));
}
@@ -494,7 +494,7 @@ fn infer_placeholder_type<'tcx>(
);
} else {
with_forced_trimmed_paths!(diag.span_note(
- tcx.hir().body(body_id).value.span,
+ tcx.hir_body(body_id).value.span,
format!("however, the inferred type `{ty}` cannot be named"),
));
}
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index e2b9fe0f9f72..0c36888f3639 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -89,7 +89,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
debug!(?scope);
if scope == hir::CRATE_HIR_ID {
- tcx.hir().walk_toplevel_module(&mut locator);
+ tcx.hir_walk_toplevel_module(&mut locator);
} else {
trace!("scope={:#?}", tcx.hir_node(scope));
match tcx.hir_node(scope) {
@@ -298,8 +298,8 @@ impl TaitConstraintLocator<'_> {
impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
type NestedFilter = nested_filter::All;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
if let hir::ExprKind::Closure(closure) = ex.kind {
@@ -441,8 +441,8 @@ impl RpitConstraintChecker<'_> {
impl<'tcx> intravisit::Visitor<'tcx> for RpitConstraintChecker<'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
if let hir::ExprKind::Closure(closure) = ex.kind {
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 14ea10461cbe..1a0b0edb2570 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1417,6 +1417,15 @@ pub(crate) struct CrossCrateTraitsDefined {
pub traits: String,
}
+#[derive(Diagnostic)]
+#[diag(hir_analysis_no_variant_named, code = E0599)]
+pub struct NoVariantNamed<'tcx> {
+ #[primary_span]
+ pub span: Span,
+ pub ident: Ident,
+ pub ty: Ty<'tcx>,
+}
+
// FIXME(fmease): Deduplicate:
#[derive(Diagnostic)]
diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
index b2501d647a55..681e8e36d589 100644
--- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
@@ -451,7 +451,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
)
});
- let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(hir::Node::fn_sig);
+ let fn_sig = self.tcx.hir_get_if_local(self.def_id).and_then(hir::Node::fn_sig);
let is_used_in_input = |def_id| {
fn_sig.is_some_and(|fn_sig| {
fn_sig.decl.inputs.iter().any(|ty| match ty.kind {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index ef6167907b5b..75c97001c327 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -8,7 +8,7 @@ use rustc_hir::HirId;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::bug;
-use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
+use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt, Upcast};
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
use rustc_trait_selection::traits;
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
@@ -16,7 +16,6 @@ use smallvec::SmallVec;
use tracing::{debug, instrument};
use super::errors::GenericsArgsErrExtend;
-use crate::bounds::Bounds;
use crate::errors;
use crate::hir_ty_lowering::{
AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
@@ -28,7 +27,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// Doesn't add the bound if the HIR bounds contain any of `Sized`, `?Sized` or `!Sized`.
pub(crate) fn add_sized_bound(
&self,
- bounds: &mut Bounds<'tcx>,
+ bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
self_ty: Ty<'tcx>,
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
@@ -113,10 +112,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound {
// There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound;
// we don't need to do anything.
- } else if sized_def_id.is_some() {
+ } else if let Some(sized_def_id) = sized_def_id {
// There was no `?Sized`, `!Sized` or explicit `Sized` bound;
// add `Sized` if it's available.
- bounds.push_sized(tcx, self_ty, span);
+ let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [self_ty]);
+ // Preferable to put this obligation first, since we report better errors for sized ambiguity.
+ bounds.insert(0, (trait_ref.upcast(tcx), span));
}
}
@@ -146,7 +147,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&self,
param_ty: Ty<'tcx>,
hir_bounds: I,
- bounds: &mut Bounds<'tcx>,
+ bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
bound_vars: &'tcx ty::List,
predicate_filter: PredicateFilter,
) where
@@ -189,14 +190,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
- bounds.push_region_bound(
- self.tcx(),
- ty::Binder::bind_with_vars(
- ty::OutlivesPredicate(param_ty, region),
- bound_vars,
- ),
- lifetime.ident.span,
+ let bound = ty::Binder::bind_with_vars(
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)),
+ bound_vars,
);
+ bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
}
hir::GenericBound::Use(..) => {
// We don't actually lower `use` into the type layer.
@@ -219,7 +217,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir_ref_id: hir::HirId,
trait_ref: ty::PolyTraitRef<'tcx>,
constraint: &hir::AssocItemConstraint<'tcx>,
- bounds: &mut Bounds<'tcx>,
+ bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
duplicates: &mut FxIndexMap,
path_span: Span,
predicate_filter: PredicateFilter,
@@ -389,14 +387,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
PredicateFilter::All
| PredicateFilter::SelfOnly
| PredicateFilter::SelfAndAssociatedTypeBounds => {
- bounds.push_projection_bound(
- tcx,
- projection_term.map_bound(|projection_term| ty::ProjectionPredicate {
+ let bound = projection_term.map_bound(|projection_term| {
+ ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_term,
term,
- }),
- constraint.span,
- );
+ })
+ });
+ bounds.push((bound.upcast(tcx), constraint.span));
}
// SelfTraitThatDefines is only interested in trait predicates.
PredicateFilter::SelfTraitThatDefines(_) => {}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index a8b37fa50542..830dca0d3cd5 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -17,7 +17,6 @@ use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument};
use super::HirTyLowerer;
-use crate::bounds::Bounds;
use crate::hir_ty_lowering::{
GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason,
};
@@ -36,7 +35,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let tcx = self.tcx();
let dummy_self = tcx.types.trait_object_dummy_self;
- let mut user_written_bounds = Bounds::default();
+ let mut user_written_bounds = Vec::new();
let mut potential_assoc_types = Vec::new();
for trait_bound in hir_bounds.iter() {
if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity {
@@ -60,15 +59,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
let (trait_bounds, mut projection_bounds) =
- traits::expand_trait_aliases(tcx, user_written_bounds.clauses());
+ traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = trait_bounds
.into_iter()
.partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
// We don't support empty trait objects.
if regular_traits.is_empty() && auto_traits.is_empty() {
- let guar =
- self.report_trait_object_with_no_traits_error(span, user_written_bounds.clauses());
+ let guar = self.report_trait_object_with_no_traits_error(
+ span,
+ user_written_bounds.iter().copied(),
+ );
return Ty::new_error(tcx, guar);
}
// We don't support >1 principal
@@ -84,7 +85,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Check that there are no gross dyn-compatibility violations;
// most importantly, that the supertraits don't contain `Self`,
// to avoid ICEs.
- for (clause, span) in user_written_bounds.clauses() {
+ for (clause, span) in user_written_bounds {
if let Some(trait_pred) = clause.as_trait_clause() {
let violations =
hir_ty_lowering_dyn_compatibility_violations(tcx, trait_pred.def_id());
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 7eb982a31798..d2789cc0fd62 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -225,7 +225,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&& let item_def_id =
tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id))
// FIXME: ...which obviously won't have any generics.
- && let Some(generics) = tcx.hir().get_generics(item_def_id.def_id)
+ && let Some(generics) = tcx.hir_get_generics(item_def_id.def_id)
{
// FIXME: Suggest adding supertrait bounds if we have a `Self` type param.
// FIXME(trait_alias): Suggest adding `Self: Trait` to
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index 431373978701..17de64db6290 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -70,7 +70,7 @@ fn generic_arg_mismatch_err(
}
Res::Def(DefKind::TyParam, src_def_id) => {
if let Some(param_local_id) = param.def_id.as_local() {
- let param_name = tcx.hir().ty_param_name(param_local_id);
+ let param_name = tcx.hir_ty_param_name(param_local_id);
let param_type = tcx.type_of(param.def_id).instantiate_identity();
if param_type.is_suggestable(tcx, false) {
err.span_suggestion(
@@ -110,7 +110,7 @@ fn generic_arg_mismatch_err(
err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
err.help("function item types cannot be named directly");
} else if let hir::ConstArgKind::Anon(anon) = cnst.kind
- && let body = tcx.hir().body(anon.body)
+ && let body = tcx.hir_body(anon.body)
&& let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
body.value.kind
&& let Res::Def(DefKind::Fn { .. }, id) = path.res
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 88323db6dda6..e9b99caf737b 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -49,11 +49,13 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::wf::object_region_bounds;
use rustc_trait_selection::traits::{self, ObligationCtxt};
+use rustc_type_ir::Upcast;
use tracing::{debug, instrument};
-use crate::bounds::Bounds;
use crate::check::check_abi_fn_ptr;
-use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType};
+use crate::errors::{
+ AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, NoVariantNamed,
+};
use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};
use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
use crate::middle::resolve_bound_vars as rbv;
@@ -217,7 +219,7 @@ impl AssocItemQSelf {
fn to_string(&self, tcx: TyCtxt<'_>) -> String {
match *self {
Self::Trait(def_id) => tcx.def_path_str(def_id),
- Self::TyParam(def_id, _) => tcx.hir().ty_param_name(def_id).to_string(),
+ Self::TyParam(def_id, _) => tcx.hir_ty_param_name(def_id).to_string(),
Self::SelfTyAlias => kw::SelfUpper.to_string(),
}
}
@@ -342,8 +344,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
rbv::ResolvedArg::EarlyBound(def_id) => {
- let name = tcx.hir().ty_param_name(def_id);
- let item_def_id = tcx.hir().ty_param_owner(def_id);
+ let name = tcx.hir_ty_param_name(def_id);
+ let item_def_id = tcx.hir_ty_param_owner(def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name })
@@ -691,7 +693,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
constness: hir::BoundConstness,
polarity: hir::BoundPolarity,
self_ty: Ty<'tcx>,
- bounds: &mut Bounds<'tcx>,
+ bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
predicate_filter: PredicateFilter,
) -> GenericArgCountResult {
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
@@ -720,6 +722,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
bound_vars,
);
+ debug!(?poly_trait_ref);
+
let polarity = match polarity {
rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
@@ -741,6 +745,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
};
+ // We deal with const conditions later.
+ match predicate_filter {
+ PredicateFilter::All
+ | PredicateFilter::SelfOnly
+ | PredicateFilter::SelfTraitThatDefines(..)
+ | PredicateFilter::SelfAndAssociatedTypeBounds => {
+ let bound = poly_trait_ref.map_bound(|trait_ref| {
+ ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
+ });
+ let bound = (bound.upcast(tcx), span);
+ // FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
+ if tcx.is_lang_item(trait_def_id, rustc_hir::LangItem::Sized) {
+ bounds.insert(0, bound);
+ } else {
+ bounds.push(bound);
+ }
+ }
+ PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
+ }
+
if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness
&& !self.tcx().is_const_trait(trait_def_id)
{
@@ -765,58 +789,53 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
suggestion_pre,
suggestion,
});
- }
-
- match predicate_filter {
- // This is only concerned with trait predicates.
- PredicateFilter::SelfTraitThatDefines(..) => {
- bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
- }
- PredicateFilter::All
- | PredicateFilter::SelfOnly
- | PredicateFilter::SelfAndAssociatedTypeBounds => {
- debug!(?poly_trait_ref);
- bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
-
- match constness {
- hir::BoundConstness::Always(span) => {
- if polarity == ty::PredicatePolarity::Positive {
- bounds.push_const_bound(
- tcx,
- poly_trait_ref,
- ty::BoundConstness::Const,
- span,
- );
+ } else {
+ match predicate_filter {
+ // This is only concerned with trait predicates.
+ PredicateFilter::SelfTraitThatDefines(..) => {}
+ PredicateFilter::All
+ | PredicateFilter::SelfOnly
+ | PredicateFilter::SelfAndAssociatedTypeBounds => {
+ match constness {
+ hir::BoundConstness::Always(span) => {
+ if polarity == ty::PredicatePolarity::Positive {
+ bounds.push((
+ poly_trait_ref
+ .to_host_effect_clause(tcx, ty::BoundConstness::Const),
+ span,
+ ));
+ }
}
+ hir::BoundConstness::Maybe(_) => {
+ // We don't emit a const bound here, since that would mean that we
+ // unconditionally need to prove a `HostEffect` predicate, even when
+ // the predicates are being instantiated in a non-const context. This
+ // is instead handled in the `const_conditions` query.
+ }
+ hir::BoundConstness::Never => {}
}
- hir::BoundConstness::Maybe(_) => {
- // We don't emit a const bound here, since that would mean that we
- // unconditionally need to prove a `HostEffect` predicate, even when
- // the predicates are being instantiated in a non-const context. This
- // is instead handled in the `const_conditions` query.
+ }
+ // On the flip side, when filtering `ConstIfConst` bounds, we only need to convert
+ // `~const` bounds. All other predicates are handled in their respective queries.
+ //
+ // Note that like `PredicateFilter::SelfOnly`, we don't need to do any filtering
+ // here because we only call this on self bounds, and deal with the recursive case
+ // in `lower_assoc_item_constraint`.
+ PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {
+ match constness {
+ hir::BoundConstness::Maybe(span) => {
+ if polarity == ty::PredicatePolarity::Positive {
+ bounds.push((
+ poly_trait_ref
+ .to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
+ span,
+ ));
+ }
+ }
+ hir::BoundConstness::Always(_) | hir::BoundConstness::Never => {}
}
- hir::BoundConstness::Never => {}
}
}
- // On the flip side, when filtering `ConstIfConst` bounds, we only need to convert
- // `~const` bounds. All other predicates are handled in their respective queries.
- //
- // Note that like `PredicateFilter::SelfOnly`, we don't need to do any filtering
- // here because we only call this on self bounds, and deal with the recursive case
- // in `lower_assoc_item_constraint`.
- PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => match constness {
- hir::BoundConstness::Maybe(span) => {
- if polarity == ty::PredicatePolarity::Positive {
- bounds.push_const_bound(
- tcx,
- poly_trait_ref,
- ty::BoundConstness::Maybe,
- span,
- );
- }
- }
- hir::BoundConstness::Always(_) | hir::BoundConstness::Never => {}
- },
}
let mut dup_constraints = FxIndexMap::default();
@@ -1188,14 +1207,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let msg = format!("expected type, found variant `{assoc_ident}`");
self.dcx().span_err(span, msg)
} else if qself_ty.is_enum() {
- let mut err = struct_span_code_err!(
- self.dcx(),
- assoc_ident.span,
- E0599,
- "no variant named `{}` found for enum `{}`",
- assoc_ident,
- qself_ty,
- );
+ let mut err = self.dcx().create_err(NoVariantNamed {
+ span: assoc_ident.span,
+ ident: assoc_ident,
+ ty: qself_ty,
+ });
let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
if let Some(variant_name) = find_best_match_for_name(
@@ -1976,7 +1992,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
if let Some(hir::Node::Item(&hir::Item {
kind: hir::ItemKind::Impl(impl_),
..
- })) = tcx.hir().get_if_local(def_id)
+ })) = tcx.hir_get_if_local(def_id)
{
err.span_note(impl_.self_ty.span, "not a concrete type");
}
@@ -2053,10 +2069,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Ty::new_bound(tcx, debruijn, br)
}
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
- let item_def_id = tcx.hir().ty_param_owner(def_id);
+ let item_def_id = tcx.hir_ty_param_owner(def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
- Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id))
+ Ty::new_param(tcx, index, tcx.hir_ty_param_name(def_id))
}
Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar),
arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
@@ -2213,7 +2229,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
fn lower_anon_const(&self, anon: &AnonConst) -> Const<'tcx> {
let tcx = self.tcx();
- let expr = &tcx.hir().body(anon.body).value;
+ let expr = &tcx.hir_body(anon.body).value;
debug!(?expr);
let ty = tcx
@@ -2382,7 +2398,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Impl trait in bindings lower as an infer var with additional
// set of type bounds.
let self_ty = self.ty_infer(None, hir_ty.span);
- let mut bounds = Bounds::default();
+ let mut bounds = Vec::new();
self.lower_bounds(
self_ty,
hir_bounds.iter(),
@@ -2390,11 +2406,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::List::empty(),
PredicateFilter::All,
);
- self.register_trait_ascription_bounds(
- bounds.clauses().collect(),
- hir_ty.hir_id,
- hir_ty.span,
- );
+ self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span);
self_ty
}
// If we encounter a type relative path with RTN generics, then it must have
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index f5abcd234401..0b1be8e4f7a9 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -22,8 +22,6 @@ fn diagnostic_hir_wf_check<'tcx>(
tcx: TyCtxt<'tcx>,
(predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc),
) -> Option> {
- let hir = tcx.hir();
-
let def_id = match loc {
WellFormedLoc::Ty(def_id) => def_id,
WellFormedLoc::Param { function, param_idx: _ } => function,
@@ -187,7 +185,7 @@ fn diagnostic_hir_wf_check<'tcx>(
ref node => bug!("Unexpected node {:?}", node),
},
WellFormedLoc::Param { function: _, param_idx } => {
- let fn_decl = hir.fn_decl_by_hir_id(hir_id).unwrap();
+ let fn_decl = tcx.hir_fn_decl_by_hir_id(hir_id).unwrap();
// Get return type
if param_idx as usize == fn_decl.inputs.len() {
match fn_decl.output {
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 8a529e9c686e..0859a39b1556 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -80,7 +80,6 @@ This API is completely unstable and subject to change.
pub mod check;
pub mod autoderef;
-mod bounds;
mod check_unused;
mod coherence;
mod collect;
@@ -93,6 +92,7 @@ mod impl_wf_check;
mod outlives;
mod variance;
+pub use errors::NoVariantNamed;
use rustc_abi::ExternAbi;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
@@ -184,7 +184,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
// what we are intending to discard, to help future type-based refactoring.
type R = Result<(), ErrorGuaranteed>;
- tcx.hir().par_for_each_module(|module| {
+ tcx.par_hir_for_each_module(|module| {
let _: R = tcx.ensure_ok().check_mod_type_wf(module);
});
@@ -209,7 +209,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
// Make sure we evaluate all static and (non-associated) const items, even if unused.
// If any of these fail to evaluate, we do not want this crate to pass compilation.
- tcx.hir().par_body_owners(|item_def_id| {
+ tcx.par_hir_body_owners(|item_def_id| {
let def_kind = tcx.def_kind(item_def_id);
match def_kind {
DefKind::Static { .. } => tcx.ensure_ok().eval_static_initializer(item_def_id),
@@ -227,7 +227,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
// for anon constants during their parents' typeck.
// Typeck all body owners in parallel will produce queries
// cycle errors because it may typeck on anon constants directly.
- tcx.hir().par_body_owners(|item_def_id| {
+ tcx.par_hir_body_owners(|item_def_id| {
let def_kind = tcx.def_kind(item_def_id);
if !matches!(def_kind, DefKind::AnonConst) {
tcx.ensure_ok().typeck(item_def_id);
diff --git a/compiler/rustc_hir_analysis/src/outlives/dump.rs b/compiler/rustc_hir_analysis/src/outlives/dump.rs
index ab50d9e86efb..4233896c3720 100644
--- a/compiler/rustc_hir_analysis/src/outlives/dump.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/dump.rs
@@ -3,7 +3,7 @@ use rustc_middle::ty::{self, TyCtxt};
use rustc_span::sym;
pub(crate) fn inferred_outlives(tcx: TyCtxt<'_>) {
- for id in tcx.hir().items() {
+ for id in tcx.hir_free_items() {
if !tcx.has_attr(id.owner_id, sym::rustc_outlives) {
continue;
}
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 036163b9f140..a0faa5e8429e 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -28,7 +28,7 @@ pub(super) fn infer_predicates(
let mut predicates_added = false;
// Visit all the crates and infer predicates
- for id in tcx.hir().items() {
+ for id in tcx.hir_free_items() {
let item_did = id.owner_id;
debug!("InferVisitor::visit_item(item={:?})", item_did);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 56e268aea54d..7343ba80854c 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -25,8 +25,8 @@ use rustc_span::source_map::SourceMap;
use rustc_span::{FileName, Ident, Span, Symbol, kw};
use {rustc_ast as ast, rustc_hir as hir};
-pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: HirId) -> String {
- to_string(&map, |s| s.print_node(map.hir_node(hir_id)))
+pub fn id_to_string(cx: &dyn rustc_hir::intravisit::HirTyCtxt<'_>, hir_id: HirId) -> String {
+ to_string(&cx, |s| s.print_node(cx.hir_node(hir_id)))
}
pub enum AnnNode<'a> {
@@ -55,15 +55,15 @@ pub trait PpAnn {
fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
}
-impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
+impl PpAnn for &dyn rustc_hir::intravisit::HirTyCtxt<'_> {
fn nested(&self, state: &mut State<'_>, nested: Nested) {
match nested {
- Nested::Item(id) => state.print_item(self.item(id)),
- Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
- Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
- Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)),
- Nested::Body(id) => state.print_expr(self.body(id).value),
- Nested::BodyParamPat(id, i) => state.print_pat(self.body(id).params[i].pat),
+ Nested::Item(id) => state.print_item(self.hir_item(id)),
+ Nested::TraitItem(id) => state.print_trait_item(self.hir_trait_item(id)),
+ Nested::ImplItem(id) => state.print_impl_item(self.hir_impl_item(id)),
+ Nested::ForeignItem(id) => state.print_foreign_item(self.hir_foreign_item(id)),
+ Nested::Body(id) => state.print_expr(self.hir_body(id).value),
+ Nested::BodyParamPat(id, i) => state.print_pat(self.hir_body(id).params[i].pat),
}
}
}
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 3d40c5ee8045..38319862334a 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -213,10 +213,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arm_ty: Ty<'tcx>,
prior_arm: Option<(Option, Ty<'tcx>, Span)>,
) {
- let hir = self.tcx.hir();
-
// First, check that we're actually in the tail of a function.
- let Some(body) = hir.maybe_body_owned_by(self.body_id) else {
+ let Some(body) = self.tcx.hir_maybe_body_owned_by(self.body_id) else {
return;
};
let hir::ExprKind::Block(block, _) = body.value.kind else {
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index f2d0b9117314..49ea2181b075 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -708,8 +708,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let Res::Local(_) = path.res
&& let [segment] = &path.segments
{
- for id in self.tcx.hir().items() {
- if let Some(node) = self.tcx.hir().get_if_local(id.owner_id.into())
+ for id in self.tcx.hir_free_items() {
+ if let Some(node) = self.tcx.hir_get_if_local(id.owner_id.into())
&& let hir::Node::Item(item) = node
&& let hir::ItemKind::Fn { .. } = item.kind
&& item.ident.name == segment.ident.name
@@ -860,7 +860,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}
- let host = match self.tcx.hir().body_const_context(self.body_id) {
+ let host = match self.tcx.hir_body_const_context(self.body_id) {
Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => {
ty::BoundConstness::Const
}
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 6fb5f6af0913..dabae7b1d094 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -35,12 +35,8 @@ pub(super) fn check_fn<'a, 'tcx>(
params_can_be_unsized: bool,
) -> Option> {
let fn_id = fcx.tcx.local_def_id_to_hir_id(fn_def_id);
-
let tcx = fcx.tcx;
- let hir = tcx.hir();
-
let declared_ret_ty = fn_sig.output();
-
let ret_ty =
fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars(
declared_ret_ty,
@@ -69,7 +65,7 @@ pub(super) fn check_fn<'a, 'tcx>(
});
// Add formal parameters.
- let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs);
+ let inputs_hir = tcx.hir_fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs);
let inputs_fn = fn_sig.inputs().iter().copied();
for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() {
// We checked the root's signature during wfcheck, but not the child.
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 43124f44ca60..71a0664bbdff 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -51,7 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
let tcx = self.tcx;
- let body = tcx.hir().body(closure.body);
+ let body = tcx.hir_body(closure.body);
let expr_def_id = closure.def_id;
// It's always helpful for inference if we know the kind of
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index ad378367e305..cf11bccae0ac 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1891,7 +1891,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
kind: hir::ExprKind::Closure(&hir::Closure { body, .. }),
..
}) = parent
- && !matches!(fcx.tcx.hir().body(body).value.kind, hir::ExprKind::Block(..))
+ && !matches!(fcx.tcx.hir_body(body).value.kind, hir::ExprKind::Block(..))
{
fcx.suggest_missing_semicolon(&mut err, expr, expected, true);
}
@@ -1943,7 +1943,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
if due_to_block
&& let Some(expr) = expression
&& let Some(parent_fn_decl) =
- fcx.tcx.hir().fn_decl_by_hir_id(fcx.tcx.local_def_id_to_hir_id(fcx.body_id))
+ fcx.tcx.hir_fn_decl_by_hir_id(fcx.tcx.local_def_id_to_hir_id(fcx.body_id))
{
fcx.suggest_missing_break_or_return_expr(
&mut err,
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 85e949952f8d..4dc736f72cf8 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -293,8 +293,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &hir::Expr<'_>,
source: TypeMismatchSource<'tcx>,
) -> bool {
- let hir = self.tcx.hir();
-
let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else {
return false;
};
@@ -334,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let mut expr_finder = FindExprs { hir_id: local_hir_id, uses: init.into_iter().collect() };
- let body = hir.body_owned_by(self.body_id);
+ let body = self.tcx.hir_body_owned_by(self.body_id);
expr_finder.visit_expr(body.value);
// Replaces all of the variables in the given type with a fresh inference variable.
@@ -727,7 +725,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ident,
kind: hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..),
..
- })) = self.tcx.hir().get_if_local(*def_id)
+ })) = self.tcx.hir_get_if_local(*def_id)
{
primary_span = ty.span;
secondary_span = ident.span;
@@ -1173,7 +1171,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }),
..
- })) = self.tcx.hir().get_if_local(*alias_to)
+ })) = self.tcx.hir_get_if_local(*alias_to)
{
err.span_label(self_ty.span, "this is the type of the `Self` literal");
}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 9ccd67460874..1c63b8b36559 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -19,6 +19,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, HirId, QPath};
+use rustc_hir_analysis::NoVariantNamed;
use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _};
use rustc_infer::infer;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
@@ -1150,13 +1151,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We are inside a function body, so reporting "return statement
// outside of function body" needs an explanation.
- let encl_body_owner_id = self.tcx.hir().enclosing_body_owner(expr.hir_id);
+ let encl_body_owner_id = self.tcx.hir_enclosing_body_owner(expr.hir_id);
// If this didn't hold, we would not have to report an error in
// the first place.
assert_ne!(encl_item_id.def_id, encl_body_owner_id);
- let encl_body = self.tcx.hir().body_owned_by(encl_body_owner_id);
+ let encl_body = self.tcx.hir_body_owned_by(encl_body_owner_id);
err.encl_body_span = Some(encl_body.value.span);
err.encl_fn_span = Some(*encl_fn_span);
@@ -1801,7 +1802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
block: &'tcx hir::ConstBlock,
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
- let body = self.tcx.hir().body(block.body);
+ let body = self.tcx.hir_body(block.body);
// Create a new function context.
let def_id = block.def_id;
@@ -3229,7 +3230,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None => return,
};
let param_span = self.tcx.hir().span(param_hir_id);
- let param_name = self.tcx.hir().ty_param_name(param_def_id.expect_local());
+ let param_name = self.tcx.hir_ty_param_name(param_def_id.expect_local());
err.span_label(param_span, format!("type parameter '{param_name}' declared here"));
}
@@ -3837,15 +3838,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.iter_enumerated()
.find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident)
else {
- type_error_struct!(
- self.dcx(),
- ident.span,
- container,
- E0599,
- "no variant named `{ident}` found for enum `{container}`",
- )
- .with_span_label(field.span, "variant not found")
- .emit();
+ self.dcx()
+ .create_err(NoVariantNamed { span: ident.span, ident, ty: container })
+ .with_span_label(field.span, "variant not found")
+ .emit_unless(container.references_error());
break;
};
let Some(&subfield) = fields.next() else {
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 860e619be718..9b85b2aeec6e 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -1001,11 +1001,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
let closure_def_id = closure_expr.def_id;
// For purposes of this function, coroutine and closures are equivalent.
let body_owner_is_closure = matches!(
- tcx.hir().body_owner_kind(self.cx.body_owner_def_id()),
+ tcx.hir_body_owner_kind(self.cx.body_owner_def_id()),
hir::BodyOwnerKind::Closure
);
- // If we have a nested closure, we want to include the fake reads present in the nested closure.
+ // If we have a nested closure, we want to include the fake reads present in the nested
+ // closure.
if let Some(fake_reads) = self.cx.typeck_results().closure_fake_reads.get(&closure_def_id) {
for (fake_read, cause, hir_id) in fake_reads.iter() {
match fake_read.base {
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 4618c5d3849b..e051fc7ac6ca 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -573,7 +573,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
coercions: &VecGraph,
) -> errors::SuggestAnnotations {
let body =
- self.tcx.hir().maybe_body_owned_by(self.body_id).expect("body id must have an owner");
+ self.tcx.hir_maybe_body_owned_by(self.body_id).expect("body id must have an owner");
// For each diverging var, look through the HIR for a place to give it
// a type annotation. We do this per var because we only really need one
// suggestion to influence a var to be `()`.
@@ -687,7 +687,7 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> {
if let hir::ExprKind::Closure(&hir::Closure { body, .. })
| hir::ExprKind::ConstBlock(hir::ConstBlock { body, .. }) = expr.kind
{
- self.visit_body(self.fcx.tcx.hir().body(body))?;
+ self.visit_body(self.fcx.tcx.hir_body(body))?;
}
// Try to suggest adding an explicit qself `()` to a trait method path.
@@ -764,7 +764,7 @@ fn compute_unsafe_infer_vars<'a, 'tcx>(
fcx: &'a FnCtxt<'a, 'tcx>,
body_id: LocalDefId,
) -> UnordMap {
- let body = fcx.tcx.hir().maybe_body_owned_by(body_id).expect("body id must have an owner");
+ let body = fcx.tcx.hir_maybe_body_owned_by(body_id).expect("body id must have an owner");
let mut res = UnordMap::default();
struct UnsafeInferVarsVisitor<'a, 'tcx> {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 1113f7f70953..ff41a080d629 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -640,7 +640,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let witness = Ty::new_coroutine_witness(self.tcx, expr_def_id.to_def_id(), args);
// Unify `interior` with `witness` and collect all the resulting obligations.
- let span = self.tcx.hir().body(body_id).value.span;
+ let span = self.tcx.hir_body(body_id).value.span;
let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else {
span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind())
};
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 77081548d115..7ca44d23e3ed 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -100,7 +100,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
for (asm, hir_id) in deferred_asm_checks.drain(..) {
- let enclosing_id = self.tcx.hir().enclosing_body_owner(hir_id);
+ let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id);
let get_operand_ty = |expr| {
let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
let ty = self.resolve_vars_if_possible(ty);
@@ -2056,7 +2056,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match node {
Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: body_id, .. }, .. })
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
- let body = self.tcx.hir().body(body_id);
+ let body = self.tcx.hir_body(body_id);
if let ExprKind::Block(block, _) = &body.value.kind {
return Some(block.span);
}
@@ -2512,11 +2512,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id)));
- } else if let Some(hir::Node::Expr(e)) = self.tcx.hir().get_if_local(def_id)
+ } else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id)
&& let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
{
let param = expected_idx
- .and_then(|expected_idx| self.tcx.hir().body(*body).params.get(expected_idx));
+ .and_then(|expected_idx| self.tcx.hir_body(*body).params.get(expected_idx));
let (kind, span) = if let Some(param) = param {
// Try to find earlier invocations of this closure to find if the type mismatch
// is because of inference. If we find one, point at them.
@@ -2650,7 +2650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
is_method: bool,
) -> Option<(IndexVec, FnParam<'_>)>, &hir::Generics<'_>)>
{
- let (sig, generics, body_id, param_names) = match self.tcx.hir().get_if_local(def_id)? {
+ let (sig, generics, body_id, param_names) = match self.tcx.hir_get_if_local(def_id)? {
hir::Node::TraitItem(&hir::TraitItem {
generics,
kind: hir::TraitItemKind::Fn(sig, trait_fn),
@@ -2695,7 +2695,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match (body_id, param_names) {
(Some(_), Some(_)) | (None, None) => unreachable!(),
(Some(body), None) => {
- let params = self.tcx.hir().body(body).params;
+ let params = self.tcx.hir_body(body).params;
let params =
params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
debug_assert_eq!(params.len(), fn_inputs.len());
@@ -2725,8 +2725,8 @@ struct FindClosureArg<'tcx> {
impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
type NestedFilter = rustc_middle::hir::nested_filter::All;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index b77e6de52ff1..42236ac6d808 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -290,7 +290,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
_: Ident,
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
let tcx = self.tcx;
- let item_def_id = tcx.hir().ty_param_owner(def_id);
+ let item_def_id = tcx.hir_ty_param_owner(def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
// HACK(eddyb) should get the original `Span`.
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 4ec8d0b1f60a..347a6557c2aa 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1811,9 +1811,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead"
),
);
- let owner = self.tcx.hir().enclosing_body_owner(expr.hir_id);
+ let owner = self.tcx.hir_enclosing_body_owner(expr.hir_id);
if let ty::Param(param) = expected_ty.kind()
- && let Some(generics) = self.tcx.hir().get_generics(owner)
+ && let Some(generics) = self.tcx.hir_get_generics(owner)
{
suggest_constraining_type_params(
self.tcx,
@@ -1933,7 +1933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
..
} = init
{
- let hir::Body { value: body_expr, .. } = self.tcx.hir().body(*body_id);
+ let hir::Body { value: body_expr, .. } = self.tcx.hir_body(*body_id);
self.note_type_is_not_clone_inner_expr(body_expr)
} else {
expr
@@ -2094,9 +2094,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &hir::Expr<'tcx>,
expected: Ty<'tcx>,
) -> bool {
- let hir = self.tcx.hir();
+ let tcx = self.tcx;
+ let hir = tcx.hir();
let enclosing_scope =
- hir.get_enclosing_scope(expr.hir_id).map(|hir_id| self.tcx.hir_node(hir_id));
+ hir.get_enclosing_scope(expr.hir_id).map(|hir_id| tcx.hir_node(hir_id));
// Get tail expr of the enclosing block or body
let tail_expr = if let Some(Node::Block(hir::Block { expr, .. })) = enclosing_scope
@@ -2104,8 +2105,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
*expr
} else {
- let body_def_id = hir.enclosing_body_owner(expr.hir_id);
- let body = hir.body_owned_by(body_def_id);
+ let body_def_id = tcx.hir_enclosing_body_owner(expr.hir_id);
+ let body = tcx.hir_body_owned_by(body_def_id);
// Get tail expr of the body
match body.value.kind {
@@ -2147,7 +2148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
("consider returning a value here", format!("`{expected}` value"))
};
- let src_map = self.tcx.sess.source_map();
+ let src_map = tcx.sess.source_map();
let suggestion = if src_map.is_multiline(expr.span) {
let indentation = src_map.indentation_before(span).unwrap_or_else(String::new);
format!("\n{indentation}/* {suggestion} */")
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 02fbd46173c4..9d5184acb3ca 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -123,7 +123,7 @@ fn typeck_with_inspect<'tcx>(
let body_id = node.body_id().unwrap_or_else(|| {
span_bug!(span, "can't type-check body of {:?}", def_id);
});
- let body = tcx.hir().body(body_id);
+ let body = tcx.hir_body(body_id);
let param_env = tcx.param_env(def_id);
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 6c4ad65be6a6..780ab8c18334 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -531,7 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let hir::def::Res::Local(recv_id) = path.res
&& let Some(segment) = path.segments.first()
{
- let body = self.tcx.hir().body_owned_by(self.body_id);
+ let body = self.tcx.hir_body_owned_by(self.body_id);
if let Node::Expr(call_expr) = self.tcx.parent_hir_node(rcvr.hir_id) {
let mut let_visitor = LetVisitor {
@@ -1091,7 +1091,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
continue;
}
- match self.tcx.hir().get_if_local(item_def_id) {
+ match self.tcx.hir_get_if_local(item_def_id) {
// Unmet obligation comes from a `derive` macro, point at it once to
// avoid multiple span labels pointing at the same place.
Some(Node::Item(hir::Item {
@@ -2599,7 +2599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
seg1.ident.span,
StashKey::CallAssocMethod,
|err| {
- let body = self.tcx.hir().body_owned_by(self.body_id);
+ let body = self.tcx.hir_body_owned_by(self.body_id);
struct LetVisitor {
ident_name: Symbol,
}
@@ -3336,7 +3336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let accessible_sugg = sugg(accessible_candidates, true);
let inaccessible_sugg = sugg(inaccessible_candidates, false);
- let (module, _, _) = self.tcx.hir().get_module(scope);
+ let (module, _, _) = self.tcx.hir_get_module(scope);
let span = module.spans.inject_use_span;
handle_candidates(accessible_sugg, inaccessible_sugg, span);
}
@@ -3753,19 +3753,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::TraitFn::Required([ident, ..]) => {
ident.name == kw::SelfLower
}
- hir::TraitFn::Provided(body_id) => self
- .tcx
- .hir()
- .body(*body_id)
- .params
- .first()
- .is_some_and(|param| {
- matches!(
- param.pat.kind,
- hir::PatKind::Binding(_, _, ident, _)
- if ident.name == kw::SelfLower
- )
- }),
+ hir::TraitFn::Provided(body_id) => {
+ self.tcx.hir_body(*body_id).params.first().is_some_and(
+ |param| {
+ matches!(
+ param.pat.kind,
+ hir::PatKind::Binding(_, _, ident, _)
+ if ident.name == kw::SelfLower
+ )
+ },
+ )
+ }
_ => false,
};
@@ -3833,20 +3831,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(param) = param_type {
let generics = self.tcx.generics_of(self.body_id.to_def_id());
let type_param = generics.type_param(param, self.tcx);
- let hir = self.tcx.hir();
+ let tcx = self.tcx;
if let Some(def_id) = type_param.def_id.as_local() {
- let id = self.tcx.local_def_id_to_hir_id(def_id);
+ let id = tcx.local_def_id_to_hir_id(def_id);
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: FooBar`,
// instead we suggest `T: Foo + Bar` in that case.
- match self.tcx.hir_node(id) {
+ match tcx.hir_node(id) {
Node::GenericParam(param) => {
enum Introducer {
Plus,
Colon,
Nothing,
}
- let hir_generics = hir.get_generics(id.owner.def_id).unwrap();
+ let hir_generics = tcx.hir_get_generics(id.owner.def_id).unwrap();
let trait_def_ids: DefIdSet = hir_generics
.bounds_for_param(def_id)
.flat_map(|bp| bp.bounds.iter())
@@ -3866,8 +3864,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let candidate_strs: Vec<_> = candidates
.iter()
.map(|cand| {
- let cand_path = self.tcx.def_path_str(cand.def_id);
- let cand_params = &self.tcx.generics_of(cand.def_id).own_params;
+ let cand_path = tcx.def_path_str(cand.def_id);
+ let cand_params = &tcx.generics_of(cand.def_id).own_params;
let cand_args: String = cand_params
.iter()
.skip(1)
@@ -3960,9 +3958,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_suggestions(
sp,
message(format!("add {article} supertrait for")),
- candidates.iter().map(|t| {
- format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
- }),
+ candidates
+ .iter()
+ .map(|t| format!("{} {}", sep, tcx.def_path_str(t.def_id),)),
Applicability::MaybeIncorrect,
);
return;
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index c5c11c2bd253..ae00bb4e218a 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1231,7 +1231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ident: Ident,
) -> bool {
match opt_def_id {
- Some(def_id) => match self.tcx.hir().get_if_local(def_id) {
+ Some(def_id) => match self.tcx.hir_get_if_local(def_id) {
Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Const(_, _, body_id),
..
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index b54e430a9d9f..762d04fdedd4 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -143,7 +143,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
match expr.kind {
hir::ExprKind::Closure(&hir::Closure { capture_clause, body: body_id, .. }) => {
- let body = self.fcx.tcx.hir().body(body_id);
+ let body = self.fcx.tcx.hir_body(body_id);
self.visit_body(body);
self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause);
}
@@ -154,7 +154,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
}
fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) {
- let body = self.fcx.tcx.hir().body(c.body);
+ let body = self.fcx.tcx.hir_body(c.body);
self.visit_body(body);
}
}
@@ -196,7 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let args = self.resolve_vars_if_possible(args);
let closure_def_id = closure_def_id.expect_local();
- assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id);
+ assert_eq!(self.tcx.hir_body_owner_def_id(body.id()), closure_def_id);
let mut delegate = InferBorrowKind {
closure_def_id,
capture_information: Default::default(),
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 1bf5b19d68d0..8c50cc59c1d5 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -38,7 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
body: &'tcx hir::Body<'tcx>,
) -> &'tcx ty::TypeckResults<'tcx> {
- let item_def_id = self.tcx.hir().body_owner_def_id(body.id());
+ let item_def_id = self.tcx.hir_body_owner_def_id(body.id());
// This attribute causes us to dump some writeback information
// in the form of errors, which is used for unit tests.
@@ -49,7 +49,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
wbcx.visit_node_id(param.pat.span, param.hir_id);
}
// Type only exists for constants and statics, not functions.
- match self.tcx.hir().body_owner_kind(item_def_id) {
+ match self.tcx.hir_body_owner_kind(item_def_id) {
hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) => {
let item_hir_id = self.tcx.local_def_id_to_hir_id(item_def_id);
wbcx.visit_node_id(body.value.span, item_hir_id);
@@ -249,7 +249,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
fn visit_const_block(&mut self, span: Span, anon_const: &hir::ConstBlock) {
self.visit_node_id(span, anon_const.hir_id);
- let body = self.tcx().hir().body(anon_const.body);
+ let body = self.tcx().hir_body(anon_const.body);
self.visit_body(body);
}
}
@@ -266,7 +266,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
match e.kind {
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
- let body = self.fcx.tcx.hir().body(body);
+ let body = self.fcx.tcx.hir_body(body);
for param in body.params {
self.visit_node_id(e.span, param.hir_id);
}
@@ -790,7 +790,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
self.fcx
.err_ctxt()
.emit_inference_failure_err(
- self.fcx.tcx.hir().body_owner_def_id(self.body.id()),
+ self.fcx.tcx.hir_body_owner_def_id(self.body.id()),
self.span.to_span(self.fcx.tcx),
p.into(),
TypeAnnotationNeeded::E0282,
@@ -814,7 +814,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
// expect that types that show up in the typeck are fully
// normalized.
let mut value = if self.should_normalize {
- let body_id = tcx.hir().body_owner_def_id(self.body.id());
+ let body_id = tcx.hir_body_owner_def_id(self.body.id());
let cause = ObligationCause::misc(self.span.to_span(tcx), body_id);
let at = self.fcx.at(&cause, self.fcx.param_env);
let universes = vec![None; outer_exclusive_binder(value).as_usize()];
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index 569034954c3d..d4407559202f 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -76,7 +76,7 @@ pub(crate) fn assert_dep_graph(tcx: TyCtxt<'_>) {
let mut visitor =
IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] };
visitor.process_attrs(CRATE_DEF_ID);
- tcx.hir().visit_all_item_likes_in_crate(&mut visitor);
+ tcx.hir_visit_all_item_likes_in_crate(&mut visitor);
(visitor.if_this_changed, visitor.then_this_would_need)
};
@@ -174,8 +174,8 @@ impl<'tcx> IfThisChanged<'tcx> {
impl<'tcx> Visitor<'tcx> for IfThisChanged<'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index 30590bf5d3cb..118a6fed036e 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -166,7 +166,7 @@ pub(crate) fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
}
let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] };
- tcx.hir().walk_attributes(&mut all_attrs);
+ tcx.hir_walk_attributes(&mut all_attrs);
// Note that we cannot use the existing "unused attribute"-infrastructure
// here, since that is running before codegen. This is also the reason why
@@ -455,8 +455,8 @@ impl<'tcx> FindAllAttrs<'tcx> {
impl<'tcx> intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> {
type NestedFilter = nested_filter::All;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_attribute(&mut self, attr: &'tcx Attribute) {
diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl
index 43c69c8e5718..adc7ed54e147 100644
--- a/compiler/rustc_interface/messages.ftl
+++ b/compiler/rustc_interface/messages.ftl
@@ -33,6 +33,10 @@ interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
interface_input_file_would_be_overwritten =
the input file "{$path}" would be overwritten by the generated executable
+interface_limit_invalid =
+ `limit` must be a non-negative integer
+ .label = {$error_str}
+
interface_mixed_bin_crate =
cannot mix `bin` crate type with others
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs
index c3b858d4f2ec..ca4e556dcdb8 100644
--- a/compiler/rustc_interface/src/errors.rs
+++ b/compiler/rustc_interface/src/errors.rs
@@ -127,3 +127,13 @@ pub(crate) struct AbiRequiredTargetFeature<'a> {
pub feature: &'a str,
pub enabled: &'a str,
}
+
+#[derive(Diagnostic)]
+#[diag(interface_limit_invalid)]
+pub(crate) struct LimitInvalid<'a> {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub value_span: Span,
+ pub error_str: &'a str,
+}
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index a2a29612e489..54cd341698f0 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -10,6 +10,7 @@
mod callbacks;
pub mod errors;
pub mod interface;
+mod limits;
pub mod passes;
mod proc_macro_decls;
mod queries;
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_interface/src/limits.rs
similarity index 56%
rename from compiler/rustc_middle/src/middle/limits.rs
rename to compiler/rustc_interface/src/limits.rs
index 8a367a947d16..8f01edec09f3 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_interface/src/limits.rs
@@ -1,61 +1,58 @@
//! Registering limits:
-//! * recursion_limit,
-//! * move_size_limit, and
-//! * type_length_limit
+//! - recursion_limit: there are various parts of the compiler that must impose arbitrary limits
+//! on how deeply they recurse to prevent stack overflow.
+//! - move_size_limit
+//! - type_length_limit
+//! - pattern_complexity_limit
//!
-//! There are various parts of the compiler that must impose arbitrary limits
-//! on how deeply they recurse to prevent stack overflow. Users can override
-//! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
-//! just peeks and looks for that attribute.
+//! Users can override these limits via an attribute on the crate like
+//! `#![recursion_limit="22"]`. This pass just looks for those attributes.
use std::num::IntErrorKind;
use rustc_ast::attr::AttributeExt;
+use rustc_middle::bug;
+use rustc_middle::query::Providers;
use rustc_session::{Limit, Limits, Session};
use rustc_span::{Symbol, sym};
-use crate::error::LimitInvalid;
-use crate::query::Providers;
+use crate::errors::LimitInvalid;
-pub fn provide(providers: &mut Providers) {
+pub(crate) fn provide(providers: &mut Providers) {
providers.limits = |tcx, ()| Limits {
- recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
+ recursion_limit: get_recursion_limit(tcx.hir_krate_attrs(), tcx.sess),
move_size_limit: get_limit(
- tcx.hir().krate_attrs(),
+ tcx.hir_krate_attrs(),
tcx.sess,
sym::move_size_limit,
- tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0),
+ Limit::new(tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0)),
),
type_length_limit: get_limit(
- tcx.hir().krate_attrs(),
+ tcx.hir_krate_attrs(),
tcx.sess,
sym::type_length_limit,
- 2usize.pow(24),
+ Limit::new(2usize.pow(24)),
+ ),
+ pattern_complexity_limit: get_limit(
+ tcx.hir_krate_attrs(),
+ tcx.sess,
+ sym::pattern_complexity_limit,
+ Limit::unlimited(),
),
}
}
-pub fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit {
- get_limit(krate_attrs, sess, sym::recursion_limit, 128)
+// This one is separate because it must be read prior to macro expansion.
+pub(crate) fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit {
+ get_limit(krate_attrs, sess, sym::recursion_limit, Limit::new(128))
}
fn get_limit(
krate_attrs: &[impl AttributeExt],
sess: &Session,
name: Symbol,
- default: usize,
+ default: Limit,
) -> Limit {
- match get_limit_size(krate_attrs, sess, name) {
- Some(size) => Limit::new(size),
- None => Limit::new(default),
- }
-}
-
-pub fn get_limit_size(
- krate_attrs: &[impl AttributeExt],
- sess: &Session,
- name: Symbol,
-) -> Option {
for attr in krate_attrs {
if !attr.has_name(name) {
continue;
@@ -63,7 +60,7 @@ pub fn get_limit_size(
if let Some(sym) = attr.value_str() {
match sym.as_str().parse() {
- Ok(n) => return Some(n),
+ Ok(n) => return Limit::new(n),
Err(e) => {
let error_str = match e.kind() {
IntErrorKind::PosOverflow => "`limit` is too large",
@@ -84,5 +81,5 @@ pub fn get_limit_size(
}
}
}
- None
+ default
}
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index fcebca3ecc91..d70d9d344b94 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -39,7 +39,7 @@ use rustc_trait_selection::traits;
use tracing::{info, instrument};
use crate::interface::Compiler;
-use crate::{errors, proc_macro_decls, util};
+use crate::{errors, limits, proc_macro_decls, util};
pub fn parse<'a>(sess: &'a Session) -> ast::Crate {
let krate = sess
@@ -687,6 +687,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| {
|tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal());
providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1;
providers.early_lint_checks = early_lint_checks;
+ limits::provide(providers);
proc_macro_decls::provide(providers);
rustc_const_eval::provide(providers);
rustc_middle::hir::provide(providers);
@@ -845,7 +846,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
CStore::from_tcx(tcx).report_unused_deps(tcx);
},
{
- tcx.hir().par_for_each_module(|module| {
+ tcx.par_hir_for_each_module(|module| {
tcx.ensure_ok().check_mod_loops(module);
tcx.ensure_ok().check_mod_attrs(module);
tcx.ensure_ok().check_mod_naked_functions(module);
@@ -870,7 +871,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
rustc_hir_analysis::check_crate(tcx);
sess.time("MIR_coroutine_by_move_body", || {
- tcx.hir().par_body_owners(|def_id| {
+ tcx.par_hir_body_owners(|def_id| {
if tcx.needs_coroutine_by_move_body_def_id(def_id.to_def_id()) {
tcx.ensure_done().coroutine_by_move_body_def_id(def_id);
}
@@ -884,7 +885,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
tcx.untracked().definitions.freeze();
sess.time("MIR_borrow_checking", || {
- tcx.hir().par_body_owners(|def_id| {
+ tcx.par_hir_body_owners(|def_id| {
// Run unsafety check because it's responsible for stealing and
// deallocating THIR.
tcx.ensure_ok().check_unsafety(def_id);
@@ -892,21 +893,21 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
});
});
sess.time("MIR_effect_checking", || {
- tcx.hir().par_body_owners(|def_id| {
+ tcx.par_hir_body_owners(|def_id| {
tcx.ensure_ok().has_ffi_unwind_calls(def_id);
// If we need to codegen, ensure that we emit all errors from
// `mir_drops_elaborated_and_const_checked` now, to avoid discovering
// them later during codegen.
if tcx.sess.opts.output_types.should_codegen()
- || tcx.hir().body_const_context(def_id).is_some()
+ || tcx.hir_body_const_context(def_id).is_some()
{
tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id);
}
});
});
sess.time("coroutine_obligations", || {
- tcx.hir().par_body_owners(|def_id| {
+ tcx.par_hir_body_owners(|def_id| {
if tcx.is_coroutine(def_id.to_def_id()) {
tcx.ensure_ok().mir_coroutine_witnesses(def_id);
tcx.ensure_ok().check_coroutine_obligations(
@@ -930,7 +931,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
// that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts.
if tcx.sess.opts.unstable_opts.validate_mir {
sess.time("ensuring_final_MIR_is_computable", || {
- tcx.hir().par_body_owners(|def_id| {
+ tcx.par_hir_body_owners(|def_id| {
tcx.instance_mir(ty::InstanceKind::Item(def_id.into()));
});
});
@@ -966,7 +967,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
tcx.ensure_ok().check_private_in_public(());
},
{
- tcx.hir().par_for_each_module(|module| {
+ tcx.par_hir_for_each_module(|module| {
tcx.ensure_ok().check_mod_deathness(module)
});
},
@@ -982,7 +983,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
},
{
sess.time("privacy_checking_modules", || {
- tcx.hir().par_for_each_module(|module| {
+ tcx.par_hir_for_each_module(|module| {
tcx.ensure_ok().check_mod_privacy(module);
});
});
@@ -1134,7 +1135,7 @@ fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit
// because that would require expanding this while in the middle of expansion, which needs to
// know the limit before expanding.
let _ = validate_and_find_value_str_builtin_attr(sym::recursion_limit, sess, krate_attrs);
- rustc_middle::middle::limits::get_recursion_limit(krate_attrs, sess)
+ crate::limits::get_recursion_limit(krate_attrs, sess)
}
/// Validate *all* occurrences of the given "[value-str]" built-in attribute and return the first find.
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index 82593dbc2b7a..00600abb5f1e 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -7,7 +7,7 @@ use rustc_span::sym;
fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option {
let mut decls = None;
- for id in tcx.hir().items() {
+ for id in tcx.hir_free_items() {
let attrs = tcx.hir().attrs(id.hir_id());
if attr::contains_name(attrs, sym::rustc_proc_macro_decls) {
decls = Some(id.owner_id.def_id);
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 480d97e377a4..dbe24c9cdf24 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -439,11 +439,11 @@ lint_invalid_crate_type_value = invalid `crate_type` value
.suggestion = did you mean
# FIXME: we should ordinalize $valid_up_to when we add support for doing so
-lint_invalid_from_utf8_checked = calls to `{$method}` with a invalid literal always return an error
+lint_invalid_from_utf8_checked = calls to `{$method}` with an invalid literal always return an error
.label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
# FIXME: we should ordinalize $valid_up_to when we add support for doing so
-lint_invalid_from_utf8_unchecked = calls to `{$method}` with a invalid literal are undefined behavior
+lint_invalid_from_utf8_unchecked = calls to `{$method}` with an invalid literal are undefined behavior
.label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be directly compared to itself
diff --git a/compiler/rustc_lint/src/async_closures.rs b/compiler/rustc_lint/src/async_closures.rs
index 5d40b8ab2eed..02fb22bf782e 100644
--- a/compiler/rustc_lint/src/async_closures.rs
+++ b/compiler/rustc_lint/src/async_closures.rs
@@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for AsyncClosureUsage {
return;
};
- let mut body = cx.tcx.hir().body(body).value;
+ let mut body = cx.tcx.hir_body(body).value;
// Only peel blocks that have no expressions.
while let hir::ExprKind::Block(&hir::Block { stmts: [], expr: Some(tail), .. }, None) =
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index ecd40a52e75f..e449f1106131 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1057,7 +1057,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
check_no_mangle_on_generic_fn(
no_mangle_attr,
Some(generics),
- cx.tcx.hir().get_generics(it.id.owner_id.def_id).unwrap(),
+ cx.tcx.hir_get_generics(it.id.owner_id.def_id).unwrap(),
it.span,
);
}
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index a67b404e6e16..c74158102c7a 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -928,7 +928,7 @@ impl<'tcx> LateContext<'tcx> {
while let hir::ExprKind::Path(ref qpath) = expr.kind
&& let Some(parent_node) = match self.qpath_res(qpath, expr.hir_id) {
Res::Local(hir_id) => Some(self.tcx.parent_hir_node(hir_id)),
- Res::Def(_, def_id) => self.tcx.hir().get_if_local(def_id),
+ Res::Def(_, def_id) => self.tcx.hir_get_if_local(def_id),
_ => None,
}
&& let Some(init) = match parent_node {
@@ -936,7 +936,7 @@ impl<'tcx> LateContext<'tcx> {
hir::Node::LetStmt(hir::LetStmt { init, .. }) => *init,
hir::Node::Item(item) => match item.kind {
hir::ItemKind::Const(.., body_id) | hir::ItemKind::Static(.., body_id) => {
- Some(self.tcx.hir().body(body_id).value)
+ Some(self.tcx.hir_body(body_id).value)
}
_ => None,
},
diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs
index bae9defa6870..59e38a882dde 100644
--- a/compiler/rustc_lint/src/default_could_be_derived.rs
+++ b/compiler/rustc_lint/src/default_could_be_derived.rs
@@ -76,10 +76,8 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
// We now know we have a manually written definition of a `::default()`.
- let hir = cx.tcx.hir();
-
let type_def_id = def.did();
- let body = hir.body(body_id);
+ let body = cx.tcx.hir_body(body_id);
// FIXME: evaluate bodies with statements and evaluate bindings to see if they would be
// derivable.
@@ -92,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
// Keep a mapping of field name to `hir::FieldDef` for every field in the type. We'll use
// these to check for things like checking whether it has a default or using its span for
// suggestions.
- let orig_fields = match hir.get_if_local(type_def_id) {
+ let orig_fields = match cx.tcx.hir_get_if_local(type_def_id) {
Some(hir::Node::Item(hir::Item {
kind:
hir::ItemKind::Struct(hir::VariantData::Struct { fields, recovered: _ }, _generics),
@@ -183,7 +181,7 @@ fn mk_lint(
if removed_all_fields {
let msg = "to avoid divergence in behavior between `Struct { .. }` and \
`::default()`, derive the `Default`";
- if let Some(hir::Node::Item(impl_)) = tcx.hir().get_if_local(impl_def_id) {
+ if let Some(hir::Node::Item(impl_)) = tcx.hir_get_if_local(impl_def_id) {
diag.multipart_suggestion_verbose(
msg,
vec![
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index 0a5c52d65ec9..757fc1f58bd5 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -155,7 +155,7 @@ fn suggest_question_mark<'tcx>(
// Check that the function/closure/constant we are in has a `Result` type.
// Otherwise suggesting using `?` may not be a good idea.
{
- let ty = cx.typeck_results().expr_ty(cx.tcx.hir().body(body_id).value);
+ let ty = cx.typeck_results().expr_ty(cx.tcx.hir_body(body_id).value);
let ty::Adt(ret_adt, ..) = ty.kind() else { return false };
if !cx.tcx.is_diagnostic_item(sym::Result, ret_adt.did()) {
return false;
@@ -166,7 +166,7 @@ fn suggest_question_mark<'tcx>(
let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env());
let ocx = ObligationCtxt::new(&infcx);
- let body_def_id = cx.tcx.hir().body_owner_def_id(body_id);
+ let body_def_id = cx.tcx.hir_body_owner_def_id(body_id);
let cause =
ObligationCause::new(span, body_def_id, rustc_infer::traits::ObligationCauseCode::Misc);
diff --git a/compiler/rustc_lint/src/invalid_from_utf8.rs b/compiler/rustc_lint/src/invalid_from_utf8.rs
index 0081374922e6..11eb079ddc09 100644
--- a/compiler/rustc_lint/src/invalid_from_utf8.rs
+++ b/compiler/rustc_lint/src/invalid_from_utf8.rs
@@ -70,12 +70,20 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
sym::str_from_utf8_mut,
sym::str_from_utf8_unchecked,
sym::str_from_utf8_unchecked_mut,
+ sym::str_inherent_from_utf8,
+ sym::str_inherent_from_utf8_mut,
+ sym::str_inherent_from_utf8_unchecked,
+ sym::str_inherent_from_utf8_unchecked_mut,
]
.contains(&diag_item)
{
let lint = |label, utf8_error: Utf8Error| {
let method = diag_item.as_str().strip_prefix("str_").unwrap();
- let method = format!("std::str::{method}");
+ let method = if let Some(method) = method.strip_prefix("inherent_") {
+ format!("str::{method}")
+ } else {
+ format!("std::str::{method}")
+ };
let valid_up_to = utf8_error.valid_up_to();
let is_unchecked_variant = diag_item.as_str().contains("unchecked");
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index 3ee908ba9bf4..d22515d62d60 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -84,8 +84,8 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
/// Because lints are scoped lexically, we want to walk nested
/// items in the context of the outer item, so enable
/// deep-walking.
- fn nested_visit_map(&mut self) -> Self::Map {
- self.context.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.context.tcx
}
fn visit_nested_body(&mut self, body_id: hir::BodyId) {
@@ -99,7 +99,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
self.context.cached_typeck_results.set(None);
}
- let body = self.context.tcx.hir().body(body_id);
+ let body = self.context.tcx.hir_body(body_id);
self.visit_body(body);
self.context.enclosing_body = old_enclosing_body;
@@ -191,7 +191,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
// in order for `check_fn` to be able to use them.
let old_enclosing_body = self.context.enclosing_body.replace(body_id);
let old_cached_typeck_results = self.context.cached_typeck_results.take();
- let body = self.context.tcx.hir().body(body_id);
+ let body = self.context.tcx.hir_body(body_id);
lint_callback!(self, check_fn, fk, decl, body, span, id);
hir_visit::walk_fn(self, fk, decl, body_id, id);
self.context.enclosing_body = old_enclosing_body;
@@ -379,7 +379,7 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(
) {
let mut cx = LateContextAndPass { context, pass };
- let (module, _span, hir_id) = tcx.hir().get_module(module_def_id);
+ let (module, _span, hir_id) = tcx.hir_get_module(module_def_id);
cx.with_lint_attrs(hir_id, |cx| {
// There is no module lint that will have the crate itself as an item, so check it here.
@@ -445,7 +445,7 @@ fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
// Since the root module isn't visited as an item (because it isn't an
// item), warn for it here.
lint_callback!(cx, check_crate,);
- tcx.hir().walk_toplevel_module(cx);
+ tcx.hir_walk_toplevel_module(cx);
lint_callback!(cx, check_crate_post,);
})
}
@@ -462,7 +462,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
|| {
tcx.sess.time("module_lints", || {
// Run per-module lints
- tcx.hir().par_for_each_module(|module| tcx.ensure_ok().lint_mod(module));
+ tcx.par_hir_for_each_module(|module| tcx.ensure_ok().lint_mod(module));
});
},
);
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 5a4ed68440a3..4ede9b440879 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -144,7 +144,7 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet {
let mut visitor = LintLevelMaximum { tcx, dont_need_to_run };
visitor.process_opts();
- tcx.hir().walk_attributes(&mut visitor);
+ tcx.hir_walk_attributes(&mut visitor);
visitor.dont_need_to_run
}
@@ -270,8 +270,8 @@ impl<'tcx> LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {
impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {
type NestedFilter = nested_filter::OnlyBodies;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.provider.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.provider.tcx
}
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
@@ -365,8 +365,8 @@ impl<'tcx> LintLevelMaximum<'tcx> {
impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> {
type NestedFilter = nested_filter::All;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
/// FIXME(blyxyas): In a future revision, we should also graph #![allow]s,
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index a6b2384f2d7b..7eb11f9e6087 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -22,6 +22,7 @@
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Program.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Target/TargetMachine.h"
@@ -472,16 +473,19 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
assert(ArgsCstrBuff[ArgsCstrBuffLen - 1] == '\0');
auto Arg0 = std::string(ArgsCstrBuff);
buffer_offset = Arg0.size() + 1;
- auto ArgsCppStr = std::string(ArgsCstrBuff + buffer_offset,
- ArgsCstrBuffLen - buffer_offset);
- auto i = 0;
- while (i != std::string::npos) {
- i = ArgsCppStr.find('\0', i + 1);
- if (i != std::string::npos)
- ArgsCppStr.replace(i, 1, " ");
+
+ std::string CommandlineArgs;
+ raw_string_ostream OS(CommandlineArgs);
+ ListSeparator LS(" ");
+ for (StringRef Arg : split(StringRef(ArgsCstrBuff + buffer_offset,
+ ArgsCstrBuffLen - buffer_offset),
+ '\0')) {
+ OS << LS;
+ sys::printArg(OS, Arg, /*Quote=*/true);
}
+ OS.flush();
Options.MCOptions.Argv0 = Arg0;
- Options.MCOptions.CommandlineArgs = ArgsCppStr;
+ Options.MCOptions.CommandlineArgs = CommandlineArgs;
#else
int buffer_offset = 0;
assert(ArgsCstrBuff[ArgsCstrBuffLen - 1] == '\0');
diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs
index 154eb684f119..24689ea61d03 100644
--- a/compiler/rustc_metadata/src/foreign_modules.rs
+++ b/compiler/rustc_metadata/src/foreign_modules.rs
@@ -10,13 +10,13 @@ pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> FxIndexMap EncodeContext<'a, 'tcx> {
let target_modifiers = stat!("target-modifiers", || self.encode_target_modifiers());
let root = stat!("final", || {
- let attrs = tcx.hir().krate_attrs();
+ let attrs = tcx.hir_krate_attrs();
self.lazy(CrateRoot {
header: CrateHeader {
name: tcx.crate_name(LOCAL_CRATE),
@@ -1763,7 +1763,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
if should_encode_const(tcx.def_kind(def_id)) {
let qualifs = tcx.mir_const_qualif(def_id);
record!(self.tables.mir_const_qualif[def_id.to_def_id()] <- qualifs);
- let body = tcx.hir().maybe_body_owned_by(def_id);
+ let body = tcx.hir_maybe_body_owned_by(def_id);
if let Some(body) = body {
let const_data = rendered_const(self.tcx, &body, def_id);
record!(self.tables.rendered_const[def_id.to_def_id()] <- const_data);
@@ -1940,7 +1940,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
bug!("Unknown proc-macro type for item {:?}", id);
};
- let mut def_key = self.tcx.hir().def_key(id);
+ let mut def_key = self.tcx.hir_def_key(id);
def_key.disambiguated_data.data = DefPathData::MacroNs(name);
let def_id = id.to_def_id();
@@ -2076,7 +2076,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let mut trait_impls: FxIndexMap)>> =
FxIndexMap::default();
- for id in tcx.hir().items() {
+ for id in tcx.hir_free_items() {
let DefKind::Impl { of_trait } = tcx.def_kind(id.owner_id) else {
continue;
};
@@ -2410,7 +2410,6 @@ pub(crate) fn provide(providers: &mut Providers) {
/// use a different method for pretty-printing. Ideally this function
/// should only ever be used as a fallback.
pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body<'_>, def_id: LocalDefId) -> String {
- let hir = tcx.hir();
let value = body.value;
#[derive(PartialEq, Eq)]
@@ -2467,7 +2466,7 @@ pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body<'_>, def_id: Loc
// Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and
// other formatting artifacts.
- Literal | Simple => id_to_string(&hir, body.id().hir_id),
+ Literal | Simple => id_to_string(&tcx, body.id().hir_id),
// FIXME: Omit the curly braces if the enclosing expression is an array literal
// with a repeated element (an `ExprKind::Repeat`) as in such case it
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index de722e62043c..1b6a174c0932 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -22,6 +22,7 @@ rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_graphviz = { path = "../rustc_graphviz" }
+rustc_hashes = { path = "../rustc_hashes" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_index = { path = "../rustc_index" }
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 09c16222be19..0b3c0be1a4e1 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -37,9 +37,6 @@ middle_autodiff_unsafe_inner_const_ref = reading from a `Duplicated` const {$ty}
middle_bounds_check =
index out of bounds: the length is {$len} but the index is {$index}
-middle_cannot_be_normalized =
- unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
-
middle_conflict_types =
this expression supplies two conflicting concrete types for the same opaque type
@@ -52,9 +49,6 @@ middle_const_eval_non_int =
middle_const_not_used_in_type_alias =
const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-middle_cycle =
- a cycle occurred during layout computation
-
middle_deprecated = use of deprecated {$kind} `{$path}`{$has_note ->
[true] : {$note}
*[other] {""}
@@ -78,12 +72,22 @@ middle_erroneous_constant = erroneous constant encountered
middle_failed_writing_file =
failed to write file {$path}: {$error}"
+middle_layout_cycle =
+ a cycle occurred during layout computation
+
+middle_layout_normalization_failure =
+ unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
+
middle_layout_references_error =
the type has an unknown layout
-middle_limit_invalid =
- `limit` must be a non-negative integer
- .label = {$error_str}
+middle_layout_size_overflow =
+ values of the type `{$ty}` are too big for the target architecture
+
+middle_layout_too_generic = the type `{$ty}` does not have a fixed layout
+
+middle_layout_unknown =
+ the type `{$ty}` has an unknown layout
middle_opaque_hidden_type_mismatch =
concrete type differs from previous defining opaque type use
@@ -102,16 +106,8 @@ middle_strict_coherence_needs_negative_coherence =
to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
.label = due to this attribute
-middle_too_generic = `{$ty}` does not have a fixed size
-
middle_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
-middle_unknown_layout =
- the type `{$ty}` has an unknown layout
-
middle_unsupported_union = we don't support unions yet: '{$ty_name}'
-middle_values_too_big =
- values of the type `{$ty}` are too big for the target architecture
-
middle_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 91b18295b43b..be8a3403ba95 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -67,16 +67,6 @@ pub enum TypeMismatchReason {
},
}
-#[derive(Diagnostic)]
-#[diag(middle_limit_invalid)]
-pub(crate) struct LimitInvalid<'a> {
- #[primary_span]
- pub span: Span,
- #[label]
- pub value_span: Span,
- pub error_str: &'a str,
-}
-
#[derive(Diagnostic)]
#[diag(middle_recursion_limit_reached)]
#[help]
@@ -142,19 +132,19 @@ impl fmt::Debug for CustomSubdiagnostic<'_> {
#[derive(Diagnostic)]
pub enum LayoutError<'tcx> {
- #[diag(middle_unknown_layout)]
+ #[diag(middle_layout_unknown)]
Unknown { ty: Ty<'tcx> },
- #[diag(middle_too_generic)]
+ #[diag(middle_layout_too_generic)]
TooGeneric { ty: Ty<'tcx> },
- #[diag(middle_values_too_big)]
+ #[diag(middle_layout_size_overflow)]
Overflow { ty: Ty<'tcx> },
- #[diag(middle_cannot_be_normalized)]
+ #[diag(middle_layout_normalization_failure)]
NormalizationFailure { ty: Ty<'tcx>, failure_ty: String },
- #[diag(middle_cycle)]
+ #[diag(middle_layout_cycle)]
Cycle,
#[diag(middle_layout_references_error)]
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map.rs
similarity index 85%
rename from compiler/rustc_middle/src/hir/map/mod.rs
rename to compiler/rustc_middle/src/hir/map.rs
index 83c7bb0f52f4..3436c2f372f4 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -93,7 +93,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> {
return None;
}
- let parent_id = self.map.def_key(self.current_id.owner.def_id).parent;
+ let parent_id = self.map.tcx.hir_def_key(self.current_id.owner.def_id).parent;
let parent_id = parent_id.map_or(CRATE_OWNER_ID, |local_def_index| {
let def_id = LocalDefId { local_def_index };
self.map.tcx.local_def_id_to_hir_id(def_id).owner
@@ -164,131 +164,127 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn parent_hir_node(self, hir_id: HirId) -> Node<'tcx> {
self.hir_node(self.parent_hir_id(hir_id))
}
-}
-
-impl<'hir> Map<'hir> {
- #[inline]
- pub fn krate(self) -> &'hir Crate<'hir> {
- self.tcx.hir_crate(())
- }
#[inline]
- pub fn root_module(self) -> &'hir Mod<'hir> {
- match self.tcx.hir_owner_node(CRATE_OWNER_ID) {
+ pub fn hir_root_module(self) -> &'tcx Mod<'tcx> {
+ match self.hir_owner_node(CRATE_OWNER_ID) {
OwnerNode::Crate(item) => item,
_ => bug!(),
}
}
#[inline]
- pub fn items(self) -> impl Iterator
- + 'hir {
- self.tcx.hir_crate_items(()).free_items.iter().copied()
+ pub fn hir_free_items(self) -> impl Iterator
- + 'tcx {
+ self.hir_crate_items(()).free_items.iter().copied()
}
#[inline]
- pub fn module_items(self, module: LocalModDefId) -> impl Iterator
- + 'hir {
- self.tcx.hir_module_items(module).free_items()
+ pub fn hir_module_free_items(
+ self,
+ module: LocalModDefId,
+ ) -> impl Iterator
- + 'tcx {
+ self.hir_module_items(module).free_items()
}
- pub fn def_key(self, def_id: LocalDefId) -> DefKey {
+ pub fn hir_def_key(self, def_id: LocalDefId) -> DefKey {
// Accessing the DefKey is ok, since it is part of DefPathHash.
- self.tcx.definitions_untracked().def_key(def_id)
+ self.definitions_untracked().def_key(def_id)
}
- pub fn def_path(self, def_id: LocalDefId) -> DefPath {
+ pub fn hir_def_path(self, def_id: LocalDefId) -> DefPath {
// Accessing the DefPath is ok, since it is part of DefPathHash.
- self.tcx.definitions_untracked().def_path(def_id)
+ self.definitions_untracked().def_path(def_id)
}
#[inline]
- pub fn def_path_hash(self, def_id: LocalDefId) -> DefPathHash {
+ pub fn hir_def_path_hash(self, def_id: LocalDefId) -> DefPathHash {
// Accessing the DefPathHash is ok, it is incr. comp. stable.
- self.tcx.definitions_untracked().def_path_hash(def_id)
+ self.definitions_untracked().def_path_hash(def_id)
}
- pub fn get_if_local(self, id: DefId) -> Option> {
- id.as_local().map(|id| self.tcx.hir_node_by_def_id(id))
+ pub fn hir_get_if_local(self, id: DefId) -> Option> {
+ id.as_local().map(|id| self.hir_node_by_def_id(id))
}
- pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> {
- self.tcx.opt_hir_owner_node(id)?.generics()
+ pub fn hir_get_generics(self, id: LocalDefId) -> Option<&'tcx Generics<'tcx>> {
+ self.opt_hir_owner_node(id)?.generics()
}
- pub fn item(self, id: ItemId) -> &'hir Item<'hir> {
- self.tcx.hir_owner_node(id.owner_id).expect_item()
+ pub fn hir_item(self, id: ItemId) -> &'tcx Item<'tcx> {
+ self.hir_owner_node(id.owner_id).expect_item()
}
- pub fn trait_item(self, id: TraitItemId) -> &'hir TraitItem<'hir> {
- self.tcx.hir_owner_node(id.owner_id).expect_trait_item()
+ pub fn hir_trait_item(self, id: TraitItemId) -> &'tcx TraitItem<'tcx> {
+ self.hir_owner_node(id.owner_id).expect_trait_item()
}
- pub fn impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> {
- self.tcx.hir_owner_node(id.owner_id).expect_impl_item()
+ pub fn hir_impl_item(self, id: ImplItemId) -> &'tcx ImplItem<'tcx> {
+ self.hir_owner_node(id.owner_id).expect_impl_item()
}
- pub fn foreign_item(self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
- self.tcx.hir_owner_node(id.owner_id).expect_foreign_item()
+ pub fn hir_foreign_item(self, id: ForeignItemId) -> &'tcx ForeignItem<'tcx> {
+ self.hir_owner_node(id.owner_id).expect_foreign_item()
}
- pub fn body(self, id: BodyId) -> &'hir Body<'hir> {
- self.tcx.hir_owner_nodes(id.hir_id.owner).bodies[&id.hir_id.local_id]
+ pub fn hir_body(self, id: BodyId) -> &'tcx Body<'tcx> {
+ self.hir_owner_nodes(id.hir_id.owner).bodies[&id.hir_id.local_id]
}
#[track_caller]
- pub fn fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
- self.tcx.hir_node(hir_id).fn_decl()
+ pub fn hir_fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'tcx FnDecl<'tcx>> {
+ self.hir_node(hir_id).fn_decl()
}
#[track_caller]
- pub fn fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> {
- self.tcx.hir_node(hir_id).fn_sig()
+ pub fn hir_fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'tcx FnSig<'tcx>> {
+ self.hir_node(hir_id).fn_sig()
}
#[track_caller]
- pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId {
- for (_, node) in self.parent_iter(hir_id) {
+ pub fn hir_enclosing_body_owner(self, hir_id: HirId) -> LocalDefId {
+ for (_, node) in self.hir().parent_iter(hir_id) {
if let Some((def_id, _)) = node.associated_body() {
return def_id;
}
}
- bug!("no `enclosing_body_owner` for hir_id `{}`", hir_id);
+ bug!("no `hir_enclosing_body_owner` for hir_id `{}`", hir_id);
}
/// Returns the `HirId` that corresponds to the definition of
/// which this is the body of, i.e., a `fn`, `const` or `static`
/// item (possibly associated), a closure, or a `hir::AnonConst`.
- pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId {
- let parent = self.tcx.parent_hir_id(hir_id);
- assert_eq!(self.tcx.hir_node(parent).body_id().unwrap().hir_id, hir_id, "{hir_id:?}");
+ pub fn hir_body_owner(self, BodyId { hir_id }: BodyId) -> HirId {
+ let parent = self.parent_hir_id(hir_id);
+ assert_eq!(self.hir_node(parent).body_id().unwrap().hir_id, hir_id, "{hir_id:?}");
parent
}
- pub fn body_owner_def_id(self, BodyId { hir_id }: BodyId) -> LocalDefId {
- self.tcx.parent_hir_node(hir_id).associated_body().unwrap().0
+ pub fn hir_body_owner_def_id(self, BodyId { hir_id }: BodyId) -> LocalDefId {
+ self.parent_hir_node(hir_id).associated_body().unwrap().0
}
/// Given a `LocalDefId`, returns the `BodyId` associated with it,
/// if the node is a body owner, otherwise returns `None`.
- pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<&'hir Body<'hir>> {
- Some(self.body(self.tcx.hir_node_by_def_id(id).body_id()?))
+ pub fn hir_maybe_body_owned_by(self, id: LocalDefId) -> Option<&'tcx Body<'tcx>> {
+ Some(self.hir_body(self.hir_node_by_def_id(id).body_id()?))
}
/// Given a body owner's id, returns the `BodyId` associated with it.
#[track_caller]
- pub fn body_owned_by(self, id: LocalDefId) -> &'hir Body<'hir> {
- self.maybe_body_owned_by(id).unwrap_or_else(|| {
- let hir_id = self.tcx.local_def_id_to_hir_id(id);
+ pub fn hir_body_owned_by(self, id: LocalDefId) -> &'tcx Body<'tcx> {
+ self.hir_maybe_body_owned_by(id).unwrap_or_else(|| {
+ let hir_id = self.local_def_id_to_hir_id(id);
span_bug!(
- self.span(hir_id),
+ self.hir().span(hir_id),
"body_owned_by: {} has no associated body",
- self.node_to_string(hir_id)
+ self.hir().node_to_string(hir_id)
);
})
}
- pub fn body_param_names(self, id: BodyId) -> impl Iterator
- + 'hir {
- self.body(id).params.iter().map(|arg| match arg.pat.kind {
+ pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator
- + 'tcx {
+ self.hir_body(id).params.iter().map(|arg| match arg.pat.kind {
PatKind::Binding(_, _, ident, _) => ident,
_ => Ident::empty(),
})
@@ -297,9 +293,9 @@ impl<'hir> Map<'hir> {
/// Returns the `BodyOwnerKind` of this `LocalDefId`.
///
/// Panics if `LocalDefId` does not have an associated body.
- pub fn body_owner_kind(self, def_id: impl Into) -> BodyOwnerKind {
+ pub fn hir_body_owner_kind(self, def_id: impl Into) -> BodyOwnerKind {
let def_id = def_id.into();
- match self.tcx.def_kind(def_id) {
+ match self.def_kind(def_id) {
DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
BodyOwnerKind::Const { inline: false }
}
@@ -320,17 +316,17 @@ impl<'hir> Map<'hir> {
/// This should only be used for determining the context of a body, a return
/// value of `Some` does not always suggest that the owner of the body is `const`,
/// just that it has to be checked as if it were.
- pub fn body_const_context(self, def_id: impl Into) -> Option {
+ pub fn hir_body_const_context(self, def_id: impl Into) -> Option {
let def_id = def_id.into();
- let ccx = match self.body_owner_kind(def_id) {
+ let ccx = match self.hir_body_owner_kind(def_id) {
BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
BodyOwnerKind::Static(mutability) => ConstContext::Static(mutability),
- BodyOwnerKind::Fn if self.tcx.is_constructor(def_id) => return None,
- BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn(def_id) => {
+ BodyOwnerKind::Fn if self.is_constructor(def_id) => return None,
+ BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.is_const_fn(def_id) => {
ConstContext::ConstFn
}
- BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id) => ConstContext::ConstFn,
+ BodyOwnerKind::Fn if self.is_const_default_method(def_id) => ConstContext::ConstFn,
BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
};
@@ -341,55 +337,55 @@ impl<'hir> Map<'hir> {
/// crate. If you would prefer to iterate over the bodies
/// themselves, you can do `self.hir().krate().body_ids.iter()`.
#[inline]
- pub fn body_owners(self) -> impl Iterator
- + 'hir {
- self.tcx.hir_crate_items(()).body_owners.iter().copied()
+ pub fn hir_body_owners(self) -> impl Iterator
- + 'tcx {
+ self.hir_crate_items(()).body_owners.iter().copied()
}
#[inline]
- pub fn par_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
- par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id));
+ pub fn par_hir_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
+ par_for_each_in(&self.hir_crate_items(()).body_owners[..], |&def_id| f(def_id));
}
- pub fn ty_param_owner(self, def_id: LocalDefId) -> LocalDefId {
- let def_kind = self.tcx.def_kind(def_id);
+ pub fn hir_ty_param_owner(self, def_id: LocalDefId) -> LocalDefId {
+ let def_kind = self.def_kind(def_id);
match def_kind {
DefKind::Trait | DefKind::TraitAlias => def_id,
DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
- self.tcx.local_parent(def_id)
+ self.local_parent(def_id)
}
_ => bug!("ty_param_owner: {:?} is a {:?} not a type parameter", def_id, def_kind),
}
}
- pub fn ty_param_name(self, def_id: LocalDefId) -> Symbol {
- let def_kind = self.tcx.def_kind(def_id);
+ pub fn hir_ty_param_name(self, def_id: LocalDefId) -> Symbol {
+ let def_kind = self.def_kind(def_id);
match def_kind {
DefKind::Trait | DefKind::TraitAlias => kw::SelfUpper,
DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
- self.tcx.item_name(def_id.to_def_id())
+ self.item_name(def_id.to_def_id())
}
_ => bug!("ty_param_name: {:?} is a {:?} not a type parameter", def_id, def_kind),
}
}
- pub fn trait_impls(self, trait_did: DefId) -> &'hir [LocalDefId] {
- self.tcx.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..])
+ pub fn hir_trait_impls(self, trait_did: DefId) -> &'tcx [LocalDefId] {
+ self.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..])
}
/// Gets the attributes on the crate. This is preferable to
/// invoking `krate.attrs` because it registers a tighter
/// dep-graph access.
- pub fn krate_attrs(self) -> &'hir [Attribute] {
- self.attrs(CRATE_HIR_ID)
+ pub fn hir_krate_attrs(self) -> &'tcx [Attribute] {
+ self.hir().attrs(CRATE_HIR_ID)
}
- pub fn rustc_coherence_is_core(self) -> bool {
- self.krate_attrs().iter().any(|attr| attr.has_name(sym::rustc_coherence_is_core))
+ pub fn hir_rustc_coherence_is_core(self) -> bool {
+ self.hir_krate_attrs().iter().any(|attr| attr.has_name(sym::rustc_coherence_is_core))
}
- pub fn get_module(self, module: LocalModDefId) -> (&'hir Mod<'hir>, Span, HirId) {
+ pub fn hir_get_module(self, module: LocalModDefId) -> (&'tcx Mod<'tcx>, Span, HirId) {
let hir_id = HirId::make_owner(module.to_local_def_id());
- match self.tcx.hir_owner_node(hir_id.owner) {
+ match self.hir_owner_node(hir_id.owner) {
OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. }) => (m, span, hir_id),
OwnerNode::Crate(item) => (item, item.spans.inner_span, hir_id),
node => panic!("not a module: {node:?}"),
@@ -397,20 +393,20 @@ impl<'hir> Map<'hir> {
}
/// Walks the contents of the local crate. See also `visit_all_item_likes_in_crate`.
- pub fn walk_toplevel_module(self, visitor: &mut V) -> V::Result
+ pub fn hir_walk_toplevel_module(self, visitor: &mut V) -> V::Result
where
- V: Visitor<'hir>,
+ V: Visitor<'tcx>,
{
- let (top_mod, span, hir_id) = self.get_module(LocalModDefId::CRATE_DEF_ID);
+ let (top_mod, span, hir_id) = self.hir_get_module(LocalModDefId::CRATE_DEF_ID);
visitor.visit_mod(top_mod, span, hir_id)
}
/// Walks the attributes in a crate.
- pub fn walk_attributes(self, visitor: &mut V) -> V::Result
+ pub fn hir_walk_attributes(self, visitor: &mut V) -> V::Result
where
- V: Visitor<'hir>,
+ V: Visitor<'tcx>,
{
- let krate = self.krate();
+ let krate = self.hir_crate(());
for info in krate.owners.iter() {
if let MaybeOwner::Owner(info) = info {
for attrs in info.attrs.map.values() {
@@ -424,73 +420,87 @@ impl<'hir> Map<'hir> {
/// Visits all item-likes in the crate in some deterministic (but unspecified) order. If you
/// need to process every item-like, and don't care about visiting nested items in a particular
/// order then this method is the best choice. If you do care about this nesting, you should
- /// use the `tcx.hir().walk_toplevel_module`.
+ /// use the `tcx.hir_walk_toplevel_module`.
///
/// Note that this function will access HIR for all the item-likes in the crate. If you only
/// need to access some of them, it is usually better to manually loop on the iterators
/// provided by `tcx.hir_crate_items(())`.
///
/// Please see the notes in `intravisit.rs` for more information.
- pub fn visit_all_item_likes_in_crate(self, visitor: &mut V) -> V::Result
+ pub fn hir_visit_all_item_likes_in_crate(self, visitor: &mut V) -> V::Result
where
- V: Visitor<'hir>,
+ V: Visitor<'tcx>,
{
- let krate = self.tcx.hir_crate_items(());
- walk_list!(visitor, visit_item, krate.free_items().map(|id| self.item(id)));
- walk_list!(visitor, visit_trait_item, krate.trait_items().map(|id| self.trait_item(id)));
- walk_list!(visitor, visit_impl_item, krate.impl_items().map(|id| self.impl_item(id)));
+ let krate = self.hir_crate_items(());
+ walk_list!(visitor, visit_item, krate.free_items().map(|id| self.hir_item(id)));
+ walk_list!(
+ visitor,
+ visit_trait_item,
+ krate.trait_items().map(|id| self.hir_trait_item(id))
+ );
+ walk_list!(visitor, visit_impl_item, krate.impl_items().map(|id| self.hir_impl_item(id)));
walk_list!(
visitor,
visit_foreign_item,
- krate.foreign_items().map(|id| self.foreign_item(id))
+ krate.foreign_items().map(|id| self.hir_foreign_item(id))
);
V::Result::output()
}
/// This method is the equivalent of `visit_all_item_likes_in_crate` but restricted to
/// item-likes in a single module.
- pub fn visit_item_likes_in_module(self, module: LocalModDefId, visitor: &mut V) -> V::Result
+ pub fn hir_visit_item_likes_in_module(
+ self,
+ module: LocalModDefId,
+ visitor: &mut V,
+ ) -> V::Result
where
- V: Visitor<'hir>,
+ V: Visitor<'tcx>,
{
- let module = self.tcx.hir_module_items(module);
- walk_list!(visitor, visit_item, module.free_items().map(|id| self.item(id)));
- walk_list!(visitor, visit_trait_item, module.trait_items().map(|id| self.trait_item(id)));
- walk_list!(visitor, visit_impl_item, module.impl_items().map(|id| self.impl_item(id)));
+ let module = self.hir_module_items(module);
+ walk_list!(visitor, visit_item, module.free_items().map(|id| self.hir_item(id)));
+ walk_list!(
+ visitor,
+ visit_trait_item,
+ module.trait_items().map(|id| self.hir_trait_item(id))
+ );
+ walk_list!(visitor, visit_impl_item, module.impl_items().map(|id| self.hir_impl_item(id)));
walk_list!(
visitor,
visit_foreign_item,
- module.foreign_items().map(|id| self.foreign_item(id))
+ module.foreign_items().map(|id| self.hir_foreign_item(id))
);
V::Result::output()
}
- pub fn for_each_module(self, mut f: impl FnMut(LocalModDefId)) {
- let crate_items = self.tcx.hir_crate_items(());
+ pub fn hir_for_each_module(self, mut f: impl FnMut(LocalModDefId)) {
+ let crate_items = self.hir_crate_items(());
for module in crate_items.submodules.iter() {
f(LocalModDefId::new_unchecked(module.def_id))
}
}
#[inline]
- pub fn par_for_each_module(self, f: impl Fn(LocalModDefId) + DynSend + DynSync) {
- let crate_items = self.tcx.hir_crate_items(());
+ pub fn par_hir_for_each_module(self, f: impl Fn(LocalModDefId) + DynSend + DynSync) {
+ let crate_items = self.hir_crate_items(());
par_for_each_in(&crate_items.submodules[..], |module| {
f(LocalModDefId::new_unchecked(module.def_id))
})
}
#[inline]
- pub fn try_par_for_each_module(
+ pub fn try_par_hir_for_each_module(
self,
f: impl Fn(LocalModDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
) -> Result<(), ErrorGuaranteed> {
- let crate_items = self.tcx.hir_crate_items(());
+ let crate_items = self.hir_crate_items(());
try_par_for_each_in(&crate_items.submodules[..], |module| {
f(LocalModDefId::new_unchecked(module.def_id))
})
}
+}
+impl<'hir> Map<'hir> {
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
/// until the crate root is reached. Prefer this over your own loop using `parent_id`.
#[inline]
@@ -526,7 +536,7 @@ impl<'hir> Map<'hir> {
/// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
/// Used exclusively for diagnostics, to avoid suggestion function calls.
pub fn is_inside_const_context(self, hir_id: HirId) -> bool {
- self.body_const_context(self.enclosing_body_owner(hir_id)).is_some()
+ self.tcx.hir_body_const_context(self.tcx.hir_enclosing_body_owner(hir_id)).is_some()
}
/// Retrieves the `HirId` for `id`'s enclosing function *if* the `id` block or return is
@@ -552,7 +562,8 @@ impl<'hir> Map<'hir> {
/// }
/// ```
pub fn get_fn_id_for_return_block(self, id: HirId) -> Option {
- let enclosing_body_owner = self.tcx.local_def_id_to_hir_id(self.enclosing_body_owner(id));
+ let enclosing_body_owner =
+ self.tcx.local_def_id_to_hir_id(self.tcx.hir_enclosing_body_owner(id));
// Return `None` if the `id` expression is not the returned value of the enclosing body
let mut iter = [id].into_iter().chain(self.parent_id_iter(id)).peekable();
@@ -921,7 +932,7 @@ impl<'hir> Map<'hir> {
Node::Variant(variant) => variant.span,
Node::Field(field) => field.span,
Node::AnonConst(constant) => constant.span,
- Node::ConstBlock(constant) => self.body(constant.body).value.span,
+ Node::ConstBlock(constant) => self.tcx.hir_body(constant.body).value.span,
Node::ConstArg(const_arg) => const_arg.span(),
Node::Expr(expr) => expr.span,
Node::ExprField(field) => field.span,
@@ -1014,39 +1025,35 @@ impl<'hir> Map<'hir> {
}
}
-impl<'hir> intravisit::Map<'hir> for Map<'hir> {
- fn hir_node(&self, hir_id: HirId) -> Node<'hir> {
- self.tcx.hir_node(hir_id)
+impl<'tcx> intravisit::HirTyCtxt<'tcx> for TyCtxt<'tcx> {
+ fn hir_node(&self, hir_id: HirId) -> Node<'tcx> {
+ (*self).hir_node(hir_id)
}
- fn hir_node_by_def_id(&self, def_id: LocalDefId) -> Node<'hir> {
- self.tcx.hir_node_by_def_id(def_id)
+ fn hir_body(&self, id: BodyId) -> &'tcx Body<'tcx> {
+ (*self).hir_body(id)
}
- fn body(&self, id: BodyId) -> &'hir Body<'hir> {
- (*self).body(id)
+ fn hir_item(&self, id: ItemId) -> &'tcx Item<'tcx> {
+ (*self).hir_item(id)
}
- fn item(&self, id: ItemId) -> &'hir Item<'hir> {
- (*self).item(id)
+ fn hir_trait_item(&self, id: TraitItemId) -> &'tcx TraitItem<'tcx> {
+ (*self).hir_trait_item(id)
}
- fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
- (*self).trait_item(id)
+ fn hir_impl_item(&self, id: ImplItemId) -> &'tcx ImplItem<'tcx> {
+ (*self).hir_impl_item(id)
}
- fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
- (*self).impl_item(id)
- }
-
- fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
- (*self).foreign_item(id)
+ fn hir_foreign_item(&self, id: ForeignItemId) -> &'tcx ForeignItem<'tcx> {
+ (*self).hir_foreign_item(id)
}
}
impl<'tcx> pprust_hir::PpAnn for TyCtxt<'tcx> {
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
- pprust_hir::PpAnn::nested(&(&self.hir() as &dyn intravisit::Map<'_>), state, nested)
+ pprust_hir::PpAnn::nested(&(self as &dyn intravisit::HirTyCtxt<'_>), state, nested)
}
}
@@ -1239,7 +1246,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> ModuleItems {
let mut collector = ItemCollector::new(tcx, false);
- let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id);
+ let (hir_mod, span, hir_id) = tcx.hir_get_module(module_id);
collector.visit_mod(hir_mod, span, hir_id);
let ItemCollector {
@@ -1272,7 +1279,7 @@ pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems {
// module item (the former starts at the crate root) but only
// the former needs to collect it. ItemCollector does not do this for us.
collector.submodules.push(CRATE_OWNER_ID);
- tcx.hir().walk_toplevel_module(&mut collector);
+ tcx.hir_walk_toplevel_module(&mut collector);
let ItemCollector {
submodules,
@@ -1333,8 +1340,8 @@ impl<'tcx> ItemCollector<'tcx> {
impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
type NestedFilter = nested_filter::All;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_item(&mut self, item: &'hir Item<'hir>) {
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 0d2acf96d08f..2a201e230155 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -213,7 +213,7 @@ pub fn provide(providers: &mut Providers) {
providers.fn_arg_names = |tcx, def_id| {
let hir = tcx.hir();
if let Some(body_id) = tcx.hir_node_by_def_id(def_id).body_id() {
- tcx.arena.alloc_from_iter(hir.body_param_names(body_id))
+ tcx.arena.alloc_from_iter(tcx.hir_body_param_names(body_id))
} else if let Node::TraitItem(&TraitItem {
kind: TraitItemKind::Fn(_, TraitFn::Required(idents)),
..
diff --git a/compiler/rustc_middle/src/hir/nested_filter.rs b/compiler/rustc_middle/src/hir/nested_filter.rs
index adbe81bb22c7..e18c28a8eac0 100644
--- a/compiler/rustc_middle/src/hir/nested_filter.rs
+++ b/compiler/rustc_middle/src/hir/nested_filter.rs
@@ -1,5 +1,7 @@
use rustc_hir::intravisit::nested_filter::NestedFilter;
+use crate::ty::TyCtxt;
+
/// Do not visit nested item-like things, but visit nested things
/// that are inside of an item-like.
///
@@ -12,8 +14,8 @@ use rustc_hir::intravisit::nested_filter::NestedFilter;
/// and to have the visitor that visits the contents of each item
/// using this setting.
pub struct OnlyBodies(());
-impl<'hir> NestedFilter<'hir> for OnlyBodies {
- type Map = crate::hir::map::Map<'hir>;
+impl<'tcx> NestedFilter<'tcx> for OnlyBodies {
+ type MaybeTyCtxt = TyCtxt<'tcx>;
const INTER: bool = false;
const INTRA: bool = true;
}
@@ -24,8 +26,8 @@ impl<'hir> NestedFilter<'hir> for OnlyBodies {
/// process everything within their lexical context. Typically you
/// kick off the visit by doing `walk_krate()`.
pub struct All(());
-impl<'hir> NestedFilter<'hir> for All {
- type Map = crate::hir::map::Map<'hir>;
+impl<'tcx> NestedFilter<'tcx> for All {
+ type MaybeTyCtxt = TyCtxt<'tcx>;
const INTER: bool = true;
const INTRA: bool = true;
}
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 692fe027c490..9f71971ea08b 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -30,12 +30,7 @@ pub mod lib_features {
}
}
}
-pub mod limits;
pub mod privacy;
pub mod region;
pub mod resolve_bound_vars;
pub mod stability;
-
-pub fn provide(providers: &mut crate::query::Providers) {
- limits::provide(providers);
-}
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index c32cf5f82533..107c3198525a 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -20,7 +20,22 @@ pub struct BasicBlocks<'tcx> {
// Typically 95%+ of basic blocks have 4 or fewer predecessors.
type Predecessors = IndexVec>;
-type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option; 1]>>;
+/// Each `(target, switch)` entry in the map contains a list of switch values
+/// that lead to a `target` block from a `switch` block.
+///
+/// Note: this type is currently never instantiated, because it's only used for
+/// `BasicBlocks::switch_sources`, which is only called by backwards analyses
+/// that do `SwitchInt` handling, and we don't have any of those, not even in
+/// tests. See #95120 and #94576.
+type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[SwitchTargetValue; 1]>>;
+
+#[derive(Debug, Clone, Copy)]
+pub enum SwitchTargetValue {
+ // A normal switch value.
+ Normal(u128),
+ // The final "otherwise" fallback value.
+ Otherwise,
+}
#[derive(Clone, Default, Debug)]
struct Cache {
@@ -70,8 +85,8 @@ impl<'tcx> BasicBlocks<'tcx> {
})
}
- /// `switch_sources()[&(target, switch)]` returns a list of switch
- /// values that lead to a `target` block from a `switch` block.
+ /// Returns info about switch values that lead from one block to another
+ /// block. See `SwitchSources`.
#[inline]
pub fn switch_sources(&self) -> &SwitchSources {
self.cache.switch_sources.get_or_init(|| {
@@ -82,9 +97,15 @@ impl<'tcx> BasicBlocks<'tcx> {
}) = &data.terminator
{
for (value, target) in targets.iter() {
- switch_sources.entry((target, bb)).or_default().push(Some(value));
+ switch_sources
+ .entry((target, bb))
+ .or_default()
+ .push(SwitchTargetValue::Normal(value));
}
- switch_sources.entry((targets.otherwise(), bb)).or_default().push(None);
+ switch_sources
+ .entry((targets.otherwise(), bb))
+ .or_default()
+ .push(SwitchTargetValue::Otherwise);
}
}
switch_sources
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 795cfcef2d36..528da4ca0577 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -4,10 +4,10 @@
use std::borrow::Cow;
use std::fmt::{self, Debug, Formatter};
+use std::iter;
use std::ops::{Index, IndexMut};
-use std::{iter, mem};
-pub use basic_blocks::BasicBlocks;
+pub use basic_blocks::{BasicBlocks, SwitchTargetValue};
use either::Either;
use polonius_engine::Atom;
use rustc_abi::{FieldIdx, VariantIdx};
@@ -53,7 +53,6 @@ pub mod pretty;
mod query;
mod statement;
mod syntax;
-pub mod tcx;
mod terminator;
pub mod traversal;
@@ -1365,66 +1364,6 @@ impl<'tcx> BasicBlockData<'tcx> {
self.terminator.as_mut().expect("invalid terminator state")
}
- pub fn retain_statements(&mut self, mut f: F)
- where
- F: FnMut(&mut Statement<'_>) -> bool,
- {
- for s in &mut self.statements {
- if !f(s) {
- s.make_nop();
- }
- }
- }
-
- pub fn expand_statements(&mut self, mut f: F)
- where
- F: FnMut(&mut Statement<'tcx>) -> Option,
- I: iter::TrustedLen
- >,
- {
- // Gather all the iterators we'll need to splice in, and their positions.
- let mut splices: Vec<(usize, I)> = vec![];
- let mut extra_stmts = 0;
- for (i, s) in self.statements.iter_mut().enumerate() {
- if let Some(mut new_stmts) = f(s) {
- if let Some(first) = new_stmts.next() {
- // We can already store the first new statement.
- *s = first;
-
- // Save the other statements for optimized splicing.
- let remaining = new_stmts.size_hint().0;
- if remaining > 0 {
- splices.push((i + 1 + extra_stmts, new_stmts));
- extra_stmts += remaining;
- }
- } else {
- s.make_nop();
- }
- }
- }
-
- // Splice in the new statements, from the end of the block.
- // FIXME(eddyb) This could be more efficient with a "gap buffer"
- // where a range of elements ("gap") is left uninitialized, with
- // splicing adding new elements to the end of that gap and moving
- // existing elements from before the gap to the end of the gap.
- // For now, this is safe code, emulating a gap but initializing it.
- let mut gap = self.statements.len()..self.statements.len() + extra_stmts;
- self.statements.resize(
- gap.end,
- Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop },
- );
- for (splice_start, new_stmts) in splices.into_iter().rev() {
- let splice_end = splice_start + new_stmts.size_hint().0;
- while gap.end > splice_end {
- gap.start -= 1;
- gap.end -= 1;
- self.statements.swap(gap.start, gap.end);
- }
- self.statements.splice(splice_start..splice_end, new_stmts);
- gap.end = splice_start;
- }
- }
-
pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
if index < self.statements.len() { &self.statements[index] } else { &self.terminator }
}
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index d4a9aac3733f..4a21b6ad2370 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -6,8 +6,9 @@ use rustc_attr_parsing::InlineAttr;
use rustc_data_structures::base_n::{BaseNString, CASE_INSENSITIVE, ToBaseN};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxIndexMap;
-use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
use rustc_data_structures::unord::UnordMap;
+use rustc_hashes::Hash128;
use rustc_hir::ItemId;
use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE};
use rustc_index::Idx;
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index b0df6c71014a..1e3b8d029e1b 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -1588,7 +1588,7 @@ pub fn write_allocations<'tcx>(
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
write!(w, " (static: {}", tcx.def_path_str(did))?;
if body.phase <= MirPhase::Runtime(RuntimePhase::PostCleanup)
- && tcx.hir().body_const_context(body.source.def_id()).is_some()
+ && tcx.hir_body_const_context(body.source.def_id()).is_some()
{
// Statics may be cyclic and evaluating them too early
// in the MIR pipeline may cause cycle errors even though
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index d345c99f902f..595a5e548b01 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -1,7 +1,10 @@
//! Functionality for statements, operands, places, and things that appear in them.
+use tracing::{debug, instrument};
+
use super::interpret::GlobalAlloc;
use super::*;
+use crate::ty::CoroutineArgsExt;
///////////////////////////////////////////////////////////////////////////
// Statements
@@ -19,15 +22,6 @@ impl Statement<'_> {
pub fn make_nop(&mut self) {
self.kind = StatementKind::Nop
}
-
- /// Changes a statement to a nop and returns the original statement.
- #[must_use = "If you don't need the statement, use `make_nop` instead"]
- pub fn replace_nop(&mut self) -> Self {
- Statement {
- source_info: self.source_info,
- kind: mem::replace(&mut self.kind, StatementKind::Nop),
- }
- }
}
impl<'tcx> StatementKind<'tcx> {
@@ -49,6 +43,162 @@ impl<'tcx> StatementKind<'tcx> {
///////////////////////////////////////////////////////////////////////////
// Places
+#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
+pub struct PlaceTy<'tcx> {
+ pub ty: Ty<'tcx>,
+ /// Downcast to a particular variant of an enum or a coroutine, if included.
+ pub variant_index: Option,
+}
+
+// At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers.
+#[cfg(target_pointer_width = "64")]
+rustc_data_structures::static_assert_size!(PlaceTy<'_>, 16);
+
+impl<'tcx> PlaceTy<'tcx> {
+ #[inline]
+ pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
+ PlaceTy { ty, variant_index: None }
+ }
+
+ /// `place_ty.field_ty(tcx, f)` computes the type of a given field.
+ ///
+ /// Most clients of `PlaceTy` can instead just extract the relevant type
+ /// directly from their `PlaceElem`, but some instances of `ProjectionElem`
+ /// do not carry a `Ty` for `T`.
+ ///
+ /// Note that the resulting type has not been normalized.
+ #[instrument(level = "debug", skip(tcx), ret)]
+ pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> {
+ if let Some(variant_index) = self.variant_index {
+ match *self.ty.kind() {
+ ty::Adt(adt_def, args) if adt_def.is_enum() => {
+ adt_def.variant(variant_index).fields[f].ty(tcx, args)
+ }
+ ty::Coroutine(def_id, args) => {
+ let mut variants = args.as_coroutine().state_tys(def_id, tcx);
+ let Some(mut variant) = variants.nth(variant_index.into()) else {
+ bug!("variant {variant_index:?} of coroutine out of range: {self:?}");
+ };
+
+ variant
+ .nth(f.index())
+ .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}"))
+ }
+ _ => bug!("can't downcast non-adt non-coroutine type: {self:?}"),
+ }
+ } else {
+ match self.ty.kind() {
+ ty::Adt(adt_def, args) if !adt_def.is_enum() => {
+ adt_def.non_enum_variant().fields[f].ty(tcx, args)
+ }
+ ty::Closure(_, args) => args
+ .as_closure()
+ .upvar_tys()
+ .get(f.index())
+ .copied()
+ .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+ ty::CoroutineClosure(_, args) => args
+ .as_coroutine_closure()
+ .upvar_tys()
+ .get(f.index())
+ .copied()
+ .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+ // Only prefix fields (upvars and current state) are
+ // accessible without a variant index.
+ ty::Coroutine(_, args) => args
+ .as_coroutine()
+ .prefix_tys()
+ .get(f.index())
+ .copied()
+ .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+ ty::Tuple(tys) => tys
+ .get(f.index())
+ .copied()
+ .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+ _ => bug!("can't project out of {self:?}"),
+ }
+ }
+ }
+
+ pub fn multi_projection_ty(
+ self,
+ tcx: TyCtxt<'tcx>,
+ elems: &[PlaceElem<'tcx>],
+ ) -> PlaceTy<'tcx> {
+ elems.iter().fold(self, |place_ty, &elem| place_ty.projection_ty(tcx, elem))
+ }
+
+ /// Convenience wrapper around `projection_ty_core` for
+ /// `PlaceElem`, where we can just use the `Ty` that is already
+ /// stored inline on field projection elems.
+ pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
+ self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty)
+ }
+
+ /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
+ /// projects `place_ty` onto `elem`, returning the appropriate
+ /// `Ty` or downcast variant corresponding to that projection.
+ /// The `handle_field` callback must map a `FieldIdx` to its `Ty`,
+ /// (which should be trivial when `T` = `Ty`).
+ pub fn projection_ty_core(
+ self,
+ tcx: TyCtxt<'tcx>,
+ elem: &ProjectionElem,
+ mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>,
+ mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>,
+ ) -> PlaceTy<'tcx>
+ where
+ V: ::std::fmt::Debug,
+ T: ::std::fmt::Debug + Copy,
+ {
+ if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) {
+ bug!("cannot use non field projection on downcasted place")
+ }
+ let answer = match *elem {
+ ProjectionElem::Deref => {
+ let ty = self.ty.builtin_deref(true).unwrap_or_else(|| {
+ bug!("deref projection of non-dereferenceable ty {:?}", self)
+ });
+ PlaceTy::from_ty(ty)
+ }
+ ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
+ PlaceTy::from_ty(self.ty.builtin_index().unwrap())
+ }
+ ProjectionElem::Subslice { from, to, from_end } => {
+ PlaceTy::from_ty(match self.ty.kind() {
+ ty::Slice(..) => self.ty,
+ ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from),
+ ty::Array(inner, size) if from_end => {
+ let size = size
+ .try_to_target_usize(tcx)
+ .expect("expected subslice projection on fixed-size array");
+ let len = size - from - to;
+ Ty::new_array(tcx, *inner, len)
+ }
+ _ => bug!("cannot subslice non-array type: `{:?}`", self),
+ })
+ }
+ ProjectionElem::Downcast(_name, index) => {
+ PlaceTy { ty: self.ty, variant_index: Some(index) }
+ }
+ ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
+ ProjectionElem::OpaqueCast(ty) => {
+ PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
+ }
+ ProjectionElem::Subtype(ty) => {
+ PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
+ }
+
+ // FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general.
+ ProjectionElem::UnwrapUnsafeBinder(ty) => {
+ PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
+ }
+ };
+ debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
+ answer
+ }
+}
+
impl ProjectionElem {
/// Returns `true` if the target of this projection may refer to a different region of memory
/// than the base.
@@ -192,6 +342,25 @@ impl<'tcx> Place<'tcx> {
self.as_ref().project_deeper(more_projections, tcx)
}
+
+ pub fn ty_from(
+ local: Local,
+ projection: &[PlaceElem<'tcx>],
+ local_decls: &D,
+ tcx: TyCtxt<'tcx>,
+ ) -> PlaceTy<'tcx>
+ where
+ D: HasLocalDecls<'tcx>,
+ {
+ PlaceTy::from_ty(local_decls.local_decls()[local].ty).multi_projection_ty(tcx, projection)
+ }
+
+ pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
+ where
+ D: HasLocalDecls<'tcx>,
+ {
+ Place::ty_from(self.local, self.projection, local_decls, tcx)
+ }
}
impl From for Place<'_> {
@@ -294,6 +463,13 @@ impl<'tcx> PlaceRef<'tcx> {
Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
}
+
+ pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
+ where
+ D: HasLocalDecls<'tcx>,
+ {
+ Place::ty_from(self.local, self.projection, local_decls, tcx)
+ }
}
impl From for PlaceRef<'_> {
@@ -388,6 +564,28 @@ impl<'tcx> Operand<'tcx> {
let const_ty = self.constant()?.const_.ty();
if let ty::FnDef(def_id, args) = *const_ty.kind() { Some((def_id, args)) } else { None }
}
+
+ pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
+ where
+ D: HasLocalDecls<'tcx>,
+ {
+ match self {
+ &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
+ Operand::Constant(c) => c.const_.ty(),
+ }
+ }
+
+ pub fn span(&self, local_decls: &D) -> Span
+ where
+ D: HasLocalDecls<'tcx>,
+ {
+ match self {
+ &Operand::Copy(ref l) | &Operand::Move(ref l) => {
+ local_decls.local_decls()[l.local].source_info.span
+ }
+ Operand::Constant(c) => c.span,
+ }
+ }
}
impl<'tcx> ConstOperand<'tcx> {
@@ -413,6 +611,11 @@ impl<'tcx> ConstOperand<'tcx> {
///////////////////////////////////////////////////////////////////////////
/// Rvalues
+pub enum RvalueInitializationState {
+ Shallow,
+ Deep,
+}
+
impl<'tcx> Rvalue<'tcx> {
/// Returns true if rvalue can be safely removed when the result is unused.
#[inline]
@@ -452,6 +655,70 @@ impl<'tcx> Rvalue<'tcx> {
| Rvalue::WrapUnsafeBinder(_, _) => true,
}
}
+
+ pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
+ where
+ D: HasLocalDecls<'tcx>,
+ {
+ match *self {
+ Rvalue::Use(ref operand) => operand.ty(local_decls, tcx),
+ Rvalue::Repeat(ref operand, count) => {
+ Ty::new_array_with_const_len(tcx, operand.ty(local_decls, tcx), count)
+ }
+ Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did),
+ Rvalue::Ref(reg, bk, ref place) => {
+ let place_ty = place.ty(local_decls, tcx).ty;
+ Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy())
+ }
+ Rvalue::RawPtr(kind, ref place) => {
+ let place_ty = place.ty(local_decls, tcx).ty;
+ Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy())
+ }
+ Rvalue::Len(..) => tcx.types.usize,
+ Rvalue::Cast(.., ty) => ty,
+ Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => {
+ let lhs_ty = lhs.ty(local_decls, tcx);
+ let rhs_ty = rhs.ty(local_decls, tcx);
+ op.ty(tcx, lhs_ty, rhs_ty)
+ }
+ Rvalue::UnaryOp(op, ref operand) => {
+ let arg_ty = operand.ty(local_decls, tcx);
+ op.ty(tcx, arg_ty)
+ }
+ Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
+ Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
+ tcx.types.usize
+ }
+ Rvalue::NullaryOp(NullOp::ContractChecks, _)
+ | Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool,
+ Rvalue::Aggregate(ref ak, ref ops) => match **ak {
+ AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64),
+ AggregateKind::Tuple => {
+ Ty::new_tup_from_iter(tcx, ops.iter().map(|op| op.ty(local_decls, tcx)))
+ }
+ AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args),
+ AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args),
+ AggregateKind::Coroutine(did, args) => Ty::new_coroutine(tcx, did, args),
+ AggregateKind::CoroutineClosure(did, args) => {
+ Ty::new_coroutine_closure(tcx, did, args)
+ }
+ AggregateKind::RawPtr(ty, mutability) => Ty::new_ptr(tcx, ty, mutability),
+ },
+ Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty),
+ Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty,
+ Rvalue::WrapUnsafeBinder(_, ty) => ty,
+ }
+ }
+
+ #[inline]
+ /// Returns `true` if this rvalue is deeply initialized (most rvalues) or
+ /// whether its only shallowly initialized (`Rvalue::Box`).
+ pub fn initialization_state(&self) -> RvalueInitializationState {
+ match *self {
+ Rvalue::ShallowInitBox(_, _) => RvalueInitializationState::Shallow,
+ _ => RvalueInitializationState::Deep,
+ }
+ }
}
impl BorrowKind {
@@ -474,4 +741,124 @@ impl BorrowKind {
BorrowKind::Mut { kind: MutBorrowKind::TwoPhaseBorrow } => true,
}
}
+
+ pub fn to_mutbl_lossy(self) -> hir::Mutability {
+ match self {
+ BorrowKind::Mut { .. } => hir::Mutability::Mut,
+ BorrowKind::Shared => hir::Mutability::Not,
+
+ // We have no type corresponding to a shallow borrow, so use
+ // `&` as an approximation.
+ BorrowKind::Fake(_) => hir::Mutability::Not,
+ }
+ }
+}
+
+impl<'tcx> UnOp {
+ pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> {
+ match self {
+ UnOp::Not | UnOp::Neg => arg_ty,
+ UnOp::PtrMetadata => arg_ty.pointee_metadata_ty_or_projection(tcx),
+ }
+ }
+}
+
+impl<'tcx> BinOp {
+ pub fn ty(&self, tcx: TyCtxt<'tcx>, lhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>) -> Ty<'tcx> {
+ // FIXME: handle SIMD correctly
+ match self {
+ &BinOp::Add
+ | &BinOp::AddUnchecked
+ | &BinOp::Sub
+ | &BinOp::SubUnchecked
+ | &BinOp::Mul
+ | &BinOp::MulUnchecked
+ | &BinOp::Div
+ | &BinOp::Rem
+ | &BinOp::BitXor
+ | &BinOp::BitAnd
+ | &BinOp::BitOr => {
+ // these should be integers or floats of the same size.
+ assert_eq!(lhs_ty, rhs_ty);
+ lhs_ty
+ }
+ &BinOp::AddWithOverflow | &BinOp::SubWithOverflow | &BinOp::MulWithOverflow => {
+ // these should be integers of the same size.
+ assert_eq!(lhs_ty, rhs_ty);
+ Ty::new_tup(tcx, &[lhs_ty, tcx.types.bool])
+ }
+ &BinOp::Shl
+ | &BinOp::ShlUnchecked
+ | &BinOp::Shr
+ | &BinOp::ShrUnchecked
+ | &BinOp::Offset => {
+ lhs_ty // lhs_ty can be != rhs_ty
+ }
+ &BinOp::Eq | &BinOp::Lt | &BinOp::Le | &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
+ tcx.types.bool
+ }
+ &BinOp::Cmp => {
+ // these should be integer-like types of the same size.
+ assert_eq!(lhs_ty, rhs_ty);
+ tcx.ty_ordering_enum(None)
+ }
+ }
+ }
+ pub(crate) fn to_hir_binop(self) -> hir::BinOpKind {
+ match self {
+ // HIR `+`/`-`/`*` can map to either of these MIR BinOp, depending
+ // on whether overflow checks are enabled or not.
+ BinOp::Add | BinOp::AddWithOverflow => hir::BinOpKind::Add,
+ BinOp::Sub | BinOp::SubWithOverflow => hir::BinOpKind::Sub,
+ BinOp::Mul | BinOp::MulWithOverflow => hir::BinOpKind::Mul,
+ BinOp::Div => hir::BinOpKind::Div,
+ BinOp::Rem => hir::BinOpKind::Rem,
+ BinOp::BitXor => hir::BinOpKind::BitXor,
+ BinOp::BitAnd => hir::BinOpKind::BitAnd,
+ BinOp::BitOr => hir::BinOpKind::BitOr,
+ BinOp::Shl => hir::BinOpKind::Shl,
+ BinOp::Shr => hir::BinOpKind::Shr,
+ BinOp::Eq => hir::BinOpKind::Eq,
+ BinOp::Ne => hir::BinOpKind::Ne,
+ BinOp::Lt => hir::BinOpKind::Lt,
+ BinOp::Gt => hir::BinOpKind::Gt,
+ BinOp::Le => hir::BinOpKind::Le,
+ BinOp::Ge => hir::BinOpKind::Ge,
+ // We don't have HIR syntax for these.
+ BinOp::Cmp
+ | BinOp::AddUnchecked
+ | BinOp::SubUnchecked
+ | BinOp::MulUnchecked
+ | BinOp::ShlUnchecked
+ | BinOp::ShrUnchecked
+ | BinOp::Offset => {
+ unreachable!()
+ }
+ }
+ }
+
+ /// If this is a `FooWithOverflow`, return `Some(Foo)`.
+ pub fn overflowing_to_wrapping(self) -> Option {
+ Some(match self {
+ BinOp::AddWithOverflow => BinOp::Add,
+ BinOp::SubWithOverflow => BinOp::Sub,
+ BinOp::MulWithOverflow => BinOp::Mul,
+ _ => return None,
+ })
+ }
+
+ /// Returns whether this is a `FooWithOverflow`
+ pub fn is_overflowing(self) -> bool {
+ self.overflowing_to_wrapping().is_some()
+ }
+
+ /// If this is a `Foo`, return `Some(FooWithOverflow)`.
+ pub fn wrapping_to_overflowing(self) -> Option {
+ Some(match self {
+ BinOp::Add => BinOp::AddWithOverflow,
+ BinOp::Sub => BinOp::SubWithOverflow,
+ BinOp::Mul => BinOp::MulWithOverflow,
+ _ => return None,
+ })
+ }
}
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 9cec8d832dd1..389792a04f8a 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1015,22 +1015,30 @@ impl TerminatorKind<'_> {
#[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
pub struct SwitchTargets {
- /// Possible values. The locations to branch to in each case
- /// are found in the corresponding indices from the `targets` vector.
+ /// Possible values. For each value, the location to branch to is found in
+ /// the corresponding element in the `targets` vector.
pub(super) values: SmallVec<[Pu128; 1]>,
- /// Possible branch sites. The last element of this vector is used
- /// for the otherwise branch, so targets.len() == values.len() + 1
- /// should hold.
+ /// Possible branch targets. The last element of this vector is used for
+ /// the "otherwise" branch, so `targets.len() == values.len() + 1` always
+ /// holds.
//
- // This invariant is quite non-obvious and also could be improved.
- // One way to make this invariant is to have something like this instead:
+ // Note: This invariant is non-obvious and easy to violate. This would be a
+ // more rigorous representation:
//
- // branches: Vec<(ConstInt, BasicBlock)>,
- // otherwise: Option // exhaustive if None
+ // normal: SmallVec<[(Pu128, BasicBlock); 1]>,
+ // otherwise: BasicBlock,
//
- // However we’ve decided to keep this as-is until we figure a case
- // where some other approach seems to be strictly better than other.
+ // But it's important to have the targets in a sliceable type, because
+ // target slices show up elsewhere. E.g. `TerminatorKind::InlineAsm` has a
+ // boxed slice, and `TerminatorKind::FalseEdge` has a single target that
+ // can be converted to a slice with `slice::from_ref`.
+ //
+ // Why does this matter? In functions like `TerminatorKind::successors` we
+ // return `impl Iterator` and a non-slice-of-targets representation here
+ // causes problems because multiple different concrete iterator types would
+ // be involved and we would need a boxed trait object, which requires an
+ // allocation, which is expensive if done frequently.
pub(super) targets: SmallVec<[BasicBlock; 2]>,
}
@@ -1125,7 +1133,7 @@ pub type AssertMessage<'tcx> = AssertKind>;
///
/// 1. The address in memory that the place refers to.
/// 2. The provenance with which the place is being accessed.
-/// 3. The type of the place and an optional variant index. See [`PlaceTy`][super::tcx::PlaceTy].
+/// 3. The type of the place and an optional variant index. See [`PlaceTy`][super::PlaceTy].
/// 4. Optionally, some metadata. This exists if and only if the type of the place is not `Sized`.
///
/// We'll give a description below of how all pieces of the place except for the provenance are
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
deleted file mode 100644
index 862f78d72598..000000000000
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ /dev/null
@@ -1,416 +0,0 @@
-/*!
- * Methods for the various MIR types. These are intended for use after
- * building is complete.
- */
-
-use rustc_hir as hir;
-use tracing::{debug, instrument};
-use ty::CoroutineArgsExt;
-
-use crate::mir::*;
-
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
-pub struct PlaceTy<'tcx> {
- pub ty: Ty<'tcx>,
- /// Downcast to a particular variant of an enum or a coroutine, if included.
- pub variant_index: Option,
-}
-
-// At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers.
-#[cfg(target_pointer_width = "64")]
-rustc_data_structures::static_assert_size!(PlaceTy<'_>, 16);
-
-impl<'tcx> PlaceTy<'tcx> {
- #[inline]
- pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
- PlaceTy { ty, variant_index: None }
- }
-
- /// `place_ty.field_ty(tcx, f)` computes the type of a given field.
- ///
- /// Most clients of `PlaceTy` can instead just extract the relevant type
- /// directly from their `PlaceElem`, but some instances of `ProjectionElem`
- /// do not carry a `Ty` for `T`.
- ///
- /// Note that the resulting type has not been normalized.
- #[instrument(level = "debug", skip(tcx), ret)]
- pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> {
- if let Some(variant_index) = self.variant_index {
- match *self.ty.kind() {
- ty::Adt(adt_def, args) if adt_def.is_enum() => {
- adt_def.variant(variant_index).fields[f].ty(tcx, args)
- }
- ty::Coroutine(def_id, args) => {
- let mut variants = args.as_coroutine().state_tys(def_id, tcx);
- let Some(mut variant) = variants.nth(variant_index.into()) else {
- bug!("variant {variant_index:?} of coroutine out of range: {self:?}");
- };
-
- variant
- .nth(f.index())
- .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}"))
- }
- _ => bug!("can't downcast non-adt non-coroutine type: {self:?}"),
- }
- } else {
- match self.ty.kind() {
- ty::Adt(adt_def, args) if !adt_def.is_enum() => {
- adt_def.non_enum_variant().fields[f].ty(tcx, args)
- }
- ty::Closure(_, args) => args
- .as_closure()
- .upvar_tys()
- .get(f.index())
- .copied()
- .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
- ty::CoroutineClosure(_, args) => args
- .as_coroutine_closure()
- .upvar_tys()
- .get(f.index())
- .copied()
- .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
- // Only prefix fields (upvars and current state) are
- // accessible without a variant index.
- ty::Coroutine(_, args) => args
- .as_coroutine()
- .prefix_tys()
- .get(f.index())
- .copied()
- .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
- ty::Tuple(tys) => tys
- .get(f.index())
- .copied()
- .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
- _ => bug!("can't project out of {self:?}"),
- }
- }
- }
-
- pub fn multi_projection_ty(
- self,
- tcx: TyCtxt<'tcx>,
- elems: &[PlaceElem<'tcx>],
- ) -> PlaceTy<'tcx> {
- elems.iter().fold(self, |place_ty, &elem| place_ty.projection_ty(tcx, elem))
- }
-
- /// Convenience wrapper around `projection_ty_core` for
- /// `PlaceElem`, where we can just use the `Ty` that is already
- /// stored inline on field projection elems.
- pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
- self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty)
- }
-
- /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
- /// projects `place_ty` onto `elem`, returning the appropriate
- /// `Ty` or downcast variant corresponding to that projection.
- /// The `handle_field` callback must map a `FieldIdx` to its `Ty`,
- /// (which should be trivial when `T` = `Ty`).
- pub fn projection_ty_core(
- self,
- tcx: TyCtxt<'tcx>,
- elem: &ProjectionElem,
- mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>,
- mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>,
- ) -> PlaceTy<'tcx>
- where
- V: ::std::fmt::Debug,
- T: ::std::fmt::Debug + Copy,
- {
- if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) {
- bug!("cannot use non field projection on downcasted place")
- }
- let answer = match *elem {
- ProjectionElem::Deref => {
- let ty = self.ty.builtin_deref(true).unwrap_or_else(|| {
- bug!("deref projection of non-dereferenceable ty {:?}", self)
- });
- PlaceTy::from_ty(ty)
- }
- ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
- PlaceTy::from_ty(self.ty.builtin_index().unwrap())
- }
- ProjectionElem::Subslice { from, to, from_end } => {
- PlaceTy::from_ty(match self.ty.kind() {
- ty::Slice(..) => self.ty,
- ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from),
- ty::Array(inner, size) if from_end => {
- let size = size
- .try_to_target_usize(tcx)
- .expect("expected subslice projection on fixed-size array");
- let len = size - from - to;
- Ty::new_array(tcx, *inner, len)
- }
- _ => bug!("cannot subslice non-array type: `{:?}`", self),
- })
- }
- ProjectionElem::Downcast(_name, index) => {
- PlaceTy { ty: self.ty, variant_index: Some(index) }
- }
- ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
- ProjectionElem::OpaqueCast(ty) => {
- PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
- }
- ProjectionElem::Subtype(ty) => {
- PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
- }
-
- // FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general.
- ProjectionElem::UnwrapUnsafeBinder(ty) => {
- PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
- }
- };
- debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
- answer
- }
-}
-
-impl<'tcx> Place<'tcx> {
- pub fn ty_from(
- local: Local,
- projection: &[PlaceElem<'tcx>],
- local_decls: &D,
- tcx: TyCtxt<'tcx>,
- ) -> PlaceTy<'tcx>
- where
- D: HasLocalDecls<'tcx>,
- {
- PlaceTy::from_ty(local_decls.local_decls()[local].ty).multi_projection_ty(tcx, projection)
- }
-
- pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
- where
- D: HasLocalDecls<'tcx>,
- {
- Place::ty_from(self.local, self.projection, local_decls, tcx)
- }
-}
-
-impl<'tcx> PlaceRef<'tcx> {
- pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
- where
- D: HasLocalDecls<'tcx>,
- {
- Place::ty_from(self.local, self.projection, local_decls, tcx)
- }
-}
-
-pub enum RvalueInitializationState {
- Shallow,
- Deep,
-}
-
-impl<'tcx> Rvalue<'tcx> {
- pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
- where
- D: HasLocalDecls<'tcx>,
- {
- match *self {
- Rvalue::Use(ref operand) => operand.ty(local_decls, tcx),
- Rvalue::Repeat(ref operand, count) => {
- Ty::new_array_with_const_len(tcx, operand.ty(local_decls, tcx), count)
- }
- Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did),
- Rvalue::Ref(reg, bk, ref place) => {
- let place_ty = place.ty(local_decls, tcx).ty;
- Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy())
- }
- Rvalue::RawPtr(kind, ref place) => {
- let place_ty = place.ty(local_decls, tcx).ty;
- Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy())
- }
- Rvalue::Len(..) => tcx.types.usize,
- Rvalue::Cast(.., ty) => ty,
- Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => {
- let lhs_ty = lhs.ty(local_decls, tcx);
- let rhs_ty = rhs.ty(local_decls, tcx);
- op.ty(tcx, lhs_ty, rhs_ty)
- }
- Rvalue::UnaryOp(op, ref operand) => {
- let arg_ty = operand.ty(local_decls, tcx);
- op.ty(tcx, arg_ty)
- }
- Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
- Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
- tcx.types.usize
- }
- Rvalue::NullaryOp(NullOp::ContractChecks, _)
- | Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool,
- Rvalue::Aggregate(ref ak, ref ops) => match **ak {
- AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64),
- AggregateKind::Tuple => {
- Ty::new_tup_from_iter(tcx, ops.iter().map(|op| op.ty(local_decls, tcx)))
- }
- AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args),
- AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args),
- AggregateKind::Coroutine(did, args) => Ty::new_coroutine(tcx, did, args),
- AggregateKind::CoroutineClosure(did, args) => {
- Ty::new_coroutine_closure(tcx, did, args)
- }
- AggregateKind::RawPtr(ty, mutability) => Ty::new_ptr(tcx, ty, mutability),
- },
- Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty),
- Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty,
- Rvalue::WrapUnsafeBinder(_, ty) => ty,
- }
- }
-
- #[inline]
- /// Returns `true` if this rvalue is deeply initialized (most rvalues) or
- /// whether its only shallowly initialized (`Rvalue::Box`).
- pub fn initialization_state(&self) -> RvalueInitializationState {
- match *self {
- Rvalue::ShallowInitBox(_, _) => RvalueInitializationState::Shallow,
- _ => RvalueInitializationState::Deep,
- }
- }
-}
-
-impl<'tcx> Operand<'tcx> {
- pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
- where
- D: HasLocalDecls<'tcx>,
- {
- match self {
- &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
- Operand::Constant(c) => c.const_.ty(),
- }
- }
-
- pub fn span(&self, local_decls: &D) -> Span
- where
- D: HasLocalDecls<'tcx>,
- {
- match self {
- &Operand::Copy(ref l) | &Operand::Move(ref l) => {
- local_decls.local_decls()[l.local].source_info.span
- }
- Operand::Constant(c) => c.span,
- }
- }
-}
-
-impl<'tcx> BinOp {
- pub fn ty(&self, tcx: TyCtxt<'tcx>, lhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>) -> Ty<'tcx> {
- // FIXME: handle SIMD correctly
- match self {
- &BinOp::Add
- | &BinOp::AddUnchecked
- | &BinOp::Sub
- | &BinOp::SubUnchecked
- | &BinOp::Mul
- | &BinOp::MulUnchecked
- | &BinOp::Div
- | &BinOp::Rem
- | &BinOp::BitXor
- | &BinOp::BitAnd
- | &BinOp::BitOr => {
- // these should be integers or floats of the same size.
- assert_eq!(lhs_ty, rhs_ty);
- lhs_ty
- }
- &BinOp::AddWithOverflow | &BinOp::SubWithOverflow | &BinOp::MulWithOverflow => {
- // these should be integers of the same size.
- assert_eq!(lhs_ty, rhs_ty);
- Ty::new_tup(tcx, &[lhs_ty, tcx.types.bool])
- }
- &BinOp::Shl
- | &BinOp::ShlUnchecked
- | &BinOp::Shr
- | &BinOp::ShrUnchecked
- | &BinOp::Offset => {
- lhs_ty // lhs_ty can be != rhs_ty
- }
- &BinOp::Eq | &BinOp::Lt | &BinOp::Le | &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
- tcx.types.bool
- }
- &BinOp::Cmp => {
- // these should be integer-like types of the same size.
- assert_eq!(lhs_ty, rhs_ty);
- tcx.ty_ordering_enum(None)
- }
- }
- }
-}
-
-impl<'tcx> UnOp {
- pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> {
- match self {
- UnOp::Not | UnOp::Neg => arg_ty,
- UnOp::PtrMetadata => arg_ty.pointee_metadata_ty_or_projection(tcx),
- }
- }
-}
-
-impl BorrowKind {
- pub fn to_mutbl_lossy(self) -> hir::Mutability {
- match self {
- BorrowKind::Mut { .. } => hir::Mutability::Mut,
- BorrowKind::Shared => hir::Mutability::Not,
-
- // We have no type corresponding to a shallow borrow, so use
- // `&` as an approximation.
- BorrowKind::Fake(_) => hir::Mutability::Not,
- }
- }
-}
-
-impl BinOp {
- pub(crate) fn to_hir_binop(self) -> hir::BinOpKind {
- match self {
- // HIR `+`/`-`/`*` can map to either of these MIR BinOp, depending
- // on whether overflow checks are enabled or not.
- BinOp::Add | BinOp::AddWithOverflow => hir::BinOpKind::Add,
- BinOp::Sub | BinOp::SubWithOverflow => hir::BinOpKind::Sub,
- BinOp::Mul | BinOp::MulWithOverflow => hir::BinOpKind::Mul,
- BinOp::Div => hir::BinOpKind::Div,
- BinOp::Rem => hir::BinOpKind::Rem,
- BinOp::BitXor => hir::BinOpKind::BitXor,
- BinOp::BitAnd => hir::BinOpKind::BitAnd,
- BinOp::BitOr => hir::BinOpKind::BitOr,
- BinOp::Shl => hir::BinOpKind::Shl,
- BinOp::Shr => hir::BinOpKind::Shr,
- BinOp::Eq => hir::BinOpKind::Eq,
- BinOp::Ne => hir::BinOpKind::Ne,
- BinOp::Lt => hir::BinOpKind::Lt,
- BinOp::Gt => hir::BinOpKind::Gt,
- BinOp::Le => hir::BinOpKind::Le,
- BinOp::Ge => hir::BinOpKind::Ge,
- // We don't have HIR syntax for these.
- BinOp::Cmp
- | BinOp::AddUnchecked
- | BinOp::SubUnchecked
- | BinOp::MulUnchecked
- | BinOp::ShlUnchecked
- | BinOp::ShrUnchecked
- | BinOp::Offset => {
- unreachable!()
- }
- }
- }
-
- /// If this is a `FooWithOverflow`, return `Some(Foo)`.
- pub fn overflowing_to_wrapping(self) -> Option {
- Some(match self {
- BinOp::AddWithOverflow => BinOp::Add,
- BinOp::SubWithOverflow => BinOp::Sub,
- BinOp::MulWithOverflow => BinOp::Mul,
- _ => return None,
- })
- }
-
- /// Returns whether this is a `FooWithOverflow`
- pub fn is_overflowing(self) -> bool {
- self.overflowing_to_wrapping().is_some()
- }
-
- /// If this is a `Foo`, return `Some(FooWithOverflow)`.
- pub fn wrapping_to_overflowing(self) -> Option {
- Some(match self {
- BinOp::Add => BinOp::AddWithOverflow,
- BinOp::Sub => BinOp::SubWithOverflow,
- BinOp::Mul => BinOp::MulWithOverflow,
- _ => return None,
- })
- }
-}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index cd81890598e7..693823b4af4d 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -163,7 +163,7 @@ rustc_queries! {
/// The items in a module.
///
- /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
+ /// This can be conveniently accessed by `tcx.hir_visit_item_likes_in_module`.
/// Avoid calling this query directly.
query hir_module_items(key: LocalModDefId) -> &'tcx rustc_middle::hir::ModuleItems {
arena_cache
@@ -771,7 +771,7 @@ rustc_queries! {
query type_param_predicates(
key: (LocalDefId, LocalDefId, rustc_span::Ident)
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
- desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir().ty_param_name(key.1) }
+ desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir_ty_param_name(key.1) }
}
query trait_def(key: DefId) -> &'tcx ty::TraitDef {
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 2ab8750f727c..98cc00c367cf 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -376,7 +376,6 @@ pub enum ExprKind<'tcx> {
/// A `match` expression.
Match {
scrutinee: ExprId,
- scrutinee_hir_id: HirId,
arms: Box<[ArmId]>,
match_source: MatchSource,
},
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index cb8dc6921487..35893ad953d1 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2079,7 +2079,7 @@ impl<'tcx> TyCtxt<'tcx> {
) -> Vec<&'tcx hir::Ty<'tcx>> {
let hir_id = self.local_def_id_to_hir_id(scope_def_id);
let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) =
- self.hir().fn_decl_by_hir_id(hir_id)
+ self.hir_fn_decl_by_hir_id(hir_id)
else {
return vec![];
};
@@ -2099,7 +2099,7 @@ impl<'tcx> TyCtxt<'tcx> {
let hir_id = self.local_def_id_to_hir_id(scope_def_id);
let mut v = TraitObjectVisitor(vec![], self.hir());
// when the return type is a type alias
- if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id)
+ if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir_fn_decl_by_hir_id(hir_id)
&& let hir::TyKind::Path(hir::QPath::Resolved(
None,
hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind
@@ -2168,6 +2168,10 @@ impl<'tcx> TyCtxt<'tcx> {
self.limits(()).move_size_limit
}
+ pub fn pattern_complexity_limit(self) -> Limit {
+ self.limits(()).pattern_complexity_limit
+ }
+
/// All traits in the crate graph, including those not visible to the user.
pub fn all_traits(self) -> impl Iterator
- + 'tcx {
iter::once(LOCAL_CRATE)
@@ -3293,9 +3297,9 @@ pub fn provide(providers: &mut Providers) {
providers.extern_mod_stmt_cnum =
|tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
providers.is_panic_runtime =
- |tcx, LocalCrate| contains_name(tcx.hir().krate_attrs(), sym::panic_runtime);
+ |tcx, LocalCrate| contains_name(tcx.hir_krate_attrs(), sym::panic_runtime);
providers.is_compiler_builtins =
- |tcx, LocalCrate| contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins);
+ |tcx, LocalCrate| contains_name(tcx.hir_krate_attrs(), sym::compiler_builtins);
providers.has_panic_handler = |tcx, LocalCrate| {
// We want to check if the panic handler was defined in this crate
tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index fd84d75b53f3..56a38a84c9f1 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -495,7 +495,7 @@ impl<'tcx> GenericArgs<'tcx> {
self.iter().filter_map(|k| k.as_const())
}
- /// Returns generic arguments that are not lifetimes or host effect params.
+ /// Returns generic arguments that are not lifetimes.
#[inline]
pub fn non_erasable_generics(
&'tcx self,
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index e5a4e38c8750..19fa83235749 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -11,6 +11,7 @@ use rustc_error_messages::DiagMessage;
use rustc_errors::{
Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
};
+use rustc_hashes::Hash64;
use rustc_hir::LangItem;
use rustc_hir::def_id::DefId;
use rustc_index::IndexVec;
@@ -228,11 +229,32 @@ impl fmt::Display for ValidityRequirement {
#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
pub enum LayoutError<'tcx> {
+ /// A type doesn't have a sensible layout.
+ ///
+ /// This variant is used for layout errors that don't necessarily cause
+ /// compile errors.
+ ///
+ /// For example, this can happen if a struct contains an unsized type in a
+ /// non-tail field, but has an unsatisfiable bound like `str: Sized`.
Unknown(Ty<'tcx>),
+ /// The size of a type exceeds [`TargetDataLayout::obj_size_bound`].
SizeOverflow(Ty<'tcx>),
+ /// The layout can vary due to a generic parameter.
+ ///
+ /// Unlike `Unknown`, this variant is a "soft" error and indicates that the layout
+ /// may become computable after further instantiating the generic parameter(s).
TooGeneric(Ty<'tcx>),
+ /// An alias failed to normalize.
+ ///
+ /// This variant is necessary, because, due to trait solver incompleteness, it is
+ /// possible than an alias that was rigid during analysis fails to normalize after
+ /// revealing opaque types.
+ ///
+ /// See `tests/ui/layout/normalization-failure.rs` for an example.
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
+ /// A non-layout error is reported elsewhere.
ReferencesError(ErrorGuaranteed),
+ /// A type has cyclic layout, i.e. the type contains itself without indirection.
Cycle(ErrorGuaranteed),
}
@@ -242,11 +264,11 @@ impl<'tcx> LayoutError<'tcx> {
use crate::fluent_generated::*;
match self {
- Unknown(_) => middle_unknown_layout,
- SizeOverflow(_) => middle_values_too_big,
- TooGeneric(_) => middle_too_generic,
- NormalizationFailure(_, _) => middle_cannot_be_normalized,
- Cycle(_) => middle_cycle,
+ Unknown(_) => middle_layout_unknown,
+ SizeOverflow(_) => middle_layout_size_overflow,
+ TooGeneric(_) => middle_layout_too_generic,
+ NormalizationFailure(_, _) => middle_layout_normalization_failure,
+ Cycle(_) => middle_layout_cycle,
ReferencesError(_) => middle_layout_references_error,
}
}
@@ -275,7 +297,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
match *self {
LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"),
LayoutError::TooGeneric(ty) => {
- write!(f, "`{ty}` does not have a fixed size")
+ write!(f, "the type `{ty}` does not have a fixed layout")
}
LayoutError::SizeOverflow(ty) => {
write!(f, "values of the type `{ty}` are too big for the target architecture")
@@ -778,7 +800,7 @@ where
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: tcx.data_layout.i8_align.abi,
- randomization_seed: 0,
+ randomization_seed: Hash64::ZERO,
})
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 52cb8f57a88a..c52e774c8b7e 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1470,7 +1470,7 @@ pub enum ImplTraitInTraitData {
impl<'tcx> TyCtxt<'tcx> {
pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
- self.typeck(self.hir().body_owner_def_id(body))
+ self.typeck(self.hir_body_owner_def_id(body))
}
pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator
- {
@@ -1487,8 +1487,7 @@ impl<'tcx> TyCtxt<'tcx> {
// Generate a deterministically-derived seed from the item's path hash
// to allow for cross-crate compilation to actually work
- let mut field_shuffle_seed =
- self.def_path_hash(did.to_def_id()).0.to_smaller_hash().as_u64();
+ let mut field_shuffle_seed = self.def_path_hash(did.to_def_id()).0.to_smaller_hash();
// If the user defined a custom seed for layout randomization, xor the item's
// path hash with the user defined seed, this will allowing determinism while
@@ -2168,7 +2167,6 @@ pub fn provide(providers: &mut Providers) {
util::provide(providers);
print::provide(providers);
super::util::bug::provide(providers);
- super::middle::provide(providers);
*providers = Providers {
trait_impls_of: trait_def::trait_impls_of_provider,
incoherent_impls: trait_def::incoherent_impls_provider,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 7166c284c3d7..11b430dd358d 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -3299,13 +3299,12 @@ define_print_and_forward_display! {
fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) {
// Iterate all local crate items no matter where they are defined.
- let hir = tcx.hir();
- for id in hir.items() {
+ for id in tcx.hir_free_items() {
if matches!(tcx.def_kind(id.owner_id), DefKind::Use) {
continue;
}
- let item = hir.item(id);
+ let item = tcx.hir_item(id);
if item.ident.name == kw::Empty {
continue;
}
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 743ea33b20a2..17e90c15d413 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -235,7 +235,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
}
}
- for &impl_def_id in tcx.hir().trait_impls(trait_id) {
+ for &impl_def_id in tcx.hir_trait_impls(trait_id) {
let impl_def_id = impl_def_id.to_def_id();
let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
@@ -267,7 +267,7 @@ pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -
pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
let mut traits = Vec::new();
- for id in tcx.hir().items() {
+ for id in tcx.hir_free_items() {
if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
traits.push(id.owner_id.to_def_id())
}
@@ -278,7 +278,7 @@ pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
pub(super) fn trait_impls_in_crate_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
let mut trait_impls = Vec::new();
- for id in tcx.hir().items() {
+ for id in tcx.hir_free_items() {
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
&& tcx.impl_trait_ref(id.owner_id).is_some()
{
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 1b5b791bb24a..b8c73d258437 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -147,9 +147,7 @@ pub struct TypeckResults<'tcx> {
coercion_casts: ItemLocalSet,
/// Set of trait imports actually used in the method resolution.
- /// This is used for warning unused imports. During type
- /// checking, this `Arc` should not be cloned: it must have a ref-count
- /// of 1 so that we can insert things into the set mutably.
+ /// This is used for warning unused imports.
pub used_trait_imports: UnordSet,
/// If any errors occurred while type-checking this body,
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 94bd359f6eb0..88d574985423 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -5,9 +5,10 @@ use std::{fmt, iter};
use rustc_abi::{ExternAbi, Float, Integer, IntegerType, Size};
use rustc_apfloat::Float as _;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::ErrorGuaranteed;
+use rustc_hashes::Hash128;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 433f7542bd70..9450ce7ec444 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -53,7 +53,7 @@ impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> {
let arity = if let Some(frame) = cycle_error.cycle.get(0)
&& frame.query.dep_kind == dep_kinds::fn_sig
&& let Some(def_id) = frame.query.def_id
- && let Some(node) = tcx.hir().get_if_local(def_id)
+ && let Some(node) = tcx.hir_get_if_local(def_id)
&& let Some(sig) = node.fn_sig()
{
sig.decl.inputs.len()
diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
index eab414e150fa..19669021eefb 100644
--- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
@@ -1,6 +1,5 @@
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty;
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index e04c70b58837..fb0aa354913f 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -465,11 +465,10 @@ fn construct_fn<'tcx>(
assert_eq!(expr.as_usize(), thir.exprs.len() - 1);
// Figure out what primary body this item has.
- let body = tcx.hir().body_owned_by(fn_def);
+ let body = tcx.hir_body_owned_by(fn_def);
let span_with_body = tcx.hir().span_with_body(fn_id);
let return_ty_span = tcx
- .hir()
- .fn_decl_by_hir_id(fn_id)
+ .hir_fn_decl_by_hir_id(fn_id)
.unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", fn_def))
.output
.span();
@@ -758,7 +757,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
check_overflow |= tcx.sess.overflow_checks();
// Constants always need overflow checks.
check_overflow |= matches!(
- tcx.hir().body_owner_kind(def),
+ tcx.hir_body_owner_kind(def),
hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_)
);
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 1bd33475e607..84f58f1968db 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -759,7 +759,7 @@ impl UnsafeOpKind {
});
let unsafe_not_inherited_note = if should_suggest {
suggest_unsafe_block.then(|| {
- let body_span = tcx.hir().body(parent_owner.body_id().unwrap()).value.span;
+ let body_span = tcx.hir_body(parent_owner.body_id().unwrap()).value.span;
UnsafeNotInheritedLintNote {
signature_span: tcx.def_span(parent_id.def_id),
body_span,
@@ -927,7 +927,7 @@ impl UnsafeOpKind {
&& let hir::BlockCheckMode::UnsafeBlock(_) = block.rules
{
true
- } else if let Some(sig) = tcx.hir().fn_sig_by_hir_id(*id)
+ } else if let Some(sig) = tcx.hir_fn_sig_by_hir_id(*id)
&& matches!(sig.header.safety, hir::HeaderSafety::Normal(hir::Safety::Unsafe))
{
true
@@ -1145,7 +1145,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
let thir = &thir.steal();
let hir_id = tcx.local_def_id_to_hir_id(def);
- let safety_context = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| {
+ let safety_context = tcx.hir_fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| {
match fn_sig.header.safety {
// We typeck the body as safe, but otherwise treat it as unsafe everywhere else.
// Call sites to other SafeTargetFeatures functions are checked explicitly and don't need
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 07bdc59756aa..f1753be845d4 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -601,8 +601,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo
let def_span = self
.cx
.tcx
- .hir()
- .get_if_local(def.did())
+ .hir_get_if_local(def.did())
.and_then(|node| node.ident())
.map(|ident| ident.span)
.unwrap_or_else(|| self.cx.tcx.def_span(def.did()));
@@ -1113,9 +1112,6 @@ pub(crate) struct Rust2024IncompatiblePatSugg {
pub(crate) suggestion: Vec<(Span, String)>,
pub(crate) ref_pattern_count: usize,
pub(crate) binding_mode_count: usize,
- /// Internal state: the ref-mutability of the default binding mode at the subpattern being
- /// lowered, with the span where it was introduced. `None` for a by-value default mode.
- pub(crate) default_mode_span: Option<(Span, ty::Mutability)>,
/// Labels for where incompatibility-causing by-ref default binding modes were introduced.
pub(crate) default_mode_labels: FxIndexMap,
}
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 54da6924db44..d0fca76fcf05 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -828,7 +828,6 @@ impl<'tcx> ThirBuildCx<'tcx> {
},
hir::ExprKind::Match(discr, arms, match_source) => ExprKind::Match {
scrutinee: self.mirror_expr(discr),
- scrutinee_hir_id: discr.hir_id,
arms: arms.iter().map(|a| self.convert_arm(a)).collect(),
match_source,
},
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index a01609012b8f..7a9f6e463045 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -22,8 +22,7 @@ pub(crate) fn thir_body(
tcx: TyCtxt<'_>,
owner_def: LocalDefId,
) -> Result<(&Steal>, ExprId), ErrorGuaranteed> {
- let hir = tcx.hir();
- let body = hir.body_owned_by(owner_def);
+ let body = tcx.hir_body_owned_by(owner_def);
let mut cx = ThirBuildCx::new(tcx, owner_def);
if let Some(reported) = cx.typeck_results.tainted_by_errors {
return Err(reported);
@@ -31,7 +30,7 @@ pub(crate) fn thir_body(
let expr = cx.mirror_expr(body.value);
let owner_id = tcx.local_def_id_to_hir_id(owner_def);
- if let Some(fn_decl) = hir.fn_decl_by_hir_id(owner_id) {
+ if let Some(fn_decl) = tcx.hir_fn_decl_by_hir_id(owner_id) {
let closure_env_param = cx.closure_env_param(owner_def, owner_id);
let explicit_params = cx.explicit_params(owner_id, fn_decl, &body);
cx.thir.params = closure_env_param.into_iter().chain(explicit_params).collect();
@@ -77,7 +76,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
let hir = tcx.hir();
let hir_id = tcx.local_def_id_to_hir_id(def);
- let body_type = if hir.body_owner_kind(def).is_fn_or_closure() {
+ let body_type = if tcx.hir_body_owner_kind(def).is_fn_or_closure() {
// fetch the fully liberated fn signature (that is, all bound
// types/lifetimes replaced)
BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id])
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 697cb7cf37a3..6dbb460d8b15 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -10,7 +10,6 @@ use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::Level;
use rustc_middle::bug;
-use rustc_middle::middle::limits::get_limit_size;
use rustc_middle::thir::visit::Visitor;
use rustc_middle::thir::*;
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -25,7 +24,7 @@ use rustc_session::lint::builtin::{
};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::DesugaringKind;
-use rustc_span::{Ident, Span, sym};
+use rustc_span::{Ident, Span};
use rustc_trait_selection::infer::InferCtxtExt;
use tracing::instrument;
@@ -152,7 +151,7 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
}
return;
}
- ExprKind::Match { scrutinee, scrutinee_hir_id: _, box ref arms, match_source } => {
+ ExprKind::Match { scrutinee, box ref arms, match_source } => {
self.check_match(scrutinee, arms, match_source, ex.span);
}
ExprKind::Let { box ref pat, expr } => {
@@ -404,18 +403,11 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
arms: &[MatchArm<'p, 'tcx>],
scrut_ty: Ty<'tcx>,
) -> Result, ErrorGuaranteed> {
- let pattern_complexity_limit =
- get_limit_size(cx.tcx.hir().krate_attrs(), cx.tcx.sess, sym::pattern_complexity);
- let report = rustc_pattern_analysis::rustc::analyze_match(
- &cx,
- &arms,
- scrut_ty,
- pattern_complexity_limit,
- )
- .map_err(|err| {
- self.error = Err(err);
- err
- })?;
+ let report =
+ rustc_pattern_analysis::rustc::analyze_match(&cx, &arms, scrut_ty).map_err(|err| {
+ self.error = Err(err);
+ err
+ })?;
// Warn unreachable subpatterns.
for (arm, is_useful) in report.arm_usefulness.iter() {
@@ -1498,7 +1490,7 @@ fn report_adt_defined_here<'tcx>(
return None;
};
let adt_def_span =
- tcx.hir().get_if_local(def.did()).and_then(|node| node.ident()).map(|ident| ident.span);
+ tcx.hir_get_if_local(def.did()).and_then(|node| node.ident()).map(|ident| ident.span);
let adt_def_span = if point_at_non_local_ty {
adt_def_span.unwrap_or_else(|| tcx.def_span(def.did()))
} else {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 551ec5cf4e9c..667d59d858e3 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -148,7 +148,7 @@ impl<'tcx> ConstToPat<'tcx> {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Param(param_ty) = ty.kind()
{
- let def_id = self.tcx.hir().enclosing_body_owner(self.id);
+ let def_id = self.tcx.hir_enclosing_body_owner(self.id);
let generics = self.tcx.generics_of(def_id);
let param = generics.type_param(*param_ty, self.tcx);
let span = self.tcx.def_span(param.def_id);
diff --git a/compiler/rustc_mir_build/src/thir/pattern/migration.rs b/compiler/rustc_mir_build/src/thir/pattern/migration.rs
new file mode 100644
index 000000000000..bd7787b643d5
--- /dev/null
+++ b/compiler/rustc_mir_build/src/thir/pattern/migration.rs
@@ -0,0 +1,182 @@
+//! Automatic migration of Rust 2021 patterns to a form valid in both Editions 2021 and 2024.
+
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_errors::MultiSpan;
+use rustc_hir::{BindingMode, ByRef, HirId, Mutability};
+use rustc_lint as lint;
+use rustc_middle::span_bug;
+use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, Ty, TyCtxt};
+use rustc_span::{Ident, Span};
+
+use crate::errors::{Rust2024IncompatiblePat, Rust2024IncompatiblePatSugg};
+use crate::fluent_generated as fluent;
+
+/// For patterns flagged for migration during HIR typeck, this handles constructing and emitting
+/// a diagnostic suggestion.
+pub(super) struct PatMigration<'a> {
+ suggestion: Vec<(Span, String)>,
+ ref_pattern_count: usize,
+ binding_mode_count: usize,
+ /// Internal state: the ref-mutability of the default binding mode at the subpattern being
+ /// lowered, with the span where it was introduced. `None` for a by-value default mode.
+ default_mode_span: Option<(Span, ty::Mutability)>,
+ /// Labels for where incompatibility-causing by-ref default binding modes were introduced.
+ // FIXME(ref_pat_eat_one_layer_2024_structural): To track the default binding mode, we duplicate
+ // logic from HIR typeck (in order to avoid needing to store all changes to the dbm in
+ // TypeckResults). Since the default binding mode acts differently under this feature gate, the
+ // labels will be wrong.
+ default_mode_labels: FxIndexMap,
+ /// Information collected from typeck, including spans for subpatterns invalid in Rust 2024.
+ info: &'a Rust2024IncompatiblePatInfo,
+}
+
+impl<'a> PatMigration<'a> {
+ pub(super) fn new(info: &'a Rust2024IncompatiblePatInfo) -> Self {
+ PatMigration {
+ suggestion: Vec::new(),
+ ref_pattern_count: 0,
+ binding_mode_count: 0,
+ default_mode_span: None,
+ default_mode_labels: Default::default(),
+ info,
+ }
+ }
+
+ /// On Rust 2024, this emits a hard error. On earlier Editions, this emits the
+ /// future-incompatibility lint `rust_2024_incompatible_pat`.
+ pub(super) fn emit<'tcx>(self, tcx: TyCtxt<'tcx>, pat_id: HirId) {
+ let mut spans =
+ MultiSpan::from_spans(self.info.primary_labels.iter().map(|(span, _)| *span).collect());
+ for (span, label) in self.info.primary_labels.iter() {
+ spans.push_span_label(*span, label.clone());
+ }
+ let sugg = Rust2024IncompatiblePatSugg {
+ suggest_eliding_modes: self.info.suggest_eliding_modes,
+ suggestion: self.suggestion,
+ ref_pattern_count: self.ref_pattern_count,
+ binding_mode_count: self.binding_mode_count,
+ default_mode_labels: self.default_mode_labels,
+ };
+ // If a relevant span is from at least edition 2024, this is a hard error.
+ let is_hard_error = spans.primary_spans().iter().any(|span| span.at_least_rust_2024());
+ if is_hard_error {
+ let mut err =
+ tcx.dcx().struct_span_err(spans, fluent::mir_build_rust_2024_incompatible_pat);
+ if let Some(info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible {
+ // provide the same reference link as the lint
+ err.note(format!("for more information, see {}", info.reference));
+ }
+ err.arg("bad_modifiers", self.info.bad_modifiers);
+ err.arg("bad_ref_pats", self.info.bad_ref_pats);
+ err.arg("is_hard_error", true);
+ err.subdiagnostic(sugg);
+ err.emit();
+ } else {
+ tcx.emit_node_span_lint(
+ lint::builtin::RUST_2024_INCOMPATIBLE_PAT,
+ pat_id,
+ spans,
+ Rust2024IncompatiblePat {
+ sugg,
+ bad_modifiers: self.info.bad_modifiers,
+ bad_ref_pats: self.info.bad_ref_pats,
+ is_hard_error,
+ },
+ );
+ }
+ }
+
+ /// Tracks when we're lowering a pattern that implicitly dereferences the scrutinee.
+ /// This should only be called when the pattern type adjustments list `adjustments` is
+ /// non-empty. Returns the prior default binding mode; this should be followed by a call to
+ /// [`PatMigration::leave_ref`] to restore it when we leave the pattern.
+ pub(super) fn visit_implicit_derefs<'tcx>(
+ &mut self,
+ pat_span: Span,
+ adjustments: &[Ty<'tcx>],
+ ) -> Option<(Span, Mutability)> {
+ let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| {
+ let &ty::Ref(_, _, mutbl) = ref_ty.kind() else {
+ span_bug!(pat_span, "pattern implicitly dereferences a non-ref type");
+ };
+ mutbl
+ });
+
+ if !self.info.suggest_eliding_modes {
+ // If we can't fix the pattern by eliding modifiers, we'll need to make the pattern
+ // fully explicit. i.e. we'll need to suggest reference patterns for this.
+ let suggestion_str: String =
+ implicit_deref_mutbls.clone().map(|mutbl| mutbl.ref_prefix_str()).collect();
+ self.suggestion.push((pat_span.shrink_to_lo(), suggestion_str));
+ self.ref_pattern_count += adjustments.len();
+ }
+
+ // Remember if this changed the default binding mode, in case we want to label it.
+ let min_mutbl = implicit_deref_mutbls.min().unwrap();
+ if self.default_mode_span.is_none_or(|(_, old_mutbl)| min_mutbl < old_mutbl) {
+ // This changes the default binding mode to `ref` or `ref mut`. Return the old mode so
+ // it can be reinstated when we leave the pattern.
+ self.default_mode_span.replace((pat_span, min_mutbl))
+ } else {
+ // This does not change the default binding mode; it was already `ref` or `ref mut`.
+ self.default_mode_span
+ }
+ }
+
+ /// Tracks the default binding mode when we're lowering a `&` or `&mut` pattern.
+ /// Returns the prior default binding mode; this should be followed by a call to
+ /// [`PatMigration::leave_ref`] to restore it when we leave the pattern.
+ pub(super) fn visit_explicit_deref(&mut self) -> Option<(Span, Mutability)> {
+ if let Some((default_mode_span, default_ref_mutbl)) = self.default_mode_span {
+ // If this eats a by-ref default binding mode, label the binding mode.
+ self.default_mode_labels.insert(default_mode_span, default_ref_mutbl);
+ }
+ // Set the default binding mode to by-value and return the old default binding mode so it
+ // can be reinstated when we leave the pattern.
+ self.default_mode_span.take()
+ }
+
+ /// Restores the default binding mode after lowering a pattern that could change it.
+ /// This should follow a call to either [`PatMigration::visit_explicit_deref`] or
+ /// [`PatMigration::visit_implicit_derefs`].
+ pub(super) fn leave_ref(&mut self, old_mode_span: Option<(Span, Mutability)>) {
+ self.default_mode_span = old_mode_span
+ }
+
+ /// Determines if a binding is relevant to the diagnostic and adjusts the notes/suggestion if
+ /// so. Bindings are relevant if they have a modifier under a by-ref default mode (invalid in
+ /// Rust 2024) or if we need to suggest a binding modifier for them.
+ pub(super) fn visit_binding(
+ &mut self,
+ pat_span: Span,
+ mode: BindingMode,
+ explicit_ba: BindingMode,
+ ident: Ident,
+ ) {
+ if explicit_ba != BindingMode::NONE
+ && let Some((default_mode_span, default_ref_mutbl)) = self.default_mode_span
+ {
+ // If this overrides a by-ref default binding mode, label the binding mode.
+ self.default_mode_labels.insert(default_mode_span, default_ref_mutbl);
+ // If our suggestion is to elide redundnt modes, this will be one of them.
+ if self.info.suggest_eliding_modes {
+ self.suggestion.push((pat_span.with_hi(ident.span.lo()), String::new()));
+ self.binding_mode_count += 1;
+ }
+ }
+ if !self.info.suggest_eliding_modes
+ && explicit_ba.0 == ByRef::No
+ && let ByRef::Yes(mutbl) = mode.0
+ {
+ // If we can't fix the pattern by eliding modifiers, we'll need to make the pattern
+ // fully explicit. i.e. we'll need to suggest reference patterns for this.
+ let sugg_str = match mutbl {
+ Mutability::Not => "ref ",
+ Mutability::Mut => "ref mut ",
+ };
+ self.suggestion
+ .push((pat_span.with_lo(ident.span.lo()).shrink_to_lo(), sugg_str.to_owned()));
+ self.binding_mode_count += 1;
+ }
+ }
+}
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 22b8bfef09d2..8dc3f998e091 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -2,18 +2,17 @@
mod check_match;
mod const_to_pat;
+mod migration;
use std::cmp::Ordering;
use std::sync::Arc;
use rustc_abi::{FieldIdx, Integer};
-use rustc_errors::MultiSpan;
use rustc_errors::codes::*;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
-use rustc_hir::{self as hir, ByRef, Mutability, RangeEnd};
+use rustc_hir::{self as hir, RangeEnd};
use rustc_index::Idx;
-use rustc_lint as lint;
use rustc_middle::mir::interpret::LitToConstInput;
use rustc_middle::thir::{
Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
@@ -26,8 +25,8 @@ use rustc_span::{ErrorGuaranteed, Span};
use tracing::{debug, instrument};
pub(crate) use self::check_match::check_match;
+use self::migration::PatMigration;
use crate::errors::*;
-use crate::fluent_generated as fluent;
struct PatCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
@@ -35,7 +34,7 @@ struct PatCtxt<'a, 'tcx> {
typeck_results: &'a ty::TypeckResults<'tcx>,
/// Used by the Rust 2024 migration lint.
- rust_2024_migration_suggestion: Option,
+ rust_2024_migration: Option>,
}
pub(super) fn pat_from_hir<'a, 'tcx>(
@@ -44,59 +43,19 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
typeck_results: &'a ty::TypeckResults<'tcx>,
pat: &'tcx hir::Pat<'tcx>,
) -> Box> {
- let migration_info = typeck_results.rust_2024_migration_desugared_pats().get(pat.hir_id);
let mut pcx = PatCtxt {
tcx,
typing_env,
typeck_results,
- rust_2024_migration_suggestion: migration_info.and_then(|info| {
- Some(Rust2024IncompatiblePatSugg {
- suggest_eliding_modes: info.suggest_eliding_modes,
- suggestion: Vec::new(),
- ref_pattern_count: 0,
- binding_mode_count: 0,
- default_mode_span: None,
- default_mode_labels: Default::default(),
- })
- }),
+ rust_2024_migration: typeck_results
+ .rust_2024_migration_desugared_pats()
+ .get(pat.hir_id)
+ .map(PatMigration::new),
};
let result = pcx.lower_pattern(pat);
debug!("pat_from_hir({:?}) = {:?}", pat, result);
- if let Some(info) = migration_info
- && let Some(sugg) = pcx.rust_2024_migration_suggestion
- {
- let mut spans =
- MultiSpan::from_spans(info.primary_labels.iter().map(|(span, _)| *span).collect());
- for (span, label) in &info.primary_labels {
- spans.push_span_label(*span, label.clone());
- }
- // If a relevant span is from at least edition 2024, this is a hard error.
- let is_hard_error = spans.primary_spans().iter().any(|span| span.at_least_rust_2024());
- if is_hard_error {
- let mut err =
- tcx.dcx().struct_span_err(spans, fluent::mir_build_rust_2024_incompatible_pat);
- if let Some(lint_info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible {
- // provide the same reference link as the lint
- err.note(format!("for more information, see {}", lint_info.reference));
- }
- err.arg("bad_modifiers", info.bad_modifiers);
- err.arg("bad_ref_pats", info.bad_ref_pats);
- err.arg("is_hard_error", true);
- err.subdiagnostic(sugg);
- err.emit();
- } else {
- tcx.emit_node_span_lint(
- lint::builtin::RUST_2024_INCOMPATIBLE_PAT,
- pat.hir_id,
- spans,
- Rust2024IncompatiblePat {
- sugg,
- bad_modifiers: info.bad_modifiers,
- bad_ref_pats: info.bad_ref_pats,
- is_hard_error,
- },
- );
- }
+ if let Some(m) = pcx.rust_2024_migration {
+ m.emit(tcx, pat.hir_id);
}
result
}
@@ -106,31 +65,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
let adjustments: &[Ty<'tcx>] =
self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
+ // Track the default binding mode for the Rust 2024 migration suggestion.
let mut opt_old_mode_span = None;
- if let Some(s) = &mut self.rust_2024_migration_suggestion
+ if let Some(s) = &mut self.rust_2024_migration
&& !adjustments.is_empty()
{
- let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| {
- let &ty::Ref(_, _, mutbl) = ref_ty.kind() else {
- span_bug!(pat.span, "pattern implicitly dereferences a non-ref type");
- };
- mutbl
- });
-
- if !s.suggest_eliding_modes {
- let suggestion_str: String =
- implicit_deref_mutbls.clone().map(|mutbl| mutbl.ref_prefix_str()).collect();
- s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str));
- s.ref_pattern_count += adjustments.len();
- }
-
- // Remember if this changed the default binding mode, in case we want to label it.
- let min_mutbl = implicit_deref_mutbls.min().unwrap();
- if s.default_mode_span.is_none_or(|(_, old_mutbl)| min_mutbl < old_mutbl) {
- opt_old_mode_span = Some(s.default_mode_span);
- s.default_mode_span = Some((pat.span, min_mutbl));
- }
- };
+ opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments);
+ }
// When implicit dereferences have been inserted in this pattern, the unadjusted lowered
// pattern has the type that results *after* dereferencing. For example, in this code:
@@ -169,10 +110,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
})
});
- if let Some(s) = &mut self.rust_2024_migration_suggestion
- && let Some(old_mode_span) = opt_old_mode_span
+ if let Some(s) = &mut self.rust_2024_migration
+ && !adjustments.is_empty()
{
- s.default_mode_span = old_mode_span;
+ s.leave_ref(opt_old_mode_span);
}
adjusted_pat
@@ -368,16 +309,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
}
hir::PatKind::Ref(subpattern, _) => {
// Track the default binding mode for the Rust 2024 migration suggestion.
- let old_mode_span = self.rust_2024_migration_suggestion.as_mut().and_then(|s| {
- if let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span {
- // If this eats a by-ref default binding mode, label the binding mode.
- s.default_mode_labels.insert(default_mode_span, default_ref_mutbl);
- }
- s.default_mode_span.take()
- });
+ let opt_old_mode_span =
+ self.rust_2024_migration.as_mut().and_then(|s| s.visit_explicit_deref());
let subpattern = self.lower_pattern(subpattern);
- if let Some(s) = &mut self.rust_2024_migration_suggestion {
- s.default_mode_span = old_mode_span;
+ if let Some(s) = &mut self.rust_2024_migration {
+ s.leave_ref(opt_old_mode_span);
}
PatKind::Deref { subpattern }
}
@@ -408,32 +344,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
.get(pat.hir_id)
.expect("missing binding mode");
- if let Some(s) = &mut self.rust_2024_migration_suggestion {
- if explicit_ba != hir::BindingMode::NONE
- && let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span
- {
- // If this overrides a by-ref default binding mode, label the binding mode.
- s.default_mode_labels.insert(default_mode_span, default_ref_mutbl);
- // If our suggestion is to elide redundnt modes, this will be one of them.
- if s.suggest_eliding_modes {
- s.suggestion.push((pat.span.with_hi(ident.span.lo()), String::new()));
- s.binding_mode_count += 1;
- }
- }
- if !s.suggest_eliding_modes
- && explicit_ba.0 == ByRef::No
- && let ByRef::Yes(mutbl) = mode.0
- {
- let sugg_str = match mutbl {
- Mutability::Not => "ref ",
- Mutability::Mut => "ref mut ",
- };
- s.suggestion.push((
- pat.span.with_lo(ident.span.lo()).shrink_to_lo(),
- sugg_str.to_owned(),
- ));
- s.binding_mode_count += 1;
- }
+ if let Some(s) = &mut self.rust_2024_migration {
+ s.visit_binding(pat.span, mode, explicit_ba, ident);
}
// A ref x pattern is the same node used for x, and as such it has
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 07517d7edab0..3d7f9e2d8e71 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -1,9 +1,11 @@
use std::ops::RangeInclusive;
-use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges};
+use rustc_middle::mir::{
+ self, BasicBlock, CallReturnPlaces, Location, SwitchTargetValue, TerminatorEdges,
+};
use super::visitor::ResultsVisitor;
-use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget};
+use super::{Analysis, Effect, EffectIndex, Results};
pub trait Direction {
const IS_FORWARD: bool;
@@ -112,14 +114,10 @@ impl Direction for Backward {
mir::TerminatorKind::SwitchInt { targets: _, ref discr } => {
if let Some(mut data) = analysis.get_switch_int_data(block, discr) {
- let values = &body.basic_blocks.switch_sources()[&(block, pred)];
- let targets =
- values.iter().map(|&value| SwitchIntTarget { value, target: block });
-
let mut tmp = analysis.bottom_value(body);
- for target in targets {
- tmp.clone_from(&exit_state);
- analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, target);
+ for &value in &body.basic_blocks.switch_sources()[&(block, pred)] {
+ tmp.clone_from(exit_state);
+ analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, value);
propagate(pred, &tmp);
}
} else {
@@ -292,12 +290,9 @@ impl Direction for Forward {
if let Some(mut data) = analysis.get_switch_int_data(block, discr) {
let mut tmp = analysis.bottom_value(body);
for (value, target) in targets.iter() {
- tmp.clone_from(&exit_state);
- analysis.apply_switch_int_edge_effect(
- &mut data,
- &mut tmp,
- SwitchIntTarget { value: Some(value), target },
- );
+ tmp.clone_from(exit_state);
+ let value = SwitchTargetValue::Normal(value);
+ analysis.apply_switch_int_edge_effect(&mut data, &mut tmp, value);
propagate(target, &tmp);
}
@@ -308,7 +303,7 @@ impl Direction for Forward {
analysis.apply_switch_int_edge_effect(
&mut data,
exit_state,
- SwitchIntTarget { value: None, target: otherwise },
+ SwitchTargetValue::Otherwise,
);
propagate(otherwise, exit_state);
} else {
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index 60c5cb0cae8a..09f6cdb5c4a7 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -38,7 +38,9 @@ use rustc_data_structures::work_queue::WorkQueue;
use rustc_index::bit_set::{DenseBitSet, MixedBitSet};
use rustc_index::{Idx, IndexVec};
use rustc_middle::bug;
-use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges, traversal};
+use rustc_middle::mir::{
+ self, BasicBlock, CallReturnPlaces, Location, SwitchTargetValue, TerminatorEdges, traversal,
+};
use rustc_middle::ty::TyCtxt;
use tracing::error;
@@ -220,7 +222,7 @@ pub trait Analysis<'tcx> {
&mut self,
_data: &mut Self::SwitchIntData,
_state: &mut Self::Domain,
- _edge: SwitchIntTarget,
+ _value: SwitchTargetValue,
) {
unreachable!();
}
@@ -430,10 +432,5 @@ impl EffectIndex {
}
}
-pub struct SwitchIntTarget {
- pub value: Option,
- pub target: BasicBlock,
-}
-
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index 3be450a0b3f4..f5ffc42d52ab 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -4,13 +4,14 @@ use rustc_abi::VariantIdx;
use rustc_index::Idx;
use rustc_index::bit_set::{DenseBitSet, MixedBitSet};
use rustc_middle::bug;
-use rustc_middle::mir::{self, Body, CallReturnPlaces, Location, TerminatorEdges};
+use rustc_middle::mir::{
+ self, Body, CallReturnPlaces, Location, SwitchTargetValue, TerminatorEdges,
+};
use rustc_middle::ty::util::Discr;
use rustc_middle::ty::{self, TyCtxt};
use tracing::{debug, instrument};
use crate::drop_flag_effects::DropFlagState;
-use crate::framework::SwitchIntTarget;
use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
use crate::{
Analysis, GenKill, MaybeReachable, drop_flag_effects, drop_flag_effects_for_function_entry,
@@ -422,9 +423,9 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
&mut self,
data: &mut Self::SwitchIntData,
state: &mut Self::Domain,
- edge: SwitchIntTarget,
+ value: SwitchTargetValue,
) {
- if let Some(value) = edge.value {
+ if let SwitchTargetValue::Normal(value) = value {
// Kill all move paths that correspond to variants we know to be inactive along this
// particular outgoing edge of a `SwitchInt`.
drop_flag_effects::on_all_inactive_variants(
@@ -535,9 +536,9 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
&mut self,
data: &mut Self::SwitchIntData,
state: &mut Self::Domain,
- edge: SwitchIntTarget,
+ value: SwitchTargetValue,
) {
- if let Some(value) = edge.value {
+ if let SwitchTargetValue::Normal(value) = value {
// Mark all move paths that correspond to variants other than this one as maybe
// uninitialized (in reality, they are *definitely* uninitialized).
drop_flag_effects::on_all_inactive_variants(
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index b6c259aa4e0a..8bbc89fdcecb 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -1,7 +1,6 @@
use std::mem;
use rustc_index::IndexVec;
-use rustc_middle::mir::tcx::{PlaceTy, RvalueInitializationState};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index a51af8c40fd4..104a2e8c0910 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -7,7 +7,6 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet, StdEntry};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_index::IndexVec;
use rustc_index::bit_set::DenseBitSet;
-use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
diff --git a/compiler/rustc_mir_transform/src/check_inline.rs b/compiler/rustc_mir_transform/src/check_inline.rs
index 497f4a660eaa..83c3cda5a505 100644
--- a/compiler/rustc_mir_transform/src/check_inline.rs
+++ b/compiler/rustc_mir_transform/src/check_inline.rs
@@ -16,7 +16,7 @@ pub(super) struct CheckForceInline;
impl<'tcx> MirLint<'tcx> for CheckForceInline {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let def_id = body.source.def_id();
- if !tcx.hir().body_owner_kind(def_id).is_fn_or_closure() || !def_id.is_local() {
+ if !tcx.hir_body_owner_kind(def_id).is_fn_or_closure() || !def_id.is_local() {
return;
}
let InlineAttr::Force { attr_span, .. } = tcx.codegen_fn_attrs(def_id).inline else {
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index afc49c5cc54a..f3f3a65cd805 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -393,12 +393,13 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
// Remove StorageLive and StorageDead statements for remapped locals
- data.retain_statements(|s| match s.kind {
- StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => {
- !self.remap.contains(l)
+ for s in &mut data.statements {
+ if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = s.kind
+ && self.remap.contains(l)
+ {
+ s.make_nop();
}
- _ => true,
- });
+ }
let ret_val = match data.terminator().kind {
TerminatorKind::Return => {
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index e195681bc92c..264995efe8fa 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -10,7 +10,6 @@ mod unexpand;
use rustc_hir as hir;
use rustc_hir::intravisit::{Visitor, walk_expr};
-use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
use rustc_middle::mir::coverage::{
CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind,
@@ -291,7 +290,7 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir
let hir_node = tcx.hir_node_by_def_id(def_id);
let fn_body_id = hir_node.body_id().expect("HIR node is a function with body");
- let hir_body = tcx.hir().body(fn_body_id);
+ let hir_body = tcx.hir_body(fn_body_id);
let maybe_fn_sig = hir_node.fn_sig();
let is_async_fn = maybe_fn_sig.is_some_and(|fn_sig| fn_sig.header.is_async());
@@ -348,7 +347,7 @@ fn extract_hole_spans_from_hir<'tcx>(
hir_body: &hir::Body<'tcx>,
) -> Vec {
struct HolesVisitor<'hir, F> {
- hir: Map<'hir>,
+ tcx: TyCtxt<'hir>,
visit_hole_span: F,
}
@@ -360,8 +359,8 @@ fn extract_hole_spans_from_hir<'tcx>(
/// items contained within them.
type NestedFilter = nested_filter::All;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.hir
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_item(&mut self, item: &'hir hir::Item<'hir>) {
@@ -388,7 +387,7 @@ fn extract_hole_spans_from_hir<'tcx>(
let mut hole_spans = vec![];
let mut visitor = HolesVisitor {
- hir: tcx.hir(),
+ tcx,
visit_hole_span: |hole_span| {
// Discard any holes that aren't directly visible within the body span.
if body_span.contains(hole_span) && body_span.eq_ctxt(hole_span) {
diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs
index 2de55e38052e..9330a9481f52 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drop.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs
@@ -185,7 +185,7 @@ where
place.ty(self.elaborator.body(), self.tcx()).ty
} else {
// We don't have a slice with all the locals, since some are in the patch.
- tcx::PlaceTy::from_ty(self.elaborator.patch_ref().local_ty(place.local))
+ PlaceTy::from_ty(self.elaborator.patch_ref().local_ty(place.local))
.multi_projection_ty(self.elaborator.tcx(), place.projection)
.ty
}
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index ab6aafab446b..530c72ca549a 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -417,7 +417,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
..
} = data.terminator().kind
{
- assert!(!self.patch.is_patched(bb));
+ assert!(!self.patch.is_term_patched(bb));
let loc = Location { block: tgt, statement_index: 0 };
let path = self.move_data().rev_lookup.find(destination.as_ref());
@@ -462,7 +462,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
// a Goto; see `MirPatch::new`).
}
_ => {
- assert!(!self.patch.is_patched(bb));
+ assert!(!self.patch.is_term_patched(bb));
}
}
}
@@ -486,7 +486,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
..
} = data.terminator().kind
{
- assert!(!self.patch.is_patched(bb));
+ assert!(!self.patch.is_term_patched(bb));
let loc = Location { block: bb, statement_index: data.statements.len() };
let path = self.move_data().rev_lookup.find(destination.as_ref());
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 9a6a153c7ba9..5d21d687a35a 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -113,7 +113,7 @@ fn required_panic_strategy(tcx: TyCtxt<'_>, _: LocalCrate) -> Option>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> b
let def_id = body.source.def_id();
// Only do inlining into fn bodies.
- if !tcx.hir().body_owner_kind(def_id).is_fn_or_closure() {
+ if !tcx.hir_body_owner_kind(def_id).is_fn_or_closure() {
return false;
}
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 3dc4edaaa5ae..da346dfc48c1 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -36,7 +36,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
typing_env: body.typing_env(tcx),
};
let preserve_ub_checks =
- attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks);
+ attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks);
for block in body.basic_blocks.as_mut() {
for statement in block.statements.iter_mut() {
match statement.kind {
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index 1e546bfbeb30..47cb478fe33e 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -6,6 +6,8 @@ use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
use rustc_session::Session;
+use crate::patch::MirPatch;
+
/// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large
/// enough discrepancy between them.
///
@@ -41,31 +43,34 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
let mut alloc_cache = FxHashMap::default();
let typing_env = body.typing_env(tcx);
- let blocks = body.basic_blocks.as_mut();
- let local_decls = &mut body.local_decls;
+ let mut patch = MirPatch::new(body);
- for bb in blocks {
- bb.expand_statements(|st| {
+ for (block, data) in body.basic_blocks.as_mut().iter_enumerated_mut() {
+ for (statement_index, st) in data.statements.iter_mut().enumerate() {
let StatementKind::Assign(box (
lhs,
Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
)) = &st.kind
else {
- return None;
+ continue;
};
- let ty = lhs.ty(local_decls, tcx).ty;
+ let location = Location { block, statement_index };
- let (adt_def, num_variants, alloc_id) =
- self.candidate(tcx, typing_env, ty, &mut alloc_cache)?;
+ let ty = lhs.ty(&body.local_decls, tcx).ty;
- let source_info = st.source_info;
- let span = source_info.span;
+ let Some((adt_def, num_variants, alloc_id)) =
+ self.candidate(tcx, typing_env, ty, &mut alloc_cache)
+ else {
+ continue;
+ };
+
+ let span = st.source_info.span;
let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64);
- let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span));
- let store_live =
- Statement { source_info, kind: StatementKind::StorageLive(size_array_local) };
+ let size_array_local = patch.new_temp(tmp_ty, span);
+
+ let store_live = StatementKind::StorageLive(size_array_local);
let place = Place::from(size_array_local);
let constant_vals = ConstOperand {
@@ -77,108 +82,63 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
),
};
let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals)));
- let const_assign =
- Statement { source_info, kind: StatementKind::Assign(Box::new((place, rval))) };
+ let const_assign = StatementKind::Assign(Box::new((place, rval)));
- let discr_place = Place::from(
- local_decls.push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)),
- );
- let store_discr = Statement {
- source_info,
- kind: StatementKind::Assign(Box::new((
- discr_place,
- Rvalue::Discriminant(*rhs),
- ))),
- };
+ let discr_place =
+ Place::from(patch.new_temp(adt_def.repr().discr_type().to_ty(tcx), span));
+ let store_discr =
+ StatementKind::Assign(Box::new((discr_place, Rvalue::Discriminant(*rhs))));
- let discr_cast_place =
- Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span)));
- let cast_discr = Statement {
- source_info,
- kind: StatementKind::Assign(Box::new((
- discr_cast_place,
- Rvalue::Cast(
- CastKind::IntToInt,
- Operand::Copy(discr_place),
- tcx.types.usize,
- ),
- ))),
- };
+ let discr_cast_place = Place::from(patch.new_temp(tcx.types.usize, span));
+ let cast_discr = StatementKind::Assign(Box::new((
+ discr_cast_place,
+ Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr_place), tcx.types.usize),
+ )));
- let size_place =
- Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span)));
- let store_size = Statement {
- source_info,
- kind: StatementKind::Assign(Box::new((
- size_place,
- Rvalue::Use(Operand::Copy(Place {
- local: size_array_local,
- projection: tcx
- .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]),
- })),
- ))),
- };
+ let size_place = Place::from(patch.new_temp(tcx.types.usize, span));
+ let store_size = StatementKind::Assign(Box::new((
+ size_place,
+ Rvalue::Use(Operand::Copy(Place {
+ local: size_array_local,
+ projection: tcx.mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]),
+ })),
+ )));
- let dst =
- Place::from(local_decls.push(LocalDecl::new(Ty::new_mut_ptr(tcx, ty), span)));
- let dst_ptr = Statement {
- source_info,
- kind: StatementKind::Assign(Box::new((
- dst,
- Rvalue::RawPtr(RawPtrKind::Mut, *lhs),
- ))),
- };
+ let dst = Place::from(patch.new_temp(Ty::new_mut_ptr(tcx, ty), span));
+ let dst_ptr =
+ StatementKind::Assign(Box::new((dst, Rvalue::RawPtr(RawPtrKind::Mut, *lhs))));
let dst_cast_ty = Ty::new_mut_ptr(tcx, tcx.types.u8);
- let dst_cast_place =
- Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span)));
- let dst_cast = Statement {
- source_info,
- kind: StatementKind::Assign(Box::new((
- dst_cast_place,
- Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty),
- ))),
- };
+ let dst_cast_place = Place::from(patch.new_temp(dst_cast_ty, span));
+ let dst_cast = StatementKind::Assign(Box::new((
+ dst_cast_place,
+ Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty),
+ )));
- let src =
- Place::from(local_decls.push(LocalDecl::new(Ty::new_imm_ptr(tcx, ty), span)));
- let src_ptr = Statement {
- source_info,
- kind: StatementKind::Assign(Box::new((
- src,
- Rvalue::RawPtr(RawPtrKind::Const, *rhs),
- ))),
- };
+ let src = Place::from(patch.new_temp(Ty::new_imm_ptr(tcx, ty), span));
+ let src_ptr =
+ StatementKind::Assign(Box::new((src, Rvalue::RawPtr(RawPtrKind::Const, *rhs))));
let src_cast_ty = Ty::new_imm_ptr(tcx, tcx.types.u8);
- let src_cast_place =
- Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span)));
- let src_cast = Statement {
- source_info,
- kind: StatementKind::Assign(Box::new((
- src_cast_place,
- Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty),
- ))),
- };
+ let src_cast_place = Place::from(patch.new_temp(src_cast_ty, span));
+ let src_cast = StatementKind::Assign(Box::new((
+ src_cast_place,
+ Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty),
+ )));
- let deinit_old =
- Statement { source_info, kind: StatementKind::Deinit(Box::new(dst)) };
+ let deinit_old = StatementKind::Deinit(Box::new(dst));
- let copy_bytes = Statement {
- source_info,
- kind: StatementKind::Intrinsic(Box::new(
- NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
- src: Operand::Copy(src_cast_place),
- dst: Operand::Copy(dst_cast_place),
- count: Operand::Copy(size_place),
- }),
- )),
- };
+ let copy_bytes = StatementKind::Intrinsic(Box::new(
+ NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
+ src: Operand::Copy(src_cast_place),
+ dst: Operand::Copy(dst_cast_place),
+ count: Operand::Copy(size_place),
+ }),
+ ));
- let store_dead =
- Statement { source_info, kind: StatementKind::StorageDead(size_array_local) };
+ let store_dead = StatementKind::StorageDead(size_array_local);
- let iter = [
+ let stmts = [
store_live,
const_assign,
store_discr,
@@ -191,14 +151,16 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
deinit_old,
copy_bytes,
store_dead,
- ]
- .into_iter();
+ ];
+ for stmt in stmts {
+ patch.add_statement(location, stmt);
+ }
st.make_nop();
-
- Some(iter)
- });
+ }
}
+
+ patch.apply(body);
}
fn is_required(&self) -> bool {
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 46abdcb2a870..04c9375b8317 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -314,11 +314,11 @@ fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
/// MIR associated with them.
fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet {
// All body-owners have MIR associated with them.
- let mut set: FxIndexSet<_> = tcx.hir().body_owners().collect();
+ let mut set: FxIndexSet<_> = tcx.hir_body_owners().collect();
// Coroutine-closures (e.g. async closures) have an additional by-move MIR
// body that isn't in the HIR.
- for body_owner in tcx.hir().body_owners() {
+ for body_owner in tcx.hir_body_owners() {
if let DefKind::Closure = tcx.def_kind(body_owner)
&& tcx.needs_coroutine_by_move_body_def_id(body_owner.to_def_id())
{
@@ -470,7 +470,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
}
let body = tcx.mir_drops_elaborated_and_const_checked(def);
- let body = match tcx.hir().body_const_context(def) {
+ let body = match tcx.hir_body_const_context(def) {
// consts and statics do not have `optimized_mir`, so we can steal the body instead of
// cloning it.
Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => body.steal(),
@@ -729,7 +729,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
return shim::build_adt_ctor(tcx, did.to_def_id());
}
- match tcx.hir().body_const_context(did) {
+ match tcx.hir_body_const_context(did) {
// Run the `mir_for_ctfe` query, which depends on `mir_drops_elaborated_and_const_checked`
// which we are going to steal below. Thus we need to run `mir_for_ctfe` first, so it
// computes and caches its result.
diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs
index b4f6fa514a48..d3d181f6cb2b 100644
--- a/compiler/rustc_mir_transform/src/patch.rs
+++ b/compiler/rustc_mir_transform/src/patch.rs
@@ -4,11 +4,12 @@ use rustc_middle::ty::Ty;
use rustc_span::Span;
use tracing::debug;
-/// This struct represents a patch to MIR, which can add
-/// new statements and basic blocks and patch over block
-/// terminators.
+/// This struct lets you "patch" a MIR body, i.e. modify it. You can queue up
+/// various changes, such as the addition of new statements and basic blocks
+/// and replacement of terminators, and then apply the queued changes all at
+/// once with `apply`. This is useful for MIR transformation passes.
pub(crate) struct MirPatch<'tcx> {
- patch_map: IndexVec>>,
+ term_patch_map: IndexVec>>,
new_blocks: Vec>,
new_statements: Vec<(Location, StatementKind<'tcx>)>,
new_locals: Vec>,
@@ -24,9 +25,10 @@ pub(crate) struct MirPatch<'tcx> {
}
impl<'tcx> MirPatch<'tcx> {
+ /// Creates a new, empty patch.
pub(crate) fn new(body: &Body<'tcx>) -> Self {
let mut result = MirPatch {
- patch_map: IndexVec::from_elem(None, &body.basic_blocks),
+ term_patch_map: IndexVec::from_elem(None, &body.basic_blocks),
new_blocks: vec![],
new_statements: vec![],
new_locals: vec![],
@@ -141,10 +143,12 @@ impl<'tcx> MirPatch<'tcx> {
bb
}
- pub(crate) fn is_patched(&self, bb: BasicBlock) -> bool {
- self.patch_map[bb].is_some()
+ /// Has a replacement of this block's terminator been queued in this patch?
+ pub(crate) fn is_term_patched(&self, bb: BasicBlock) -> bool {
+ self.term_patch_map[bb].is_some()
}
+ /// Queues the addition of a new temporary with additional local info.
pub(crate) fn new_local_with_info(
&mut self,
ty: Ty<'tcx>,
@@ -159,6 +163,7 @@ impl<'tcx> MirPatch<'tcx> {
Local::new(index)
}
+ /// Queues the addition of a new temporary.
pub(crate) fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
let index = self.next_local;
self.next_local += 1;
@@ -174,29 +179,46 @@ impl<'tcx> MirPatch<'tcx> {
self.new_locals[new_local_idx].ty
}
+ /// Queues the addition of a new basic block.
pub(crate) fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
- let block = BasicBlock::new(self.patch_map.len());
+ let block = BasicBlock::new(self.term_patch_map.len());
debug!("MirPatch: new_block: {:?}: {:?}", block, data);
self.new_blocks.push(data);
- self.patch_map.push(None);
+ self.term_patch_map.push(None);
block
}
+ /// Queues the replacement of a block's terminator.
pub(crate) fn patch_terminator(&mut self, block: BasicBlock, new: TerminatorKind<'tcx>) {
- assert!(self.patch_map[block].is_none());
+ assert!(self.term_patch_map[block].is_none());
debug!("MirPatch: patch_terminator({:?}, {:?})", block, new);
- self.patch_map[block] = Some(new);
+ self.term_patch_map[block] = Some(new);
}
+ /// Queues the insertion of a statement at a given location. The statement
+ /// currently at that location, and all statements that follow, are shifted
+ /// down. If multiple statements are queued for addition at the same
+ /// location, the final statement order after calling `apply` will match
+ /// the queue insertion order.
+ ///
+ /// E.g. if we have `s0` at location `loc` and do these calls:
+ ///
+ /// p.add_statement(loc, s1);
+ /// p.add_statement(loc, s2);
+ /// p.apply(body);
+ ///
+ /// then the final order will be `s1, s2, s0`, with `s1` at `loc`.
pub(crate) fn add_statement(&mut self, loc: Location, stmt: StatementKind<'tcx>) {
debug!("MirPatch: add_statement({:?}, {:?})", loc, stmt);
self.new_statements.push((loc, stmt));
}
+ /// Like `add_statement`, but specialized for assignments.
pub(crate) fn add_assign(&mut self, loc: Location, place: Place<'tcx>, rv: Rvalue<'tcx>) {
self.add_statement(loc, StatementKind::Assign(Box::new((place, rv))));
}
+ /// Applies the queued changes.
pub(crate) fn apply(self, body: &mut Body<'tcx>) {
debug!(
"MirPatch: {:?} new temps, starting from index {}: {:?}",
@@ -209,14 +231,14 @@ impl<'tcx> MirPatch<'tcx> {
self.new_blocks.len(),
body.basic_blocks.len()
);
- let bbs = if self.patch_map.is_empty() && self.new_blocks.is_empty() {
+ let bbs = if self.term_patch_map.is_empty() && self.new_blocks.is_empty() {
body.basic_blocks.as_mut_preserves_cfg()
} else {
body.basic_blocks.as_mut()
};
bbs.extend(self.new_blocks);
body.local_decls.extend(self.new_locals);
- for (src, patch) in self.patch_map.into_iter_enumerated() {
+ for (src, patch) in self.term_patch_map.into_iter_enumerated() {
if let Some(patch) = patch {
debug!("MirPatch: patching block {:?}", src);
bbs[src].terminator_mut().kind = patch;
@@ -224,6 +246,9 @@ impl<'tcx> MirPatch<'tcx> {
}
let mut new_statements = self.new_statements;
+
+ // This must be a stable sort to provide the ordering described in the
+ // comment for `add_statement`.
new_statements.sort_by_key(|s| s.0);
let mut delta = 0;
diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs
index c5e951eb8b2c..02caa92ad3fc 100644
--- a/compiler/rustc_mir_transform/src/single_use_consts.rs
+++ b/compiler/rustc_mir_transform/src/single_use_consts.rs
@@ -48,9 +48,11 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts {
// We're only changing an operand, not the terminator kinds or successors
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
- let init_statement =
- basic_blocks[init_loc.block].statements[init_loc.statement_index].replace_nop();
- let StatementKind::Assign(place_and_rvalue) = init_statement.kind else {
+ let init_statement_kind = std::mem::replace(
+ &mut basic_blocks[init_loc.block].statements[init_loc.statement_index].kind,
+ StatementKind::Nop,
+ );
+ let StatementKind::Assign(place_and_rvalue) = init_statement_kind else {
bug!("No longer an assign?");
};
let (place, rvalue) = *place_and_rvalue;
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index e4a733fcbce8..1195c25e1308 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -478,7 +478,7 @@ fn collect_items_rec<'tcx>(
);
recursion_depth_reset = None;
- let item = tcx.hir().item(item_id);
+ let item = tcx.hir_item(item_id);
if let hir::ItemKind::GlobalAsm(asm) = item.kind {
for (op, op_sp) in asm.operands {
match op {
diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
index d8c1dc8b4e9f..0fc313e33b32 100644
--- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs
@@ -34,7 +34,17 @@ where
) -> QueryResult {
let cx = self.cx();
let Goal { param_env, predicate: (lhs, rhs, direction) } = goal;
- debug_assert!(lhs.to_alias_term().is_some() || rhs.to_alias_term().is_some());
+
+ // Check that the alias-relate goal is reasonable. Writeback for
+ // `coroutine_stalled_predicates` can replace alias terms with
+ // `{type error}` if the alias still contains infer vars, so we also
+ // accept alias-relate goals where one of the terms is an error.
+ debug_assert!(
+ lhs.to_alias_term().is_some()
+ || rhs.to_alias_term().is_some()
+ || lhs.is_error()
+ || rhs.is_error()
+ );
// Structurally normalize the lhs.
let lhs = if let Some(alias) = lhs.to_alias_term() {
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index b0f59ed1474c..bfb590e87679 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -791,7 +791,7 @@ where
return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Ambiguity));
};
- let responses: Vec<_> = match proven_via {
+ match proven_via {
// Even when a trait bound has been proven using a where-bound, we
// still need to consider alias-bounds for normalization, see
// tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
@@ -800,7 +800,7 @@ where
// constness checking. Doing so is *at least theoretically* breaking,
// see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
- let mut candidates_from_env: Vec<_> = candidates
+ let mut candidates_from_env_and_bounds: Vec<_> = candidates
.iter()
.filter(|c| {
matches!(
@@ -813,16 +813,37 @@ where
// If the trait goal has been proven by using the environment, we want to treat
// aliases as rigid if there are no applicable projection bounds in the environment.
- if candidates_from_env.is_empty() {
+ if candidates_from_env_and_bounds.is_empty() {
if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
- candidates_from_env.push(response);
+ candidates_from_env_and_bounds.push(response);
}
}
- candidates_from_env
- }
- TraitGoalProvenVia::Misc => candidates.iter().map(|c| c.result).collect(),
- };
- self.try_merge_responses(&responses).map_or_else(|| self.flounder(&responses), Ok)
+ if let Some(response) = self.try_merge_responses(&candidates_from_env_and_bounds) {
+ Ok(response)
+ } else {
+ self.flounder(&candidates_from_env_and_bounds)
+ }
+ }
+ TraitGoalProvenVia::Misc => {
+ // Prefer "orphaned" param-env normalization predicates, which are used
+ // (for example, and ideally only) when proving item bounds for an impl.
+ let candidates_from_env: Vec<_> = candidates
+ .iter()
+ .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
+ .map(|c| c.result)
+ .collect();
+ if let Some(response) = self.try_merge_responses(&candidates_from_env) {
+ return Ok(response);
+ }
+
+ let responses: Vec<_> = candidates.iter().map(|c| c.result).collect();
+ if let Some(response) = self.try_merge_responses(&responses) {
+ Ok(response)
+ } else {
+ self.flounder(&responses)
+ }
+ }
+ }
}
}
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index ea464fc8ebbb..bbd73dec2e47 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -117,12 +117,15 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
($self: expr, $allow_qpath_recovery: expr) => {
if $allow_qpath_recovery
&& $self.may_recover()
- && $self.look_ahead(1, |t| t == &token::PathSep)
- && let token::Interpolated(nt) = &$self.token.kind
- && let token::NtTy(ty) = &**nt
+ && let Some(mv_kind) = $self.token.is_metavar_seq()
+ && let token::MetaVarKind::Ty { .. } = mv_kind
+ && $self.check_noexpect_past_close_delim(&token::PathSep)
{
- let ty = ty.clone();
- $self.bump();
+ // Reparse the type, then move to recovery.
+ let ty = $self
+ .eat_metavar_seq(mv_kind, |this| this.parse_ty_no_question_mark_recover())
+ .expect("metavar seq ty");
+
return $self.maybe_recover_from_bad_qpath_stage_2($self.prev_token.span, ty);
}
};
@@ -614,6 +617,24 @@ impl<'a> Parser<'a> {
self.token == *tok
}
+ // Check the first token after the delimiter that closes the current
+ // delimited sequence. (Panics if used in the outermost token stream, which
+ // has no delimiters.) It uses a clone of the relevant tree cursor to skip
+ // past the entire `TokenTree::Delimited` in a single step, avoiding the
+ // need for unbounded token lookahead.
+ //
+ // Primarily used when `self.token` matches
+ // `OpenDelim(Delimiter::Invisible(_))`, to look ahead through the current
+ // metavar expansion.
+ fn check_noexpect_past_close_delim(&self, tok: &TokenKind) -> bool {
+ let mut tree_cursor = self.token_cursor.stack.last().unwrap().clone();
+ tree_cursor.bump();
+ matches!(
+ tree_cursor.curr(),
+ Some(TokenTree::Token(token::Token { kind, .. }, _)) if kind == tok
+ )
+ }
+
/// Consumes a token 'tok' if it exists. Returns whether the given token was present.
///
/// the main purpose of this function is to reduce the cluttering of the suggestions list
@@ -721,6 +742,43 @@ impl<'a> Parser<'a> {
if !self.eat_keyword(exp) { self.unexpected() } else { Ok(()) }
}
+ /// Consume a sequence produced by a metavar expansion, if present.
+ fn eat_metavar_seq(
+ &mut self,
+ mv_kind: MetaVarKind,
+ f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
+ ) -> Option {
+ self.eat_metavar_seq_with_matcher(|mvk| mvk == mv_kind, f)
+ }
+
+ /// A slightly more general form of `eat_metavar_seq`, for use with the
+ /// `MetaVarKind` variants that have parameters, where an exact match isn't
+ /// desired.
+ fn eat_metavar_seq_with_matcher(
+ &mut self,
+ match_mv_kind: impl Fn(MetaVarKind) -> bool,
+ mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
+ ) -> Option {
+ if let token::OpenDelim(delim) = self.token.kind
+ && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim
+ && match_mv_kind(mv_kind)
+ {
+ self.bump();
+ let res = f(self).expect("failed to reparse {mv_kind:?}");
+ if let token::CloseDelim(delim) = self.token.kind
+ && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim
+ && match_mv_kind(mv_kind)
+ {
+ self.bump();
+ Some(res)
+ } else {
+ panic!("no close delim when reparsing {mv_kind:?}");
+ }
+ } else {
+ None
+ }
+ }
+
/// Is the given keyword `kw` followed by a non-reserved identifier?
fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool {
self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
@@ -754,9 +812,9 @@ impl<'a> Parser<'a> {
self.is_keyword_ahead(0, &[kw::Const])
&& self.look_ahead(1, |t| match &t.kind {
// async closures do not work with const closures, so we do not parse that here.
- token::Ident(kw::Move | kw::Static, _) | token::OrOr | token::BinOp(token::Or) => {
- true
- }
+ token::Ident(kw::Move | kw::Static, IdentIsRaw::No)
+ | token::OrOr
+ | token::BinOp(token::Or) => true,
_ => false,
})
}
@@ -1455,7 +1513,11 @@ impl<'a> Parser<'a> {
/// so emit a proper diagnostic.
// Public for rustfmt usage.
pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> {
- maybe_whole!(self, NtVis, |vis| vis.into_inner());
+ if let Some(vis) = self
+ .eat_metavar_seq(MetaVarKind::Vis, |this| this.parse_visibility(FollowedByType::Yes))
+ {
+ return Ok(vis);
+ }
if !self.eat_keyword(exp!(Pub)) {
// We need a span for our `Spanned`, but there's inherently no
@@ -1683,7 +1745,9 @@ pub enum ParseNtResult {
Tt(TokenTree),
Ident(Ident, IdentIsRaw),
Lifetime(Ident, IdentIsRaw),
+ Ty(P),
+ Vis(P),
- /// This case will eventually be removed, along with `Token::Interpolate`.
+ /// This variant will eventually be removed, along with `Token::Interpolate`.
Nt(Arc),
}
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index eefdb641da22..f202f85752e1 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -30,7 +30,7 @@ impl<'a> Parser<'a> {
MetaVarKind::Stmt
| MetaVarKind::Pat(_)
| MetaVarKind::Expr { .. }
- | MetaVarKind::Ty
+ | MetaVarKind::Ty { .. }
| MetaVarKind::Literal // `true`, `false`
| MetaVarKind::Meta
| MetaVarKind::Path => true,
@@ -51,14 +51,11 @@ impl<'a> Parser<'a> {
NtStmt(_)
| NtPat(_)
| NtExpr(_)
- | NtTy(_)
| NtLiteral(_) // `true`, `false`
| NtMeta(_)
| NtPath(_) => true,
- NtItem(_)
- | NtBlock(_)
- | NtVis(_) => false,
+ NtItem(_) | NtBlock(_) => false,
}
}
@@ -88,7 +85,7 @@ impl<'a> Parser<'a> {
NonterminalKind::Ident => get_macro_ident(token).is_some(),
NonterminalKind::Literal => token.can_begin_literal_maybe_minus(),
NonterminalKind::Vis => match token.kind {
- // The follow-set of :vis + "priv" keyword + interpolated
+ // The follow-set of :vis + "priv" keyword + interpolated/metavar-expansion.
token::Comma
| token::Ident(..)
| token::NtIdent(..)
@@ -102,7 +99,7 @@ impl<'a> Parser<'a> {
token::NtLifetime(..) => true,
token::Interpolated(nt) => match &**nt {
NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
- NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) | NtVis(_) => false,
+ NtItem(_) | NtPat(_) | NtMeta(_) | NtPath(_) => false,
},
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k {
MetaVarKind::Block
@@ -111,7 +108,7 @@ impl<'a> Parser<'a> {
| MetaVarKind::Literal => true,
MetaVarKind::Item
| MetaVarKind::Pat(_)
- | MetaVarKind::Ty
+ | MetaVarKind::Ty { .. }
| MetaVarKind::Meta
| MetaVarKind::Path
| MetaVarKind::Vis => false,
@@ -189,7 +186,9 @@ impl<'a> Parser<'a> {
NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?)
}
NonterminalKind::Ty => {
- NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?)
+ return Ok(ParseNtResult::Ty(
+ self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?,
+ ));
}
// this could be handled like a token, since it is one
NonterminalKind::Ident => {
@@ -208,8 +207,9 @@ impl<'a> Parser<'a> {
}
NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(ForceCollect::Yes)?)),
NonterminalKind::Vis => {
- NtVis(P(self
- .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?))
+ return Ok(ParseNtResult::Vis(P(self.collect_tokens_no_attrs(|this| {
+ this.parse_visibility(FollowedByType::Yes)
+ })?)));
}
NonterminalKind::Lifetime => {
// We want to keep `'keyword` parsing, just like `keyword` is still
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index b241aa892db9..c24305ea9a86 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -2,7 +2,7 @@ use std::mem;
use ast::token::IdentIsRaw;
use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, Token, TokenKind};
+use rustc_ast::token::{self, Delimiter, MetaVarKind, Token, TokenKind};
use rustc_ast::{
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint,
AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
@@ -196,14 +196,12 @@ impl<'a> Parser<'a> {
maybe_whole!(self, NtPath, |path| reject_generics_if_mod_style(self, path.into_inner()));
- if let token::Interpolated(nt) = &self.token.kind {
- if let token::NtTy(ty) = &**nt {
- if let ast::TyKind::Path(None, path) = &ty.kind {
- let path = path.clone();
- self.bump();
- return Ok(reject_generics_if_mod_style(self, path));
- }
- }
+ // If we have a `ty` metavar in the form of a path, reparse it directly as a path, instead
+ // of reparsing it as a `ty` and then extracting the path.
+ if let Some(path) = self.eat_metavar_seq(MetaVarKind::Ty { is_path: true }, |this| {
+ this.parse_path(PathStyle::Type)
+ }) {
+ return Ok(reject_generics_if_mod_style(self, path));
}
let lo = self.token.span;
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index dc5919b3630c..18af0a1c79aa 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -1,5 +1,5 @@
use rustc_ast::ptr::P;
-use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind};
+use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, MetaVarKind, Token, TokenKind};
use rustc_ast::util::case::Case;
use rustc_ast::{
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy,
@@ -18,7 +18,7 @@ use crate::errors::{
HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
NestedCVariadicType, ReturnTypesUseThinArrow,
};
-use crate::{exp, maybe_recover_from_interpolated_ty_qpath, maybe_whole};
+use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
/// Signals whether parsing a type should allow `+`.
///
@@ -183,7 +183,8 @@ impl<'a> Parser<'a> {
)
}
- /// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>`
+ /// Parse a type without recovering `:` as `->` to avoid breaking code such
+ /// as `where fn() : for<'a>`.
pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P> {
self.parse_ty_common(
AllowPlus::Yes,
@@ -247,7 +248,13 @@ impl<'a> Parser<'a> {
) -> PResult<'a, P> {
let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
- maybe_whole!(self, NtTy, |ty| ty);
+
+ if let Some(ty) = self.eat_metavar_seq_with_matcher(
+ |mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),
+ |this| this.parse_ty_no_question_mark_recover(),
+ ) {
+ return Ok(ty);
+ }
let lo = self.token.span;
let mut impl_dyn_multi = false;
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index f578708b40cd..5111a025f94e 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -627,7 +627,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
fn check_object_lifetime_default(&self, hir_id: HirId) {
let tcx = self.tcx;
if let Some(owner_id) = hir_id.as_owner()
- && let Some(generics) = tcx.hir().get_generics(owner_id.def_id)
+ && let Some(generics) = tcx.hir_get_generics(owner_id.def_id)
{
for p in generics.params {
let hir::GenericParamKind::Type { .. } = p.kind else { continue };
@@ -2461,7 +2461,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
if let Err(terr) = ocx.eq(&cause, param_env, expected_sig, sig) {
let mut diag = tcx.dcx().create_err(errors::ProcMacroBadSig { span, kind });
- let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id);
+ let hir_sig = tcx.hir_fn_sig_by_hir_id(hir_id);
if let Some(hir_sig) = hir_sig {
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
match terr {
@@ -2606,8 +2606,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
@@ -2740,9 +2740,8 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
for attr_to_check in ATTRS_TO_CHECK {
if attr.has_name(*attr_to_check) {
let item = tcx
- .hir()
- .items()
- .map(|id| tcx.hir().item(id))
+ .hir_free_items()
+ .map(|id| tcx.hir_item(id))
.find(|item| !item.span.is_dummy()) // Skip prelude `use`s
.map(|item| errors::ItemFollowingInnerAttr {
span: item.ident.span,
@@ -2792,10 +2791,10 @@ fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>)
fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
let check_attr_visitor = &mut CheckAttrVisitor { tcx, abort: Cell::new(false) };
- tcx.hir().visit_item_likes_in_module(module_def_id, check_attr_visitor);
+ tcx.hir_visit_item_likes_in_module(module_def_id, check_attr_visitor);
if module_def_id.to_local_def_id().is_top_level_module() {
check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None);
- check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
+ check_invalid_crate_level_attr(tcx, tcx.hir_krate_attrs());
}
if check_attr_visitor.abort.get() {
tcx.dcx().abort_if_errors()
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 95f18eaa7ef1..7b4fecf2ed19 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -358,7 +358,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
if let Some(local_impl_of) = impl_of.as_local()
&& let Some(local_def_id) = def_id.as_local()
&& let Some(fn_sig) =
- self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
+ self.tcx.hir_fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
&& matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
&& let TyKind::Path(hir::QPath::Resolved(_, path)) =
self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind
@@ -531,7 +531,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId, impl_item_id: LocalDefId) -> bool {
if let TyKind::Path(hir::QPath::Resolved(_, path)) =
- self.tcx.hir().item(impl_id).expect_impl().self_ty.kind
+ self.tcx.hir_item(impl_id).expect_impl().self_ty.kind
&& let Res::Def(def_kind, def_id) = path.res
&& let Some(local_def_id) = def_id.as_local()
&& matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
@@ -559,7 +559,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
fn visit_nested_body(&mut self, body: hir::BodyId) {
let old_maybe_typeck_results =
self.maybe_typeck_results.replace(self.tcx.typeck_body(body));
- let body = self.tcx.hir().body(body);
+ let body = self.tcx.hir_body(body);
self.visit_body(body);
self.maybe_typeck_results = old_maybe_typeck_results;
}
@@ -750,7 +750,7 @@ fn check_item<'tcx>(
match tcx.def_kind(id.owner_id) {
DefKind::Enum => {
- let item = tcx.hir().item(id);
+ let item = tcx.hir_item(id);
if let hir::ItemKind::Enum(ref enum_def, _) = item.kind {
if let Some(comes_from_allow) = allow_dead_code {
worklist.extend(
@@ -772,14 +772,14 @@ fn check_item<'tcx>(
.iter()
.filter_map(|def_id| def_id.as_local());
- let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir().item(id).expect_impl().self_ty);
+ let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir_item(id).expect_impl().self_ty);
// And we access the Map here to get HirId from LocalDefId
for local_def_id in local_def_ids {
// check the function may construct Self
let mut may_construct_self = false;
if let Some(fn_sig) =
- tcx.hir().fn_sig_by_hir_id(tcx.local_def_id_to_hir_id(local_def_id))
+ tcx.hir_fn_sig_by_hir_id(tcx.local_def_id_to_hir_id(local_def_id))
{
may_construct_self =
matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None);
@@ -805,7 +805,7 @@ fn check_item<'tcx>(
}
}
DefKind::Struct => {
- let item = tcx.hir().item(id);
+ let item = tcx.hir_item(id);
if let hir::ItemKind::Struct(ref variant_data, _) = item.kind
&& let Some(ctor_def_id) = variant_data.ctor_def_id()
{
@@ -827,7 +827,7 @@ fn check_trait_item(
) {
use hir::TraitItemKind::{Const, Fn};
if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
- let trait_item = tcx.hir().trait_item(id);
+ let trait_item = tcx.hir_trait_item(id);
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..))
&& let Some(comes_from_allow) =
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 22291c9282db..c2225ea1e642 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -37,7 +37,7 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
let mut ctxt = EntryContext { tcx, rustc_main_fn: None, non_main_fns: Vec::new() };
- for id in tcx.hir().items() {
+ for id in tcx.hir_free_items() {
check_and_search_item(id, &mut ctxt);
}
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index 74038b24dccd..509c2f547752 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -9,11 +9,11 @@ use rustc_middle::ty::TyCtxt;
pub fn check_crate(tcx: TyCtxt<'_>) {
let errors = Lock::new(Vec::new());
- tcx.hir().par_for_each_module(|module_id| {
+ tcx.par_hir_for_each_module(|module_id| {
let mut v =
HirIdValidator { tcx, owner: None, hir_ids_seen: Default::default(), errors: &errors };
- tcx.hir().visit_item_likes_in_module(module_id, &mut v);
+ tcx.hir_visit_item_likes_in_module(module_id, &mut v);
});
let errors = errors.into_inner();
@@ -61,7 +61,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
if max != self.hir_ids_seen.len() - 1 {
let hir = self.tcx.hir();
- let pretty_owner = hir.def_path(owner.def_id).to_string_no_crate_verbose();
+ let pretty_owner = self.tcx.hir_def_path(owner.def_id).to_string_no_crate_verbose();
let missing_items: Vec<_> = (0..=max as u32)
.map(|i| ItemLocalId::from_u32(i))
@@ -105,8 +105,8 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
type NestedFilter = nested_filter::OnlyBodies;
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
+ fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+ self.tcx
}
fn visit_nested_item(&mut self, id: hir::ItemId) {
@@ -138,8 +138,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
format!(
"HirIdValidator: The recorded owner of {} is {} instead of {}",
self.tcx.hir().node_to_string(hir_id),
- self.tcx.hir().def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
- self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose()
+ self.tcx.hir_def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
+ self.tcx.hir_def_path(owner.def_id).to_string_no_crate_verbose()
)
});
}
diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs
index f7cae89852e1..92ea49f18e5d 100644
--- a/compiler/rustc_passes/src/input_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -7,7 +7,6 @@ use rustc_ast::{self as ast, NodeId, visit as ast_visit};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::thousands::format_with_underscores;
use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit};
-use rustc_middle::hir::map::Map;
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;
use rustc_span::def_id::LocalDefId;
@@ -56,19 +55,16 @@ impl Node {
/// a `visit_*` method for, and so we cannot measure these, which is
/// unfortunate.
struct StatCollector<'k> {
- krate: Option