From eb3fdb2cee12a7fac53df4aa28046349185fa814 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 24 Dec 2025 21:55:37 +0900 Subject: [PATCH 1/3] 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 8ee77f8e64d77330d0346b368e134853842d253d Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 24 Dec 2025 22:08:23 +0900 Subject: [PATCH 2/3] Do not use ill-formed input expectations when checking function calls --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 18 ++++- ...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, 25 insertions(+), 217 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 c07cbfae256dd..1b800c725a944 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -305,7 +305,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .ok() }) - .unwrap_or_default(); + .unwrap_or_default() + .filter(|expected_input_tys: &Vec>| { + // Check the well-formedness of expected input tys, as using ill-formed + // expectation may cause type inference errors. + self.probe(|_| { + let ocx = ObligationCtxt::new(self); + for &ty in expected_input_tys { + ocx.register_obligation(traits::Obligation::new( + self.tcx, + self.misc(call_span), + self.param_env, + ty::ClauseKind::WellFormed(ty.into()), + )); + } + ocx.try_evaluate_obligations().is_empty() + }) + }); let mut err_code = E0061; 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 679a8e4980a0fe1e8641cd559222e88d434cbc0b Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 16 Dec 2025 15:14:29 +0100 Subject: [PATCH 3/3] fix fudging --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 65 +++++++++---------- ...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, 97 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 1b800c725a944..f518c9b909232 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -235,6 +235,38 @@ 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| { + // 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); + 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 @@ -257,39 +289,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // No argument expectations are produced if unification fails. 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 - }; - if !ocx.try_evaluate_obligations().is_empty() { return Err(TypeError::Mismatch); } 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 52794b19945b6..6d938e73a15f7 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 7b91078c639ed..3dc87f8d600e4 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 the requirement `<() as Foo>::Item well-formed` //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item 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 3509aea717ef6..8fb17bd5e7529 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..0636d8fd4d739 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: 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`.