Rollup merge of #148173 - tiif:fix-opaque-ice, r=BoxyUwU

Emit delayed bug during wfck for stranded opaque

Fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/235

## Problem

The fundamental issue here is ``OpaqueTypeCollector`` operates on ``rustc_middle::Ty``, but ``check_type_wf`` operates on HIR.

Since [check_type_wf](2f7620a5cc/compiler/rustc_hir_analysis/src/check/wfcheck.rs (L2262)) operates on HIR, it can see the stranded opaque and tries to infer it's hidden type. But ``OpaqueTypeCollector`` operates on ``rustc_middle::Ty``, so the ``OpaqueTypeCollector`` can no longer see a stranded opaque, hence its hidden type could not be inferred.

As a result, the tests ICE'ed at 34a8c7368c/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs (L253)

## Proposed solution

This PR detects stranded opaque types during wf check and emit a delayed bug for it.

## Alternative solution

`@BoxyUwU` and I had considered rewriting ``OpaqueTypeCollector`` to be a HIR visitor instead of a ``rustc_middle::Ty`` visitor, but we believe a HIR-based ``OpaqueTypeCollector`` will not work and might not worth the cost of rewriting.

## Acknowledgement

This PR is a joint effort with `@BoxyUwU` :3
This commit is contained in:
Matthias Krüger
2025-10-28 17:49:29 +01:00
committed by GitHub
3 changed files with 176 additions and 0 deletions

View File

@@ -242,6 +242,16 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
owner_def_id: LocalDefId,
opaque_types_from: DefiningScopeKind,
) -> Ty<'tcx> {
// When an opaque type is stranded, its hidden type cannot be inferred
// so we should not continue.
if !tcx.opaque_types_defined_by(owner_def_id).contains(&def_id) {
let opaque_type_span = tcx.def_span(def_id);
let guar = tcx
.dcx()
.span_delayed_bug(opaque_type_span, "cannot infer type for stranded opaque type");
return Ty::new_error(tcx, guar);
}
match opaque_types_from {
DefiningScopeKind::HirTypeck => {
let tables = tcx.typeck(owner_def_id);

View File

@@ -0,0 +1,50 @@
//@ compile-flags: -Znext-solver
#![feature(type_alias_impl_trait)]
use std::future::Future;
// Test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/235
// These are cases where an opaque types become "stranded" due to
// some errors. Make sure we don't ICE in either case.
// Case 1: `impl Send` is stranded
fn foo() -> impl ?Future<Output = impl Send> {
//~^ ERROR bound modifier `?` can only be applied to `Sized`
//~| ERROR bound modifier `?` can only be applied to `Sized`
()
}
// Case 2: `Assoc = impl Trait` is stranded
trait Trait {}
impl Trait for i32 {}
fn produce() -> impl Trait<Assoc = impl Trait> {
//~^ ERROR associated type `Assoc` not found for `Trait`
//~| ERROR associated type `Assoc` not found for `Trait`
16
}
// Case 3: `impl Trait` is stranded
fn ill_formed_string() -> String<impl Trait> {
//~^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied
String::from("a string")
}
// Case 4: TAIT variant of Case 1 to 3
type Foo = impl ?Future<Output = impl Send>;
//~^ ERROR unconstrained opaque type
//~| ERROR unconstrained opaque type
//~| ERROR bound modifier `?` can only be applied to `Sized`
//~| ERROR bound modifier `?` can only be applied to `Sized`
type Produce = impl Trait<Assoc = impl Trait>;
//~^ ERROR unconstrained opaque type
//~| ERROR unconstrained opaque type
//~| ERROR associated type `Assoc` not found for `Trait`
//~| ERROR associated type `Assoc` not found for `Trait`
type IllFormedString = String<impl Trait>;
//~^ ERROR unconstrained opaque type
//~| ERROR struct takes 0 generic arguments but 1 generic argument was supplied
fn main() {}

View File

@@ -0,0 +1,116 @@
error: bound modifier `?` can only be applied to `Sized`
--> $DIR/stranded_opaque.rs:11:18
|
LL | fn foo() -> impl ?Future<Output = impl Send> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0220]: associated type `Assoc` not found for `Trait`
--> $DIR/stranded_opaque.rs:21:28
|
LL | fn produce() -> impl Trait<Assoc = impl Trait> {
| ^^^^^ associated type `Assoc` not found
error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/stranded_opaque.rs:28:27
|
LL | fn ill_formed_string() -> String<impl Trait> {
| ^^^^^^------------ help: remove the unnecessary generics
| |
| expected 0 generic arguments
error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/stranded_opaque.rs:46:25
|
LL | type IllFormedString = String<impl Trait>;
| ^^^^^^------------ help: remove the unnecessary generics
| |
| expected 0 generic arguments
error: bound modifier `?` can only be applied to `Sized`
--> $DIR/stranded_opaque.rs:11:18
|
LL | fn foo() -> impl ?Future<Output = impl Send> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0220]: associated type `Assoc` not found for `Trait`
--> $DIR/stranded_opaque.rs:21:28
|
LL | fn produce() -> impl Trait<Assoc = impl Trait> {
| ^^^^^ associated type `Assoc` not found
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: unconstrained opaque type
--> $DIR/stranded_opaque.rs:34:12
|
LL | type Foo = impl ?Future<Output = impl Send>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `Foo` must be used in combination with a concrete type within the same crate
error: bound modifier `?` can only be applied to `Sized`
--> $DIR/stranded_opaque.rs:34:17
|
LL | type Foo = impl ?Future<Output = impl Send>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: bound modifier `?` can only be applied to `Sized`
--> $DIR/stranded_opaque.rs:34:17
|
LL | type Foo = impl ?Future<Output = impl Send>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: unconstrained opaque type
--> $DIR/stranded_opaque.rs:34:34
|
LL | type Foo = impl ?Future<Output = impl Send>;
| ^^^^^^^^^
|
= note: `Foo` must be used in combination with a concrete type within the same crate
error: unconstrained opaque type
--> $DIR/stranded_opaque.rs:40:17
|
LL | type Produce = impl Trait<Assoc = impl Trait>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `Produce` must be used in combination with a concrete type within the same crate
error[E0220]: associated type `Assoc` not found for `Trait`
--> $DIR/stranded_opaque.rs:40:28
|
LL | type Produce = impl Trait<Assoc = impl Trait>;
| ^^^^^ associated type `Assoc` not found
error[E0220]: associated type `Assoc` not found for `Trait`
--> $DIR/stranded_opaque.rs:40:28
|
LL | type Produce = impl Trait<Assoc = impl Trait>;
| ^^^^^ associated type `Assoc` not found
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: unconstrained opaque type
--> $DIR/stranded_opaque.rs:40:36
|
LL | type Produce = impl Trait<Assoc = impl Trait>;
| ^^^^^^^^^^
|
= note: `Produce` must be used in combination with a concrete type within the same crate
error: unconstrained opaque type
--> $DIR/stranded_opaque.rs:46:32
|
LL | type IllFormedString = String<impl Trait>;
| ^^^^^^^^^^
|
= note: `IllFormedString` must be used in combination with a concrete type within the same crate
error: aborting due to 15 previous errors
Some errors have detailed explanations: E0107, E0220.
For more information about an error, try `rustc --explain E0107`.