Skip to content

Commit bf7dbff

Browse files
committed
instantiate canonical vars eagerly
1 parent b738b06 commit bf7dbff

File tree

11 files changed

+509
-496
lines changed

11 files changed

+509
-496
lines changed

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,17 +1106,6 @@ impl<'tcx, T> Binder<'tcx, T> {
11061106
if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
11071107
}
11081108

1109-
pub fn no_bound_vars_ignoring_escaping(self, tcx: TyCtxt<'tcx>) -> Option<T>
1110-
where
1111-
T: TypeFoldable<'tcx>,
1112-
{
1113-
if !self.0.has_escaping_bound_vars() {
1114-
Some(self.skip_binder())
1115-
} else {
1116-
self.0.try_fold_with(&mut SkipBindersAt { index: ty::INNERMOST, tcx }).ok()
1117-
}
1118-
}
1119-
11201109
/// Splits the contents into two things that share the same binder
11211110
/// level as the original, returning two distinct binders.
11221111
///

compiler/rustc_trait_selection/src/solve/assembly.rs

Lines changed: 27 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
11
//! Code shared by trait and projection goals for candidate assembly.
22
33
use super::infcx_ext::InferCtxtExt;
4-
use super::{
5-
instantiate_canonical_query_response, CanonicalGoal, CanonicalResponse, Certainty, EvalCtxt,
6-
Goal,
7-
};
4+
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal};
85
use rustc_hir::def_id::DefId;
9-
use rustc_infer::infer::TyCtxtInferExt;
10-
use rustc_infer::infer::{
11-
canonical::{CanonicalVarValues, OriginalQueryValues},
12-
InferCtxt,
13-
};
146
use rustc_infer::traits::query::NoSolution;
157
use rustc_middle::ty::TypeFoldable;
168
use rustc_middle::ty::{self, Ty, TyCtxt};
17-
use rustc_span::DUMMY_SP;
189
use std::fmt::Debug;
1910

2011
/// A candidate is a possible way to prove a goal.
@@ -40,7 +31,7 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy {
4031
fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId;
4132

4233
fn consider_impl_candidate(
43-
acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
34+
acx: &mut AssemblyCtxt<'_, '_, 'tcx, Self>,
4435
goal: Goal<'tcx, Self>,
4536
impl_def_id: DefId,
4637
);
@@ -49,21 +40,17 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy {
4940
/// An abstraction which correctly deals with the canonical results for candidates.
5041
///
5142
/// It also deduplicates the behavior between trait and projection predicates.
52-
pub(super) struct AssemblyCtxt<'a, 'tcx, G: GoalKind<'tcx>> {
53-
pub(super) cx: &'a mut EvalCtxt<'tcx>,
54-
pub(super) infcx: &'a InferCtxt<'tcx>,
55-
var_values: CanonicalVarValues<'tcx>,
43+
pub(super) struct AssemblyCtxt<'a, 'b, 'tcx, G: GoalKind<'tcx>> {
44+
pub(super) cx: &'a mut EvalCtxt<'b, 'tcx>,
5645
candidates: Vec<Candidate<'tcx, G>>,
5746
}
5847

59-
impl<'a, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'tcx, G> {
48+
impl<'a, 'b, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'b, 'tcx, G> {
6049
pub(super) fn assemble_and_evaluate_candidates(
61-
cx: &'a mut EvalCtxt<'tcx>,
62-
goal: CanonicalGoal<'tcx, G>,
50+
cx: &'a mut EvalCtxt<'b, 'tcx>,
51+
goal: Goal<'tcx, G>,
6352
) -> Vec<Candidate<'tcx, G>> {
64-
let (ref infcx, goal, var_values) =
65-
cx.tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
66-
let mut acx = AssemblyCtxt { cx, infcx, var_values, candidates: Vec::new() };
53+
let mut acx = AssemblyCtxt { cx, candidates: Vec::new() };
6754

6855
acx.assemble_candidates_after_normalizing_self_ty(goal);
6956

@@ -77,7 +64,7 @@ impl<'a, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'tcx, G> {
7764
source: G::CandidateSource,
7865
certainty: Certainty,
7966
) {
80-
match self.infcx.make_canonical_response(self.var_values.clone(), certainty) {
67+
match self.cx.make_canonical_response(certainty) {
8168
Ok(result) => self.candidates.push(Candidate { source, result }),
8269
Err(NoSolution) => debug!(?source, ?certainty, "failed leakcheck"),
8370
}
@@ -89,57 +76,46 @@ impl<'a, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'tcx, G> {
8976
/// self type to the list of candidates in case that succeeds. Note that we can't just eagerly return in
9077
/// this case as projections as self types add `
9178
fn assemble_candidates_after_normalizing_self_ty(&mut self, goal: Goal<'tcx, G>) {
92-
let tcx = self.cx.tcx;
79+
let tcx = self.cx.tcx();
80+
let infcx = self.cx.infcx;
9381
// FIXME: We also have to normalize opaque types, not sure where to best fit that in.
9482
let &ty::Alias(ty::Projection, projection_ty) = goal.predicate.self_ty().kind() else {
9583
return
9684
};
97-
self.infcx.probe(|_| {
98-
let normalized_ty = self.infcx.next_ty_infer();
85+
infcx.probe(|_| {
86+
let normalized_ty = infcx.next_ty_infer();
9987
let normalizes_to_goal = goal.with(
10088
tcx,
10189
ty::Binder::dummy(ty::ProjectionPredicate {
10290
projection_ty,
10391
term: normalized_ty.into(),
10492
}),
10593
);
106-
let normalization_certainty =
107-
match self.cx.evaluate_goal(&self.infcx, normalizes_to_goal) {
108-
Ok((_, certainty)) => certainty,
109-
Err(NoSolution) => return,
110-
};
94+
let normalization_certainty = match self.cx.evaluate_goal(normalizes_to_goal) {
95+
Ok((_, certainty)) => certainty,
96+
Err(NoSolution) => return,
97+
};
11198

11299
// NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate.
113100
// This doesn't work as long as we use `CandidateSource` in both winnowing and to resolve associated items.
114101
let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
115-
let mut orig_values = OriginalQueryValues::default();
116-
let goal = self.infcx.canonicalize_query(goal, &mut orig_values);
117102
let normalized_candidates =
118103
AssemblyCtxt::assemble_and_evaluate_candidates(self.cx, goal);
119-
120-
// Map each candidate from being canonical wrt the current inference context to being
121-
// canonical wrt the caller.
122-
for Candidate { source, result } in normalized_candidates {
123-
self.infcx.probe(|_| {
124-
let candidate_certainty =
125-
instantiate_canonical_query_response(&self.infcx, &orig_values, result);
126-
127-
// FIXME: This is a bit scary if the `normalizes_to_goal` overflows.
128-
//
129-
// If we have an ambiguous candidate it hides that normalization
130-
// caused an overflow which may cause issues.
131-
self.try_insert_candidate(
132-
source,
133-
normalization_certainty.unify_and(candidate_certainty),
134-
)
135-
})
104+
for mut normalized_candidate in normalized_candidates {
105+
normalized_candidate.result =
106+
normalized_candidate.result.unchecked_map(|mut response| {
107+
response.certainty = response.certainty.unify_and(normalization_certainty);
108+
response
109+
});
110+
self.candidates.push(normalized_candidate);
136111
}
137112
})
138113
}
139114

140115
fn assemble_impl_candidates(&mut self, goal: Goal<'tcx, G>) {
141-
self.cx.tcx.for_each_relevant_impl(
142-
goal.predicate.trait_def_id(self.cx.tcx),
116+
let tcx = self.cx.tcx();
117+
tcx.for_each_relevant_impl(
118+
goal.predicate.trait_def_id(tcx),
143119
goal.predicate.self_ty(),
144120
|impl_def_id| G::consider_impl_candidate(self, goal, impl_def_id),
145121
);

0 commit comments

Comments
 (0)