Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 64aac8d

Browse files
committed
Replace type params with bound vars in rustc_traits::lowering
1 parent 485397e commit 64aac8d

File tree

4 files changed

+143
-61
lines changed

4 files changed

+143
-61
lines changed

src/librustc/ty/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ define_queries! { <'tcx>
687687
) -> Clauses<'tcx>,
688688

689689
// Get the chalk-style environment of the given item.
690-
[] fn environment: Environment(DefId) -> traits::Environment<'tcx>,
690+
[] fn environment: Environment(DefId) -> ty::Binder<traits::Environment<'tcx>>,
691691
},
692692

693693
Linking {

src/librustc/ty/subst.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,30 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
179179
})
180180
}
181181

182+
pub fn bound_vars_for_item(
183+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
184+
def_id: DefId
185+
) -> &'tcx Substs<'tcx> {
186+
Substs::for_item(tcx, def_id, |param, _| {
187+
match param.kind {
188+
ty::GenericParamDefKind::Type { .. } => {
189+
tcx.mk_ty(ty::Bound(ty::BoundTy {
190+
index: ty::INNERMOST,
191+
var: ty::BoundVar::from(param.index),
192+
kind: ty::BoundTyKind::Param(param.name),
193+
})).into()
194+
}
195+
196+
ty::GenericParamDefKind::Lifetime => {
197+
tcx.mk_region(ty::RegionKind::ReLateBound(
198+
ty::INNERMOST,
199+
ty::BoundRegion::BrNamed(param.def_id, param.name)
200+
)).into()
201+
}
202+
}
203+
})
204+
}
205+
182206
/// Creates a `Substs` for generic parameter definitions,
183207
/// by calling closures to obtain each kind.
184208
/// The closures get to observe the `Substs` as they're

src/librustc_traits/lowering/environment.rs

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,12 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
8888
ty::FnPtr(..) |
8989
ty::Tuple(..) |
9090
ty::Never |
91-
ty::Param(..) => (),
91+
ty::Infer(..) |
92+
ty::Bound(..) => (),
9293

9394
ty::GeneratorWitness(..) |
9495
ty::UnnormalizedProjection(..) |
95-
ty::Infer(..) |
96-
ty::Bound(..) |
96+
ty::Param(..) |
9797
ty::Error => {
9898
bug!("unexpected type {:?}", ty);
9999
}
@@ -173,21 +173,28 @@ crate fn program_clauses_for_env<'a, 'tcx>(
173173
);
174174
}
175175

176-
crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Environment<'tcx> {
176+
crate fn environment<'a, 'tcx>(
177+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
178+
def_id: DefId
179+
) -> ty::Binder<Environment<'tcx>> {
177180
use super::{Lower, IntoFromEnvGoal};
178181
use rustc::hir::{Node, TraitItemKind, ImplItemKind, ItemKind, ForeignItemKind};
182+
use rustc::ty::subst::{Subst, Substs};
179183

180184
// The environment of an impl Trait type is its defining function's environment.
181185
if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
182186
return environment(tcx, parent);
183187
}
184188

189+
let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
190+
185191
// Compute the bounds on `Self` and the type parameters.
186-
let ty::InstantiatedPredicates { predicates } =
187-
tcx.predicates_of(def_id).instantiate_identity(tcx);
192+
let ty::InstantiatedPredicates { predicates } = tcx.predicates_of(def_id)
193+
.instantiate_identity(tcx);
188194

189195
let clauses = predicates.into_iter()
190196
.map(|predicate| predicate.lower())
197+
.map(|predicate| predicate.subst(tcx, bound_vars))
191198
.map(|domain_goal| domain_goal.map_bound(|bound| bound.into_from_env_goal()))
192199
.map(|domain_goal| domain_goal.map_bound(|bound| bound.into_program_clause()))
193200

@@ -228,33 +235,43 @@ crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> En
228235

229236
let mut input_tys = FxHashSet::default();
230237

231-
// In an impl, we assume that the receiver type and all its constituents
238+
// In an impl, we assume that the header trait ref and all its constituents
232239
// are well-formed.
233240
if is_impl {
234-
let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
235-
input_tys.extend(trait_ref.self_ty().walk());
241+
let trait_ref = tcx.impl_trait_ref(def_id)
242+
.expect("not an impl")
243+
.subst(tcx, bound_vars);
244+
245+
input_tys.extend(
246+
trait_ref.substs.types().flat_map(|ty| ty.walk())
247+
);
236248
}
237249

238250
// In an fn, we assume that the arguments and all their constituents are
239251
// well-formed.
240252
if is_fn {
241-
let fn_sig = tcx.fn_sig(def_id);
253+
// `skip_binder` because we move late bound regions to the root binder,
254+
// restored in the return type
255+
let fn_sig = tcx.fn_sig(def_id).skip_binder().subst(tcx, bound_vars);
256+
242257
input_tys.extend(
243-
// FIXME: `skip_binder` seems ok for now? In a real setting,
244-
// the late bound regions would next be instantiated with things
245-
// in the inference table.
246-
fn_sig.skip_binder().inputs().iter().flat_map(|ty| ty.walk())
258+
fn_sig.inputs().iter().flat_map(|ty| ty.walk())
247259
);
248260
}
249261

250262
let clauses = clauses.chain(
251263
input_tys.into_iter()
264+
// Filter out type parameters
265+
.filter(|ty| match ty.sty {
266+
ty::Bound(..) => false,
267+
_ => true,
268+
})
252269
.map(|ty| DomainGoal::FromEnv(FromEnv::Ty(ty)))
253270
.map(|domain_goal| domain_goal.into_program_clause())
254271
.map(Clause::Implies)
255272
);
256273

257-
Environment {
274+
ty::Binder::bind(Environment {
258275
clauses: tcx.mk_clauses(clauses),
259-
}
276+
})
260277
}

0 commit comments

Comments
 (0)