From 98f40672a617f2ba9bf22cc9252a8f743da809e7 Mon Sep 17 00:00:00 2001 From: rabindra789 Date: Thu, 6 Aug 2026 21:09:28 +0530 Subject: [PATCH 1/9] mir: validate Move call arguments are locals or box derefs --- compiler/rustc_mir_transform/src/validate.rs | 20 ++++++++++++++ tests/ui/mir/validate/call-move-arg.rs | 28 ++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tests/ui/mir/validate/call-move-arg.rs diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index b9c55439f0597..6602a69549ed2 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -431,6 +431,26 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { ), ); } + + // Call arguments are moved by reference, so they must be plain locals + // or the contents of a box; other moved places violate MIR invariants. + if self.tcx.sess.opts.unstable_opts.validate_mir + && self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) + { + let is_plain_local = place.projection.is_empty(); + let is_box_deref = + matches!(place.projection.as_ref(), [ProjectionElem::Deref]) + && self.body.local_decls[place.local].ty.is_box(); + if !is_plain_local && !is_box_deref { + self.fail( + location, + format!( + "encountered `Move` of a non-local, non-box place in `Call` terminator: {:?}", + terminator.kind, + ), + ); + } + } } } diff --git a/tests/ui/mir/validate/call-move-arg.rs b/tests/ui/mir/validate/call-move-arg.rs new file mode 100644 index 0000000000000..a6e01f264a986 --- /dev/null +++ b/tests/ui/mir/validate/call-move-arg.rs @@ -0,0 +1,28 @@ +// Check that validation rejects moving a non-local, non-box place as a +// `Call` argument. +// +//@ failure-status: 101 +//@ dont-check-compiler-stderr +//@ compile-flags: -Zvalidate-mir + +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +fn bar(_x: i32) {} + +#[custom_mir(dialect = "built")] +pub fn main() { + mir! { + let a: (i32, i32); + { + a = (1, 2); + Call(RET = bar(Move(a.0)), ReturnTo(retblock), UnwindContinue()) + //~^ ERROR broken MIR in + //~| ERROR encountered `Move` of a non-local, non-box place in `Call` terminator + } + retblock = { + Return() + } + } +} From 84963f87e68007ad1adbd331661f6e0d28b55395 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 28 Aug 2026 13:04:20 +0200 Subject: [PATCH 2/9] run `extern "tail"` with `byval` argument test --- .../tailcc-no-signature-restriction.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs b/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs index 9c9085ca1daca..64cea66c1d565 100644 --- a/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs +++ b/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs @@ -1,9 +1,9 @@ //@ run-pass //@ ignore-backends: gcc -//@ min-llvm-version: 22 -//@ revisions: x86_64 aarch64 +//@ min-llvm-version: 23 +//@ revisions: x86 x86_64 aarch64 // -// FIXME: enable x86 on LLVM 23. +//@ [x86] only-x86 //@ [x86_64] only-x86_64 //@ [aarch64] only-aarch64 #![feature(explicit_tail_calls, rust_tail_cc)] @@ -18,6 +18,7 @@ pub extern "tail" fn add() -> u64 { become add(1, 2); } +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(windows)))] #[inline(never)] pub extern "tail" fn pass_struct(a: u64, d: u64) -> u64 { #[derive(Clone, Copy)] @@ -42,8 +43,7 @@ pub extern "tail" fn pass_struct(a: u64, d: u64) -> u64 { fn main() { assert_eq!(add(), 3); - // FIXME: LLVM 22 has a bug which makes this miscompile. - if false { - assert_eq!(pass_struct(5, 6), 5 + 6); - } + // Windows and Aarch64 in LLVM 23 does not support byval arguments. + #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(windows)))] + assert_eq!(pass_struct(5, 6), 5 + 6); } From 38e3714a7a7bedb70a5a2a2a20ba3a0c2c4710ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Mon, 7 Sep 2026 17:13:35 +0200 Subject: [PATCH 3/9] windows-gnu: document libgcc requirement --- src/doc/rustc/src/platform-support/windows-gnu.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/platform-support/windows-gnu.md b/src/doc/rustc/src/platform-support/windows-gnu.md index d7aec5af21dec..595c2a42c81a4 100644 --- a/src/doc/rustc/src/platform-support/windows-gnu.md +++ b/src/doc/rustc/src/platform-support/windows-gnu.md @@ -34,6 +34,7 @@ The targets are built and tested using a reasonably modern C toolchain, and it s * GCC 14.2 * mingw-w64 12.0.0 * MSVCRT library as the default +* Libgcc with DWARF-2 exception handling for i686 and SEH for x86_64 Using older tools (especially Binutils) may not work properly, due to the number of issues plaguing older versions of Binutils. The supported toolchain versions are subject to change. From 9dee1dc06af405502f88fd2d162024802d9b85b1 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 7 Sep 2026 19:00:47 +0200 Subject: [PATCH 4/9] Update books --- src/doc/book | 2 +- src/doc/edition-guide | 2 +- src/doc/reference | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/book b/src/doc/book index 917544888a55e..1500248d8f230 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 917544888a55e4da7109bdba8c88c893c0da70f4 +Subproject commit 1500248d8f230566e4ec9f27fcbb8fe9e2898ab1 diff --git a/src/doc/edition-guide b/src/doc/edition-guide index f5abcf137698e..ab8544aeed7b7 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit f5abcf137698e5ad6ebed359d69654ff705346af +Subproject commit ab8544aeed7b792984366aa122ac19bd47ad9a2f diff --git a/src/doc/reference b/src/doc/reference index 3b38834b39f73..e24eecf97b0c9 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 3b38834b39f732c64686f7c64aa29dcf3cd83ba5 +Subproject commit e24eecf97b0c9a6dbac67191098204dc8a190aaa From fa2850ebe725abe8aa786e514a5b0ffcae57ba07 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 24 Aug 2026 11:43:21 +0200 Subject: [PATCH 5/9] misc typo fixes --- .../src/solve/sharing-crates-with-rust-analyzer.md | 10 +++++----- src/doc/rustc-dev-guide/src/solve/the-solver.md | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md b/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md index 110fd1331bc44..bf9655c866ee0 100644 --- a/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md +++ b/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md @@ -115,7 +115,7 @@ For rust-analyzer, the corresponding implementations are located across several These two traits correspond to the role of [`InferCtxt`][rustc inferctxt] in rustc. [`InferCtxtLike`][ir inferctxtlike] must be defined in `rustc_infer` due to coherence -constraints(orphan rules). +constraints (orphan rules). As a result, it cannot provide functionality that lives in `rustc_trait_selection`. Instead, behavior that depends on trait-solving logic is abstracted into a separate trait, [`SolverDelegate`][ir solverdelegate]. @@ -214,9 +214,9 @@ non-obvious considerations: 1. The generic parameters `I` and `J` are reserved for `I: Interner` and `J` being the interner it is being lifted to. -2. `PhantomData` is handled automatically, creating a new `PhantomData` but - _has_ to be included in the file through; `use std::marker::PhantomData;` - you cannot use `std::marker::PhantomData` directly on the field of a struct. +2. `PhantomData` is handled automatically, creating a new `PhantomData`. But it + _has_ to be used in the fully unqualified form -- you cannot use + `std::marker::PhantomData` directly in the field. 3. The bounds are deliberately written as associated type bounds on the `Interner` trait rather than as `where` clauses on `LiftInto`. Given only `I: LiftInto`, Rust can then treat bounds such as the following as implied: @@ -310,4 +310,4 @@ There are still duplicated implementations between rustc and rust-analyzer—suc [r-a coerce]: https://github.com/rust-lang/rust-analyzer/blob/34f47d9298c478c12c6c4c0348771d1b05706e09/crates/hir-ty/src/infer/coerce.rs [rustc_lift]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/lift.rs#L18 [rustc_typevisitable]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/visit.rs#L62 -[rustc_typefoldable]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/fold.rs#L71 \ No newline at end of file +[rustc_typefoldable]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/fold.rs#L71 diff --git a/src/doc/rustc-dev-guide/src/solve/the-solver.md b/src/doc/rustc-dev-guide/src/solve/the-solver.md index 0151c0482d109..3d66ec272698d 100644 --- a/src/doc/rustc-dev-guide/src/solve/the-solver.md +++ b/src/doc/rustc-dev-guide/src/solve/the-solver.md @@ -7,7 +7,7 @@ as it is very similar to this implementation and also talks about limitations of ## A rough walkthrough -The entry-point of the solver is `InferCtxtEvalExt::evaluate_root_goal`. +The entry-point of the solver is `SolverDelegateEvalExt::evaluate_root_goal`. This function sets up the root `EvalCtxt` and then calls `EvalCtxt::evaluate_goal`, to actually enter the trait solver. From 2827a304fe7ce27405a6edae347c61e967409972 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 24 Aug 2026 11:55:40 +0200 Subject: [PATCH 6/9] remove outdated docs I ended up deciding not to add docs about `bounds` as it seems like a relatively minor feature of the derive, and there are docs at [1]. [1]: https://github.com/rust-lang/rust/blob/3ffb26fbf5bf232cf59e314e75ea325973f4f583/compiler/rustc_type_ir_macros/src/lib.rs#L21-L55 --- .../src/solve/sharing-crates-with-rust-analyzer.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md b/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md index bf9655c866ee0..2b06f5b414c1b 100644 --- a/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md +++ b/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md @@ -255,12 +255,6 @@ There is intentionally no ignore attribute. The traversal must visit every field. This is a soundness requirement for rust-analyzer's use of the traversal when tracing and garbage-collecting interned types. -When the macro crate's `nightly` feature is enabled, the derive macro remains -registered but emits no tokens. The `GenericTypeVisitable` trait and its -traversal module are also excluded from the nightly configuration of -`rustc_type_ir`; they exist only in its non-nightly configuration. - - ## Long-term plans for supporting rust-analyzer In general, we aim to support rust-analyzer just as well as rustc in these shared crates—provided From 0db592d2919c1ca9cc3c1773005989df0e90ae75 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 24 Aug 2026 12:51:58 +0200 Subject: [PATCH 7/9] realize that `bounds` works a bit differently than advertised Just specifying `T: GenericTypeVisitable` doesn't work, as the trait has a generic: `V`, the visitor. `T: GenericTypeVisitable<__V>` is what actually works, as `__V` is the generic added to the impl generated by the derive macro. We discussed[1] different ways of making this nicer, but settled on not doing anything, as we don't expect people to need to specify any actual bounds. [1]: https://rust-lang.zulipchat.com/#narrow/channel/185405-t-compiler.2Frust-analyzer/topic/Updating.20next-solver/near/618331780 and below --- compiler/rustc_type_ir_macros/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs index e1d2b53366066..8a437c4995724 100644 --- a/compiler/rustc_type_ir_macros/src/lib.rs +++ b/compiler/rustc_type_ir_macros/src/lib.rs @@ -48,11 +48,15 @@ decl_derive!( /// struct Foo { /// #[generic_type_visitable(bounds())] /// just_self: Box, - /// #[generic_type_visitable(bounds(Bar: GenericTypeVisitable))] + /// #[generic_type_visitable(bounds(Bar: GenericTypeVisitable<__V>))] /// contains_self: (Box, Bar), /// } /// struct Bar; /// ``` + /// + /// Note: the `__V` lifetime is an implementation detail of the derive macro. + /// We could probably handle this in a nicer way, but we don't expect this form + /// to really be necessary any time soon, so for now we don't. customizable_type_visitable_derive ); @@ -461,7 +465,7 @@ mod kw { /// Parses a bound like: /// /// ```ignore (would need to import GenericTypeVisitable to get this to compile) -/// #[generic_type_visitable(bounds(Foo: GenericTypeVisitable, Bar: GenericTypeVisitable))] +/// #[generic_type_visitable(bounds(Foo: GenericTypeVisitable<__V>, Bar: GenericTypeVisitable<__V>))] /// ``` fn parse_generic_type_visitable_bound( attr: &Attribute, From ada4f67f8aefa8707a65f87c4f9501e109b22333 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 7 Sep 2026 21:31:33 +0200 Subject: [PATCH 8/9] add tests for `#[derive(GenericTypeVisitable)]` and `bounds` --- ...ve-generic-type-visitable-missing-bound.rs | 19 +++ ...eneric-type-visitable-missing-bound.stderr | 18 +++ .../derive-generic-type-visitable.rs | 119 ++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.rs create mode 100644 tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.stderr create mode 100644 tests/ui-fulldeps/derive-generic-type-visitable.rs diff --git a/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.rs b/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.rs new file mode 100644 index 0000000000000..af44ff7e92252 --- /dev/null +++ b/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.rs @@ -0,0 +1,19 @@ +//@ edition: 2024 +//@ check-fail + +#![crate_type = "rlib"] +#![feature(rustc_private)] + +extern crate rustc_type_ir; +extern crate rustc_type_ir_macros; + +use rustc_type_ir_macros::GenericTypeVisitable; + +#[derive(GenericTypeVisitable)] +struct MissingBound { + // This should fail, as `T: GenericTypeVisitable<__V>` wasn't specified + #[generic_type_visitable(bounds())] + //~^ ERROR: the trait bound `T: GenericTypeVisitable<__V>` is not satisfied + partially_rec: (Vec, T), + other: u32, +} diff --git a/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.stderr b/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.stderr new file mode 100644 index 0000000000000..44433984e4a7f --- /dev/null +++ b/tests/ui-fulldeps/derive-generic-type-visitable-missing-bound.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `T: GenericTypeVisitable<__V>` is not satisfied + --> $DIR/derive-generic-type-visitable-missing-bound.rs:15:5 + | +LL | #[derive(GenericTypeVisitable)] + | -------------------- + | | + | required by a bound introduced by this call + | in this derive macro expansion +... +LL | #[generic_type_visitable(bounds())] + | ^ the nightly-only, unstable trait `GenericTypeVisitable<__V>` is not implemented for `T` + | + = note: required for `(Vec>, T)` to implement `GenericTypeVisitable<__V>` + = note: this error originates in the derive macro `GenericTypeVisitable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui-fulldeps/derive-generic-type-visitable.rs b/tests/ui-fulldeps/derive-generic-type-visitable.rs new file mode 100644 index 0000000000000..91c7a502a87d8 --- /dev/null +++ b/tests/ui-fulldeps/derive-generic-type-visitable.rs @@ -0,0 +1,119 @@ +//@ edition: 2024 +//@ run-pass + +#![feature(rustc_private)] + +extern crate rustc_type_ir; +extern crate rustc_type_ir_macros; + +use rustc_type_ir::GenericTypeVisitable; +use rustc_type_ir_macros::GenericTypeVisitable; + +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[expect(unused_extern_crates)] +extern crate rustc_driver; + +#[derive(GenericTypeVisitable)] +struct DerivesGenericTypeVisitable; + +#[derive(GenericTypeVisitable)] +struct Foo { + one: Incrementer, + two: Vec, +} + +#[derive(GenericTypeVisitable)] +enum Enum { + A, + B(Incrementer), + C { one: Incrementer, two: Vec }, +} + +#[derive(GenericTypeVisitable)] +struct Generic(Vec); + +#[derive(GenericTypeVisitable)] +struct Recursive { + #[generic_type_visitable(bounds())] + rec: Vec, + other: Incrementer, +} + +#[derive(GenericTypeVisitable)] +struct PartiallyRecursiveField { + #[generic_type_visitable(bounds(T: GenericTypeVisitable<__V>))] + partially_rec: (Vec, T), + other: Incrementer, +} + +// start testing setup + +use std::sync::atomic::{AtomicU8, Ordering}; + +static COUNT: AtomicU8 = AtomicU8::new(0); + +/// A type that, when visited, increments a global counter. +/// +/// Used to (weakly) test the correctness of the derive by making sure that +/// it traverses all the fields, and thus reaches all the incrementers. +#[derive(Clone)] +struct Incrementer; + +unsafe impl GenericTypeVisitable for Incrementer { + fn generic_visit_with(&self, _visitor: &mut V) { + COUNT.fetch_add(1, Ordering::Relaxed); + } +} + +// end testing setup + +fn main() { + use Incrementer as Inc; // for brevity + + #[track_caller] + fn check>(item: T, count: u8) { + let mut v = (); + item.generic_visit_with(&mut v); + assert_eq!(COUNT.swap(0, Ordering::Relaxed), count); + } + + check(DerivesGenericTypeVisitable, 0); + check(Foo { one: Inc, two: vec![] }, 1); + check(Foo { one: Inc, two: vec![Inc; 2] }, 1 + 2); + check(Enum::A, 0); + check(Enum::B(Inc), 1); + check(Enum::C { one: Inc, two: vec![] }, 1); + check(Enum::C { one: Inc, two: vec![Inc; 3] }, 1 + 3); + check(Generic::(vec![]), 0); + // visits each of the nested `Inc`s + check(Generic(vec![Inc; 5]), 5); + + // Every (nested) `rec!` adds another `Recursive`, and thus 1 more visited `Inc`. + macro_rules! rec { + [$($i:expr),* $(,)?] => { + Recursive { rec: vec![$($i),*], other: Inc } + } + } + check(rec![], 1); + check(rec![rec![]], 2); + check(rec![rec![], rec![]], 3); + check(rec![rec![rec![]]], 3); + + // Every (nested) `prec!` adds another `PartiallyRecursiveField`, and thus 1 more visited `Inc`. + macro_rules! prec { + ([$($i:expr),* $(,)?], $o:expr) => { + PartiallyRecursiveField { partially_rec: (vec![$($i),*], $o), other: Inc } + } + } + // Every nested `a()`, `b()`, and `c()` adds 0, 1, and 2 more visited `Inc`s, respectively. + let a = || Enum::A; + let b = || Enum::B(Inc); + let c = || Enum::C { one: Inc, two: vec![Inc] }; + check(prec!([], a()), 1 + 0); + check(prec!([], b()), 1 + 1); + check(prec!([], c()), 1 + 2); + check(prec!([prec!([], a())], a()), 1 + (1 + 0) + 0); + check(prec!([prec!([], b())], a()), 1 + (1 + 1) + 0); + check(prec!([prec!([], b())], b()), 1 + (1 + 1) + 1); +} From 8463342e91b9b0b19e97ebbf34e248564f333f28 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Tue, 8 Sep 2026 17:18:39 +0900 Subject: [PATCH 9/9] docs(time): replace "method" with "function" --- library/core/src/time.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index f9e2dc6b7f849..c123c66ee3bc0 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -345,7 +345,7 @@ impl Duration { /// Creates a new `Duration` from the specified number of weeks. /// - /// For this method, one week is defined as 7 days, or 604,800 seconds. + /// For this function, one week is defined as 7 days, or 604,800 seconds. /// /// # Panics /// @@ -375,7 +375,7 @@ impl Duration { /// Creates a new `Duration` from the specified number of days. /// - /// For this method, one day is defined as 24 hours, or 86,400 seconds. + /// For this function, one day is defined as 24 hours, or 86,400 seconds. /// /// # Panics /// @@ -405,7 +405,7 @@ impl Duration { /// Creates a new `Duration` from the specified number of hours. /// - /// For this method, one hour is defined as 60 minutes, or 3,600 seconds. + /// For this function, one hour is defined as 60 minutes, or 3,600 seconds. /// /// # Panics /// @@ -435,7 +435,7 @@ impl Duration { /// Creates a new `Duration` from the specified number of minutes. /// - /// For this method, one minute is defined as 60 seconds. + /// For this function, one minute is defined as 60 seconds. /// /// # Panics ///