diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index c9666f55d440e..1092e826a35f9 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>> +{ + // Rule Implemented-From-Env (see rustc guide) + // + // `trait Trait where WC { .. } // P0 == Self` + // + // ``` + // forall { + // Implemented(Self: Trait) :- FromEnv(Self: Trait) + // } + // ``` + + // `Self: Trait` + let trait_pred = ty::TraitPredicate { + trait_ref: ty::TraitRef { + def_id, + substs: Substs::identity_for_item(tcx, def_id) + } + }; + // `FromEnv(Self: Trait)` + let from_env = Goal::DomainGoal(DomainGoal::FromEnv(trait_pred.lower())); + // `Implemented(Self: Trait)` + let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred)); + + // `Implemented(Self: Trait) :- FromEnv(Self: Trait)` + 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>> { @@ -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 Trait for A0 where WC { .. }` // - // (see rustc guide) + // ``` + // forall { + // Implemented(A0: Trait) :- WC + // } + // ``` let trait_ref = tcx.impl_trait_ref(def_id).unwrap(); - let trait_ref = ty::TraitPredicate { trait_ref }.lower(); + // `Implemented(A0: Trait)` + 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) :- 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 0000000000000..010cb77edc3f1 --- /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 or the MIT license +// , 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) :- +trait Foo { + 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 0000000000000..6da1e2fd8edd8 --- /dev/null +++ b/src/test/ui/chalkify/lower_trait.stderr @@ -0,0 +1,8 @@ +error: Implemented(Self: Foo) :- FromEnv(Self: Foo). + --> $DIR/lower_trait.rs:13:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error +