From aa8c14785c39a7e69b460ae68792dee2fe218e4a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 12:05:38 +0000 Subject: [PATCH 1/3] Add regression test --- .../self-referential-in-fn-trait.rs | 10 ++++++++++ .../self-referential-in-fn-trait.stderr | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs create mode 100644 tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.stderr diff --git a/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs new file mode 100644 index 0000000000000..cda403769ac44 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +type Foo<'a> = impl Fn() -> Foo<'a>; + +fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { + //~^ ERROR: overflow evaluating the requirement ` as FnOnce<()>>::Output == Foo<'a> + x +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.stderr b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.stderr new file mode 100644 index 0000000000000..08721d49db4f4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement ` as FnOnce<()>>::Output == Foo<'a>` + --> $DIR/self-referential-in-fn-trait.rs:5:40 + | +LL | fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. From 1474ee5238cc7f02349512155784ae4467947df7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 13:17:18 +0000 Subject: [PATCH 2/3] Don't try to prove opaque type bounds twice on the same types --- .../rustc_infer/src/infer/opaque_types.rs | 37 ++++++++++++------- .../tests/ui/new_ret_no_self_overflow.stderr | 23 +++++++++--- .../async-await/suggest-missing-await.stderr | 2 + tests/ui/parser/expr-as-stmt.stderr | 13 +++++-- tests/ui/type-alias-impl-trait/issue-63279.rs | 1 - .../type-alias-impl-trait/issue-63279.stderr | 14 ++----- .../self-referential-in-fn-trait.rs | 2 +- .../self-referential-in-fn-trait.stderr | 11 +++--- ...ue-90027-async-fn-return-suggestion.stderr | 7 +++- 9 files changed, 69 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 945136fbff2e9..b9d7f5762a648 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -508,7 +508,7 @@ impl<'tcx> InferCtxt<'tcx> { ) -> InferResult<'tcx, ()> { let mut obligations = Vec::new(); - self.insert_hidden_type( + let already_had_hidden_ty = self.insert_hidden_type( opaque_type_key, &cause, param_env, @@ -517,14 +517,21 @@ impl<'tcx> InferCtxt<'tcx> { &mut obligations, )?; - self.add_item_bounds_for_hidden_type( - opaque_type_key.def_id.to_def_id(), - opaque_type_key.args, - cause, - param_env, - hidden_ty, - &mut obligations, - ); + // If we already had a hidden type, that hidden type will + // have already gone through `add_item_bounds_for_hidden_type`. + // Since all the bounds must already hold for the previous hidden type + // and the new hidden type must be equal to the previous hidden type, + // we can conclude that the bounds must already hold. + if !already_had_hidden_ty { + self.add_item_bounds_for_hidden_type( + opaque_type_key.def_id.to_def_id(), + opaque_type_key.args, + cause, + param_env, + hidden_ty, + &mut obligations, + ); + } Ok(InferOk { value: (), obligations }) } @@ -544,7 +551,7 @@ impl<'tcx> InferCtxt<'tcx> { hidden_ty: Ty<'tcx>, a_is_expected: bool, obligations: &mut Vec>, - ) -> Result<(), TypeError<'tcx>> { + ) -> Result> { // Ideally, we'd get the span where *this specific `ty` came // from*, but right now we just use the span from the overall // value being folded. In simple cases like `-> impl Foo`, @@ -560,7 +567,8 @@ impl<'tcx> InferCtxt<'tcx> { cause.clone(), param_env, ty::PredicateKind::Ambiguous, - )) + )); + Ok(false) } else { let prev = self .inner @@ -573,10 +581,11 @@ impl<'tcx> InferCtxt<'tcx> { .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? .obligations, ); + Ok(true) + } else { + Ok(false) } - }; - - Ok(()) + } } pub fn add_item_bounds_for_hidden_type( diff --git a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr index babb634fdcd1a..55c7e4020ce0d 100644 --- a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr +++ b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr @@ -1,9 +1,20 @@ -error[E0275]: overflow evaluating the requirement `::Output == issue10041::X` - --> $DIR/new_ret_no_self_overflow.rs:20:25 +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self_overflow.rs:9:9 | -LL | pub fn new() -> X { - | ^ +LL | / pub fn new() -> impl PartialOrd { +LL | | 0i32 +LL | | } + | |_________^ + | + = note: `-D clippy::new-ret-no-self` implied by `-D warnings` + +error: methods called `new` usually return `Self` + --> $DIR/new_ret_no_self_overflow.rs:20:9 + | +LL | / pub fn new() -> X { +LL | | 0i32 +LL | | } + | |_________^ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/async-await/suggest-missing-await.stderr b/tests/ui/async-await/suggest-missing-await.stderr index f0ec34a6a5557..0f63d9a59cb1d 100644 --- a/tests/ui/async-await/suggest-missing-await.stderr +++ b/tests/ui/async-await/suggest-missing-await.stderr @@ -24,6 +24,8 @@ LL | take_u32(x.await) error[E0308]: mismatched types --> $DIR/suggest-missing-await.rs:22:5 | +LL | async fn suggest_await_in_async_fn_return() { + | - expected `()` because of return type LL | dummy() | ^^^^^^^ expected `()`, found future | diff --git a/tests/ui/parser/expr-as-stmt.stderr b/tests/ui/parser/expr-as-stmt.stderr index 18c8b0b7c506b..3cc2268ccf33e 100644 --- a/tests/ui/parser/expr-as-stmt.stderr +++ b/tests/ui/parser/expr-as-stmt.stderr @@ -81,9 +81,16 @@ error[E0308]: mismatched types --> $DIR/expr-as-stmt.rs:64:7 | LL | { foo() } || { true } - | ^^^^^- help: consider using a semicolon here: `;` - | | - | expected `()`, found `i32` + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | { foo(); } || { true } + | + +help: you might have meant to return this value + | +LL | { return foo(); } || { true } + | ++++++ + error[E0308]: mismatched types --> $DIR/expr-as-stmt.rs:8:6 diff --git a/tests/ui/type-alias-impl-trait/issue-63279.rs b/tests/ui/type-alias-impl-trait/issue-63279.rs index 0e46745c65cd6..212cc49575f6d 100644 --- a/tests/ui/type-alias-impl-trait/issue-63279.rs +++ b/tests/ui/type-alias-impl-trait/issue-63279.rs @@ -7,7 +7,6 @@ fn c() -> Closure { || -> Closure { || () } //~^ ERROR: mismatched types //~| ERROR: mismatched types - //~| ERROR: expected a `FnOnce<()>` closure, found `()` } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-63279.stderr b/tests/ui/type-alias-impl-trait/issue-63279.stderr index a4f6359b904c6..39282d75cc013 100644 --- a/tests/ui/type-alias-impl-trait/issue-63279.stderr +++ b/tests/ui/type-alias-impl-trait/issue-63279.stderr @@ -7,15 +7,6 @@ LL | fn c() -> Closure { = help: the trait `FnOnce<()>` is not implemented for `()` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` -error[E0277]: expected a `FnOnce<()>` closure, found `()` - --> $DIR/issue-63279.rs:7:11 - | -LL | || -> Closure { || () } - | ^^^^^^^ expected an `FnOnce<()>` closure, found `()` - | - = help: the trait `FnOnce<()>` is not implemented for `()` - = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` - error[E0308]: mismatched types --> $DIR/issue-63279.rs:7:21 | @@ -32,6 +23,9 @@ LL | || -> Closure { (|| ())() } error[E0308]: mismatched types --> $DIR/issue-63279.rs:7:5 | +LL | fn c() -> Closure { + | ------- expected `()` because of return type +LL | LL | || -> Closure { || () } | ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure | @@ -42,7 +36,7 @@ help: use parentheses to call this closure LL | (|| -> Closure { || () })() | + +++ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs index cda403769ac44..1eb68807e9d5b 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs +++ b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs @@ -1,9 +1,9 @@ #![feature(type_alias_impl_trait)] type Foo<'a> = impl Fn() -> Foo<'a>; +//~^ ERROR: unconstrained opaque type fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { - //~^ ERROR: overflow evaluating the requirement ` as FnOnce<()>>::Output == Foo<'a> x } diff --git a/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.stderr b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.stderr index 08721d49db4f4..236a8e899a8a9 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.stderr @@ -1,9 +1,10 @@ -error[E0275]: overflow evaluating the requirement ` as FnOnce<()>>::Output == Foo<'a>` - --> $DIR/self-referential-in-fn-trait.rs:5:40 +error: unconstrained opaque type + --> $DIR/self-referential-in-fn-trait.rs:3:16 | -LL | fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { - | ^^^^^^^ +LL | type Foo<'a> = impl Fn() -> Foo<'a>; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module error: aborting due to previous error -For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr index 0d72ae118f3aa..5af00480c2cb6 100644 --- a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr +++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr @@ -10,13 +10,18 @@ error[E0308]: mismatched types --> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5 | LL | async fn world() -> () { - | -- expected `()` because of return type + | -- + | | + | expected `()` because of return type + | expected `()` because of return type LL | 0 | ^ expected `()`, found integer error[E0308]: mismatched types --> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5 | +LL | async fn suggest_await_in_async_fn_return() { + | - expected `()` because of return type LL | hello() | ^^^^^^^ expected `()`, found future | From ab01463f48f497cd89772363ffdbaa52def6cc2e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 19:17:25 +0000 Subject: [PATCH 3/3] Show that the opaque type works in the new solver and is actually instantiatable --- ...=> self-referential-in-fn-trait.next.stderr} | 2 +- .../self-referential-in-fn-trait.old.stderr | 10 ++++++++++ .../self-referential-in-fn-trait.rs | 17 ++++++++++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) rename tests/ui/type-alias-impl-trait/{self-referential-in-fn-trait.stderr => self-referential-in-fn-trait.next.stderr} (83%) create mode 100644 tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.old.stderr diff --git a/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.stderr b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.next.stderr similarity index 83% rename from tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.stderr rename to tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.next.stderr index 236a8e899a8a9..b7c913eae003f 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.next.stderr @@ -1,5 +1,5 @@ error: unconstrained opaque type - --> $DIR/self-referential-in-fn-trait.rs:3:16 + --> $DIR/self-referential-in-fn-trait.rs:13:16 | LL | type Foo<'a> = impl Fn() -> Foo<'a>; | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.old.stderr b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.old.stderr new file mode 100644 index 0000000000000..b7c913eae003f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.old.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/self-referential-in-fn-trait.rs:13:16 + | +LL | type Foo<'a> = impl Fn() -> Foo<'a>; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs index 1eb68807e9d5b..89d4a0247a15a 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs +++ b/tests/ui/type-alias-impl-trait/self-referential-in-fn-trait.rs @@ -1,10 +1,25 @@ +//! This test checks that we do not +//! end up with an infinite recursion, +//! a cycle error or an overflow when +//! encountering an opaque type that has +//! an associated type that is just itself +//! again. + #![feature(type_alias_impl_trait)] +// revisions: next old working +//[next] compile-flags: -Ztrait-solver=next +//[working] check-pass type Foo<'a> = impl Fn() -> Foo<'a>; -//~^ ERROR: unconstrained opaque type +//[old,next]~^ ERROR: unconstrained opaque type fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { x } +#[cfg(working)] +fn foo<'a>() -> Foo<'a> { + foo +} + fn main() {}