diff options
| author | Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> | 2023-03-29 14:07:29 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-29 14:07:29 +0530 |
| commit | 09e937744ad6e87e751fe874bd33e18e3f73c3f6 (patch) | |
| tree | d66516a3cc4847631464dd32e26218176511abda /compiler/rustc_trait_selection/src | |
| parent | a3eb2f0f222d628440975b58589fc75994403a97 (diff) | |
| parent | ef5f773bffdc2fb28bc833fa6132cbdade1dc549 (diff) | |
| download | rust-09e937744ad6e87e751fe874bd33e18e3f73c3f6.tar.gz rust-09e937744ad6e87e751fe874bd33e18e3f73c3f6.zip | |
Rollup merge of #109683 - compiler-errors:self-ty-overflow, r=lcnr
Check for overflow in `assemble_candidates_after_normalizing_self_ty` Prevents a stack overflow (:warning: :exclamation:) in the new solver when we have param-env candidates that look like: `T: Trait<Assoc = <T as Trait>::Assoc>` The current error message looks bad, but that's because we don't distinguish overflow and other ambiguity errors. I'll break that out into a separate PR since the fix may be controversial. r? `@lcnr`
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/assembly.rs | 50 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs | 21 |
2 files changed, 53 insertions, 18 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 4fb77d79518..0f7a0eb337b 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -1,5 +1,6 @@ //! Code shared by trait and projection goals for candidate assembly. +use super::search_graph::OverflowHandler; #[cfg(doc)] use super::trait_goals::structural_traits::*; use super::{EvalCtxt, SolverMode}; @@ -279,25 +280,38 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { return }; - self.probe(|ecx| { - let normalized_ty = ecx.next_ty_infer(); - let normalizes_to_goal = goal.with( - tcx, - ty::Binder::dummy(ty::ProjectionPredicate { - projection_ty, - term: normalized_ty.into(), - }), - ); - ecx.add_goal(normalizes_to_goal); - if let Ok(_) = ecx.try_evaluate_added_goals() { - let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty); - - // NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate. - // This doesn't work as long as we use `CandidateSource` in winnowing. - let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty)); - candidates.extend(ecx.assemble_and_evaluate_candidates(goal)); - } + let normalized_self_candidates: Result<_, NoSolution> = self.probe(|ecx| { + ecx.with_incremented_depth( + |ecx| { + let result = ecx.evaluate_added_goals_and_make_canonical_response( + Certainty::Maybe(MaybeCause::Overflow), + )?; + Ok(vec![Candidate { source: CandidateSource::BuiltinImpl, result }]) + }, + |ecx| { + let normalized_ty = ecx.next_ty_infer(); + let normalizes_to_goal = goal.with( + tcx, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty, + term: normalized_ty.into(), + }), + ); + ecx.add_goal(normalizes_to_goal); + let _ = ecx.try_evaluate_added_goals()?; + let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty); + // NOTE: Alternatively we could call `evaluate_goal` here and only + // have a `Normalized` candidate. This doesn't work as long as we + // use `CandidateSource` in winnowing. + let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty)); + Ok(ecx.assemble_and_evaluate_candidates(goal)) + }, + ) }); + + if let Ok(normalized_self_candidates) = normalized_self_candidates { + candidates.extend(normalized_self_candidates); + } } fn assemble_impl_candidates<G: GoalKind<'tcx>>( diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs b/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs index 7c9e63f529b..574f3e9a577 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs @@ -73,6 +73,27 @@ pub(in crate::solve) trait OverflowHandler<'tcx> { self.search_graph().overflow_data.deal_with_overflow(); on_overflow(self) } + + // Increment the `additional_depth` by one and evaluate `body`, or `on_overflow` + // if the depth is overflown. + fn with_incremented_depth<T>( + &mut self, + on_overflow: impl FnOnce(&mut Self) -> T, + body: impl FnOnce(&mut Self) -> T, + ) -> T { + let depth = self.search_graph().stack.len(); + self.search_graph().overflow_data.additional_depth += 1; + + let result = if self.search_graph().overflow_data.has_overflow(depth) { + self.search_graph().overflow_data.deal_with_overflow(); + on_overflow(self) + } else { + body(self) + }; + + self.search_graph().overflow_data.additional_depth -= 1; + result + } } impl<'tcx> OverflowHandler<'tcx> for EvalCtxt<'_, 'tcx> { |
