[−][src]Struct rustc_trait_selection::traits::auto_trait::AutoTraitFinder
Fields
tcx: TyCtxt<'tcx>Implementations
impl<'tcx> AutoTraitFinder<'tcx>[src]
pub fn new(tcx: TyCtxt<'tcx>) -> Self[src]
pub fn find_auto_trait_generics<A>(
&self,
ty: Ty<'tcx>,
orig_env: ParamEnv<'tcx>,
trait_did: DefId,
auto_trait_callback: impl Fn(&InferCtxt<'_, 'tcx>, AutoTraitInfo<'tcx>) -> A
) -> AutoTraitResult<A>[src]
&self,
ty: Ty<'tcx>,
orig_env: ParamEnv<'tcx>,
trait_did: DefId,
auto_trait_callback: impl Fn(&InferCtxt<'_, 'tcx>, AutoTraitInfo<'tcx>) -> A
) -> AutoTraitResult<A>
Makes a best effort to determine whether and under which conditions an auto trait is implemented for a type. For example, if you have
struct Foo<T> { data: Box<T> }
then this might return that Foo
(Note that due to the coinductive nature of Send, the full and correct result is actually
quite simple to generate. That is, when a type has no custom impl, it is Send iff its field
types are all Send. So, in our example, we might have that Foo
Warning: The API should be considered highly unstable, and it may be refactored or removed in the future.
impl<'tcx> AutoTraitFinder<'tcx>[src]
pub(in traits::auto_trait) fn evaluate_predicates(
&self,
infcx: &InferCtxt<'_, 'tcx>,
trait_did: DefId,
ty: Ty<'tcx>,
param_env: ParamEnv<'tcx>,
user_env: ParamEnv<'tcx>,
fresh_preds: &mut FxHashSet<Predicate<'tcx>>,
only_projections: bool
) -> Option<(ParamEnv<'tcx>, ParamEnv<'tcx>)>[src]
&self,
infcx: &InferCtxt<'_, 'tcx>,
trait_did: DefId,
ty: Ty<'tcx>,
param_env: ParamEnv<'tcx>,
user_env: ParamEnv<'tcx>,
fresh_preds: &mut FxHashSet<Predicate<'tcx>>,
only_projections: bool
) -> Option<(ParamEnv<'tcx>, ParamEnv<'tcx>)>
The core logic responsible for computing the bounds for our synthesized impl.
To calculate the bounds, we call SelectionContext.select in a loop. Like
FulfillmentContext, we recursively select the nested obligations of predicates we
encounter. However, whenever we encounter an UnimplementedError involving a type
parameter, we add it to our ParamEnv. Since our goal is to determine when a particular
type implements an auto trait, Unimplemented errors tell us what conditions need to be met.
This method ends up working somewhat similarly to FulfillmentContext, but with a few key
differences. FulfillmentContext works under the assumption that it's dealing with concrete
user code. According, it considers all possible ways that a Predicate could be met, which
isn't always what we want for a synthesized impl. For example, given the predicate T: Iterator, FulfillmentContext can end up reporting an Unimplemented error for T: IntoIterator -- since there's an implementation of Iterator where T: IntoIterator,
FulfillmentContext will drive SelectionContext to consider that impl before giving up.
If we were to rely on FulfillmentContexts decision, we might end up synthesizing an impl
like this:
impl<T> Send for Foo<T> where T: IntoIterator
While it might be technically true that Foo implements Send where T: IntoIterator,
the bound is overly restrictive - it's really only necessary that T: Iterator.
For this reason, evaluate_predicates handles predicates with type variables specially.
When we encounter an Unimplemented error for a bound such as T: Iterator, we immediately
add it to our ParamEnv, and add it to our stack for recursive evaluation. When we later
select it, we'll pick up any nested bounds, without ever inferring that T: IntoIterator
needs to hold.
One additional consideration is supertrait bounds. Normally, a ParamEnv is only ever
constructed once for a given type. As part of the construction process, the ParamEnv will
have any supertrait bounds normalized -- e.g., if we have a type struct Foo<T: Copy>, the
ParamEnv will contain T: Copy and T: Clone, since Copy: Clone. When we construct our
own ParamEnv, we need to do this ourselves, through traits::elaborate_predicates, or
else SelectionContext will choke on the missing predicates. However, this should never
show up in the final synthesized generics: we don't want our generated docs page to contain
something like T: Copy + Clone, as that's redundant. Therefore, we keep track of a
separate user_env, which only holds the predicates that will actually be displayed to the
user.
pub(in traits::auto_trait) fn add_user_pred(
&self,
user_computed_preds: &mut FxHashSet<Predicate<'tcx>>,
new_pred: Predicate<'tcx>
)[src]
&self,
user_computed_preds: &mut FxHashSet<Predicate<'tcx>>,
new_pred: Predicate<'tcx>
)
This method is designed to work around the following issue:
When we compute auto trait bounds, we repeatedly call SelectionContext.select,
progressively building a ParamEnv based on the results we get.
However, our usage of SelectionContext differs from its normal use within the compiler,
in that we capture and re-reprocess predicates from Unimplemented errors.
This can lead to a corner case when dealing with region parameters.
During our selection loop in evaluate_predicates, we might end up with
two trait predicates that differ only in their region parameters:
one containing a HRTB lifetime parameter, and one containing a 'normal'
lifetime parameter. For example:
T as MyTrait<'a> T as MyTrait<'static>
If we put both of these predicates in our computed ParamEnv, we'll
confuse SelectionContext, since it will (correctly) view both as being applicable.
To solve this, we pick the 'more strict' lifetime bound -- i.e., the HRTB
Our end goal is to generate a user-visible description of the conditions
under which a type implements an auto trait. A trait predicate involving
a HRTB means that the type needs to work with any choice of lifetime,
not just one specific lifetime (e.g., 'static).
pub(in traits::auto_trait) fn map_vid_to_region<'cx>(
&self,
regions: &RegionConstraintData<'cx>
) -> FxHashMap<RegionVid, Region<'cx>>[src]
&self,
regions: &RegionConstraintData<'cx>
) -> FxHashMap<RegionVid, Region<'cx>>
This is very similar to handle_lifetimes. However, instead of matching ty::Regions
to each other, we match ty::RegionVids to ty::Regions.
pub(in traits::auto_trait) fn is_param_no_infer(
&self,
substs: SubstsRef<'_>
) -> bool[src]
&self,
substs: SubstsRef<'_>
) -> bool
pub fn is_of_param(&self, ty: Ty<'_>) -> bool[src]
pub(in traits::auto_trait) fn is_self_referential_projection(
&self,
p: PolyProjectionPredicate<'_>
) -> bool[src]
&self,
p: PolyProjectionPredicate<'_>
) -> bool
pub(in traits::auto_trait) fn evaluate_nested_obligations(
&self,
ty: Ty<'_>,
nested: impl Iterator<Item = Obligation<'tcx, Predicate<'tcx>>>,
computed_preds: &mut FxHashSet<Predicate<'tcx>>,
fresh_preds: &mut FxHashSet<Predicate<'tcx>>,
predicates: &mut VecDeque<PolyTraitPredicate<'tcx>>,
select: &mut SelectionContext<'_, 'tcx>,
only_projections: bool
) -> bool[src]
&self,
ty: Ty<'_>,
nested: impl Iterator<Item = Obligation<'tcx, Predicate<'tcx>>>,
computed_preds: &mut FxHashSet<Predicate<'tcx>>,
fresh_preds: &mut FxHashSet<Predicate<'tcx>>,
predicates: &mut VecDeque<PolyTraitPredicate<'tcx>>,
select: &mut SelectionContext<'_, 'tcx>,
only_projections: bool
) -> bool
pub fn clean_pred(
&self,
infcx: &InferCtxt<'_, 'tcx>,
p: Predicate<'tcx>
) -> Predicate<'tcx>[src]
&self,
infcx: &InferCtxt<'_, 'tcx>,
p: Predicate<'tcx>
) -> Predicate<'tcx>
Auto Trait Implementations
impl<'tcx> !RefUnwindSafe for AutoTraitFinder<'tcx>
impl<'tcx> !Send for AutoTraitFinder<'tcx>
impl<'tcx> !Sync for AutoTraitFinder<'tcx>
impl<'tcx> Unpin for AutoTraitFinder<'tcx>
impl<'tcx> !UnwindSafe for AutoTraitFinder<'tcx>
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized, [src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized, [src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized, [src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T[src]
impl<T> From<T> for T[src]
impl<T, U> Into<U> for T where
U: From<T>, [src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>, [src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>, [src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.