From e2f3577131d3c87a5a0c0517d778bfe7834dc966 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Wed, 2 May 2018 08:02:47 +0800 Subject: [PATCH 1/8] wellformed wc --- src/librustc_traits/lowering.rs | 102 +++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 22 deletions(-) diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index 27daebbf8c12d..bac0381f0b005 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -12,8 +12,10 @@ 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, Clauses, DomainGoal, Goal, PolyDomainGoal, ProgramClause, - WhereClause, FromEnv, WellFormed}; +use rustc::traits::{ + Clause, Clauses, DomainGoal, FromEnv, Goal, PolyDomainGoal, ProgramClause, WellFormed, + WhereClause, +}; use rustc::ty::query::Providers; use rustc::ty::{self, Slice, TyCtxt}; use rustc_data_structures::fx::FxHashSet; @@ -101,39 +103,52 @@ impl<'tcx> Lower> for ty::Predicate<'tcx> { Predicate::RegionOutlives(predicate) => predicate.lower(), Predicate::TypeOutlives(predicate) => predicate.lower(), Predicate::Projection(predicate) => predicate.lower(), - Predicate::WellFormed(ty) => ty::Binder::dummy( - DomainGoal::WellFormed(WellFormed::Ty(*ty)) - ), - Predicate::ObjectSafe(..) | - Predicate::ClosureKind(..) | - Predicate::Subtype(..) | - Predicate::ConstEvaluatable(..) => { - unimplemented!() + Predicate::WellFormed(ty) => { + ty::Binder::dummy(DomainGoal::WellFormed(WellFormed::Ty(*ty))) } + Predicate::ObjectSafe(..) + | Predicate::ClosureKind(..) + | Predicate::Subtype(..) + | Predicate::ConstEvaluatable(..) => unimplemented!(), } } } -/// Transforms an existing goal into a FromEnv goal. -/// /// Used for lowered where clauses (see rustc guide). trait IntoFromEnvGoal { + // Transforms an existing goal into a FromEnv goal. fn into_from_env_goal(self) -> Self; } -impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { +trait IntoWellFormedGoal { + fn into_wellformed_goal(self) -> Self; +} + +impl<'tcx> IntoGoal for DomainGoal<'tcx> { + // Transforms an existing goal into a WellFormed goal. fn into_from_env_goal(self) -> DomainGoal<'tcx> { use self::WhereClause::*; match self { - DomainGoal::Holds(Implemented(trait_ref)) => DomainGoal::FromEnv( - FromEnv::Trait(trait_ref) - ), + DomainGoal::Holds(Implemented(trait_ref)) => { + DomainGoal::FromEnv(FromEnv::Trait(trait_ref)) + } other => other, } } } +impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { + fn into_wellformed_goal(self) -> DomainGoal<'tcx> { + use self::DomainGoal::*; + match self { + Holds(wc_atom) => WellFormed(wc_atom), + WellFormed(..) | FromEnv(..) | WellFormedTy(..) | FromEnvTy(..) | Normalize(..) + | RegionOutlives(..) | TypeOutlives(..) => self, + } + } +} + crate fn program_clauses_for<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, @@ -230,7 +245,7 @@ fn program_clauses_for_trait<'a, 'tcx>( // `Implemented(Self: Trait)` let impl_trait: DomainGoal = trait_pred.lower(); - // `FromEnv(Self: Trait)` + // `FromEnv(Self: Trait)` let from_env_goal = impl_trait.into_from_env_goal().into_goal(); let hypotheses = tcx.intern_goals(&[from_env_goal]); @@ -262,10 +277,50 @@ fn program_clauses_for_trait<'a, 'tcx>( goal: goal.into_from_env_goal(), hypotheses, })) + .map(|wc| implied_bound_from_trait(tcx, trait_pred, wc)); + let wellformed_clauses = where_clauses[1..] + .into_iter() + .map(|wc| wellformed_from_bound(tcx, trait_pred, wc)); + tcx.mk_clauses( + clauses + .chain(implied_bound_clauses) + .chain(wellformed_clauses), + ) +} - .map(Clause::ForAll); +fn wellformed_from_bound<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + trait_pred: ty::TraitPredicate<'tcx>, + where_clause: &ty::Predicate<'tcx>, +) -> Clause<'tcx> { + // Rule WellFormed-TraitRef + // + // For each where clause WC: + // forall { + // WellFormed(Self: Trait) :- Implemented(Self: Trait) && WellFormed(WC) + // } - tcx.mk_clauses(clauses.chain(implied_bound_clauses)) + // WellFormed(Self: Trait) + let wellformed_trait = DomainGoal::WellFormed(WhereClauseAtom::Implemented(trait_pred)); + // Impemented(Self: Trait) + let impl_trait = ty::Binder::dummy(DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred))); + // WellFormed(WC) + let wellformed_wc = where_clause + .lower() + .map_bound(|wc| wc.into_wellformed_goal()); + // Implemented(Self: Trait) && WellFormed(WC) + let mut where_clauses = vec![impl_trait]; + where_clauses.push(wellformed_wc); + Clause::ForAll(where_clause.lower().map_bound(|_| { + ProgramClause { + goal: wellformed_trait, + hypotheses: tcx.mk_goals( + where_clauses + .into_iter() + .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), + ), + } + })) } fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Clauses<'tcx> { @@ -307,7 +362,6 @@ pub fn program_clauses_for_type_def<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, ) -> Clauses<'tcx> { - // Rule WellFormed-Type // // `struct Ty where WC1, ..., WCm` @@ -328,7 +382,10 @@ pub fn program_clauses_for_type_def<'a, 'tcx>( let well_formed = ProgramClause { goal: DomainGoal::WellFormed(WellFormed::Ty(ty)), hypotheses: tcx.mk_goals( - where_clauses.iter().cloned().map(|wc| Goal::from_poly_domain_goal(wc, tcx)) + where_clauses + .iter() + .cloned() + .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), ), }; @@ -459,7 +516,8 @@ impl<'a, 'tcx> ClauseDumper<'a, 'tcx> { } if let Some(clauses) = clauses { - let mut err = self.tcx + let mut err = self + .tcx .sess .struct_span_err(attr.span, "program clause dump"); From 329d03ac1f1aef856dbd872468816be57f6b87ea Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Wed, 2 May 2018 18:12:28 +0800 Subject: [PATCH 2/8] update test --- src/test/ui/chalkify/lower_env1.stderr | 4 ++++ src/test/ui/chalkify/lower_trait.stderr | 3 +++ src/test/ui/chalkify/lower_trait_higher_rank.stderr | 3 +++ src/test/ui/chalkify/lower_trait_where_clause.stderr | 6 ++++++ 4 files changed, 16 insertions(+) diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr index 812418a3053e9..e32df036ef4b7 100644 --- a/src/test/ui/chalkify/lower_env1.stderr +++ b/src/test/ui/chalkify/lower_env1.stderr @@ -7,6 +7,8 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Bar). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). error: program clause dump --> $DIR/lower_env1.rs:19:1 @@ -19,6 +21,8 @@ LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Bar). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). error: aborting due to 2 previous errors diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr index 55cd9699b0616..4e03fc634cc52 100644 --- a/src/test/ui/chalkify/lower_trait.stderr +++ b/src/test/ui/chalkify/lower_trait.stderr @@ -8,6 +8,9 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo). = note: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo). = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). + = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(S: std::marker::Sized). + = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(T: std::marker::Sized). + = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(U: std::marker::Sized). error: aborting due to previous error diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr index ea275d647fa7c..891f0453561ea 100644 --- a/src/test/ui/chalkify/lower_trait_higher_rank.stderr +++ b/src/test/ui/chalkify/lower_trait_higher_rank.stderr @@ -8,6 +8,9 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump = note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo). = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). = note: ProjectionEq(>::Output == &'a u8) :- FromEnv(Self: Foo). + = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(F: std::marker::Sized). + = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), forall<> { WellFormed(>::Output == &'a u8) }. + = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), forall<> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }. error: aborting due to previous error diff --git a/src/test/ui/chalkify/lower_trait_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr index 68bc2ddf2930e..db5a795e3011d 100644 --- a/src/test/ui/chalkify/lower_trait_where_clause.stderr +++ b/src/test/ui/chalkify/lower_trait_where_clause.stderr @@ -11,6 +11,12 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump = note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). = note: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). = note: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), RegionOutlives('a : 'b). + = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), TypeOutlives(U : 'b). + = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::fmt::Debug). + = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::marker::Sized). + = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(T: std::borrow::Borrow). + = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(T: std::marker::Sized). error: aborting due to previous error From dabd3f6935771ef26131b06c29f7937f9c561b38 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Fri, 4 May 2018 10:00:11 +0800 Subject: [PATCH 3/8] split IntoWellFormedGoal --- src/librustc_traits/lowering.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index bac0381f0b005..c8192f2141867 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -121,11 +121,11 @@ trait IntoFromEnvGoal { } trait IntoWellFormedGoal { + // Transforms an existing goal into a WellFormed goal. fn into_wellformed_goal(self) -> Self; } -impl<'tcx> IntoGoal for DomainGoal<'tcx> { - // Transforms an existing goal into a WellFormed goal. +impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { fn into_from_env_goal(self) -> DomainGoal<'tcx> { use self::WhereClause::*; @@ -138,7 +138,7 @@ impl<'tcx> IntoGoal for DomainGoal<'tcx> { } } -impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { +impl<'tcx> IntoWellFormedGoal for DomainGoal<'tcx> { fn into_wellformed_goal(self) -> DomainGoal<'tcx> { use self::DomainGoal::*; match self { @@ -302,7 +302,7 @@ fn wellformed_from_bound<'a, 'tcx>( // WellFormed(Self: Trait) let wellformed_trait = DomainGoal::WellFormed(WhereClauseAtom::Implemented(trait_pred)); - // Impemented(Self: Trait) + // Implemented(Self: Trait) let impl_trait = ty::Binder::dummy(DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred))); // WellFormed(WC) let wellformed_wc = where_clause From ff83ef0c24f866ff1b07fd27bbce5b931b9dc065 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Fri, 11 May 2018 18:32:51 +0800 Subject: [PATCH 4/8] merge wellformed(wc)s --- src/librustc_traits/lowering.rs | 42 ++++++++----------- src/test/ui/chalkify/lower_env1.stderr | 8 ++-- src/test/ui/chalkify/lower_trait.stderr | 4 +- .../chalkify/lower_trait_higher_rank.stderr | 1 + .../chalkify/lower_trait_where_clause.stderr | 7 +--- 5 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index c8192f2141867..cc12a2e1dcdf2 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -13,10 +13,9 @@ use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::hir::map::definitions::DefPathData; use rustc::hir::{self, ImplPolarity}; use rustc::traits::{ - Clause, Clauses, DomainGoal, FromEnv, Goal, PolyDomainGoal, ProgramClause, WellFormed, - WhereClause, + Clause, Clauses, DomainGoal, Goal, PolyDomainGoal, ProgramClause, WhereClauseAtom, }; -use rustc::ty::query::Providers; +use rustc::ty::subst::Substs; use rustc::ty::{self, Slice, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use std::mem; @@ -278,21 +277,15 @@ fn program_clauses_for_trait<'a, 'tcx>( hypotheses, })) .map(|wc| implied_bound_from_trait(tcx, trait_pred, wc)); - let wellformed_clauses = where_clauses[1..] - .into_iter() - .map(|wc| wellformed_from_bound(tcx, trait_pred, wc)); - tcx.mk_clauses( - clauses - .chain(implied_bound_clauses) - .chain(wellformed_clauses), - ) + let wellformed_clauses = wellformed_from_bound(tcx, trait_pred, &where_clauses[1..]); + tcx.mk_clauses(clauses.chain(implied_bound_clauses).chain(wellformed_clauses)) } fn wellformed_from_bound<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_pred: ty::TraitPredicate<'tcx>, - where_clause: &ty::Predicate<'tcx>, -) -> Clause<'tcx> { + where_clauses: &[ty::Predicate<'tcx>], +) -> iter::Once> { // Rule WellFormed-TraitRef // // For each where clause WC: @@ -309,18 +302,17 @@ fn wellformed_from_bound<'a, 'tcx>( .lower() .map_bound(|wc| wc.into_wellformed_goal()); // Implemented(Self: Trait) && WellFormed(WC) - let mut where_clauses = vec![impl_trait]; - where_clauses.push(wellformed_wc); - Clause::ForAll(where_clause.lower().map_bound(|_| { - ProgramClause { - goal: wellformed_trait, - hypotheses: tcx.mk_goals( - where_clauses - .into_iter() - .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), - ), - } - })) + let mut wcs = vec![impl_trait]; + wcs.extend(wellformed_wcs); + + let clause = ProgramClause { + goal: wellformed_trait, + hypotheses: tcx.mk_goals( + wcs.into_iter() + .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), + ), + }; + iter::once(Clause::ForAll(ty::Binder::dummy(clause))) } fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Clauses<'tcx> { diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr index e32df036ef4b7..e688d9e8b49e7 100644 --- a/src/test/ui/chalkify/lower_env1.stderr +++ b/src/test/ui/chalkify/lower_env1.stderr @@ -7,8 +7,7 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). - = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Bar). - = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Bar), WellFormed(Self: Foo). error: program clause dump --> $DIR/lower_env1.rs:19:1 @@ -21,8 +20,9 @@ LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). - = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Bar). - = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Bar), WellFormed(Self: Foo). + = note: WellFormed(Self: Foo) :- Implemented(Self: Foo). + = note: WellFormed(Self: std::marker::Sized) :- Implemented(Self: std::marker::Sized). error: aborting due to 2 previous errors diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr index 4e03fc634cc52..c4e768415d60b 100644 --- a/src/test/ui/chalkify/lower_trait.stderr +++ b/src/test/ui/chalkify/lower_trait.stderr @@ -8,9 +8,7 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo). = note: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo). = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). - = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(S: std::marker::Sized). - = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(T: std::marker::Sized). - = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(U: std::marker::Sized). + = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(U: std::marker::Sized). error: aborting due to previous error diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr index 891f0453561ea..ab86b6fdb2586 100644 --- a/src/test/ui/chalkify/lower_trait_higher_rank.stderr +++ b/src/test/ui/chalkify/lower_trait_higher_rank.stderr @@ -11,6 +11,7 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(F: std::marker::Sized). = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), forall<> { WellFormed(>::Output == &'a u8) }. = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), forall<> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }. + = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(F: std::marker::Sized), forall<> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<> { WellFormed(>::Output == &'a u8) }. error: aborting due to previous error diff --git a/src/test/ui/chalkify/lower_trait_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr index db5a795e3011d..5ea397d424b63 100644 --- a/src/test/ui/chalkify/lower_trait_where_clause.stderr +++ b/src/test/ui/chalkify/lower_trait_where_clause.stderr @@ -11,12 +11,7 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump = note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). = note: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). = note: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). - = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), RegionOutlives('a : 'b). - = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), TypeOutlives(U : 'b). - = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::fmt::Debug). - = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::marker::Sized). - = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(T: std::borrow::Borrow). - = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(T: std::marker::Sized). + = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(S: std::fmt::Debug), WellFormed(T: std::borrow::Borrow), RegionOutlives('a : 'b), TypeOutlives(U : 'b). error: aborting due to previous error From a6d4d2b9455a7954a4321b2b3af3d3aa8dcdd08a Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Fri, 6 Jul 2018 18:44:42 +0800 Subject: [PATCH 5/8] refactor --- src/librustc_traits/lowering.rs | 67 ++++++++++++++++----------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index cc12a2e1dcdf2..e363d73fc6a9d 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -13,9 +13,10 @@ use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::hir::map::definitions::DefPathData; use rustc::hir::{self, ImplPolarity}; use rustc::traits::{ - Clause, Clauses, DomainGoal, Goal, PolyDomainGoal, ProgramClause, WhereClauseAtom, + Clause, Clauses, DomainGoal, FromEnv, Goal, PolyDomainGoal, ProgramClause, WellFormed, + WhereClause, }; -use rustc::ty::subst::Substs; +use rustc::ty::query::Providers; use rustc::ty::{self, Slice, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use std::mem; @@ -139,11 +140,13 @@ impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { impl<'tcx> IntoWellFormedGoal for DomainGoal<'tcx> { fn into_wellformed_goal(self) -> DomainGoal<'tcx> { - use self::DomainGoal::*; + use self::WhereClause::*; + match self { - Holds(wc_atom) => WellFormed(wc_atom), - WellFormed(..) | FromEnv(..) | WellFormedTy(..) | FromEnvTy(..) | Normalize(..) - | RegionOutlives(..) | TypeOutlives(..) => self, + DomainGoal::Holds(Implemented(trait_ref)) => { + DomainGoal::WellFormed(WellFormed::Trait(trait_ref)) + } + other => other, } } } @@ -256,6 +259,8 @@ fn program_clauses_for_trait<'a, 'tcx>( let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env))); + let where_clauses = &tcx.predicates_defined_on(def_id).predicates; + // Rule Implied-Bound-From-Trait // // For each where clause WC: @@ -266,7 +271,6 @@ fn program_clauses_for_trait<'a, 'tcx>( // ``` // `FromEnv(WC) :- FromEnv(Self: Trait)`, for each where clause WC - let where_clauses = &tcx.predicates_defined_on(def_id).predicates; let implied_bound_clauses = where_clauses .into_iter() .map(|wc| wc.lower()) @@ -276,16 +280,8 @@ fn program_clauses_for_trait<'a, 'tcx>( goal: goal.into_from_env_goal(), hypotheses, })) - .map(|wc| implied_bound_from_trait(tcx, trait_pred, wc)); - let wellformed_clauses = wellformed_from_bound(tcx, trait_pred, &where_clauses[1..]); - tcx.mk_clauses(clauses.chain(implied_bound_clauses).chain(wellformed_clauses)) -} + .map(Clause::ForAll); -fn wellformed_from_bound<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - trait_pred: ty::TraitPredicate<'tcx>, - where_clauses: &[ty::Predicate<'tcx>], -) -> iter::Once> { // Rule WellFormed-TraitRef // // For each where clause WC: @@ -293,26 +289,27 @@ fn wellformed_from_bound<'a, 'tcx>( // WellFormed(Self: Trait) :- Implemented(Self: Trait) && WellFormed(WC) // } - // WellFormed(Self: Trait) - let wellformed_trait = DomainGoal::WellFormed(WhereClauseAtom::Implemented(trait_pred)); - // Implemented(Self: Trait) - let impl_trait = ty::Binder::dummy(DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred))); - // WellFormed(WC) - let wellformed_wc = where_clause - .lower() - .map_bound(|wc| wc.into_wellformed_goal()); - // Implemented(Self: Trait) && WellFormed(WC) - let mut wcs = vec![impl_trait]; - wcs.extend(wellformed_wcs); + let wellformed_clauses = where_clauses + .into_iter() + .map(|wc| wc.lower()) + // WellFormed(Self: Trait) :- Implemented(Self: Trait) && WellFormed(WC) + .map(|wc| { + wc.map_bound(|goal| ProgramClause { + goal: goal.into_wellformed_goal(), + hypotheses: tcx.mk_goals( + where_clauses + .into_iter() + .map(|wc| Goal::from_poly_domain_goal(wc.lower(), tcx)), + ), + }) + }) + .map(Clause::ForAll); - let clause = ProgramClause { - goal: wellformed_trait, - hypotheses: tcx.mk_goals( - wcs.into_iter() - .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), - ), - }; - iter::once(Clause::ForAll(ty::Binder::dummy(clause))) + tcx.mk_clauses( + clauses + .chain(implied_bound_clauses) + .chain(wellformed_clauses), + ) } fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Clauses<'tcx> { From b9c6dba5c4934033fd8aa1a51f432fbdb42d3ea3 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sat, 7 Jul 2018 11:02:47 +0800 Subject: [PATCH 6/8] extend where clauses --- src/librustc_traits/lowering.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index e363d73fc6a9d..2c6c6bd2a935b 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -289,21 +289,24 @@ fn program_clauses_for_trait<'a, 'tcx>( // WellFormed(Self: Trait) :- Implemented(Self: Trait) && WellFormed(WC) // } - let wellformed_clauses = where_clauses - .into_iter() - .map(|wc| wc.lower()) - // WellFormed(Self: Trait) :- Implemented(Self: Trait) && WellFormed(WC) - .map(|wc| { - wc.map_bound(|goal| ProgramClause { - goal: goal.into_wellformed_goal(), - hypotheses: tcx.mk_goals( - where_clauses - .into_iter() - .map(|wc| Goal::from_poly_domain_goal(wc.lower(), tcx)), - ), - }) - }) - .map(Clause::ForAll); + //Implemented(Self: Trait) && WellFormed(WC) + let mut extend_where_clauses = vec![ty::Binder::dummy(trait_pred.lower())]; + extend_where_clauses.extend( + where_clauses + .into_iter() + .map(|wc| wc.lower().map_bound(|wc| wc.into_wellformed_goal())), + ); + + // WellFormed(Self: Trait) :- Implemented(Self: Trait) && WellFormed(WC) + let clause = ProgramClause { + goal: DomainGoal::WellFormed(WellFormed::Trait(trait_pred)), + hypotheses: tcx.mk_goals( + extend_where_clauses + .into_iter() + .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), + ), + }; + let wellformed_clauses = iter::once(Clause::ForAll(ty::Binder::dummy(clause))); tcx.mk_clauses( clauses From f5f97b37a7c9492e8b5e6252cce63c4ec7b3abf1 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sat, 7 Jul 2018 11:57:04 +0800 Subject: [PATCH 7/8] update tests --- src/test/ui/chalkify/lower_env1.stderr | 4 ++-- src/test/ui/chalkify/lower_trait_higher_rank.stderr | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr index e688d9e8b49e7..d6673f6a8a6fb 100644 --- a/src/test/ui/chalkify/lower_env1.stderr +++ b/src/test/ui/chalkify/lower_env1.stderr @@ -7,7 +7,7 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). - = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Bar), WellFormed(Self: Foo). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo). error: program clause dump --> $DIR/lower_env1.rs:19:1 @@ -20,7 +20,7 @@ LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). - = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Bar), WellFormed(Self: Foo). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo). = note: WellFormed(Self: Foo) :- Implemented(Self: Foo). = note: WellFormed(Self: std::marker::Sized) :- Implemented(Self: std::marker::Sized). diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr index ab86b6fdb2586..afb2cd4b56332 100644 --- a/src/test/ui/chalkify/lower_trait_higher_rank.stderr +++ b/src/test/ui/chalkify/lower_trait_higher_rank.stderr @@ -8,10 +8,7 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump = note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo). = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). = note: ProjectionEq(>::Output == &'a u8) :- FromEnv(Self: Foo). - = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(F: std::marker::Sized). - = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), forall<> { WellFormed(>::Output == &'a u8) }. - = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), forall<> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }. - = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(F: std::marker::Sized), forall<> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<> { WellFormed(>::Output == &'a u8) }. + = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(F: std::marker::Sized), forall<> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<> { ProjectionEq(>::Output == &'a u8) }. error: aborting due to previous error From 37c5c0bf9ce4e14b3cfaf102b1250c9201113b55 Mon Sep 17 00:00:00 2001 From: scalexm Date: Mon, 9 Jul 2018 21:20:26 +0200 Subject: [PATCH 8/8] Change wording --- src/librustc_traits/lowering.rs | 42 +++++++++++++++++---------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index 2c6c6bd2a935b..cf61258577619 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -114,15 +114,16 @@ impl<'tcx> Lower> for ty::Predicate<'tcx> { } } -/// Used for lowered where clauses (see rustc guide). +/// Used for implied bounds related rules (see rustc guide). trait IntoFromEnvGoal { - // Transforms an existing goal into a FromEnv goal. + /// Transforms an existing goal into a `FromEnv` goal. fn into_from_env_goal(self) -> Self; } +/// Used for well-formedness related rules (see rustc guide). trait IntoWellFormedGoal { - // Transforms an existing goal into a WellFormed goal. - fn into_wellformed_goal(self) -> Self; + /// Transforms an existing goal into a `WellFormed` goal. + fn into_well_formed_goal(self) -> Self; } impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { @@ -139,7 +140,7 @@ impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { } impl<'tcx> IntoWellFormedGoal for DomainGoal<'tcx> { - fn into_wellformed_goal(self) -> DomainGoal<'tcx> { + fn into_well_formed_goal(self) -> DomainGoal<'tcx> { use self::WhereClause::*; match self { @@ -284,34 +285,35 @@ fn program_clauses_for_trait<'a, 'tcx>( // Rule WellFormed-TraitRef // - // For each where clause WC: + // Here `WC` denotes the set of all where clauses: + // ``` // forall { // WellFormed(Self: Trait) :- Implemented(Self: Trait) && WellFormed(WC) // } + // ``` - //Implemented(Self: Trait) && WellFormed(WC) - let mut extend_where_clauses = vec![ty::Binder::dummy(trait_pred.lower())]; - extend_where_clauses.extend( - where_clauses - .into_iter() - .map(|wc| wc.lower().map_bound(|wc| wc.into_wellformed_goal())), - ); + // `Implemented(Self: Trait) && WellFormed(WC)` + let wf_conditions = iter::once(ty::Binder::dummy(trait_pred.lower())) + .chain( + where_clauses + .into_iter() + .map(|wc| wc.lower()) + .map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal())) + ); - // WellFormed(Self: Trait) :- Implemented(Self: Trait) && WellFormed(WC) - let clause = ProgramClause { + // `WellFormed(Self: Trait) :- Implemented(Self: Trait) && WellFormed(WC)` + let wf_clause = ProgramClause { goal: DomainGoal::WellFormed(WellFormed::Trait(trait_pred)), hypotheses: tcx.mk_goals( - extend_where_clauses - .into_iter() - .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), + wf_conditions.map(|wc| Goal::from_poly_domain_goal(wc, tcx)), ), }; - let wellformed_clauses = iter::once(Clause::ForAll(ty::Binder::dummy(clause))); + let wf_clause = iter::once(Clause::ForAll(ty::Binder::dummy(wf_clause))); tcx.mk_clauses( clauses .chain(implied_bound_clauses) - .chain(wellformed_clauses), + .chain(wf_clause) ) }