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/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/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 70c152b40c0d2..322cfd55510bb 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 }); @@ -1417,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/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/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 { diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8d2398d34090d..5bfea1631894b 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -282,13 +282,16 @@ 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>), - Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>) + Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>), + CannotProve, } +pub type Goals<'tcx> = &'tcx Slice>; + impl<'tcx> Goal<'tcx> { pub fn from_poly_domain_goal<'a>( domain_goal: PolyDomainGoal<'tcx>, @@ -318,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 @@ -330,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/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), } } 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/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/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..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,7 +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> + ) -> Clauses<'tcx>, [] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc>, [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum) 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/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* 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/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 36e60cee788dc..b6a086f609d04 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -8,14 +8,17 @@ // 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::hir::map::definitions::DefPathData; +use rustc::hir::{self, ImplPolarity}; +use rustc::traits::{Clause, Clauses, DomainGoal, Goal, PolyDomainGoal, ProgramClause, + WhereClauseAtom}; use rustc::ty::subst::Substs; -use rustc::traits::{WhereClauseAtom, PolyDomainGoal, DomainGoal, ProgramClause, Clause, Goal}; +use rustc::ty::{self, Slice, TyCtxt}; +use rustc_data_structures::fx::FxHashSet; +use std::mem; use syntax::ast; -use rustc_data_structures::sync::Lrc; use std::iter; @@ -24,7 +27,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 +48,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 +76,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 +94,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,44 +113,88 @@ 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>> -{ - 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::())) - } - }, +crate fn program_clauses_for<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, +) -> 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), + _ => Slice::empty(), + } +} - // FIXME: other constructions e.g. traits, associated types... - _ => Lrc::new(tcx.mk_clauses(iter::empty::())), +crate fn program_clauses_for_env<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, +) -> Clauses<'tcx> { + 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); + + 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 + /// 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, + } } } -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, +) -> Clauses<'tcx> { // `trait Trait where WC { .. } // P0 == Self` // Rule Implemented-From-Env (see rustc guide) @@ -156,8 +209,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 +222,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,11 +237,11 @@ 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))) + tcx.mk_clauses(clauses.chain(implied_bound_clauses)) } /// For a given `where_clause`, returns a clause `FromEnv(WC) :- FromEnv(Self: Trait)`. @@ -203,19 +254,15 @@ 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) -> 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) @@ -231,23 +278,25 @@ 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))))) + 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 @@ -290,10 +339,12 @@ 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))))) + tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))) } pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { @@ -302,27 +353,54 @@ 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 { + 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 { - // 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(); + 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"); + + 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/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, }); 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..3a280f85e7694 --- /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: 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 + | +LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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_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..55cd9699b0616 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: 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 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..7f6f503c6ff72 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: 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: Implemented(Self: Foo) :- 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..68bc2ddf2930e 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: 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>). + +error: aborting due to previous error