pub(crate) struct LoweringContext<'a, 'hir> {
Show 26 fields pub(crate) tcx: TyCtxt<'hir>, pub(crate) resolver: &'a mut ResolverAstLowering, pub(crate) arena: &'hir Arena<'hir>, pub(crate) ast_arena: &'a Arena<'static>, pub(crate) bodies: Vec<(ItemLocalId, &'hir Body<'hir>)>, pub(crate) attrs: SortedMap<ItemLocalId, &'hir [Attribute]>, pub(crate) children: Vec<(LocalDefId, MaybeOwner<&'hir OwnerInfo<'hir>>)>, pub(crate) generator_kind: Option<GeneratorKind>, pub(crate) task_context: Option<HirId>, pub(crate) current_item: Option<Span>, pub(crate) catch_scope: Option<NodeId>, pub(crate) loop_scope: Option<NodeId>, pub(crate) is_in_loop_condition: bool, pub(crate) is_in_trait_impl: bool, pub(crate) is_in_dyn_type: bool, pub(crate) current_hir_id_owner: OwnerId, pub(crate) item_local_id_counter: ItemLocalId, pub(crate) local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>, pub(crate) trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>, pub(crate) impl_trait_defs: Vec<GenericParam<'hir>>, pub(crate) impl_trait_bounds: Vec<WherePredicate<'hir>>, pub(crate) node_id_to_local_id: FxHashMap<NodeId, ItemLocalId>, pub(crate) allow_try_trait: Option<Lrc<[Symbol]>>, pub(crate) allow_gen_future: Option<Lrc<[Symbol]>>, pub(crate) allow_into_future: Option<Lrc<[Symbol]>>, pub(crate) generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
}

Fields§

§tcx: TyCtxt<'hir>§resolver: &'a mut ResolverAstLowering§arena: &'hir Arena<'hir>

Used to allocate HIR nodes.

§ast_arena: &'a Arena<'static>

Used to allocate temporary AST nodes for use during lowering. This allows us to create “fake” AST – these nodes can sometimes be allocated on the stack, but other times we need them to live longer than the current stack frame, so they can be collected into vectors and things like that.

§bodies: Vec<(ItemLocalId, &'hir Body<'hir>)>

Bodies inside the owner being lowered.

§attrs: SortedMap<ItemLocalId, &'hir [Attribute]>

Attributes inside the owner being lowered.

§children: Vec<(LocalDefId, MaybeOwner<&'hir OwnerInfo<'hir>>)>

Collect items that were created by lowering the current owner.

§generator_kind: Option<GeneratorKind>§task_context: Option<HirId>

When inside an async context, this is the HirId of the task_context local bound to the resume argument of the generator.

§current_item: Option<Span>

Used to get the current fn’s def span to point to when using await outside of an async fn.

§catch_scope: Option<NodeId>§loop_scope: Option<NodeId>§is_in_loop_condition: bool§is_in_trait_impl: bool§is_in_dyn_type: bool§current_hir_id_owner: OwnerId§item_local_id_counter: ItemLocalId§local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>§trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>§impl_trait_defs: Vec<GenericParam<'hir>>§impl_trait_bounds: Vec<WherePredicate<'hir>>§node_id_to_local_id: FxHashMap<NodeId, ItemLocalId>

NodeIds that are lowered inside the current HIR owner.

§allow_try_trait: Option<Lrc<[Symbol]>>§allow_gen_future: Option<Lrc<[Symbol]>>§allow_into_future: Option<Lrc<[Symbol]>>§generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>

Mapping from generics def_ids to TAIT generics def_ids. For each captured lifetime (e.g., ’a), we create a new lifetime parameter that is a generic defined on the TAIT, so we have type Foo<’a1> = … and we establish a mapping in this field from the original parameter ’a to the new parameter ’a1.

Implementations§

Desugar try { <stmts>; <expr> } into { <stmts>; ::std::ops::Try::from_output(<expr>) }, try { <stmts>; } into { <stmts>; ::std::ops::Try::from_output(()) } and save the block id to use it as a break target for desugaring of the ? operator.

Lower an async construct to a generator that implements Future.

This results in:

std::future::identity_future(static move? |_task_context| -> <ret_ty> {
    <body>
})

Desugar <expr>.await into:

match ::std::future::IntoFuture::into_future(<expr>) {
    mut __awaitee => loop {
        match unsafe { ::std::future::Future::poll(
            <::std::pin::Pin>::new_unchecked(&mut __awaitee),
            ::std::future::get_context(task_context),
        ) } {
            ::std::task::Poll::Ready(result) => break result,
            ::std::task::Poll::Pending => {}
        }
        task_context = yield ();
    }
}

Destructure the LHS of complex assignments. For instance, lower (a, b) = t to { let (lhs1, lhs2) = t; a = lhs1; b = lhs2; }.

If the given expression is a path to a tuple struct, returns that path. It is not a complete check, but just tries to reject most paths early if they are not tuple structs. Type checking will take care of the full validation later.

If the given expression is a path to a unit struct, returns that path. It is not a complete check, but just tries to reject most paths early if they are not unit structs. Type checking will take care of the full validation later.

Convert the LHS of a destructuring assignment to a pattern. Each sub-assignment is recorded in assignments.

Destructure a sequence of expressions occurring on the LHS of an assignment. Such a sequence occurs in a tuple (struct)/slice. Return a sequence of corresponding patterns, and the index and the span of .. if it exists. Each sub-assignment is recorded in assignments.

Desugar <start>..=<end> into std::ops::RangeInclusive::new(<start>, <end>).

Desugar ExprForLoop from: [opt_ident]: for <pat> in <head> <body> into:

{
    let result = match IntoIterator::into_iter(<head>) {
        mut iter => {
            [opt_ident]: loop {
                match Iterator::next(&mut iter) {
                    None => break,
                    Some(<pat>) => <body>,
                };
            }
        }
    };
    result
}

Desugar ExprKind::Try from: <expr>? into:

match Try::branch(<expr>) {
    ControlFlow::Continue(val) => #[allow(unreachable_code)] val,,
    ControlFlow::Break(residual) =>
        #[allow(unreachable_code)]
        // If there is an enclosing `try {...}`:
        break 'catch_target Try::from_residual(residual),
        // Otherwise:
        return Try::from_residual(residual),
}

Desugar ExprKind::Yeet from: do yeet <expr> into:

// If there is an enclosing `try {...}`:
break 'catch_target FromResidual::from_residual(Yeet(residual));
// Otherwise:
return FromResidual::from_residual(Yeet(residual));

But to simplify this, there’s a from_yeet lang item function which handles the combined FromResidual::from_residual(Yeet(residual)).

Wrap the given expr in a terminating scope using hir::ExprKind::DropTemps.

In terms of drop order, it has the same effect as wrapping expr in { let _t = $expr; _t } but should provide better compile-time performance.

The drop order can be important in e.g. if expr { .. }.

Construct ExprKind::Err for the given span.

Return the pair of the lowered generics as hir::Generics and the evaluation of f with the carried impl trait definitions and bounds.

Lower a slice pattern of form [pat_0, ..., pat_n] into hir::PatKind::Slice(before, slice, after).

When encountering ($binding_mode $ident @)? .. (slice), this is interpreted as a sub-slice pattern semantically. Patterns that follow, which are not like slice – or an error occurs, are in after.

Construct a Pat with the HirId of p.id lowered.

Emit a friendly error for extra .. patterns in a tuple/tuple struct/slice pattern.

Used to ban the .. pattern in places it shouldn’t be semantically.

Matches '-' lit | lit (cf. parser::Parser::parse_literal_maybe_minus), or paths for ranges.

An associated type binding Output = $ty.

Given the id of some node in the AST, finds the LocalDefId associated with it by the name resolver (if any).

Given the id of some node in the AST, finds the LocalDefId associated with it by the name resolver (if any), after applying any remapping from get_remapped_def_id.

For example, in a function like fn foo<'a>(x: &'a u32), invoking with the id from the ast::Lifetime node found inside the &'a u32 type would return the LocalDefId of the 'a parameter declared on foo.

This function also applies remapping from get_remapped_def_id. These are used when synthesizing opaque types from -> impl Trait return types and so forth. For example, in a function like fn foo<'a>() -> impl Debug + 'a, we would create an opaque type type FooReturn<'a1> = impl Debug + 'a1. When lowering the Debug + 'a bounds, we add a remapping to map 'a to 'a1.

Get the previously recorded to local def id given the from local def id, obtained using generics_def_id_map field.

Freshen the LoweringContext and ready it to lower a nested item. The lowered item is registered into self.children.

This function sets up HirId lowering infrastructure, and stashes the shared mutable state to avoid pollution by the closure.

Installs the remapping remap in scope while f is being executed. This causes references to the LocalDefId keys to be changed to refer to the values instead.

The remapping is used when one piece of AST expands to multiple pieces of HIR. For example, the function fn foo<'a>(...) -> impl Debug + 'a, expands to both a function definition (foo) and a TAIT for the return value, both of which have a lifetime parameter 'a. The remapping allows us to rewrite the 'a in the return value to refer to the 'a declared on the TAIT, instead of the function.

Hash the HIR node twice, one deep and one shallow hash. This allows to differentiate queries which depend on the full HIR tree and those which only depend on the item signature.

This method allocates a new HirId for the given NodeId and stores it in the LoweringContext’s NodeId => HirId map. Take care not to call this method if the resulting HirId is then not actually used in the HIR, as that would trigger an assertion in the HirIdValidator later on, which makes sure that all NodeIds got mapped properly. Calling the method twice with the same NodeId is fine though.

Generate a new HirId without a backing NodeId.

Reuses the span but adds information like the kind of the desugaring and features that are allowed inside this span.

Intercept all spans entering HIR. Mark a span as relative to the current owning item.

Converts a lifetime into a new generic parameter.

Lowers a lifetime binder that defines generic_params, returning the corresponding HIR nodes. The returned list includes any “extra” lifetime parameters that were added by the name resolver owing to lifetime elision; this also populates the resolver’s node-id->def-id map, so that later calls to opt_node_id_to_def_id that refer to these extra lifetime parameters will be successful.

Given an associated type constraint like one of these:

T: Iterator<Item: Debug>
            ^^^^^^^^^^^
T: Iterator<Item = Debug>
            ^^^^^^^^^^^^

returns a hir::TypeBinding representing Item.

Lowers a ReturnPositionOpaqueTy (-> impl Trait) or a TypeAliasesOpaqueTy (type F = impl Trait): this creates the associated Opaque Type (TAIT) definition and then returns a HIR type that references the TAIT.

Given a function definition like:

fn test<'a, T: Debug>(x: &'a T) -> impl Debug + 'a {
    x
}

we will create a TAIT definition in the HIR like

type TestReturn<'a, T, 'x> = impl Debug + 'x

and return a type like TestReturn<'static, T, 'a>, so that the function looks like:

fn test<'a, T: Debug>(x: &'a T) -> TestReturn<'static, T, 'a>

Note the subtlety around type parameters! The new TAIT, TestReturn, inherits all the type parameters from the function test (this is implemented in the query layer, they aren’t added explicitly in the HIR). But this includes all the lifetimes, and we only want to capture the lifetimes that are referenced in the bounds. Therefore, we add extra lifetime parameters for the lifetimes that get captured ('x, in our example above) and reference those.

Registers a new opaque type with the proper NodeIds and returns the lowered node-ID for the opaque type.

Given a parent_def_id, a list of lifetimes_in_bounds and a remappinghash to be filled, this function creates new definitions forParamandFresh` lifetimes, inserts the new definition, adds it to the remapping with the definition of the given lifetime and returns a list of lifetimes to be lowered afterwards.

Transforms -> T into Future<Output = T>.

Lowers a block directly to an expression, presuming that it has no attributes and is not targeted by a break.

Invoked to create the lifetime argument(s) for an elided trait object bound, like the bound in Box<dyn Debug>. This method is not invoked when the bound is written, even if it is written with '_ like in Box<dyn Debug + '_>. In those cases, lower_lifetime is invoked.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.

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: 352 bytes