Skip to content

Commit 5fa8209

Browse files
Clear response values for overflow in new solver
1 parent 1c42cb4 commit 5fa8209

File tree

4 files changed

+88
-9
lines changed

4 files changed

+88
-9
lines changed

compiler/rustc_trait_selection/src/solve/eval_ctxt.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use rustc_infer::infer::at::ToTrace;
33
use rustc_infer::infer::canonical::CanonicalVarValues;
44
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
55
use rustc_infer::infer::{
6-
DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, TyCtxtInferExt,
6+
DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, RegionVariableOrigin,
7+
TyCtxtInferExt,
78
};
89
use rustc_infer::traits::query::NoSolution;
910
use rustc_infer::traits::ObligationCause;
@@ -223,18 +224,20 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
223224
{
224225
debug!("rerunning goal to check result is stable");
225226
let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
226-
let canonical_response =
227+
let new_canonical_response =
227228
EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
228-
if !canonical_response.value.var_values.is_identity() {
229+
if !new_canonical_response.value.var_values.is_identity() {
229230
bug!(
230231
"unstable result: re-canonicalized goal={canonical_goal:#?} \
231-
response={canonical_response:#?}"
232+
first_response={canonical_response:#?} \
233+
second_response={new_canonical_response:#?}"
232234
);
233235
}
234-
if certainty != canonical_response.value.certainty {
236+
if certainty != new_canonical_response.value.certainty {
235237
bug!(
236238
"unstable certainty: {certainty:#?} re-canonicalized goal={canonical_goal:#?} \
237-
response={canonical_response:#?}"
239+
first_response={canonical_response:#?} \
240+
second_response={new_canonical_response:#?}"
238241
);
239242
}
240243
}
@@ -434,6 +437,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
434437
})
435438
}
436439

440+
pub(super) fn next_region_infer(&self) -> ty::Region<'tcx> {
441+
self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
442+
}
443+
437444
pub(super) fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
438445
self.infcx.next_const_var(
439446
ty,

compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_infer::infer::canonical::query_response::make_query_region_constraints
1616
use rustc_infer::infer::canonical::CanonicalVarValues;
1717
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
1818
use rustc_middle::traits::query::NoSolution;
19-
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
19+
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData, MaybeCause};
2020
use rustc_middle::ty::{self, BoundVar, GenericArgKind};
2121
use rustc_span::DUMMY_SP;
2222
use std::iter;
@@ -60,9 +60,38 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
6060

6161
let certainty = certainty.unify_with(goals_certainty);
6262

63-
let external_constraints = self.compute_external_query_constraints()?;
63+
let response = match certainty {
64+
Certainty::Yes | Certainty::Maybe(MaybeCause::Ambiguity) => {
65+
let external_constraints = self.compute_external_query_constraints()?;
66+
Response { var_values: self.var_values, external_constraints, certainty }
67+
}
68+
Certainty::Maybe(MaybeCause::Overflow) => {
69+
// If we have overflow, it's probable that we're substituting a type
70+
// into itself infinitely and any partial substitutions in the query
71+
// response are probably not useful anyways, so just return an empty
72+
// query response.
73+
Response {
74+
var_values: CanonicalVarValues {
75+
var_values: self.tcx().mk_substs_from_iter(
76+
self.var_values.var_values.iter().map(|arg| -> ty::GenericArg<'tcx> {
77+
match arg.unpack() {
78+
GenericArgKind::Lifetime(_) => self.next_region_infer().into(),
79+
GenericArgKind::Type(_) => self.next_ty_infer().into(),
80+
GenericArgKind::Const(ct) => {
81+
self.next_const_infer(ct.ty()).into()
82+
}
83+
}
84+
}),
85+
),
86+
},
87+
external_constraints: self
88+
.tcx()
89+
.mk_external_constraints(ExternalConstraintsData::default()),
90+
certainty,
91+
}
92+
}
93+
};
6494

65-
let response = Response { var_values: self.var_values, external_constraints, certainty };
6695
let canonical = Canonicalizer::canonicalize(
6796
self.infcx,
6897
CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// compile-flags: -Ztrait-solver=next
2+
3+
trait Trait {}
4+
5+
struct W<T>(T);
6+
7+
impl<T, U> Trait for W<(W<T>, W<U>)>
8+
where
9+
W<T>: Trait,
10+
W<U>: Trait,
11+
{
12+
}
13+
14+
fn impls<T: Trait>() {}
15+
16+
fn main() {
17+
impls::<W<_>>();
18+
//~^ ERROR type annotations needed
19+
//~| ERROR overflow evaluating the requirement `W<_>: Trait`
20+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/exponential-trait-goals.rs:17:5
3+
|
4+
LL | impls::<W<_>>();
5+
| ^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls`
6+
7+
error[E0275]: overflow evaluating the requirement `W<_>: Trait`
8+
--> $DIR/exponential-trait-goals.rs:17:5
9+
|
10+
LL | impls::<W<_>>();
11+
| ^^^^^^^^^^^^^
12+
|
13+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`exponential_trait_goals`)
14+
note: required by a bound in `impls`
15+
--> $DIR/exponential-trait-goals.rs:14:13
16+
|
17+
LL | fn impls<T: Trait>() {}
18+
| ^^^^^ required by this bound in `impls`
19+
20+
error: aborting due to 2 previous errors
21+
22+
Some errors have detailed explanations: E0275, E0282.
23+
For more information about an error, try `rustc --explain E0275`.

0 commit comments

Comments
 (0)