From ef5f773bffdc2fb28bc833fa6132cbdade1dc549 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 27 Mar 2023 21:48:43 +0000 Subject: [PATCH] Check for overflow in assemble_candidates_after_normalizing_self_ty --- .../src/solve/assembly.rs | 50 ++++++++++++------- .../src/solve/search_graph/overflow.rs | 21 ++++++++ .../recursive-self-normalization-2.rs | 19 +++++++ .../recursive-self-normalization-2.stderr | 9 ++++ .../recursive-self-normalization.rs | 15 ++++++ .../recursive-self-normalization.stderr | 9 ++++ 6 files changed, 105 insertions(+), 18 deletions(-) create mode 100644 tests/ui/traits/new-solver/recursive-self-normalization-2.rs create mode 100644 tests/ui/traits/new-solver/recursive-self-normalization-2.stderr create mode 100644 tests/ui/traits/new-solver/recursive-self-normalization.rs create mode 100644 tests/ui/traits/new-solver/recursive-self-normalization.stderr diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 4fb77d795189d..0f7a0eb337ba6 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>( 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 7c9e63f529b55..574f3e9a5772d 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( + &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> { diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.rs b/tests/ui/traits/new-solver/recursive-self-normalization-2.rs new file mode 100644 index 0000000000000..7417d6018a131 --- /dev/null +++ b/tests/ui/traits/new-solver/recursive-self-normalization-2.rs @@ -0,0 +1,19 @@ +// compile-flags: -Ztrait-solver=next + +trait Foo1 { + type Assoc1; +} + +trait Foo2 { + type Assoc2; +} + +trait Bar {} +fn needs_bar() {} + +fn test::Assoc2> + Foo2::Assoc1>>() { + needs_bar::(); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr b/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr new file mode 100644 index 0000000000000..29cfa47a1050a --- /dev/null +++ b/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/recursive-self-normalization-2.rs:15:5 + | +LL | needs_bar::(); + | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `S` declared on the function `needs_bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.rs b/tests/ui/traits/new-solver/recursive-self-normalization.rs new file mode 100644 index 0000000000000..f3e3d71d813e4 --- /dev/null +++ b/tests/ui/traits/new-solver/recursive-self-normalization.rs @@ -0,0 +1,15 @@ +// compile-flags: -Ztrait-solver=next + +trait Foo { + type Assoc; +} + +trait Bar {} +fn needs_bar() {} + +fn test::Assoc>>() { + needs_bar::(); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.stderr b/tests/ui/traits/new-solver/recursive-self-normalization.stderr new file mode 100644 index 0000000000000..ba39981893d44 --- /dev/null +++ b/tests/ui/traits/new-solver/recursive-self-normalization.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/recursive-self-normalization.rs:11:5 + | +LL | needs_bar::(); + | ^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `S` declared on the function `needs_bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`.