Skip to content

Commit 471f298

Browse files
committed
normalize correctly
1 parent 2f8c93e commit 471f298

File tree

3 files changed

+242
-78
lines changed

3 files changed

+242
-78
lines changed

compiler/rustc_next_trait_solver/src/placeholder.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,107 @@ where
162162
if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
163163
}
164164
}
165+
166+
/// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which
167+
/// they came.
168+
pub struct PlaceholderReplacer<'a, I: Interner> {
169+
cx: I,
170+
mapped_regions: IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
171+
mapped_types: IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
172+
mapped_consts: IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
173+
universe_indices: &'a [Option<ty::UniverseIndex>],
174+
current_index: ty::DebruijnIndex,
175+
}
176+
177+
impl<'a, I: Interner> PlaceholderReplacer<'a, I> {
178+
pub fn replace_placeholders<T: TypeFoldable<I>>(
179+
cx: I,
180+
mapped_regions: IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
181+
mapped_types: IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
182+
mapped_consts: IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
183+
universe_indices: &'a [Option<ty::UniverseIndex>],
184+
value: T,
185+
) -> T {
186+
let mut replacer = PlaceholderReplacer {
187+
cx,
188+
mapped_regions,
189+
mapped_types,
190+
mapped_consts,
191+
universe_indices,
192+
current_index: ty::INNERMOST,
193+
};
194+
value.fold_with(&mut replacer)
195+
}
196+
197+
fn debruijn_for_universe(&self, universe: ty::UniverseIndex) -> ty::DebruijnIndex {
198+
let index = self
199+
.universe_indices
200+
.iter()
201+
.position(|u| matches!(u, Some(u_idx) if *u_idx == universe))
202+
.unwrap_or_else(|| panic!("unexpected placeholder universe {universe:?}"));
203+
204+
ty::DebruijnIndex::from_usize(
205+
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
206+
)
207+
}
208+
}
209+
210+
impl<I: Interner> TypeFolder<I> for PlaceholderReplacer<'_, I> {
211+
fn cx(&self) -> I {
212+
self.cx
213+
}
214+
215+
fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
216+
if !t.has_placeholders() && !t.has_infer() {
217+
return t;
218+
}
219+
220+
self.current_index.shift_in(1);
221+
let t = t.super_fold_with(self);
222+
self.current_index.shift_out(1);
223+
t
224+
}
225+
226+
fn fold_region(&mut self, r: I::Region) -> I::Region {
227+
if let ty::RePlaceholder(p) = r.kind() {
228+
if let Some(replace_var) = self.mapped_regions.get(&p) {
229+
let db = self.debruijn_for_universe(p.universe());
230+
return Region::new_bound(self.cx(), db, *replace_var);
231+
}
232+
}
233+
234+
r
235+
}
236+
237+
fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
238+
if let ty::Placeholder(p) = ty.kind() {
239+
match self.mapped_types.get(&p) {
240+
Some(replace_var) => {
241+
let db = self.debruijn_for_universe(p.universe());
242+
Ty::new_bound(self.cx(), db, *replace_var)
243+
}
244+
None => ty,
245+
}
246+
} else if ty.has_placeholders() || ty.has_infer() {
247+
ty.super_fold_with(self)
248+
} else {
249+
ty
250+
}
251+
}
252+
253+
fn fold_const(&mut self, ct: I::Const) -> I::Const {
254+
if let ty::ConstKind::Placeholder(p) = ct.kind() {
255+
match self.mapped_consts.get(&p) {
256+
Some(replace_var) => {
257+
let db = self.debruijn_for_universe(p.universe());
258+
Const::new_bound(self.cx(), db, *replace_var)
259+
}
260+
None => ct,
261+
}
262+
} else if ct.has_placeholders() || ct.has_infer() {
263+
ct.super_fold_with(self)
264+
} else {
265+
ct
266+
}
267+
}
268+
}

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
33

44
#[cfg(feature = "nightly")]
55
use rustc_macros::HashStable_NoContext;
6-
use rustc_type_ir::data_structures::{HashMap, HashSet};
6+
use rustc_type_ir::data_structures::{HashMap, HashSet, IndexMap};
77
use rustc_type_ir::inherent::*;
88
use rustc_type_ir::relate::Relate;
99
use rustc_type_ir::relate::solver_relating::RelateExt;
@@ -420,18 +420,6 @@ where
420420
Ok(goal_evaluation)
421421
}
422422

423-
/// Evaluate `goal` without adding it to `nested_goals`.
424-
///
425-
/// This is intended for goal evaluation which should not affect the
426-
/// certainty of the currently evaluated goal.
427-
pub(super) fn try_evaluate_goal(
428-
&mut self,
429-
source: GoalSource,
430-
goal: Goal<I, I::Predicate>,
431-
) -> Result<GoalEvaluation<I>, NoSolution> {
432-
self.evaluate_goal(source, goal, None)
433-
}
434-
435423
/// Recursively evaluates `goal`, returning the nested goals in case
436424
/// the nested goal is a `NormalizesTo` goal.
437425
///
@@ -1201,6 +1189,19 @@ where
12011189
BoundVarReplacer::replace_bound_vars(&**self.delegate, universes, t).0
12021190
}
12031191

1192+
pub(super) fn replace_escaping_bound_vars<T: TypeFoldable<I>>(
1193+
&self,
1194+
value: T,
1195+
universes: &mut Vec<Option<ty::UniverseIndex>>,
1196+
) -> (
1197+
T,
1198+
IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
1199+
IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
1200+
IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
1201+
) {
1202+
BoundVarReplacer::replace_bound_vars(&**self.delegate, universes, value)
1203+
}
1204+
12041205
pub(super) fn may_use_unstable_feature(
12051206
&self,
12061207
param_env: I::ParamEnv,

0 commit comments

Comments
 (0)