Split traits::structural_impls in two.
This commit is contained in:
parent
b3f13b00f5
commit
9444975e96
3 changed files with 714 additions and 703 deletions
|
@ -1,13 +1,9 @@
|
|||
use crate::traits;
|
||||
use crate::traits::project::Normalized;
|
||||
use crate::ty;
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use crate::ty::{self, Lift, Ty, TyCtxt};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
|
||||
// Structural impls for the structs in `traits`.
|
||||
|
||||
|
@ -31,102 +27,6 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for traits::Obligation<'tcx, O> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::Vtable<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
super::VtableImpl(ref v) => write!(f, "{:?}", v),
|
||||
|
||||
super::VtableAutoImpl(ref t) => write!(f, "{:?}", t),
|
||||
|
||||
super::VtableClosure(ref d) => write!(f, "{:?}", d),
|
||||
|
||||
super::VtableGenerator(ref d) => write!(f, "{:?}", d),
|
||||
|
||||
super::VtableFnPointer(ref d) => write!(f, "VtableFnPointer({:?})", d),
|
||||
|
||||
super::VtableObject(ref d) => write!(f, "{:?}", d),
|
||||
|
||||
super::VtableParam(ref n) => write!(f, "VtableParam({:?})", n),
|
||||
|
||||
super::VtableBuiltin(ref d) => write!(f, "{:?}", d),
|
||||
|
||||
super::VtableTraitAlias(ref d) => write!(f, "{:?}", d),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableImplData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableImplData(impl_def_id={:?}, substs={:?}, nested={:?})",
|
||||
self.impl_def_id, self.substs, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableGeneratorData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})",
|
||||
self.generator_def_id, self.substs, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableClosureData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableClosureData(closure_def_id={:?}, substs={:?}, nested={:?})",
|
||||
self.closure_def_id, self.substs, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: fmt::Debug> fmt::Debug for traits::VtableBuiltinData<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "VtableBuiltinData(nested={:?})", self.nested)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: fmt::Debug> fmt::Debug for traits::VtableAutoImplData<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableAutoImplData(trait_def_id={:?}, nested={:?})",
|
||||
self.trait_def_id, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableObjectData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableObjectData(upcast={:?}, vtable_base={}, nested={:?})",
|
||||
self.upcast_trait_ref, self.vtable_base, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableFnPointerData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "VtableFnPointerData(fn_ty={:?}, nested={:?})", self.fn_ty, self.nested)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableTraitAliasData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableTraitAlias(alias_def_id={:?}, substs={:?}, nested={:?})",
|
||||
self.alias_def_id, self.substs, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)
|
||||
|
@ -152,531 +52,6 @@ impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::WhereClause<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::WhereClause::*;
|
||||
|
||||
// Bypass `ty::print` because it does not print out anonymous regions.
|
||||
// FIXME(eddyb) implement a custom `PrettyPrinter`, or move this to `ty::print`.
|
||||
fn write_region_name<'tcx>(
|
||||
r: ty::Region<'tcx>,
|
||||
fmt: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
match r {
|
||||
ty::ReLateBound(index, br) => match br {
|
||||
ty::BoundRegion::BrNamed(_, name) => write!(fmt, "{}", name),
|
||||
ty::BoundRegion::BrAnon(var) => {
|
||||
if *index == ty::INNERMOST {
|
||||
write!(fmt, "'^{}", var)
|
||||
} else {
|
||||
write!(fmt, "'^{}_{}", index.index(), var)
|
||||
}
|
||||
}
|
||||
_ => write!(fmt, "'_"),
|
||||
},
|
||||
|
||||
_ => write!(fmt, "{}", r),
|
||||
}
|
||||
}
|
||||
|
||||
match self {
|
||||
Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
|
||||
ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
|
||||
RegionOutlives(predicate) => {
|
||||
write!(fmt, "RegionOutlives({}: ", predicate.0)?;
|
||||
write_region_name(predicate.1, fmt)?;
|
||||
write!(fmt, ")")
|
||||
}
|
||||
TypeOutlives(predicate) => {
|
||||
write!(fmt, "TypeOutlives({}: ", predicate.0)?;
|
||||
write_region_name(predicate.1, fmt)?;
|
||||
write!(fmt, ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::WellFormed<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::WellFormed::*;
|
||||
|
||||
match self {
|
||||
Trait(trait_ref) => write!(fmt, "WellFormed({})", trait_ref),
|
||||
Ty(ty) => write!(fmt, "WellFormed({})", ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::FromEnv<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::FromEnv::*;
|
||||
|
||||
match self {
|
||||
Trait(trait_ref) => write!(fmt, "FromEnv({})", trait_ref),
|
||||
Ty(ty) => write!(fmt, "FromEnv({})", ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::DomainGoal::*;
|
||||
|
||||
match self {
|
||||
Holds(wc) => write!(fmt, "{}", wc),
|
||||
WellFormed(wf) => write!(fmt, "{}", wf),
|
||||
FromEnv(from_env) => write!(fmt, "{}", from_env),
|
||||
Normalize(projection) => {
|
||||
write!(fmt, "Normalize({} -> {})", projection.projection_ty, projection.ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for traits::QuantifierKind {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::QuantifierKind::*;
|
||||
|
||||
match self {
|
||||
Universal => write!(fmt, "forall"),
|
||||
Existential => write!(fmt, "exists"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect names for regions / types bound by a quantified goal / clause.
|
||||
/// This collector does not try to do anything clever like in `ty::print`, it's just used
|
||||
/// for debug output in tests anyway.
|
||||
struct BoundNamesCollector {
|
||||
// Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway.
|
||||
regions: BTreeSet<Symbol>,
|
||||
|
||||
// Sort by `BoundVar` index, so usually this should be equivalent to the order given
|
||||
// by the list of type parameters.
|
||||
types: BTreeMap<u32, Symbol>,
|
||||
|
||||
binder_index: ty::DebruijnIndex,
|
||||
}
|
||||
|
||||
impl BoundNamesCollector {
|
||||
fn new() -> Self {
|
||||
BoundNamesCollector {
|
||||
regions: BTreeSet::new(),
|
||||
types: BTreeMap::new(),
|
||||
binder_index: ty::INNERMOST,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.regions.is_empty() && self.types.is_empty()
|
||||
}
|
||||
|
||||
fn write_names(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut start = true;
|
||||
for r in &self.regions {
|
||||
if !start {
|
||||
write!(fmt, ", ")?;
|
||||
}
|
||||
start = false;
|
||||
write!(fmt, "{}", r)?;
|
||||
}
|
||||
for (_, t) in &self.types {
|
||||
if !start {
|
||||
write!(fmt, ", ")?;
|
||||
}
|
||||
start = false;
|
||||
write!(fmt, "{}", t)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
|
||||
self.binder_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
self.binder_index.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
||||
match t.kind {
|
||||
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
|
||||
self.types.insert(
|
||||
bound_ty.var.as_u32(),
|
||||
match bound_ty.kind {
|
||||
ty::BoundTyKind::Param(name) => name,
|
||||
ty::BoundTyKind::Anon => {
|
||||
Symbol::intern(&format!("^{}", bound_ty.var.as_u32()))
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
||||
match r {
|
||||
ty::ReLateBound(index, br) if *index == self.binder_index => match br {
|
||||
ty::BoundRegion::BrNamed(_, name) => {
|
||||
self.regions.insert(*name);
|
||||
}
|
||||
|
||||
ty::BoundRegion::BrAnon(var) => {
|
||||
self.regions.insert(Symbol::intern(&format!("'^{}", var)));
|
||||
}
|
||||
|
||||
_ => (),
|
||||
},
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
r.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::Goal<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::GoalKind::*;
|
||||
|
||||
match self {
|
||||
Implies(hypotheses, goal) => {
|
||||
write!(fmt, "if (")?;
|
||||
for (index, hyp) in hypotheses.iter().enumerate() {
|
||||
if index > 0 {
|
||||
write!(fmt, ", ")?;
|
||||
}
|
||||
write!(fmt, "{}", hyp)?;
|
||||
}
|
||||
write!(fmt, ") {{ {} }}", goal)
|
||||
}
|
||||
And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
|
||||
Not(goal) => write!(fmt, "not {{ {} }}", goal),
|
||||
DomainGoal(goal) => write!(fmt, "{}", goal),
|
||||
Quantified(qkind, goal) => {
|
||||
let mut collector = BoundNamesCollector::new();
|
||||
goal.skip_binder().visit_with(&mut collector);
|
||||
|
||||
if !collector.is_empty() {
|
||||
write!(fmt, "{}<", qkind)?;
|
||||
collector.write_names(fmt)?;
|
||||
write!(fmt, "> {{ ")?;
|
||||
}
|
||||
|
||||
write!(fmt, "{}", goal.skip_binder())?;
|
||||
|
||||
if !collector.is_empty() {
|
||||
write!(fmt, " }}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Subtype(a, b) => write!(fmt, "{} <: {}", a, b),
|
||||
CannotProve => write!(fmt, "CannotProve"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let traits::ProgramClause { goal, hypotheses, .. } = self;
|
||||
write!(fmt, "{}", goal)?;
|
||||
if !hypotheses.is_empty() {
|
||||
write!(fmt, " :- ")?;
|
||||
for (index, condition) in hypotheses.iter().enumerate() {
|
||||
if index > 0 {
|
||||
write!(fmt, ", ")?;
|
||||
}
|
||||
write!(fmt, "{}", condition)?;
|
||||
}
|
||||
}
|
||||
write!(fmt, ".")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::Clause<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::Clause::*;
|
||||
|
||||
match self {
|
||||
Implies(clause) => write!(fmt, "{}", clause),
|
||||
ForAll(clause) => {
|
||||
let mut collector = BoundNamesCollector::new();
|
||||
clause.skip_binder().visit_with(&mut collector);
|
||||
|
||||
if !collector.is_empty() {
|
||||
write!(fmt, "forall<")?;
|
||||
collector.write_names(fmt)?;
|
||||
write!(fmt, "> {{ ")?;
|
||||
}
|
||||
|
||||
write!(fmt, "{}", clause.skip_binder())?;
|
||||
|
||||
if !collector.is_empty() {
|
||||
write!(fmt, " }}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Lift implementations
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
|
||||
type Lifted = traits::SelectionError<'tcx>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
match *self {
|
||||
super::Unimplemented => Some(super::Unimplemented),
|
||||
super::OutputTypeParameterMismatch(a, b, ref err) => {
|
||||
tcx.lift(&(a, b)).and_then(|(a, b)| {
|
||||
tcx.lift(err).map(|err| super::OutputTypeParameterMismatch(a, b, err))
|
||||
})
|
||||
}
|
||||
super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
|
||||
super::ConstEvalFailure(err) => Some(super::ConstEvalFailure(err)),
|
||||
super::Overflow => Some(super::Overflow),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
||||
type Lifted = traits::ObligationCauseCode<'tcx>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
match *self {
|
||||
super::ReturnNoExpression => Some(super::ReturnNoExpression),
|
||||
super::MiscObligation => Some(super::MiscObligation),
|
||||
super::SliceOrArrayElem => Some(super::SliceOrArrayElem),
|
||||
super::TupleElem => Some(super::TupleElem),
|
||||
super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf),
|
||||
super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)),
|
||||
super::BindingObligation(def_id, span) => Some(super::BindingObligation(def_id, span)),
|
||||
super::ReferenceOutlivesReferent(ty) => {
|
||||
tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
|
||||
}
|
||||
super::ObjectTypeBound(ty, r) => tcx
|
||||
.lift(&ty)
|
||||
.and_then(|ty| tcx.lift(&r).and_then(|r| Some(super::ObjectTypeBound(ty, r)))),
|
||||
super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
|
||||
super::Coercion { source, target } => {
|
||||
Some(super::Coercion { source: tcx.lift(&source)?, target: tcx.lift(&target)? })
|
||||
}
|
||||
super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
|
||||
super::TupleInitializerSized => Some(super::TupleInitializerSized),
|
||||
super::StructInitializerSized => Some(super::StructInitializerSized),
|
||||
super::VariableType(id) => Some(super::VariableType(id)),
|
||||
super::ReturnValue(id) => Some(super::ReturnValue(id)),
|
||||
super::ReturnType => Some(super::ReturnType),
|
||||
super::SizedArgumentType => Some(super::SizedArgumentType),
|
||||
super::SizedReturnType => Some(super::SizedReturnType),
|
||||
super::SizedYieldType => Some(super::SizedYieldType),
|
||||
super::RepeatVec(suggest_flag) => Some(super::RepeatVec(suggest_flag)),
|
||||
super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }),
|
||||
super::ConstSized => Some(super::ConstSized),
|
||||
super::ConstPatternStructural => Some(super::ConstPatternStructural),
|
||||
super::SharedStatic => Some(super::SharedStatic),
|
||||
super::BuiltinDerivedObligation(ref cause) => {
|
||||
tcx.lift(cause).map(super::BuiltinDerivedObligation)
|
||||
}
|
||||
super::ImplDerivedObligation(ref cause) => {
|
||||
tcx.lift(cause).map(super::ImplDerivedObligation)
|
||||
}
|
||||
super::CompareImplMethodObligation {
|
||||
item_name,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
} => Some(super::CompareImplMethodObligation {
|
||||
item_name,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
}),
|
||||
super::CompareImplTypeObligation { item_name, impl_item_def_id, trait_item_def_id } => {
|
||||
Some(super::CompareImplTypeObligation {
|
||||
item_name,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
})
|
||||
}
|
||||
super::ExprAssignable => Some(super::ExprAssignable),
|
||||
super::MatchExpressionArm(box super::MatchExpressionArmCause {
|
||||
arm_span,
|
||||
source,
|
||||
ref prior_arms,
|
||||
last_ty,
|
||||
scrut_hir_id,
|
||||
}) => tcx.lift(&last_ty).map(|last_ty| {
|
||||
super::MatchExpressionArm(box super::MatchExpressionArmCause {
|
||||
arm_span,
|
||||
source,
|
||||
prior_arms: prior_arms.clone(),
|
||||
last_ty,
|
||||
scrut_hir_id,
|
||||
})
|
||||
}),
|
||||
super::Pattern { span, root_ty, origin_expr } => {
|
||||
tcx.lift(&root_ty).map(|root_ty| super::Pattern { span, root_ty, origin_expr })
|
||||
}
|
||||
super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
|
||||
Some(super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }))
|
||||
}
|
||||
super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
|
||||
super::MainFunctionType => Some(super::MainFunctionType),
|
||||
super::StartFunctionType => Some(super::StartFunctionType),
|
||||
super::IntrinsicType => Some(super::IntrinsicType),
|
||||
super::MethodReceiver => Some(super::MethodReceiver),
|
||||
super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
|
||||
super::TrivialBound => Some(super::TrivialBound),
|
||||
super::AssocTypeBound(ref data) => Some(super::AssocTypeBound(data.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
|
||||
type Lifted = traits::DerivedObligationCause<'tcx>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| {
|
||||
tcx.lift(&*self.parent_code).map(|code| traits::DerivedObligationCause {
|
||||
parent_trait_ref: trait_ref,
|
||||
parent_code: Rc::new(code),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCause<'a> {
|
||||
type Lifted = traits::ObligationCause<'tcx>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(&self.code).map(|code| traits::ObligationCause {
|
||||
span: self.span,
|
||||
body_id: self.body_id,
|
||||
code,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// For codegen only.
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
|
||||
type Lifted = traits::Vtable<'tcx, ()>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
match self.clone() {
|
||||
traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested }) => {
|
||||
tcx.lift(&substs).map(|substs| {
|
||||
traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested })
|
||||
})
|
||||
}
|
||||
traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
|
||||
traits::VtableGenerator(traits::VtableGeneratorData {
|
||||
generator_def_id,
|
||||
substs,
|
||||
nested,
|
||||
}) => tcx.lift(&substs).map(|substs| {
|
||||
traits::VtableGenerator(traits::VtableGeneratorData {
|
||||
generator_def_id: generator_def_id,
|
||||
substs: substs,
|
||||
nested: nested,
|
||||
})
|
||||
}),
|
||||
traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested }) => {
|
||||
tcx.lift(&substs).map(|substs| {
|
||||
traits::VtableClosure(traits::VtableClosureData {
|
||||
closure_def_id,
|
||||
substs,
|
||||
nested,
|
||||
})
|
||||
})
|
||||
}
|
||||
traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => {
|
||||
tcx.lift(&fn_ty).map(|fn_ty| {
|
||||
traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested })
|
||||
})
|
||||
}
|
||||
traits::VtableParam(n) => Some(traits::VtableParam(n)),
|
||||
traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
|
||||
traits::VtableObject(traits::VtableObjectData {
|
||||
upcast_trait_ref,
|
||||
vtable_base,
|
||||
nested,
|
||||
}) => tcx.lift(&upcast_trait_ref).map(|trait_ref| {
|
||||
traits::VtableObject(traits::VtableObjectData {
|
||||
upcast_trait_ref: trait_ref,
|
||||
vtable_base,
|
||||
nested,
|
||||
})
|
||||
}),
|
||||
traits::VtableTraitAlias(traits::VtableTraitAliasData {
|
||||
alias_def_id,
|
||||
substs,
|
||||
nested,
|
||||
}) => tcx.lift(&substs).map(|substs| {
|
||||
traits::VtableTraitAlias(traits::VtableTraitAliasData {
|
||||
alias_def_id,
|
||||
substs,
|
||||
nested,
|
||||
})
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::Environment<'a> {
|
||||
type Lifted = traits::Environment<'tcx>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(&self.clauses).map(|clauses| traits::Environment { clauses })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> {
|
||||
type Lifted = traits::InEnvironment<'tcx, G::Lifted>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(&self.environment).and_then(|environment| {
|
||||
tcx.lift(&self.goal).map(|goal| traits::InEnvironment { environment, goal })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
|
||||
where
|
||||
C: chalk_engine::context::Context + Clone,
|
||||
C: traits::ChalkContextLift<'tcx>,
|
||||
{
|
||||
type Lifted = C::LiftedExClause;
|
||||
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
<C as traits::ChalkContextLift>::lift_ex_clause_to_tcx(self, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, C> Lift<'tcx> for chalk_engine::DelayedLiteral<C>
|
||||
where
|
||||
C: chalk_engine::context::Context + Clone,
|
||||
C: traits::ChalkContextLift<'tcx>,
|
||||
{
|
||||
type Lifted = C::LiftedDelayedLiteral;
|
||||
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
<C as traits::ChalkContextLift>::lift_delayed_literal_to_tcx(self, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, C> Lift<'tcx> for chalk_engine::Literal<C>
|
||||
where
|
||||
C: chalk_engine::context::Context + Clone,
|
||||
C: traits::ChalkContextLift<'tcx>,
|
||||
{
|
||||
type Lifted = C::LiftedLiteral;
|
||||
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
<C as traits::ChalkContextLift>::lift_literal_to_tcx(self, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// TypeFoldable implementations.
|
||||
|
||||
|
@ -694,80 +69,3 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx
|
|||
self.predicate.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! {
|
||||
traits::QuantifierKind,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<traits::Goal<'tcx>> {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
|
||||
folder.tcx().intern_goals(&v)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.iter().any(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let v = (**self).fold_with(folder);
|
||||
folder.tcx().mk_goal(v)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! {
|
||||
traits::ProgramClauseCategory,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
|
||||
folder.tcx().intern_clauses(&v)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.iter().any(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::ExClause<C>
|
||||
where
|
||||
C: traits::ExClauseFold<'tcx>,
|
||||
C::Substitution: Clone,
|
||||
C::RegionConstraint: Clone,
|
||||
{
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
<C as traits::ExClauseFold>::fold_ex_clause_with(self, folder)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
<C as traits::ExClauseFold>::visit_ex_clause_with(self, visitor)
|
||||
}
|
||||
}
|
||||
|
||||
EnumTypeFoldableImpl! {
|
||||
impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::DelayedLiteral<C> {
|
||||
(chalk_engine::DelayedLiteral::CannotProve)(a),
|
||||
(chalk_engine::DelayedLiteral::Negative)(a),
|
||||
(chalk_engine::DelayedLiteral::Positive)(a, b),
|
||||
} where
|
||||
C: chalk_engine::context::Context<CanonicalConstrainedSubst: TypeFoldable<'tcx>> + Clone,
|
||||
}
|
||||
|
||||
EnumTypeFoldableImpl! {
|
||||
impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::Literal<C> {
|
||||
(chalk_engine::Literal::Negative)(a),
|
||||
(chalk_engine::Literal::Positive)(a),
|
||||
} where
|
||||
C: chalk_engine::context::Context<GoalInEnvironment: Clone + TypeFoldable<'tcx>> + Clone,
|
||||
}
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! {
|
||||
chalk_engine::TableIndex,
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
pub mod query;
|
||||
pub mod select;
|
||||
mod structural_impls;
|
||||
|
||||
use crate::mir::interpret::ErrorHandled;
|
||||
use crate::ty::fold::{TypeFolder, TypeVisitor};
|
||||
|
|
712
src/librustc/traits/types/structural_impls.rs
Normal file
712
src/librustc/traits/types/structural_impls.rs
Normal file
|
@ -0,0 +1,712 @@
|
|||
use crate::traits;
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use crate::ty::{self, Lift, Ty, TyCtxt};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
|
||||
// Structural impls for the structs in `traits`.
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::Vtable<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
super::VtableImpl(ref v) => write!(f, "{:?}", v),
|
||||
|
||||
super::VtableAutoImpl(ref t) => write!(f, "{:?}", t),
|
||||
|
||||
super::VtableClosure(ref d) => write!(f, "{:?}", d),
|
||||
|
||||
super::VtableGenerator(ref d) => write!(f, "{:?}", d),
|
||||
|
||||
super::VtableFnPointer(ref d) => write!(f, "VtableFnPointer({:?})", d),
|
||||
|
||||
super::VtableObject(ref d) => write!(f, "{:?}", d),
|
||||
|
||||
super::VtableParam(ref n) => write!(f, "VtableParam({:?})", n),
|
||||
|
||||
super::VtableBuiltin(ref d) => write!(f, "{:?}", d),
|
||||
|
||||
super::VtableTraitAlias(ref d) => write!(f, "{:?}", d),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableImplData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableImplData(impl_def_id={:?}, substs={:?}, nested={:?})",
|
||||
self.impl_def_id, self.substs, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableGeneratorData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})",
|
||||
self.generator_def_id, self.substs, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableClosureData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableClosureData(closure_def_id={:?}, substs={:?}, nested={:?})",
|
||||
self.closure_def_id, self.substs, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: fmt::Debug> fmt::Debug for traits::VtableBuiltinData<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "VtableBuiltinData(nested={:?})", self.nested)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: fmt::Debug> fmt::Debug for traits::VtableAutoImplData<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableAutoImplData(trait_def_id={:?}, nested={:?})",
|
||||
self.trait_def_id, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableObjectData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableObjectData(upcast={:?}, vtable_base={}, nested={:?})",
|
||||
self.upcast_trait_ref, self.vtable_base, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableFnPointerData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "VtableFnPointerData(fn_ty={:?}, nested={:?})", self.fn_ty, self.nested)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableTraitAliasData<'tcx, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VtableTraitAlias(alias_def_id={:?}, substs={:?}, nested={:?})",
|
||||
self.alias_def_id, self.substs, self.nested
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::WhereClause<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::WhereClause::*;
|
||||
|
||||
// Bypass `ty::print` because it does not print out anonymous regions.
|
||||
// FIXME(eddyb) implement a custom `PrettyPrinter`, or move this to `ty::print`.
|
||||
fn write_region_name<'tcx>(
|
||||
r: ty::Region<'tcx>,
|
||||
fmt: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
match r {
|
||||
ty::ReLateBound(index, br) => match br {
|
||||
ty::BoundRegion::BrNamed(_, name) => write!(fmt, "{}", name),
|
||||
ty::BoundRegion::BrAnon(var) => {
|
||||
if *index == ty::INNERMOST {
|
||||
write!(fmt, "'^{}", var)
|
||||
} else {
|
||||
write!(fmt, "'^{}_{}", index.index(), var)
|
||||
}
|
||||
}
|
||||
_ => write!(fmt, "'_"),
|
||||
},
|
||||
|
||||
_ => write!(fmt, "{}", r),
|
||||
}
|
||||
}
|
||||
|
||||
match self {
|
||||
Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
|
||||
ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
|
||||
RegionOutlives(predicate) => {
|
||||
write!(fmt, "RegionOutlives({}: ", predicate.0)?;
|
||||
write_region_name(predicate.1, fmt)?;
|
||||
write!(fmt, ")")
|
||||
}
|
||||
TypeOutlives(predicate) => {
|
||||
write!(fmt, "TypeOutlives({}: ", predicate.0)?;
|
||||
write_region_name(predicate.1, fmt)?;
|
||||
write!(fmt, ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::WellFormed<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::WellFormed::*;
|
||||
|
||||
match self {
|
||||
Trait(trait_ref) => write!(fmt, "WellFormed({})", trait_ref),
|
||||
Ty(ty) => write!(fmt, "WellFormed({})", ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::FromEnv<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::FromEnv::*;
|
||||
|
||||
match self {
|
||||
Trait(trait_ref) => write!(fmt, "FromEnv({})", trait_ref),
|
||||
Ty(ty) => write!(fmt, "FromEnv({})", ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::DomainGoal::*;
|
||||
|
||||
match self {
|
||||
Holds(wc) => write!(fmt, "{}", wc),
|
||||
WellFormed(wf) => write!(fmt, "{}", wf),
|
||||
FromEnv(from_env) => write!(fmt, "{}", from_env),
|
||||
Normalize(projection) => {
|
||||
write!(fmt, "Normalize({} -> {})", projection.projection_ty, projection.ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for traits::QuantifierKind {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::QuantifierKind::*;
|
||||
|
||||
match self {
|
||||
Universal => write!(fmt, "forall"),
|
||||
Existential => write!(fmt, "exists"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect names for regions / types bound by a quantified goal / clause.
|
||||
/// This collector does not try to do anything clever like in `ty::print`, it's just used
|
||||
/// for debug output in tests anyway.
|
||||
struct BoundNamesCollector {
|
||||
// Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway.
|
||||
regions: BTreeSet<Symbol>,
|
||||
|
||||
// Sort by `BoundVar` index, so usually this should be equivalent to the order given
|
||||
// by the list of type parameters.
|
||||
types: BTreeMap<u32, Symbol>,
|
||||
|
||||
binder_index: ty::DebruijnIndex,
|
||||
}
|
||||
|
||||
impl BoundNamesCollector {
|
||||
fn new() -> Self {
|
||||
BoundNamesCollector {
|
||||
regions: BTreeSet::new(),
|
||||
types: BTreeMap::new(),
|
||||
binder_index: ty::INNERMOST,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.regions.is_empty() && self.types.is_empty()
|
||||
}
|
||||
|
||||
fn write_names(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut start = true;
|
||||
for r in &self.regions {
|
||||
if !start {
|
||||
write!(fmt, ", ")?;
|
||||
}
|
||||
start = false;
|
||||
write!(fmt, "{}", r)?;
|
||||
}
|
||||
for (_, t) in &self.types {
|
||||
if !start {
|
||||
write!(fmt, ", ")?;
|
||||
}
|
||||
start = false;
|
||||
write!(fmt, "{}", t)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
|
||||
self.binder_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
self.binder_index.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
||||
match t.kind {
|
||||
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
|
||||
self.types.insert(
|
||||
bound_ty.var.as_u32(),
|
||||
match bound_ty.kind {
|
||||
ty::BoundTyKind::Param(name) => name,
|
||||
ty::BoundTyKind::Anon => {
|
||||
Symbol::intern(&format!("^{}", bound_ty.var.as_u32()))
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
||||
match r {
|
||||
ty::ReLateBound(index, br) if *index == self.binder_index => match br {
|
||||
ty::BoundRegion::BrNamed(_, name) => {
|
||||
self.regions.insert(*name);
|
||||
}
|
||||
|
||||
ty::BoundRegion::BrAnon(var) => {
|
||||
self.regions.insert(Symbol::intern(&format!("'^{}", var)));
|
||||
}
|
||||
|
||||
_ => (),
|
||||
},
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
r.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::Goal<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::GoalKind::*;
|
||||
|
||||
match self {
|
||||
Implies(hypotheses, goal) => {
|
||||
write!(fmt, "if (")?;
|
||||
for (index, hyp) in hypotheses.iter().enumerate() {
|
||||
if index > 0 {
|
||||
write!(fmt, ", ")?;
|
||||
}
|
||||
write!(fmt, "{}", hyp)?;
|
||||
}
|
||||
write!(fmt, ") {{ {} }}", goal)
|
||||
}
|
||||
And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
|
||||
Not(goal) => write!(fmt, "not {{ {} }}", goal),
|
||||
DomainGoal(goal) => write!(fmt, "{}", goal),
|
||||
Quantified(qkind, goal) => {
|
||||
let mut collector = BoundNamesCollector::new();
|
||||
goal.skip_binder().visit_with(&mut collector);
|
||||
|
||||
if !collector.is_empty() {
|
||||
write!(fmt, "{}<", qkind)?;
|
||||
collector.write_names(fmt)?;
|
||||
write!(fmt, "> {{ ")?;
|
||||
}
|
||||
|
||||
write!(fmt, "{}", goal.skip_binder())?;
|
||||
|
||||
if !collector.is_empty() {
|
||||
write!(fmt, " }}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Subtype(a, b) => write!(fmt, "{} <: {}", a, b),
|
||||
CannotProve => write!(fmt, "CannotProve"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let traits::ProgramClause { goal, hypotheses, .. } = self;
|
||||
write!(fmt, "{}", goal)?;
|
||||
if !hypotheses.is_empty() {
|
||||
write!(fmt, " :- ")?;
|
||||
for (index, condition) in hypotheses.iter().enumerate() {
|
||||
if index > 0 {
|
||||
write!(fmt, ", ")?;
|
||||
}
|
||||
write!(fmt, "{}", condition)?;
|
||||
}
|
||||
}
|
||||
write!(fmt, ".")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for traits::Clause<'tcx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use crate::traits::Clause::*;
|
||||
|
||||
match self {
|
||||
Implies(clause) => write!(fmt, "{}", clause),
|
||||
ForAll(clause) => {
|
||||
let mut collector = BoundNamesCollector::new();
|
||||
clause.skip_binder().visit_with(&mut collector);
|
||||
|
||||
if !collector.is_empty() {
|
||||
write!(fmt, "forall<")?;
|
||||
collector.write_names(fmt)?;
|
||||
write!(fmt, "> {{ ")?;
|
||||
}
|
||||
|
||||
write!(fmt, "{}", clause.skip_binder())?;
|
||||
|
||||
if !collector.is_empty() {
|
||||
write!(fmt, " }}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Lift implementations
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
|
||||
type Lifted = traits::SelectionError<'tcx>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
match *self {
|
||||
super::Unimplemented => Some(super::Unimplemented),
|
||||
super::OutputTypeParameterMismatch(a, b, ref err) => {
|
||||
tcx.lift(&(a, b)).and_then(|(a, b)| {
|
||||
tcx.lift(err).map(|err| super::OutputTypeParameterMismatch(a, b, err))
|
||||
})
|
||||
}
|
||||
super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
|
||||
super::ConstEvalFailure(err) => Some(super::ConstEvalFailure(err)),
|
||||
super::Overflow => Some(super::Overflow),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
||||
type Lifted = traits::ObligationCauseCode<'tcx>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
match *self {
|
||||
super::ReturnNoExpression => Some(super::ReturnNoExpression),
|
||||
super::MiscObligation => Some(super::MiscObligation),
|
||||
super::SliceOrArrayElem => Some(super::SliceOrArrayElem),
|
||||
super::TupleElem => Some(super::TupleElem),
|
||||
super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf),
|
||||
super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)),
|
||||
super::BindingObligation(def_id, span) => Some(super::BindingObligation(def_id, span)),
|
||||
super::ReferenceOutlivesReferent(ty) => {
|
||||
tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
|
||||
}
|
||||
super::ObjectTypeBound(ty, r) => tcx
|
||||
.lift(&ty)
|
||||
.and_then(|ty| tcx.lift(&r).and_then(|r| Some(super::ObjectTypeBound(ty, r)))),
|
||||
super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
|
||||
super::Coercion { source, target } => {
|
||||
Some(super::Coercion { source: tcx.lift(&source)?, target: tcx.lift(&target)? })
|
||||
}
|
||||
super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
|
||||
super::TupleInitializerSized => Some(super::TupleInitializerSized),
|
||||
super::StructInitializerSized => Some(super::StructInitializerSized),
|
||||
super::VariableType(id) => Some(super::VariableType(id)),
|
||||
super::ReturnValue(id) => Some(super::ReturnValue(id)),
|
||||
super::ReturnType => Some(super::ReturnType),
|
||||
super::SizedArgumentType => Some(super::SizedArgumentType),
|
||||
super::SizedReturnType => Some(super::SizedReturnType),
|
||||
super::SizedYieldType => Some(super::SizedYieldType),
|
||||
super::RepeatVec(suggest_flag) => Some(super::RepeatVec(suggest_flag)),
|
||||
super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }),
|
||||
super::ConstSized => Some(super::ConstSized),
|
||||
super::ConstPatternStructural => Some(super::ConstPatternStructural),
|
||||
super::SharedStatic => Some(super::SharedStatic),
|
||||
super::BuiltinDerivedObligation(ref cause) => {
|
||||
tcx.lift(cause).map(super::BuiltinDerivedObligation)
|
||||
}
|
||||
super::ImplDerivedObligation(ref cause) => {
|
||||
tcx.lift(cause).map(super::ImplDerivedObligation)
|
||||
}
|
||||
super::CompareImplMethodObligation {
|
||||
item_name,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
} => Some(super::CompareImplMethodObligation {
|
||||
item_name,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
}),
|
||||
super::CompareImplTypeObligation { item_name, impl_item_def_id, trait_item_def_id } => {
|
||||
Some(super::CompareImplTypeObligation {
|
||||
item_name,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
})
|
||||
}
|
||||
super::ExprAssignable => Some(super::ExprAssignable),
|
||||
super::MatchExpressionArm(box super::MatchExpressionArmCause {
|
||||
arm_span,
|
||||
source,
|
||||
ref prior_arms,
|
||||
last_ty,
|
||||
scrut_hir_id,
|
||||
}) => tcx.lift(&last_ty).map(|last_ty| {
|
||||
super::MatchExpressionArm(box super::MatchExpressionArmCause {
|
||||
arm_span,
|
||||
source,
|
||||
prior_arms: prior_arms.clone(),
|
||||
last_ty,
|
||||
scrut_hir_id,
|
||||
})
|
||||
}),
|
||||
super::Pattern { span, root_ty, origin_expr } => {
|
||||
tcx.lift(&root_ty).map(|root_ty| super::Pattern { span, root_ty, origin_expr })
|
||||
}
|
||||
super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
|
||||
Some(super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }))
|
||||
}
|
||||
super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
|
||||
super::MainFunctionType => Some(super::MainFunctionType),
|
||||
super::StartFunctionType => Some(super::StartFunctionType),
|
||||
super::IntrinsicType => Some(super::IntrinsicType),
|
||||
super::MethodReceiver => Some(super::MethodReceiver),
|
||||
super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
|
||||
super::TrivialBound => Some(super::TrivialBound),
|
||||
super::AssocTypeBound(ref data) => Some(super::AssocTypeBound(data.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
|
||||
type Lifted = traits::DerivedObligationCause<'tcx>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| {
|
||||
tcx.lift(&*self.parent_code).map(|code| traits::DerivedObligationCause {
|
||||
parent_trait_ref: trait_ref,
|
||||
parent_code: Rc::new(code),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCause<'a> {
|
||||
type Lifted = traits::ObligationCause<'tcx>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(&self.code).map(|code| traits::ObligationCause {
|
||||
span: self.span,
|
||||
body_id: self.body_id,
|
||||
code,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// For codegen only.
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
|
||||
type Lifted = traits::Vtable<'tcx, ()>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
match self.clone() {
|
||||
traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested }) => {
|
||||
tcx.lift(&substs).map(|substs| {
|
||||
traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested })
|
||||
})
|
||||
}
|
||||
traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
|
||||
traits::VtableGenerator(traits::VtableGeneratorData {
|
||||
generator_def_id,
|
||||
substs,
|
||||
nested,
|
||||
}) => tcx.lift(&substs).map(|substs| {
|
||||
traits::VtableGenerator(traits::VtableGeneratorData {
|
||||
generator_def_id: generator_def_id,
|
||||
substs: substs,
|
||||
nested: nested,
|
||||
})
|
||||
}),
|
||||
traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested }) => {
|
||||
tcx.lift(&substs).map(|substs| {
|
||||
traits::VtableClosure(traits::VtableClosureData {
|
||||
closure_def_id,
|
||||
substs,
|
||||
nested,
|
||||
})
|
||||
})
|
||||
}
|
||||
traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => {
|
||||
tcx.lift(&fn_ty).map(|fn_ty| {
|
||||
traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested })
|
||||
})
|
||||
}
|
||||
traits::VtableParam(n) => Some(traits::VtableParam(n)),
|
||||
traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
|
||||
traits::VtableObject(traits::VtableObjectData {
|
||||
upcast_trait_ref,
|
||||
vtable_base,
|
||||
nested,
|
||||
}) => tcx.lift(&upcast_trait_ref).map(|trait_ref| {
|
||||
traits::VtableObject(traits::VtableObjectData {
|
||||
upcast_trait_ref: trait_ref,
|
||||
vtable_base,
|
||||
nested,
|
||||
})
|
||||
}),
|
||||
traits::VtableTraitAlias(traits::VtableTraitAliasData {
|
||||
alias_def_id,
|
||||
substs,
|
||||
nested,
|
||||
}) => tcx.lift(&substs).map(|substs| {
|
||||
traits::VtableTraitAlias(traits::VtableTraitAliasData {
|
||||
alias_def_id,
|
||||
substs,
|
||||
nested,
|
||||
})
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::Environment<'a> {
|
||||
type Lifted = traits::Environment<'tcx>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(&self.clauses).map(|clauses| traits::Environment { clauses })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> {
|
||||
type Lifted = traits::InEnvironment<'tcx, G::Lifted>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(&self.environment).and_then(|environment| {
|
||||
tcx.lift(&self.goal).map(|goal| traits::InEnvironment { environment, goal })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
|
||||
where
|
||||
C: chalk_engine::context::Context + Clone,
|
||||
C: traits::ChalkContextLift<'tcx>,
|
||||
{
|
||||
type Lifted = C::LiftedExClause;
|
||||
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
<C as traits::ChalkContextLift>::lift_ex_clause_to_tcx(self, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, C> Lift<'tcx> for chalk_engine::DelayedLiteral<C>
|
||||
where
|
||||
C: chalk_engine::context::Context + Clone,
|
||||
C: traits::ChalkContextLift<'tcx>,
|
||||
{
|
||||
type Lifted = C::LiftedDelayedLiteral;
|
||||
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
<C as traits::ChalkContextLift>::lift_delayed_literal_to_tcx(self, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, C> Lift<'tcx> for chalk_engine::Literal<C>
|
||||
where
|
||||
C: chalk_engine::context::Context + Clone,
|
||||
C: traits::ChalkContextLift<'tcx>,
|
||||
{
|
||||
type Lifted = C::LiftedLiteral;
|
||||
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
<C as traits::ChalkContextLift>::lift_literal_to_tcx(self, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// TypeFoldable implementations.
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! {
|
||||
traits::QuantifierKind,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<traits::Goal<'tcx>> {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
|
||||
folder.tcx().intern_goals(&v)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.iter().any(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let v = (**self).fold_with(folder);
|
||||
folder.tcx().mk_goal(v)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! {
|
||||
traits::ProgramClauseCategory,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
|
||||
folder.tcx().intern_clauses(&v)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.iter().any(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::ExClause<C>
|
||||
where
|
||||
C: traits::ExClauseFold<'tcx>,
|
||||
C::Substitution: Clone,
|
||||
C::RegionConstraint: Clone,
|
||||
{
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
<C as traits::ExClauseFold>::fold_ex_clause_with(self, folder)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
<C as traits::ExClauseFold>::visit_ex_clause_with(self, visitor)
|
||||
}
|
||||
}
|
||||
|
||||
EnumTypeFoldableImpl! {
|
||||
impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::DelayedLiteral<C> {
|
||||
(chalk_engine::DelayedLiteral::CannotProve)(a),
|
||||
(chalk_engine::DelayedLiteral::Negative)(a),
|
||||
(chalk_engine::DelayedLiteral::Positive)(a, b),
|
||||
} where
|
||||
C: chalk_engine::context::Context<CanonicalConstrainedSubst: TypeFoldable<'tcx>> + Clone,
|
||||
}
|
||||
|
||||
EnumTypeFoldableImpl! {
|
||||
impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::Literal<C> {
|
||||
(chalk_engine::Literal::Negative)(a),
|
||||
(chalk_engine::Literal::Positive)(a),
|
||||
} where
|
||||
C: chalk_engine::context::Context<GoalInEnvironment: Clone + TypeFoldable<'tcx>> + Clone,
|
||||
}
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! {
|
||||
chalk_engine::TableIndex,
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue