From 7ac35eaa12c4a1185a7a18fad6d8f39139ca668c Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Mon, 26 Mar 2018 23:03:50 -0500 Subject: [PATCH] chalkify: Implement Rule Implied-Bound-From-Trait --- src/librustc_traits/lowering.rs | 69 +++++++++++++++++-- src/test/ui/chalkify/lower_trait.rs | 3 + src/test/ui/chalkify/lower_trait.stderr | 20 +++++- .../ui/chalkify/lower_trait_higher_rank.rs | 24 +++++++ .../chalkify/lower_trait_higher_rank.stderr | 26 +++++++ .../ui/chalkify/lower_trait_where_clause.rs | 31 +++++++++ .../chalkify/lower_trait_where_clause.stderr | 44 ++++++++++++ 7 files changed, 212 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/chalkify/lower_trait_higher_rank.rs create mode 100644 src/test/ui/chalkify/lower_trait_higher_rank.stderr create mode 100644 src/test/ui/chalkify/lower_trait_where_clause.rs create mode 100644 src/test/ui/chalkify/lower_trait_where_clause.stderr diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index 153b2e730337d..3d24b087c5958 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -90,6 +90,28 @@ impl<'tcx> Lower> for ty::Predicate<'tcx> { } } +/// Transforms an existing goal into a FromEnv goal. +/// +/// Used for lowered where clauses (see rustc guide). +trait IntoFromEnvGoal { + fn into_from_env_goal(self) -> Self; +} + +impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { + fn into_from_env_goal(self) -> DomainGoal<'tcx> { + use self::DomainGoal::*; + match self { + Holds(wc_atom) => FromEnv(wc_atom), + WellFormed(..) | + FromEnv(..) | + WellFormedTy(..) | + FromEnvTy(..) | + RegionOutlives(..) | + TypeOutlives(..) => self, + } + } +} + crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Lrc>> { @@ -107,9 +129,9 @@ 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` + + // Rule Implemented-From-Env (see rustc guide) // // ``` // forall { @@ -130,11 +152,50 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred)); // `Implemented(Self: Trait) :- FromEnv(Self: Trait)` - let clause = ProgramClause { + let implemented_from_env = ProgramClause { goal: impl_trait, hypotheses: vec![from_env], }; - Lrc::new(vec![Clause::ForAll(ty::Binder::dummy(clause))]) + let mut clauses = vec![ + Clause::ForAll(ty::Binder::dummy(implemented_from_env)) + ]; + + // Rule Implied-Bound-From-Trait + // + // For each where clause WC: + // ``` + // forall { + // FromEnv(WC) :- FromEnv(Self: Trait)`, for each where clause WC + // FIXME: Remove the [1..] slice; this is a hack because the query + // predicates_of currently includes the trait itself (`Self: Trait`). + let where_clauses = &tcx.predicates_of(def_id).predicates; + let implied_bound_clauses = + where_clauses[1..].into_iter() + .map(|wc| implied_bound_from_trait(trait_pred, wc)); + clauses.extend(implied_bound_clauses); + + Lrc::new(clauses) +} + +/// For a given `where_clause`, returns a clause `FromEnv(WC) :- FromEnv(Self: Trait)`. +fn implied_bound_from_trait<'tcx>( + trait_pred: ty::TraitPredicate<'tcx>, + where_clause: &ty::Predicate<'tcx>, +) -> Clause<'tcx> { + // `FromEnv(Self: Trait)` + let impl_trait = DomainGoal::FromEnv(WhereClauseAtom::Implemented(trait_pred)); + + // `FromEnv(WC) :- FromEnv(Self: Trait)` + Clause::ForAll( + where_clause.lower().map_bound(|goal| ProgramClause { + goal: goal.into_from_env_goal(), + hypotheses: vec![impl_trait.into()], + }) + ) } fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs index 010cb77edc3f1..74feb0105ccf1 100644 --- a/src/test/ui/chalkify/lower_trait.rs +++ b/src/test/ui/chalkify/lower_trait.rs @@ -11,6 +11,9 @@ #![feature(rustc_attrs)] #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- + //~| ERROR FromEnv + //~| ERROR FromEnv + //~| ERROR FromEnv trait Foo { fn s(S) -> S; fn t(T) -> T; diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr index 6da1e2fd8edd8..45753c3bb90c2 100644 --- a/src/test/ui/chalkify/lower_trait.stderr +++ b/src/test/ui/chalkify/lower_trait.stderr @@ -4,5 +4,23 @@ error: Implemented(Self: Foo) :- FromEnv(Self: Foo). LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo). + --> $DIR/lower_trait.rs:13:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo). + --> $DIR/lower_trait.rs:13:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo). + --> $DIR/lower_trait.rs:13:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.rs b/src/test/ui/chalkify/lower_trait_higher_rank.rs new file mode 100644 index 0000000000000..e5eaf4591ece8 --- /dev/null +++ b/src/test/ui/chalkify/lower_trait_higher_rank.rs @@ -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 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) :- + //~| ERROR FromEnv + //~| ERROR FromEnv + //~| ERROR FromEnv +trait Foo where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8 +{ + fn s(F) -> F; +} + +fn main() { + println!("hello"); +} diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr new file mode 100644 index 0000000000000..9aed0c018c947 --- /dev/null +++ b/src/test/ui/chalkify/lower_trait_higher_rank.stderr @@ -0,0 +1,26 @@ +error: Implemented(Self: Foo) :- FromEnv(Self: Foo). + --> $DIR/lower_trait_higher_rank.rs:13:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo). + --> $DIR/lower_trait_higher_rank.rs:13:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo). + --> $DIR/lower_trait_higher_rank.rs:13:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: FromEnv(>::Output == &'a u8) :- FromEnv(Self: Foo). + --> $DIR/lower_trait_higher_rank.rs:13:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs new file mode 100644 index 0000000000000..b2ce3ca48b27a --- /dev/null +++ b/src/test/ui/chalkify/lower_trait_where_clause.rs @@ -0,0 +1,31 @@ +// 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)] + +use std::fmt::{Debug, Display}; +use std::borrow::Borrow; + +#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- + //~| ERROR FromEnv + //~| ERROR FromEnv + //~| ERROR FromEnv + //~| ERROR FromEnv + //~| ERROR RegionOutlives + //~| ERROR TypeOutlives +trait Foo<'a, 'b, S, T, U> where S: Debug, T: Borrow, U: ?Sized, 'a: 'b, U: 'b { + 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_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr new file mode 100644 index 0000000000000..a9ecaec3aff9e --- /dev/null +++ b/src/test/ui/chalkify/lower_trait_where_clause.stderr @@ -0,0 +1,44 @@ +error: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + --> $DIR/lower_trait_where_clause.rs:16:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + --> $DIR/lower_trait_where_clause.rs:16:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + --> $DIR/lower_trait_where_clause.rs:16:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + --> $DIR/lower_trait_where_clause.rs:16:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: FromEnv(T: std::borrow::Borrow) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + --> $DIR/lower_trait_where_clause.rs:16:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + --> $DIR/lower_trait_where_clause.rs:16:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + --> $DIR/lower_trait_where_clause.rs:16:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors +