]> git.lizzy.rs Git - rust.git/commitdiff
Add `FromEnv` for input types in the environment
authorscalexm <alexandre@scalexm.fr>
Thu, 11 Oct 2018 15:57:45 +0000 (17:57 +0200)
committerscalexm <alexandre@scalexm.fr>
Wed, 17 Oct 2018 12:09:39 +0000 (14:09 +0200)
src/librustc/ty/query/mod.rs
src/librustc_traits/lowering/environment.rs

index adb5883fd5e26eb13f602caf8a3331f94c22756b..b61bc8b4fd952a9820e15dae2df3ac0a8e000cfd 100644 (file)
         // might want to use `reveal_all()` method to change modes.
         [] fn param_env: ParamEnv(DefId) -> ty::ParamEnv<'tcx>,
 
-        // Get the chalk-style environment of the given item.
-        [] fn environment: Environment(DefId) -> traits::Environment<'tcx>,
-
         // Trait selection queries. These are best used by invoking `ty.moves_by_default()`,
         // `ty.is_copy()`, etc, since that will prune the environment where possible.
         [] fn is_copy_raw: is_copy_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
         [] fn program_clauses_for_env: ProgramClausesForEnv(
             traits::Environment<'tcx>
         ) -> Clauses<'tcx>,
+
+        // Get the chalk-style environment of the given item.
+        [] fn environment: Environment(DefId) -> traits::Environment<'tcx>,
     },
 
     Linking {
index 1774db3d85a8722f8f397b90fa292aedceae1cc4..1f3fec4699066d4c202fe5a1290c6a7e4e86fa0c 100644 (file)
@@ -45,7 +45,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) {
 
             // forall<'a, T> { `Outlives(T, 'a) :- FromEnv(&'a T)` }
             ty::Ref(_region, _sub_ty, ..) => {
-                // FIXME: we need bound tys in order to write the above rule
+                // FIXME: we'd need bound tys in order to properly write the above rule
             }
 
             ty::Dynamic(..) => {
@@ -166,8 +166,9 @@ fn visit_clause(&mut self, clause: Clause<'tcx>) {
 
 crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Environment<'tcx> {
     use super::{Lower, IntoFromEnvGoal};
+    use rustc::hir::{Node, TraitItemKind, ImplItemKind, ItemKind, ForeignItemKind};
 
-    // The environment of an impl Trait type is its defining function's environment
+    // The environment of an impl Trait type is its defining function's environment.
     if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
         return environment(tcx, parent);
     }
@@ -178,10 +179,71 @@ fn visit_clause(&mut self, clause: Clause<'tcx>) {
     
     let clauses = predicates.into_iter()
         .map(|predicate| predicate.lower())
-        .map(|domain_goal| domain_goal.map_bound(|dg| dg.into_from_env_goal()))
-        .map(|domain_goal| domain_goal.map_bound(|dg| dg.into_program_clause()))
+        .map(|domain_goal| domain_goal.map_bound(|bound| bound.into_from_env_goal()))
+        .map(|domain_goal| domain_goal.map_bound(|bound| bound.into_program_clause()))
+
+        // `ForAll` because each `domain_goal` is a `PolyDomainGoal` and
+        // could bound lifetimes.
         .map(Clause::ForAll);
     
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let node = tcx.hir.get(node_id);
+
+    let mut is_fn = false;
+    let mut is_impl = false;
+    match node {
+        Node::TraitItem(item) => match item.node {
+            TraitItemKind::Method(..) => is_fn = true,
+            _ => (),
+        }
+
+        Node::ImplItem(item) => match item.node {
+            ImplItemKind::Method(..) => is_fn = true,
+            _ => (),
+        }
+
+        Node::Item(item) => match item.node {
+            ItemKind::Impl(..) => is_impl = true,
+            ItemKind::Fn(..) => is_fn = true,
+            _ => (),
+        }
+
+        Node::ForeignItem(item) => match item.node {
+            ForeignItemKind::Fn(..) => is_fn = true,
+            _ => (),
+        }
+
+        // FIXME: closures?
+        _ => (),
+    }
+
+    let mut input_tys = FxHashSet::default();
+
+    // In an impl, we assume that the receiver type and all its constituents
+    // are well-formed.
+    if is_impl {
+        let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
+        input_tys.extend(trait_ref.self_ty().walk());
+    }
+
+    // In an fn, we assume that the arguments and all their constitutents are
+    // well-formed.
+    if is_fn {
+        let fn_sig = tcx.fn_sig(def_id)
+            .no_late_bound_regions()
+            .expect("only early bound regions");
+        input_tys.extend(
+            fn_sig.inputs().iter().flat_map(|ty| ty.walk())
+        );
+    }
+
+    let clauses = clauses.chain(
+        input_tys.into_iter()
+            .map(|ty| DomainGoal::FromEnv(FromEnv::Ty(ty)))
+            .map(|domain_goal| domain_goal.into_program_clause())
+            .map(Clause::Implies)
+    );
+    
     Environment {
         clauses: tcx.mk_clauses(clauses),
     }