diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index e4d94fd7beb..6f143c1c607 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -1034,10 +1034,6 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match *t.kind() { - // FIXME(chalk): currently we convert params to placeholders starting at - // index `0`. To support placeholders, we'll actually need to do a - // first pass to collect placeholders. Then we can insert params after. - ty::Placeholder(_) => unimplemented!(), ty::Param(param) => match self.list.iter().position(|r| r == ¶m) { Some(idx) => self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::from_usize(0), @@ -1053,15 +1049,15 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { })) } }, - _ => t.super_fold_with(self), } } fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { match r { - // FIXME(chalk) - jackh726 - this currently isn't hit in any tests. - // This covers any region variables in a goal, right? + // FIXME(chalk) - jackh726 - this currently isn't hit in any tests, + // since canonicalization will already change these to canonical + // variables (ty::ReLateBound). ty::ReEarlyBound(_re) => match self.named_regions.get(&_re.def_id) { Some(idx) => { let br = ty::BoundRegion { @@ -1084,6 +1080,39 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { } } +crate struct ReverseParamsSubstitutor<'tcx> { + tcx: TyCtxt<'tcx>, + params: rustc_data_structures::fx::FxHashMap, +} + +impl<'tcx> ReverseParamsSubstitutor<'tcx> { + crate fn new( + tcx: TyCtxt<'tcx>, + params: rustc_data_structures::fx::FxHashMap, + ) -> Self { + Self { tcx, params } + } +} + +impl<'tcx> TypeFolder<'tcx> for ReverseParamsSubstitutor<'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match *t.kind() { + ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, name }) => { + match self.params.get(&name.as_usize()) { + Some(param) => self.tcx.mk_ty(ty::Param(*param)), + None => t, + } + } + + _ => t.super_fold_with(self), + } + } +} + /// Used to collect `Placeholder`s. crate struct PlaceholdersCollector { universe_index: ty::UniverseIndex, diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs index 8c42b019554..3c2a266dab9 100644 --- a/compiler/rustc_traits/src/chalk/mod.rs +++ b/compiler/rustc_traits/src/chalk/mod.rs @@ -23,7 +23,7 @@ use rustc_infer::traits::{self, CanonicalChalkEnvironmentAndGoal}; use crate::chalk::db::RustIrDatabase as ChalkRustIrDatabase; use crate::chalk::lowering::LowerInto; -use crate::chalk::lowering::{ParamsSubstitutor, PlaceholdersCollector}; +use crate::chalk::lowering::{ParamsSubstitutor, PlaceholdersCollector, ReverseParamsSubstitutor}; use chalk_solve::Solution; @@ -44,7 +44,7 @@ crate fn evaluate_goal<'tcx>( let mut params_substitutor = ParamsSubstitutor::new(tcx, placeholders_collector.next_ty_placeholder); let obligation = obligation.fold_with(&mut params_substitutor); - let _params: FxHashMap = params_substitutor.params; + let params: FxHashMap = params_substitutor.params; let max_universe = obligation.max_universe.index(); @@ -101,8 +101,9 @@ crate fn evaluate_goal<'tcx>( use rustc_middle::infer::canonical::CanonicalVarInfo; let mut var_values: IndexVec> = IndexVec::new(); + let mut reverse_param_substitutor = ReverseParamsSubstitutor::new(tcx, params); subst.as_slice(interner).iter().for_each(|p| { - var_values.push(p.lower_into(interner)); + var_values.push(p.lower_into(interner).fold_with(&mut reverse_param_substitutor)); }); let variables: Vec<_> = binders .iter(interner)