about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_traits/lowering.rs49
-rw-r--r--src/test/ui/chalkify/lower_trait.rs22
-rw-r--r--src/test/ui/chalkify/lower_trait.stderr8
3 files changed, 75 insertions, 4 deletions
diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs
index c9666f55d44..1092e826a35 100644
--- a/src/librustc_traits/lowering.rs
+++ b/src/librustc_traits/lowering.rs
@@ -12,6 +12,7 @@ use rustc::hir::{self, ImplPolarity};
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::ty::{self, TyCtxt};
+use rustc::ty::subst::Substs;
 use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
 use syntax::ast;
 use rustc_data_structures::sync::Lrc;
@@ -104,6 +105,7 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     let item = tcx.hir.expect_item(node_id);
     match item.node {
+        hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id),
         hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
 
         // FIXME: other constructions e.g. traits, associated types...
@@ -111,6 +113,36 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
     }
 }
 
+fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+    -> Lrc<Vec<Clause<'tcx>>>
+{
+    // Rule Implemented-From-Env (see rustc guide)
+    //
+    // `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
+    //
+    // ```
+    // forall<Self, P1..Pn> {
+    //   Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)
+    // }
+    // ```
+
+    // `Self: Trait<P1..Pn>`
+    let trait_pred = ty::TraitPredicate {
+        trait_ref: ty::TraitRef {
+            def_id,
+            substs: Substs::identity_for_item(tcx, def_id)
+        }
+    };
+    // `FromEnv(Self: Trait<P1..Pn>)`
+    let from_env = Goal::DomainGoal(DomainGoal::FromEnv(trait_pred.lower()));
+    // `Implemented(Self: Trait<P1..Pn>)`
+    let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred));
+
+    // `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
+    let clause = Clause::Implies(vec![from_env], impl_trait);
+    Lrc::new(vec![clause])
+}
+
 fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     -> Lrc<Vec<Clause<'tcx>>>
 {
@@ -118,15 +150,24 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
         return Lrc::new(vec![]);
     }
 
-    // Rule Implemented-From-Impl
+    // Rule Implemented-From-Impl (see rustc guide)
+    //
+    // `impl<P0..Pn> Trait<A1..An> for A0 where WC { .. }`
     //
-    // (see rustc guide)
+    // ```
+    // forall<P0..Pn> {
+    //   Implemented(A0: Trait<A1..An>) :- WC
+    // }
+    // ```
 
     let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
-    let trait_ref = ty::TraitPredicate { trait_ref }.lower();
+    // `Implemented(A0: Trait<A1..An>)`
+    let trait_pred = ty::TraitPredicate { trait_ref }.lower();
+     // `WC`
     let where_clauses = tcx.predicates_of(def_id).predicates.lower();
 
-    let clause = Clause::Implies(where_clauses, trait_ref);
+     // `Implemented(A0: Trait<A1..An>) :- WC`
+    let clause = Clause::Implies(where_clauses, trait_pred);
     Lrc::new(vec![clause])
 }
 
diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs
new file mode 100644
index 00000000000..010cb77edc3
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait.rs
@@ -0,0 +1,22 @@
+// 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)]
+
+#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+trait Foo<S, T, U> {
+    fn s(S) -> S;
+    fn t(T) -> T;
+    fn u(U) -> U;
+}
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr
new file mode 100644
index 00000000000..6da1e2fd8ed
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait.stderr
@@ -0,0 +1,8 @@
+error: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
+  --> $DIR/lower_trait.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+