1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use rustc_data_structures::accumulate_vec::AccumulateVec;
13 use traits::project::Normalized;
14 use ty::{self, Lift, TyCtxt};
15 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
20 // structural impls for the structs in traits
22 impl<'tcx, T: fmt::Debug> fmt::Debug for Normalized<'tcx, T> {
23 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24 write!(f, "Normalized({:?},{:?})",
30 impl<'tcx, O: fmt::Debug> fmt::Debug for traits::Obligation<'tcx, O> {
31 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32 if ty::tls::with(|tcx| tcx.sess.verbose()) {
33 write!(f, "Obligation(predicate={:?},cause={:?},depth={})",
38 write!(f, "Obligation(predicate={:?},depth={})",
45 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::Vtable<'tcx, N> {
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 super::VtableImpl(ref v) =>
51 super::VtableAutoImpl(ref t) =>
54 super::VtableClosure(ref d) =>
57 super::VtableGenerator(ref d) =>
60 super::VtableFnPointer(ref d) =>
61 write!(f, "VtableFnPointer({:?})", d),
63 super::VtableObject(ref d) =>
66 super::VtableParam(ref n) =>
67 write!(f, "VtableParam({:?})", n),
69 super::VtableBuiltin(ref d) =>
75 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableImplData<'tcx, N> {
76 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 write!(f, "VtableImpl(impl_def_id={:?}, substs={:?}, nested={:?})",
84 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableGeneratorData<'tcx, N> {
85 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 write!(f, "VtableGenerator(closure_def_id={:?}, substs={:?}, nested={:?})",
93 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableClosureData<'tcx, N> {
94 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95 write!(f, "VtableClosure(closure_def_id={:?}, substs={:?}, nested={:?})",
102 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableBuiltinData<N> {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 write!(f, "VtableBuiltin(nested={:?})", self.nested)
108 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableAutoImplData<N> {
109 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110 write!(f, "VtableAutoImplData(trait_def_id={:?}, nested={:?})",
116 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableObjectData<'tcx, N> {
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 write!(f, "VtableObject(upcast={:?}, vtable_base={}, nested={:?})",
119 self.upcast_trait_ref,
125 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableFnPointerData<'tcx, N> {
126 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
127 write!(f, "VtableFnPointer(fn_ty={:?}, nested={:?})",
133 impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 write!(f, "FulfillmentError({:?},{:?})",
141 impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
142 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144 super::CodeSelectionError(ref e) => write!(f, "{:?}", e),
145 super::CodeProjectionError(ref e) => write!(f, "{:?}", e),
146 super::CodeSubtypeError(ref a, ref b) =>
147 write!(f, "CodeSubtypeError({:?}, {:?})", a, b),
148 super::CodeAmbiguity => write!(f, "Ambiguity")
153 impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> {
154 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155 write!(f, "MismatchedProjectionTypes({:?})", self.err)
159 ///////////////////////////////////////////////////////////////////////////
160 // Lift implementations
162 impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
163 type Lifted = traits::SelectionError<'tcx>;
164 fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
166 super::Unimplemented => Some(super::Unimplemented),
167 super::OutputTypeParameterMismatch(a, b, ref err) => {
168 tcx.lift(&(a, b)).and_then(|(a, b)| {
169 tcx.lift(err).map(|err| {
170 super::OutputTypeParameterMismatch(a, b, err)
174 super::TraitNotObjectSafe(def_id) => {
175 Some(super::TraitNotObjectSafe(def_id))
177 super::ConstEvalFailure(ref err) => {
178 tcx.lift(err).map(super::ConstEvalFailure)
180 super::Overflow => bug!() // FIXME: ape ConstEvalFailure?
185 impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
186 type Lifted = traits::ObligationCauseCode<'tcx>;
187 fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
189 super::ReturnNoExpression => Some(super::ReturnNoExpression),
190 super::MiscObligation => Some(super::MiscObligation),
191 super::SliceOrArrayElem => Some(super::SliceOrArrayElem),
192 super::TupleElem => Some(super::TupleElem),
193 super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf),
194 super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)),
195 super::ReferenceOutlivesReferent(ty) => {
196 tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
198 super::ObjectTypeBound(ty, r) => {
199 tcx.lift(&ty).and_then(|ty| {
200 tcx.lift(&r).and_then(|r| {
201 Some(super::ObjectTypeBound(ty, r))
205 super::ObjectCastObligation(ty) => {
206 tcx.lift(&ty).map(super::ObjectCastObligation)
208 super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
209 super::TupleInitializerSized => Some(super::TupleInitializerSized),
210 super::StructInitializerSized => Some(super::StructInitializerSized),
211 super::VariableType(id) => Some(super::VariableType(id)),
212 super::ReturnType(id) => Some(super::ReturnType(id)),
213 super::SizedReturnType => Some(super::SizedReturnType),
214 super::SizedYieldType => Some(super::SizedYieldType),
215 super::RepeatVec => Some(super::RepeatVec),
216 super::FieldSized(item) => Some(super::FieldSized(item)),
217 super::ConstSized => Some(super::ConstSized),
218 super::SharedStatic => Some(super::SharedStatic),
219 super::BuiltinDerivedObligation(ref cause) => {
220 tcx.lift(cause).map(super::BuiltinDerivedObligation)
222 super::ImplDerivedObligation(ref cause) => {
223 tcx.lift(cause).map(super::ImplDerivedObligation)
225 super::CompareImplMethodObligation { item_name,
227 trait_item_def_id } => {
228 Some(super::CompareImplMethodObligation {
234 super::ExprAssignable => Some(super::ExprAssignable),
235 super::MatchExpressionArm { arm_span, source } => {
236 Some(super::MatchExpressionArm { arm_span,
239 super::IfExpression => Some(super::IfExpression),
240 super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
241 super::MainFunctionType => Some(super::MainFunctionType),
242 super::StartFunctionType => Some(super::StartFunctionType),
243 super::IntrinsicType => Some(super::IntrinsicType),
244 super::MethodReceiver => Some(super::MethodReceiver),
245 super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
250 impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
251 type Lifted = traits::DerivedObligationCause<'tcx>;
252 fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
253 tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| {
254 tcx.lift(&*self.parent_code).map(|code| {
255 traits::DerivedObligationCause {
256 parent_trait_ref: trait_ref,
257 parent_code: Rc::new(code)
264 impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCause<'a> {
265 type Lifted = traits::ObligationCause<'tcx>;
266 fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
267 tcx.lift(&self.code).map(|code| {
268 traits::ObligationCause {
270 body_id: self.body_id,
278 impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
279 type Lifted = traits::Vtable<'tcx, ()>;
280 fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
282 traits::VtableImpl(traits::VtableImplData {
287 tcx.lift(&substs).map(|substs| {
288 traits::VtableImpl(traits::VtableImplData {
295 traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
296 traits::VtableGenerator(traits::VtableGeneratorData {
301 tcx.lift(&substs).map(|substs| {
302 traits::VtableGenerator(traits::VtableGeneratorData {
303 closure_def_id: closure_def_id,
309 traits::VtableClosure(traits::VtableClosureData {
314 tcx.lift(&substs).map(|substs| {
315 traits::VtableClosure(traits::VtableClosureData {
322 traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => {
323 tcx.lift(&fn_ty).map(|fn_ty| {
324 traits::VtableFnPointer(traits::VtableFnPointerData {
330 traits::VtableParam(n) => Some(traits::VtableParam(n)),
331 traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
332 traits::VtableObject(traits::VtableObjectData {
337 tcx.lift(&upcast_trait_ref).map(|trait_ref| {
338 traits::VtableObject(traits::VtableObjectData {
339 upcast_trait_ref: trait_ref,
349 ///////////////////////////////////////////////////////////////////////////
350 // TypeFoldable implementations.
352 impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O>
354 fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
356 cause: self.cause.clone(),
357 recursion_depth: self.recursion_depth,
358 predicate: self.predicate.fold_with(folder),
359 param_env: self.param_env.fold_with(folder),
363 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
364 self.predicate.visit_with(visitor)
368 BraceStructTypeFoldableImpl! {
369 impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableImplData<'tcx, N> {
370 impl_def_id, substs, nested
371 } where N: TypeFoldable<'tcx>
374 BraceStructTypeFoldableImpl! {
375 impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableGeneratorData<'tcx, N> {
376 closure_def_id, substs, nested
377 } where N: TypeFoldable<'tcx>
380 BraceStructTypeFoldableImpl! {
381 impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableClosureData<'tcx, N> {
382 closure_def_id, substs, nested
383 } where N: TypeFoldable<'tcx>
386 BraceStructTypeFoldableImpl! {
387 impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableAutoImplData<N> {
389 } where N: TypeFoldable<'tcx>
392 BraceStructTypeFoldableImpl! {
393 impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableBuiltinData<N> {
395 } where N: TypeFoldable<'tcx>
398 BraceStructTypeFoldableImpl! {
399 impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx, N> {
400 upcast_trait_ref, vtable_base, nested
401 } where N: TypeFoldable<'tcx>
404 BraceStructTypeFoldableImpl! {
405 impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableFnPointerData<'tcx, N> {
408 } where N: TypeFoldable<'tcx>
411 EnumTypeFoldableImpl! {
412 impl<'tcx, N> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> {
413 (traits::VtableImpl)(a),
414 (traits::VtableAutoImpl)(a),
415 (traits::VtableGenerator)(a),
416 (traits::VtableClosure)(a),
417 (traits::VtableFnPointer)(a),
418 (traits::VtableParam)(a),
419 (traits::VtableBuiltin)(a),
420 (traits::VtableObject)(a),
421 } where N: TypeFoldable<'tcx>
424 BraceStructTypeFoldableImpl! {
425 impl<'tcx, T> TypeFoldable<'tcx> for Normalized<'tcx, T> {
428 } where T: TypeFoldable<'tcx>
431 impl<'tcx> fmt::Display for traits::WhereClauseAtom<'tcx> {
432 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
433 use traits::WhereClauseAtom::*;
436 Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
437 ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
442 impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
443 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
444 use traits::DomainGoal::*;
445 use traits::WhereClauseAtom::*;
448 Holds(wc) => write!(fmt, "{}", wc),
449 WellFormed(Implemented(trait_ref)) => write!(fmt, "WellFormed({})", trait_ref),
450 WellFormed(ProjectionEq(projection)) => write!(fmt, "WellFormed({})", projection),
451 FromEnv(Implemented(trait_ref)) => write!(fmt, "FromEnv({})", trait_ref),
452 FromEnv(ProjectionEq(projection)) => write!(fmt, "FromEnv({})", projection),
453 WellFormedTy(ty) => write!(fmt, "WellFormed({})", ty),
454 Normalize(projection) => write!(fmt, "Normalize({})", projection),
455 FromEnvTy(ty) => write!(fmt, "FromEnv({})", ty),
456 RegionOutlives(predicate) => write!(fmt, "RegionOutlives({})", predicate),
457 TypeOutlives(predicate) => write!(fmt, "TypeOutlives({})", predicate),
462 impl fmt::Display for traits::QuantifierKind {
463 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
464 use traits::QuantifierKind::*;
467 Universal => write!(fmt, "forall"),
468 Existential => write!(fmt, "exists"),
473 impl<'tcx> fmt::Display for traits::Goal<'tcx> {
474 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
478 Implies(hypotheses, goal) => {
479 write!(fmt, "if (")?;
480 for (index, hyp) in hypotheses.iter().enumerate() {
484 write!(fmt, "{}", hyp)?;
486 write!(fmt, ") {{ {} }}", goal)
488 And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
489 Not(goal) => write!(fmt, "not {{ {} }}", goal),
490 DomainGoal(goal) => write!(fmt, "{}", goal),
491 Quantified(qkind, goal) => {
492 // FIXME: appropriate binder names
493 write!(fmt, "{}<> {{ {} }}", qkind, goal.skip_binder())
495 CannotProve => write!(fmt, "CannotProve"),
500 impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
501 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
502 let traits::ProgramClause { goal, hypotheses } = self;
503 write!(fmt, "{}", goal)?;
504 if !hypotheses.is_empty() {
505 write!(fmt, " :- ")?;
506 for (index, condition) in hypotheses.iter().enumerate() {
510 write!(fmt, "{}", condition)?;
517 impl<'tcx> fmt::Display for traits::Clause<'tcx> {
518 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
519 use traits::Clause::*;
522 Implies(clause) => write!(fmt, "{}", clause),
524 // FIXME: appropriate binder names
525 write!(fmt, "forall<> {{ {} }}", clause.skip_binder())
531 EnumTypeFoldableImpl! {
532 impl<'tcx> TypeFoldable<'tcx> for traits::WhereClauseAtom<'tcx> {
533 (traits::WhereClauseAtom::Implemented)(trait_ref),
534 (traits::WhereClauseAtom::ProjectionEq)(projection),
538 EnumTypeFoldableImpl! {
539 impl<'tcx> TypeFoldable<'tcx> for traits::DomainGoal<'tcx> {
540 (traits::DomainGoal::Holds)(wc),
541 (traits::DomainGoal::WellFormed)(wc),
542 (traits::DomainGoal::FromEnv)(wc),
543 (traits::DomainGoal::WellFormedTy)(ty),
544 (traits::DomainGoal::Normalize)(projection),
545 (traits::DomainGoal::FromEnvTy)(ty),
546 (traits::DomainGoal::RegionOutlives)(predicate),
547 (traits::DomainGoal::TypeOutlives)(predicate),
551 CloneTypeFoldableImpls! {
552 traits::QuantifierKind,
555 EnumTypeFoldableImpl! {
556 impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
557 (traits::Goal::Implies)(hypotheses, goal),
558 (traits::Goal::And)(goal1, goal2),
559 (traits::Goal::Not)(goal),
560 (traits::Goal::DomainGoal)(domain_goal),
561 (traits::Goal::Quantified)(qkind, goal),
562 (traits::Goal::CannotProve),
566 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<traits::Goal<'tcx>> {
567 fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
568 let v = self.iter().map(|t| t.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
569 folder.tcx().intern_goals(&v)
572 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
573 self.iter().any(|t| t.visit_with(visitor))
577 impl<'tcx> TypeFoldable<'tcx> for &'tcx traits::Goal<'tcx> {
578 fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
579 let v = (**self).fold_with(folder);
580 folder.tcx().mk_goal(v)
583 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
584 (**self).visit_with(visitor)
588 BraceStructTypeFoldableImpl! {
589 impl<'tcx> TypeFoldable<'tcx> for traits::ProgramClause<'tcx> {
595 EnumTypeFoldableImpl! {
596 impl<'tcx> TypeFoldable<'tcx> for traits::Clause<'tcx> {
597 (traits::Clause::Implies)(clause),
598 (traits::Clause::ForAll)(clause),
602 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<traits::Clause<'tcx>> {
603 fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
604 let v = self.iter().map(|t| t.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
605 folder.tcx().intern_clauses(&v)
608 fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
609 self.iter().any(|t| t.visit_with(visitor))