2019-02-05 11:20:45 -06:00
|
|
|
use crate::traits;
|
|
|
|
use crate::traits::project::Normalized;
|
2020-03-29 16:41:09 +02:00
|
|
|
use rustc_middle::ty;
|
2022-06-17 13:15:00 +01:00
|
|
|
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable};
|
|
|
|
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor};
|
2015-09-14 12:53:53 +03:00
|
|
|
|
|
|
|
use std::fmt;
|
2020-10-21 14:24:35 +02:00
|
|
|
use std::ops::ControlFlow;
|
2015-09-14 12:53:53 +03:00
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
// Structural impls for the structs in `traits`.
|
2015-09-14 12:53:53 +03:00
|
|
|
|
|
|
|
impl<'tcx, T: fmt::Debug> fmt::Debug for Normalized<'tcx, T> {
|
2018-08-29 22:02:42 -07:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2019-02-28 22:43:53 +00:00
|
|
|
write!(f, "Normalized({:?}, {:?})", self.value, self.obligations)
|
2015-09-14 12:53:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx, O: fmt::Debug> fmt::Debug for traits::Obligation<'tcx, O> {
|
2018-08-29 22:02:42 -07:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2017-11-23 23:03:47 +02:00
|
|
|
if ty::tls::with(|tcx| tcx.sess.verbose()) {
|
2018-05-08 18:15:48 -03:00
|
|
|
write!(
|
|
|
|
f,
|
2019-02-28 22:43:53 +00:00
|
|
|
"Obligation(predicate={:?}, cause={:?}, param_env={:?}, depth={})",
|
2018-12-03 00:49:12 +02:00
|
|
|
self.predicate, self.cause, self.param_env, self.recursion_depth
|
2018-05-08 18:15:48 -03:00
|
|
|
)
|
2017-11-23 23:03:47 +02:00
|
|
|
} else {
|
2019-02-28 22:43:53 +00:00
|
|
|
write!(f, "Obligation(predicate={:?}, depth={})", self.predicate, self.recursion_depth)
|
2017-11-23 23:03:47 +02:00
|
|
|
}
|
2015-09-14 12:53:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
|
2018-08-29 22:02:42 -07:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2018-05-08 18:15:48 -03:00
|
|
|
write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)
|
2015-09-14 12:53:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
|
2018-08-29 22:02:42 -07:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2015-09-14 12:53:53 +03:00
|
|
|
match *self {
|
|
|
|
super::CodeSelectionError(ref e) => write!(f, "{:?}", e),
|
|
|
|
super::CodeProjectionError(ref e) => write!(f, "{:?}", e),
|
2018-05-08 18:15:48 -03:00
|
|
|
super::CodeSubtypeError(ref a, ref b) => {
|
|
|
|
write!(f, "CodeSubtypeError({:?}, {:?})", a, b)
|
|
|
|
}
|
2020-02-29 10:03:04 +13:00
|
|
|
super::CodeConstEquateError(ref a, ref b) => {
|
|
|
|
write!(f, "CodeConstEquateError({:?}, {:?})", a, b)
|
|
|
|
}
|
2018-05-08 18:15:48 -03:00
|
|
|
super::CodeAmbiguity => write!(f, "Ambiguity"),
|
2015-09-14 12:53:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> {
|
2018-08-29 22:02:42 -07:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2015-09-14 12:53:53 +03:00
|
|
|
write!(f, "MismatchedProjectionTypes({:?})", self.err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-01 14:39:03 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// TypeFoldable implementations.
|
|
|
|
|
|
|
|
impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O> {
|
Folding revamp.
This commit makes type folding more like the way chalk does it.
Currently, `TypeFoldable` has `fold_with` and `super_fold_with` methods.
- `fold_with` is the standard entry point, and defaults to calling
`super_fold_with`.
- `super_fold_with` does the actual work of traversing a type.
- For a few types of interest (`Ty`, `Region`, etc.) `fold_with` instead
calls into a `TypeFolder`, which can then call back into
`super_fold_with`.
With the new approach, `TypeFoldable` has `fold_with` and
`TypeSuperFoldable` has `super_fold_with`.
- `fold_with` is still the standard entry point, *and* it does the
actual work of traversing a type, for all types except types of
interest.
- `super_fold_with` is only implemented for the types of interest.
Benefits of the new model.
- I find it easier to understand. The distinction between types of
interest and other types is clearer, and `super_fold_with` doesn't
exist for most types.
- With the current model is easy to get confused and implement a
`super_fold_with` method that should be left defaulted. (Some of the
precursor commits fixed such cases.)
- With the current model it's easy to call `super_fold_with` within
`TypeFolder` impls where `fold_with` should be called. The new
approach makes this mistake impossible, and this commit fixes a number
of such cases.
- It's potentially faster, because it avoids the `fold_with` ->
`super_fold_with` call in all cases except types of interest. A lot of
the time the compile would inline those away, but not necessarily
always.
2022-06-02 11:38:15 +10:00
|
|
|
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
2021-05-19 13:34:54 +02:00
|
|
|
Ok(traits::Obligation {
|
2020-10-24 09:27:15 +02:00
|
|
|
cause: self.cause,
|
2018-11-01 14:39:03 +01:00
|
|
|
recursion_depth: self.recursion_depth,
|
2021-12-01 00:55:57 +00:00
|
|
|
predicate: self.predicate.try_fold_with(folder)?,
|
|
|
|
param_env: self.param_env.try_fold_with(folder)?,
|
2021-05-19 13:34:54 +02:00
|
|
|
})
|
2018-11-01 14:39:03 +01:00
|
|
|
}
|
2022-06-17 12:09:23 +01:00
|
|
|
}
|
2018-11-01 14:39:03 +01:00
|
|
|
|
2022-06-17 12:09:23 +01:00
|
|
|
impl<'tcx, O: TypeVisitable<'tcx>> TypeVisitable<'tcx> for traits::Obligation<'tcx, O> {
|
Folding revamp.
This commit makes type folding more like the way chalk does it.
Currently, `TypeFoldable` has `fold_with` and `super_fold_with` methods.
- `fold_with` is the standard entry point, and defaults to calling
`super_fold_with`.
- `super_fold_with` does the actual work of traversing a type.
- For a few types of interest (`Ty`, `Region`, etc.) `fold_with` instead
calls into a `TypeFolder`, which can then call back into
`super_fold_with`.
With the new approach, `TypeFoldable` has `fold_with` and
`TypeSuperFoldable` has `super_fold_with`.
- `fold_with` is still the standard entry point, *and* it does the
actual work of traversing a type, for all types except types of
interest.
- `super_fold_with` is only implemented for the types of interest.
Benefits of the new model.
- I find it easier to understand. The distinction between types of
interest and other types is clearer, and `super_fold_with` doesn't
exist for most types.
- With the current model is easy to get confused and implement a
`super_fold_with` method that should be left defaulted. (Some of the
precursor commits fixed such cases.)
- With the current model it's easy to call `super_fold_with` within
`TypeFolder` impls where `fold_with` should be called. The new
approach makes this mistake impossible, and this commit fixes a number
of such cases.
- It's potentially faster, because it avoids the `fold_with` ->
`super_fold_with` call in all cases except types of interest. A lot of
the time the compile would inline those away, but not necessarily
always.
2022-06-02 11:38:15 +10:00
|
|
|
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
2021-11-24 17:20:52 -06:00
|
|
|
self.predicate.visit_with(visitor)?;
|
|
|
|
self.param_env.visit_with(visitor)
|
2018-03-28 14:13:08 +02:00
|
|
|
}
|
|
|
|
}
|