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 dea8096100cda..47efd33727dbd 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -199,6 +199,7 @@ where /// but prevents incorrect normalization while hiding any trait errors. fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, D>, + goal: Goal, guar: I::ErrorGuaranteed, ) -> Result, NoSolution>; @@ -539,8 +540,8 @@ where // Instead of adding the logic here, it's a better idea to add it in // `EvalCtxt::disqualify_auto_trait_candidate_due_to_possible_impl` in // `solve::trait_goals` instead. - let result = if let Err(guar) = goal.predicate.error_reported() { - G::consider_error_guaranteed_candidate(self, guar) + let result = if let ty::Error(guar) = goal.predicate.self_ty().kind() { + G::consider_error_guaranteed_candidate(self, goal, guar) } else if cx.trait_is_auto(trait_def_id) { G::consider_auto_trait_candidate(self, goal) } else if cx.trait_is_alias(trait_def_id) { diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 3e44ba689cd25..f5a6144bdbc25 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -182,6 +182,7 @@ where fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, D>, + _goal: Goal, _guar: I::ErrorGuaranteed, ) -> Result, NoSolution> { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 4deb6ed0bb81f..9b4c85e97fd51 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -396,10 +396,21 @@ where /// Fail to normalize if the predicate contains an error, alternatively, we could normalize to `ty::Error` /// and succeed. Can experiment with this to figure out what results in better error messages. fn consider_error_guaranteed_candidate( - _ecx: &mut EvalCtxt<'_, D>, - _guar: I::ErrorGuaranteed, + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + guar: I::ErrorGuaranteed, ) -> Result, NoSolution> { - Err(NoSolution) + let cx = ecx.cx(); + let error_term = match goal.predicate.alias.kind(cx) { + ty::AliasTermKind::ProjectionTy => Ty::new_error(cx, guar).into(), + ty::AliasTermKind::ProjectionConst => Const::new_error(cx, guar).into(), + kind => panic!("expected projection, found {kind:?}"), + }; + + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.instantiate_normalizes_to_term(goal, error_term); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } fn consider_auto_trait_candidate( 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..35cfc69db71c1 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -121,6 +121,7 @@ where fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, D>, + _goal: Goal, _guar: I::ErrorGuaranteed, ) -> Result, NoSolution> { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index e8f94c8e7cc92..67cc82346941a 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -462,6 +462,15 @@ impl CoroutineClosureSignature { coroutine_captures_by_ref_ty: I::Ty, env_region: I::Region, ) -> I::Ty { + // If either of the tupled capture types are constrained to error + // (e.g. during typeck when the infcx is tainted), then just return + // the error type directly. + if let ty::Error(_) = tupled_inputs_ty.kind() { + return tupled_inputs_ty; + } else if let ty::Error(_) = coroutine_captures_by_ref_ty.kind() { + return coroutine_captures_by_ref_ty; + } + match kind { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else { diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr index f2e249f2cbf99..ca2021a0816d5 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr @@ -31,19 +31,7 @@ error[E0271]: type mismatch resolving `::LineStreamFut<'a, Repr> normali LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ -error[E0271]: type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to _` - --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:73 - | -LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} - | ^^ types differ - -error[E0271]: type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to _` - --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:5 - | -LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0049, E0271, E0407. For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs index 7cf155ce01ef4..fe990ad283fc8 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs @@ -30,8 +30,6 @@ impl X for Y { //~^ ERROR method `line_stream` is not a member of trait `X` //[current]~^^ ERROR `()` is not a future //[next]~^^^ ERROR type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to ()` - //[next]~| ERROR type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to _` - //[next]~| ERROR type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to _` } pub fn main() {}