]> git.lizzy.rs Git - rust.git/commitdiff
first draft of `program_clauses_for_env`
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 10 Apr 2018 09:55:18 +0000 (05:55 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 23 Apr 2018 17:28:14 +0000 (13:28 -0400)
This computes the transitive closure of traits that appear in the
environment and then appends their clauses. It needs some work, but
it's in the right direction.

src/librustc/dep_graph/dep_node.rs
src/librustc/ty/maps/config.rs
src/librustc/ty/maps/keys.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/mod.rs
src/librustc_traits/lib.rs
src/librustc_traits/lowering.rs
src/test/ui/chalkify/lower_env1.rs [new file with mode: 0644]
src/test/ui/chalkify/lower_env1.stderr [new file with mode: 0644]

index b4f39439d5b4d4d93c4b36bee707a1775650bd6a..18bf54297afc6b3d100e6835c5baf647a0aa0819 100644 (file)
@@ -655,6 +655,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [input] Features,
 
     [] ProgramClausesFor(DefId),
+    [] ProgramClausesForEnv(ParamEnv<'tcx>),
     [] WasmImportModuleMap(CrateNum),
     [] ForeignModules(CrateNum),
 
index fea7de955e0bfdc72fa713bd0c94a321010ac785..735fe06560f5f3a765fbc561bc7085c0859a489f 100644 (file)
@@ -717,6 +717,12 @@ fn describe(_tcx: TyCtxt, _: DefId) -> String {
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for_env<'tcx> {
+    fn describe(_tcx: TyCtxt, _: ty::ParamEnv<'tcx>) -> String {
+        format!("generating chalk-style clauses for param env")
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::wasm_import_module_map<'tcx> {
     fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
         format!("wasm import module map")
index b8167ec918638be880a6bc0351e98c105208dd01..72f2cb49abc0e73f837476907d7331f1a55ba656 100644 (file)
@@ -154,6 +154,15 @@ fn default_span(&self, _: TyCtxt) -> Span {
     }
 }
 
+impl<'tcx> Key for ty::ParamEnv<'tcx> {
+    fn map_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+    fn default_span(&self, _: TyCtxt) -> Span {
+        DUMMY_SP
+    }
+}
+
 impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
     fn map_crate(&self) -> CrateNum {
         self.value.map_crate()
index 0ab9f16dab481064f7b8b6330a2b5be32fb24eb1..368e9dc0fadca780d3b93628a5642ff060ecb1ab 100644 (file)
 
     [] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<&'tcx Slice<Clause<'tcx>>>,
 
+    [] fn program_clauses_for_env: ProgramClausesForEnv(
+        ty::ParamEnv<'tcx>
+    ) -> Lrc<&'tcx Slice<Clause<'tcx>>>,
+
     [] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc<Vec<DefId>>,
     [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
         -> Lrc<FxHashMap<DefId, String>>,
index 8d6c7474a9f94f495569460e2938754f7651caba..70fbd17e6cbb0fbce9b04dc3ed5d02c62543a301 100644 (file)
@@ -978,6 +978,7 @@ macro_rules! force {
         DepKind::DropckOutlives |
         DepKind::SubstituteNormalizeAndTestPredicates |
         DepKind::InstanceDefSizeEstimate |
+        DepKind::ProgramClausesForEnv |
 
         // This one should never occur in this context
         DepKind::Null => {
index c3d2d5675de0544de65a577b3c0f62b4ed9b974c..1524d4b9e7f62bd44411b8f9280c09cef9147145 100644 (file)
@@ -1138,6 +1138,11 @@ pub struct ProjectionPredicate<'tcx> {
 pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
 
 impl<'tcx> PolyProjectionPredicate<'tcx> {
+    /// Returns the def-id of the associated item being projected.
+    pub fn item_def_id(&self) -> DefId {
+        self.skip_binder().projection_ty.item_def_id
+    }
+
     pub fn to_poly_trait_ref(&self, tcx: TyCtxt) -> PolyTraitRef<'tcx> {
         // Note: unlike with TraitRef::to_poly_trait_ref(),
         // self.0.trait_ref is permitted to have escaping regions.
index 8136f6857a5c62cc8ff1eacd8a1cb371cb9e2a70..90c870096e179f711af17cac046249fbc2a7d2e5 100644 (file)
@@ -37,6 +37,7 @@ pub fn provide(p: &mut Providers) {
         normalize_ty_after_erasing_regions:
             normalize_erasing_regions::normalize_ty_after_erasing_regions,
         program_clauses_for: lowering::program_clauses_for,
+        program_clauses_for_env: lowering::program_clauses_for_env,
         ..*p
     };
 }
index 942cf7a657130a8bc2eb4f16900fd27cffa975c1..25a3621fd00b6f031f4b5fc502a50be1d983f362 100644 (file)
 
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::definitions::DefPathData;
+use rustc::hir::{self, ImplPolarity};
 use rustc::traits::{Clause, DomainGoal, Goal, PolyDomainGoal, ProgramClause, WhereClauseAtom};
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Slice, TyCtxt};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
-use syntax::ast;
+use std::mem;
 use syntax::ast;
 
 use std::iter;
@@ -120,24 +123,73 @@ fn into_from_env_goal(self) -> DomainGoal<'tcx> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
 ) -> Lrc<&'tcx Slice<Clause<'tcx>>> {
-    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
-    let node = tcx.hir.find(node_id).unwrap();
-    match node {
-        hir::map::Node::NodeItem(item) => match item.node {
-            hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id),
-            hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
-            _ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
-        },
-        hir::map::Node::NodeImplItem(item) => {
-            if let hir::ImplItemKind::Type(..) = item.node {
-                program_clauses_for_associated_type_value(tcx, def_id)
-            } else {
-                Lrc::new(tcx.mk_clauses(iter::empty::<Clause>()))
-            }
-        }
+    match tcx.def_key(def_id).disambiguated_data.data {
+        DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id),
+        DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
+        DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
+        _ => Lrc::new(Slice::empty()),
+    }
+}
+
+crate fn program_clauses_for_env<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+) -> Lrc<&'tcx Slice<Clause<'tcx>>> {
+    debug!("program_clauses_for_env(param_env={:?})", param_env);
+
+    let mut last_round = FxHashSet();
+    last_round.extend(
+        param_env
+            .caller_bounds
+            .iter()
+            .flat_map(|&p| predicate_def_id(p)),
+    );
+
+    let mut closure = last_round.clone();
+    let mut next_round = FxHashSet();
+    while !last_round.is_empty() {
+        next_round.extend(
+            last_round
+                .drain()
+                .flat_map(|def_id| {
+                    tcx.predicates_of(def_id)
+                        .instantiate_identity(tcx)
+                        .predicates
+                })
+                .flat_map(|p| predicate_def_id(p))
+                .filter(|&def_id| closure.insert(def_id)),
+        );
+        mem::swap(&mut next_round, &mut last_round);
+    }
+
+    debug!("program_clauses_for_env: closure = {:#?}", closure);
 
-        // FIXME: other constructions e.g. traits, associated types...
-        _ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
+    return Lrc::new(
+        tcx.mk_clauses(
+            closure
+                .into_iter()
+                .flat_map(|def_id| tcx.program_clauses_for(def_id).iter().cloned()),
+        ),
+    );
+
+    /// Given that `predicate` is in the environment, returns the
+    /// def-id of something (e.g., a trait, associated item, etc)
+    /// whose predicates can also be assumed to be true. We will
+    /// compute the transitive closure of such things.
+    fn predicate_def_id<'tcx>(predicate: ty::Predicate<'tcx>) -> Option<DefId> {
+        match predicate {
+            ty::Predicate::Trait(predicate) => Some(predicate.def_id()),
+
+            ty::Predicate::Projection(projection) => Some(projection.item_def_id()),
+
+            ty::Predicate::WellFormed(..)
+            | ty::Predicate::RegionOutlives(..)
+            | ty::Predicate::TypeOutlives(..)
+            | ty::Predicate::ObjectSafe(..)
+            | ty::Predicate::ClosureKind(..)
+            | ty::Predicate::Subtype(..)
+            | ty::Predicate::ConstEvaluatable(..) => None,
+        }
     }
 }
 
diff --git a/src/test/ui/chalkify/lower_env1.rs b/src/test/ui/chalkify/lower_env1.rs
new file mode 100644 (file)
index 0000000..fc20ad0
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+trait Foo { }
+
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
+trait Bar where Self: Foo { }
+
+#[rustc_dump_env_program_clauses] //~ ERROR program clause dump
+fn bar<T: Bar>() {
+}
+
+fn main() {
+}
diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr
new file mode 100644 (file)
index 0000000..aaf74f1
--- /dev/null
@@ -0,0 +1,24 @@
+error: program clause dump
+  --> $DIR/lower_env1.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
+   = note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
+   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
+
+error: program clause dump
+  --> $DIR/lower_env1.rs:19:1
+   |
+LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
+   = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
+   = note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
+   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
+   = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
+
+error: aborting due to 2 previous errors
+