From 9437d227905267358663609ecddad97eb9f587f4 Mon Sep 17 00:00:00 2001 From: Maximilian Azendorf Date: Sat, 14 Mar 2026 23:51:44 +0100 Subject: [PATCH 01/16] Avoid stack overflow in FindExprBySpan --- .../src/error_reporting/traits/mod.rs | 23 +++++++++++-------- tests/ui/try-trait/issue-153583.rs | 7 ++++++ tests/ui/try-trait/issue-153583.stderr | 11 +++++++++ 3 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 tests/ui/try-trait/issue-153583.rs create mode 100644 tests/ui/try-trait/issue-153583.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index bda0c4fa2c6f6..69afa4f20b3eb 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -8,6 +8,7 @@ pub mod suggestions; use std::{fmt, iter}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::unord::UnordSet; use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; @@ -74,18 +75,20 @@ impl<'v> Visitor<'v> for FindExprBySpan<'v> { } fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { - if self.span == ex.span { - self.result = Some(ex); - } else { - if let hir::ExprKind::Closure(..) = ex.kind - && self.include_closures - && let closure_header_sp = self.span.with_hi(ex.span.hi()) - && closure_header_sp == ex.span - { + ensure_sufficient_stack(|| { + if self.span == ex.span { self.result = Some(ex); + } else { + if let hir::ExprKind::Closure(..) = ex.kind + && self.include_closures + && let closure_header_sp = self.span.with_hi(ex.span.hi()) + && closure_header_sp == ex.span + { + self.result = Some(ex); + } + hir::intravisit::walk_expr(self, ex); } - hir::intravisit::walk_expr(self, ex); - } + }); } fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) { diff --git a/tests/ui/try-trait/issue-153583.rs b/tests/ui/try-trait/issue-153583.rs new file mode 100644 index 0000000000000..9872d1bbc8173 --- /dev/null +++ b/tests/ui/try-trait/issue-153583.rs @@ -0,0 +1,7 @@ +// Regression test for #153583: deeply nested `?` operators should not overflow +// the error-reporting visitor. + +fn main() -> Result<(), ()> { + 0????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????; //~ ERROR the `?` operator can only be applied to values that implement `Try` + Ok(()) +} diff --git a/tests/ui/try-trait/issue-153583.stderr b/tests/ui/try-trait/issue-153583.stderr new file mode 100644 index 0000000000000..cbeeaa348024e --- /dev/null +++ b/tests/ui/try-trait/issue-153583.stderr @@ -0,0 +1,11 @@ +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/issue-153583.rs:5:5 + | +LL | 0???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????... + | ^^ the `?` operator cannot be applied to type `{integer}` + | + = help: the nightly-only, unstable trait `Try` is not implemented for `{integer}` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From cf6ea02d28f626dd37dc3d535a0a0e9cd89fbe1e Mon Sep 17 00:00:00 2001 From: Maximilian Azendorf Date: Sun, 15 Mar 2026 00:06:27 +0100 Subject: [PATCH 02/16] Add tidy exemption for issue-153583 test --- tests/ui/try-trait/issue-153583.rs | 1 + tests/ui/try-trait/issue-153583.stderr | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ui/try-trait/issue-153583.rs b/tests/ui/try-trait/issue-153583.rs index 9872d1bbc8173..cc00866fa3295 100644 --- a/tests/ui/try-trait/issue-153583.rs +++ b/tests/ui/try-trait/issue-153583.rs @@ -1,5 +1,6 @@ // Regression test for #153583: deeply nested `?` operators should not overflow // the error-reporting visitor. +// ignore-tidy-linelength fn main() -> Result<(), ()> { 0????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????; //~ ERROR the `?` operator can only be applied to values that implement `Try` diff --git a/tests/ui/try-trait/issue-153583.stderr b/tests/ui/try-trait/issue-153583.stderr index cbeeaa348024e..8a732f8a882ea 100644 --- a/tests/ui/try-trait/issue-153583.stderr +++ b/tests/ui/try-trait/issue-153583.stderr @@ -1,5 +1,5 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/issue-153583.rs:5:5 + --> $DIR/issue-153583.rs:6:5 | LL | 0???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????... | ^^ the `?` operator cannot be applied to type `{integer}` From 572bdae107b69ed37a1f466367d859a99228b351 Mon Sep 17 00:00:00 2001 From: Maximilian Azendorf Date: Sun, 15 Mar 2026 00:19:17 +0100 Subject: [PATCH 03/16] Rename issue-153583 UI test --- .../{issue-153583.rs => deep-try-chain-issue-153583.rs} | 0 .../{issue-153583.stderr => deep-try-chain-issue-153583.stderr} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/ui/try-trait/{issue-153583.rs => deep-try-chain-issue-153583.rs} (100%) rename tests/ui/try-trait/{issue-153583.stderr => deep-try-chain-issue-153583.stderr} (91%) diff --git a/tests/ui/try-trait/issue-153583.rs b/tests/ui/try-trait/deep-try-chain-issue-153583.rs similarity index 100% rename from tests/ui/try-trait/issue-153583.rs rename to tests/ui/try-trait/deep-try-chain-issue-153583.rs diff --git a/tests/ui/try-trait/issue-153583.stderr b/tests/ui/try-trait/deep-try-chain-issue-153583.stderr similarity index 91% rename from tests/ui/try-trait/issue-153583.stderr rename to tests/ui/try-trait/deep-try-chain-issue-153583.stderr index 8a732f8a882ea..d3794136202b4 100644 --- a/tests/ui/try-trait/issue-153583.stderr +++ b/tests/ui/try-trait/deep-try-chain-issue-153583.stderr @@ -1,5 +1,5 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/issue-153583.rs:6:5 + --> $DIR/deep-try-chain-issue-153583.rs:6:5 | LL | 0???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????... | ^^ the `?` operator cannot be applied to type `{integer}` From 86d2cf1fe949192f286fd061bbd73b117677d087 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 24 Dec 2025 21:55:37 +0900 Subject: [PATCH 04/16] Add tests for issue number 89299 and 149881 --- ...ying-fn-bounds-issue-149881.current.stderr | 22 +++++++++++++++++++ ...isfying-fn-bounds-issue-149881.next.stderr | 22 +++++++++++++++++++ ...t-not-satisfying-fn-bounds-issue-149881.rs | 17 ++++++++++++++ ...fying-fn-bounds-issue-89299.current.stderr | 16 ++++++++++++++ ...tisfying-fn-bounds-issue-89299.next.stderr | 16 ++++++++++++++ ...ut-not-satisfying-fn-bounds-issue-89299.rs | 22 +++++++++++++++++++ 6 files changed, 115 insertions(+) create mode 100644 tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.current.stderr create mode 100644 tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.next.stderr create mode 100644 tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.rs create mode 100644 tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.current.stderr create mode 100644 tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.next.stderr create mode 100644 tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.rs diff --git a/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.current.stderr b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.current.stderr new file mode 100644 index 0000000000000..788551f4eaa2d --- /dev/null +++ b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.current.stderr @@ -0,0 +1,22 @@ +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/expectated-input-not-satisfying-fn-bounds-issue-149881.rs:15:24 + | +LL | <[_]>::into_vec(id(Box::new([0, 1, 2]))); + | -- ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[{integer}]` +note: required by an implicit `Sized` bound in `id` + --> $DIR/expectated-input-not-satisfying-fn-bounds-issue-149881.rs:10:7 + | +LL | fn id(x: Box) -> Box { + | ^ required by the implicit `Sized` requirement on this type parameter in `id` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn id(x: Box) -> Box { + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.next.stderr b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.next.stderr new file mode 100644 index 0000000000000..788551f4eaa2d --- /dev/null +++ b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.next.stderr @@ -0,0 +1,22 @@ +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/expectated-input-not-satisfying-fn-bounds-issue-149881.rs:15:24 + | +LL | <[_]>::into_vec(id(Box::new([0, 1, 2]))); + | -- ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[{integer}]` +note: required by an implicit `Sized` bound in `id` + --> $DIR/expectated-input-not-satisfying-fn-bounds-issue-149881.rs:10:7 + | +LL | fn id(x: Box) -> Box { + | ^ required by the implicit `Sized` requirement on this type parameter in `id` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn id(x: Box) -> Box { + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.rs b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.rs new file mode 100644 index 0000000000000..d6d522055b538 --- /dev/null +++ b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.rs @@ -0,0 +1,17 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// FIXME(#149379): This should pass, but fails due to fudged expactation +// types which are potentially not well-formed or for whom the function +// where-bounds don't actually hold. And this results in weird bugs when +// later treating these expectations as if they were actually correct.. + +fn id(x: Box) -> Box { + x +} + +fn main() { + <[_]>::into_vec(id(Box::new([0, 1, 2]))); + //~^ ERROR: the size for values of type `[{integer}]` cannot be known at compilation time +} diff --git a/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.current.stderr b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.current.stderr new file mode 100644 index 0000000000000..2c0f15edd872e --- /dev/null +++ b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.current.stderr @@ -0,0 +1,16 @@ +error[E0277]: `dyn Trait + Send` cannot be unpinned + --> $DIR/expectated-input-not-satisfying-fn-bounds-issue-89299.rs:20:27 + | +LL | let _x = Foo(Pin::new(&mut a)); + | -------- ^^^^^^ the trait `Unpin` is not implemented for `dyn Trait + Send` + | | + | required by a bound introduced by this call + | + = note: consider using the `pin!` macro + consider using `Box::pin` if you need to access the pinned value outside of the current scope +note: required by a bound in `Pin::::new` + --> $SRC_DIR/core/src/pin.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.next.stderr b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.next.stderr new file mode 100644 index 0000000000000..2c0f15edd872e --- /dev/null +++ b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.next.stderr @@ -0,0 +1,16 @@ +error[E0277]: `dyn Trait + Send` cannot be unpinned + --> $DIR/expectated-input-not-satisfying-fn-bounds-issue-89299.rs:20:27 + | +LL | let _x = Foo(Pin::new(&mut a)); + | -------- ^^^^^^ the trait `Unpin` is not implemented for `dyn Trait + Send` + | | + | required by a bound introduced by this call + | + = note: consider using the `pin!` macro + consider using `Box::pin` if you need to access the pinned value outside of the current scope +note: required by a bound in `Pin::::new` + --> $SRC_DIR/core/src/pin.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.rs b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.rs new file mode 100644 index 0000000000000..9af723b35c27d --- /dev/null +++ b/tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.rs @@ -0,0 +1,22 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// FIXME(#149379): This should pass, but fails due to fudged expactation +// types which are potentially not well-formed or for whom the function +// where-bounds don't actually hold. And this results in weird bugs when +// later treating these expectations as if they were actually correct.. + +use std::pin::Pin; + +trait Trait {} + +impl Trait for i32 {} + +struct Foo<'a>(Pin<&'a mut (dyn Trait + Send)>); + +fn main() { + let mut a = 1; + let _x = Foo(Pin::new(&mut a)); + //~^ ERROR: `dyn Trait + Send` cannot be unpinned +} From dadf2eef344d5124ee0671ce0b9e8ff65da72eb0 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 24 Dec 2025 22:08:23 +0900 Subject: [PATCH 05/16] Do not use ill-formed input expectations when checking function calls --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 11 +++ ...ed-to-inputs-issue-149379-1.current.stderr | 32 -------- ...gated-to-inputs-issue-149379-1.next.stderr | 32 -------- ...ect-propagated-to-inputs-issue-149379-1.rs | 8 +- ...ed-to-inputs-issue-149379-3.current.stderr | 74 +------------------ ...gated-to-inputs-issue-149379-3.next.stderr | 74 +------------------ ...ect-propagated-to-inputs-issue-149379-3.rs | 4 - 7 files changed, 19 insertions(+), 216 deletions(-) delete mode 100644 tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.current.stderr delete mode 100644 tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.next.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 0471fd965cd82..d025b83076b6f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -270,6 +270,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { formal_input_tys }; + // Check the well-formedness of expected input tys, as using ill-formed + // expectation may cause type inference errors. + for &ty in formal_input_tys { + ocx.register_obligation(traits::Obligation::new( + self.tcx, + self.misc(call_span), + self.param_env, + ty::ClauseKind::WellFormed(ty.into()), + )); + } + if !ocx.try_evaluate_obligations().is_empty() { return Err(TypeError::Mismatch); } diff --git a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.current.stderr b/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.current.stderr deleted file mode 100644 index 426e0fe9e0d92..0000000000000 --- a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.current.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:16:33 - | -LL | let _: Box = foo(((), ())); - | ^^ expected trait object, found `()` - | - = note: expected trait object `dyn Send` - found unit type `()` - -error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:16:32 - | -LL | let _: Box = foo(((), ())); - | --- ^^^^^^^^ doesn't have a size known at compile-time - | | - | required by a bound introduced by this call - | - = help: the trait `Sized` is not implemented for `dyn Send` -note: required by an implicit `Sized` bound in `foo` - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:10:8 - | -LL | fn foo(x: (T, ())) -> Box { - | ^ required by the implicit `Sized` requirement on this type parameter in `foo` -help: consider relaxing the implicit `Sized` restriction - | -LL | fn foo(x: (T, ())) -> Box { - | ++++++++ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.next.stderr b/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.next.stderr deleted file mode 100644 index 426e0fe9e0d92..0000000000000 --- a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.next.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:16:33 - | -LL | let _: Box = foo(((), ())); - | ^^ expected trait object, found `()` - | - = note: expected trait object `dyn Send` - found unit type `()` - -error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:16:32 - | -LL | let _: Box = foo(((), ())); - | --- ^^^^^^^^ doesn't have a size known at compile-time - | | - | required by a bound introduced by this call - | - = help: the trait `Sized` is not implemented for `dyn Send` -note: required by an implicit `Sized` bound in `foo` - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs:10:8 - | -LL | fn foo(x: (T, ())) -> Box { - | ^ required by the implicit `Sized` requirement on this type parameter in `foo` -help: consider relaxing the implicit `Sized` restriction - | -LL | fn foo(x: (T, ())) -> Box { - | ++++++++ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs b/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs index 070baf77783de..634e4b2d47924 100644 --- a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs +++ b/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs @@ -1,11 +1,9 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver +//@ check-pass -// FIXME(#149379): This should pass, but fails due to fudged expactation -// types which are potentially not well-formed or for whom the function -// where-bounds don't actually hold. And this results in weird bugs when -// later treating these expectations as if they were actually correct.. +// A regression test for https://github.com/rust-lang/rust/issues/149379. fn foo(x: (T, ())) -> Box { Box::new(x.0) @@ -14,6 +12,4 @@ fn foo(x: (T, ())) -> Box { fn main() { // Uses expectation as its struct tail is sized, resulting in `(dyn Send, ())` let _: Box = foo(((), ())); - //~^ ERROR mismatched types - //~| ERROR the size for values of type `dyn Send` cannot be known at compilation time } diff --git a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.current.stderr b/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.current.stderr index abeee7fe68a1e..f0270c28292ba 100644 --- a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.current.stderr +++ b/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.current.stderr @@ -1,72 +1,5 @@ -error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:55 - | -LL | let _: Box = field_to_box1(Foo { field: 1, tail: () }); - | ^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `dyn Send` -note: required by an implicit `Sized` bound in `Foo` - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:10:12 - | -LL | struct Foo { - | ^ required by the implicit `Sized` requirement on this type parameter in `Foo` -help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:10:12 - | -LL | struct Foo { - | ^ this could be changed to `T: ?Sized`... -LL | field: T, - | - ...if indirection were used here: `Box` - -error[E0308]: mismatched types - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:55 - | -LL | let _: Box = field_to_box1(Foo { field: 1, tail: () }); - | ^ expected trait object, found integer - | - = note: expected trait object `dyn Send` - found type `{integer}` - -error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:42 - | -LL | let _: Box = field_to_box1(Foo { field: 1, tail: () }); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | | - | required by a bound introduced by this call - | - = help: the trait `Sized` is not implemented for `dyn Send` -note: required by an implicit `Sized` bound in `field_to_box1` - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:19:18 - | -LL | fn field_to_box1(x: Foo) -> Box { - | ^ required by the implicit `Sized` requirement on this type parameter in `field_to_box1` -help: consider relaxing the implicit `Sized` restriction - | -LL | fn field_to_box1(x: Foo) -> Box { - | ++++++++ - -error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:36:38 - | -LL | let _: &dyn Send = field_to_box2(&Bar { field: 1 }); - | ------------- ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | | - | required by a bound introduced by this call - | - = help: the trait `Sized` is not implemented for `dyn Send` -note: required by an implicit `Sized` bound in `field_to_box2` - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:23:18 - | -LL | fn field_to_box2(x: &Bar) -> &T { - | ^ required by the implicit `Sized` requirement on this type parameter in `field_to_box2` -help: consider relaxing the implicit `Sized` restriction - | -LL | fn field_to_box2(x: &Bar) -> &T { - | ++++++++ - error[E0308]: mismatched types - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:38:38 + --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:34:38 | LL | let _: &dyn Send = field_to_box3(&(1,)); | ------------- ^^^^^ expected `&(dyn Send,)`, found `&({integer},)` @@ -81,7 +14,6 @@ note: function defined here LL | fn field_to_box3(x: &(T,)) -> &T { | ^^^^^^^^^^^^^ -------- -error: aborting due to 5 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.next.stderr b/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.next.stderr index abeee7fe68a1e..f0270c28292ba 100644 --- a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.next.stderr +++ b/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.next.stderr @@ -1,72 +1,5 @@ -error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:55 - | -LL | let _: Box = field_to_box1(Foo { field: 1, tail: () }); - | ^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `dyn Send` -note: required by an implicit `Sized` bound in `Foo` - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:10:12 - | -LL | struct Foo { - | ^ required by the implicit `Sized` requirement on this type parameter in `Foo` -help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:10:12 - | -LL | struct Foo { - | ^ this could be changed to `T: ?Sized`... -LL | field: T, - | - ...if indirection were used here: `Box` - -error[E0308]: mismatched types - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:55 - | -LL | let _: Box = field_to_box1(Foo { field: 1, tail: () }); - | ^ expected trait object, found integer - | - = note: expected trait object `dyn Send` - found type `{integer}` - -error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:32:42 - | -LL | let _: Box = field_to_box1(Foo { field: 1, tail: () }); - | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | | - | required by a bound introduced by this call - | - = help: the trait `Sized` is not implemented for `dyn Send` -note: required by an implicit `Sized` bound in `field_to_box1` - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:19:18 - | -LL | fn field_to_box1(x: Foo) -> Box { - | ^ required by the implicit `Sized` requirement on this type parameter in `field_to_box1` -help: consider relaxing the implicit `Sized` restriction - | -LL | fn field_to_box1(x: Foo) -> Box { - | ++++++++ - -error[E0277]: the size for values of type `dyn Send` cannot be known at compilation time - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:36:38 - | -LL | let _: &dyn Send = field_to_box2(&Bar { field: 1 }); - | ------------- ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | | - | required by a bound introduced by this call - | - = help: the trait `Sized` is not implemented for `dyn Send` -note: required by an implicit `Sized` bound in `field_to_box2` - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:23:18 - | -LL | fn field_to_box2(x: &Bar) -> &T { - | ^ required by the implicit `Sized` requirement on this type parameter in `field_to_box2` -help: consider relaxing the implicit `Sized` restriction - | -LL | fn field_to_box2(x: &Bar) -> &T { - | ++++++++ - error[E0308]: mismatched types - --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:38:38 + --> $DIR/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs:34:38 | LL | let _: &dyn Send = field_to_box3(&(1,)); | ------------- ^^^^^ expected `&(dyn Send,)`, found `&({integer},)` @@ -81,7 +14,6 @@ note: function defined here LL | fn field_to_box3(x: &(T,)) -> &T { | ^^^^^^^^^^^^^ -------- -error: aborting due to 5 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs b/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs index 7df7878d6d594..f10121e86466d 100644 --- a/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs +++ b/tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs @@ -30,11 +30,7 @@ fn field_to_box3(x: &(T,)) -> &T { fn main() { let _: Box = field_to_box1(Foo { field: 1, tail: () }); - //~^ ERROR the size for values of type `dyn Send` cannot be known at compilation time - //~| ERROR the size for values of type `dyn Send` cannot be known at compilation time - //~| ERROR mismatched types let _: &dyn Send = field_to_box2(&Bar { field: 1 }); - //~^ ERROR the size for values of type `dyn Send` cannot be known at compilation time let _: &dyn Send = field_to_box3(&(1,)); //~^ ERROR mismatched types } From 94e58c09796d793427079f639a5a576e47304479 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 16 Dec 2025 15:14:29 +0100 Subject: [PATCH 06/16] fix fudging --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 57 ++++++++----------- ...t-impl-for-trait-obj-coherence.next.stderr | 4 +- .../occurs-check/associated-type.next.stderr | 4 +- .../traits/next-solver/alias-bound-unsound.rs | 2 +- .../next-solver/alias-bound-unsound.stderr | 6 +- .../diagnostics/coerce-in-may-coerce.stderr | 2 +- .../traits/next-solver/dyn-incompatibility.rs | 1 - .../next-solver/dyn-incompatibility.stderr | 21 +------ .../do-not-drop-ambig-normalization.rs | 27 +++++++++ .../fudge-inference-with-aliases-1.rs | 4 +- .../fudge-inference-with-aliases-2.rs | 4 +- .../fudge-inference-with-aliases-3.rs | 4 +- .../next-solver/lazy-nested-obligations-2.rs | 7 ++- .../lazy-nested-obligations-2.stderr | 15 +++++ 14 files changed, 89 insertions(+), 69 deletions(-) create mode 100644 tests/ui/traits/next-solver/fudge-inference/do-not-drop-ambig-normalization.rs create mode 100644 tests/ui/traits/next-solver/lazy-nested-obligations-2.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d025b83076b6f..a742fe75a9428 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -215,6 +215,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_place_expr_if_unsized(fn_input_ty, arg_expr); } + let formal_input_tys_ns; + let formal_input_tys = if self.next_trait_solver() { + // In the new solver, the normalizations are done lazily. + // Because of this, if we encounter unnormalized alias types inside this + // fudge scope, we might lose the relationships between them and other vars + // when fudging inference variables created here. + // So, we utilize generalization to normalize aliases by adding a new + // inference var and equating it with the type we want to pull out of the + // fudge scope. + formal_input_tys_ns = formal_input_tys + .iter() + .map(|&ty| { + let generalized_ty = self.next_ty_var(call_span); + self.demand_eqtype(call_span, ty, generalized_ty); + generalized_ty + }) + .collect_vec(); + + formal_input_tys_ns.as_slice() + } else { + formal_input_tys + }; + // First, let's unify the formal method signature with the expectation eagerly. // We use this to guide coercion inference; it's output is "fudged" which means // any remaining type variables are assigned to new, unrelated variables. This @@ -238,40 +261,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let origin = self.misc(call_span); ocx.sup(&origin, self.param_env, expected_output, formal_output)?; - let formal_input_tys_ns; - let formal_input_tys = if self.next_trait_solver() { - // In the new solver, the normalizations are done lazily. - // Because of this, if we encounter unnormalized alias types inside this - // fudge scope, we might lose the relationships between them and other vars - // when fudging inference variables created here. - // So, we utilize generalization to normalize aliases by adding a new - // inference var and equating it with the type we want to pull out of the - // fudge scope. - formal_input_tys_ns = formal_input_tys - .iter() - .map(|&ty| { - // If we replace a (unresolved) inference var with a new inference - // var, it will be eventually resolved to itself and this will - // weaken type inferences as the new inference var will be fudged - // out and lose all relationships with other vars while the former - // will not be fudged. - if ty.is_ty_var() { - return ty; - } - - let generalized_ty = self.next_ty_var(call_span); - ocx.eq(&origin, self.param_env, ty, generalized_ty).unwrap(); - generalized_ty - }) - .collect_vec(); - - formal_input_tys_ns.as_slice() - } else { - formal_input_tys - }; - // Check the well-formedness of expected input tys, as using ill-formed - // expectation may cause type inference errors. + // expectation may cause type inference errors, see #150316. for &ty in formal_input_tys { ocx.register_obligation(traits::Obligation::new( self.tcx, diff --git a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr index b6636d4de86eb..04c1aaa192ee3 100644 --- a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr +++ b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr @@ -1,8 +1,8 @@ error[E0284]: type annotations needed: cannot normalize ` as Object>::Output` - --> $DIR/indirect-impl-for-trait-obj-coherence.rs:25:41 + --> $DIR/indirect-impl-for-trait-obj-coherence.rs:25:5 | LL | foo::, U>(x) - | ^ cannot normalize ` as Object>::Output` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize ` as Object>::Output` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 381f5c60f9831..4f02a91ae8ee3 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -15,10 +15,10 @@ LL | | for<'a> *const T: ToUnit<'a>, = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details error[E0284]: type annotations needed: cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` - --> $DIR/associated-type.rs:45:59 + --> $DIR/associated-type.rs:45:5 | LL | foo:: fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); - | ^^^^^^ cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs index b2015b336b24a..1a00aef189d71 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs @@ -28,7 +28,7 @@ fn main() { let _ = identity(<() as Foo>::copy_me(&x)); //~^ ERROR overflow evaluating whether `<() as Foo>::Item` is well-formed //~| ERROR overflow evaluating whether `&<() as Foo>::Item` is well-formed - //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == String` + //~| ERROR overflow evaluating the requirement `String == <() as Foo>::Item` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr index ebfaf469ddf89..234f4269c0c02 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr @@ -12,11 +12,11 @@ LL | trait Foo { LL | type Item: Copy | ^^^^ this trait's associated type doesn't have the requirement `String: Copy` -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == String` - --> $DIR/alias-bound-unsound.rs:28:43 +error[E0275]: overflow evaluating the requirement `String == <() as Foo>::Item` + --> $DIR/alias-bound-unsound.rs:28:22 | LL | let _ = identity(<() as Foo>::copy_me(&x)); - | ^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` --> $DIR/alias-bound-unsound.rs:28:22 diff --git a/tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.stderr b/tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.stderr index e4775e41ba1a5..e23751168c0dd 100644 --- a/tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.stderr +++ b/tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.stderr @@ -4,7 +4,7 @@ error[E0308]: arguments to this function are incorrect LL | arg_error((), || ()); | ^^^^^^^^^ -- ----- expected `()`, found `{closure@$DIR/coerce-in-may-coerce.rs:17:19: 17:21}` | | - | expected `::Assoc`, found `()` + | expected `fn()`, found `()` | note: function defined here --> $DIR/coerce-in-may-coerce.rs:12:4 diff --git a/tests/ui/traits/next-solver/dyn-incompatibility.rs b/tests/ui/traits/next-solver/dyn-incompatibility.rs index a347984daf6a6..370bc410e12bb 100644 --- a/tests/ui/traits/next-solver/dyn-incompatibility.rs +++ b/tests/ui/traits/next-solver/dyn-incompatibility.rs @@ -11,7 +11,6 @@ fn copy(from: &U::From) -> U::From { pub fn copy_any(t: &T) -> T { copy::>(t) //~^ ERROR the trait bound `T: Copy` is not satisfied in `dyn Setup` - //~| ERROR mismatched types //~| ERROR the trait bound `T: Copy` is not satisfied // FIXME(-Znext-solver): These error messages are horrible and some of them diff --git a/tests/ui/traits/next-solver/dyn-incompatibility.stderr b/tests/ui/traits/next-solver/dyn-incompatibility.stderr index 6398fbddca5e5..4d51f1907775f 100644 --- a/tests/ui/traits/next-solver/dyn-incompatibility.stderr +++ b/tests/ui/traits/next-solver/dyn-incompatibility.stderr @@ -15,22 +15,6 @@ help: consider restricting type parameter `T` with trait `Copy` LL | pub fn copy_any(t: &T) -> T { | +++++++++++++++++++ -error[E0308]: mismatched types - --> $DIR/dyn-incompatibility.rs:12:31 - | -LL | copy::>(t) - | ------------------------- ^ types differ - | | - | arguments to this function are incorrect - | - = note: expected reference `& as Setup>::From` - found reference `&T` -note: function defined here - --> $DIR/dyn-incompatibility.rs:7:4 - | -LL | fn copy(from: &U::From) -> U::From { - | ^^^^ -------------- - error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup` --> $DIR/dyn-incompatibility.rs:12:5 | @@ -43,7 +27,6 @@ help: consider restricting type parameter `T` with trait `Copy` LL | pub fn copy_any(t: &T) -> T { | +++++++++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/fudge-inference/do-not-drop-ambig-normalization.rs b/tests/ui/traits/next-solver/fudge-inference/do-not-drop-ambig-normalization.rs new file mode 100644 index 0000000000000..cad5ccfdb1af9 --- /dev/null +++ b/tests/ui/traits/next-solver/fudge-inference/do-not-drop-ambig-normalization.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// A regression test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/259. +// We previously normalized inside of a call to `fn fudge_inference_if_ok`. If that normalization +// ended up ambiguous, we'd drop the normalization goal and return an unconstrained infer var. +// +// This meant that even though `DB::MetadataLookup` could be normalized after equating the +// receiver with the self type, at this point the normalization goal was no longer around. + +trait BindCollector { + fn push_bound_value(self, metadata_lookup: &DB::MetadataLookup); +} + +trait Backend { + type BindCollector; + type MetadataLookup; +} + +fn foo>>( + collector: DB::BindCollector, + metadata_lookup: &&DB::MetadataLookup, +) { + collector.push_bound_value(metadata_lookup) +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-1.rs b/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-1.rs index 3189ad811df67..8713e288ad107 100644 --- a/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-1.rs +++ b/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-1.rs @@ -2,8 +2,8 @@ //@ check-pass // A regression test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/252. -// `fn fudge_inference_if_ok` might lose relationships between ty vars so we need to normalize -// them inside the fudge scope. +// `fn fudge_inference_if_ok` might lose relationships between ty vars so we need to make sure +// there'll be no ambiguous aliases referencing infer vars from inside of the fudge scope. trait Trait { type Assoc; diff --git a/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-2.rs b/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-2.rs index 9c8e184e879a5..4b8384a6b6460 100644 --- a/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-2.rs +++ b/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-2.rs @@ -2,8 +2,8 @@ //@ check-pass // A regression test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/252. -// `fn fudge_inference_if_ok` might lose relationships between ty vars so we need to normalize -// them inside the fudge scope. +// `fn fudge_inference_if_ok` might lose relationships between ty vars so we need to make sure +// there'll be no ambiguous aliases referencing infer vars from inside of the fudge scope. enum Either { Left(L), diff --git a/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-3.rs b/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-3.rs index 1383a0325a8e5..fb2087a2889a5 100644 --- a/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-3.rs +++ b/tests/ui/traits/next-solver/fudge-inference/fudge-inference-with-aliases-3.rs @@ -2,8 +2,8 @@ //@ check-pass // A regression test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/252. -// `fn fudge_inference_if_ok` might lose relationships between ty vars so we need to normalize -// them inside the fudge scope. +// `fn fudge_inference_if_ok` might lose relationships between ty vars so we need to make sure +// there'll be no ambiguous aliases referencing infer vars from inside of the fudge scope. pub struct Error; diff --git a/tests/ui/traits/next-solver/lazy-nested-obligations-2.rs b/tests/ui/traits/next-solver/lazy-nested-obligations-2.rs index 51b7f57f7e60c..d2ac3cecb443e 100644 --- a/tests/ui/traits/next-solver/lazy-nested-obligations-2.rs +++ b/tests/ui/traits/next-solver/lazy-nested-obligations-2.rs @@ -1,5 +1,8 @@ //@ compile-flags: -Znext-solver -//@ check-pass + +// FIXME(#149379): This fails on the old solver. The next solver used to accept it +// thanks to lazy normalization, but that behavior regressed when output expectation +// fudge handling was updated in #149320 and #150316. pub trait With { type F; @@ -13,10 +16,12 @@ fn f(_: &str) {} fn main() { let _: V = V(f); + //~^ ERROR: type mismatch pub struct V(::F); pub enum E3 { Var(::F), } let _: E3 = E3::Var(f); + //~^ ERROR: type mismatch } diff --git a/tests/ui/traits/next-solver/lazy-nested-obligations-2.stderr b/tests/ui/traits/next-solver/lazy-nested-obligations-2.stderr new file mode 100644 index 0000000000000..f290e3eddb86e --- /dev/null +++ b/tests/ui/traits/next-solver/lazy-nested-obligations-2.stderr @@ -0,0 +1,15 @@ +error[E0271]: type mismatch resolving `fn(&str) {f} == fn(&str)` + --> $DIR/lazy-nested-obligations-2.rs:18:21 + | +LL | let _: V = V(f); + | ^^^^ types differ + +error[E0271]: type mismatch resolving `fn(&str) {f} == fn(&str)` + --> $DIR/lazy-nested-obligations-2.rs:25:22 + | +LL | let _: E3 = E3::Var(f); + | ^^^^^^^^^^ types differ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. From 642f34880532ff758be2fab9cae7dd6d0681ef2a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 5 Apr 2026 20:07:50 +0200 Subject: [PATCH 07/16] Fix linking two dylibs together when both depend on profiler_builtins See the comment inside this commit for why. --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 ++- compiler/rustc_metadata/src/creader.rs | 9 +++++- .../duplicate-profiler-builtins/dylib_a.rs | 1 + .../duplicate-profiler-builtins/dylib_b.rs | 1 + .../duplicate-profiler-builtins/main.rs | 4 +++ .../duplicate-profiler-builtins/rmake.rs | 29 +++++++++++++++++++ 6 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 tests/run-make/duplicate-profiler-builtins/dylib_a.rs create mode 100644 tests/run-make/duplicate-profiler-builtins/dylib_b.rs create mode 100644 tests/run-make/duplicate-profiler-builtins/main.rs create mode 100644 tests/run-make/duplicate-profiler-builtins/rmake.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 20e75f0fdfd20..cb22aac4e952d 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2972,9 +2972,11 @@ fn add_upstream_rust_crates( // We must always link crates `compiler_builtins` and `profiler_builtins` statically. // Even if they were already included into a dylib // (e.g. `libstd` when `-C prefer-dynamic` is used). + // HACK: `dependency_formats` can report `profiler_builtins` as `NotLinked`. + // See the comment in inject_profiler_runtime for why this is the case. let linkage = data[cnum]; let link_static_crate = linkage == Linkage::Static - || linkage == Linkage::IncludedFromDylib + || (linkage == Linkage::IncludedFromDylib || linkage == Linkage::NotLinked) && (crate_info.compiler_builtins == Some(cnum) || crate_info.profiler_runtime == Some(cnum)); diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 3c8ea1a9f43d4..f36485cf03382 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1024,12 +1024,19 @@ impl CStore { info!("loading profiler"); + // HACK: This uses conditional despite actually being unconditional to ensure that + // there is no error emitted when two dylibs independently depend on profiler_builtins. + // This is fine as profiler_builtins is always statically linked into the dylib just + // like compiler_builtins. Unlike compiler_builtins however there is no guaranteed + // common dylib that the duplicate crate check believes the crate to be included in. + // add_upstream_rust_crates has a corresponding check that forces profiler_builtins + // to be statically linked in even when marked as NotLinked. let name = Symbol::intern(&tcx.sess.opts.unstable_opts.profiler_runtime); let Some(cnum) = self.resolve_crate( tcx, name, DUMMY_SP, - CrateDepKind::Unconditional, + CrateDepKind::Conditional, CrateOrigin::Injected, ) else { return; diff --git a/tests/run-make/duplicate-profiler-builtins/dylib_a.rs b/tests/run-make/duplicate-profiler-builtins/dylib_a.rs new file mode 100644 index 0000000000000..6833f39199943 --- /dev/null +++ b/tests/run-make/duplicate-profiler-builtins/dylib_a.rs @@ -0,0 +1 @@ +pub fn something() {} diff --git a/tests/run-make/duplicate-profiler-builtins/dylib_b.rs b/tests/run-make/duplicate-profiler-builtins/dylib_b.rs new file mode 100644 index 0000000000000..b56f00f19d586 --- /dev/null +++ b/tests/run-make/duplicate-profiler-builtins/dylib_b.rs @@ -0,0 +1 @@ +pub fn something_else() {} diff --git a/tests/run-make/duplicate-profiler-builtins/main.rs b/tests/run-make/duplicate-profiler-builtins/main.rs new file mode 100644 index 0000000000000..78677b37b5f74 --- /dev/null +++ b/tests/run-make/duplicate-profiler-builtins/main.rs @@ -0,0 +1,4 @@ +fn main() { + dylib_a::something(); + dylib_b::something_else(); +} diff --git a/tests/run-make/duplicate-profiler-builtins/rmake.rs b/tests/run-make/duplicate-profiler-builtins/rmake.rs new file mode 100644 index 0000000000000..2dc53d0ee59d0 --- /dev/null +++ b/tests/run-make/duplicate-profiler-builtins/rmake.rs @@ -0,0 +1,29 @@ +// Checks that two dylibs compiled with code coverage enabled can be linked +// together without getting an error about duplicate profiler_builtins. + +//@ needs-profiler-runtime + +use run_make_support::{dynamic_lib_name, rustc}; + +fn main() { + rustc() + .crate_name("dylib_a") + .crate_type("dylib") + .arg("-Cinstrument-coverage") + .arg("-Cprefer-dynamic") + .input("dylib_a.rs") + .run(); + rustc() + .crate_name("dylib_b") + .crate_type("dylib") + .arg("-Cinstrument-coverage") + .arg("-Cprefer-dynamic") + .input("dylib_b.rs") + .run(); + rustc() + .crate_type("bin") + .extern_("dylib_a", dynamic_lib_name("dylib_a")) + .extern_("dylib_b", dynamic_lib_name("dylib_b")) + .input("main.rs") + .run(); +} From 923311c40bc6fdc88cc5cfa3dd47b3392001d1a5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 8 Apr 2026 17:59:14 +0200 Subject: [PATCH 08/16] min/max_by tests: also check result --- library/coretests/tests/cmp.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/coretests/tests/cmp.rs b/library/coretests/tests/cmp.rs index 888a3cfd57a85..bb350b1d59fef 100644 --- a/library/coretests/tests/cmp.rs +++ b/library/coretests/tests/cmp.rs @@ -52,30 +52,33 @@ fn test_ord_min_max_by() { #[test] fn min_by_compare_argument_order() { let mut order = vec![]; - let _ = cmp::min_by(1i32, 2, |a, b| { + let res = cmp::min_by(1i32, 2, |a, b| { order.push((*a, *b)); a.cmp(b) }); + assert_eq!(res, 1); assert_eq!(order, [(1, 2)]); } #[test] fn max_by_compare_argument_order() { let mut order = vec![]; - let _ = cmp::max_by(1i32, 2, |a, b| { + let res = cmp::max_by(1i32, 2, |a, b| { order.push((*a, *b)); a.cmp(b) }); + assert_eq!(res, 2); assert_eq!(order, [(1, 2)]); } #[test] fn minmax_by_compare_argument_order() { let mut order = vec![]; - let _ = cmp::minmax_by(1i32, 2, |a, b| { + let res = cmp::minmax_by(1i32, 2, |a, b| { order.push((*a, *b)); a.cmp(b) }); + assert_eq!(res, [1, 2]); assert_eq!(order, [(1, 2)]); } From bec43041b36684975a067e1530b251371741b1b8 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 9 Apr 2026 01:57:29 +0900 Subject: [PATCH 09/16] Clarify old solver behavior with revisions in a test --- .../lazy-nested-obligations-2.current.stderr | 31 +++++++++++++++++++ ... => lazy-nested-obligations-2.next.stderr} | 4 +-- .../next-solver/lazy-nested-obligations-2.rs | 10 +++--- 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 tests/ui/traits/next-solver/lazy-nested-obligations-2.current.stderr rename tests/ui/traits/next-solver/{lazy-nested-obligations-2.stderr => lazy-nested-obligations-2.next.stderr} (81%) diff --git a/tests/ui/traits/next-solver/lazy-nested-obligations-2.current.stderr b/tests/ui/traits/next-solver/lazy-nested-obligations-2.current.stderr new file mode 100644 index 0000000000000..ba8d29263b747 --- /dev/null +++ b/tests/ui/traits/next-solver/lazy-nested-obligations-2.current.stderr @@ -0,0 +1,31 @@ +error[E0271]: type mismatch resolving `::F == fn(&str) {f}` + --> $DIR/lazy-nested-obligations-2.rs:20:21 + | +LL | let _: V = V(f); + | ^^^^ type mismatch resolving `::F == fn(&str) {f}` + | +note: expected this to be `for<'a> fn(&'a str) {f}` + --> $DIR/lazy-nested-obligations-2.rs:14:14 + | +LL | type F = fn(&str); + | ^^^^^^^^ + = note: expected fn item `for<'a> fn(&'a _) {f}` + found fn pointer `for<'a> fn(&'a _)` + +error[E0271]: type mismatch resolving `::F == fn(&str) {f}` + --> $DIR/lazy-nested-obligations-2.rs:27:22 + | +LL | let _: E3 = E3::Var(f); + | ^^^^^^^^^^ type mismatch resolving `::F == fn(&str) {f}` + | +note: expected this to be `for<'a> fn(&'a str) {f}` + --> $DIR/lazy-nested-obligations-2.rs:14:14 + | +LL | type F = fn(&str); + | ^^^^^^^^ + = note: expected fn item `for<'a> fn(&'a _) {f}` + found fn pointer `for<'a> fn(&'a _)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/lazy-nested-obligations-2.stderr b/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr similarity index 81% rename from tests/ui/traits/next-solver/lazy-nested-obligations-2.stderr rename to tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr index f290e3eddb86e..2e58377876e1d 100644 --- a/tests/ui/traits/next-solver/lazy-nested-obligations-2.stderr +++ b/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr @@ -1,11 +1,11 @@ error[E0271]: type mismatch resolving `fn(&str) {f} == fn(&str)` - --> $DIR/lazy-nested-obligations-2.rs:18:21 + --> $DIR/lazy-nested-obligations-2.rs:20:21 | LL | let _: V = V(f); | ^^^^ types differ error[E0271]: type mismatch resolving `fn(&str) {f} == fn(&str)` - --> $DIR/lazy-nested-obligations-2.rs:25:22 + --> $DIR/lazy-nested-obligations-2.rs:27:22 | LL | let _: E3 = E3::Var(f); | ^^^^^^^^^^ types differ diff --git a/tests/ui/traits/next-solver/lazy-nested-obligations-2.rs b/tests/ui/traits/next-solver/lazy-nested-obligations-2.rs index d2ac3cecb443e..6ba3d01a49501 100644 --- a/tests/ui/traits/next-solver/lazy-nested-obligations-2.rs +++ b/tests/ui/traits/next-solver/lazy-nested-obligations-2.rs @@ -1,8 +1,10 @@ -//@ compile-flags: -Znext-solver +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver -// FIXME(#149379): This fails on the old solver. The next solver used to accept it -// thanks to lazy normalization, but that behavior regressed when output expectation -// fudge handling was updated in #149320 and #150316. +// FIXME(#149379): This was previously accepted by the next-solver, thanks to its +// lazy normalization. But it started failing after #150316 due to changes in +// output expectation fudging in #149320 and #150316. pub trait With { type F; From 77ea376be32f0f856372787a97d3cbe1610d7a3a Mon Sep 17 00:00:00 2001 From: Jose Date: Wed, 8 Apr 2026 12:58:26 -0400 Subject: [PATCH 10/16] renaming method is_impl_trait to is_opaque --- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 2 +- compiler/rustc_lint/src/traits.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 9b44034adc23b..b55506117c1dc 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -2167,7 +2167,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorG for def_id in visitor.opaques { let ty_span = tcx.def_span(def_id); if !seen.contains(&ty_span) { - let descr = if ty.is_impl_trait() { "opaque " } else { "" }; + let descr = if ty.is_opaque() { "opaque " } else { "" }; err.span_label(ty_span, format!("returning this {descr}type `{ty}`")); seen.insert(ty_span); } diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 9587b774c4ff2..f3d0b4d000c28 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -1462,7 +1462,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx && self .cx .structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), place_ty) - .is_impl_trait() + .is_opaque() { projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty }); } diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 99222742b65de..9c2aada46c415 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { let def_id = trait_predicate.trait_ref.def_id; if cx.tcx.is_lang_item(def_id, LangItem::Drop) { // Explicitly allow `impl Drop`, a drop-guards-as-unnameable-type pattern. - if trait_predicate.trait_ref.self_ty().is_impl_trait() { + if trait_predicate.trait_ref.self_ty().is_opaque() { continue; } let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return }; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 7b30723d291ce..08bfe15137a24 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1594,7 +1594,7 @@ impl<'tcx> Ty<'tcx> { } #[inline] - pub fn is_impl_trait(self) -> bool { + pub fn is_opaque(self) -> bool { matches!(self.kind(), Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. })) } From ba3b486c3c0724223b226a0b4ee32977e9cb4ffb Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Fri, 20 Feb 2026 00:02:46 +0900 Subject: [PATCH 11/16] Use the trait object's own bounds instead of goal when considering builtin object bounds --- .../rustc_next_trait_solver/src/coherence.rs | 2 +- .../src/solve/assembly/mod.rs | 18 +++++- .../src/solve/assembly/structural_traits.rs | 7 ++- .../src/solve/eval_ctxt/probe.rs | 21 ++++++- ...bject-projection-with-param-env-bound-1.rs | 24 ++++++++ ...bject-projection-with-param-env-bound-2.rs | 35 +++++++++++ ...on-with-unsatisfied-bound-1.current.stderr | 14 +++++ ...ction-with-unsatisfied-bound-1.next.stderr | 14 +++++ ...ect-projection-with-unsatisfied-bound-1.rs | 21 +++++++ ...on-with-unsatisfied-bound-2.current.stderr | 58 +++++++++++++++++++ ...ction-with-unsatisfied-bound-2.next.stderr | 58 +++++++++++++++++++ ...ect-projection-with-unsatisfied-bound-2.rs | 32 ++++++++++ 12 files changed, 297 insertions(+), 7 deletions(-) create mode 100644 tests/ui/traits/next-solver/object-projection-with-param-env-bound-1.rs create mode 100644 tests/ui/traits/next-solver/object-projection-with-param-env-bound-2.rs create mode 100644 tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.current.stderr create mode 100644 tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.next.stderr create mode 100644 tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.rs create mode 100644 tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.current.stderr create mode 100644 tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.next.stderr create mode 100644 tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.rs diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index c370fd24a1bb3..38ece587c3726 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -425,7 +425,7 @@ where } } ty::Dynamic(tt, ..) => { - let principal = tt.principal().map(|p| p.def_id()); + let principal = tt.principal_def_id(); if principal.is_some_and(|p| self.def_id_is_local(p)) { ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) } else { diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 32b1e93bf98be..be543835b9bc8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -88,10 +88,26 @@ where let ty::Dynamic(bounds, _) = goal.predicate.self_ty().kind() else { panic!("expected object type in `probe_and_consider_object_bound_candidate`"); }; + + let trait_ref = assumption.kind().map_bound(|clause| match clause { + ty::ClauseKind::Trait(pred) => pred.trait_ref, + ty::ClauseKind::Projection(proj) => proj.projection_term.trait_ref(cx), + + ty::ClauseKind::RegionOutlives(..) + | ty::ClauseKind::TypeOutlives(..) + | ty::ClauseKind::ConstArgHasType(..) + | ty::ClauseKind::WellFormed(..) + | ty::ClauseKind::ConstEvaluatable(..) + | ty::ClauseKind::HostEffect(..) + | ty::ClauseKind::UnstableFeature(..) => { + unreachable!("expected trait or projection predicate as an assumption") + } + }); + match structural_traits::predicates_for_object_candidate( ecx, goal.param_env, - goal.predicate.trait_ref(cx), + trait_ref, bounds, ) { Ok(requirements) => { diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index cd74e87b670f1..ad2721560d309 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -8,7 +8,7 @@ use rustc_type_ir::lang_items::{SolverLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::solve::inspect::ProbeKind; use rustc_type_ir::{ - self as ty, FallibleTypeFolder, Interner, Movability, Mutability, TypeFoldable, + self as ty, Binder, FallibleTypeFolder, Interner, Movability, Mutability, TypeFoldable, TypeSuperFoldable, Upcast as _, elaborate, }; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; @@ -856,7 +856,7 @@ pub(in crate::solve) fn const_conditions_for_destruct( pub(in crate::solve) fn predicates_for_object_candidate( ecx: &mut EvalCtxt<'_, D>, param_env: I::ParamEnv, - trait_ref: ty::TraitRef, + trait_ref: Binder>, object_bounds: I::BoundExistentialPredicates, ) -> Result>, Ambiguous> where @@ -864,6 +864,7 @@ where I: Interner, { let cx = ecx.cx(); + let trait_ref = ecx.instantiate_binder_with_infer(trait_ref); let mut requirements = vec![]; // Elaborating all supertrait outlives obligations here is not soundness critical, // since if we just used the unelaborated set, then the transitive supertraits would @@ -942,7 +943,7 @@ where && self .ecx .probe(|_| ProbeKind::ProjectionCompatibility) - .enter(|ecx| -> Result<_, NoSolution> { + .enter_without_propagated_nested_goals(|ecx| -> Result<_, NoSolution> { let source_projection = ecx.instantiate_binder_with_infer(source_projection); ecx.eq(self.param_env, source_projection.projection_term, target_projection)?; ecx.try_evaluate_added_goals() diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs index edf2a5d1ba8dc..8ef2dad78848e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs @@ -7,7 +7,8 @@ use tracing::instrument; use crate::delegate::SolverDelegate; use crate::solve::assembly::Candidate; use crate::solve::{ - BuiltinImplSource, CandidateSource, EvalCtxt, NoSolution, QueryResult, inspect, + BuiltinImplSource, CandidateSource, EvalCtxt, Goal, GoalSource, GoalStalledOn, NoSolution, + QueryResult, inspect, }; pub(in crate::solve) struct ProbeCtxt<'me, 'a, D, I, F, T> @@ -41,6 +42,22 @@ where } pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T) -> T { + let nested_goals = self.ecx.nested_goals.clone(); + self.enter_inner(f, nested_goals) + } + + pub(in crate::solve) fn enter_without_propagated_nested_goals( + self, + f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T, + ) -> T { + self.enter_inner(f, Default::default()) + } + + fn enter_inner( + self, + f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T, + propagated_nested_goals: Vec<(GoalSource, Goal, Option>)>, + ) -> T { let ProbeCtxt { ecx: outer, probe_kind, _result } = self; let delegate = outer.delegate; @@ -54,7 +71,7 @@ where initial_opaque_types_storage_num_entries: outer .initial_opaque_types_storage_num_entries, search_graph: outer.search_graph, - nested_goals: outer.nested_goals.clone(), + nested_goals: propagated_nested_goals, origin_span: outer.origin_span, tainted: outer.tainted, inspect: outer.inspect.take_and_enter_probe(), diff --git a/tests/ui/traits/next-solver/object-projection-with-param-env-bound-1.rs b/tests/ui/traits/next-solver/object-projection-with-param-env-bound-1.rs new file mode 100644 index 0000000000000..2231fa3958175 --- /dev/null +++ b/tests/ui/traits/next-solver/object-projection-with-param-env-bound-1.rs @@ -0,0 +1,24 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass + +// A regression test for https://github.com/rust-lang/rust/issues/152789. +// Ensures we do not trigger an ICE or compilation error when normalizing +// a projection on a trait object, where the matching trait predicate +// (with the same trait id as the object bound) originates from another +// source such as the param env, rather than from the object's own bounds. + +pub trait Trait { + type Assoc; +} + +pub trait Foo { + type FooAssoc; +} + +pub struct Wrap( as Trait>::Assoc) +where + dyn Trait: Trait; + +fn main() {} diff --git a/tests/ui/traits/next-solver/object-projection-with-param-env-bound-2.rs b/tests/ui/traits/next-solver/object-projection-with-param-env-bound-2.rs new file mode 100644 index 0000000000000..a1651404cf150 --- /dev/null +++ b/tests/ui/traits/next-solver/object-projection-with-param-env-bound-2.rs @@ -0,0 +1,35 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass + +// A regression test for https://github.com/rust-lang/rust/issues/152789. +// Ensures we do not trigger an ICE or compilation error when normalizing +// a projection on a trait object, where the matching trait predicate +// (with the same trait id as the object bound) originates from another +// source such as the param env, rather than from the object's own bounds. + +pub trait Trait { + type Assoc; +} + +pub trait Trait2 { + type Assoc2; +} + +impl Trait for U +where + U: Trait2, +{ + type Assoc = >::Assoc2; +} + +pub trait Foo { + type FooAssoc; +} + +pub struct Wrap( as Trait>::Assoc) +where + dyn Trait: Trait2; + +fn main() {} diff --git a/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.current.stderr b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.current.stderr new file mode 100644 index 0000000000000..a9a5bb42998aa --- /dev/null +++ b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.current.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `(dyn Trait + 'static): Trait<::FooAssoc>` is not satisfied + --> $DIR/object-projection-with-unsatisfied-bound-1.rs:18:25 + | +LL | pub struct Wrap( as Trait>::Assoc); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<::FooAssoc>` is not implemented for `(dyn Trait + 'static)` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub struct Wrap( as Trait>::Assoc) where (dyn Trait + 'static): Trait<::FooAssoc>; + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.next.stderr b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.next.stderr new file mode 100644 index 0000000000000..a9a5bb42998aa --- /dev/null +++ b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.next.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `(dyn Trait + 'static): Trait<::FooAssoc>` is not satisfied + --> $DIR/object-projection-with-unsatisfied-bound-1.rs:18:25 + | +LL | pub struct Wrap( as Trait>::Assoc); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<::FooAssoc>` is not implemented for `(dyn Trait + 'static)` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub struct Wrap( as Trait>::Assoc) where (dyn Trait + 'static): Trait<::FooAssoc>; + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.rs b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.rs new file mode 100644 index 0000000000000..95126bd20ce0d --- /dev/null +++ b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-1.rs @@ -0,0 +1,21 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +// A regression test for https://github.com/rust-lang/rust/issues/152789. +// Ensures we do not trigger an ICE when normalization fails for a +// projection on a trait object, even if the projection has the same +// trait id as the object's bound. + +pub trait Trait { + type Assoc; +} + +pub trait Foo { + type FooAssoc; +} + +pub struct Wrap( as Trait>::Assoc); +//~^ ERROR: the trait bound `(dyn Trait + 'static): Trait<::FooAssoc>` is not satisfied + +fn main() {} diff --git a/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.current.stderr b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.current.stderr new file mode 100644 index 0000000000000..06bbc51e03399 --- /dev/null +++ b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.current.stderr @@ -0,0 +1,58 @@ +error[E0277]: the trait bound `(dyn Callback + 'static): Foo` is not satisfied + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:20:14 + | +LL | impl Bar> { + | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback + 'static)` + | +help: this trait has no implementations, consider adding one + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:10:1 + | +LL | trait Foo { + | ^^^^^^^^^ +note: required by a bound in `Bar` + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:16:15 + | +LL | struct Bar { + | ^^^ required by this bound in `Bar` + +error[E0277]: the trait bound `(dyn Callback + 'static): Foo` is not satisfied + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:22:14 + | +LL | fn event(&self) { + | ^^^^^ the trait `Foo` is not implemented for `(dyn Callback + 'static)` + | +help: this trait has no implementations, consider adding one + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:10:1 + | +LL | trait Foo { + | ^^^^^^^^^ +note: required by a bound in `Bar` + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:16:15 + | +LL | struct Bar { + | ^^^ required by this bound in `Bar` + +error[E0277]: the trait bound `(dyn Callback + 'static): Foo` is not satisfied + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:24:9 + | +LL | (self.callback)(any(), any()); + | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback + 'static)` + | +help: this trait has no implementations, consider adding one + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:10:1 + | +LL | trait Foo { + | ^^^^^^^^^ + +error[E0618]: expected function, found `Box<(dyn Callback<(dyn Callback + 'static), Output = ()> + 'static)>` + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:24:9 + | +LL | (self.callback)(any(), any()); + | ^^^^^^^^^^^^^^^-------------- + | | + | call expression requires function + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0618. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.next.stderr b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.next.stderr new file mode 100644 index 0000000000000..b123a3d1d3e6b --- /dev/null +++ b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.next.stderr @@ -0,0 +1,58 @@ +error[E0277]: the trait bound `(dyn Callback + 'static): Foo` is not satisfied + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:20:14 + | +LL | impl Bar> { + | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback + 'static)` + | +help: this trait has no implementations, consider adding one + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:10:1 + | +LL | trait Foo { + | ^^^^^^^^^ +note: required by a bound in `Bar` + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:16:15 + | +LL | struct Bar { + | ^^^ required by this bound in `Bar` + +error[E0277]: the trait bound `(dyn Callback + 'static): Foo` is not satisfied + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:22:14 + | +LL | fn event(&self) { + | ^^^^^ the trait `Foo` is not implemented for `(dyn Callback + 'static)` + | +help: this trait has no implementations, consider adding one + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:10:1 + | +LL | trait Foo { + | ^^^^^^^^^ +note: required by a bound in `Bar` + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:16:15 + | +LL | struct Bar { + | ^^^ required by this bound in `Bar` + +error[E0618]: expected function, found `Box<(dyn Callback<(dyn Callback + 'static)> + 'static)>` + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:24:9 + | +LL | (self.callback)(any(), any()); + | ^^^^^^^^^^^^^^^-------------- + | | + | call expression requires function + +error[E0277]: the trait bound `(dyn Callback + 'static): Foo` is not satisfied + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:24:9 + | +LL | (self.callback)(any(), any()); + | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback + 'static)` + | +help: this trait has no implementations, consider adding one + --> $DIR/object-projection-with-unsatisfied-bound-2.rs:10:1 + | +LL | trait Foo { + | ^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0618. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.rs b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.rs new file mode 100644 index 0000000000000..7fa189f9aac8b --- /dev/null +++ b/tests/ui/traits/next-solver/object-projection-with-unsatisfied-bound-2.rs @@ -0,0 +1,32 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +// A regression test for https://github.com/rust-lang/rust/issues/151329. +// Ensures we do not trigger an ICE when normalization fails for a +// projection on a trait object, even if the projection has the same +// trait id as the object's bound. + +trait Foo { + type V; +} + +trait Callback: Fn(&T, &T::V) {} + +struct Bar { + callback: Box>, +} + +impl Bar> { + //~^ ERROR: the trait bound `(dyn Callback + 'static): Foo` is not satisfied + fn event(&self) { + //~^ ERROR: the trait bound `(dyn Callback + 'static): Foo` is not satisfied + (self.callback)(any(), any()); + //~^ ERROR: the trait bound `(dyn Callback + 'static): Foo` is not satisfied + //~| ERROR: expected function + } +} + +fn any() {} + +fn main() {} From c1ac7693f6d1637fbc512dc025f69ba2e1389e01 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Wed, 8 Apr 2026 15:55:00 -0400 Subject: [PATCH 12/16] Fix feature name for unstable `integer_extend_truncate` functions The feature name for the const unstable attribute was accidentally transposed when const traits were added. --- library/core/src/num/int_macros.rs | 8 ++++---- library/core/src/num/traits.rs | 8 ++++---- library/core/src/num/uint_macros.rs | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index b148c7578db26..6a403542dd237 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -3958,7 +3958,7 @@ macro_rules! int_impl { /// ``` #[must_use = "this returns the truncated value and does not modify the original"] #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] + #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] #[inline] pub const fn truncate(self) -> Target where Self: [const] traits::TruncateTarget @@ -3980,7 +3980,7 @@ macro_rules! int_impl { /// ``` #[must_use = "this returns the truncated value and does not modify the original"] #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] + #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] #[inline] pub const fn saturating_truncate(self) -> Target where Self: [const] traits::TruncateTarget @@ -4002,7 +4002,7 @@ macro_rules! int_impl { /// ``` #[must_use = "this returns the truncated value and does not modify the original"] #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] + #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] #[inline] pub const fn checked_truncate(self) -> Option where Self: [const] traits::TruncateTarget @@ -4021,7 +4021,7 @@ macro_rules! int_impl { /// ``` #[must_use = "this returns the extended value and does not modify the original"] #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] + #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] #[inline] pub const fn extend(self) -> Target where Self: [const] traits::ExtendTarget diff --git a/library/core/src/num/traits.rs b/library/core/src/num/traits.rs index 9ce4d878a6e09..92217a4817b49 100644 --- a/library/core/src/num/traits.rs +++ b/library/core/src/num/traits.rs @@ -3,7 +3,7 @@ /// Trait for types that this type can be truncated to #[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")] -#[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] +#[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] pub const trait TruncateTarget: crate::sealed::Sealed { #[doc(hidden)] fn internal_truncate(self) -> Target; @@ -17,7 +17,7 @@ pub const trait TruncateTarget: crate::sealed::Sealed { /// Trait for types that this type can be truncated to #[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")] -#[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] +#[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] pub const trait ExtendTarget: crate::sealed::Sealed { #[doc(hidden)] fn internal_extend(self) -> Target; @@ -40,7 +40,7 @@ macro_rules! impl_truncate { ); #[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")] - #[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] + #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] impl const TruncateTarget<$to> for $from { #[inline] fn internal_truncate(self) -> $to { @@ -87,7 +87,7 @@ macro_rules! impl_extend { ); #[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")] - #[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] + #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] impl const ExtendTarget<$to> for $from { fn internal_extend(self) -> $to { self as _ diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index e048f8f485390..c35deee920e46 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -4120,7 +4120,7 @@ macro_rules! uint_impl { /// ``` #[must_use = "this returns the truncated value and does not modify the original"] #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] + #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] #[inline] pub const fn truncate(self) -> Target where Self: [const] traits::TruncateTarget @@ -4140,7 +4140,7 @@ macro_rules! uint_impl { /// ``` #[must_use = "this returns the truncated value and does not modify the original"] #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] + #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] #[inline] pub const fn saturating_truncate(self) -> Target where Self: [const] traits::TruncateTarget @@ -4160,7 +4160,7 @@ macro_rules! uint_impl { /// ``` #[must_use = "this returns the truncated value and does not modify the original"] #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] + #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] #[inline] pub const fn checked_truncate(self) -> Option where Self: [const] traits::TruncateTarget @@ -4178,7 +4178,7 @@ macro_rules! uint_impl { /// ``` #[must_use = "this returns the extended value and does not modify the original"] #[unstable(feature = "integer_extend_truncate", issue = "154330")] - #[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")] + #[rustc_const_unstable(feature = "integer_extend_truncate", issue = "154330")] #[inline] pub const fn extend(self) -> Target where Self: [const] traits::ExtendTarget From e1d0fe5ceb1e75d1c5c3fb2244461aa973b65b0d Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 8 Apr 2026 16:25:40 -0400 Subject: [PATCH 13/16] meta: Add checkboxes to unsresolved questions in issue templates These frequently have links to comments on closed PRs, meaning it can looks like issues have been resolved even if that isn't the case. Add checkboxes to make it more clear when a conclusion has been reached. --- .github/ISSUE_TEMPLATE/library_tracking_issue.md | 2 +- .github/ISSUE_TEMPLATE/tracking_issue.md | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/library_tracking_issue.md b/.github/ISSUE_TEMPLATE/library_tracking_issue.md index de823dc300d15..89f6c3e136956 100644 --- a/.github/ISSUE_TEMPLATE/library_tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/library_tracking_issue.md @@ -83,6 +83,6 @@ It's useful to link any relevant discussions and conclusions (whether on GitHub, Zulip, or the internals forum) here. --> -- None yet. +- [ ] None yet. [^1]: https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html diff --git a/.github/ISSUE_TEMPLATE/tracking_issue.md b/.github/ISSUE_TEMPLATE/tracking_issue.md index 6def803b269e9..0e0fdc5ca864e 100644 --- a/.github/ISSUE_TEMPLATE/tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/tracking_issue.md @@ -55,11 +55,12 @@ for larger features an implementation could be broken up into multiple PRs. ### Unresolved Questions -XXX --- list all the "unresolved questions" found in the RFC to ensure they are -not forgotten +- [ ] list all the "unresolved questions" found in the RFC to ensure they are + not forgotten. ### Implementation history From 501480e15e1760915c645df499cd85018b2ffc59 Mon Sep 17 00:00:00 2001 From: Jose Date: Wed, 8 Apr 2026 16:58:59 -0400 Subject: [PATCH 14/16] fixing clippy reference --- src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs | 2 +- src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs index 367d98ece1951..0b38bdcdf5443 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs @@ -41,7 +41,7 @@ fn needs_turbofish<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) -> bool if !fn_return_ty .skip_binder() .walk() - .any(|generic| generic.as_type().is_some_and(Ty::is_impl_trait)) => + .any(|generic| generic.as_type().is_some_and(Ty::is_opaque)) => { return false; }, diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index c9fcc1bb6aba3..99c3266718436 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -207,7 +207,7 @@ fn fn_inputs_has_impl_trait_ty(cx: &LateContext<'_>, def_id: LocalDefId) -> bool inputs.iter().any(|input| { matches!( input.kind(), - &ty::Alias(ty::AliasTy { kind: ty::Free{def_id} , ..}) if cx.tcx.type_of(def_id).skip_binder().is_impl_trait() + &ty::Alias(ty::AliasTy { kind: ty::Free{def_id} , ..}) if cx.tcx.type_of(def_id).skip_binder().is_opaque() ) }) } From 2d33b30eb104342fc470ad05c0ea9c241f2ef418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 9 Apr 2026 01:08:52 +0200 Subject: [PATCH 15/16] Update tracking issue number of future-incompatibility lint `unstable_syntax_pre_expansion` --- compiler/rustc_lint_defs/src/builtin.rs | 10 +++++----- tests/ui/cfg/cfg-false-feature.stderr | 4 ++-- .../feature-gates/soft-feature-gate-auto_traits.stderr | 2 +- .../soft-feature-gate-box_patterns.stderr | 4 ++-- .../feature-gates/soft-feature-gate-decl_macro.stderr | 4 ++-- .../soft-feature-gate-negative_impls.stderr | 2 +- .../feature-gates/soft-feature-gate-trait_alias.stderr | 4 ++-- .../feature-gates/soft-feature-gate-try_blocks.stderr | 2 +- .../soft-syntax-gates-without-errors.stderr | 4 ++-- tests/ui/or-patterns/or-patterns-syntactic-pass.stderr | 2 +- tests/ui/pattern/rest-pat-syntactic.stderr | 4 ++-- .../soft-feature-gate-specialization.default.stderr | 10 +++++----- .../soft-feature-gate-specialization.min.stderr | 6 +++--- 13 files changed, 29 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index b3cac5a9f93db..4aff294aeac61 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3158,7 +3158,7 @@ declare_lint! { /// ### Example /// /// ```rust - /// #[cfg(FALSE)] + /// #[cfg(feature = "nightly")] /// macro foo() {} /// ``` /// @@ -3182,22 +3182,22 @@ declare_lint! { /// ( $($tokens:tt)* ) => { $($tokens)* } /// } /// - /// #[cfg(FALSE)] + /// #[cfg(feature = "nightly")] /// identity! { /// macro foo() {} /// } /// ``` /// /// This is a [future-incompatible] lint to transition this - /// to a hard error in the future. See [issue #65860] for more details. + /// to a hard error in the future. See [issue #154045] for more details. /// - /// [issue #65860]: https://github.com/rust-lang/rust/issues/65860 + /// [issue #154045]: https://github.com/rust-lang/rust/issues/154045 /// [future-incompatible]: ../index.md#future-incompatible-lints pub UNSTABLE_SYNTAX_PRE_EXPANSION, Warn, "unstable syntax can change at any point in the future, causing a hard error!", @future_incompatible = FutureIncompatibleInfo { - reason: fcw!(FutureReleaseError #65860), + reason: fcw!(FutureReleaseError #154045), }; } diff --git a/tests/ui/cfg/cfg-false-feature.stderr b/tests/ui/cfg/cfg-false-feature.stderr index 542aeaf5caf81..25c221369bcc9 100644 --- a/tests/ui/cfg/cfg-false-feature.stderr +++ b/tests/ui/cfg/cfg-false-feature.stderr @@ -8,7 +8,7 @@ LL | let box _ = Box::new(0); = help: add `#![feature(box_patterns)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: trait aliases are experimental --> $DIR/cfg-false-feature.rs:12:1 @@ -20,7 +20,7 @@ LL | trait A = Clone; = help: add `#![feature(trait_alias)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 2 warnings emitted diff --git a/tests/ui/feature-gates/soft-feature-gate-auto_traits.stderr b/tests/ui/feature-gates/soft-feature-gate-auto_traits.stderr index 20811aadda929..899db503eb2c3 100644 --- a/tests/ui/feature-gates/soft-feature-gate-auto_traits.stderr +++ b/tests/ui/feature-gates/soft-feature-gate-auto_traits.stderr @@ -8,7 +8,7 @@ LL | auto trait Foo {} = help: add `#![feature(auto_traits)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 1 warning emitted diff --git a/tests/ui/feature-gates/soft-feature-gate-box_patterns.stderr b/tests/ui/feature-gates/soft-feature-gate-box_patterns.stderr index a8399b5f01f88..2a191417d6e2d 100644 --- a/tests/ui/feature-gates/soft-feature-gate-box_patterns.stderr +++ b/tests/ui/feature-gates/soft-feature-gate-box_patterns.stderr @@ -8,7 +8,7 @@ LL | let box x; = help: add `#![feature(box_patterns)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: box pattern syntax is experimental --> $DIR/soft-feature-gate-box_patterns.rs:14:18 @@ -20,7 +20,7 @@ LL | let Packet { box x }; = help: add `#![feature(box_patterns)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 2 warnings emitted diff --git a/tests/ui/feature-gates/soft-feature-gate-decl_macro.stderr b/tests/ui/feature-gates/soft-feature-gate-decl_macro.stderr index 71521626f69bc..1162c9e36d2a2 100644 --- a/tests/ui/feature-gates/soft-feature-gate-decl_macro.stderr +++ b/tests/ui/feature-gates/soft-feature-gate-decl_macro.stderr @@ -8,7 +8,7 @@ LL | macro make() {} = help: add `#![feature(decl_macro)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: `macro` is experimental --> $DIR/soft-feature-gate-decl_macro.rs:13:1 @@ -20,7 +20,7 @@ LL | macro create { () => {} } = help: add `#![feature(decl_macro)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 2 warnings emitted diff --git a/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr b/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr index 35e125cb2d24c..361244ae63b30 100644 --- a/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr +++ b/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr @@ -8,7 +8,7 @@ LL | impl !Trait for () {} = help: add `#![feature(negative_impls)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 1 warning emitted diff --git a/tests/ui/feature-gates/soft-feature-gate-trait_alias.stderr b/tests/ui/feature-gates/soft-feature-gate-trait_alias.stderr index e50d4c36d1228..975b9dfb7f766 100644 --- a/tests/ui/feature-gates/soft-feature-gate-trait_alias.stderr +++ b/tests/ui/feature-gates/soft-feature-gate-trait_alias.stderr @@ -8,7 +8,7 @@ LL | trait Trait =; = help: add `#![feature(trait_alias)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: trait aliases are experimental --> $DIR/soft-feature-gate-trait_alias.rs:13:1 @@ -20,7 +20,7 @@ LL | trait Trait = Bound where T: Bound; = help: add `#![feature(trait_alias)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 2 warnings emitted diff --git a/tests/ui/feature-gates/soft-feature-gate-try_blocks.stderr b/tests/ui/feature-gates/soft-feature-gate-try_blocks.stderr index 2b20f40e09d07..360f517d0debc 100644 --- a/tests/ui/feature-gates/soft-feature-gate-try_blocks.stderr +++ b/tests/ui/feature-gates/soft-feature-gate-try_blocks.stderr @@ -8,7 +8,7 @@ LL | try {} = help: add `#![feature(try_blocks)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 1 warning emitted diff --git a/tests/ui/feature-gates/soft-syntax-gates-without-errors.stderr b/tests/ui/feature-gates/soft-syntax-gates-without-errors.stderr index 817e28570f21e..112245b273f99 100644 --- a/tests/ui/feature-gates/soft-syntax-gates-without-errors.stderr +++ b/tests/ui/feature-gates/soft-syntax-gates-without-errors.stderr @@ -8,7 +8,7 @@ LL | macro b() {} = help: add `#![feature(decl_macro)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: `macro` is experimental --> $DIR/soft-syntax-gates-without-errors.rs:21:5 @@ -20,7 +20,7 @@ LL | macro e() {} = help: add `#![feature(decl_macro)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 2 warnings emitted diff --git a/tests/ui/or-patterns/or-patterns-syntactic-pass.stderr b/tests/ui/or-patterns/or-patterns-syntactic-pass.stderr index a755342ecf3c3..828a395218fb6 100644 --- a/tests/ui/or-patterns/or-patterns-syntactic-pass.stderr +++ b/tests/ui/or-patterns/or-patterns-syntactic-pass.stderr @@ -8,7 +8,7 @@ LL | let (box 0 | 1); // Unstable; we *can* change the precedence if we want = help: add `#![feature(box_patterns)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 1 warning emitted diff --git a/tests/ui/pattern/rest-pat-syntactic.stderr b/tests/ui/pattern/rest-pat-syntactic.stderr index 4de2730518905..41bbfd67dab4c 100644 --- a/tests/ui/pattern/rest-pat-syntactic.stderr +++ b/tests/ui/pattern/rest-pat-syntactic.stderr @@ -8,7 +8,7 @@ LL | let box ..; = help: add `#![feature(box_patterns)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: box pattern syntax is experimental --> $DIR/rest-pat-syntactic.rs:62:17 @@ -20,7 +20,7 @@ LL | box .., = help: add `#![feature(box_patterns)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 2 warnings emitted diff --git a/tests/ui/specialization/soft-feature-gate-specialization.default.stderr b/tests/ui/specialization/soft-feature-gate-specialization.default.stderr index f5961090947ed..de79600612448 100644 --- a/tests/ui/specialization/soft-feature-gate-specialization.default.stderr +++ b/tests/ui/specialization/soft-feature-gate-specialization.default.stderr @@ -8,7 +8,7 @@ LL | default type Ty = (); = help: add `#![feature(specialization)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: specialization is experimental --> $DIR/soft-feature-gate-specialization.rs:24:5 @@ -20,7 +20,7 @@ LL | default const CT: () = (); = help: add `#![feature(specialization)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: specialization is experimental --> $DIR/soft-feature-gate-specialization.rs:40:1 @@ -32,7 +32,7 @@ LL | default impl Trait for () {} = help: add `#![feature(specialization)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: specialization is experimental --> $DIR/soft-feature-gate-specialization.rs:27:5 @@ -44,7 +44,7 @@ LL | default fn fn_(); = help: add `#![feature(specialization)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: specialization is experimental --> $DIR/soft-feature-gate-specialization.rs:35:1 @@ -56,7 +56,7 @@ LL | default fn fn_() {} = help: add `#![feature(specialization)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 5 warnings emitted diff --git a/tests/ui/specialization/soft-feature-gate-specialization.min.stderr b/tests/ui/specialization/soft-feature-gate-specialization.min.stderr index aa4ce0cc58be2..d5337488ef3f7 100644 --- a/tests/ui/specialization/soft-feature-gate-specialization.min.stderr +++ b/tests/ui/specialization/soft-feature-gate-specialization.min.stderr @@ -8,7 +8,7 @@ LL | default type Ty = (); = help: add `#![feature(specialization)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: specialization is experimental --> $DIR/soft-feature-gate-specialization.rs:24:5 @@ -20,7 +20,7 @@ LL | default const CT: () = (); = help: add `#![feature(specialization)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: specialization is experimental --> $DIR/soft-feature-gate-specialization.rs:40:1 @@ -32,7 +32,7 @@ LL | default impl Trait for () {} = help: add `#![feature(specialization)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error! - = note: for more information, see issue #65860 + = note: for more information, see issue #154045 warning: 3 warnings emitted From ee135be0415aa531339d2a536207f32b15a0acac Mon Sep 17 00:00:00 2001 From: cijiugechu Date: Wed, 8 Apr 2026 18:45:42 +0800 Subject: [PATCH 16/16] Fix ICE in next-solver TransmuteFrom candidate Treat TransmuteFrom goals with non-region inference variables as ambiguous before running transmutability, instead of computing layouts for unresolved types. The old solver already treated these goals as ambiguous, so only the next solver could hit this ICE. --- .../src/solve/trait_goals.rs | 6 +++++ .../transmute-from-async-closure.rs | 22 ++++++++++++++++++ .../transmute-from-async-closure.stderr | 23 +++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 tests/ui/traits/next-solver/transmute-from-async-closure.rs create mode 100644 tests/ui/traits/next-solver/transmute-from-async-closure.stderr diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 76ab5403a9c6b..44a570fc4fa79 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -665,6 +665,12 @@ where return Err(NoSolution); } + // Match the old solver by treating unresolved inference variables as + // ambiguous until `rustc_transmute` can compute their layout. + if goal.has_non_region_infer() { + return ecx.forced_ambiguity(MaybeCause::Ambiguity); + } + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let assume = ecx.structurally_normalize_const( goal.param_env, diff --git a/tests/ui/traits/next-solver/transmute-from-async-closure.rs b/tests/ui/traits/next-solver/transmute-from-async-closure.rs new file mode 100644 index 0000000000000..7c23ba5fc0f14 --- /dev/null +++ b/tests/ui/traits/next-solver/transmute-from-async-closure.rs @@ -0,0 +1,22 @@ +//! Regression test for . + +//@ edition:2024 +//@ compile-flags: -Znext-solver=globally + +#![feature(transmutability)] + +trait NodeImpl {} +struct Wrap(F, P); +impl Wrap { + fn new(_: F) -> Self { + loop {} + } +} + +impl NodeImpl for Wrap where F: std::mem::TransmuteFrom<()> {} +fn trigger_ice() { + let _: &dyn NodeImpl = &Wrap::<_, (i128,)>::new(async |_: &(), i128| 0); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/transmute-from-async-closure.stderr b/tests/ui/traits/next-solver/transmute-from-async-closure.stderr new file mode 100644 index 0000000000000..6de86b6dfaa48 --- /dev/null +++ b/tests/ui/traits/next-solver/transmute-from-async-closure.stderr @@ -0,0 +1,23 @@ +error[E0283]: type annotations needed + --> $DIR/transmute-from-async-closure.rs:18:29 + | +LL | let _: &dyn NodeImpl = &Wrap::<_, (i128,)>::new(async |_: &(), i128| 0); + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `F` declared on the struct `Wrap` + | + = note: cannot satisfy `{async closure@$DIR/transmute-from-async-closure.rs:18:53: 18:73}: TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` +note: required for `Wrap<{async closure@$DIR/transmute-from-async-closure.rs:18:53: 18:73}, (i128,)>` to implement `NodeImpl` + --> $DIR/transmute-from-async-closure.rs:16:12 + | +LL | impl NodeImpl for Wrap where F: std::mem::TransmuteFrom<()> {} + | ^^^^^^^^ ^^^^^^^^^^^^^ --------------------------- unsatisfied trait bound introduced here +note: required because it appears within the type `Wrap<{async closure@$DIR/transmute-from-async-closure.rs:18:53: 18:73}, (i128,)>` + --> $DIR/transmute-from-async-closure.rs:9:8 + | +LL | struct Wrap(F, P); + | ^^^^ + = note: required for `&Wrap<{async closure@$DIR/transmute-from-async-closure.rs:18:53: 18:73}, (i128,)>` to implement `CoerceUnsized<&dyn NodeImpl>` + = note: required for the cast from `&Wrap<{async closure@$DIR/transmute-from-async-closure.rs:18:53: 18:73}, (i128,)>` to `&dyn NodeImpl` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`.