Skip to content

Commit ef5f773

Browse files
Check for overflow in assemble_candidates_after_normalizing_self_ty
1 parent bf57e8a commit ef5f773

File tree

6 files changed

+105
-18
lines changed

6 files changed

+105
-18
lines changed

Diff for: compiler/rustc_trait_selection/src/solve/assembly.rs

+32-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Code shared by trait and projection goals for candidate assembly.
22
3+
use super::search_graph::OverflowHandler;
34
#[cfg(doc)]
45
use super::trait_goals::structural_traits::*;
56
use super::{EvalCtxt, SolverMode};
@@ -279,25 +280,38 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
279280
return
280281
};
281282

282-
self.probe(|ecx| {
283-
let normalized_ty = ecx.next_ty_infer();
284-
let normalizes_to_goal = goal.with(
285-
tcx,
286-
ty::Binder::dummy(ty::ProjectionPredicate {
287-
projection_ty,
288-
term: normalized_ty.into(),
289-
}),
290-
);
291-
ecx.add_goal(normalizes_to_goal);
292-
if let Ok(_) = ecx.try_evaluate_added_goals() {
293-
let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty);
294-
295-
// NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate.
296-
// This doesn't work as long as we use `CandidateSource` in winnowing.
297-
let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
298-
candidates.extend(ecx.assemble_and_evaluate_candidates(goal));
299-
}
283+
let normalized_self_candidates: Result<_, NoSolution> = self.probe(|ecx| {
284+
ecx.with_incremented_depth(
285+
|ecx| {
286+
let result = ecx.evaluate_added_goals_and_make_canonical_response(
287+
Certainty::Maybe(MaybeCause::Overflow),
288+
)?;
289+
Ok(vec![Candidate { source: CandidateSource::BuiltinImpl, result }])
290+
},
291+
|ecx| {
292+
let normalized_ty = ecx.next_ty_infer();
293+
let normalizes_to_goal = goal.with(
294+
tcx,
295+
ty::Binder::dummy(ty::ProjectionPredicate {
296+
projection_ty,
297+
term: normalized_ty.into(),
298+
}),
299+
);
300+
ecx.add_goal(normalizes_to_goal);
301+
let _ = ecx.try_evaluate_added_goals()?;
302+
let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty);
303+
// NOTE: Alternatively we could call `evaluate_goal` here and only
304+
// have a `Normalized` candidate. This doesn't work as long as we
305+
// use `CandidateSource` in winnowing.
306+
let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
307+
Ok(ecx.assemble_and_evaluate_candidates(goal))
308+
},
309+
)
300310
});
311+
312+
if let Ok(normalized_self_candidates) = normalized_self_candidates {
313+
candidates.extend(normalized_self_candidates);
314+
}
301315
}
302316

303317
fn assemble_impl_candidates<G: GoalKind<'tcx>>(

Diff for: compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs

+21
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,27 @@ pub(in crate::solve) trait OverflowHandler<'tcx> {
7373
self.search_graph().overflow_data.deal_with_overflow();
7474
on_overflow(self)
7575
}
76+
77+
// Increment the `additional_depth` by one and evaluate `body`, or `on_overflow`
78+
// if the depth is overflown.
79+
fn with_incremented_depth<T>(
80+
&mut self,
81+
on_overflow: impl FnOnce(&mut Self) -> T,
82+
body: impl FnOnce(&mut Self) -> T,
83+
) -> T {
84+
let depth = self.search_graph().stack.len();
85+
self.search_graph().overflow_data.additional_depth += 1;
86+
87+
let result = if self.search_graph().overflow_data.has_overflow(depth) {
88+
self.search_graph().overflow_data.deal_with_overflow();
89+
on_overflow(self)
90+
} else {
91+
body(self)
92+
};
93+
94+
self.search_graph().overflow_data.additional_depth -= 1;
95+
result
96+
}
7697
}
7798

7899
impl<'tcx> OverflowHandler<'tcx> for EvalCtxt<'_, 'tcx> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// compile-flags: -Ztrait-solver=next
2+
3+
trait Foo1 {
4+
type Assoc1;
5+
}
6+
7+
trait Foo2 {
8+
type Assoc2;
9+
}
10+
11+
trait Bar {}
12+
fn needs_bar<S: Bar>() {}
13+
14+
fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
15+
needs_bar::<T::Assoc1>();
16+
//~^ ERROR type annotations needed
17+
}
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/recursive-self-normalization-2.rs:15:5
3+
|
4+
LL | needs_bar::<T::Assoc1>();
5+
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `S` declared on the function `needs_bar`
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0282`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// compile-flags: -Ztrait-solver=next
2+
3+
trait Foo {
4+
type Assoc;
5+
}
6+
7+
trait Bar {}
8+
fn needs_bar<S: Bar>() {}
9+
10+
fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
11+
needs_bar::<T::Assoc>();
12+
//~^ ERROR type annotations needed
13+
}
14+
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/recursive-self-normalization.rs:11:5
3+
|
4+
LL | needs_bar::<T::Assoc>();
5+
| ^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `S` declared on the function `needs_bar`
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)