From 3aa1085cfc3b39d4c2b03642c79f1557a2424d87 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 22 Mar 2018 05:19:25 -0400 Subject: [PATCH 1/9] add a `-Zchalk` command-line option --- src/librustc/session/config.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index e9fe94cdb4a36..456e83f4700e4 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1289,6 +1289,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "tell the linker to strip debuginfo when building without debuginfo enabled."), share_generics: Option = (None, parse_opt_bool, [TRACKED], "make the current crate share its generic instantiations"), + chalk: bool = (false, parse_bool, [TRACKED], + "enable the experimental Chalk-based trait solving engine"), } pub fn default_lib_output() -> CrateType { From c8a52850cffd1e13e1f695451127f981345c72ec Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 23 Mar 2018 04:19:34 -0400 Subject: [PATCH 2/9] create a `QueryRegionConstraint` type Chalk wants to be able to pass these constraints around. Also, the form we were using in our existing queries was not as general as we are going to need. --- src/librustc/ich/impls_ty.rs | 4 -- src/librustc/infer/canonical.rs | 71 +++++++++++---------------------- src/librustc_traits/util.rs | 40 ++++++++++--------- 3 files changed, 45 insertions(+), 70 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 70c152b40c0d2..acb1d2272ef52 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1352,10 +1352,6 @@ impl_stable_hash_for!( } ); -impl_stable_hash_for!(struct infer::canonical::QueryRegionConstraints<'tcx> { - region_outlives, ty_outlives -}); - impl_stable_hash_for!(enum infer::canonical::Certainty { Proven, Ambiguous }); diff --git a/src/librustc/infer/canonical.rs b/src/librustc/infer/canonical.rs index 8ea6eb005a140..25f8b5d8c9cc0 100644 --- a/src/librustc/infer/canonical.rs +++ b/src/librustc/infer/canonical.rs @@ -42,7 +42,6 @@ use traits::{Obligation, ObligationCause, PredicateObligation}; use ty::{self, CanonicalVar, Lift, Region, Slice, Ty, TyCtxt, TypeFlags}; use ty::subst::{Kind, UnpackedKind}; use ty::fold::{TypeFoldable, TypeFolder}; -use util::captures::Captures; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::FxHashMap; @@ -121,7 +120,7 @@ pub enum CanonicalTyVarKind { #[derive(Clone, Debug)] pub struct QueryResult<'tcx, R> { pub var_values: CanonicalVarValues<'tcx>, - pub region_constraints: QueryRegionConstraints<'tcx>, + pub region_constraints: Vec>, pub certainty: Certainty, pub value: R, } @@ -181,12 +180,7 @@ impl<'tcx, R> Canonical<'tcx, QueryResult<'tcx, R>> { } } -/// Subset of `RegionConstraintData` produced by trait query. -#[derive(Clone, Debug, Default)] -pub struct QueryRegionConstraints<'tcx> { - pub region_outlives: Vec<(Region<'tcx>, Region<'tcx>)>, - pub ty_outlives: Vec<(Ty<'tcx>, Region<'tcx>)>, -} +pub type QueryRegionConstraint<'tcx> = ty::Binder, Region<'tcx>>>; /// Trait implemented by values that can be canonicalized. It mainly /// serves to identify the interning table we will use. @@ -382,35 +376,29 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { &'a self, cause: &'a ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - unsubstituted_region_constraints: &'a QueryRegionConstraints<'tcx>, + unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>], result_subst: &'a CanonicalVarValues<'tcx>, - ) -> impl Iterator> + Captures<'gcx> + 'a { - let QueryRegionConstraints { - region_outlives, - ty_outlives, - } = unsubstituted_region_constraints; - - let region_obligations = region_outlives.iter().map(move |(r1, r2)| { - let r1 = substitute_value(self.tcx, result_subst, r1); - let r2 = substitute_value(self.tcx, result_subst, r2); - Obligation::new( - cause.clone(), - param_env, - ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r1, r2))), - ) - }); - - let ty_obligations = ty_outlives.iter().map(move |(t1, r2)| { - let t1 = substitute_value(self.tcx, result_subst, t1); + ) -> impl Iterator> + 'a { + Box::new(unsubstituted_region_constraints.iter().map(move |constraint| { + let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below + let k1 = substitute_value(self.tcx, result_subst, k1); let r2 = substitute_value(self.tcx, result_subst, r2); - Obligation::new( - cause.clone(), - param_env, - ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t1, r2))), - ) - }); - - region_obligations.chain(ty_obligations) + match k1.unpack() { + UnpackedKind::Lifetime(r1) => + Obligation::new( + cause.clone(), + param_env, + ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r1, r2))), + ), + + UnpackedKind::Type(t1) => + Obligation::new( + cause.clone(), + param_env, + ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t1, r2))), + ), + } + })) as Box> } /// Given two sets of values for the same set of canonical variables, unify them. @@ -913,19 +901,6 @@ BraceStructTypeFoldableImpl! { } } -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for QueryRegionConstraints<'tcx> { - region_outlives, ty_outlives - } -} - -BraceStructLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for QueryRegionConstraints<'a> { - type Lifted = QueryRegionConstraints<'tcx>; - region_outlives, ty_outlives - } -} - BraceStructTypeFoldableImpl! { impl<'tcx, R> TypeFoldable<'tcx> for QueryResult<'tcx, R> { var_values, region_constraints, certainty, value diff --git a/src/librustc_traits/util.rs b/src/librustc_traits/util.rs index bff070ab73de3..f25906a7bcad1 100644 --- a/src/librustc_traits/util.rs +++ b/src/librustc_traits/util.rs @@ -9,8 +9,7 @@ // except according to those terms. use rustc::infer::InferCtxt; -use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryRegionConstraints, - QueryResult}; +use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryResult}; use rustc::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc::traits::{FulfillmentContext, TraitEngine}; use rustc::traits::query::NoSolution; @@ -62,7 +61,7 @@ where let region_obligations = infcx.take_registered_region_obligations(); - let (region_outlives, ty_outlives) = infcx.with_region_constraints(|region_constraints| { + let region_constraints = infcx.with_region_constraints(|region_constraints| { let RegionConstraintData { constraints, verifys, @@ -72,24 +71,32 @@ where assert!(verifys.is_empty()); assert!(givens.is_empty()); - let region_outlives: Vec<_> = constraints + let mut outlives: Vec<_> = constraints .into_iter() .map(|(k, _)| match *k { - Constraint::VarSubVar(v1, v2) => { - (tcx.mk_region(ty::ReVar(v1)), tcx.mk_region(ty::ReVar(v2))) + Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( + tcx.mk_region(ty::ReVar(v1)).into(), + tcx.mk_region(ty::ReVar(v2)), + ), + Constraint::VarSubReg(v1, r2) => { + ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v1)).into(), r2) } - Constraint::VarSubReg(v1, r2) => (tcx.mk_region(ty::ReVar(v1)), r2), - Constraint::RegSubVar(r1, v2) => (r1, tcx.mk_region(ty::ReVar(v2))), - Constraint::RegSubReg(r1, r2) => (r1, r2), + Constraint::RegSubVar(r1, v2) => { + ty::OutlivesPredicate(r1.into(), tcx.mk_region(ty::ReVar(v2))) + } + Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r1.into(), r2), }) + .map(ty::Binder) // no bound regions in the code above .collect(); - let ty_outlives: Vec<_> = region_obligations - .into_iter() - .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region)) - .collect(); + outlives.extend( + region_obligations + .into_iter() + .map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region)) + .map(ty::Binder) // no bound regions in the code above + ); - (region_outlives, ty_outlives) + outlives }); let certainty = if ambig_errors.is_empty() { @@ -100,10 +107,7 @@ where let (canonical_result, _) = infcx.canonicalize_response(&QueryResult { var_values: inference_vars, - region_constraints: QueryRegionConstraints { - region_outlives, - ty_outlives, - }, + region_constraints, certainty, value: answer, }); From cfbf62f7dfcf2f89d12b59140fe0d0f95dc5afbd Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 23 Mar 2018 04:58:18 -0400 Subject: [PATCH 3/9] add `Goal::CannotProve` and extract `ProgramClause` struct --- src/librustc/ich/impls_ty.rs | 1 + src/librustc/traits/mod.rs | 3 ++- src/librustc/traits/structural_impls.rs | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index acb1d2272ef52..322cfd55510bb 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1413,6 +1413,7 @@ impl<'a, 'tcx> HashStable> for traits::Goal<'tcx> { quantifier.hash_stable(hcx, hasher); goal.hash_stable(hcx, hasher); }, + CannotProve => { }, } } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8d2398d34090d..b05c4539f6a49 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -286,7 +286,8 @@ pub enum Goal<'tcx> { And(&'tcx Goal<'tcx>, &'tcx Goal<'tcx>), Not(&'tcx Goal<'tcx>), DomainGoal(DomainGoal<'tcx>), - Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>) + Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>), + CannotProve, } impl<'tcx> Goal<'tcx> { diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 31c5bf1bbad84..1e3e4160de196 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -491,6 +491,7 @@ impl<'tcx> fmt::Display for traits::Goal<'tcx> { // FIXME: appropriate binder names write!(fmt, "{}<> {{ {} }}", qkind, goal.skip_binder()) } + CannotProve => write!(fmt, "CannotProve"), } } } @@ -557,6 +558,7 @@ EnumTypeFoldableImpl! { (traits::Goal::Not)(goal), (traits::Goal::DomainGoal)(domain_goal), (traits::Goal::Quantified)(qkind, goal), + (traits::Goal::CannotProve), } } From 09bd6f3ee7efe4e257dec353b9a6223571c875de Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 30 Mar 2018 00:51:39 -0400 Subject: [PATCH 4/9] introduce new DefPathData variants for traits, assoc types --- src/librustc/hir/map/def_collector.rs | 7 ++++--- src/librustc/hir/map/definitions.rs | 15 +++++++++++++++ src/librustc/ty/item_path.rs | 3 +++ src/librustc/util/ppaux.rs | 21 +++++++++++++++++++-- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 4bd857c73e6cf..bfe21549e453d 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -107,8 +107,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { // information we encapsulate into let def_data = match i.node { ItemKind::Impl(..) => DefPathData::Impl, + ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_str()), ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | - ItemKind::Trait(..) | ItemKind::TraitAlias(..) | + ItemKind::TraitAlias(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.name.as_str()), ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { @@ -222,7 +223,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let def_data = match ti.node { TraitItemKind::Method(..) | TraitItemKind::Const(..) => DefPathData::ValueNs(ti.ident.name.as_str()), - TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()), + TraitItemKind::Type(..) => DefPathData::AssocTypeInTrait(ti.ident.name.as_str()), TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false), }; @@ -240,7 +241,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let def_data = match ii.node { ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name.as_str()), - ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()), + ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_str()), ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false), }; diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 1a2840de447de..12f146ef49115 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -212,6 +212,9 @@ impl DefKey { ::std::mem::discriminant(data).hash(&mut hasher); match *data { DefPathData::TypeNs(name) | + DefPathData::Trait(name) | + DefPathData::AssocTypeInTrait(name) | + DefPathData::AssocTypeInImpl(name) | DefPathData::ValueNs(name) | DefPathData::Module(name) | DefPathData::MacroDef(name) | @@ -358,6 +361,12 @@ pub enum DefPathData { // Different kinds of items and item-like things: /// An impl Impl, + /// A trait + Trait(InternedString), + /// An associated type **declaration** (i.e., in a trait) + AssocTypeInTrait(InternedString), + /// An associated type **value** (i.e., in an impl) + AssocTypeInImpl(InternedString), /// Something in the type NS TypeNs(InternedString), /// Something in the value NS @@ -639,6 +648,9 @@ impl DefPathData { use self::DefPathData::*; match *self { TypeNs(name) | + Trait(name) | + AssocTypeInTrait(name) | + AssocTypeInImpl(name) | ValueNs(name) | Module(name) | MacroDef(name) | @@ -663,6 +675,9 @@ impl DefPathData { use self::DefPathData::*; let s = match *self { TypeNs(name) | + Trait(name) | + AssocTypeInTrait(name) | + AssocTypeInImpl(name) | ValueNs(name) | Module(name) | MacroDef(name) | diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 8189064db6968..2819141c81be2 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -204,6 +204,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // finer-grained distinctions, e.g. between enum/struct). data @ DefPathData::Misc | data @ DefPathData::TypeNs(..) | + data @ DefPathData::Trait(..) | + data @ DefPathData::AssocTypeInTrait(..) | + data @ DefPathData::AssocTypeInImpl(..) | data @ DefPathData::ValueNs(..) | data @ DefPathData::Module(..) | data @ DefPathData::TypeParam(..) | diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index dd478967b185a..84e3358ff1389 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -268,14 +268,31 @@ impl PrintContext { loop { let key = tcx.def_key(item_def_id); match key.disambiguated_data.data { + DefPathData::AssocTypeInTrait(_) | + DefPathData::AssocTypeInImpl(_) | + DefPathData::Trait(_) | DefPathData::TypeNs(_) => { break; } - DefPathData::ValueNs(_) | DefPathData::EnumVariant(_) => { + DefPathData::ValueNs(_) | + DefPathData::EnumVariant(_) => { is_value_path = true; break; } - _ => { + DefPathData::CrateRoot | + DefPathData::Misc | + DefPathData::Impl | + DefPathData::Module(_) | + DefPathData::MacroDef(_) | + DefPathData::ClosureExpr | + DefPathData::TypeParam(_) | + DefPathData::LifetimeDef(_) | + DefPathData::Field(_) | + DefPathData::StructCtor | + DefPathData::Initializer | + DefPathData::ImplTrait | + DefPathData::Typeof | + DefPathData::GlobalMetaData(_) => { // if we're making a symbol for something, there ought // to be a value or type-def or something in there // *somewhere* From 94639ca40697b0cb06a6c6ec77c42ec152b9b899 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 10 Apr 2018 05:56:35 -0400 Subject: [PATCH 5/9] rustfmt lowering.rs --- src/librustc_traits/lowering.rs | 109 +++++++++++++++++--------------- 1 file changed, 59 insertions(+), 50 deletions(-) diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index 36e60cee788dc..ca785e5e05863 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir::{self, ImplPolarity}; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc::ty::{self, Slice, TyCtxt}; +use rustc::traits::{Clause, DomainGoal, Goal, PolyDomainGoal, ProgramClause, WhereClauseAtom}; use rustc::ty::subst::Substs; -use rustc::traits::{WhereClauseAtom, PolyDomainGoal, DomainGoal, ProgramClause, Clause, Goal}; -use syntax::ast; +use rustc::ty::{self, Slice, TyCtxt}; use rustc_data_structures::sync::Lrc; +use syntax::ast; +use syntax::ast; use std::iter; @@ -24,7 +24,10 @@ trait Lower { fn lower(&self) -> T; } -impl Lower> for Vec where T: Lower { +impl Lower> for Vec +where + T: Lower, +{ fn lower(&self) -> Vec { self.iter().map(|item| item.lower()).collect() } @@ -42,7 +45,10 @@ impl<'tcx> Lower> for ty::ProjectionPredicate<'tcx> { } } -impl<'tcx, T> Lower> for T where T: Lower> { +impl<'tcx, T> Lower> for T +where + T: Lower>, +{ fn lower(&self) -> DomainGoal<'tcx> { DomainGoal::Holds(self.lower()) } @@ -67,7 +73,8 @@ impl<'tcx> Lower> for ty::TypeOutlivesPredicate<'tcx> { /// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like /// `Binder`. impl<'tcx, T> Lower> for ty::Binder - where T: Lower> + ty::fold::TypeFoldable<'tcx> +where + T: Lower> + ty::fold::TypeFoldable<'tcx>, { fn lower(&self) -> PolyDomainGoal<'tcx> { self.map_bound_ref(|p| p.lower()) @@ -84,10 +91,9 @@ impl<'tcx> Lower> for ty::Predicate<'tcx> { TypeOutlives(predicate) => predicate.lower(), Projection(predicate) => predicate.lower(), WellFormed(ty) => ty::Binder::dummy(DomainGoal::WellFormedTy(*ty)), - ObjectSafe(..) | - ClosureKind(..) | - Subtype(..) | - ConstEvaluatable(..) => unimplemented!(), + ObjectSafe(..) | ClosureKind(..) | Subtype(..) | ConstEvaluatable(..) => { + unimplemented!() + } } } } @@ -104,20 +110,16 @@ impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { use self::DomainGoal::*; match self { Holds(wc_atom) => FromEnv(wc_atom), - WellFormed(..) | - FromEnv(..) | - WellFormedTy(..) | - FromEnvTy(..) | - Normalize(..) | - RegionOutlives(..) | - TypeOutlives(..) => self, + WellFormed(..) | FromEnv(..) | WellFormedTy(..) | FromEnvTy(..) | Normalize(..) + | RegionOutlives(..) | TypeOutlives(..) => self, } } } -crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc<&'tcx Slice>> -{ +crate fn program_clauses_for<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, +) -> Lrc<&'tcx Slice>> { let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let node = tcx.hir.find(node_id).unwrap(); match node { @@ -125,23 +127,24 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI 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::())), - } + }, 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::())) } - }, + } // FIXME: other constructions e.g. traits, associated types... _ => Lrc::new(tcx.mk_clauses(iter::empty::())), } } -fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc<&'tcx Slice>> -{ +fn program_clauses_for_trait<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, +) -> Lrc<&'tcx Slice>> { // `trait Trait where WC { .. } // P0 == Self` // Rule Implemented-From-Env (see rustc guide) @@ -156,8 +159,8 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI let trait_pred = ty::TraitPredicate { trait_ref: ty::TraitRef { def_id, - substs: Substs::identity_for_item(tcx, def_id) - } + substs: Substs::identity_for_item(tcx, def_id), + }, }; // `FromEnv(Self: Trait)` let from_env = Goal::from(DomainGoal::FromEnv(trait_pred.lower())); @@ -169,9 +172,7 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI goal: impl_trait, hypotheses: tcx.mk_goals(iter::once(from_env)), }; - let clauses = iter::once( - Clause::ForAll(ty::Binder::dummy(implemented_from_env)) - ); + let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env))); // Rule Implied-Bound-From-Trait // @@ -186,8 +187,8 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI // 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() + let implied_bound_clauses = where_clauses[1..] + .into_iter() .map(|wc| implied_bound_from_trait(tcx, trait_pred, wc)); Lrc::new(tcx.mk_clauses(clauses.chain(implied_bound_clauses))) @@ -203,17 +204,16 @@ fn implied_bound_from_trait<'a, 'tcx>( 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: tcx.mk_goals(iter::once(Goal::from(impl_trait))), - }) - ) + Clause::ForAll(where_clause.lower().map_bound(|goal| ProgramClause { + goal: goal.into_from_env_goal(), + hypotheses: tcx.mk_goals(iter::once(Goal::from(impl_trait))), + })) } -fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc<&'tcx Slice>> -{ +fn program_clauses_for_impl<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, +) -> Lrc<&'tcx Slice>> { if let ImplPolarity::Negative = tcx.impl_polarity(def_id) { return Lrc::new(tcx.mk_clauses(iter::empty::())); } @@ -231,15 +231,17 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId let trait_ref = tcx.impl_trait_ref(def_id).unwrap(); // `Implemented(A0: Trait)` let trait_pred = ty::TraitPredicate { trait_ref }.lower(); - // `WC` + // `WC` let where_clauses = tcx.predicates_of(def_id).predicates.lower(); - // `Implemented(A0: Trait) :- WC` + // `Implemented(A0: Trait) :- WC` let clause = ProgramClause { goal: trait_pred, hypotheses: tcx.mk_goals( - where_clauses.into_iter().map(|wc| Goal::from_poly_domain_goal(wc, tcx)) - ) + where_clauses + .into_iter() + .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), + ), }; Lrc::new(tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))) } @@ -290,7 +292,9 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>( let clause = ProgramClause { goal: normalize_goal, hypotheses: tcx.mk_goals( - where_clauses.into_iter().map(|wc| Goal::from_poly_domain_goal(wc, tcx)) + where_clauses + .into_iter() + .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), ), }; Lrc::new(tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))) @@ -302,14 +306,16 @@ pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { } let mut visitor = ClauseDumper { tcx }; - tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); + tcx.hir + .krate() + .visit_all_item_likes(&mut visitor.as_deep_visitor()); } struct ClauseDumper<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, } -impl<'a, 'tcx> ClauseDumper<'a, 'tcx > { +impl<'a, 'tcx> ClauseDumper<'a, 'tcx> { fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) { let def_id = self.tcx.hir.local_def_id(node_id); for attr in attrs { @@ -321,7 +327,10 @@ impl<'a, 'tcx> ClauseDumper<'a, 'tcx > { Clause::Implies(program_clause) => program_clause, Clause::ForAll(program_clause) => program_clause.skip_binder(), }; - self.tcx.sess.struct_span_err(attr.span, &format!("{}", program_clause)).emit(); + self.tcx + .sess + .struct_span_err(attr.span, &format!("{}", program_clause)) + .emit(); } } } From 7173fd78c62c84dffbf0c05c895a2ec57fe170af Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 18 Apr 2018 19:58:22 -0400 Subject: [PATCH 6/9] in unit tests, use `note` to dump multiple program clauses (rather than issuing multiple errors) Also, reorder so that the annotations are considered "used" when the lint runs. --- src/librustc_driver/driver.rs | 8 +-- src/librustc_traits/lowering.rs | 25 +++++++--- src/test/ui/chalkify/lower_impl.rs | 4 +- src/test/ui/chalkify/lower_impl.stderr | 12 +++-- src/test/ui/chalkify/lower_trait.rs | 5 +- src/test/ui/chalkify/lower_trait.stderr | 27 +++------- .../ui/chalkify/lower_trait_higher_rank.rs | 5 +- .../chalkify/lower_trait_higher_rank.stderr | 27 +++------- .../ui/chalkify/lower_trait_where_clause.rs | 8 +-- .../chalkify/lower_trait_where_clause.stderr | 50 ++++--------------- 10 files changed, 61 insertions(+), 110 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 2c781fda4ed03..2fb811eba1e9a 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1155,6 +1155,10 @@ where } }); + time(sess, "dumping chalk-like clauses", || { + rustc_traits::lowering::dump_program_clauses(tcx); + }); + time(sess, "MIR effect checking", || { for def_id in tcx.body_owners() { mir::transform::check_unsafety::check_unsafety(tcx, def_id) @@ -1178,10 +1182,6 @@ where time(sess, "lint checking", || lint::check_crate(tcx)); - time(sess, "dumping chalk-like clauses", || { - rustc_traits::lowering::dump_program_clauses(tcx) - }); - return Ok(f(tcx, analysis, rx, tcx.sess.compile_status())); }, ) diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index ca785e5e05863..942cf7a657130 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -319,19 +319,32 @@ impl<'a, 'tcx> ClauseDumper<'a, 'tcx> { fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) { let def_id = self.tcx.hir.local_def_id(node_id); for attr in attrs { + let mut clauses = None; + if attr.check_name("rustc_dump_program_clauses") { - let clauses = self.tcx.program_clauses_for(def_id); - for clause in *clauses { + clauses = Some(self.tcx.program_clauses_for(def_id)); + } + + if attr.check_name("rustc_dump_env_program_clauses") { + let param_env = self.tcx.param_env(def_id); + clauses = Some(self.tcx.program_clauses_for_env(param_env)); + } + + if let Some(clauses) = clauses { + let mut err = self.tcx + .sess + .struct_span_err(attr.span, "program clause dump"); + + for clause in clauses.iter() { // Skip the top-level binder for a less verbose output let program_clause = match clause { Clause::Implies(program_clause) => program_clause, Clause::ForAll(program_clause) => program_clause.skip_binder(), }; - self.tcx - .sess - .struct_span_err(attr.span, &format!("{}", program_clause)) - .emit(); + err.note(&format!("{}", program_clause)); } + + err.emit(); } } } diff --git a/src/test/ui/chalkify/lower_impl.rs b/src/test/ui/chalkify/lower_impl.rs index 671d77efbea3a..b38b87cdb1236 100644 --- a/src/test/ui/chalkify/lower_impl.rs +++ b/src/test/ui/chalkify/lower_impl.rs @@ -12,7 +12,7 @@ trait Foo { } -#[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :- +#[rustc_dump_program_clauses] //~ ERROR program clause dump impl Foo for T where T: Iterator { } trait Bar { @@ -20,7 +20,7 @@ trait Bar { } impl Bar for T where T: Iterator { - #[rustc_dump_program_clauses] //~ ERROR Normalize(::Assoc == std::vec::Vec) :- + #[rustc_dump_program_clauses] //~ ERROR program clause dump type Assoc = Vec; } diff --git a/src/test/ui/chalkify/lower_impl.stderr b/src/test/ui/chalkify/lower_impl.stderr index f253f9847d162..c497d76f8d4f9 100644 --- a/src/test/ui/chalkify/lower_impl.stderr +++ b/src/test/ui/chalkify/lower_impl.stderr @@ -1,14 +1,18 @@ -error: Implemented(T: Foo) :- ProjectionEq(::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). +error: program clause dump --> $DIR/lower_impl.rs:15:1 | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :- +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Implemented(T: Foo) :- ProjectionEq(::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). -error: Normalize(::Assoc == std::vec::Vec) :- Implemented(T: Bar). +error: program clause dump --> $DIR/lower_impl.rs:23:5 | -LL | #[rustc_dump_program_clauses] //~ ERROR Normalize(::Assoc == std::vec::Vec) :- +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Normalize(::Assoc == std::vec::Vec) :- Implemented(T: Bar). error: aborting due to 2 previous errors diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs index 74feb0105ccf1..7c0f233a645cb 100644 --- a/src/test/ui/chalkify/lower_trait.rs +++ b/src/test/ui/chalkify/lower_trait.rs @@ -10,10 +10,7 @@ #![feature(rustc_attrs)] -#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- - //~| ERROR FromEnv - //~| ERROR FromEnv - //~| ERROR FromEnv +#[rustc_dump_program_clauses] //~ ERROR program clause dump 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 45753c3bb90c2..2bd836a8fc143 100644 --- a/src/test/ui/chalkify/lower_trait.stderr +++ b/src/test/ui/chalkify/lower_trait.stderr @@ -1,26 +1,13 @@ -error: Implemented(Self: Foo) :- FromEnv(Self: Foo). +error: program clause dump --> $DIR/lower_trait.rs:13:1 | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -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) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). + = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo). + = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo). + = note: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo). -error: aborting due to 4 previous errors +error: aborting due to previous error diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.rs b/src/test/ui/chalkify/lower_trait_higher_rank.rs index e5eaf4591ece8..47e9398d3647e 100644 --- a/src/test/ui/chalkify/lower_trait_higher_rank.rs +++ b/src/test/ui/chalkify/lower_trait_higher_rank.rs @@ -10,10 +10,7 @@ #![feature(rustc_attrs)] -#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- - //~| ERROR FromEnv - //~| ERROR FromEnv - //~| ERROR FromEnv +#[rustc_dump_program_clauses] //~ ERROR program clause dump trait Foo where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8 { fn s(F) -> F; diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr index 9aed0c018c947..11dc87401802a 100644 --- a/src/test/ui/chalkify/lower_trait_higher_rank.stderr +++ b/src/test/ui/chalkify/lower_trait_higher_rank.stderr @@ -1,26 +1,13 @@ -error: Implemented(Self: Foo) :- FromEnv(Self: Foo). +error: program clause dump --> $DIR/lower_trait_higher_rank.rs:13:1 | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -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) :- - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). + = note: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo). + = note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo). + = note: FromEnv(>::Output == &'a u8) :- FromEnv(Self: Foo). -error: aborting due to 4 previous errors +error: aborting due to previous error diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs index b2ce3ca48b27a..67ee7c28b6a4e 100644 --- a/src/test/ui/chalkify/lower_trait_where_clause.rs +++ b/src/test/ui/chalkify/lower_trait_where_clause.rs @@ -13,13 +13,7 @@ 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 +#[rustc_dump_program_clauses] //~ ERROR program clause dump 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; diff --git a/src/test/ui/chalkify/lower_trait_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr index a9ecaec3aff9e..cfea1379dabef 100644 --- a/src/test/ui/chalkify/lower_trait_where_clause.stderr +++ b/src/test/ui/chalkify/lower_trait_where_clause.stderr @@ -1,44 +1,16 @@ -error: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). +error: program clause dump --> $DIR/lower_trait_where_clause.rs:16:1 | -LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :- +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -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 + = note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: FromEnv(T: std::borrow::Borrow) :- 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>). + +error: aborting due to previous error From 294cae22ee473f34928f5b24ec977132011e3699 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 10 Apr 2018 05:55:18 -0400 Subject: [PATCH 7/9] first draft of `program_clauses_for_env` 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 | 1 + src/librustc/ty/maps/config.rs | 6 ++ src/librustc/ty/maps/keys.rs | 9 +++ src/librustc/ty/maps/mod.rs | 4 ++ src/librustc/ty/maps/plumbing.rs | 1 + src/librustc/ty/mod.rs | 5 ++ src/librustc_traits/lib.rs | 1 + src/librustc_traits/lowering.rs | 88 ++++++++++++++++++++------ src/test/ui/chalkify/lower_env1.rs | 24 +++++++ src/test/ui/chalkify/lower_env1.stderr | 24 +++++++ 10 files changed, 145 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/chalkify/lower_env1.rs create mode 100644 src/test/ui/chalkify/lower_env1.stderr diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index b4f39439d5b4d..18bf54297afc6 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -655,6 +655,7 @@ define_dep_nodes!( <'tcx> [input] Features, [] ProgramClausesFor(DefId), + [] ProgramClausesForEnv(ParamEnv<'tcx>), [] WasmImportModuleMap(CrateNum), [] ForeignModules(CrateNum), diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index fea7de955e0bf..735fe06560f5f 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -717,6 +717,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> { } } +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") diff --git a/src/librustc/ty/maps/keys.rs b/src/librustc/ty/maps/keys.rs index b8167ec918638..72f2cb49abc0e 100644 --- a/src/librustc/ty/maps/keys.rs +++ b/src/librustc/ty/maps/keys.rs @@ -154,6 +154,15 @@ impl<'tcx> Key for Ty<'tcx> { } } +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() diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 0ab9f16dab481..368e9dc0fadca 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -447,6 +447,10 @@ define_maps! { <'tcx> [] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<&'tcx Slice>>, + [] fn program_clauses_for_env: ProgramClausesForEnv( + ty::ParamEnv<'tcx> + ) -> Lrc<&'tcx Slice>>, + [] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc>, [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum) -> Lrc>, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 8d6c7474a9f94..70fbd17e6cbb0 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -978,6 +978,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::DropckOutlives | DepKind::SubstituteNormalizeAndTestPredicates | DepKind::InstanceDefSizeEstimate | + DepKind::ProgramClausesForEnv | // This one should never occur in this context DepKind::Null => { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c3d2d5675de05..1524d4b9e7f62 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1138,6 +1138,11 @@ pub struct ProjectionPredicate<'tcx> { pub type PolyProjectionPredicate<'tcx> = Binder>; 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. diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs index 8136f6857a5c6..90c870096e179 100644 --- a/src/librustc_traits/lib.rs +++ b/src/librustc_traits/lib.rs @@ -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 }; } diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index 942cf7a657130..25a3621fd00b6 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -10,11 +10,14 @@ 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 @@ crate fn program_clauses_for<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, ) -> Lrc<&'tcx Slice>> { - 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::())), - }, - 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::())) - } - } + 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>> { + 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::())), + 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 { + 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 index 0000000000000..fc20ad0e08b2a --- /dev/null +++ b/src/test/ui/chalkify/lower_env1.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)] +#![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() { +} + +fn main() { +} diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr new file mode 100644 index 0000000000000..aaf74f1095a4b --- /dev/null +++ b/src/test/ui/chalkify/lower_env1.stderr @@ -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 + From 7fa3c8f445fa29db82231ea56fd6eebf37a806f2 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 23 Apr 2018 13:12:00 -0400 Subject: [PATCH 8/9] eliminate the `Lrc` of a slice and just return the slice Also, introduce `Clauses` and `Goals` type alises for readability. --- src/librustc/traits/mod.rs | 9 ++++++-- src/librustc/ty/context.rs | 12 +++++------ src/librustc/ty/maps/mod.rs | 8 +++---- src/librustc_traits/lowering.rs | 37 ++++++++++++++------------------- 4 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index b05c4539f6a49..5bfea1631894b 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -282,7 +282,7 @@ pub enum QuantifierKind { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum Goal<'tcx> { - Implies(&'tcx Slice>, &'tcx Goal<'tcx>), + Implies(Clauses<'tcx>, &'tcx Goal<'tcx>), And(&'tcx Goal<'tcx>, &'tcx Goal<'tcx>), Not(&'tcx Goal<'tcx>), DomainGoal(DomainGoal<'tcx>), @@ -290,6 +290,8 @@ pub enum Goal<'tcx> { CannotProve, } +pub type Goals<'tcx> = &'tcx Slice>; + impl<'tcx> Goal<'tcx> { pub fn from_poly_domain_goal<'a>( domain_goal: PolyDomainGoal<'tcx>, @@ -319,6 +321,9 @@ pub enum Clause<'tcx> { ForAll(ty::Binder>), } +/// Multiple clauses. +pub type Clauses<'tcx> = &'tcx Slice>; + /// A "program clause" has the form `D :- G1, ..., Gn`. It is saying /// that the domain goal `D` is true if `G1...Gn` are provable. This /// is equivalent to the implication `G1..Gn => D`; we usually write @@ -331,7 +336,7 @@ pub struct ProgramClause<'tcx> { pub goal: DomainGoal<'tcx>, /// ...if we can prove these hypotheses (there may be no hypotheses at all): - pub hypotheses: &'tcx Slice>, + pub hypotheses: Goals<'tcx>, } pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index f3a2aa519465c..56669243f273a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -38,7 +38,7 @@ use ty::subst::{Kind, Substs}; use ty::ReprOptions; use ty::Instance; use traits; -use traits::{Clause, Goal}; +use traits::{Clause, Clauses, Goal, Goals}; use ty::{self, Ty, TypeAndMut}; use ty::{TyS, TypeVariants, Slice}; use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorInterior, Region, Const}; @@ -2517,7 +2517,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> &'tcx Slice> { + pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> Clauses<'tcx> { if ts.len() == 0 { Slice::empty() } else { @@ -2525,7 +2525,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> &'tcx Slice> { + pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> Goals<'tcx> { if ts.len() == 0 { Slice::empty() } else { @@ -2579,13 +2579,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from)) } - pub fn mk_clauses], - &'tcx Slice>>>(self, iter: I) -> I::Output { + pub fn mk_clauses], Clauses<'tcx>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_clauses(xs)) } - pub fn mk_goals], - &'tcx Slice>>>(self, iter: I) -> I::Output { + pub fn mk_goals], Goals<'tcx>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_goals(xs)) } diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 368e9dc0fadca..92d23d4338f9d 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -37,8 +37,8 @@ use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal, NoSolution}; use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult}; use traits::query::normalize::NormalizationResult; use traits::specialization_graph; -use traits::Clause; -use ty::{self, CrateInherentImpls, ParamEnvAnd, Slice, Ty, TyCtxt}; +use traits::Clauses; +use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt}; use ty::steal::Steal; use ty::subst::Substs; use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet}; @@ -445,11 +445,11 @@ define_maps! { <'tcx> [] fn features_query: features_node(CrateNum) -> Lrc, - [] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<&'tcx Slice>>, + [] fn program_clauses_for: ProgramClausesFor(DefId) -> Clauses<'tcx>, [] fn program_clauses_for_env: ProgramClausesForEnv( ty::ParamEnv<'tcx> - ) -> Lrc<&'tcx Slice>>, + ) -> Clauses<'tcx>, [] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc>, [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum) diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index 25a3621fd00b6..8acc77be60d4f 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -12,11 +12,11 @@ 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::traits::{Clause, Clauses, 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 std::mem; use syntax::ast; @@ -122,19 +122,19 @@ impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> { crate fn program_clauses_for<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> Lrc<&'tcx Slice>> { +) -> Clauses<'tcx> { 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()), + _ => Slice::empty(), } } crate fn program_clauses_for_env<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, -) -> Lrc<&'tcx Slice>> { +) -> Clauses<'tcx> { debug!("program_clauses_for_env(param_env={:?})", param_env); let mut last_round = FxHashSet(); @@ -164,12 +164,10 @@ crate fn program_clauses_for_env<'a, 'tcx>( debug!("program_clauses_for_env: closure = {:#?}", closure); - return Lrc::new( - tcx.mk_clauses( - closure - .into_iter() - .flat_map(|def_id| tcx.program_clauses_for(def_id).iter().cloned()), - ), + return 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 @@ -196,7 +194,7 @@ crate fn program_clauses_for_env<'a, 'tcx>( fn program_clauses_for_trait<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> Lrc<&'tcx Slice>> { +) -> Clauses<'tcx> { // `trait Trait where WC { .. } // P0 == Self` // Rule Implemented-From-Env (see rustc guide) @@ -243,7 +241,7 @@ fn program_clauses_for_trait<'a, 'tcx>( .into_iter() .map(|wc| implied_bound_from_trait(tcx, trait_pred, wc)); - Lrc::new(tcx.mk_clauses(clauses.chain(implied_bound_clauses))) + tcx.mk_clauses(clauses.chain(implied_bound_clauses)) } /// For a given `where_clause`, returns a clause `FromEnv(WC) :- FromEnv(Self: Trait)`. @@ -262,12 +260,9 @@ fn implied_bound_from_trait<'a, 'tcx>( })) } -fn program_clauses_for_impl<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId, -) -> Lrc<&'tcx Slice>> { +fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Clauses<'tcx> { if let ImplPolarity::Negative = tcx.impl_polarity(def_id) { - return Lrc::new(tcx.mk_clauses(iter::empty::())); + return Slice::empty(); } // Rule Implemented-From-Impl (see rustc guide) @@ -295,13 +290,13 @@ fn program_clauses_for_impl<'a, 'tcx>( .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), ), }; - Lrc::new(tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))) + tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))) } pub fn program_clauses_for_associated_type_value<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: DefId, -) -> Lrc<&'tcx Slice>> { +) -> Clauses<'tcx> { // Rule Normalize-From-Impl (see rustc guide) // // ```impl Trait for A0 @@ -349,7 +344,7 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>( .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), ), }; - Lrc::new(tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))) + tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))) } pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { From 2c5fbe20585e69801d4db95ac587e7c452058c79 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 17 Apr 2018 06:06:33 -0400 Subject: [PATCH 9/9] sort strings on output --- src/librustc_traits/lowering.rs | 23 +++++++++++++------ src/test/ui/chalkify/lower_env1.stderr | 6 ++--- src/test/ui/chalkify/lower_trait.stderr | 2 +- .../chalkify/lower_trait_higher_rank.stderr | 4 ++-- .../chalkify/lower_trait_where_clause.stderr | 6 ++--- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index 8acc77be60d4f..b6a086f609d04 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -382,13 +382,22 @@ impl<'a, 'tcx> ClauseDumper<'a, 'tcx> { .sess .struct_span_err(attr.span, "program clause dump"); - for clause in clauses.iter() { - // Skip the top-level binder for a less verbose output - let program_clause = match clause { - Clause::Implies(program_clause) => program_clause, - Clause::ForAll(program_clause) => program_clause.skip_binder(), - }; - err.note(&format!("{}", program_clause)); + let mut strings: Vec<_> = clauses + .iter() + .map(|clause| { + // Skip the top-level binder for a less verbose output + let program_clause = match clause { + Clause::Implies(program_clause) => program_clause, + Clause::ForAll(program_clause) => program_clause.skip_binder(), + }; + format!("{}", program_clause) + }) + .collect(); + + strings.sort(); + + for string in strings { + err.note(&string); } err.emit(); diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr index aaf74f1095a4b..3a280f85e7694 100644 --- a/src/test/ui/chalkify/lower_env1.stderr +++ b/src/test/ui/chalkify/lower_env1.stderr @@ -4,9 +4,9 @@ error: program clause dump 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). + = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). error: program clause dump --> $DIR/lower_env1.rs:19:1 @@ -14,11 +14,11 @@ error: program clause dump 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: Bar) :- FromEnv(Self: Bar). = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). + = note: Implemented(Self: std::marker::Sized) :- FromEnv(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 2bd836a8fc143..55cd9699b0616 100644 --- a/src/test/ui/chalkify/lower_trait.stderr +++ b/src/test/ui/chalkify/lower_trait.stderr @@ -4,10 +4,10 @@ error: program clause dump LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo). = 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). 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 11dc87401802a..7f6f503c6ff72 100644 --- a/src/test/ui/chalkify/lower_trait_higher_rank.stderr +++ b/src/test/ui/chalkify/lower_trait_higher_rank.stderr @@ -4,10 +4,10 @@ error: program clause dump LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). + = note: FromEnv(>::Output == &'a u8) :- FromEnv(Self: Foo). = note: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo). = note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo). - = note: FromEnv(>::Output == &'a u8) :- FromEnv(Self: Foo). + = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). 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 cfea1379dabef..68bc2ddf2930e 100644 --- a/src/test/ui/chalkify/lower_trait_where_clause.stderr +++ b/src/test/ui/chalkify/lower_trait_where_clause.stderr @@ -4,11 +4,11 @@ error: program clause dump 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: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). - = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). = note: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). = note: FromEnv(T: std::borrow::Borrow) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). + = 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>).