Skip to content

Commit e192608

Browse files
committed
Add FromEnv for input types in the environment
1 parent 079b97c commit e192608

File tree

2 files changed

+69
-7
lines changed

2 files changed

+69
-7
lines changed

src/librustc/ty/query/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,6 @@ define_queries! { <'tcx>
377377
// might want to use `reveal_all()` method to change modes.
378378
[] fn param_env: ParamEnv(DefId) -> ty::ParamEnv<'tcx>,
379379

380-
// Get the chalk-style environment of the given item.
381-
[] fn environment: Environment(DefId) -> traits::Environment<'tcx>,
382-
383380
// Trait selection queries. These are best used by invoking `ty.moves_by_default()`,
384381
// `ty.is_copy()`, etc, since that will prune the environment where possible.
385382
[] fn is_copy_raw: is_copy_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
@@ -669,6 +666,9 @@ define_queries! { <'tcx>
669666
[] fn program_clauses_for_env: ProgramClausesForEnv(
670667
traits::Environment<'tcx>
671668
) -> Clauses<'tcx>,
669+
670+
// Get the chalk-style environment of the given item.
671+
[] fn environment: Environment(DefId) -> traits::Environment<'tcx>,
672672
},
673673

674674
Linking {

src/librustc_traits/lowering/environment.rs

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
4545

4646
// forall<'a, T> { `Outlives(T, 'a) :- FromEnv(&'a T)` }
4747
ty::Ref(_region, _sub_ty, ..) => {
48-
// FIXME: we need bound tys in order to write the above rule
48+
// FIXME: we'd need bound tys in order to properly write the above rule
4949
}
5050

5151
ty::Dynamic(..) => {
@@ -166,8 +166,9 @@ crate fn program_clauses_for_env<'a, 'tcx>(
166166

167167
crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Environment<'tcx> {
168168
use super::{Lower, IntoFromEnvGoal};
169+
use rustc::hir::{Node, TraitItemKind, ImplItemKind, ItemKind, ForeignItemKind};
169170

170-
// The environment of an impl Trait type is its defining function's environment
171+
// The environment of an impl Trait type is its defining function's environment.
171172
if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
172173
return environment(tcx, parent);
173174
}
@@ -178,10 +179,71 @@ crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> En
178179

179180
let clauses = predicates.into_iter()
180181
.map(|predicate| predicate.lower())
181-
.map(|domain_goal| domain_goal.map_bound(|dg| dg.into_from_env_goal()))
182-
.map(|domain_goal| domain_goal.map_bound(|dg| dg.into_program_clause()))
182+
.map(|domain_goal| domain_goal.map_bound(|bound| bound.into_from_env_goal()))
183+
.map(|domain_goal| domain_goal.map_bound(|bound| bound.into_program_clause()))
184+
185+
// `ForAll` because each `domain_goal` is a `PolyDomainGoal` and
186+
// could bound lifetimes.
183187
.map(Clause::ForAll);
184188

189+
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
190+
let node = tcx.hir.get(node_id);
191+
192+
let mut is_fn = false;
193+
let mut is_impl = false;
194+
match node {
195+
Node::TraitItem(item) => match item.node {
196+
TraitItemKind::Method(..) => is_fn = true,
197+
_ => (),
198+
}
199+
200+
Node::ImplItem(item) => match item.node {
201+
ImplItemKind::Method(..) => is_fn = true,
202+
_ => (),
203+
}
204+
205+
Node::Item(item) => match item.node {
206+
ItemKind::Impl(..) => is_impl = true,
207+
ItemKind::Fn(..) => is_fn = true,
208+
_ => (),
209+
}
210+
211+
Node::ForeignItem(item) => match item.node {
212+
ForeignItemKind::Fn(..) => is_fn = true,
213+
_ => (),
214+
}
215+
216+
// FIXME: closures?
217+
_ => (),
218+
}
219+
220+
let mut input_tys = FxHashSet::default();
221+
222+
// In an impl, we assume that the receiver type and all its constituents
223+
// are well-formed.
224+
if is_impl {
225+
let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
226+
input_tys.extend(trait_ref.self_ty().walk());
227+
}
228+
229+
// In an fn, we assume that the arguments and all their constitutents are
230+
// well-formed.
231+
if is_fn {
232+
let fn_sig = tcx.fn_sig(def_id)
233+
.no_late_bound_regions()
234+
.expect("only early bound regions");
235+
input_tys.extend(
236+
fn_sig.inputs().iter().flat_map(|ty| ty.walk())
237+
);
238+
}
239+
240+
let clauses = clauses.chain(
241+
input_tys.into_iter()
242+
.map(|ty| DomainGoal::FromEnv(FromEnv::Ty(ty)))
243+
.map(|domain_goal| domain_goal.into_program_clause())
244+
.map(Clause::Implies)
245+
);
246+
185247
Environment {
186248
clauses: tcx.mk_clauses(clauses),
187249
}

0 commit comments

Comments
 (0)