diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0934e42b277e4..de144ee6104c5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -70,6 +70,7 @@ jobs:
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SCCACHE_BUCKET: rust-lang-ci-sccache2
+ SCCACHE_REGION: us-west-1
CACHE_DOMAIN: ci-caches.rust-lang.org
continue-on-error: ${{ matrix.continue_on_error || false }}
strategy:
@@ -173,6 +174,11 @@ jobs:
- name: ensure the stable version number is correct
run: src/ci/scripts/verify-stable-version-number.sh
+ # Show the environment just before we run the build
+ # This makes it easier to diagnose problems with the above install scripts.
+ - name: show the current environment
+ run: src/ci/scripts/dump-environment.sh
+
- name: run the build
# Redirect stderr to stdout to avoid reordering the two streams in the GHA logs.
run: src/ci/scripts/run-build-from-ci.sh 2>&1
diff --git a/.gitmodules b/.gitmodules
index f9bd42edab3f4..97a0c0c54cf9f 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 38a861727a9d3..4401489813a40 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"
@@ -2903,9 +2751,9 @@ dependencies = [
[[package]]
name = "psm"
-version = "0.1.24"
+version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810"
+checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88"
dependencies = [
"cc",
]
@@ -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",
@@ -3905,7 +3748,6 @@ dependencies = [
"itertools",
"rustc_abi",
"rustc_ast",
- "rustc_ast_ir",
"rustc_attr_parsing",
"rustc_data_structures",
"rustc_errors",
@@ -3937,6 +3779,7 @@ dependencies = [
"rustc_fluent_macro",
"rustc_fs_util",
"rustc_graphviz",
+ "rustc_hashes",
"rustc_hir",
"rustc_macros",
"rustc_middle",
@@ -3970,7 +3813,6 @@ dependencies = [
name = "rustc_infer"
version = "0.0.0"
dependencies = [
- "rustc_ast_ir",
"rustc_data_structures",
"rustc_errors",
"rustc_fluent_macro",
@@ -4161,7 +4003,6 @@ dependencies = [
"rustc_apfloat",
"rustc_arena",
"rustc_ast",
- "rustc_ast_ir",
"rustc_attr_parsing",
"rustc_data_structures",
"rustc_error_messages",
@@ -4169,6 +4010,7 @@ dependencies = [
"rustc_feature",
"rustc_fluent_macro",
"rustc_graphviz",
+ "rustc_hashes",
"rustc_hir",
"rustc_hir_pretty",
"rustc_index",
@@ -4290,7 +4132,6 @@ name = "rustc_next_trait_solver"
version = "0.0.0"
dependencies = [
"derive-where",
- "rustc_ast_ir",
"rustc_data_structures",
"rustc_index",
"rustc_macros",
@@ -4405,6 +4246,7 @@ dependencies = [
"measureme",
"rustc_data_structures",
"rustc_errors",
+ "rustc_hashes",
"rustc_hir",
"rustc_index",
"rustc_middle",
@@ -4428,6 +4270,7 @@ dependencies = [
"rustc_errors",
"rustc_feature",
"rustc_fluent_macro",
+ "rustc_hashes",
"rustc_hir",
"rustc_index",
"rustc_macros",
@@ -4488,6 +4331,7 @@ name = "rustc_serialize"
version = "0.0.0"
dependencies = [
"indexmap",
+ "rustc_hashes",
"rustc_macros",
"smallvec",
"tempfile",
@@ -4508,6 +4352,7 @@ dependencies = [
"rustc_feature",
"rustc_fluent_macro",
"rustc_fs_util",
+ "rustc_hashes",
"rustc_hir",
"rustc_lint_defs",
"rustc_macros",
@@ -4549,6 +4394,7 @@ dependencies = [
"md-5",
"rustc_arena",
"rustc_data_structures",
+ "rustc_hashes",
"rustc_index",
"rustc_macros",
"rustc_serialize",
@@ -4568,6 +4414,7 @@ dependencies = [
"rustc_abi",
"rustc_data_structures",
"rustc_errors",
+ "rustc_hashes",
"rustc_hir",
"rustc_middle",
"rustc_session",
@@ -4604,7 +4451,6 @@ dependencies = [
"itertools",
"rustc_abi",
"rustc_ast",
- "rustc_ast_ir",
"rustc_attr_parsing",
"rustc_data_structures",
"rustc_errors",
@@ -4643,7 +4489,6 @@ version = "0.0.0"
dependencies = [
"itertools",
"rustc_abi",
- "rustc_ast_ir",
"rustc_data_structures",
"rustc_hir",
"rustc_infer",
@@ -4659,10 +4504,10 @@ version = "0.0.0"
dependencies = [
"itertools",
"rustc_abi",
- "rustc_ast_ir",
"rustc_data_structures",
"rustc_errors",
"rustc_fluent_macro",
+ "rustc_hashes",
"rustc_hir",
"rustc_index",
"rustc_infer",
@@ -5103,9 +4948,9 @@ dependencies = [
[[package]]
name = "stacker"
-version = "0.1.17"
+version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b"
+checksum = "1d08feb8f695b465baed819b03c128dc23f57a694510ab1f06c77f763975685e"
dependencies = [
"cc",
"cfg-if",
@@ -5289,16 +5134,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 +5374,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 +5494,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 97e782d0df020..20a43aaaeeb37 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 f0def1a0e423a..038d7ca639f20 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/Cargo.toml b/compiler/rustc/Cargo.toml
index d24b630516a7c..f4caa3ef769d5 100644
--- a/compiler/rustc/Cargo.toml
+++ b/compiler/rustc/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc-main"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs
index a55a63a7bf179..ca1bb59e59d60 100644
--- a/compiler/rustc/src/main.rs
+++ b/compiler/rustc/src/main.rs
@@ -65,7 +65,7 @@ fn main() {
// linking, so we need to explicitly depend on the function.
#[cfg(target_os = "macos")]
{
- extern "C" {
+ unsafe extern "C" {
fn _rjem_je_zone_register();
}
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index 1013f1d3958d8..86dc84e2016d6 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_abi"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
@@ -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/callconv.rs b/compiler/rustc_abi/src/callconv.rs
index 9fb70b80c9efb..4529ab8058e9a 100644
--- a/compiler/rustc_abi/src/callconv.rs
+++ b/compiler/rustc_abi/src/callconv.rs
@@ -65,8 +65,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
Ty: TyAbiInterface<'a, C> + Copy,
{
match self.backend_repr {
- BackendRepr::Uninhabited => Err(Heterogeneous),
-
// The primitive for this algorithm.
BackendRepr::Scalar(scalar) => {
let kind = match scalar.primitive() {
diff --git a/compiler/rustc_abi/src/callconv/reg.rs b/compiler/rustc_abi/src/callconv/reg.rs
index 66f47c52c15d1..8cf140dbaad4e 100644
--- a/compiler/rustc_abi/src/callconv/reg.rs
+++ b/compiler/rustc_abi/src/callconv/reg.rs
@@ -57,7 +57,7 @@ impl Reg {
128 => dl.f128_align.abi,
_ => panic!("unsupported float: {self:?}"),
},
- RegKind::Vector => dl.vector_align(self.size).abi,
+ RegKind::Vector => dl.llvmlike_vector_align(self.size).abi,
}
}
}
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index b8773f9ff38f6..3f83787ea3765 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;
@@ -129,11 +130,12 @@ impl LayoutCalculator {
},
backend_repr: BackendRepr::ScalarPair(a, b),
largest_niche,
+ uninhabited: false,
align,
size,
max_repr_align: None,
unadjusted_abi_align: align.abi,
- randomization_seed: combined_seed,
+ randomization_seed: Hash64::new(combined_seed),
}
}
@@ -220,13 +222,14 @@ impl LayoutCalculator {
LayoutData {
variants: Variants::Empty,
fields: FieldsShape::Primitive,
- backend_repr: BackendRepr::Uninhabited,
+ backend_repr: BackendRepr::Memory { sized: true },
largest_niche: None,
+ uninhabited: true,
align: dl.i8_align,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align.abi,
- randomization_seed: 0,
+ randomization_seed: Hash64::ZERO,
}
}
@@ -307,10 +310,10 @@ impl LayoutCalculator {
let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
let mut max_repr_align = repr.align;
- // If all the non-ZST fields have the same ABI and union ABI optimizations aren't
- // disabled, we can use that common ABI for the union as a whole.
+ // If all the non-ZST fields have the same repr and union repr optimizations aren't
+ // disabled, we can use that common repr for the union as a whole.
struct AbiMismatch;
- let mut common_non_zst_abi_and_align = if repr.inhibits_union_abi_opt() {
+ let mut common_non_zst_repr_and_align = if repr.inhibits_union_abi_opt() {
// Can't optimize
Err(AbiMismatch)
} else {
@@ -334,14 +337,14 @@ impl LayoutCalculator {
continue;
}
- if let Ok(common) = common_non_zst_abi_and_align {
+ if let Ok(common) = common_non_zst_repr_and_align {
// Discard valid range information and allow undef
let field_abi = field.backend_repr.to_union();
if let Some((common_abi, common_align)) = common {
if common_abi != field_abi {
// Different fields have different ABI: disable opt
- common_non_zst_abi_and_align = Err(AbiMismatch);
+ common_non_zst_repr_and_align = Err(AbiMismatch);
} else {
// Fields with the same non-Aggregate ABI should also
// have the same alignment
@@ -354,7 +357,7 @@ impl LayoutCalculator {
}
} else {
// First non-ZST field: record its ABI and alignment
- common_non_zst_abi_and_align = Ok(Some((field_abi, field.align.abi)));
+ common_non_zst_repr_and_align = Ok(Some((field_abi, field.align.abi)));
}
}
}
@@ -373,16 +376,25 @@ impl LayoutCalculator {
// If all non-ZST fields have the same ABI, we may forward that ABI
// for the union as a whole, unless otherwise inhibited.
- let abi = match common_non_zst_abi_and_align {
+ let backend_repr = match common_non_zst_repr_and_align {
Err(AbiMismatch) | Ok(None) => BackendRepr::Memory { sized: true },
- Ok(Some((abi, _))) => {
- if abi.inherent_align(dl).map(|a| a.abi) != Some(align.abi) {
- // Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
+ Ok(Some((repr, _))) => match repr {
+ // Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
+ BackendRepr::Scalar(_) | BackendRepr::ScalarPair(_, _)
+ if repr.scalar_align(dl).unwrap() != align.abi =>
+ {
BackendRepr::Memory { sized: true }
- } else {
- abi
}
- }
+ // Vectors require at least element alignment, else disable the opt
+ BackendRepr::Vector { element, count: _ } if element.align(dl).abi > align.abi => {
+ BackendRepr::Memory { sized: true }
+ }
+ // the alignment tests passed and we can use this
+ BackendRepr::Scalar(..)
+ | BackendRepr::ScalarPair(..)
+ | BackendRepr::Vector { .. }
+ | BackendRepr::Memory { .. } => repr,
+ },
};
let Some(union_field_count) = NonZeroUsize::new(only_variant.len()) else {
@@ -397,8 +409,9 @@ impl LayoutCalculator {
Ok(LayoutData {
variants: Variants::Single { index: only_variant_idx },
fields: FieldsShape::Union(union_field_count),
- backend_repr: abi,
+ backend_repr,
largest_niche: None,
+ uninhabited: false,
align,
size: size.align_to(align.abi),
max_repr_align,
@@ -446,7 +459,6 @@ impl LayoutCalculator {
Scalar::Union { .. } => {}
};
match &mut st.backend_repr {
- BackendRepr::Uninhabited => {}
BackendRepr::Scalar(scalar) => hide_niches(scalar),
BackendRepr::ScalarPair(a, b) => {
hide_niches(a);
@@ -638,9 +650,8 @@ impl LayoutCalculator {
let same_size = size == variant_layouts[largest_variant_index].size;
let same_align = align == variant_layouts[largest_variant_index].align;
- let abi = if variant_layouts.iter().all(|v| v.is_uninhabited()) {
- BackendRepr::Uninhabited
- } else if same_size && same_align && others_zst {
+ let uninhabited = variant_layouts.iter().all(|v| v.is_uninhabited());
+ let abi = if same_size && same_align && others_zst {
match variant_layouts[largest_variant_index].backend_repr {
// When the total alignment and size match, we can use the
// same ABI as the scalar variant with the reserved niche.
@@ -682,6 +693,7 @@ impl LayoutCalculator {
},
backend_repr: abi,
largest_niche,
+ uninhabited,
size,
align,
max_repr_align,
@@ -852,9 +864,8 @@ impl LayoutCalculator {
};
let mut abi = BackendRepr::Memory { sized: true };
- if layout_variants.iter().all(|v| v.is_uninhabited()) {
- abi = BackendRepr::Uninhabited;
- } else if tag.size(dl) == size {
+ let uninhabited = layout_variants.iter().all(|v| v.is_uninhabited());
+ if tag.size(dl) == size {
// Make sure we only use scalar layout when the enum is entirely its
// own tag (i.e. it has no padding nor any non-ZST variant fields).
abi = BackendRepr::Scalar(tag);
@@ -994,6 +1005,7 @@ impl LayoutCalculator {
memory_index: [0].into(),
},
largest_niche,
+ uninhabited,
backend_repr: abi,
align,
size,
@@ -1058,7 +1070,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 +1084,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.
@@ -1354,9 +1366,7 @@ impl LayoutCalculator {
_ => {}
}
}
- if fields.iter().any(|f| f.is_uninhabited()) {
- abi = BackendRepr::Uninhabited;
- }
+ let uninhabited = fields.iter().any(|f| f.is_uninhabited());
let unadjusted_abi_align = if repr.transparent() {
match layout_of_single_non_zst_field {
@@ -1377,6 +1387,7 @@ impl LayoutCalculator {
fields: FieldsShape::Arbitrary { offsets, memory_index },
backend_repr: abi,
largest_niche,
+ uninhabited,
align,
size,
max_repr_align,
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index da1c706d67cc4..81e4e255f3799 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 {
@@ -328,19 +329,19 @@ impl TargetDataLayout {
[p] if p.starts_with('P') => {
dl.instruction_address_space = parse_address_space(&p[1..], "P")?
}
- ["a", ref a @ ..] => dl.aggregate_align = parse_align(a, "a")?,
- ["f16", ref a @ ..] => dl.f16_align = parse_align(a, "f16")?,
- ["f32", ref a @ ..] => dl.f32_align = parse_align(a, "f32")?,
- ["f64", ref a @ ..] => dl.f64_align = parse_align(a, "f64")?,
- ["f128", ref a @ ..] => dl.f128_align = parse_align(a, "f128")?,
+ ["a", a @ ..] => dl.aggregate_align = parse_align(a, "a")?,
+ ["f16", a @ ..] => dl.f16_align = parse_align(a, "f16")?,
+ ["f32", a @ ..] => dl.f32_align = parse_align(a, "f32")?,
+ ["f64", a @ ..] => dl.f64_align = parse_align(a, "f64")?,
+ ["f128", a @ ..] => dl.f128_align = parse_align(a, "f128")?,
// FIXME(erikdesjardins): we should be parsing nonzero address spaces
// this will require replacing TargetDataLayout::{pointer_size,pointer_align}
// with e.g. `fn pointer_size_in(AddressSpace)`
- [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => {
+ [p @ "p", s, a @ ..] | [p @ "p0", s, a @ ..] => {
dl.pointer_size = parse_size(s, p)?;
dl.pointer_align = parse_align(a, p)?;
}
- [s, ref a @ ..] if s.starts_with('i') => {
+ [s, a @ ..] if s.starts_with('i') => {
let Ok(bits) = s[1..].parse::() else {
parse_size(&s[1..], "i")?; // For the user error.
continue;
@@ -361,7 +362,7 @@ impl TargetDataLayout {
dl.i128_align = a;
}
}
- [s, ref a @ ..] if s.starts_with('v') => {
+ [s, a @ ..] if s.starts_with('v') => {
let v_size = parse_size(&s[1..], "v")?;
let a = parse_align(a, s)?;
if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
@@ -407,16 +408,21 @@ impl TargetDataLayout {
}
}
+ /// psABI-mandated alignment for a vector type, if any
#[inline]
- pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
- for &(size, align) in &self.vector_align {
- if size == vec_size {
- return align;
- }
- }
- // Default to natural alignment, which is what LLVM does.
- // That is, use the size, rounded up to a power of 2.
- AbiAndPrefAlign::new(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap())
+ fn cabi_vector_align(&self, vec_size: Size) -> Option {
+ self.vector_align
+ .iter()
+ .find(|(size, _align)| *size == vec_size)
+ .map(|(_size, align)| *align)
+ }
+
+ /// an alignment resembling the one LLVM would pick for a vector
+ #[inline]
+ pub fn llvmlike_vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
+ self.cabi_vector_align(vec_size).unwrap_or(AbiAndPrefAlign::new(
+ Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap(),
+ ))
}
}
@@ -809,20 +815,19 @@ impl Align {
self.bits().try_into().unwrap()
}
- /// Computes the best alignment possible for the given offset
- /// (the largest power of two that the offset is a multiple of).
+ /// Obtain the greatest factor of `size` that is an alignment
+ /// (the largest power of two the Size is a multiple of).
///
- /// N.B., for an offset of `0`, this happens to return `2^64`.
+ /// Note that all numbers are factors of 0
#[inline]
- pub fn max_for_offset(offset: Size) -> Align {
- Align { pow2: offset.bytes().trailing_zeros() as u8 }
+ pub fn max_aligned_factor(size: Size) -> Align {
+ Align { pow2: size.bytes().trailing_zeros() as u8 }
}
- /// Lower the alignment, if necessary, such that the given offset
- /// is aligned to it (the offset is a multiple of the alignment).
+ /// Reduces Align to an aligned factor of `size`.
#[inline]
- pub fn restrict_for_offset(self, offset: Size) -> Align {
- self.min(Align::max_for_offset(offset))
+ pub fn restrict_for_offset(self, size: Size) -> Align {
+ self.min(Align::max_aligned_factor(size))
}
}
@@ -1344,7 +1349,7 @@ impl FieldsShape {
/// Gets source indices of the fields by increasing offsets.
#[inline]
- pub fn index_by_increasing_offset(&self) -> impl ExactSizeIterator- + '_ {
+ pub fn index_by_increasing_offset(&self) -> impl ExactSizeIterator
- {
let mut inverse_small = [0u8; 64];
let mut inverse_big = IndexVec::new();
let use_small = self.count() <= inverse_small.len();
@@ -1403,7 +1408,6 @@ impl AddressSpace {
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum BackendRepr {
- Uninhabited,
Scalar(Scalar),
ScalarPair(Scalar, Scalar),
Vector {
@@ -1422,10 +1426,9 @@ impl BackendRepr {
#[inline]
pub fn is_unsized(&self) -> bool {
match *self {
- BackendRepr::Uninhabited
- | BackendRepr::Scalar(_)
- | BackendRepr::ScalarPair(..)
- | BackendRepr::Vector { .. } => false,
+ BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => {
+ false
+ }
BackendRepr::Memory { sized } => !sized,
}
}
@@ -1444,12 +1447,6 @@ impl BackendRepr {
}
}
- /// Returns `true` if this is an uninhabited type
- #[inline]
- pub fn is_uninhabited(&self) -> bool {
- matches!(*self, BackendRepr::Uninhabited)
- }
-
/// Returns `true` if this is a scalar type
#[inline]
pub fn is_scalar(&self) -> bool {
@@ -1462,37 +1459,38 @@ impl BackendRepr {
matches!(*self, BackendRepr::Scalar(s) if s.is_bool())
}
- /// Returns the fixed alignment of this ABI, if any is mandated.
- pub fn inherent_align(&self, cx: &C) -> Option {
- Some(match *self {
- BackendRepr::Scalar(s) => s.align(cx),
- BackendRepr::ScalarPair(s1, s2) => s1.align(cx).max(s2.align(cx)),
- BackendRepr::Vector { element, count } => {
- cx.data_layout().vector_align(element.size(cx) * count)
- }
- BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None,
- })
+ /// The psABI alignment for a `Scalar` or `ScalarPair`
+ ///
+ /// `None` for other variants.
+ pub fn scalar_align(&self, cx: &C) -> Option {
+ match *self {
+ BackendRepr::Scalar(s) => Some(s.align(cx).abi),
+ BackendRepr::ScalarPair(s1, s2) => Some(s1.align(cx).max(s2.align(cx)).abi),
+ // The align of a Vector can vary in surprising ways
+ BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => None,
+ }
}
- /// Returns the fixed size of this ABI, if any is mandated.
- pub fn inherent_size(&self, cx: &C) -> Option {
- Some(match *self {
- BackendRepr::Scalar(s) => {
- // No padding in scalars.
- s.size(cx)
- }
+ /// The psABI size for a `Scalar` or `ScalarPair`
+ ///
+ /// `None` for other variants
+ pub fn scalar_size(&self, cx: &C) -> Option {
+ match *self {
+ // No padding in scalars.
+ BackendRepr::Scalar(s) => Some(s.size(cx)),
+ // May have some padding between the pair.
BackendRepr::ScalarPair(s1, s2) => {
- // May have some padding between the pair.
let field2_offset = s1.size(cx).align_to(s2.align(cx).abi);
- (field2_offset + s2.size(cx)).align_to(self.inherent_align(cx)?.abi)
+ let size = (field2_offset + s2.size(cx)).align_to(
+ self.scalar_align(cx)
+ // We absolutely must have an answer here or everything is FUBAR.
+ .unwrap(),
+ );
+ Some(size)
}
- BackendRepr::Vector { element, count } => {
- // No padding in vectors, except possibly for trailing padding
- // to make the size a multiple of align (e.g. for vectors of size 3).
- (element.size(cx) * count).align_to(self.inherent_align(cx)?.abi)
- }
- BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None,
- })
+ // The size of a Vector can vary in surprising ways
+ BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => None,
+ }
}
/// Discard validity range information and allow undef.
@@ -1505,9 +1503,7 @@ impl BackendRepr {
BackendRepr::Vector { element, count } => {
BackendRepr::Vector { element: element.to_union(), count }
}
- BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
- BackendRepr::Memory { sized: true }
- }
+ BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true },
}
}
@@ -1703,6 +1699,11 @@ pub struct LayoutData {
/// The leaf scalar with the largest number of invalid values
/// (i.e. outside of its `valid_range`), if it exists.
pub largest_niche: Option,
+ /// Is this type known to be uninhabted?
+ ///
+ /// This is separate from BackendRepr because uninhabited return types can affect ABI,
+ /// especially in the case of by-pointer struct returns, which allocate stack even when unused.
+ pub uninhabited: bool,
pub align: AbiAndPrefAlign,
pub size: Size,
@@ -1727,21 +1728,21 @@ 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 {
/// Returns `true` if this is an aggregate type (including a ScalarPair!)
pub fn is_aggregate(&self) -> bool {
match self.backend_repr {
- BackendRepr::Uninhabited | BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false,
+ BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false,
BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => true,
}
}
/// Returns `true` if this is an uninhabited type
pub fn is_uninhabited(&self) -> bool {
- self.backend_repr.is_uninhabited()
+ self.uninhabited
}
pub fn scalar(cx: &C, scalar: Scalar) -> Self {
@@ -1777,11 +1778,12 @@ impl LayoutData {
fields: FieldsShape::Primitive,
backend_repr: BackendRepr::Scalar(scalar),
largest_niche,
+ uninhabited: false,
size,
align,
max_repr_align: None,
unadjusted_abi_align: align.abi,
- randomization_seed,
+ randomization_seed: Hash64::new(randomization_seed),
}
}
}
@@ -1801,10 +1803,11 @@ where
backend_repr,
fields,
largest_niche,
+ uninhabited,
variants,
max_repr_align,
unadjusted_abi_align,
- ref randomization_seed,
+ randomization_seed,
} = self;
f.debug_struct("Layout")
.field("size", size)
@@ -1812,6 +1815,7 @@ where
.field("abi", backend_repr)
.field("fields", fields)
.field("largest_niche", largest_niche)
+ .field("uninhabited", uninhabited)
.field("variants", variants)
.field("max_repr_align", max_repr_align)
.field("unadjusted_abi_align", unadjusted_abi_align)
@@ -1876,7 +1880,6 @@ impl LayoutData {
BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => {
false
}
- BackendRepr::Uninhabited => self.size.bytes() == 0,
BackendRepr::Memory { sized } => sized && self.size.bytes() == 0,
}
}
diff --git a/compiler/rustc_arena/Cargo.toml b/compiler/rustc_arena/Cargo.toml
index 382ab2b077547..bbcd8ea6d389d 100644
--- a/compiler/rustc_arena/Cargo.toml
+++ b/compiler/rustc_arena/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_arena"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml
index 34c612dac692b..902287d032802 100644
--- a/compiler/rustc_ast/Cargo.toml
+++ b/compiler/rustc_ast/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_ast"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 60f8c6e10481b..346edc87c86bc 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/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs
index 70222f4acabe1..c8ec185ee5e29 100644
--- a/compiler/rustc_ast/src/expand/autodiff_attrs.rs
+++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs
@@ -17,7 +17,6 @@ use crate::{Ty, TyKind};
/// functions. The proper solution is to recognize and resolve this DAG of autodiff invocations,
/// as it's already done in the C++ and Julia frontend of Enzyme.
///
-/// (FIXME) remove *First variants.
/// Documentation for using [reverse](https://enzyme.mit.edu/rust/rev.html) and
/// [forward](https://enzyme.mit.edu/rust/fwd.html) mode is available online.
#[derive(Clone, Copy, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index de9f049704a4f..40b29fdba2506 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 36a7b7d87892f..97d121909f8dd 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 50f10d083a041..1123ea3a449b6 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/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 3242d4145959d..1cb32b56875c3 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -597,7 +597,7 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
visit_opt!(visitor, visit_ident, rename);
}
UseTreeKind::Glob => {}
- UseTreeKind::Nested { ref items, span: _ } => {
+ UseTreeKind::Nested { items, span: _ } => {
for &(ref nested_tree, nested_id) in items {
try_visit!(visitor.visit_use_tree(nested_tree, nested_id, true));
}
diff --git a/compiler/rustc_ast_ir/Cargo.toml b/compiler/rustc_ast_ir/Cargo.toml
index 1905574073f13..f54e9687d8c7f 100644
--- a/compiler/rustc_ast_ir/Cargo.toml
+++ b/compiler/rustc_ast_ir/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_ast_ir"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs
index ff9d940ce9f28..9884e191ea7bd 100644
--- a/compiler/rustc_ast_ir/src/lib.rs
+++ b/compiler/rustc_ast_ir/src/lib.rs
@@ -1,3 +1,10 @@
+//! Common utilities shared by both `rustc_ast` and `rustc_type_ir`.
+//!
+//! Don't depend on this crate directly; both of those crates should re-export
+//! the functionality. Additionally, if you're in scope of `rustc_middle`, then
+//! prefer imports via that too, to avoid needing to directly depend on (e.g.)
+//! `rustc_type_ir` for a single import.
+
// tidy-alphabetical-start
#![cfg_attr(feature = "nightly", allow(internal_features))]
#![cfg_attr(feature = "nightly", feature(never_type))]
diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml
index ce95f4dfa1b82..3215ce6b0cb47 100644
--- a/compiler/rustc_ast_lowering/Cargo.toml
+++ b/compiler/rustc_ast_lowering/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_ast_lowering"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[lib]
doctest = false
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 96c230ec243a2..cfd32fc066f41 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -1,13 +1,12 @@
use std::collections::hash_map::Entry;
use std::fmt::Write;
-use rustc_ast::ptr::P;
use rustc_ast::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_session::parse::feature_err;
-use rustc_span::{Span, kw, sym};
+use rustc_span::{Span, sym};
use rustc_target::asm;
use super::LoweringContext;
@@ -230,20 +229,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
tokens: None,
};
- // Wrap the expression in an AnonConst.
- let parent_def_id = self.current_hir_id_owner.def_id;
- let node_id = self.next_node_id();
- self.create_def(
- parent_def_id,
- node_id,
- kw::Empty,
- DefKind::AnonConst,
- *op_sp,
- );
- let anon_const = AnonConst { id: node_id, value: P(expr) };
- hir::InlineAsmOperand::SymFn {
- anon_const: self.lower_anon_const_to_anon_const(&anon_const),
- }
+ hir::InlineAsmOperand::SymFn { expr: self.lower_expr(&expr) }
}
}
InlineAsmOperand::Label { block } => {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index bc2db41546989..1d3db64b47ed9 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -251,7 +251,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
.arena
.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
},
- ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)),
+ ItemKind::GlobalAsm(asm) => {
+ let asm = self.lower_inline_asm(span, asm);
+ let fake_body =
+ self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm))));
+ hir::ItemKind::GlobalAsm { asm, fake_body }
+ }
ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
// We lower
//
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 1c777111896dc..b865cbedbbb78 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -45,7 +45,6 @@ use std::sync::Arc;
use rustc_ast::node_id::NodeMap;
use rustc_ast::{self as ast, *};
-use rustc_data_structures::captures::Captures;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -1821,11 +1820,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.new_named_lifetime_with_res(new_id, ident, res)
}
- fn lower_generic_params_mut<'s>(
- &'s mut self,
- params: &'s [GenericParam],
+ fn lower_generic_params_mut(
+ &mut self,
+ params: &[GenericParam],
source: hir::GenericParamSource,
- ) -> impl Iterator
- > + Captures<'a> + Captures<'s> {
+ ) -> impl Iterator
- > {
params.iter().map(move |param| self.lower_generic_param(param, source))
}
@@ -1986,11 +1985,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
}
- fn lower_param_bounds_mut<'s>(
- &'s mut self,
- bounds: &'s [GenericBound],
+ fn lower_param_bounds_mut(
+ &mut self,
+ bounds: &[GenericBound],
itctx: ImplTraitContext,
- ) -> impl Iterator
- > + Captures<'s> + Captures<'a> {
+ ) -> impl Iterator
- > {
bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx))
}
diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml
index e4c227532085f..c738cb2aa2fd4 100644
--- a/compiler/rustc_ast_passes/Cargo.toml
+++ b/compiler/rustc_ast_passes/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_ast_passes"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 0eb2043eaa356..6eb9bb1c0dafa 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -804,7 +804,14 @@ pub(crate) struct NegativeBoundWithParentheticalNotation {
pub(crate) struct MatchArmWithNoBody {
#[primary_span]
pub span: Span,
- #[suggestion(code = " => todo!(),", applicability = "has-placeholders")]
+ // We include the braces around `todo!()` so that a comma is optional, and we don't have to have
+ // any logic looking at the arm being replaced if there was a comma already or not for the
+ // resulting code to be correct.
+ #[suggestion(
+ code = " => {{ todo!() }}",
+ applicability = "has-placeholders",
+ style = "verbose"
+ )]
pub suggestion: Span,
}
diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml
index f290fedcd8b9a..2634dd1fdf93e 100644
--- a/compiler/rustc_ast_pretty/Cargo.toml
+++ b/compiler/rustc_ast_pretty/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_ast_pretty"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 0bf5de3ef8985..44e956dc37f3e 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -424,20 +424,23 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere
self.ann_post(ident)
}
- fn strsep(
+ fn strsep<'x, T: 'x, F, I>(
&mut self,
sep: &'static str,
space_before: bool,
b: Breaks,
- elts: &[T],
+ elts: I,
mut op: F,
) where
F: FnMut(&mut Self, &T),
+ I: IntoIterator
- ,
{
+ let mut it = elts.into_iter();
+
self.rbox(0, b);
- if let Some((first, rest)) = elts.split_first() {
+ if let Some(first) = it.next() {
op(self, first);
- for elt in rest {
+ for elt in it {
if space_before {
self.space();
}
@@ -448,9 +451,10 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere
self.end();
}
- fn commasep(&mut self, b: Breaks, elts: &[T], op: F)
+ fn commasep<'x, T: 'x, F, I>(&mut self, b: Breaks, elts: I, op: F)
where
F: FnMut(&mut Self, &T),
+ I: IntoIterator
- ,
{
self.strsep(",", false, b, elts, op)
}
diff --git a/compiler/rustc_attr_data_structures/Cargo.toml b/compiler/rustc_attr_data_structures/Cargo.toml
index 2ee58f24470e9..19d0d5a306d6e 100644
--- a/compiler/rustc_attr_data_structures/Cargo.toml
+++ b/compiler/rustc_attr_data_structures/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_attr_data_structures"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml
index 7ccedf40c3fa9..f681e9397d9f1 100644
--- a/compiler/rustc_attr_parsing/Cargo.toml
+++ b/compiler/rustc_attr_parsing/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_attr_parsing"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
index 471168ed4f56d..13d246b08a8f4 100644
--- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
@@ -4,25 +4,25 @@ use rustc_span::{Symbol, sym};
use crate::session_diagnostics;
-pub fn allow_internal_unstable<'a>(
- sess: &'a Session,
- attrs: &'a [impl AttributeExt],
-) -> impl Iterator
- + 'a {
+pub fn allow_internal_unstable(
+ sess: &Session,
+ attrs: &[impl AttributeExt],
+) -> impl Iterator
- {
allow_unstable(sess, attrs, sym::allow_internal_unstable)
}
-pub fn rustc_allow_const_fn_unstable<'a>(
- sess: &'a Session,
- attrs: &'a [impl AttributeExt],
-) -> impl Iterator
- + 'a {
+pub fn rustc_allow_const_fn_unstable(
+ sess: &Session,
+ attrs: &[impl AttributeExt],
+) -> impl Iterator
- {
allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable)
}
-fn allow_unstable<'a>(
- sess: &'a Session,
- attrs: &'a [impl AttributeExt],
+fn allow_unstable(
+ sess: &Session,
+ attrs: &[impl AttributeExt],
symbol: Symbol,
-) -> impl Iterator
- + 'a {
+) -> impl Iterator
- {
let attrs = filter_by_name(attrs, symbol);
let list = attrs
.filter_map(move |attr| {
diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml
index c35556dcf5bf2..cb0e145386b83 100644
--- a/compiler/rustc_baked_icu_data/Cargo.toml
+++ b/compiler/rustc_baked_icu_data/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_baked_icu_data"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml
index 89154bf2c23c4..9e7d55180a233 100644
--- a/compiler/rustc_borrowck/Cargo.toml
+++ b/compiler/rustc_borrowck/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_borrowck"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 59c76cb7f2bbc..f33f2ab58e05f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -8,7 +8,6 @@ use std::ops::ControlFlow;
use either::Either;
use hir::{ClosureKind, Path};
-use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, MultiSpan, struct_span_code_err};
@@ -18,12 +17,11 @@ 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::{
@@ -386,8 +384,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
hir::intravisit::walk_pat(self, p);
}
}
- let hir = self.infcx.tcx.hir();
- if let Some(body) = hir.maybe_body_owned_by(self.mir_def_id()) {
+ let tcx = self.infcx.tcx;
+ 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,13 +394,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
expr: None,
pat: None,
parent_pat: None,
- tcx: self.infcx.tcx,
+ tcx,
};
finder.visit_expr(expr);
if let Some(span) = span
&& let Some(expr) = finder.expr
{
- for (_, expr) in hir.parent_iter(expr.hir_id) {
+ for (_, expr) in tcx.hir_parent_iter(expr.hir_id) {
if let hir::Node::Expr(expr) = expr {
if expr.span.contains(span) {
// If the let binding occurs within the same loop, then that
@@ -782,9 +780,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;
@@ -969,7 +967,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let mut parent = None;
// The top-most loop where the moved expression could be moved to a new binding.
let mut outer_most_loop: Option<&hir::Expr<'_>> = None;
- for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
+ for (_, node) in tcx.hir_parent_iter(expr.hir_id) {
let e = match node {
hir::Node::Expr(e) => e,
hir::Node::LetStmt(hir::LetStmt { els: Some(els), .. }) => {
@@ -1021,8 +1019,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
}
let loop_count: usize = tcx
- .hir()
- .parent_iter(expr.hir_id)
+ .hir_parent_iter(expr.hir_id)
.map(|(_, node)| match node {
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Loop(..), .. }) => 1,
_ => 0,
@@ -1048,8 +1045,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
.collect::>();
// All of the spans for the loops above the expression with the move error.
let loop_spans: Vec<_> = tcx
- .hir()
- .parent_iter(expr.hir_id)
+ .hir_parent_iter(expr.hir_id)
.filter_map(|(_, node)| match node {
hir::Node::Expr(hir::Expr { span, kind: hir::ExprKind::Loop(..), .. }) => {
Some(*span)
@@ -1334,7 +1330,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
fn in_move_closure(&self, expr: &hir::Expr<'_>) -> bool {
- for (_, node) in self.infcx.tcx.hir().parent_iter(expr.hir_id) {
+ for (_, node) in self.infcx.tcx.hir_parent_iter(expr.hir_id) {
if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) = node
&& let hir::CaptureBy::Value { .. } = closure.capture_clause
{
@@ -2118,7 +2114,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
issued_span: Span,
) {
let tcx = self.infcx.tcx;
- let hir = tcx.hir();
let has_split_at_mut = |ty: Ty<'tcx>| {
let ty = ty.peel_refs();
@@ -2171,7 +2166,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
return;
};
- let Some(object) = hir.parent_id_iter(index1.hir_id).find_map(|id| {
+ let Some(object) = tcx.hir_parent_id_iter(index1.hir_id).find_map(|id| {
if let hir::Node::Expr(expr) = tcx.hir_node(id)
&& let hir::ExprKind::Index(obj, ..) = expr.kind
{
@@ -2189,7 +2184,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
return;
};
- let Some(swap_call) = hir.parent_id_iter(object.hir_id).find_map(|id| {
+ let Some(swap_call) = tcx.hir_parent_id_iter(object.hir_id).find_map(|id| {
if let hir::Node::Expr(call) = tcx.hir_node(id)
&& let hir::ExprKind::Call(callee, ..) = call.kind
&& let hir::ExprKind::Path(qpath) = callee.kind
@@ -2443,7 +2438,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;
@@ -2522,7 +2516,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()
})
@@ -2622,7 +2616,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
if let hir::Pat { kind: hir::PatKind::Binding(_, hir_id, _ident, _), .. } =
local.pat
&& let Some(init) = local.init
- && let hir::Expr {
+ && let &hir::Expr {
kind:
hir::ExprKind::Closure(&hir::Closure {
kind: hir::ClosureKind::Closure,
@@ -3535,10 +3529,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
location: Location,
mpi: MovePathIndex,
) -> (Vec, Vec) {
- fn predecessor_locations<'a, 'tcx>(
- body: &'a mir::Body<'tcx>,
+ fn predecessor_locations<'tcx>(
+ body: &mir::Body<'tcx>,
location: Location,
- ) -> impl Iterator
- + Captures<'tcx> + 'a {
+ ) -> impl Iterator
- {
if location.statement_index == 0 {
let predecessors = body.basic_blocks.predecessors()[location.block].to_vec();
Either::Left(predecessors.into_iter().map(move |bb| body.terminator_loc(bb)))
@@ -4178,7 +4172,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 a88b27f24767e..f77dda0d386aa 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -117,7 +117,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
let local_decl = &body.local_decls[dropped_local];
if let &LocalInfo::IfThenRescopeTemp { if_then } = local_decl.local_info()
- && let Some((_, hir::Node::Expr(expr))) = tcx.hir().parent_iter(if_then).next()
+ && let Some((_, hir::Node::Expr(expr))) = tcx.hir_parent_iter(if_then).next()
&& let hir::ExprKind::If(cond, conseq, alt) = expr.kind
&& let hir::ExprKind::Let(&hir::LetExpr {
span: _,
@@ -262,7 +262,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
if let hir::ExprKind::If(cond, _conseq, _alt)
| hir::ExprKind::Loop(
- hir::Block {
+ &hir::Block {
expr:
Some(&hir::Expr {
kind: hir::ExprKind::If(cond, _conseq, _alt),
@@ -522,7 +522,7 @@ fn suggest_rewrite_if_let(
);
if expr.span.can_be_used_for_suggestions() && conseq.span.can_be_used_for_suggestions() {
let needs_block = if let Some(hir::Node::Expr(expr)) =
- alt.and_then(|alt| tcx.hir().parent_iter(alt.hir_id).next()).map(|(_, node)| node)
+ alt.and_then(|alt| tcx.hir_parent_iter(alt.hir_id).next()).map(|(_, node)| node)
{
matches!(expr.kind, hir::ExprKind::If(..))
} else {
diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
index 26a090f5579ce..96f48840468e5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
@@ -1,7 +1,7 @@
use std::collections::VecDeque;
use rustc_data_structures::fx::FxIndexSet;
-use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
+use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{self, Body, Local, Location};
use rustc_middle::ty::{RegionVid, TyCtxt};
@@ -45,7 +45,22 @@ impl<'a, 'tcx> UseFinder<'a, 'tcx> {
let block_data = &self.body[p.block];
- match self.def_use(p, block_data.visitable(p.statement_index)) {
+ let mut visitor = DefUseVisitor {
+ body: self.body,
+ tcx: self.tcx,
+ region_vid: self.region_vid,
+ def_use_result: None,
+ };
+
+ let is_statement = p.statement_index < block_data.statements.len();
+
+ if is_statement {
+ visitor.visit_statement(&block_data.statements[p.statement_index], p);
+ } else {
+ visitor.visit_terminator(block_data.terminator.as_ref().unwrap(), p);
+ }
+
+ match visitor.def_use_result {
Some(DefUseResult::Def) => {}
Some(DefUseResult::UseLive { local }) => {
@@ -57,7 +72,7 @@ impl<'a, 'tcx> UseFinder<'a, 'tcx> {
}
None => {
- if p.statement_index < block_data.statements.len() {
+ if is_statement {
queue.push_back(p.successor_within_block());
} else {
queue.extend(
@@ -77,19 +92,6 @@ impl<'a, 'tcx> UseFinder<'a, 'tcx> {
None
}
-
- fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option {
- let mut visitor = DefUseVisitor {
- body: self.body,
- tcx: self.tcx,
- region_vid: self.region_vid,
- def_use_result: None,
- };
-
- thing.apply(location, &mut visitor);
-
- visitor.def_use_result
- }
}
struct DefUseVisitor<'a, 'tcx> {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 07ea369c5c7f2..d1f238331d56f 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;
@@ -1127,7 +1126,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let hir_id = self.infcx.tcx.local_def_id_to_hir_id(def_id);
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
- if let hir::ExprKind::Closure(&hir::Closure { kind, fn_decl_span, .. }) = expr {
+ if let &hir::ExprKind::Closure(&hir::Closure { kind, fn_decl_span, .. }) = expr {
for (captured_place, place) in
self.infcx.tcx.closure_captures(def_id).iter().zip(places)
{
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 38f22473edfac..5e83d2ffa97a1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -388,7 +388,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// Search for an appropriate place for the structured `.clone()` suggestion to be applied.
// If we encounter a statement before the borrow error, we insert a statement there.
- for (_, node) in tcx.hir().parent_iter(closure_expr.hir_id) {
+ for (_, node) in tcx.hir_parent_iter(closure_expr.hir_id) {
if let Node::Stmt(stmt) = node {
let padding = tcx
.sess
@@ -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,
- tcx: self.infcx.tcx,
+ 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 fc782ce642497..be4a7736b1c20 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -404,7 +404,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
pat.kind
{
if upvar_ident.name == kw::SelfLower {
- for (_, node) in self.infcx.tcx.hir().parent_iter(upvar_hir_id) {
+ for (_, node) in self.infcx.tcx.hir_parent_iter(upvar_hir_id) {
if let Some(fn_decl) = node.fn_decl() {
if !matches!(
fn_decl.implicit_self,
@@ -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
@@ -937,12 +934,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
err.span_label(sp, format!("cannot {act}"));
let tcx = self.infcx.tcx;
- let hir = tcx.hir();
let closure_id = self.mir_hir_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 = hir.enclosing_body_owner(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
@@ -1020,10 +1016,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
}
- if look_at_return && hir.get_fn_id_for_return_block(closure_id).is_some() {
+ if look_at_return && tcx.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 tcx.hir_node_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
+ match tcx.hir_node_by_def_id(tcx.hir_get_parent_item(fn_call_id).def_id) {
hir::Node::Item(hir::Item {
ident, kind: hir::ItemKind::Fn { sig, .. }, ..
})
@@ -1275,7 +1271,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 d3c91cbdee9cf..55b6367f35ff8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -1169,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 ccd13badad742..be28f84debd90 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
@@ -671,7 +671,6 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
#[instrument(level = "trace", skip(self))]
fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option {
let tcx = self.infcx.tcx;
- let hir = tcx.hir();
let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
@@ -682,7 +681,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
let mir_hir_id = self.mir_hir_id();
let (return_span, mir_description, hir_ty) = match tcx.hir_node(mir_hir_id) {
- hir::Node::Expr(hir::Expr {
+ hir::Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl, kind, fn_decl_span, .. }),
..
}) => {
@@ -711,7 +710,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
hir::CoroutineSource::Fn,
)) => {
let parent_item =
- tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
+ tcx.hir_node_by_def_id(tcx.hir_get_parent_item(mir_hir_id).def_id);
let output = &parent_item
.fn_decl()
.expect("coroutine lowered from async fn should be in fn")
@@ -741,7 +740,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
hir::CoroutineSource::Fn,
)) => {
let parent_item =
- tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
+ tcx.hir_node_by_def_id(tcx.hir_get_parent_item(mir_hir_id).def_id);
let output = &parent_item
.fn_decl()
.expect("coroutine lowered from gen fn should be in fn")
@@ -768,7 +767,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
hir::CoroutineSource::Fn,
)) => {
let parent_item =
- tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
+ tcx.hir_node_by_def_id(tcx.hir_get_parent_item(mir_hir_id).def_id);
let output = &parent_item
.fn_decl()
.expect("coroutine lowered from async gen fn should be in fn")
@@ -874,7 +873,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
.name;
let yield_span = match tcx.hir_node(self.mir_hir_id()) {
- hir::Node::Expr(hir::Expr {
+ hir::Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
..
}) => tcx.sess.source_map().end_point(fn_decl_span),
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 53cf4f34ae794..a98984a4b4c7a 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/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs
index a0adf471fd31f..bdd0f6fe11e0f 100644
--- a/compiler/rustc_borrowck/src/member_constraints.rs
+++ b/compiler/rustc_borrowck/src/member_constraints.rs
@@ -1,7 +1,6 @@
use std::hash::Hash;
use std::ops::Index;
-use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexMap;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::ty::{self, Ty};
@@ -147,9 +146,7 @@ impl<'tcx, R> MemberConstraintSet<'tcx, R>
where
R: Copy + Hash + Eq,
{
- pub(crate) fn all_indices(
- &self,
- ) -> impl Iterator
- + Captures<'tcx> + '_ {
+ pub(crate) fn all_indices(&self) -> impl Iterator
- {
self.constraints.indices()
}
@@ -159,7 +156,7 @@ where
pub(crate) fn indices(
&self,
member_region_vid: R,
- ) -> impl Iterator
- + Captures<'tcx> + '_ {
+ ) -> impl Iterator
- {
let mut next = self.first_constraints.get(&member_region_vid).cloned();
std::iter::from_fn(move || -> Option {
if let Some(current) = next {
diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs
index 5f9fa3612b8d1..aa64a7c4e2a68 100644
--- a/compiler/rustc_borrowck/src/polonius/dump.rs
+++ b/compiler/rustc_borrowck/src/polonius/dump.rs
@@ -226,7 +226,7 @@ fn emit_polonius_mir<'tcx>(
regioncx,
closure_region_requirements,
borrow_set,
- pass_where.clone(),
+ pass_where,
out,
)?;
diff --git a/compiler/rustc_borrowck/src/polonius/loan_liveness.rs b/compiler/rustc_borrowck/src/polonius/loan_liveness.rs
index 768c12a97a64e..5cd265e0db92d 100644
--- a/compiler/rustc_borrowck/src/polonius/loan_liveness.rs
+++ b/compiler/rustc_borrowck/src/polonius/loan_liveness.rs
@@ -175,7 +175,7 @@ impl LocalizedConstraintGraph {
}
/// Returns the outgoing edges of a given node, not its transitive closure.
- fn outgoing_edges(&self, node: LocalizedNode) -> impl Iterator
- + use<'_> {
+ fn outgoing_edges(&self, node: LocalizedNode) -> impl Iterator
- {
// The outgoing edges are:
// - the physical edges present at this node,
// - the materialized logical edges that exist virtually at all points for this node's
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index d2268c4779d63..a00fce08c9bac 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -576,9 +576,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
/// Returns an iterator over all the outlives constraints.
- pub(crate) fn outlives_constraints(
- &self,
- ) -> impl Iterator
- > + '_ {
+ pub(crate) fn outlives_constraints(&self) -> impl Iterator
- > {
self.constraints.outlives().iter().copied()
}
@@ -615,10 +613,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.scc_values.region_value_str(scc)
}
- pub(crate) fn placeholders_contained_in<'a>(
- &'a self,
+ pub(crate) fn placeholders_contained_in(
+ &self,
r: RegionVid,
- ) -> impl Iterator
- + 'a {
+ ) -> impl Iterator
- {
let scc = self.constraint_sccs.scc(r);
self.scc_values.placeholders_contained_in(scc)
}
@@ -1267,6 +1265,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/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
index d0cfe572d0876..b2ed8a3582796 100644
--- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
+++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
@@ -20,10 +20,7 @@ pub(crate) struct ReverseSccGraph {
impl ReverseSccGraph {
/// Find all universal regions that are required to outlive the given SCC.
- pub(super) fn upper_bounds<'a>(
- &'a self,
- scc0: ConstraintSccIndex,
- ) -> impl Iterator
- + 'a {
+ pub(super) fn upper_bounds(&self, scc0: ConstraintSccIndex) -> impl Iterator
- {
let mut duplicates = FxIndexSet::default();
graph::depth_first_search(&self.graph, scc0)
.flat_map(move |scc1| {
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index f1bcb353dc61c..d9ac5b5cb132a 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -88,7 +88,7 @@ impl LivenessValues {
}
/// Iterate through each region that has a value in this set.
- pub(crate) fn regions(&self) -> impl Iterator
- + '_ {
+ pub(crate) fn regions(&self) -> impl Iterator
- {
self.points.as_ref().expect("use with_specific_points").rows()
}
@@ -96,7 +96,7 @@ impl LivenessValues {
// We are passing query instability implications to the caller.
#[rustc_lint_query_instability]
#[allow(rustc::potential_query_instability)]
- pub(crate) fn live_regions_unordered(&self) -> impl Iterator
- + '_ {
+ pub(crate) fn live_regions_unordered(&self) -> impl Iterator
- {
self.live_regions.as_ref().unwrap().iter().copied()
}
@@ -143,7 +143,7 @@ impl LivenessValues {
}
/// Returns an iterator of all the points where `region` is live.
- fn live_points(&self, region: RegionVid) -> impl Iterator
- + '_ {
+ fn live_points(&self, region: RegionVid) -> impl Iterator
- {
let Some(points) = &self.points else {
unreachable!(
"Should be using LivenessValues::with_specific_points to ask whether live at a location"
@@ -340,7 +340,7 @@ impl RegionValues {
}
/// Returns the locations contained within a given region `r`.
- pub(crate) fn locations_outlived_by<'a>(&'a self, r: N) -> impl Iterator
- + 'a {
+ pub(crate) fn locations_outlived_by(&self, r: N) -> impl Iterator
- {
self.points.row(r).into_iter().flat_map(move |set| {
set.iter()
.take_while(move |&p| self.location_map.point_in_range(p))
@@ -349,18 +349,15 @@ impl RegionValues {
}
/// Returns just the universal regions that are contained in a given region's value.
- pub(crate) fn universal_regions_outlived_by<'a>(
- &'a self,
- r: N,
- ) -> impl Iterator
- + 'a {
+ pub(crate) fn universal_regions_outlived_by(&self, r: N) -> impl Iterator
- {
self.free_regions.row(r).into_iter().flat_map(|set| set.iter())
}
/// Returns all the elements contained in a given region's value.
- pub(crate) fn placeholders_contained_in<'a>(
- &'a self,
+ pub(crate) fn placeholders_contained_in(
+ &self,
r: N,
- ) -> impl Iterator
- + 'a {
+ ) -> impl Iterator
- {
self.placeholders
.row(r)
.into_iter()
@@ -369,10 +366,7 @@ impl RegionValues {
}
/// Returns all the elements contained in a given region's value.
- pub(crate) fn elements_contained_in<'a>(
- &'a self,
- r: N,
- ) -> impl Iterator
- + 'a {
+ pub(crate) fn elements_contained_in(&self, r: N) -> impl Iterator
- {
let points_iter = self.locations_outlived_by(r).map(RegionElement::Location);
let free_regions_iter =
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index efbae1e153537..eaac633b512d6 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -172,7 +172,7 @@ impl UniversalRegionRelations<'_> {
}
/// Returns the _non-transitive_ set of known `outlives` constraints between free regions.
- pub(crate) fn known_outlives(&self) -> impl Iterator
- + '_ {
+ pub(crate) fn known_outlives(&self) -> impl Iterator
- {
self.outlives.base_edges()
}
}
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
index 6182b68f6f411..9591da83708b7 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
@@ -54,7 +54,7 @@ rustc_index::newtype_index! {
fn appearances_iter(
first: Option,
appearances: &Appearances,
-) -> impl Iterator
- + '_ {
+) -> impl Iterator
- {
AppearancesIter { appearances, current: first }
}
@@ -107,17 +107,17 @@ impl LocalUseMap {
local_use_map
}
- pub(crate) fn defs(&self, local: Local) -> impl Iterator
- + '_ {
+ pub(crate) fn defs(&self, local: Local) -> impl Iterator
- {
appearances_iter(self.first_def_at[local], &self.appearances)
.map(move |aa| self.appearances[aa].point_index)
}
- pub(crate) fn uses(&self, local: Local) -> impl Iterator
- + '_ {
+ pub(crate) fn uses(&self, local: Local) -> impl Iterator
- {
appearances_iter(self.first_use_at[local], &self.appearances)
.map(move |aa| self.appearances[aa].point_index)
}
- pub(crate) fn drops(&self, local: Local) -> impl Iterator
- + '_ {
+ pub(crate) fn drops(&self, local: Local) -> impl Iterator
- {
appearances_iter(self.first_drop_at[local], &self.appearances)
.map(move |aa| self.appearances[aa].point_index)
}
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 62d49a62744e7..12e8be41614bd 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -3,7 +3,8 @@ use rustc_index::bit_set::DenseBitSet;
use rustc_index::interval::IntervalSet;
use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_infer::infer::outlives::for_liveness;
-use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
+use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Local, Location};
+use rustc_middle::span_bug;
use rustc_middle::traits::query::DropckOutlivesResult;
use rustc_middle::ty::relate::Relate;
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
@@ -11,7 +12,10 @@ use rustc_mir_dataflow::ResultsCursor;
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
-use rustc_span::DUMMY_SP;
+use rustc_span::{DUMMY_SP, Span};
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
+use rustc_trait_selection::traits::ObligationCtxt;
+use rustc_trait_selection::traits::query::dropck_outlives;
use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, TypeOpOutput};
use tracing::debug;
@@ -162,9 +166,10 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
fn dropck_boring_locals(&mut self, boring_locals: Vec) {
for local in boring_locals {
let local_ty = self.cx.body.local_decls[local].ty;
+ let local_span = self.cx.body.local_decls[local].source_info.span;
let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({
let typeck = &self.cx.typeck;
- move || LivenessContext::compute_drop_data(typeck, local_ty)
+ move || LivenessContext::compute_drop_data(typeck, local_ty, local_span)
});
drop_data.dropck_result.report_overflows(
@@ -522,9 +527,10 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
values::pretty_print_points(self.location_map, live_at.iter()),
);
+ let local_span = self.body.local_decls()[dropped_local].source_info.span;
let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
let typeck = &self.typeck;
- move || Self::compute_drop_data(typeck, dropped_ty)
+ move || Self::compute_drop_data(typeck, dropped_ty, local_span)
});
if let Some(data) = &drop_data.region_constraint_data {
@@ -589,19 +595,50 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
}
}
- fn compute_drop_data(typeck: &TypeChecker<'_, 'tcx>, dropped_ty: Ty<'tcx>) -> DropData<'tcx> {
- debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
+ fn compute_drop_data(
+ typeck: &TypeChecker<'_, 'tcx>,
+ dropped_ty: Ty<'tcx>,
+ span: Span,
+ ) -> DropData<'tcx> {
+ debug!("compute_drop_data(dropped_ty={:?})", dropped_ty);
+
+ let op = typeck.infcx.param_env.and(DropckOutlives { dropped_ty });
- match typeck
- .infcx
- .param_env
- .and(DropckOutlives { dropped_ty })
- .fully_perform(typeck.infcx, DUMMY_SP)
- {
+ match op.fully_perform(typeck.infcx, DUMMY_SP) {
Ok(TypeOpOutput { output, constraints, .. }) => {
DropData { dropck_result: output, region_constraint_data: constraints }
}
- Err(_) => DropData { dropck_result: Default::default(), region_constraint_data: None },
+ Err(_) => {
+ // We don't run dropck on HIR, and dropck looks inside fields of
+ // types, so there's no guarantee that it succeeds. We also
+ // can't rely on the the `ErrorGuaranteed` from `fully_perform` here
+ // because it comes from delay_span_bug.
+ //
+ // Do this inside of a probe because we don't particularly care (or want)
+ // any region side-effects of this operation in our infcx.
+ typeck.infcx.probe(|_| {
+ let ocx = ObligationCtxt::new_with_diagnostics(&typeck.infcx);
+ let errors = match dropck_outlives::compute_dropck_outlives_with_errors(
+ &ocx, op, span,
+ ) {
+ Ok(_) => ocx.select_all_or_error(),
+ Err(e) => {
+ if e.is_empty() {
+ ocx.select_all_or_error()
+ } else {
+ e
+ }
+ }
+ };
+
+ if !errors.is_empty() {
+ typeck.infcx.err_ctxt().report_fulfillment_errors(errors);
+ } else {
+ span_bug!(span, "Rerunning drop data query produced no error.");
+ }
+ });
+ DropData { dropck_result: Default::default(), region_constraint_data: None }
+ }
}
}
}
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 93081919ec79d..bd0d98028ae88 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;
@@ -457,38 +456,38 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
self.super_local_decl(local, local_decl);
- if let Some(user_ty) = &local_decl.user_ty {
- for (user_ty, span) in user_ty.projections_and_spans() {
- let ty = if !local_decl.is_nonref_binding() {
- // If we have a binding of the form `let ref x: T = ..`
- // then remove the outermost reference so we can check the
- // type annotation for the remaining type.
- if let ty::Ref(_, rty, _) = local_decl.ty.kind() {
- *rty
- } else {
- bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
- }
- } else {
- local_decl.ty
- };
+ for user_ty in
+ local_decl.user_ty.as_deref().into_iter().flat_map(UserTypeProjections::projections)
+ {
+ let span = self.typeck.user_type_annotations[user_ty.base].span;
+
+ let ty = if local_decl.is_nonref_binding() {
+ local_decl.ty
+ } else if let &ty::Ref(_, rty, _) = local_decl.ty.kind() {
+ // If we have a binding of the form `let ref x: T = ..`
+ // then remove the outermost reference so we can check the
+ // type annotation for the remaining type.
+ rty
+ } else {
+ bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
+ };
- if let Err(terr) = self.typeck.relate_type_and_user_type(
- ty,
- ty::Invariant,
- user_ty,
- Locations::All(*span),
- ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
- ) {
- span_mirbug!(
- self,
- local,
- "bad user type on variable {:?}: {:?} != {:?} ({:?})",
- local,
- local_decl.ty,
- local_decl.user_ty,
- terr,
- );
- }
+ if let Err(terr) = self.typeck.relate_type_and_user_type(
+ ty,
+ ty::Invariant,
+ user_ty,
+ Locations::All(span),
+ ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
+ ) {
+ span_mirbug!(
+ self,
+ local,
+ "bad user type on variable {:?}: {:?} != {:?} ({:?})",
+ local,
+ local_decl.ty,
+ local_decl.user_ty,
+ terr,
+ );
}
}
}
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index eb0079a3883f0..cfac9b36832fd 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;
@@ -125,6 +126,11 @@ pub(crate) enum DefiningTy<'tcx> {
/// The MIR represents an inline const. The signature has no inputs and a
/// single return value found via `InlineConstArgs::ty`.
InlineConst(DefId, GenericArgsRef<'tcx>),
+
+ // Fake body for a global asm. Not particularly useful or interesting,
+ // but we need it so we can properly store the typeck results of the asm
+ // operands, which aren't associated with a body otherwise.
+ GlobalAsm(DefId),
}
impl<'tcx> DefiningTy<'tcx> {
@@ -137,9 +143,10 @@ impl<'tcx> DefiningTy<'tcx> {
DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(),
DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(),
DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(),
- DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
- ty::List::empty()
- }
+ DefiningTy::FnDef(..)
+ | DefiningTy::Const(..)
+ | DefiningTy::InlineConst(..)
+ | DefiningTy::GlobalAsm(_) => ty::List::empty(),
}
}
@@ -151,7 +158,10 @@ impl<'tcx> DefiningTy<'tcx> {
DefiningTy::Closure(..)
| DefiningTy::CoroutineClosure(..)
| DefiningTy::Coroutine(..) => 1,
- DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0,
+ DefiningTy::FnDef(..)
+ | DefiningTy::Const(..)
+ | DefiningTy::InlineConst(..)
+ | DefiningTy::GlobalAsm(_) => 0,
}
}
@@ -170,7 +180,8 @@ impl<'tcx> DefiningTy<'tcx> {
| DefiningTy::Coroutine(def_id, ..)
| DefiningTy::FnDef(def_id, ..)
| DefiningTy::Const(def_id, ..)
- | DefiningTy::InlineConst(def_id, ..) => def_id,
+ | DefiningTy::InlineConst(def_id, ..)
+ | DefiningTy::GlobalAsm(def_id) => def_id,
}
}
}
@@ -307,7 +318,7 @@ impl<'tcx> UniversalRegions<'tcx> {
/// Returns an iterator over all the RegionVids corresponding to
/// universally quantified free regions.
- pub(crate) fn universal_regions_iter(&self) -> impl Iterator
- {
+ pub(crate) fn universal_regions_iter(&self) -> impl Iterator
- + 'static {
(FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
}
@@ -331,9 +342,9 @@ impl<'tcx> UniversalRegions<'tcx> {
}
/// Gets an iterator over all the early-bound regions that have names.
- pub(crate) fn named_universal_regions_iter<'s>(
- &'s self,
- ) -> impl Iterator
- , ty::RegionVid)> + 's {
+ pub(crate) fn named_universal_regions_iter(
+ &self,
+ ) -> impl Iterator
- , ty::RegionVid)> {
self.indices.indices.iter().map(|(&r, &v)| (r, v))
}
@@ -410,6 +421,7 @@ impl<'tcx> UniversalRegions<'tcx> {
tcx.def_path_str_with_args(def_id, args),
));
}
+ DefiningTy::GlobalAsm(_) => unreachable!(),
}
}
@@ -576,7 +588,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 +615,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)
@@ -629,6 +644,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
DefiningTy::InlineConst(self.mir_def.to_def_id(), args)
}
}
+
+ BodyOwnerKind::GlobalAsm => DefiningTy::GlobalAsm(self.mir_def.to_def_id()),
}
}
@@ -662,6 +679,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
}
DefiningTy::FnDef(_, args) | DefiningTy::Const(_, args) => args,
+
+ DefiningTy::GlobalAsm(_) => ty::List::empty(),
};
let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
@@ -798,6 +817,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let ty = args.as_inline_const().ty();
ty::Binder::dummy(tcx.mk_type_list(&[ty]))
}
+
+ DefiningTy::GlobalAsm(def_id) => {
+ ty::Binder::dummy(tcx.mk_type_list(&[tcx.type_of(def_id).instantiate_identity()]))
+ }
};
// FIXME(#129952): We probably want a more principled approach here.
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml
index b50cb35b8e983..f29be2ee81855 100644
--- a/compiler/rustc_builtin_macros/Cargo.toml
+++ b/compiler/rustc_builtin_macros/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_builtin_macros"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[lints.rust]
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index 24c54edd705a1..8d7ac6de8010b 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -242,6 +242,7 @@ mod llvm_enzyme {
defaultness: ast::Defaultness::Final,
sig: d_sig,
generics: Generics::default(),
+ contract: None,
body: Some(d_body),
});
let mut rustc_ad_attr =
diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
index 1a3f4d2d44908..6933ca09349a1 100644
--- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs
+++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
@@ -19,16 +19,12 @@ pub fn inject(
let edition = sess.psess.edition;
// the first name in this list is the crate name of the crate with the prelude
- let names: &[Symbol] = if attr::contains_name(pre_configured_attrs, sym::no_core) {
+ let name: Symbol = if attr::contains_name(pre_configured_attrs, sym::no_core) {
return 0;
} else if attr::contains_name(pre_configured_attrs, sym::no_std) {
- if attr::contains_name(pre_configured_attrs, sym::compiler_builtins) {
- &[sym::core]
- } else {
- &[sym::core, sym::compiler_builtins]
- }
+ sym::core
} else {
- &[sym::std]
+ sym::std
};
let expn_id = resolver.expansion_for_ast_pass(
@@ -43,36 +39,16 @@ pub fn inject(
let ecfg = ExpansionConfig::default("std_lib_injection".to_string(), features);
let cx = ExtCtxt::new(sess, ecfg, resolver, None);
- // .rev() to preserve ordering above in combination with insert(0, ...)
- for &name in names.iter().rev() {
- let ident_span = if edition >= Edition2018 { span } else { call_site };
- let item = if name == sym::compiler_builtins {
- // compiler_builtins is a private implementation detail. We only
- // need to insert it into the crate graph for linking and should not
- // expose any of its public API.
- //
- // FIXME(#113634) We should inject this during post-processing like
- // we do for the panic runtime, profiler runtime, etc.
- cx.item(
- span,
- Ident::new(kw::Underscore, ident_span),
- thin_vec![],
- ast::ItemKind::ExternCrate(Some(name)),
- )
- } else {
- cx.item(
- span,
- Ident::new(name, ident_span),
- thin_vec![cx.attr_word(sym::macro_use, span)],
- ast::ItemKind::ExternCrate(None),
- )
- };
- krate.items.insert(0, item);
- }
+ let ident_span = if edition >= Edition2018 { span } else { call_site };
- // The crates have been injected, the assumption is that the first one is
- // the one with the prelude.
- let name = names[0];
+ let item = cx.item(
+ span,
+ Ident::new(name, ident_span),
+ thin_vec![cx.attr_word(sym::macro_use, span)],
+ ast::ItemKind::ExternCrate(None),
+ );
+
+ krate.items.insert(0, item);
let root = (edition == Edition2015).then_some(kw::PathRoot);
@@ -88,6 +64,7 @@ pub fn inject(
.map(|&symbol| Ident::new(symbol, span))
.collect();
+ // Inject the relevant crate's prelude.
let use_item = cx.item(
span,
Ident::empty(),
diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
index e3a9512dda9c6..364a6a035ab88 100644
--- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
@@ -15,9 +15,9 @@ index 7165c3e48af..968552ad435 100644
edition = "2021"
[dependencies]
- core = { path = "../core" }
--compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] }
-+compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std', 'no-f16-f128'] }
+ core = { path = "../core", public = true }
+-compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std'] }
++compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std', 'no-f16-f128'] }
[dev-dependencies]
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
index 521a250ab82cc..c74efeb59f3fc 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 425b2adf32a37..bcc70f4567fbd 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/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index 54745b0d8c104..9ea92c300f898 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -16,7 +16,7 @@ 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);
- if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
+ if let rustc_hir::ItemKind::GlobalAsm { asm, .. } = item.kind {
let is_x86 =
matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64);
@@ -55,7 +55,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
}
}
}
- InlineAsmOperand::SymFn { anon_const } => {
+ InlineAsmOperand::SymFn { expr } => {
if cfg!(not(feature = "inline_asm_sym")) {
tcx.dcx().span_err(
item.span,
@@ -63,7 +63,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
);
}
- let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
+ let ty = tcx.typeck(item_id.owner_id).expr_ty(expr);
let instance = match ty.kind() {
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
_ => span_bug!(op_sp, "asm sym is not a function"),
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 26f14532b458e..4d9bed8652cbd 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -340,14 +340,10 @@ fn codegen_float_intrinsic_call<'tcx>(
sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64, types::F64),
sym::truncf32 => ("truncf", 1, fx.tcx.types.f32, types::F32),
sym::truncf64 => ("trunc", 1, fx.tcx.types.f64, types::F64),
- sym::rintf32 => ("rintf", 1, fx.tcx.types.f32, types::F32),
- sym::rintf64 => ("rint", 1, fx.tcx.types.f64, types::F64),
+ sym::round_ties_even_f32 => ("rintf", 1, fx.tcx.types.f32, types::F32),
+ sym::round_ties_even_f64 => ("rint", 1, fx.tcx.types.f64, types::F64),
sym::roundf32 => ("roundf", 1, fx.tcx.types.f32, types::F32),
sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64),
- sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32, types::F32),
- sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64, types::F64),
- sym::nearbyintf32 => ("nearbyintf", 1, fx.tcx.types.f32, types::F32),
- sym::nearbyintf64 => ("nearbyint", 1, fx.tcx.types.f64, types::F64),
sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32),
sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64),
sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32),
@@ -399,8 +395,8 @@ fn codegen_float_intrinsic_call<'tcx>(
| sym::ceilf64
| sym::truncf32
| sym::truncf64
- | sym::nearbyintf32
- | sym::nearbyintf64
+ | sym::round_ties_even_f32
+ | sym::round_ties_even_f64
| sym::sqrtf32
| sym::sqrtf64 => {
let val = match intrinsic {
@@ -408,7 +404,9 @@ fn codegen_float_intrinsic_call<'tcx>(
sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]),
sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]),
sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]),
- sym::nearbyintf32 | sym::nearbyintf64 => fx.bcx.ins().nearest(args[0]),
+ sym::round_ties_even_f32 | sym::round_ties_even_f64 => {
+ fx.bcx.ins().nearest(args[0])
+ }
sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]),
_ => unreachable!(),
};
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index a9b8e1bd39353..1b3f86c8405de 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -638,9 +638,7 @@ impl<'tcx> CPlace<'tcx> {
}
CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self),
CPlaceInner::Addr(to_ptr, None) => {
- if dst_layout.size == Size::ZERO
- || dst_layout.backend_repr == BackendRepr::Uninhabited
- {
+ if dst_layout.size == Size::ZERO {
return;
}
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index b8e37b604801f..c8b7616e64509 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -989,10 +989,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
OperandValue::Ref(place.val)
} else if place.layout.is_gcc_immediate() {
let load = self.load(place.layout.gcc_type(self), place.val.llval, place.val.align);
- if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr {
- scalar_load_metadata(self, load, scalar);
- }
- OperandValue::Immediate(self.to_immediate(load, place.layout))
+ OperandValue::Immediate(
+ if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr {
+ scalar_load_metadata(self, load, scalar);
+ self.to_immediate_scalar(load, *scalar)
+ } else {
+ load
+ },
+ )
} else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr {
let b_offset = a.size(self).align_to(b.align(self).abi);
@@ -1694,7 +1698,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
if scalar.is_bool() {
- return self.trunc(val, self.cx().type_i1());
+ return self.unchecked_utrunc(val, self.cx().type_i1());
}
val
}
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index a1123fafe2f30..f8672c0729998 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -9,7 +9,7 @@ use gccjit::FunctionType;
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp};
#[cfg(feature = "master")]
use rustc_abi::ExternAbi;
-use rustc_abi::HasDataLayout;
+use rustc_abi::{BackendRepr, HasDataLayout};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::base::wants_msvc_seh;
use rustc_codegen_ssa::common::IntPredicate;
@@ -84,14 +84,11 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
sym::ceilf64 => "ceil",
sym::truncf32 => "truncf",
sym::truncf64 => "trunc",
- sym::rintf32 => "rintf",
- sym::rintf64 => "rint",
- sym::nearbyintf32 => "nearbyintf",
- sym::nearbyintf64 => "nearbyint",
+ // We match the LLVM backend and lower this to `rint`.
+ sym::round_ties_even_f32 => "rintf",
+ sym::round_ties_even_f64 => "rint",
sym::roundf32 => "roundf",
sym::roundf64 => "round",
- sym::roundevenf32 => "roundevenf",
- sym::roundevenf64 => "roundeven",
sym::abort => "abort",
_ => return None,
};
@@ -181,14 +178,19 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
sym::volatile_load | sym::unaligned_volatile_load => {
let tp_ty = fn_args.type_at(0);
let ptr = args[0].immediate();
+ let layout = self.layout_of(tp_ty);
let load = if let PassMode::Cast { cast: ref ty, pad_i32: _ } = fn_abi.ret.mode {
let gcc_ty = ty.gcc_type(self);
self.volatile_load(gcc_ty, ptr)
} else {
- self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr)
+ self.volatile_load(layout.gcc_type(self), ptr)
};
// TODO(antoyo): set alignment.
- self.to_immediate(load, self.layout_of(tp_ty))
+ if let BackendRepr::Scalar(scalar) = layout.backend_repr {
+ self.to_immediate_scalar(load, scalar)
+ } else {
+ load
+ }
}
sym::volatile_store => {
let dst = args[0].deref(self.cx());
@@ -310,7 +312,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
let layout = self.layout_of(tp_ty).layout;
let _use_integer_compare = match layout.backend_repr() {
Scalar(_) | ScalarPair(_, _) => true,
- Uninhabited | Vector { .. } => false,
+ Vector { .. } => false,
Memory { .. } => {
// For rusty ABIs, small aggregates are actually passed
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 8b8b54753e7fd..bac4fc51300a2 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -84,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
false,
);
}
- BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {}
+ BackendRepr::Memory { .. } => {}
}
let name = match *layout.ty.kind() {
@@ -179,19 +179,16 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
fn is_gcc_immediate(&self) -> bool {
match self.backend_repr {
BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true,
- BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
- false
- }
+ BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false,
}
}
fn is_gcc_scalar_pair(&self) -> bool {
match self.backend_repr {
BackendRepr::ScalarPair(..) => true,
- BackendRepr::Uninhabited
- | BackendRepr::Scalar(_)
- | BackendRepr::Vector { .. }
- | BackendRepr::Memory { .. } => false,
+ BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => {
+ false
+ }
}
}
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 94f21ac5f5742..d3ce7c5a1130f 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_codegen_llvm"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[lib]
test = false
@@ -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/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index 399d7ffea8e6d..17f2e7ca9f702 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -1,3 +1,4 @@
+codegen_llvm_autodiff_without_enable = using the autodiff feature requires -Z autodiff=Enable
codegen_llvm_autodiff_without_lto = using the autodiff feature requires using fat-lto
codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 28f423efc2141..8c75125e009b9 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/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 7262fce491191..99906ea7bce39 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -362,8 +362,8 @@ fn fat_lto(
ptr as *const *const libc::c_char,
symbols_below_threshold.len() as libc::size_t,
);
- save_temp_bitcode(cgcx, &module, "lto.after-restriction");
}
+ save_temp_bitcode(cgcx, &module, "lto.after-restriction");
}
Ok(LtoModuleCodegen::Fat(module))
@@ -586,6 +586,42 @@ fn thin_lto(
}
}
+fn enable_autodiff_settings(ad: &[config::AutoDiff], module: &mut ModuleCodegen) {
+ for &val in ad {
+ match val {
+ config::AutoDiff::PrintModBefore => {
+ unsafe { llvm::LLVMDumpModule(module.module_llvm.llmod()) };
+ }
+ config::AutoDiff::PrintPerf => {
+ llvm::set_print_perf(true);
+ }
+ config::AutoDiff::PrintAA => {
+ llvm::set_print_activity(true);
+ }
+ config::AutoDiff::PrintTA => {
+ llvm::set_print_type(true);
+ }
+ config::AutoDiff::Inline => {
+ llvm::set_inline(true);
+ }
+ config::AutoDiff::LooseTypes => {
+ llvm::set_loose_types(false);
+ }
+ config::AutoDiff::PrintSteps => {
+ llvm::set_print(true);
+ }
+ // We handle this below
+ config::AutoDiff::PrintModAfter => {}
+ // This is required and already checked
+ config::AutoDiff::Enable => {}
+ }
+ }
+ // This helps with handling enums for now.
+ llvm::set_strict_aliasing(false);
+ // FIXME(ZuseZ4): Test this, since it was added a long time ago.
+ llvm::set_rust_rules(true);
+}
+
pub(crate) fn run_pass_manager(
cgcx: &CodegenContext,
dcx: DiagCtxtHandle<'_>,
@@ -604,34 +640,37 @@ pub(crate) fn run_pass_manager(
let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
- // If this rustc version was build with enzyme/autodiff enabled, and if users applied the
- // `#[autodiff]` macro at least once, then we will later call llvm_optimize a second time.
- debug!("running llvm pm opt pipeline");
+ // The PostAD behavior is the same that we would have if no autodiff was used.
+ // It will run the default optimization pipeline. If AD is enabled we select
+ // the DuringAD stage, which will disable vectorization and loop unrolling, and
+ // schedule two autodiff optimization + differentiation passes.
+ // We then run the llvm_optimize function a second time, to optimize the code which we generated
+ // in the enzyme differentiation pass.
+ let enable_ad = config.autodiff.contains(&config::AutoDiff::Enable);
+ let stage =
+ if enable_ad { write::AutodiffStage::DuringAD } else { write::AutodiffStage::PostAD };
+
+ if enable_ad {
+ enable_autodiff_settings(&config.autodiff, module);
+ }
+
unsafe {
- write::llvm_optimize(
- cgcx,
- dcx,
- module,
- config,
- opt_level,
- opt_stage,
- write::AutodiffStage::DuringAD,
- )?;
+ write::llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage, stage)?;
}
- // FIXME(ZuseZ4): Make this more granular
- if cfg!(llvm_enzyme) && !thin {
+
+ if cfg!(llvm_enzyme) && enable_ad {
+ let opt_stage = llvm::OptStage::FatLTO;
+ let stage = write::AutodiffStage::PostAD;
unsafe {
- write::llvm_optimize(
- cgcx,
- dcx,
- module,
- config,
- opt_level,
- llvm::OptStage::FatLTO,
- write::AutodiffStage::PostAD,
- )?;
+ write::llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage, stage)?;
+ }
+
+ // This is the final IR, so people should be able to inspect the optimized autodiff output.
+ if config.autodiff.contains(&config::AutoDiff::PrintModAfter) {
+ unsafe { llvm::LLVMDumpModule(module.module_llvm.llmod()) };
}
}
+
debug!("lto done");
Ok(())
}
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 9fa10e960680b..b67890c046572 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -564,19 +564,16 @@ pub(crate) unsafe fn llvm_optimize(
// FIXME(ZuseZ4): In a future update we could figure out how to only optimize individual functions getting
// differentiated.
+ let consider_ad = cfg!(llvm_enzyme) && config.autodiff.contains(&config::AutoDiff::Enable);
+ let run_enzyme = autodiff_stage == AutodiffStage::DuringAD;
let unroll_loops;
let vectorize_slp;
let vectorize_loop;
- let run_enzyme = cfg!(llvm_enzyme) && autodiff_stage == AutodiffStage::DuringAD;
// When we build rustc with enzyme/autodiff support, we want to postpone size-increasing
// optimizations until after differentiation. Our pipeline is thus: (opt + enzyme), (full opt).
// We therefore have two calls to llvm_optimize, if autodiff is used.
- //
- // FIXME(ZuseZ4): Before shipping on nightly,
- // we should make this more granular, or at least check that the user has at least one autodiff
- // call in their code, to justify altering the compilation pipeline.
- if cfg!(llvm_enzyme) && autodiff_stage != AutodiffStage::PostAD {
+ if consider_ad && autodiff_stage != AutodiffStage::PostAD {
unroll_loops = false;
vectorize_slp = false;
vectorize_loop = false;
@@ -706,10 +703,8 @@ pub(crate) unsafe fn optimize(
// If we know that we will later run AD, then we disable vectorization and loop unrolling.
// Otherwise we pretend AD is already done and run the normal opt pipeline (=PostAD).
- // FIXME(ZuseZ4): Make this more granular, only set PreAD if we actually have autodiff
- // usages, not just if we build rustc with autodiff support.
- let autodiff_stage =
- if cfg!(llvm_enzyme) { AutodiffStage::PreAD } else { AutodiffStage::PostAD };
+ let consider_ad = cfg!(llvm_enzyme) && config.autodiff.contains(&config::AutoDiff::Enable);
+ let autodiff_stage = if consider_ad { AutodiffStage::PreAD } else { AutodiffStage::PostAD };
return unsafe {
llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage, autodiff_stage)
};
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 57f09b1fa2fd2..677a9cd3e90ea 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -4,7 +4,7 @@ use std::{iter, ptr};
pub(crate) mod autodiff;
-use libc::{c_char, c_uint};
+use libc::{c_char, c_uint, size_t};
use rustc_abi as abi;
use rustc_abi::{Align, Size, WrappingRange};
use rustc_codegen_ssa::MemFlags;
@@ -29,13 +29,15 @@ use smallvec::SmallVec;
use tracing::{debug, instrument};
use crate::abi::FnAbiLlvmExt;
-use crate::attributes;
use crate::common::Funclet;
use crate::context::{CodegenCx, SimpleCx};
-use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True};
+use crate::llvm::{
+ self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, GEPNoWrapFlags, Metadata, True,
+};
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
+use crate::{attributes, llvm_util};
#[must_use]
pub(crate) struct GenericBuilder<'a, 'll, CX: Borrow>> {
@@ -333,6 +335,50 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
}
}
+ fn switch_with_weights(
+ &mut self,
+ v: Self::Value,
+ else_llbb: Self::BasicBlock,
+ else_is_cold: bool,
+ cases: impl ExactSizeIterator
- ,
+ ) {
+ if self.cx.sess().opts.optimize == rustc_session::config::OptLevel::No {
+ self.switch(v, else_llbb, cases.map(|(val, dest, _)| (val, dest)));
+ return;
+ }
+
+ let id_str = "branch_weights";
+ let id = unsafe {
+ llvm::LLVMMDStringInContext2(self.cx.llcx, id_str.as_ptr().cast(), id_str.len())
+ };
+
+ // For switch instructions with 2 targets, the `llvm.expect` intrinsic is used.
+ // This function handles switch instructions with more than 2 targets and it needs to
+ // emit branch weights metadata instead of using the intrinsic.
+ // The values 1 and 2000 are the same as the values used by the `llvm.expect` intrinsic.
+ let cold_weight = unsafe { llvm::LLVMValueAsMetadata(self.cx.const_u32(1)) };
+ let hot_weight = unsafe { llvm::LLVMValueAsMetadata(self.cx.const_u32(2000)) };
+ let weight =
+ |is_cold: bool| -> &Metadata { if is_cold { cold_weight } else { hot_weight } };
+
+ let mut md: SmallVec<[&Metadata; 16]> = SmallVec::with_capacity(cases.len() + 2);
+ md.push(id);
+ md.push(weight(else_is_cold));
+
+ let switch =
+ unsafe { llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, cases.len() as c_uint) };
+ for (on_val, dest, is_cold) in cases {
+ let on_val = self.const_uint_big(self.val_ty(v), on_val);
+ unsafe { llvm::LLVMAddCase(switch, on_val, dest) }
+ md.push(weight(is_cold));
+ }
+
+ unsafe {
+ let md_node = llvm::LLVMMDNodeInContext2(self.cx.llcx, md.as_ptr(), md.len() as size_t);
+ self.cx.set_metadata(switch, llvm::MD_prof, md_node);
+ }
+ }
+
fn invoke(
&mut self,
llty: &'ll Type,
@@ -562,7 +608,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
if scalar.is_bool() {
- return self.trunc(val, self.cx().type_i1());
+ return self.unchecked_utrunc(val, self.cx().type_i1());
}
val
}
@@ -702,10 +748,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
let load = self.load(llty, place.val.llval, place.val.align);
if let abi::BackendRepr::Scalar(scalar) = place.layout.backend_repr {
scalar_load_metadata(self, load, scalar, place.layout, Size::ZERO);
+ self.to_immediate_scalar(load, scalar)
+ } else {
+ load
}
- load
});
- OperandValue::Immediate(self.to_immediate(llval, place.layout))
+ OperandValue::Immediate(llval)
} else if let abi::BackendRepr::ScalarPair(a, b) = place.layout.backend_repr {
let b_offset = a.size(self).align_to(b.align(self).abi);
@@ -864,13 +912,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn gep(&mut self, ty: &'ll Type, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
unsafe {
- llvm::LLVMBuildGEP2(
+ llvm::LLVMBuildGEPWithNoWrapFlags(
self.llbuilder,
ty,
ptr,
indices.as_ptr(),
indices.len() as c_uint,
UNNAMED,
+ GEPNoWrapFlags::default(),
)
}
}
@@ -882,13 +931,33 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
indices: &[&'ll Value],
) -> &'ll Value {
unsafe {
- llvm::LLVMBuildInBoundsGEP2(
+ llvm::LLVMBuildGEPWithNoWrapFlags(
self.llbuilder,
ty,
ptr,
indices.as_ptr(),
indices.len() as c_uint,
UNNAMED,
+ GEPNoWrapFlags::InBounds,
+ )
+ }
+ }
+
+ fn inbounds_nuw_gep(
+ &mut self,
+ ty: &'ll Type,
+ ptr: &'ll Value,
+ indices: &[&'ll Value],
+ ) -> &'ll Value {
+ unsafe {
+ llvm::LLVMBuildGEPWithNoWrapFlags(
+ self.llbuilder,
+ ty,
+ ptr,
+ indices.as_ptr(),
+ indices.len() as c_uint,
+ UNNAMED,
+ GEPNoWrapFlags::InBounds | GEPNoWrapFlags::NUW,
)
}
}
@@ -898,6 +967,34 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
unsafe { llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, UNNAMED) }
}
+ fn unchecked_utrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
+ debug_assert_ne!(self.val_ty(val), dest_ty);
+
+ let trunc = self.trunc(val, dest_ty);
+ if llvm_util::get_version() >= (19, 0, 0) {
+ unsafe {
+ if llvm::LLVMIsAInstruction(trunc).is_some() {
+ llvm::LLVMSetNUW(trunc, True);
+ }
+ }
+ }
+ trunc
+ }
+
+ fn unchecked_strunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
+ debug_assert_ne!(self.val_ty(val), dest_ty);
+
+ let trunc = self.trunc(val, dest_ty);
+ if llvm_util::get_version() >= (19, 0, 0) {
+ unsafe {
+ if llvm::LLVMIsAInstruction(trunc).is_some() {
+ llvm::LLVMSetNSW(trunc, True);
+ }
+ }
+ }
+ trunc
+ }
+
fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe { llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, UNNAMED) }
}
diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
index b2c1088e3fc02..2c7899975e3ee 100644
--- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
@@ -10,7 +10,7 @@ use crate::back::write::llvm_err;
use crate::builder::SBuilder;
use crate::context::SimpleCx;
use crate::declare::declare_simple_fn;
-use crate::errors::LlvmError;
+use crate::errors::{AutoDiffWithoutEnable, LlvmError};
use crate::llvm::AttributePlace::Function;
use crate::llvm::{Metadata, True};
use crate::value::Value;
@@ -46,9 +46,6 @@ fn generate_enzyme_call<'ll>(
let output = attrs.ret_activity;
// We have to pick the name depending on whether we want forward or reverse mode autodiff.
- // FIXME(ZuseZ4): The new pass based approach should not need the {Forward/Reverse}First method anymore, since
- // it will handle higher-order derivatives correctly automatically (in theory). Currently
- // higher-order derivatives fail, so we should debug that before adjusting this code.
let mut ad_name: String = match attrs.mode {
DiffMode::Forward => "__enzyme_fwddiff",
DiffMode::Reverse => "__enzyme_autodiff",
@@ -291,6 +288,14 @@ pub(crate) fn differentiate<'ll>(
let diag_handler = cgcx.create_dcx();
let cx = SimpleCx { llmod: module.module_llvm.llmod(), llcx: module.module_llvm.llcx };
+ // First of all, did the user try to use autodiff without using the -Zautodiff=Enable flag?
+ if !diff_items.is_empty()
+ && !cgcx.opts.unstable_opts.autodiff.contains(&rustc_session::config::AutoDiff::Enable)
+ {
+ let dcx = cgcx.create_dcx();
+ return Err(dcx.handle().emit_almost_fatal(AutoDiffWithoutEnable));
+ }
+
// Before dumping the module, we want all the TypeTrees to become part of the module.
for item in diff_items.iter() {
let name = item.source.clone();
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index aa9a0f34f55e9..ea9ab5c02bd6c 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -66,9 +66,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
// LLVM will prefix the name with `__imp_`. Ideally, we'd like the
// existing logic below to set the Storage Class, but it has an
// exemption for MinGW for backwards compatibility.
- unsafe {
- llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
- }
+ llvm::set_dllimport_storage_class(llfn);
llfn
} else {
cx.declare_fn(sym, fn_abi, Some(instance))
@@ -99,65 +97,61 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
// has been applied to the definition (wherever that definition may be).
llvm::set_linkage(llfn, llvm::Linkage::ExternalLinkage);
- unsafe {
- let is_generic = instance.args.non_erasable_generics().next().is_some();
-
- let is_hidden = if is_generic {
- // This is a monomorphization of a generic function.
- if !(cx.tcx.sess.opts.share_generics()
- || tcx.codegen_fn_attrs(instance_def_id).inline
- == rustc_attr_parsing::InlineAttr::Never)
- {
- // When not sharing generics, all instances are in the same
- // crate and have hidden visibility.
- true
- } else {
- if let Some(instance_def_id) = instance_def_id.as_local() {
- // This is a monomorphization of a generic function
- // defined in the current crate. It is hidden if:
- // - the definition is unreachable for downstream
- // crates, or
- // - the current crate does not re-export generics
- // (because the crate is a C library or executable)
- cx.tcx.is_unreachable_local_definition(instance_def_id)
- || !cx.tcx.local_crate_exports_generics()
- } else {
- // This is a monomorphization of a generic function
- // defined in an upstream crate. It is hidden if:
- // - it is instantiated in this crate, and
- // - the current crate does not re-export generics
- instance.upstream_monomorphization(tcx).is_none()
- && !cx.tcx.local_crate_exports_generics()
- }
- }
- } else {
- // This is a non-generic function. It is hidden if:
- // - it is instantiated in the local crate, and
- // - it is defined an upstream crate (non-local), or
- // - it is not reachable
- cx.tcx.is_codegened_item(instance_def_id)
- && (!instance_def_id.is_local()
- || !cx.tcx.is_reachable_non_generic(instance_def_id))
- };
- if is_hidden {
- llvm::set_visibility(llfn, llvm::Visibility::Hidden);
- }
+ let is_generic = instance.args.non_erasable_generics().next().is_some();
- // MinGW: For backward compatibility we rely on the linker to decide whether it
- // should use dllimport for functions.
- if cx.use_dll_storage_attrs
- && let Some(library) = tcx.native_library(instance_def_id)
- && library.kind.is_dllimport()
- && !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc")
+ let is_hidden = if is_generic {
+ // This is a monomorphization of a generic function.
+ if !(cx.tcx.sess.opts.share_generics()
+ || tcx.codegen_fn_attrs(instance_def_id).inline
+ == rustc_attr_parsing::InlineAttr::Never)
{
- llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
+ // When not sharing generics, all instances are in the same
+ // crate and have hidden visibility.
+ true
+ } else {
+ if let Some(instance_def_id) = instance_def_id.as_local() {
+ // This is a monomorphization of a generic function
+ // defined in the current crate. It is hidden if:
+ // - the definition is unreachable for downstream
+ // crates, or
+ // - the current crate does not re-export generics
+ // (because the crate is a C library or executable)
+ cx.tcx.is_unreachable_local_definition(instance_def_id)
+ || !cx.tcx.local_crate_exports_generics()
+ } else {
+ // This is a monomorphization of a generic function
+ // defined in an upstream crate. It is hidden if:
+ // - it is instantiated in this crate, and
+ // - the current crate does not re-export generics
+ instance.upstream_monomorphization(tcx).is_none()
+ && !cx.tcx.local_crate_exports_generics()
+ }
}
+ } else {
+ // This is a non-generic function. It is hidden if:
+ // - it is instantiated in the local crate, and
+ // - it is defined an upstream crate (non-local), or
+ // - it is not reachable
+ cx.tcx.is_codegened_item(instance_def_id)
+ && (!instance_def_id.is_local()
+ || !cx.tcx.is_reachable_non_generic(instance_def_id))
+ };
+ if is_hidden {
+ llvm::set_visibility(llfn, llvm::Visibility::Hidden);
+ }
- if cx.should_assume_dso_local(llfn, true) {
- llvm::LLVMRustSetDSOLocal(llfn, true);
- }
+ // MinGW: For backward compatibility we rely on the linker to decide whether it
+ // should use dllimport for functions.
+ if cx.use_dll_storage_attrs
+ && let Some(library) = tcx.native_library(instance_def_id)
+ && library.kind.is_dllimport()
+ && !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc")
+ {
+ llvm::set_dllimport_storage_class(llfn);
}
+ cx.assume_dso_local(llfn, true);
+
llfn
};
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 78b3a7f85417b..f17d98fa242b7 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/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 4a5491ec7a18c..330e8a8f4069d 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -336,12 +336,7 @@ impl<'ll> CodegenCx<'ll, '_> {
llvm::set_thread_local_mode(g, self.tls_model);
}
- let dso_local = self.should_assume_dso_local(g, true);
- if dso_local {
- unsafe {
- llvm::LLVMRustSetDSOLocal(g, true);
- }
- }
+ let dso_local = self.assume_dso_local(g, true);
if !def_id.is_local() {
let needs_dll_storage_attr = self.use_dll_storage_attrs
@@ -375,9 +370,7 @@ impl<'ll> CodegenCx<'ll, '_> {
// is actually present in the current crate. We can find out via the
// is_codegened_item query.
if !self.tcx.is_codegened_item(def_id) {
- unsafe {
- llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
- }
+ llvm::set_dllimport_storage_class(g);
}
}
}
@@ -387,9 +380,7 @@ impl<'ll> CodegenCx<'ll, '_> {
&& library.kind.is_dllimport()
{
// For foreign (native) libs we know the exact storage type to use.
- unsafe {
- llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
- }
+ llvm::set_dllimport_storage_class(g);
}
self.instances.borrow_mut().insert(instance, g);
@@ -460,9 +451,7 @@ impl<'ll> CodegenCx<'ll, '_> {
set_global_alignment(self, g, alloc.align);
llvm::set_initializer(g, v);
- if self.should_assume_dso_local(g, true) {
- llvm::LLVMRustSetDSOLocal(g, true);
- }
+ self.assume_dso_local(g, true);
// Forward the allocation's mutability (picked by the const interner) to LLVM.
if alloc.mutability.is_not() {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index 54c5d445f66bd..4ffe551df09b5 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 59c3fe635d070..98d59f5a8ae06 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 17f2d5f4e731f..10819a53b1df8 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 cebceef1b93f8..e79662ebc6472 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/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index 97f4925616595..4c5a78ca74fe4 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -92,9 +92,12 @@ impl Diagnostic<'_, G> for ParseTargetMachineConfig<'_> {
#[derive(Diagnostic)]
#[diag(codegen_llvm_autodiff_without_lto)]
-#[note]
pub(crate) struct AutoDiffWithoutLTO;
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_autodiff_without_enable)]
+pub(crate) struct AutoDiffWithoutEnable;
+
#[derive(Diagnostic)]
#[diag(codegen_llvm_lto_disallowed)]
pub(crate) struct LtoDisallowed;
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 8b97688590456..dfbb5bc1731df 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};
@@ -126,15 +127,14 @@ fn get_simple_intrinsic<'ll>(
sym::truncf64 => "llvm.trunc.f64",
sym::truncf128 => "llvm.trunc.f128",
- sym::rintf16 => "llvm.rint.f16",
- sym::rintf32 => "llvm.rint.f32",
- sym::rintf64 => "llvm.rint.f64",
- sym::rintf128 => "llvm.rint.f128",
-
- sym::nearbyintf16 => "llvm.nearbyint.f16",
- sym::nearbyintf32 => "llvm.nearbyint.f32",
- sym::nearbyintf64 => "llvm.nearbyint.f64",
- sym::nearbyintf128 => "llvm.nearbyint.f128",
+ // We could use any of `rint`, `nearbyint`, or `roundeven`
+ // for this -- they are all identical in semantics when
+ // assuming the default FP environment.
+ // `rint` is what we used for $forever.
+ sym::round_ties_even_f16 => "llvm.rint.f16",
+ sym::round_ties_even_f32 => "llvm.rint.f32",
+ sym::round_ties_even_f64 => "llvm.rint.f64",
+ sym::round_ties_even_f128 => "llvm.rint.f128",
sym::roundf16 => "llvm.round.f16",
sym::roundf32 => "llvm.round.f32",
@@ -143,11 +143,6 @@ fn get_simple_intrinsic<'ll>(
sym::ptr_mask => "llvm.ptrmask",
- sym::roundevenf16 => "llvm.roundeven.f16",
- sym::roundevenf32 => "llvm.roundeven.f32",
- sym::roundevenf64 => "llvm.roundeven.f64",
- sym::roundevenf128 => "llvm.roundeven.f128",
-
_ => return None,
};
Some(cx.get_intrinsic(llvm_name))
@@ -257,7 +252,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,12 +465,12 @@ 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() {
Scalar(_) | ScalarPair(_, _) => true,
- Uninhabited | Vector { .. } => false,
+ Vector { .. } => false,
Memory { .. } => {
// For rusty ABIs, small aggregates are actually passed
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
@@ -582,8 +577,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_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
index 39bac13a9680c..3c2c6964a3d79 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
@@ -7,7 +7,7 @@ use super::ffi::{BasicBlock, Metadata, Module, Type, Value};
use crate::llvm::Bool;
#[link(name = "llvm-wrapper", kind = "static")]
-extern "C" {
+unsafe extern "C" {
// Enzyme
pub(crate) fn LLVMRustHasMetadata(I: &Value, KindID: c_uint) -> bool;
pub(crate) fn LLVMRustEraseInstUntilInclusive(BB: &BasicBlock, I: &Value);
@@ -18,7 +18,7 @@ extern "C" {
pub(crate) fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool;
}
-extern "C" {
+unsafe extern "C" {
// Enzyme
pub(crate) fn LLVMDumpModule(M: &Module);
pub(crate) fn LLVMDumpValue(V: &Value);
@@ -35,3 +35,97 @@ pub enum LLVMRustVerifierFailureAction {
LLVMPrintMessageAction = 1,
LLVMReturnStatusAction = 2,
}
+
+#[cfg(llvm_enzyme)]
+pub use self::Enzyme_AD::*;
+
+#[cfg(llvm_enzyme)]
+pub mod Enzyme_AD {
+ use libc::c_void;
+ extern "C" {
+ pub fn EnzymeSetCLBool(arg1: *mut ::std::os::raw::c_void, arg2: u8);
+ }
+ extern "C" {
+ static mut EnzymePrintPerf: c_void;
+ static mut EnzymePrintActivity: c_void;
+ static mut EnzymePrintType: c_void;
+ static mut EnzymePrint: c_void;
+ static mut EnzymeStrictAliasing: c_void;
+ static mut looseTypeAnalysis: c_void;
+ static mut EnzymeInline: c_void;
+ static mut RustTypeRules: c_void;
+ }
+ pub fn set_print_perf(print: bool) {
+ unsafe {
+ EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintPerf), print as u8);
+ }
+ }
+ pub fn set_print_activity(print: bool) {
+ unsafe {
+ EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintActivity), print as u8);
+ }
+ }
+ pub fn set_print_type(print: bool) {
+ unsafe {
+ EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintType), print as u8);
+ }
+ }
+ pub fn set_print(print: bool) {
+ unsafe {
+ EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrint), print as u8);
+ }
+ }
+ pub fn set_strict_aliasing(strict: bool) {
+ unsafe {
+ EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymeStrictAliasing), strict as u8);
+ }
+ }
+ pub fn set_loose_types(loose: bool) {
+ unsafe {
+ EnzymeSetCLBool(std::ptr::addr_of_mut!(looseTypeAnalysis), loose as u8);
+ }
+ }
+ pub fn set_inline(val: bool) {
+ unsafe {
+ EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymeInline), val as u8);
+ }
+ }
+ pub fn set_rust_rules(val: bool) {
+ unsafe {
+ EnzymeSetCLBool(std::ptr::addr_of_mut!(RustTypeRules), val as u8);
+ }
+ }
+}
+
+#[cfg(not(llvm_enzyme))]
+pub use self::Fallback_AD::*;
+
+#[cfg(not(llvm_enzyme))]
+pub mod Fallback_AD {
+ #![allow(unused_variables)]
+
+ pub fn set_inline(val: bool) {
+ unimplemented!()
+ }
+ pub fn set_print_perf(print: bool) {
+ unimplemented!()
+ }
+ pub fn set_print_activity(print: bool) {
+ unimplemented!()
+ }
+ pub fn set_print_type(print: bool) {
+ unimplemented!()
+ }
+ pub fn set_print(print: bool) {
+ unimplemented!()
+ }
+ pub fn set_strict_aliasing(strict: bool) {
+ unimplemented!()
+ }
+ pub fn set_loose_types(loose: bool) {
+ unimplemented!()
+ }
+ pub fn set_rust_rules(val: bool) {
+ unimplemented!()
+ }
+}
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 3b0187b9d37b1..da91e6edbcfb8 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -954,6 +954,17 @@ bitflags! {
}
}
+// These values **must** match with LLVMGEPNoWrapFlags
+bitflags! {
+ #[repr(transparent)]
+ #[derive(Default)]
+ pub struct GEPNoWrapFlags : c_uint {
+ const InBounds = 1 << 0;
+ const NUSW = 1 << 1;
+ const NUW = 1 << 2;
+ }
+}
+
unsafe extern "C" {
pub type ModuleBuffer;
}
@@ -1454,21 +1465,14 @@ unsafe extern "C" {
pub(crate) fn LLVMBuildStore<'a>(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value;
- pub(crate) fn LLVMBuildGEP2<'a>(
- B: &Builder<'a>,
- Ty: &'a Type,
- Pointer: &'a Value,
- Indices: *const &'a Value,
- NumIndices: c_uint,
- Name: *const c_char,
- ) -> &'a Value;
- pub(crate) fn LLVMBuildInBoundsGEP2<'a>(
+ pub(crate) fn LLVMBuildGEPWithNoWrapFlags<'a>(
B: &Builder<'a>,
Ty: &'a Type,
Pointer: &'a Value,
Indices: *const &'a Value,
NumIndices: c_uint,
Name: *const c_char,
+ Flags: GEPNoWrapFlags,
) -> &'a Value;
// Casts
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index efc9cf2ef691b..5ec934241314c 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -403,3 +403,15 @@ pub(crate) fn add_module_flag_str(
);
}
}
+
+pub(crate) fn set_dllimport_storage_class<'ll>(v: &'ll Value) {
+ unsafe {
+ LLVMSetDLLStorageClass(v, DLLStorageClass::DllImport);
+ }
+}
+
+pub(crate) fn set_dso_local<'ll>(v: &'ll Value) {
+ unsafe {
+ LLVMRustSetDSOLocal(v, true);
+ }
+}
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index 70edee21bd63a..a64627eaf5986 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -38,11 +38,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
llvm::set_linkage(g, base::linkage_to_llvm(linkage));
llvm::set_visibility(g, base::visibility_to_llvm(visibility));
- unsafe {
- if self.should_assume_dso_local(g, false) {
- llvm::LLVMRustSetDSOLocal(g, true);
- }
- }
+ self.assume_dso_local(g, false);
self.instances.borrow_mut().insert(instance, g);
}
@@ -79,9 +75,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
debug!("predefine_fn: instance = {:?}", instance);
- if self.should_assume_dso_local(lldecl, false) {
- unsafe { llvm::LLVMRustSetDSOLocal(lldecl, true) };
- }
+ self.assume_dso_local(lldecl, false);
self.instances.borrow_mut().insert(instance, lldecl);
}
@@ -90,11 +84,16 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
impl CodegenCx<'_, '_> {
/// Whether a definition or declaration can be assumed to be local to a group of
/// libraries that form a single DSO or executable.
- pub(crate) fn should_assume_dso_local(
- &self,
- llval: &llvm::Value,
- is_declaration: bool,
- ) -> bool {
+ /// Marks the local as DSO if so.
+ pub(crate) fn assume_dso_local(&self, llval: &llvm::Value, is_declaration: bool) -> bool {
+ let assume = self.should_assume_dso_local(llval, is_declaration);
+ if assume {
+ llvm::set_dso_local(llval);
+ }
+ assume
+ }
+
+ fn should_assume_dso_local(&self, llval: &llvm::Value, is_declaration: bool) -> bool {
let linkage = llvm::get_linkage(llval);
let visibility = llvm::get_visibility(llval);
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index b0b6da869da68..ba01fbff38539 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -23,7 +23,7 @@ fn uncached_llvm_type<'a, 'tcx>(
let element = layout.scalar_llvm_type_at(cx, element);
return cx.type_vector(element, count);
}
- BackendRepr::Uninhabited | BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {}
+ BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {}
}
let name = match layout.ty.kind() {
@@ -172,19 +172,16 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
fn is_llvm_immediate(&self) -> bool {
match self.backend_repr {
BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true,
- BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
- false
- }
+ BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false,
}
}
fn is_llvm_scalar_pair(&self) -> bool {
match self.backend_repr {
BackendRepr::ScalarPair(..) => true,
- BackendRepr::Uninhabited
- | BackendRepr::Scalar(_)
- | BackendRepr::Vector { .. }
- | BackendRepr::Memory { .. } => false,
+ BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => {
+ false
+ }
}
}
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 2afc1efc1b34d..83d847f2d155a 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_codegen_ssa"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
@@ -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/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 105a4cb81f0d1..4c07645026943 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -244,22 +244,17 @@ pub fn each_linked_rlib(
fmts
} else {
- for combination in info.dependency_formats.iter().combinations(2) {
- let (ty1, list1) = &combination[0];
- let (ty2, list2) = &combination[1];
- if list1 != list2 {
- return Err(errors::LinkRlibError::IncompatibleDependencyFormats {
- ty1: format!("{ty1:?}"),
- ty2: format!("{ty2:?}"),
- list1: format!("{list1:?}"),
- list2: format!("{list2:?}"),
- });
- }
- }
- if info.dependency_formats.is_empty() {
- return Err(errors::LinkRlibError::MissingFormat);
+ let mut dep_formats = info.dependency_formats.iter();
+ let (ty1, list1) = dep_formats.next().ok_or(errors::LinkRlibError::MissingFormat)?;
+ if let Some((ty2, list2)) = dep_formats.find(|(_, list2)| list1 != *list2) {
+ return Err(errors::LinkRlibError::IncompatibleDependencyFormats {
+ ty1: format!("{ty1:?}"),
+ ty2: format!("{ty2:?}"),
+ list1: format!("{list1:?}"),
+ list2: format!("{list2:?}"),
+ });
}
- info.dependency_formats.first().unwrap().1
+ list1
};
let used_dep_crates = info.used_crates.iter();
@@ -626,10 +621,9 @@ fn link_staticlib(
let mut all_rust_dylibs = vec![];
for &cnum in crates {
- match fmts.get(cnum) {
- Some(&Linkage::Dynamic) => {}
- _ => continue,
- }
+ let Some(Linkage::Dynamic) = fmts.get(cnum) else {
+ continue;
+ };
let crate_name = codegen_results.crate_info.crate_name[&cnum];
let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum];
if let Some((path, _)) = &used_crate_source.dylib {
@@ -1990,6 +1984,7 @@ fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor)
if let Some(args) = sess.target.pre_link_args.get(&flavor) {
cmd.verbatim_args(args.iter().map(Deref::deref));
}
+
cmd.verbatim_args(&sess.opts.unstable_opts.pre_link_args);
}
@@ -2518,6 +2513,12 @@ fn add_order_independent_options(
"--target-cpu",
&codegen_results.crate_info.target_cpu,
]);
+ if codegen_results.crate_info.target_features.len() > 0 {
+ cmd.link_arg(&format!(
+ "--target-feature={}",
+ &codegen_results.crate_info.target_features.join(",")
+ ));
+ }
} else if flavor == LinkerFlavor::Ptx {
cmd.link_args(&["--fallback-arch", &codegen_results.crate_info.target_cpu]);
} else if flavor == LinkerFlavor::Bpf {
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index e3ace01c1eb54..8900405c1b8f8 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -153,6 +153,7 @@ pub(crate) fn get_linker<'a>(
hinted_static: None,
is_ld: cc == Cc::No,
is_gnu: flavor.is_gnu(),
+ uses_lld: flavor.uses_lld(),
}) as Box,
LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box,
LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box,
@@ -361,6 +362,7 @@ struct GccLinker<'a> {
// Link as ld
is_ld: bool,
is_gnu: bool,
+ uses_lld: bool,
}
impl<'a> GccLinker<'a> {
@@ -552,6 +554,7 @@ impl<'a> Linker for GccLinker<'a> {
self.link_args(&["--entry", "_initialize"]);
}
}
+
// VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
// it switches linking for libc and similar system libraries to static without using
// any `#[link]` attributes in the `libc` crate, see #72782 for details.
@@ -567,6 +570,15 @@ impl<'a> Linker for GccLinker<'a> {
{
self.cc_arg("--static-crt");
}
+
+ // avr-none doesn't have default ISA, users must specify which specific
+ // CPU (well, microcontroller) they are targetting using `-Ctarget-cpu`.
+ //
+ // Currently this makes sense only when using avr-gcc as a linker, since
+ // it brings a couple of hand-written important intrinsics from libgcc.
+ if self.sess.target.arch == "avr" && !self.uses_lld {
+ self.verbatim_arg(format!("-mmcu={}", self.target_cpu));
+ }
}
fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) {
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index d70413b8a4741..236507ac0cd28 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -252,15 +252,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option return None,
};
- let binary_format = if sess.target.is_like_osx {
- BinaryFormat::MachO
- } else if sess.target.is_like_windows {
- BinaryFormat::Coff
- } else if sess.target.is_like_aix {
- BinaryFormat::Xcoff
- } else {
- BinaryFormat::Elf
- };
+ let binary_format = sess.target.binary_format.to_object();
let mut file = write::Object::new(binary_format, architecture, endianness);
file.set_sub_architecture(sub_architecture);
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 12ee872d53141..459f4329d6e92 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -183,11 +183,11 @@ fn exported_symbols_provider_local(
});
let mut symbols: Vec<_> =
- sorted.iter().map(|(&def_id, &info)| (ExportedSymbol::NonGeneric(def_id), info)).collect();
+ sorted.iter().map(|&(&def_id, &info)| (ExportedSymbol::NonGeneric(def_id), info)).collect();
// Export TLS shims
if !tcx.sess.target.dll_tls_export {
- symbols.extend(sorted.iter().filter_map(|(&def_id, &info)| {
+ symbols.extend(sorted.iter().filter_map(|&(&def_id, &info)| {
tcx.needs_thread_local_shim(def_id).then(|| {
(
ExportedSymbol::ThreadLocalShim(def_id),
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index f029c08a80821..f008bd12ed8fe 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -405,7 +405,8 @@ fn generate_lto_work(
B::run_fat_lto(cgcx, needs_fat_lto, import_only_modules).unwrap_or_else(|e| e.raise());
if cgcx.lto == Lto::Fat && !autodiff.is_empty() {
let config = cgcx.config(ModuleKind::Regular);
- module = unsafe { module.autodiff(cgcx, autodiff, config).unwrap() };
+ module =
+ unsafe { module.autodiff(cgcx, autodiff, config).unwrap_or_else(|e| e.raise()) };
}
// We are adding a single work item, so the cost doesn't matter.
vec![(WorkItem::LTO(module), 0)]
@@ -572,10 +573,10 @@ fn produce_final_output_artifacts(
};
let copy_if_one_unit = |output_type: OutputType, keep_numbered: bool| {
- if compiled_modules.modules.len() == 1 {
+ if let [module] = &compiled_modules.modules[..] {
// 1) Only one codegen unit. In this case it's no difficulty
// to copy `foo.0.x` to `foo.x`.
- let module_name = Some(&compiled_modules.modules[0].name[..]);
+ let module_name = Some(&module.name[..]);
let path = crate_output.temp_path(output_type, module_name);
let output = crate_output.path(output_type);
if !output_type.is_text_output() && output.is_tty() {
@@ -707,8 +708,8 @@ fn produce_final_output_artifacts(
}
if sess.opts.json_artifact_notifications {
- if compiled_modules.modules.len() == 1 {
- compiled_modules.modules[0].for_each_output(|_path, ty| {
+ if let [module] = &compiled_modules.modules[..] {
+ module.for_each_output(|_path, ty| {
if sess.opts.output_types.contains_key(&ty) {
let descr = ty.shorthand();
// for single cgu file is renamed to drop cgu specific suffix
@@ -864,7 +865,7 @@ pub(crate) fn compute_per_cgu_lto_type(
// require LTO so the request for LTO is always unconditionally
// passed down to the backend, but we don't actually want to do
// anything about it yet until we've got a final product.
- let is_rlib = sess_crate_types.len() == 1 && sess_crate_types[0] == CrateType::Rlib;
+ let is_rlib = matches!(sess_crate_types, [CrateType::Rlib]);
match sess_lto {
Lto::ThinLocal if !linker_does_lto && !is_allocator => ComputedLtoType::Thin,
@@ -1537,8 +1538,9 @@ fn start_executing_work(
// Spin up what work we can, only doing this while we've got available
// parallelism slots and work left to spawn.
if codegen_state != Aborted {
- while !work_items.is_empty() && running_with_own_token < tokens.len() {
- let (item, _) = work_items.pop().unwrap();
+ while running_with_own_token < tokens.len()
+ && let Some((item, _)) = work_items.pop()
+ {
spawn_work(
&cgcx,
&mut llvm_start_time,
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index e800492dad02f..40238f4b4915a 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -24,7 +24,7 @@ use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_session::Session;
-use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
+use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
use rustc_span::{DUMMY_SP, Symbol, sym};
use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
@@ -364,13 +364,7 @@ pub(crate) fn build_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let rhs_sz = bx.cx().int_width(rhs_llty);
let lhs_sz = bx.cx().int_width(lhs_llty);
if lhs_sz < rhs_sz {
- if is_unchecked && bx.sess().opts.optimize != OptLevel::No {
- // FIXME: Use `trunc nuw` once that's available
- let inrange = bx.icmp(IntPredicate::IntULE, rhs, mask);
- bx.assume(inrange);
- }
-
- bx.trunc(rhs, lhs_llty)
+ if is_unchecked { bx.unchecked_utrunc(rhs, lhs_llty) } else { bx.trunc(rhs, lhs_llty) }
} else if lhs_sz > rhs_sz {
// We zero-extend even if the RHS is signed. So e.g. `(x: i32) << -1i8` will zero-extend the
// RHS to `255i32`. But then we mask the shift amount to be within the size of the LHS
@@ -921,6 +915,7 @@ impl CrateInfo {
let n_crates = crates.len();
let mut info = CrateInfo {
target_cpu,
+ target_features: tcx.global_backend_features(()).clone(),
crate_types,
exported_symbols,
linked_symbols,
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 3e9dfcea58b8b..97bc84c0b698b 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -1,7 +1,6 @@
use std::str::FromStr;
use rustc_abi::ExternAbi;
-use rustc_ast::attr::list_contains_name;
use rustc_ast::expand::autodiff_attrs::{
AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
};
@@ -377,24 +376,20 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
let segments =
set.path.segments.iter().map(|x| x.ident.name).collect::>();
match segments.as_slice() {
- [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
- if !tcx.sess.target.has_thumb_interworking {
- struct_span_code_err!(
- tcx.dcx(),
- attr.span,
- E0779,
- "target does not support `#[instruction_set]`"
- )
- .emit();
- None
- } else if segments[1] == sym::a32 {
- Some(InstructionSetAttr::ArmA32)
- } else if segments[1] == sym::t32 {
- Some(InstructionSetAttr::ArmT32)
- } else {
- unreachable!()
- }
+ [sym::arm, sym::a32 | sym::t32]
+ if !tcx.sess.target.has_thumb_interworking =>
+ {
+ struct_span_code_err!(
+ tcx.dcx(),
+ attr.span,
+ E0779,
+ "target does not support `#[instruction_set]`"
+ )
+ .emit();
+ None
}
+ [sym::arm, sym::a32] => Some(InstructionSetAttr::ArmA32),
+ [sym::arm, sym::t32] => Some(InstructionSetAttr::ArmT32),
_ => {
struct_span_code_err!(
tcx.dcx(),
@@ -435,7 +430,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
&& let Some((sym::align, literal)) = item.singleton_lit_list()
{
rustc_attr_parsing::parse_alignment(&literal.kind)
- .map_err(|msg| {
+ .inspect_err(|msg| {
struct_span_code_err!(
tcx.dcx(),
literal.span,
@@ -536,25 +531,27 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
}
if attr.is_word() {
- InlineAttr::Hint
- } else if let Some(ref items) = attr.meta_item_list() {
- inline_span = Some(attr.span);
- if items.len() != 1 {
- struct_span_code_err!(tcx.dcx(), attr.span, E0534, "expected one argument").emit();
- InlineAttr::None
- } else if list_contains_name(items, sym::always) {
- InlineAttr::Always
- } else if list_contains_name(items, sym::never) {
- InlineAttr::Never
- } else {
- struct_span_code_err!(tcx.dcx(), items[0].span(), E0535, "invalid argument")
- .with_help("valid inline arguments are `always` and `never`")
- .emit();
+ return InlineAttr::Hint;
+ }
+ let Some(ref items) = attr.meta_item_list() else {
+ return ia;
+ };
- InlineAttr::None
- }
+ inline_span = Some(attr.span);
+ let [item] = &items[..] else {
+ struct_span_code_err!(tcx.dcx(), attr.span, E0534, "expected one argument").emit();
+ return InlineAttr::None;
+ };
+ if item.has_name(sym::always) {
+ InlineAttr::Always
+ } else if item.has_name(sym::never) {
+ InlineAttr::Never
} else {
- ia
+ struct_span_code_err!(tcx.dcx(), item.span(), E0535, "invalid argument")
+ .with_help("valid inline arguments are `always` and `never`")
+ .emit();
+
+ InlineAttr::None
}
});
codegen_fn_attrs.inline = attrs.iter().fold(codegen_fn_attrs.inline, |ia, attr| {
@@ -586,23 +583,25 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
let err = |sp, s| struct_span_code_err!(tcx.dcx(), sp, E0722, "{}", s).emit();
if attr.is_word() {
err(attr.span, "expected one argument");
- ia
- } else if let Some(ref items) = attr.meta_item_list() {
- inline_span = Some(attr.span);
- if items.len() != 1 {
- err(attr.span, "expected one argument");
- OptimizeAttr::Default
- } else if list_contains_name(items, sym::size) {
- OptimizeAttr::Size
- } else if list_contains_name(items, sym::speed) {
- OptimizeAttr::Speed
- } else if list_contains_name(items, sym::none) {
- OptimizeAttr::DoNotOptimize
- } else {
- err(items[0].span(), "invalid argument");
- OptimizeAttr::Default
- }
+ return ia;
+ }
+ let Some(ref items) = attr.meta_item_list() else {
+ return OptimizeAttr::Default;
+ };
+
+ inline_span = Some(attr.span);
+ let [item] = &items[..] else {
+ err(attr.span, "expected one argument");
+ return OptimizeAttr::Default;
+ };
+ if item.has_name(sym::size) {
+ OptimizeAttr::Size
+ } else if item.has_name(sym::speed) {
+ OptimizeAttr::Speed
+ } else if item.has_name(sym::none) {
+ OptimizeAttr::DoNotOptimize
} else {
+ err(item.span(), "invalid argument");
OptimizeAttr::Default
}
});
@@ -644,25 +643,20 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
// llvm/llvm-project#70563).
if !codegen_fn_attrs.target_features.is_empty()
&& matches!(codegen_fn_attrs.inline, InlineAttr::Always)
+ && let Some(span) = inline_span
{
- if let Some(span) = inline_span {
- tcx.dcx().span_err(span, "cannot use `#[inline(always)]` with `#[target_feature]`");
- }
+ tcx.dcx().span_err(span, "cannot use `#[inline(always)]` with `#[target_feature]`");
}
- if !codegen_fn_attrs.no_sanitize.is_empty() && codegen_fn_attrs.inline.always() {
- if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
- let hir_id = tcx.local_def_id_to_hir_id(did);
- tcx.node_span_lint(
- lint::builtin::INLINE_NO_SANITIZE,
- hir_id,
- no_sanitize_span,
- |lint| {
- lint.primary_message("`no_sanitize` will have no effect after inlining");
- lint.span_note(inline_span, "inlining requested here");
- },
- )
- }
+ if !codegen_fn_attrs.no_sanitize.is_empty()
+ && codegen_fn_attrs.inline.always()
+ && let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span)
+ {
+ let hir_id = tcx.local_def_id_to_hir_id(did);
+ tcx.node_span_lint(lint::builtin::INLINE_NO_SANITIZE, hir_id, no_sanitize_span, |lint| {
+ lint.primary_message("`no_sanitize` will have no effect after inlining");
+ lint.span_note(inline_span, "inlining requested here");
+ })
}
// Weak lang items have the same semantics as "std internal" symbols in the
@@ -692,10 +686,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
// Any linkage to LLVM intrinsics for now forcibly marks them all as never
// unwinds since LLVM sometimes can't handle codegen which `invoke`s
// intrinsic functions.
- if let Some(name) = &codegen_fn_attrs.link_name {
- if name.as_str().starts_with("llvm.") {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
- }
+ if let Some(name) = &codegen_fn_attrs.link_name
+ && name.as_str().starts_with("llvm.")
+ {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
}
if let Some(features) = check_tied_features(
@@ -756,18 +750,13 @@ fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Option {
use rustc_ast::{LitIntType, LitKind, MetaItemLit};
- let meta_item_list = attr.meta_item_list();
- let meta_item_list = meta_item_list.as_deref();
- let sole_meta_list = match meta_item_list {
- Some([item]) => item.lit(),
- Some(_) => {
- tcx.dcx().emit_err(errors::InvalidLinkOrdinalNargs { span: attr.span });
- return None;
- }
- _ => None,
+ let meta_item_list = attr.meta_item_list()?;
+ let [sole_meta_list] = &meta_item_list[..] else {
+ tcx.dcx().emit_err(errors::InvalidLinkOrdinalNargs { span: attr.span });
+ return None;
};
if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
- sole_meta_list
+ sole_meta_list.lit()
{
// According to the table at
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header, the
@@ -894,7 +883,7 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option {
let [mode, input_activities @ .., ret_activity] = &list[..] else {
span_bug!(attr.span, "rustc_autodiff attribute must contain mode and activities");
};
- let mode = if let MetaItemInner::MetaItem(MetaItem { path: ref p1, .. }) = mode {
+ let mode = if let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = mode {
p1.segments.first().unwrap().ident
} else {
span_bug!(attr.span, "rustc_autodiff attribute must contain mode");
@@ -910,7 +899,7 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option {
};
// First read the ret symbol from the attribute
- let ret_symbol = if let MetaItemInner::MetaItem(MetaItem { path: ref p1, .. }) = ret_activity {
+ let ret_symbol = if let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = ret_activity {
p1.segments.first().unwrap().ident
} else {
span_bug!(attr.span, "rustc_autodiff attribute must contain the return activity");
@@ -924,7 +913,7 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option {
// Now parse all the intermediate (input) activities
let mut arg_activities: Vec = vec![];
for arg in input_activities {
- let arg_symbol = if let MetaItemInner::MetaItem(MetaItem { path: ref p2, .. }) = arg {
+ let arg_symbol = if let MetaItemInner::MetaItem(MetaItem { path: p2, .. }) = arg {
match p2.segments.first() {
Some(x) => x.ident,
None => {
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 53953b089c613..84703a0a15692 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/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 428a45975f1ec..9d2ac219d592c 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -190,6 +190,7 @@ impl From<&cstore::NativeLib> for NativeLib {
#[derive(Debug, Encodable, Decodable)]
pub struct CrateInfo {
pub target_cpu: String,
+ pub target_features: Vec,
pub crate_types: Vec,
pub exported_symbols: UnordMap>,
pub linked_symbols: FxIndexMap>,
@@ -230,6 +231,7 @@ pub fn provide(providers: &mut Providers) {
crate::base::provide(providers);
crate::target_features::provide(providers);
crate::codegen_attrs::provide(providers);
+ providers.queries.global_backend_features = |_tcx: TyCtxt<'_>, ()| vec![];
}
/// Checks if the given filename ends with the `.rcgu.o` extension that `rustc`
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 4630ed48c520e..1e52c6394635b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -4,9 +4,7 @@ use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, WrappingRange};
use rustc_ast as ast;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::lang_items::LangItem;
-use rustc_middle::mir::{
- self, AssertKind, BasicBlock, InlineAsmMacro, SwitchTargets, UnwindTerminateReason,
-};
+use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty};
@@ -429,11 +427,34 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let cmp = bx.icmp(IntPredicate::IntEQ, discr_value, llval);
bx.cond_br(cmp, ll1, ll2);
} else {
- bx.switch(
- discr_value,
- helper.llbb_with_cleanup(self, targets.otherwise()),
- target_iter.map(|(value, target)| (value, helper.llbb_with_cleanup(self, target))),
- );
+ let otherwise = targets.otherwise();
+ let otherwise_cold = self.cold_blocks[otherwise];
+ let otherwise_unreachable = self.mir[otherwise].is_empty_unreachable();
+ let cold_count = targets.iter().filter(|(_, target)| self.cold_blocks[*target]).count();
+ let none_cold = cold_count == 0;
+ let all_cold = cold_count == targets.iter().len();
+ if (none_cold && (!otherwise_cold || otherwise_unreachable))
+ || (all_cold && (otherwise_cold || otherwise_unreachable))
+ {
+ // All targets have the same weight,
+ // or `otherwise` is unreachable and it's the only target with a different weight.
+ bx.switch(
+ discr_value,
+ helper.llbb_with_cleanup(self, targets.otherwise()),
+ target_iter
+ .map(|(value, target)| (value, helper.llbb_with_cleanup(self, target))),
+ );
+ } else {
+ // Targets have different weights
+ bx.switch_with_weights(
+ discr_value,
+ helper.llbb_with_cleanup(self, targets.otherwise()),
+ otherwise_cold,
+ target_iter.map(|(value, target)| {
+ (value, helper.llbb_with_cleanup(self, target), self.cold_blocks[target])
+ }),
+ );
+ }
}
}
@@ -699,14 +720,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// Put together the arguments to the panic entry point.
let (lang_item, args) = match msg {
- AssertKind::BoundsCheck { ref len, ref index } => {
+ AssertKind::BoundsCheck { len, index } => {
let len = self.codegen_operand(bx, len).immediate();
let index = self.codegen_operand(bx, index).immediate();
// It's `fn panic_bounds_check(index: usize, len: usize)`,
// and `#[track_caller]` adds an implicit third argument.
(LangItem::PanicBoundsCheck, vec![index, len, location])
}
- AssertKind::MisalignedPointerDereference { ref required, ref found } => {
+ AssertKind::MisalignedPointerDereference { required, found } => {
let required = self.codegen_operand(bx, required).immediate();
let found = self.codegen_operand(bx, found).immediate();
// It's `fn panic_misaligned_pointer_dereference(required: usize, found: usize)`,
@@ -919,7 +940,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
&fn_abi.ret,
&mut llargs,
Some(intrinsic),
- target,
);
let dest = match ret_dest {
_ if fn_abi.ret.is_indirect() => llargs[0],
@@ -975,23 +995,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
};
let mut llargs = Vec::with_capacity(arg_count);
- let destination = target.as_ref().map(|&target| {
- (
- self.make_return_dest(
- bx,
- destination,
- &fn_abi.ret,
- &mut llargs,
- None,
- Some(target),
- ),
- target,
- )
- });
+
+ // We still need to call `make_return_dest` even if there's no `target`, since
+ // `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited,
+ // and `make_return_dest` adds the return-place indirect pointer to `llargs`.
+ let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, None);
+ let destination = target.map(|target| (return_dest, target));
// Split the rust-call tupled arguments off.
- let (first_args, untuple) = if abi == ExternAbi::RustCall && !args.is_empty() {
- let (tup, args) = args.split_last().unwrap();
+ let (first_args, untuple) = if abi == ExternAbi::RustCall
+ && let Some((tup, args)) = args.split_last()
+ {
(args, Some(tup))
} else {
(args, None)
@@ -1017,7 +1031,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let (idx, _) = op.layout.non_1zst_field(bx).expect(
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
);
- op = op.extract_field(bx, idx);
+ op = op.extract_field(self, bx, idx);
}
// Now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
@@ -1049,7 +1063,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let (idx, _) = op.layout.non_1zst_field(bx).expect(
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
);
- op = op.extract_field(bx, idx);
+ op = op.extract_field(self, bx, idx);
}
// Make sure that we've actually unwrapped the rcvr down
@@ -1549,9 +1563,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if scalar.is_bool() {
bx.range_metadata(llval, WrappingRange { start: 0, end: 1 });
}
+ // We store bools as `i8` so we need to truncate to `i1`.
+ llval = bx.to_immediate_scalar(llval, scalar);
}
- // We store bools as `i8` so we need to truncate to `i1`.
- llval = bx.to_immediate(llval, arg.layout);
}
}
@@ -1581,7 +1595,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} else {
// If the tuple is immediate, the elements are as well.
for i in 0..tuple.layout.fields.count() {
- let op = tuple.extract_field(bx, i);
+ let op = tuple.extract_field(self, bx, i);
self.codegen_argument(bx, op, llargs, &args[i]);
}
}
@@ -1790,11 +1804,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
fn_ret: &ArgAbi<'tcx, Ty<'tcx>>,
llargs: &mut Vec,
intrinsic: Option,
- target: Option,
) -> ReturnDest<'tcx, Bx::Value> {
- if target.is_none() {
- return ReturnDest::Nothing;
- }
// If the return is ignored, we can just return a do-nothing `ReturnDest`.
if fn_ret.is_ignore() {
return ReturnDest::Nothing;
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 3a896071bc6b8..ba28720afecdd 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -502,14 +502,25 @@ fn find_cold_blocks<'tcx>(
for (bb, bb_data) in traversal::postorder(mir) {
let terminator = bb_data.terminator();
- // If a BB ends with a call to a cold function, mark it as cold.
- if let mir::TerminatorKind::Call { ref func, .. } = terminator.kind
- && let ty::FnDef(def_id, ..) = *func.ty(local_decls, tcx).kind()
- && let attrs = tcx.codegen_fn_attrs(def_id)
- && attrs.flags.contains(CodegenFnAttrFlags::COLD)
- {
- cold_blocks[bb] = true;
- continue;
+ match terminator.kind {
+ // If a BB ends with a call to a cold function, mark it as cold.
+ mir::TerminatorKind::Call { ref func, .. }
+ | mir::TerminatorKind::TailCall { ref func, .. }
+ if let ty::FnDef(def_id, ..) = *func.ty(local_decls, tcx).kind()
+ && let attrs = tcx.codegen_fn_attrs(def_id)
+ && attrs.flags.contains(CodegenFnAttrFlags::COLD) =>
+ {
+ cold_blocks[bb] = true;
+ continue;
+ }
+
+ // If a BB ends with an `unreachable`, also mark it as cold.
+ mir::TerminatorKind::Unreachable => {
+ cold_blocks[bb] = true;
+ continue;
+ }
+
+ _ => {}
}
// If all successors of a BB are cold and there's at least one of them, mark this BB as cold
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
index eb0711dbb32ff..0593fb420c306 100644
--- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::{Instance, Ty, TyCtxt};
use rustc_middle::{bug, span_bug, ty};
use rustc_span::sym;
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
-use rustc_target::spec::WasmCAbi;
+use rustc_target::spec::{BinaryFormat, WasmCAbi};
use crate::common;
use crate::traits::{AsmCodegenMethods, BuilderMethods, GlobalAsmOperandRef, MiscCodegenMethods};
@@ -104,27 +104,6 @@ fn inline_to_global_operand<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
}
}
-enum AsmBinaryFormat {
- Elf,
- Macho,
- Coff,
- Wasm,
-}
-
-impl AsmBinaryFormat {
- fn from_target(target: &rustc_target::spec::Target) -> Self {
- if target.is_like_windows {
- Self::Coff
- } else if target.is_like_osx {
- Self::Macho
- } else if target.is_like_wasm {
- Self::Wasm
- } else {
- Self::Elf
- }
- }
-}
-
fn prefix_and_suffix<'tcx>(
tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>,
@@ -134,7 +113,7 @@ fn prefix_and_suffix<'tcx>(
) -> (String, String) {
use std::fmt::Write;
- let asm_binary_format = AsmBinaryFormat::from_target(&tcx.sess.target);
+ let asm_binary_format = &tcx.sess.target.binary_format;
let is_arm = tcx.sess.target.arch == "arm";
let is_thumb = tcx.sess.unstable_target_features.contains(&sym::thumb_mode);
@@ -178,10 +157,13 @@ fn prefix_and_suffix<'tcx>(
}
Linkage::LinkOnceAny | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR => {
match asm_binary_format {
- AsmBinaryFormat::Elf | AsmBinaryFormat::Coff | AsmBinaryFormat::Wasm => {
+ BinaryFormat::Elf
+ | BinaryFormat::Coff
+ | BinaryFormat::Wasm
+ | BinaryFormat::Xcoff => {
writeln!(w, ".weak {asm_name}")?;
}
- AsmBinaryFormat::Macho => {
+ BinaryFormat::MachO => {
writeln!(w, ".globl {asm_name}")?;
writeln!(w, ".weak_definition {asm_name}")?;
}
@@ -207,7 +189,7 @@ fn prefix_and_suffix<'tcx>(
let mut begin = String::new();
let mut end = String::new();
match asm_binary_format {
- AsmBinaryFormat::Elf => {
+ BinaryFormat::Elf | BinaryFormat::Xcoff => {
let section = link_section.unwrap_or(format!(".text.{asm_name}"));
let progbits = match is_arm {
@@ -239,7 +221,7 @@ fn prefix_and_suffix<'tcx>(
writeln!(end, "{}", arch_suffix).unwrap();
}
}
- AsmBinaryFormat::Macho => {
+ BinaryFormat::MachO => {
let section = link_section.unwrap_or("__TEXT,__text".to_string());
writeln!(begin, ".pushsection {},regular,pure_instructions", section).unwrap();
writeln!(begin, ".balign {align}").unwrap();
@@ -255,7 +237,7 @@ fn prefix_and_suffix<'tcx>(
writeln!(end, "{}", arch_suffix).unwrap();
}
}
- AsmBinaryFormat::Coff => {
+ BinaryFormat::Coff => {
let section = link_section.unwrap_or(format!(".text.{asm_name}"));
writeln!(begin, ".pushsection {},\"xr\"", section).unwrap();
writeln!(begin, ".balign {align}").unwrap();
@@ -272,7 +254,7 @@ fn prefix_and_suffix<'tcx>(
writeln!(end, "{}", arch_suffix).unwrap();
}
}
- AsmBinaryFormat::Wasm => {
+ BinaryFormat::Wasm => {
let section = link_section.unwrap_or(format!(".text.{asm_name}"));
writeln!(begin, ".section {section},\"\",@").unwrap();
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 9ca7d4f8f0047..461cf1b8acdaf 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -1,15 +1,14 @@
-use std::assert_matches::assert_matches;
use std::fmt;
use arrayvec::ArrayVec;
use either::Either;
use rustc_abi as abi;
use rustc_abi::{Align, BackendRepr, Size};
-use rustc_middle::bug;
use rustc_middle::mir::interpret::{Pointer, Scalar, alloc_range};
use rustc_middle::mir::{self, ConstValue};
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::{bug, span_bug};
use tracing::debug;
use super::place::{PlaceRef, PlaceValue};
@@ -352,79 +351,83 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
pub(crate) fn extract_field>(
&self,
+ fx: &mut FunctionCx<'a, 'tcx, Bx>,
bx: &mut Bx,
i: usize,
) -> Self {
let field = self.layout.field(bx.cx(), i);
let offset = self.layout.fields.offset(i);
- let mut val = match (self.val, self.layout.backend_repr) {
- // If the field is ZST, it has no data.
- _ if field.is_zst() => OperandValue::ZeroSized,
-
- // Newtype of a scalar, scalar pair or vector.
- (OperandValue::Immediate(_) | OperandValue::Pair(..), _)
- if field.size == self.layout.size =>
+ if !bx.is_backend_ref(self.layout) && bx.is_backend_ref(field) {
+ if let BackendRepr::Vector { count, .. } = self.layout.backend_repr
+ && let BackendRepr::Memory { sized: true } = field.backend_repr
+ && count.is_power_of_two()
{
- assert_eq!(offset.bytes(), 0);
- self.val
+ assert_eq!(field.size, self.layout.size);
+ // This is being deprecated, but for now stdarch still needs it for
+ // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
+ let place = PlaceRef::alloca(bx, field);
+ self.val.store(bx, place.val.with_type(self.layout));
+ return bx.load_operand(place);
+ } else {
+ // Part of https://github.com/rust-lang/compiler-team/issues/838
+ bug!("Non-ref type {self:?} cannot project to ref field type {field:?}");
}
+ }
- // Extract a scalar component from a pair.
- (OperandValue::Pair(a_llval, b_llval), BackendRepr::ScalarPair(a, b)) => {
- if offset.bytes() == 0 {
- assert_eq!(field.size, a.size(bx.cx()));
- OperandValue::Immediate(a_llval)
- } else {
- assert_eq!(offset, a.size(bx.cx()).align_to(b.align(bx.cx()).abi));
- assert_eq!(field.size, b.size(bx.cx()));
- OperandValue::Immediate(b_llval)
+ let val = if field.is_zst() {
+ OperandValue::ZeroSized
+ } else if field.size == self.layout.size {
+ assert_eq!(offset.bytes(), 0);
+ fx.codegen_transmute_operand(bx, *self, field).unwrap_or_else(|| {
+ bug!(
+ "Expected `codegen_transmute_operand` to handle equal-size \
+ field {i:?} projection from {self:?} to {field:?}"
+ )
+ })
+ } else {
+ let (in_scalar, imm) = match (self.val, self.layout.backend_repr) {
+ // Extract a scalar component from a pair.
+ (OperandValue::Pair(a_llval, b_llval), BackendRepr::ScalarPair(a, b)) => {
+ if offset.bytes() == 0 {
+ assert_eq!(field.size, a.size(bx.cx()));
+ (Some(a), a_llval)
+ } else {
+ assert_eq!(offset, a.size(bx.cx()).align_to(b.align(bx.cx()).abi));
+ assert_eq!(field.size, b.size(bx.cx()));
+ (Some(b), b_llval)
+ }
}
- }
-
- // `#[repr(simd)]` types are also immediate.
- (OperandValue::Immediate(llval), BackendRepr::Vector { .. }) => {
- OperandValue::Immediate(bx.extract_element(llval, bx.cx().const_usize(i as u64)))
- }
- _ => bug!("OperandRef::extract_field({:?}): not applicable", self),
+ _ => {
+ span_bug!(fx.mir.span, "OperandRef::extract_field({:?}): not applicable", self)
+ }
+ };
+ OperandValue::Immediate(match field.backend_repr {
+ BackendRepr::Vector { .. } => imm,
+ BackendRepr::Scalar(out_scalar) => {
+ let Some(in_scalar) = in_scalar else {
+ span_bug!(
+ fx.mir.span,
+ "OperandRef::extract_field({:?}): missing input scalar for output scalar",
+ self
+ )
+ };
+ if in_scalar != out_scalar {
+ // If the backend and backend_immediate types might differ,
+ // flip back to the backend type then to the new immediate.
+ // This avoids nop truncations, but still handles things like
+ // Bools in union fields needs to be truncated.
+ let backend = bx.from_immediate(imm);
+ bx.to_immediate_scalar(backend, out_scalar)
+ } else {
+ imm
+ }
+ }
+ BackendRepr::ScalarPair(_, _) | BackendRepr::Memory { .. } => bug!(),
+ })
};
- match (&mut val, field.backend_repr) {
- (OperandValue::ZeroSized, _) => {}
- (
- OperandValue::Immediate(llval),
- BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. },
- ) => {
- // Bools in union fields needs to be truncated.
- *llval = bx.to_immediate(*llval, field);
- }
- (OperandValue::Pair(a, b), BackendRepr::ScalarPair(a_abi, b_abi)) => {
- // Bools in union fields needs to be truncated.
- *a = bx.to_immediate_scalar(*a, a_abi);
- *b = bx.to_immediate_scalar(*b, b_abi);
- }
- // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
- (OperandValue::Immediate(llval), BackendRepr::Memory { sized: true }) => {
- assert_matches!(self.layout.backend_repr, BackendRepr::Vector { .. });
-
- let llfield_ty = bx.cx().backend_type(field);
-
- // Can't bitcast an aggregate, so round trip through memory.
- let llptr = bx.alloca(field.size, field.align.abi);
- bx.store(*llval, llptr, field.align.abi);
- *llval = bx.load(llfield_ty, llptr, field.align.abi);
- }
- (
- OperandValue::Immediate(_),
- BackendRepr::Uninhabited | BackendRepr::Memory { sized: false },
- ) => {
- bug!()
- }
- (OperandValue::Pair(..), _) => bug!(),
- (OperandValue::Ref(..), _) => bug!(),
- }
-
OperandRef { val, layout: field }
}
}
@@ -581,13 +584,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// Moves out of scalar and scalar pair fields are trivial.
for elem in place_ref.projection.iter() {
match elem {
- mir::ProjectionElem::Field(ref f, _) => {
+ mir::ProjectionElem::Field(f, _) => {
assert!(
!o.layout.ty.is_any_ptr(),
"Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \
but tried to access field {f:?} of pointer {o:?}",
);
- o = o.extract_field(bx, f.index());
+ o = o.extract_field(self, bx, f.index());
}
mir::ProjectionElem::Index(_)
| mir::ProjectionElem::ConstantIndex { .. } => {
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index eb4270ffe8096..edd09b9c3c5fd 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};
@@ -423,7 +423,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
layout.size
};
- let llval = bx.inbounds_gep(bx.cx().backend_type(layout), self.val.llval, &[llindex]);
+ let llval = bx.inbounds_nuw_gep(bx.cx().backend_type(layout), self.val.llval, &[llindex]);
let align = self.val.align.restrict_for_offset(offset);
PlaceValue::new_sized(llval, align).with_type(layout)
}
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 4c5b183cfe92a..1eebe04225bef 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -231,7 +231,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
///
/// Returns `None` for cases that can't work in that framework, such as for
/// `Immediate`->`Ref` that needs an `alloc` to get the location.
- fn codegen_transmute_operand(
+ pub(crate) fn codegen_transmute_operand(
&mut self,
bx: &mut Bx,
operand: OperandRef<'tcx, Bx::Value>,
@@ -260,6 +260,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
OperandValue::Ref(source_place_val) => {
assert_eq!(source_place_val.llextra, None);
assert_matches!(operand_kind, OperandValueKind::Ref);
+ // The existing alignment is part of `source_place_val`,
+ // so that alignment will be used, not `cast`'s.
Some(bx.load_operand(source_place_val.with_type(cast)).val)
}
OperandValue::ZeroSized => {
@@ -664,9 +666,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
lhs.layout.ty,
),
- (OperandValue::Immediate(lhs_val), OperandValue::Immediate(rhs_val)) => {
- self.codegen_scalar_binop(bx, op, lhs_val, rhs_val, lhs.layout.ty)
- }
+ (OperandValue::Immediate(lhs_val), OperandValue::Immediate(rhs_val)) => self
+ .codegen_scalar_binop(
+ bx,
+ op,
+ lhs_val,
+ rhs_val,
+ lhs.layout.ty,
+ rhs.layout.ty,
+ ),
_ => bug!(),
};
@@ -887,10 +895,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
op: mir::BinOp,
lhs: Bx::Value,
rhs: Bx::Value,
- input_ty: Ty<'tcx>,
+ lhs_ty: Ty<'tcx>,
+ rhs_ty: Ty<'tcx>,
) -> Bx::Value {
- let is_float = input_ty.is_floating_point();
- let is_signed = input_ty.is_signed();
+ let is_float = lhs_ty.is_floating_point();
+ let is_signed = lhs_ty.is_signed();
match op {
mir::BinOp::Add => {
if is_float {
@@ -956,9 +965,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::BinOp::BitAnd => bx.and(lhs, rhs),
mir::BinOp::BitXor => bx.xor(lhs, rhs),
mir::BinOp::Offset => {
- let pointee_type = input_ty
+ let pointee_type = lhs_ty
.builtin_deref(true)
- .unwrap_or_else(|| bug!("deref of non-pointer {:?}", input_ty));
+ .unwrap_or_else(|| bug!("deref of non-pointer {:?}", lhs_ty));
let pointee_layout = bx.cx().layout_of(pointee_type);
if pointee_layout.is_zst() {
// `Offset` works in terms of the size of pointee,
@@ -966,7 +975,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
lhs
} else {
let llty = bx.cx().backend_type(pointee_layout);
- bx.inbounds_gep(llty, lhs, &[rhs])
+ if !rhs_ty.is_signed() {
+ bx.inbounds_nuw_gep(llty, lhs, &[rhs])
+ } else {
+ bx.inbounds_gep(llty, lhs, &[rhs])
+ }
}
}
mir::BinOp::Shl | mir::BinOp::ShlUnchecked => {
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index 5f95b6615bd30..f6af889fd6ecb 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -36,7 +36,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
}
MonoItem::GlobalAsm(item_id) => {
let item = cx.tcx().hir_item(item_id);
- if let hir::ItemKind::GlobalAsm(asm) = item.kind {
+ if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind {
let operands: Vec<_> = asm
.operands
.iter()
@@ -71,11 +71,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
}
}
}
- hir::InlineAsmOperand::SymFn { ref anon_const } => {
- let ty = cx
- .tcx()
- .typeck_body(anon_const.body)
- .node_type(anon_const.hir_id);
+ hir::InlineAsmOperand::SymFn { expr } => {
+ let ty = cx.tcx().typeck(item_id.owner_id).expr_ty(expr);
let instance = match ty.kind() {
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
_ => span_bug!(*op_sp, "asm sym is not a function"),
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 2c843e2f5e460..99fd6b6510ffe 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -1,7 +1,7 @@
use std::assert_matches::assert_matches;
use std::ops::Deref;
-use rustc_abi::{Align, BackendRepr, Scalar, Size, WrappingRange};
+use rustc_abi::{Align, Scalar, Size, WrappingRange};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
use rustc_middle::ty::{Instance, Ty};
@@ -110,6 +110,20 @@ pub trait BuilderMethods<'a, 'tcx>:
else_llbb: Self::BasicBlock,
cases: impl ExactSizeIterator
- ,
);
+
+ // This is like `switch()`, but every case has a bool flag indicating whether it's cold.
+ //
+ // Default implementation throws away the cold flags and calls `switch()`.
+ fn switch_with_weights(
+ &mut self,
+ v: Self::Value,
+ else_llbb: Self::BasicBlock,
+ _else_is_cold: bool,
+ cases: impl ExactSizeIterator
- ,
+ ) {
+ self.switch(v, else_llbb, cases.map(|(val, bb, _)| (val, bb)))
+ }
+
fn invoke(
&mut self,
llty: Self::Type,
@@ -209,13 +223,6 @@ pub trait BuilderMethods<'a, 'tcx>:
) -> (Self::Value, Self::Value);
fn from_immediate(&mut self, val: Self::Value) -> Self::Value;
- fn to_immediate(&mut self, val: Self::Value, layout: TyAndLayout<'_>) -> Self::Value {
- if let BackendRepr::Scalar(scalar) = layout.backend_repr {
- self.to_immediate_scalar(val, scalar)
- } else {
- val
- }
- }
fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
fn alloca(&mut self, size: Size, align: Align) -> Self::Value;
@@ -318,6 +325,14 @@ pub trait BuilderMethods<'a, 'tcx>:
ptr: Self::Value,
indices: &[Self::Value],
) -> Self::Value;
+ fn inbounds_nuw_gep(
+ &mut self,
+ ty: Self::Type,
+ ptr: Self::Value,
+ indices: &[Self::Value],
+ ) -> Self::Value {
+ self.inbounds_gep(ty, ptr, indices)
+ }
fn ptradd(&mut self, ptr: Self::Value, offset: Self::Value) -> Self::Value {
self.gep(self.cx().type_i8(), ptr, &[offset])
}
@@ -326,6 +341,17 @@ pub trait BuilderMethods<'a, 'tcx>:
}
fn trunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
+ /// Produces the same value as [`Self::trunc`] (and defaults to that),
+ /// but is UB unless the *zero*-extending the result can reproduce `val`.
+ fn unchecked_utrunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
+ self.trunc(val, dest_ty)
+ }
+ /// Produces the same value as [`Self::trunc`] (and defaults to that),
+ /// but is UB unless the *sign*-extending the result can reproduce `val`.
+ fn unchecked_strunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
+ self.trunc(val, dest_ty)
+ }
+
fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml
index 7717cd2c69664..a0cc2c65e6e03 100644
--- a/compiler/rustc_const_eval/Cargo.toml
+++ b/compiler/rustc_const_eval/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_const_eval"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs
index bfa0a0319c344..52e000858b4c7 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_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 82e0a6e6666f3..4db862afd9f6d 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -502,12 +502,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
RemainderByZero(op) => RemainderByZero(eval_to_int(op)?),
ResumedAfterReturn(coroutine_kind) => ResumedAfterReturn(*coroutine_kind),
ResumedAfterPanic(coroutine_kind) => ResumedAfterPanic(*coroutine_kind),
- MisalignedPointerDereference { ref required, ref found } => {
- MisalignedPointerDereference {
- required: eval_to_int(required)?,
- found: eval_to_int(found)?,
- }
- }
+ MisalignedPointerDereference { required, found } => MisalignedPointerDereference {
+ required: eval_to_int(required)?,
+ found: eval_to_int(found)?,
+ },
NullPointerDereference => NullPointerDereference,
};
Err(ConstEvalErrKind::AssertFailure(err)).into()
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index b53c1505f6b18..7b706334ed85e 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -430,10 +430,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
};
let erased_trait_ref =
ty::ExistentialTraitRef::erase_self_ty(*self.tcx, upcast_trait_ref);
- assert!(data_b.principal().is_some_and(|b| self.eq_in_param_env(
- erased_trait_ref,
- self.tcx.instantiate_bound_regions_with_erased(b)
- )));
+ assert_eq!(
+ data_b.principal().map(|b| {
+ self.tcx.normalize_erasing_late_bound_regions(self.typing_env, b)
+ }),
+ Some(erased_trait_ref),
+ );
} else {
// In this case codegen would keep using the old vtable. We don't want to do
// that as it has the wrong trait. The reason codegen can do this is that
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 66a75113652f1..c1948e9f31f10 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -4,9 +4,6 @@ use either::{Left, Right};
use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout};
use rustc_errors::DiagCtxtHandle;
use rustc_hir::def_id::DefId;
-use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::infer::at::ToTrace;
-use rustc_infer::traits::ObligationCause;
use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{
@@ -17,8 +14,7 @@ use rustc_middle::{mir, span_bug};
use rustc_session::Limit;
use rustc_span::Span;
use rustc_target::callconv::FnAbi;
-use rustc_trait_selection::traits::ObligationCtxt;
-use tracing::{debug, instrument, trace};
+use tracing::{debug, trace};
use super::{
Frame, FrameInfo, GlobalId, InterpErrorInfo, InterpErrorKind, InterpResult, MPlaceTy, Machine,
@@ -320,40 +316,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
}
- /// Check if the two things are equal in the current param_env, using an infcx to get proper
- /// equality checks.
- #[instrument(level = "trace", skip(self), ret)]
- pub(super) fn eq_in_param_env(&self, a: T, b: T) -> bool
- where
- T: PartialEq + TypeFoldable> + ToTrace<'tcx>,
- {
- // Fast path: compare directly.
- if a == b {
- return true;
- }
- // Slow path: spin up an inference context to check if these traits are sufficiently equal.
- let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
- let ocx = ObligationCtxt::new(&infcx);
- let cause = ObligationCause::dummy_with_span(self.cur_span());
- // equate the two trait refs after normalization
- let a = ocx.normalize(&cause, param_env, a);
- let b = ocx.normalize(&cause, param_env, b);
-
- if let Err(terr) = ocx.eq(&cause, param_env, a, b) {
- trace!(?terr);
- return false;
- }
-
- let errors = ocx.select_all_or_error();
- if !errors.is_empty() {
- trace!(?errors);
- return false;
- }
-
- // All good.
- true
- }
-
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
/// frame which is not `#[track_caller]`. This matches the `caller_location` intrinsic,
/// and is primarily intended for the panic machinery.
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index e14cc1dad3634..43631330f89bf 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -61,8 +61,8 @@ impl HasStaticRootDefId for const_eval::CompileTimeMachine<'_> {
/// already mutable (as a sanity check).
///
/// Returns an iterator over all relocations referred to by this allocation.
-fn intern_shallow<'rt, 'tcx, T, M: CompileTimeMachine<'tcx, T>>(
- ecx: &'rt mut InterpCx<'tcx, M>,
+fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
+ ecx: &mut InterpCx<'tcx, M>,
alloc_id: AllocId,
mutability: Mutability,
) -> Result + 'tcx, ()> {
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 5d905cff1f216..36da9037e43d9 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -385,7 +385,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
(Immediate::Uninit, _) => Immediate::Uninit,
// If the field is uninhabited, we can forget the data (can happen in ConstProp).
// `enum S { A(!), B, C }` is an example of an enum with Scalar layout that
- // has an `Uninhabited` variant, which means this case is possible.
+ // has an uninhabited variant, which means this case is possible.
_ if layout.is_uninhabited() => Immediate::Uninit,
// the field contains no information, can be left uninit
// (Scalar/ScalarPair can contain even aligned ZST, not just 1-ZST)
diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs
index 4cfaacebfcd0e..a5029eea5a796 100644
--- a/compiler/rustc_const_eval/src/interpret/traits.rs
+++ b/compiler/rustc_const_eval/src/interpret/traits.rs
@@ -86,21 +86,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
throw_ub!(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type });
}
+ // This checks whether there is a subtyping relation between the predicates in either direction.
+ // For example:
+ // - casting between `dyn for<'a> Trait` and `dyn Trait` is OK
+ // - casting between `dyn Trait fn(&'a u8)>` and either of the above is UB
for (a_pred, b_pred) in std::iter::zip(sorted_vtable, sorted_expected) {
- let is_eq = match (a_pred.skip_binder(), b_pred.skip_binder()) {
- (
- ty::ExistentialPredicate::Trait(a_data),
- ty::ExistentialPredicate::Trait(b_data),
- ) => self.eq_in_param_env(a_pred.rebind(a_data), b_pred.rebind(b_data)),
+ let a_pred = self.tcx.normalize_erasing_late_bound_regions(self.typing_env, a_pred);
+ let b_pred = self.tcx.normalize_erasing_late_bound_regions(self.typing_env, b_pred);
- (
- ty::ExistentialPredicate::Projection(a_data),
- ty::ExistentialPredicate::Projection(b_data),
- ) => self.eq_in_param_env(a_pred.rebind(a_data), b_pred.rebind(b_data)),
-
- _ => false,
- };
- if !is_eq {
+ if a_pred != b_pred {
throw_ub!(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type });
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 0ac34f4633b57..40dec0cb39e7b 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -1264,21 +1264,20 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
}
}
- // *After* all of this, check the ABI. We need to check the ABI to handle
- // types like `NonNull` where the `Scalar` info is more restrictive than what
- // the fields say (`rustc_layout_scalar_valid_range_start`).
- // But in most cases, this will just propagate what the fields say,
- // and then we want the error to point at the field -- so, first recurse,
- // then check ABI.
+ // *After* all of this, check further information stored in the layout. We need to check
+ // this to handle types like `NonNull` where the `Scalar` info is more restrictive than what
+ // the fields say (`rustc_layout_scalar_valid_range_start`). But in most cases, this will
+ // just propagate what the fields say, and then we want the error to point at the field --
+ // so, we first recurse, then we do this check.
//
// FIXME: We could avoid some redundant checks here. For newtypes wrapping
// scalars, we do the same check on every "level" (e.g., first we check
// MyNewtype and then the scalar in there).
+ if val.layout.is_uninhabited() {
+ let ty = val.layout.ty;
+ throw_validation_failure!(self.path, UninhabitedVal { ty });
+ }
match val.layout.backend_repr {
- BackendRepr::Uninhabited => {
- let ty = val.layout.ty;
- throw_validation_failure!(self.path, UninhabitedVal { ty });
- }
BackendRepr::Scalar(scalar_layout) => {
if !scalar_layout.is_uninit_valid() {
// There is something to check here.
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index 79baf91c3ce64..6426bca2332d4 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -111,13 +111,15 @@ fn check_validity_requirement_lax<'tcx>(
};
// Check the ABI.
- let valid = match this.backend_repr {
- BackendRepr::Uninhabited => false, // definitely UB
- BackendRepr::Scalar(s) => scalar_allows_raw_init(s),
- BackendRepr::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
- BackendRepr::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
- BackendRepr::Memory { .. } => true, // Fields are checked below.
- };
+ let valid = !this.is_uninhabited() // definitely UB if uninhabited
+ && match this.backend_repr {
+ BackendRepr::Scalar(s) => scalar_allows_raw_init(s),
+ BackendRepr::ScalarPair(s1, s2) => {
+ scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2)
+ }
+ BackendRepr::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
+ BackendRepr::Memory { .. } => true, // Fields are checked below.
+ };
if !valid {
// This is definitely not okay.
return Ok(false);
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index a8f83ca13e267..bdf5494f2107b 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_data_structures"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
@@ -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 16c66824c5ba1..c7c0d0ab0725d 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/flock.rs b/compiler/rustc_data_structures/src/flock.rs
index 292a33d56469a..d423d8acefd0a 100644
--- a/compiler/rustc_data_structures/src/flock.rs
+++ b/compiler/rustc_data_structures/src/flock.rs
@@ -4,31 +4,6 @@
//! green/native threading. This is just a bare-bones enough solution for
//! librustdoc, it is not production quality at all.
-#[cfg(bootstrap)]
-cfg_match! {
- cfg(target_os = "linux") => {
- mod linux;
- use linux as imp;
- }
- cfg(target_os = "redox") => {
- mod linux;
- use linux as imp;
- }
- cfg(unix) => {
- mod unix;
- use unix as imp;
- }
- cfg(windows) => {
- mod windows;
- use self::windows as imp;
- }
- _ => {
- mod unsupported;
- use unsupported as imp;
- }
-}
-
-#[cfg(not(bootstrap))]
cfg_match! {
target_os = "linux" => {
mod linux;
diff --git a/compiler/rustc_data_structures/src/graph/implementation/mod.rs b/compiler/rustc_data_structures/src/graph/implementation/mod.rs
index 7724e9347d822..a80365938b96c 100644
--- a/compiler/rustc_data_structures/src/graph/implementation/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/implementation/mod.rs
@@ -193,11 +193,11 @@ impl Graph {
AdjacentEdges { graph: self, direction, next: first_edge }
}
- pub fn successor_nodes(&self, source: NodeIndex) -> impl Iterator
- + '_ {
+ pub fn successor_nodes(&self, source: NodeIndex) -> impl Iterator
- {
self.outgoing_edges(source).targets()
}
- pub fn predecessor_nodes(&self, target: NodeIndex) -> impl Iterator
- + '_ {
+ pub fn predecessor_nodes(&self, target: NodeIndex) -> impl Iterator
- {
self.incoming_edges(target).sources()
}
@@ -255,11 +255,11 @@ pub struct AdjacentEdges<'g, N, E> {
}
impl<'g, N: Debug, E: Debug> AdjacentEdges<'g, N, E> {
- fn targets(self) -> impl Iterator
- + 'g {
+ fn targets(self) -> impl Iterator
- {
self.map(|(_, edge)| edge.target)
}
- fn sources(self) -> impl Iterator
- + 'g {
+ fn sources(self) -> impl Iterator
- {
self.map(|(_, edge)| edge.source)
}
}
diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs
index 93f6192b10b03..e7c4ea3daae45 100644
--- a/compiler/rustc_data_structures/src/graph/scc/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs
@@ -133,7 +133,7 @@ impl Sccs {
/// meaning that if `S1 -> S2`, we will visit `S2` first and `S1` after.
/// This is convenient when the edges represent dependencies: when you visit
/// `S1`, the value for `S2` will already have been computed.
- pub fn all_sccs(&self) -> impl Iterator
- {
+ pub fn all_sccs(&self) -> impl Iterator
- + 'static {
(0..self.scc_data.len()).map(S::new)
}
diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs
index 850b052f564b7..8079212fac551 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 6ef73debadd50..66d3834d85784 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/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 18e98e6c39fa9..39db551adfb84 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -860,69 +860,6 @@ fn get_thread_id() -> u32 {
}
// Memory reporting
-#[cfg(bootstrap)]
-cfg_match! {
- cfg(windows) => {
- pub fn get_resident_set_size() -> Option {
- use std::mem;
-
- use windows::{
- Win32::System::ProcessStatus::{K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS},
- Win32::System::Threading::GetCurrentProcess,
- };
-
- let mut pmc = PROCESS_MEMORY_COUNTERS::default();
- let pmc_size = mem::size_of_val(&pmc);
- unsafe {
- K32GetProcessMemoryInfo(
- GetCurrentProcess(),
- &mut pmc,
- pmc_size as u32,
- )
- }
- .ok()
- .ok()?;
-
- Some(pmc.WorkingSetSize)
- }
- }
- cfg(target_os = "macos") => {
- pub fn get_resident_set_size() -> Option {
- use libc::{c_int, c_void, getpid, proc_pidinfo, proc_taskinfo, PROC_PIDTASKINFO};
- use std::mem;
- const PROC_TASKINFO_SIZE: c_int = mem::size_of::() as c_int;
-
- unsafe {
- let mut info: proc_taskinfo = mem::zeroed();
- let info_ptr = &mut info as *mut proc_taskinfo as *mut c_void;
- let pid = getpid() as c_int;
- let ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, info_ptr, PROC_TASKINFO_SIZE);
- if ret == PROC_TASKINFO_SIZE {
- Some(info.pti_resident_size as usize)
- } else {
- None
- }
- }
- }
- }
- cfg(unix) => {
- pub fn get_resident_set_size() -> Option {
- let field = 1;
- let contents = fs::read("/proc/self/statm").ok()?;
- let contents = String::from_utf8(contents).ok()?;
- let s = contents.split_whitespace().nth(field)?;
- let npages = s.parse::().ok()?;
- Some(npages * 4096)
- }
- }
- _ => {
- pub fn get_resident_set_size() -> Option {
- None
- }
- }
-}
-
-#[cfg(not(bootstrap))]
cfg_match! {
windows => {
pub fn get_resident_set_size() -> Option {
diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
index e9a5fb5197548..1654867739f0d 100644
--- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
@@ -84,7 +84,7 @@ impl SortedIndexMultiMap {
/// If there are multiple items that are equivalent to `key`, they will be yielded in
/// insertion order.
#[inline]
- pub fn get_by_key(&self, key: K) -> impl Iterator
- + '_ {
+ pub fn get_by_key(&self, key: K) -> impl Iterator
- {
self.get_by_key_enumerated(key).map(|(_, v)| v)
}
@@ -94,7 +94,7 @@ impl SortedIndexMultiMap {
/// If there are multiple items that are equivalent to `key`, they will be yielded in
/// insertion order.
#[inline]
- pub fn get_by_key_enumerated(&self, key: K) -> impl Iterator
- + '_ {
+ pub fn get_by_key_enumerated(&self, key: K) -> impl Iterator
- {
let lower_bound = self.idx_sorted_by_item_key.partition_point(|&i| self.items[i].0 < key);
self.idx_sorted_by_item_key[lower_bound..].iter().map_while(move |&i| {
let (k, v) = &self.items[i];
diff --git a/compiler/rustc_data_structures/src/sorted_map/tests.rs b/compiler/rustc_data_structures/src/sorted_map/tests.rs
index def7a7112fb3f..ea4d2f1feacc0 100644
--- a/compiler/rustc_data_structures/src/sorted_map/tests.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/tests.rs
@@ -24,7 +24,7 @@ fn test_sorted_index_multi_map() {
// `get_by_key` returns items in insertion order.
let twos: Vec<_> = set.get_by_key_enumerated(2).collect();
let idxs: Vec = twos.iter().map(|(i, _)| *i).collect();
- let values: Vec = twos.iter().map(|(_, &v)| v).collect();
+ let values: Vec = twos.iter().map(|&(_, &v)| v).collect();
assert_eq!(idxs, vec![0, 2, 4]);
assert_eq!(values, vec![0, 1, 2]);
diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs
index 3200249a2dc4c..827c82fa46a11 100644
--- a/compiler/rustc_data_structures/src/sso/map.rs
+++ b/compiler/rustc_data_structures/src/sso/map.rs
@@ -165,7 +165,7 @@ impl SsoHashMap {
/// Clears the map, returning all key-value pairs as an iterator. Keeps the
/// allocated memory for reuse.
- pub fn drain(&mut self) -> impl Iterator
- + '_ {
+ pub fn drain(&mut self) -> impl Iterator
- {
match self {
SsoHashMap::Array(array) => Either::Left(array.drain(..)),
SsoHashMap::Map(map) => Either::Right(map.drain()),
diff --git a/compiler/rustc_data_structures/src/sso/set.rs b/compiler/rustc_data_structures/src/sso/set.rs
index a4b40138933de..e3fa1cbf4cc57 100644
--- a/compiler/rustc_data_structures/src/sso/set.rs
+++ b/compiler/rustc_data_structures/src/sso/set.rs
@@ -80,7 +80,7 @@ impl SsoHashSet {
/// Clears the set, returning all elements in an iterator.
#[inline]
- pub fn drain(&mut self) -> impl Iterator
- + '_ {
+ pub fn drain(&mut self) -> impl Iterator
- {
self.map.drain().map(entry_to_key)
}
}
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index 9cd0cc499ca32..ffbe54d620612 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/stack.rs b/compiler/rustc_data_structures/src/stack.rs
index 102b364091154..3d6d000348324 100644
--- a/compiler/rustc_data_structures/src/stack.rs
+++ b/compiler/rustc_data_structures/src/stack.rs
@@ -17,18 +17,6 @@ const STACK_PER_RECURSION: usize = 16 * 1024 * 1024; // 16MB
///
/// Should not be sprinkled around carelessly, as it causes a little bit of overhead.
#[inline]
-#[cfg(not(miri))]
pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R {
stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f)
}
-
-/// Grows the stack on demand to prevent stack overflow. Call this in strategic locations
-/// to "break up" recursive calls. E.g. almost any call to `visit_expr` or equivalent can benefit
-/// from this.
-///
-/// Should not be sprinkled around carelessly, as it causes a little bit of overhead.
-#[cfg(miri)]
-#[inline]
-pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R {
- f()
-}
diff --git a/compiler/rustc_data_structures/src/sync/vec.rs b/compiler/rustc_data_structures/src/sync/vec.rs
index 21ec5cf6c13bf..afbb0cef9f956 100644
--- a/compiler/rustc_data_structures/src/sync/vec.rs
+++ b/compiler/rustc_data_structures/src/sync/vec.rs
@@ -45,14 +45,14 @@ impl AppendOnlyVec {
self.vec.read().get(i).copied()
}
- pub fn iter_enumerated(&self) -> impl Iterator
- + '_ {
+ pub fn iter_enumerated(&self) -> impl Iterator
- {
(0..)
.map(|i| (i, self.get(i)))
.take_while(|(_, o)| o.is_some())
.filter_map(|(i, o)| Some((i, o?)))
}
- pub fn iter(&self) -> impl Iterator
- + '_ {
+ pub fn iter(&self) -> impl Iterator
- {
(0..).map(|i| self.get(i)).take_while(|o| o.is_some()).flatten()
}
}
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/tests.rs
index b1bdee18d6d43..9c1e4cefa6923 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_data_structures/src/transitive_relation.rs b/compiler/rustc_data_structures/src/transitive_relation.rs
index e81ebb9a4be22..33ac279f3e0ae 100644
--- a/compiler/rustc_data_structures/src/transitive_relation.rs
+++ b/compiler/rustc_data_structures/src/transitive_relation.rs
@@ -363,7 +363,7 @@ impl TransitiveRelation {
/// Lists all the base edges in the graph: the initial _non-transitive_ set of element
/// relations, which will be later used as the basis for the transitive closure computation.
- pub fn base_edges(&self) -> impl Iterator
- + '_ {
+ pub fn base_edges(&self) -> impl Iterator
- {
self.edges
.iter()
.map(move |edge| (self.elements[edge.source.0], self.elements[edge.target.0]))
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index ae9712ad66d83..e3ee83512952a 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_driver"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[lib]
crate-type = ["dylib"]
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index 0b45e5786e83d..8593d1faba264 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_driver_impl"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 093ee659bb42a..828a14e707c50 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()))
});
@@ -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 08b7d937661fb..e7bc57c9749b5 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/Cargo.toml b/compiler/rustc_error_codes/Cargo.toml
index de668b81b7e07..55b4e89905126 100644
--- a/compiler/rustc_error_codes/Cargo.toml
+++ b/compiler/rustc_error_codes/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_error_codes"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
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 0000000000000..4c022688a2ded
--- /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 e970b16f61064..098ca42be2b44 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_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml
index 6974c12f994b1..578af7fc51d40 100644
--- a/compiler/rustc_error_messages/Cargo.toml
+++ b/compiler/rustc_error_messages/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_error_messages"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index fbb6a1cc47559..c1d8cd9bb9ed2 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_errors"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
@@ -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/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 634afacf53900..f7f842393084b 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -2216,12 +2216,7 @@ impl HumanEmitter {
if let DisplaySuggestion::Diff | DisplaySuggestion::Underline | DisplaySuggestion::Add =
show_code_change
{
- for mut part in parts {
- // If this is a replacement of, e.g. `"a"` into `"ab"`, adjust the
- // suggestion and snippet to look as if we just suggested to add
- // `"b"`, which is typically much easier for the user to understand.
- part.trim_trivial_replacements(sm);
-
+ for part in parts {
let snippet = if let Ok(snippet) = sm.span_to_snippet(part.span) {
snippet
} else {
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 8ff5dc1259697..ceed0cd94fc91 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -58,19 +58,20 @@ 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};
pub use rustc_span::ErrorGuaranteed;
pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
use rustc_span::source_map::SourceMap;
-use rustc_span::{DUMMY_SP, Loc, Span};
+use rustc_span::{BytePos, DUMMY_SP, Loc, Span};
pub use snippet::Style;
// Used by external projects such as `rust-gpu`.
// See https://github.com/rust-lang/rust/pull/115393.
@@ -236,10 +237,9 @@ impl SubstitutionPart {
/// it with "abx" is, since the "c" character is lost.
pub fn is_destructive_replacement(&self, sm: &SourceMap) -> bool {
self.is_replacement(sm)
- && !sm.span_to_snippet(self.span).is_ok_and(|snippet| {
- self.snippet.trim_start().starts_with(snippet.trim_start())
- || self.snippet.trim_end().ends_with(snippet.trim_end())
- })
+ && !sm
+ .span_to_snippet(self.span)
+ .is_ok_and(|snippet| as_substr(snippet.trim(), self.snippet.trim()).is_some())
}
fn replaces_meaningful_content(&self, sm: &SourceMap) -> bool {
@@ -256,16 +256,40 @@ impl SubstitutionPart {
let Ok(snippet) = sm.span_to_snippet(self.span) else {
return;
};
- if self.snippet.starts_with(&snippet) {
- self.span = self.span.shrink_to_hi();
- self.snippet = self.snippet[snippet.len()..].to_string();
- } else if self.snippet.ends_with(&snippet) {
- self.span = self.span.shrink_to_lo();
- self.snippet = self.snippet[..self.snippet.len() - snippet.len()].to_string();
+
+ if let Some((prefix, substr, suffix)) = as_substr(&snippet, &self.snippet) {
+ self.span = Span::new(
+ self.span.lo() + BytePos(prefix as u32),
+ self.span.hi() - BytePos(suffix as u32),
+ self.span.ctxt(),
+ self.span.parent(),
+ );
+ self.snippet = substr.to_string();
}
}
}
+/// Given an original string like `AACC`, and a suggestion like `AABBCC`, try to detect
+/// the case where a substring of the suggestion is "sandwiched" in the original, like
+/// `BB` is. Return the length of the prefix, the "trimmed" suggestion, and the length
+/// of the suffix.
+fn as_substr<'a>(original: &'a str, suggestion: &'a str) -> Option<(usize, &'a str, usize)> {
+ let common_prefix = original
+ .chars()
+ .zip(suggestion.chars())
+ .take_while(|(c1, c2)| c1 == c2)
+ .map(|(c, _)| c.len_utf8())
+ .sum();
+ let original = &original[common_prefix..];
+ let suggestion = &suggestion[common_prefix..];
+ if suggestion.ends_with(original) {
+ let common_suffix = original.len();
+ Some((common_prefix, &suggestion[..suggestion.len() - original.len()], common_suffix))
+ } else {
+ None
+ }
+}
+
impl CodeSuggestion {
/// Returns the assembled code suggestions, whether they should be shown with an underline
/// and whether the substitution only differs in capitalization.
@@ -379,7 +403,12 @@ impl CodeSuggestion {
// or deleted code in order to point at the correct column *after* substitution.
let mut acc = 0;
let mut only_capitalization = false;
- for part in &substitution.parts {
+ for part in &mut substitution.parts {
+ // If this is a replacement of, e.g. `"a"` into `"ab"`, adjust the
+ // suggestion and snippet to look as if we just suggested to add
+ // `"b"`, which is typically much easier for the user to understand.
+ part.trim_trivial_replacements(sm);
+
only_capitalization |= is_case_difference(sm, &part.snippet, part.span);
let cur_lo = sm.lookup_char_pos(part.span.lo());
if prev_hi.line == cur_lo.line {
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index eb93972387d40..33bada106ca79 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_expand"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
build = false
[lib]
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 595c8c3279f41..7fe9fa7937d9f 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;
@@ -255,7 +258,7 @@ pub(super) fn transcribe<'a>(
}
// Replace the meta-var with the matched token tree from the invocation.
- mbe::TokenTree::MetaVar(mut sp, mut original_ident) => {
+ &mbe::TokenTree::MetaVar(mut sp, mut original_ident) => {
// Find the matched nonterminal from the macro invocation, and use it to replace
// the meta-var.
//
@@ -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.
@@ -339,7 +376,7 @@ pub(super) fn transcribe<'a>(
// We will produce all of the results of the inside of the `Delimited` and then we will
// jump back out of the Delimited, pop the result_stack and add the new results back to
// the previous results (from outside the Delimited).
- mbe::TokenTree::Delimited(mut span, spacing, delimited) => {
+ &mbe::TokenTree::Delimited(mut span, ref spacing, ref delimited) => {
mut_visit::visit_delim_span(&mut marker, &mut span);
stack.push(Frame::new_delimited(delimited, span, *spacing));
result_stack.push(mem::take(&mut result));
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index dca0516f9f3b3..a6cdeaee176f1 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -31,7 +31,7 @@ impl pm::bridge::server::MessagePipe for MessagePipe {
}
}
-fn exec_strategy(ecx: &ExtCtxt<'_>) -> impl pm::bridge::server::ExecutionStrategy {
+fn exec_strategy(ecx: &ExtCtxt<'_>) -> impl pm::bridge::server::ExecutionStrategy + 'static {
pm::bridge::server::MaybeCrossThread::>::new(
ecx.sess.opts.unstable_opts.proc_macro_execution_strategy
== ProcMacroExecutionStrategy::CrossThread,
diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml
index 77de7fabd4f92..a5ae06473cbe3 100644
--- a/compiler/rustc_feature/Cargo.toml
+++ b/compiler/rustc_feature/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_feature"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 2dfb0c8e04093..d50fe8c6a3e6b 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -387,7 +387,7 @@ declare_features! (
/// Allows `#[target_feature(...)]`.
(accepted, target_feature, "1.27.0", None),
/// Allows the use of `#[target_feature]` on safe functions.
- (accepted, target_feature_11, "CURRENT_RUSTC_VERSION", Some(69098)),
+ (accepted, target_feature_11, "1.86.0", Some(69098)),
/// Allows `fn main()` with return types which implements `Termination` (RFC 1937).
(accepted, termination_trait, "1.26.0", Some(43301)),
/// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937).
@@ -401,7 +401,7 @@ declare_features! (
(accepted, track_caller, "1.46.0", Some(47809)),
/// Allows dyn upcasting trait objects via supertraits.
/// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
- (accepted, trait_upcasting, "CURRENT_RUSTC_VERSION", Some(65991)),
+ (accepted, trait_upcasting, "1.86.0", Some(65991)),
/// Allows #[repr(transparent)] on univariant enums (RFC 2645).
(accepted, transparent_enums, "1.42.0", Some(60405)),
/// Allows indexing tuples.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 8eb9bf1582902..b2ada8fe61ef0 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -743,7 +743,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_attr!(
rustc_autodiff, Normal,
template!(Word, List: r#""...""#), DuplicatesOk,
- EncodeCrossCrate::No, INTERNAL_UNSTABLE
+ EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
),
// ==========================================================================
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 2fb0c8e43448a..60e7788f2c05d 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -135,6 +135,8 @@ declare_features! (
Some("removed as it caused some confusion and discussion was inactive for years")),
/// Lazily evaluate constants. This allows constants to depend on type parameters.
(removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")),
+ /// Changes `impl Trait` to capture all lifetimes in scope.
+ (removed, lifetime_capture_rules_2024, "1.76.0", None, Some("unnecessary -- use edition 2024 instead")),
/// Allows using the `#[link_args]` attribute.
(removed, link_args, "1.53.0", Some(29596),
Some("removed in favor of using `-C link-arg=ARG` on command line, \
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index e852f239aa27c..fe643e9a7d1d8 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -203,7 +203,7 @@ declare_features! (
/// Allows using anonymous lifetimes in argument-position impl-trait.
(unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None),
/// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind
- (internal, cfg_emscripten_wasm_eh, "CURRENT_RUSTC_VERSION", None),
+ (internal, cfg_emscripten_wasm_eh, "1.86.0", None),
/// Allows identifying the `compiler_builtins` crate.
(internal, compiler_builtins, "1.13.0", None),
/// Allows writing custom MIR
@@ -214,8 +214,6 @@ declare_features! (
(internal, intrinsics, "1.0.0", None),
/// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
(internal, lang_items, "1.0.0", None),
- /// Changes `impl Trait` to capture all lifetimes in scope.
- (unstable, lifetime_capture_rules_2024, "1.76.0", None),
/// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
(internal, link_cfg, "1.14.0", None),
/// Allows using `?Trait` trait bounds in more contexts.
@@ -360,7 +358,7 @@ declare_features! (
/// Allows `extern "C-cmse-nonsecure-call" fn()`.
(unstable, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391)),
/// Allows `extern "gpu-kernel" fn()`.
- (unstable, abi_gpu_kernel, "CURRENT_RUSTC_VERSION", Some(135467)),
+ (unstable, abi_gpu_kernel, "1.86.0", Some(135467)),
/// Allows `extern "msp430-interrupt" fn()`.
(unstable, abi_msp430_interrupt, "1.16.0", Some(38487)),
/// Allows `extern "ptx-*" fn()`.
@@ -404,7 +402,7 @@ declare_features! (
/// Allows the use of `#[cfg()]`.
(unstable, cfg_boolean_literals, "1.83.0", Some(131204)),
/// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled.
- (unstable, cfg_contract_checks, "CURRENT_RUSTC_VERSION", Some(128044)),
+ (unstable, cfg_contract_checks, "1.86.0", Some(128044)),
/// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
(unstable, cfg_overflow_checks, "1.71.0", Some(111466)),
/// Provides the relocation model information as cfg entry
@@ -448,9 +446,9 @@ declare_features! (
/// Allows the `?` operator in const contexts.
(unstable, const_try, "1.56.0", Some(74935)),
/// Allows use of contracts attributes.
- (incomplete, contracts, "CURRENT_RUSTC_VERSION", Some(128044)),
+ (incomplete, contracts, "1.86.0", Some(128044)),
/// Allows access to internal machinery used to implement contracts.
- (internal, contracts_internals, "CURRENT_RUSTC_VERSION", Some(128044)),
+ (internal, contracts_internals, "1.86.0", Some(128044)),
/// Allows coroutines to be cloned.
(unstable, coroutine_clone, "1.65.0", Some(95360)),
/// Allows defining coroutines.
@@ -491,7 +489,7 @@ declare_features! (
/// for functions with varargs.
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
/// Allows using `system` as a calling convention with varargs.
- (unstable, extern_system_varargs, "CURRENT_RUSTC_VERSION", Some(136946)),
+ (unstable, extern_system_varargs, "1.86.0", Some(136946)),
/// Allows defining `extern type`s.
(unstable, extern_types, "1.23.0", Some(43467)),
/// Allow using 128-bit (quad precision) floating point numbers.
@@ -519,7 +517,7 @@ declare_features! (
/// Allows generic parameters and where-clauses on free & associated const items.
(incomplete, generic_const_items, "1.73.0", Some(113521)),
/// Allows any generic constants being used as pattern type range ends
- (incomplete, generic_pattern_types, "CURRENT_RUSTC_VERSION", Some(136574)),
+ (incomplete, generic_pattern_types, "1.86.0", Some(136574)),
/// Allows registering static items globally, possibly across crates, to iterate over at runtime.
(unstable, global_registration, "1.80.0", Some(125119)),
/// Allows using guards in patterns.
@@ -535,7 +533,7 @@ declare_features! (
/// Allows `impl Trait` as output type in `Fn` traits in return position of functions.
(unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697)),
/// Allows `use` associated functions from traits.
- (unstable, import_trait_associated_functions, "CURRENT_RUSTC_VERSION", Some(134691)),
+ (unstable, import_trait_associated_functions, "1.86.0", Some(134691)),
/// Allows associated types in inherent impls.
(incomplete, inherent_associated_types, "1.52.0", Some(8995)),
/// Allow anonymous constants from an inline `const` block in pattern position
@@ -543,7 +541,7 @@ declare_features! (
/// Allows using `pointer` and `reference` in intra-doc links
(unstable, intra_doc_pointers, "1.51.0", Some(80896)),
// Allows using the `kl` and `widekl` target features and the associated intrinsics
- (unstable, keylocker_x86, "CURRENT_RUSTC_VERSION", Some(134813)),
+ (unstable, keylocker_x86, "1.86.0", Some(134813)),
// Allows setting the threshold for the `large_assignments` lint.
(unstable, large_assignments, "1.52.0", Some(83518)),
/// Allow to have type alias types for inter-crate use.
@@ -584,7 +582,7 @@ declare_features! (
/// Allows diverging expressions to fall back to `!` rather than `()`.
(unstable, never_type_fallback, "1.41.0", Some(65992)),
/// Switch `..` syntax to use the new (`Copy + IntoIterator`) range types.
- (unstable, new_range, "CURRENT_RUSTC_VERSION", Some(123741)),
+ (unstable, new_range, "1.86.0", Some(123741)),
/// Allows `#![no_core]`.
(unstable, no_core, "1.3.0", Some(29639)),
/// Allows the use of `no_sanitize` attribute.
@@ -636,7 +634,7 @@ declare_features! (
/// Allows string patterns to dereference values to match them.
(unstable, string_deref_patterns, "1.67.0", Some(87121)),
/// Allows subtrait items to shadow supertrait items.
- (unstable, supertrait_item_shadowing, "CURRENT_RUSTC_VERSION", Some(89151)),
+ (unstable, supertrait_item_shadowing, "1.86.0", Some(89151)),
/// Allows using `#[thread_local]` on `static` items.
(unstable, thread_local, "1.0.0", Some(29594)),
/// Allows defining `trait X = A + B;` alias items.
diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml
index eeceaa4691a2a..ce76b2745eaad 100644
--- a/compiler/rustc_fluent_macro/Cargo.toml
+++ b/compiler/rustc_fluent_macro/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_fluent_macro"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[lib]
proc-macro = true
diff --git a/compiler/rustc_fs_util/Cargo.toml b/compiler/rustc_fs_util/Cargo.toml
index 4b76200c06c53..baca3bc7d49eb 100644
--- a/compiler/rustc_fs_util/Cargo.toml
+++ b/compiler/rustc_fs_util/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_fs_util"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_graphviz/Cargo.toml b/compiler/rustc_graphviz/Cargo.toml
index 780004ae3fbc8..d84943760baeb 100644
--- a/compiler/rustc_graphviz/Cargo.toml
+++ b/compiler/rustc_graphviz/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_graphviz"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
diff --git a/compiler/rustc_hashes/Cargo.toml b/compiler/rustc_hashes/Cargo.toml
new file mode 100644
index 0000000000000..c7a273cff88c9
--- /dev/null
+++ b/compiler/rustc_hashes/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "rustc_hashes"
+version = "0.0.0"
+edition = "2024"
+
+[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 8f4639fc2e666..3755caaaa2963 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,26 +36,17 @@ impl Hash64 {
pub fn as_u64(self) -> u64 {
self.inner
}
-}
-impl BitXorAssign for Hash64 {
#[inline]
- fn bitxor_assign(&mut self, rhs: u64) {
- self.inner ^= rhs;
- }
-}
-
-impl Encodable
for Hash64 {
- #[inline]
- fn encode(&self, s: &mut S) {
- s.emit_raw_bytes(&self.inner.to_le_bytes());
+ pub fn wrapping_add(self, other: Self) -> Self {
+ Self { inner: self.inner.wrapping_add(other.inner) }
}
}
-impl Decodable for Hash64 {
+impl BitXorAssign for Hash64 {
#[inline]
- fn decode(d: &mut D) -> Self {
- Self { inner: u64::from_le_bytes(d.read_raw_bytes(8).try_into().unwrap()) }
+ fn bitxor_assign(&mut self, rhs: u64) {
+ self.inner ^= rhs;
}
}
@@ -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 5bfc4756ec6a7..98300fc40fbeb 100644
--- a/compiler/rustc_hir/Cargo.toml
+++ b/compiler/rustc_hir/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_hir"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[dependencies]
# tidy-alphabetical-start
@@ -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 9a6dee1e511df..35c6e57b87700 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 dc527240f742a..c4c309e77e194 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};
@@ -92,7 +93,7 @@ impl DefPathTable {
pub fn enumerated_keys_and_path_hashes(
&self,
- ) -> impl Iterator- + ExactSizeIterator + '_ {
+ ) -> impl Iterator
- + ExactSizeIterator {
self.index_to_key
.iter_enumerated()
.map(move |(index, key)| (index, key, self.def_path_hash(index)))
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index eafc60f9d72f7..61f64e62058fc 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1913,13 +1913,18 @@ pub enum BodyOwnerKind {
/// Initializer of a `static` item.
Static(Mutability),
+
+ /// Fake body for a global asm to store its const-like value types.
+ GlobalAsm,
}
impl BodyOwnerKind {
pub fn is_fn_or_closure(self) -> bool {
match self {
BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
- BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) => false,
+ BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) | BodyOwnerKind::GlobalAsm => {
+ false
+ }
}
}
}
@@ -3420,7 +3425,7 @@ pub enum InlineAsmOperand<'hir> {
anon_const: &'hir AnonConst,
},
SymFn {
- anon_const: &'hir AnonConst,
+ expr: &'hir Expr<'hir>,
},
SymStatic {
path: QPath<'hir>,
@@ -3848,7 +3853,7 @@ impl<'hir> Item<'hir> {
expect_foreign_mod, (ExternAbi, &'hir [ForeignItemRef]),
ItemKind::ForeignMod { abi, items }, (*abi, items);
- expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm(asm), asm;
+ expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm, .. }, asm;
expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>),
ItemKind::TyAlias(ty, generics), (ty, generics);
@@ -4015,7 +4020,15 @@ pub enum ItemKind<'hir> {
/// An external module, e.g. `extern { .. }`.
ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemRef] },
/// Module-level inline assembly (from `global_asm!`).
- GlobalAsm(&'hir InlineAsm<'hir>),
+ GlobalAsm {
+ asm: &'hir InlineAsm<'hir>,
+ /// A fake body which stores typeck results for the global asm's sym_fn
+ /// operands, which are represented as path expressions. This body contains
+ /// a single [`ExprKind::InlineAsm`] which points to the asm in the field
+ /// above, and which is typechecked like a inline asm expr just for the
+ /// typeck results.
+ fake_body: BodyId,
+ },
/// A type alias, e.g., `type Foo = Bar`.
TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>),
/// An enum definition, e.g., `enum Foo {C, D}`.
@@ -4081,7 +4094,7 @@ impl ItemKind<'_> {
ItemKind::Macro(..) => "macro",
ItemKind::Mod(..) => "module",
ItemKind::ForeignMod { .. } => "extern block",
- ItemKind::GlobalAsm(..) => "global asm item",
+ ItemKind::GlobalAsm { .. } => "global asm item",
ItemKind::TyAlias(..) => "type alias",
ItemKind::Enum(..) => "enum",
ItemKind::Struct(..) => "struct",
@@ -4540,6 +4553,10 @@ impl<'hir> Node<'hir> {
..
}) => Some((owner_id.def_id, *body)),
+ Node::Item(Item {
+ owner_id, kind: ItemKind::GlobalAsm { asm: _, fake_body }, ..
+ }) => Some((owner_id.def_id, *fake_body)),
+
Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => {
Some((*def_id, *body))
}
diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs
index 300d44355303a..f75b9662132e8 100644
--- a/compiler/rustc_hir/src/hir/tests.rs
+++ b/compiler/rustc_hir/src/hir/tests.rs
@@ -9,11 +9,11 @@ macro_rules! define_tests {
let unambig = $kind::$variant::<'_, ()> { $($init)* };
let unambig_to_ambig = unsafe { std::mem::transmute::<_, $kind<'_, AmbigArg>>(unambig) };
- assert!(matches!(&unambig_to_ambig, $kind::$variant { $($init)* }));
+ assert!(matches!(&unambig_to_ambig, &$kind::$variant { $($init)* }));
let ambig_to_unambig = unsafe { std::mem::transmute::<_, $kind<'_, ()>>(unambig_to_ambig) };
- assert!(matches!(&ambig_to_unambig, $kind::$variant { $($init)* }));
+ assert!(matches!(&ambig_to_unambig, &$kind::$variant { $($init)* }));
}
)*};
}
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 949f8daa4dcf2..d5fa7ec366b28 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -19,7 +19,7 @@
//! - 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 `maybe_tcx`), and use
-//! `tcx.hir().visit_all_item_likes_in_crate(&mut visitor)`. Within your
+//! `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.
@@ -31,7 +31,7 @@
//! 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 `maybe_tcx`). Walk your crate with
-//! `tcx.hir().walk_toplevel_module(visitor)` invoked on `tcx.hir().krate()`.
+//! `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.
@@ -193,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
@@ -573,9 +573,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
try_visit!(visitor.visit_id(item.hir_id()));
walk_list!(visitor, visit_foreign_item_ref, items);
}
- ItemKind::GlobalAsm(asm) => {
+ ItemKind::GlobalAsm { asm: _, fake_body } => {
try_visit!(visitor.visit_id(item.hir_id()));
- try_visit!(visitor.visit_inline_asm(asm, item.hir_id()));
+ // Visit the fake body, which contains the asm statement.
+ // Therefore we should not visit the asm statement again
+ // outside of the body, or some visitors won't have their
+ // typeck results set correctly.
+ try_visit!(visitor.visit_nested_body(fake_body));
}
ItemKind::TyAlias(ref ty, ref generics) => {
try_visit!(visitor.visit_id(item.hir_id()));
@@ -593,9 +597,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
defaultness: _,
polarity: _,
defaultness_span: _,
- ref generics,
- ref of_trait,
- ref self_ty,
+ generics,
+ of_trait,
+ self_ty,
items,
}) => {
try_visit!(visitor.visit_id(item.hir_id()));
@@ -1045,7 +1049,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
}
GenericParamKind::Const { ref ty, ref default, synthetic: _ } => {
try_visit!(visitor.visit_ty_unambig(ty));
- if let Some(ref default) = default {
+ if let Some(default) = default {
try_visit!(visitor.visit_const_param_default(param.hir_id, default));
}
}
@@ -1401,8 +1405,8 @@ pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>(
try_visit!(visitor.visit_generic_args(constraint.gen_args));
match constraint.kind {
AssocItemConstraintKind::Equality { ref term } => match term {
- Term::Ty(ref ty) => try_visit!(visitor.visit_ty_unambig(ty)),
- Term::Const(ref c) => try_visit!(visitor.visit_const_arg_unambig(c)),
+ Term::Ty(ty) => try_visit!(visitor.visit_ty_unambig(ty)),
+ Term::Const(c) => try_visit!(visitor.visit_const_arg_unambig(c)),
},
AssocItemConstraintKind::Bound { bounds } => {
walk_list!(visitor, visit_param_bound, bounds)
@@ -1442,10 +1446,12 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>(
try_visit!(visitor.visit_expr(in_expr));
visit_opt!(visitor, visit_expr, out_expr);
}
- InlineAsmOperand::Const { anon_const, .. }
- | InlineAsmOperand::SymFn { anon_const, .. } => {
+ InlineAsmOperand::Const { anon_const, .. } => {
try_visit!(visitor.visit_anon_const(anon_const));
}
+ InlineAsmOperand::SymFn { expr, .. } => {
+ try_visit!(visitor.visit_expr(expr));
+ }
InlineAsmOperand::SymStatic { path, .. } => {
try_visit!(visitor.visit_qpath(path, id, *op_sp));
}
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 34c0837b25a52..f5626937ec456 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -60,7 +60,7 @@ impl LanguageItems {
self.reverse_items.get(&def_id).copied()
}
- pub fn iter(&self) -> impl Iterator
- + '_ {
+ pub fn iter(&self) -> impl Iterator
- {
self.items
.iter()
.enumerate()
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index f3e8f059c9e3c..70e95a84e68cc 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -110,7 +110,7 @@ impl Target {
ItemKind::Macro(..) => Target::MacroDef,
ItemKind::Mod(..) => Target::Mod,
ItemKind::ForeignMod { .. } => Target::ForeignMod,
- ItemKind::GlobalAsm(..) => Target::GlobalAsm,
+ ItemKind::GlobalAsm { .. } => Target::GlobalAsm,
ItemKind::TyAlias(..) => Target::TyAlias,
ItemKind::Enum(..) => Target::Enum,
ItemKind::Struct(..) => Target::Struct,
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index e0e63d183c63d..0837444ffdbe5 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/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index 196d7d99e933d..55a816a855af4 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustc_hir_analysis"
version = "0.0.0"
-edition = "2021"
+edition = "2024"
[lib]
test = false
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 5560d087e96f0..47d5976be09ef 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 9b02651a8bdf5..0000000000000
--- 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