Struct rustdoc::clean::auto_trait::AutoTraitFinder
source · pub(crate) struct AutoTraitFinder<'a, 'tcx> {
pub(crate) cx: &'a mut DocContext<'tcx>,
}
Fields§
§cx: &'a mut DocContext<'tcx>
Implementations§
source§impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx>where
'tcx: 'a,
impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx>where
'tcx: 'a,
pub(crate) fn new(cx: &'a mut DocContext<'tcx>) -> Self
fn generate_for_trait(
&mut self,
ty: Ty<'tcx>,
trait_def_id: DefId,
param_env: ParamEnv<'tcx>,
item_def_id: DefId,
f: &AutoTraitFinder<'tcx>,
discard_positive_impl: bool
) -> Option<Item>
pub(crate) fn get_auto_trait_impls(&mut self, item_def_id: DefId) -> Vec<Item> ⓘ
fn get_lifetime(
region: Region<'_>,
names_map: &FxHashMap<Symbol, Lifetime>
) -> Lifetime
sourcefn handle_lifetimes<'cx>(
regions: &RegionConstraintData<'cx>,
names_map: &FxHashMap<Symbol, Lifetime>
) -> ThinVec<WherePredicate>
fn handle_lifetimes<'cx>(
regions: &RegionConstraintData<'cx>,
names_map: &FxHashMap<Symbol, Lifetime>
) -> ThinVec<WherePredicate>
This method calculates two things: Lifetime constraints of the form 'a: 'b
,
and region constraints of the form RegionVid: 'a
This is essentially a simplified version of lexical_region_resolve. However, handle_lifetimes determines what needs be true in order for an impl to hold. lexical_region_resolve, along with much of the rest of the compiler, is concerned with determining if a given set up constraints/predicates are met, given some starting conditions (e.g., user-provided code). For this reason, it’s easier to perform the calculations we need on our own, rather than trying to make existing inference/solver code do what we want.
fn extract_for_generics(
&self,
pred: Predicate<'tcx>
) -> FxHashSet<GenericParamDef>
fn make_final_bounds(
&self,
ty_to_bounds: FxHashMap<Type, FxHashSet<GenericBound>>,
ty_to_fn: FxHashMap<Type, (PolyTrait, Option<Type>)>,
lifetime_to_bounds: FxHashMap<Lifetime, FxHashSet<GenericBound>>
) -> Vec<WherePredicate> ⓘ
sourcefn param_env_to_generics(
&mut self,
item_def_id: DefId,
param_env: ParamEnv<'tcx>,
existing_predicates: ThinVec<WherePredicate>,
vid_to_region: FxHashMap<RegionVid, Region<'tcx>>
) -> Generics
fn param_env_to_generics(
&mut self,
item_def_id: DefId,
param_env: ParamEnv<'tcx>,
existing_predicates: ThinVec<WherePredicate>,
vid_to_region: FxHashMap<RegionVid, Region<'tcx>>
) -> Generics
Converts the calculated ParamEnv
and lifetime information to a clean::Generics
, suitable for
display on the docs page. Cleaning the Predicates
produces sub-optimal WherePredicate
s,
so we fix them up:
- Multiple bounds for the same type are coalesced into one: e.g.,
T: Copy
,T: Debug
becomesT: Copy + Debug
Fn
bounds are handled specially - instead of leaving it asT: Fn(), <T as Fn::Output> = K
, we use the dedicated syntaxT: Fn() -> K
- We explicitly add a
?Sized
bound if we didn’t find anySized
predicates for a type
sourcefn sort_where_predicates(&self, predicates: &mut [WherePredicate])
fn sort_where_predicates(&self, predicates: &mut [WherePredicate])
Ensure that the predicates are in a consistent order. The precise ordering doesn’t actually matter, but it’s important that a given set of predicates always appears in the same order - both for visual consistency between ‘rustdoc’ runs, and to make writing tests much easier
sourcefn sort_where_bounds(&self, bounds: &mut Vec<GenericBound>)
fn sort_where_bounds(&self, bounds: &mut Vec<GenericBound>)
Ensure that the bounds are in a consistent order. The precise ordering doesn’t actually matter, but it’s important that a given set of bounds always appears in the same order - both for visual consistency between ‘rustdoc’ runs, and to make writing tests much easier
sourcefn unstable_debug_sort<T: Debug>(&self, vec: &mut [T])
fn unstable_debug_sort<T: Debug>(&self, vec: &mut [T])
This might look horrendously hacky, but it’s actually not that bad.
For performance reasons, we use several different FxHashMaps in the process of computing the final set of where predicates. However, the iteration order of a HashMap is completely unspecified. In fact, the iteration of an FxHashMap can even vary between platforms, since FxHasher has different behavior for 32-bit and 64-bit platforms.
Obviously, it’s extremely undesirable for documentation rendering to be dependent on the platform it’s run on. Apart from being confusing to end users, it makes writing tests much more difficult, as predicates can appear in any order in the final result.
To solve this problem, we sort WherePredicates and GenericBounds by their Debug string. The thing to keep in mind is that we don’t really care what the final order is - we’re synthesizing an impl or bound ourselves, so any order can be considered equally valid. By sorting the predicates and bounds, however, we ensure that for a given codebase, all auto-trait impls always render in exactly the same way.
Using the Debug implementation for sorting prevents us from needing to write quite a bit of almost entirely useless code (e.g., how should two Types be sorted relative to each other). It also allows us to solve the problem for both WherePredicates and GenericBounds at the same time. This approach is probably somewhat slower, but the small number of items involved (impls rarely have more than a few bounds) means that it shouldn’t matter in practice.
fn is_fn_trait(&self, path: &Path) -> bool
Auto Trait Implementations§
impl<'a, 'tcx> !RefUnwindSafe for AutoTraitFinder<'a, 'tcx>
impl<'a, 'tcx> !Send for AutoTraitFinder<'a, 'tcx>
impl<'a, 'tcx> !Sync for AutoTraitFinder<'a, 'tcx>
impl<'a, 'tcx> Unpin for AutoTraitFinder<'a, 'tcx>where
'tcx: 'a,
impl<'a, 'tcx> !UnwindSafe for AutoTraitFinder<'a, 'tcx>
Blanket Implementations§
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
source§fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where
S: Into<Dispatch>,
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where
S: Into<Dispatch>,
source§fn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
Layout§
Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...)
attributes. Please see the Rust Reference’s “Type Layout” chapter for details on type layout guarantees.
Size: 8 bytes