From a68644522ac3213857eda90029fbe1eb15cec779 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 15 Sep 2025 12:51:57 -0400 Subject: [PATCH] Dont bail in error predicate unless self ty is error --- .../src/solve/assembly/mod.rs | 5 +++-- .../src/solve/effect_goals.rs | 1 + .../src/solve/normalizes_to/mod.rs | 17 ++++++++++++++--- .../src/solve/trait_goals.rs | 1 + compiler/rustc_type_ir/src/ty_kind/closure.rs | 9 +++++++++ ...am-type-whensubstituting-in-region-112823.rs | 2 +- 6 files changed, 29 insertions(+), 6 deletions(-) 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 5a73c99616815..930d13c8d275b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -215,6 +215,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>; @@ -560,8 +561,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 aa49997253dc2..750f6cf4513ed 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -189,6 +189,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 d93b7843b2251..9d0187a81a83f 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 @@ -403,10 +403,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 b97d895bec15f..9f9e8d086136b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -125,6 +125,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 3b8ed0a15994d..b688a001f73fa 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -454,6 +454,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.rs b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs index dd94458d988e6..4c3ec862675aa 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 @@ -29,7 +29,7 @@ impl X for Y { fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} //~^ 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 _` [E0271] } pub fn main() {}