Auto merge of #49837 - nikomatsakis:chalkify-engine, r=scalexm
work towards chalkify-ing the engine This work towards creating a "all program clauses needed for this goal" query r? @scalexm
This commit is contained in:
commit
898c9f7d71
@ -655,6 +655,7 @@ define_dep_nodes!( <'tcx>
|
||||
[input] Features,
|
||||
|
||||
[] ProgramClausesFor(DefId),
|
||||
[] ProgramClausesForEnv(ParamEnv<'tcx>),
|
||||
[] WasmImportModuleMap(CrateNum),
|
||||
[] ForeignModules(CrateNum),
|
||||
|
||||
|
@ -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),
|
||||
};
|
||||
|
||||
|
@ -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) |
|
||||
|
@ -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<StableHashingContext<'a>> for traits::Goal<'tcx> {
|
||||
quantifier.hash_stable(hcx, hasher);
|
||||
goal.hash_stable(hcx, hasher);
|
||||
},
|
||||
CannotProve => { },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<QueryRegionConstraint<'tcx>>,
|
||||
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<ty::OutlivesPredicate<Kind<'tcx>, 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<Item = PredicateObligation<'tcx>> + 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);
|
||||
) -> impl Iterator<Item = PredicateObligation<'tcx>> + '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::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r1, r2))),
|
||||
)
|
||||
});
|
||||
match k1.unpack() {
|
||||
UnpackedKind::Lifetime(r1) =>
|
||||
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);
|
||||
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)
|
||||
UnpackedKind::Type(t1) =>
|
||||
Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t1, r2))),
|
||||
),
|
||||
}
|
||||
})) as Box<dyn Iterator<Item = _>>
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
@ -1289,6 +1289,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
"tell the linker to strip debuginfo when building without debuginfo enabled."),
|
||||
share_generics: Option<bool> = (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 {
|
||||
|
@ -282,13 +282,16 @@ pub enum QuantifierKind {
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum Goal<'tcx> {
|
||||
Implies(&'tcx Slice<Clause<'tcx>>, &'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<Goal<'tcx>>;
|
||||
|
||||
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<ProgramClause<'tcx>>),
|
||||
}
|
||||
|
||||
/// Multiple clauses.
|
||||
pub type Clauses<'tcx> = &'tcx Slice<Clause<'tcx>>;
|
||||
|
||||
/// 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<Goal<'tcx>>,
|
||||
pub hypotheses: Goals<'tcx>,
|
||||
}
|
||||
|
||||
pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<Clause<'tcx>> {
|
||||
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<Goal<'tcx>> {
|
||||
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<I: InternAs<[Clause<'tcx>],
|
||||
&'tcx Slice<Clause<'tcx>>>>(self, iter: I) -> I::Output {
|
||||
pub fn mk_clauses<I: InternAs<[Clause<'tcx>], Clauses<'tcx>>>(self, iter: I) -> I::Output {
|
||||
iter.intern_with(|xs| self.intern_clauses(xs))
|
||||
}
|
||||
|
||||
pub fn mk_goals<I: InternAs<[Goal<'tcx>],
|
||||
&'tcx Slice<Goal<'tcx>>>>(self, iter: I) -> I::Output {
|
||||
pub fn mk_goals<I: InternAs<[Goal<'tcx>], Goals<'tcx>>>(self, iter: I) -> I::Output {
|
||||
iter.intern_with(|xs| self.intern_goals(xs))
|
||||
}
|
||||
|
||||
|
@ -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(..) |
|
||||
|
@ -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")
|
||||
|
@ -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()
|
||||
|
@ -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<feature_gate::Features>,
|
||||
|
||||
[] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<&'tcx Slice<Clause<'tcx>>>,
|
||||
[] 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<Vec<DefId>>,
|
||||
[] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
|
||||
|
@ -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 => {
|
||||
|
@ -1138,6 +1138,11 @@ pub struct ProjectionPredicate<'tcx> {
|
||||
pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
|
||||
|
||||
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.
|
||||
|
@ -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*
|
||||
|
@ -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()));
|
||||
},
|
||||
)
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -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<T> {
|
||||
fn lower(&self) -> T;
|
||||
}
|
||||
|
||||
impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> {
|
||||
impl<T, U> Lower<Vec<U>> for Vec<T>
|
||||
where
|
||||
T: Lower<U>,
|
||||
{
|
||||
fn lower(&self) -> Vec<U> {
|
||||
self.iter().map(|item| item.lower()).collect()
|
||||
}
|
||||
@ -42,7 +48,10 @@ impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::ProjectionPredicate<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> {
|
||||
impl<'tcx, T> Lower<DomainGoal<'tcx>> for T
|
||||
where
|
||||
T: Lower<WhereClauseAtom<'tcx>>,
|
||||
{
|
||||
fn lower(&self) -> DomainGoal<'tcx> {
|
||||
DomainGoal::Holds(self.lower())
|
||||
}
|
||||
@ -67,7 +76,8 @@ impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
|
||||
/// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
|
||||
/// `Binder<Holds(Implemented(TraitPredicate))>`.
|
||||
impl<'tcx, T> Lower<PolyDomainGoal<'tcx>> for ty::Binder<T>
|
||||
where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx>
|
||||
where
|
||||
T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx>,
|
||||
{
|
||||
fn lower(&self) -> PolyDomainGoal<'tcx> {
|
||||
self.map_bound_ref(|p| p.lower())
|
||||
@ -84,10 +94,9 @@ impl<'tcx> Lower<PolyDomainGoal<'tcx>> 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<Clause<'tcx>>>
|
||||
{
|
||||
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::<Clause>())),
|
||||
}
|
||||
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::<Clause>()))
|
||||
}
|
||||
},
|
||||
|
||||
// FIXME: other constructions e.g. traits, associated types...
|
||||
_ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
|
||||
-> Lrc<&'tcx Slice<Clause<'tcx>>>
|
||||
{
|
||||
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<DefId> {
|
||||
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,
|
||||
) -> Clauses<'tcx> {
|
||||
// `trait Trait<P1..Pn> 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<P1..Pn>)`
|
||||
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<P1..Pn>`).
|
||||
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<P1..Pn>)`.
|
||||
@ -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<P1..Pn>)`
|
||||
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<Clause<'tcx>>>
|
||||
{
|
||||
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::<Clause>()));
|
||||
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<A1..An>)`
|
||||
let trait_pred = ty::TraitPredicate { trait_ref }.lower();
|
||||
// `WC`
|
||||
// `WC`
|
||||
let where_clauses = tcx.predicates_of(def_id).predicates.lower();
|
||||
|
||||
// `Implemented(A0: Trait<A1..An>) :- WC`
|
||||
// `Implemented(A0: Trait<A1..An>) :- 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<Clause<'tcx>>> {
|
||||
) -> Clauses<'tcx> {
|
||||
// Rule Normalize-From-Impl (see rustc guide)
|
||||
//
|
||||
// ```impl<P0..Pn> Trait<A1..An> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
});
|
||||
|
24
src/test/ui/chalkify/lower_env1.rs
Normal file
24
src/test/ui/chalkify/lower_env1.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T: Bar>() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
24
src/test/ui/chalkify/lower_env1.stderr
Normal file
24
src/test/ui/chalkify/lower_env1.stderr
Normal file
@ -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
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
trait Foo { }
|
||||
|
||||
#[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :-
|
||||
#[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||
impl<T: 'static> Foo for T where T: Iterator<Item = i32> { }
|
||||
|
||||
trait Bar {
|
||||
@ -20,7 +20,7 @@ trait Bar {
|
||||
}
|
||||
|
||||
impl<T> Bar for T where T: Iterator<Item = i32> {
|
||||
#[rustc_dump_program_clauses] //~ ERROR Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :-
|
||||
#[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||
type Assoc = Vec<T>;
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,18 @@
|
||||
error: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::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(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized).
|
||||
|
||||
error: Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- Implemented(T: Bar).
|
||||
error: program clause dump
|
||||
--> $DIR/lower_impl.rs:23:5
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :-
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- Implemented(T: Bar).
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -10,10 +10,7 @@
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
|
||||
//~| ERROR FromEnv
|
||||
//~| ERROR FromEnv
|
||||
//~| ERROR FromEnv
|
||||
#[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||
trait Foo<S, T, U> {
|
||||
fn s(S) -> S;
|
||||
fn t(T) -> T;
|
||||
|
@ -1,26 +1,13 @@
|
||||
error: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
|
||||
error: program clause dump
|
||||
--> $DIR/lower_trait.rs:13:1
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
|
||||
--> $DIR/lower_trait.rs:13:1
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
|
||||
= note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
|
||||
= note: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
|
||||
= note: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
|
||||
|
||||
error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
|
||||
--> $DIR/lower_trait.rs:13:1
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
|
||||
--> $DIR/lower_trait.rs:13:1
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -10,10 +10,7 @@
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
|
||||
//~| ERROR FromEnv
|
||||
//~| ERROR FromEnv
|
||||
//~| ERROR FromEnv
|
||||
#[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||
trait Foo<F> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
|
||||
{
|
||||
fn s(F) -> F;
|
||||
|
@ -1,26 +1,13 @@
|
||||
error: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
|
||||
error: program clause dump
|
||||
--> $DIR/lower_trait_higher_rank.rs:13:1
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>).
|
||||
--> $DIR/lower_trait_higher_rank.rs:13:1
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: FromEnv(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
|
||||
= note: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>).
|
||||
= note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
|
||||
= note: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
|
||||
|
||||
error: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
|
||||
--> $DIR/lower_trait_higher_rank.rs:13:1
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: FromEnv(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
|
||||
--> $DIR/lower_trait_higher_rank.rs:13:1
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -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>, U: ?Sized, 'a: 'b, U: 'b {
|
||||
fn s(S) -> S;
|
||||
fn t(T) -> T;
|
||||
|
@ -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>) :-
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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<U>) :- 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: 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<U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
|
||||
--> $DIR/lower_trait_where_clause.rs:16:1
|
||||
|
|
||||
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: 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
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user