Skip to main content

## TypingMode

# Type Alias TypingMode

Source

    pub type TypingMode<'tcx> = TypingMode<TyCtxt<'tcx>>;

## Aliased Type§

    pub enum TypingMode<'tcx> {
        Coherence,
        Analysis {
            defining_opaque_types_and_generators: &'tcx RawList<(), LocalDefId>,
        },
        Borrowck {
            defining_opaque_types: &'tcx RawList<(), LocalDefId>,
        },
        PostBorrowckAnalysis {
            defined_opaque_types: &'tcx RawList<(), LocalDefId>,
        },
        PostAnalysis,
    }

## Variants§

§

### Coherence

When checking whether impls overlap, we check whether any obligations are guaranteed to never hold when unifying the impls. This requires us to be complete: we must never fail to prove something which may actually hold.

In this typing mode we bail with ambiguity in case its not knowable whether a trait goal may hold, e.g. because the trait may get implemented in a downstream or sibling crate.

We also have to be careful when generalizing aliases inside of higher-ranked types to not unnecessarily constrain any inference variables.

§

### Analysis

Analysis includes type inference, checking that items are well-formed, and pretty much everything else which may emit proper type errors to the user.

We only normalize opaque types which may get defined by the current body, which are stored in `defining_opaque_types`.

We also refuse to project any associated type that is marked `default`. Non-`default` (“final”) types are always projected. This is necessary in general for soundness of specialization. However, we could allow projections in fully-monomorphic cases. We choose not to, because we prefer for `default type` to force the type definition to be treated abstractly by any consumers of the impl. Concretely, that means that the following example will fail to compile:

ⓘ

    #![feature(specialization)]
    trait Assoc {
        type Output;
    }

    impl<T> Assoc for T {
        default type Output = bool;
    }

    fn main() {
        let x: <() as Assoc>::Output = true;
    }

#### Fields

§`defining_opaque_types_and_generators: &'tcx RawList<(), LocalDefId>`
§

### Borrowck

The behavior during MIR borrowck is identical to `TypingMode::Analysis` except that the initial value for opaque types is the type computed during HIR typeck with unique unconstrained region inference variables.

This is currently only used with by the new solver as it results in new non-universal defining uses of opaque types, which is a breaking change. See tests/ui/impl-trait/non-defining-use/as-projection-term.rs.

#### Fields

§`defining_opaque_types: &'tcx RawList<(), LocalDefId>`
§

### PostBorrowckAnalysis

Any analysis after borrowck for a given body should be able to use all the hidden types defined by borrowck, without being able to define any new ones.

This is currently only used by the new solver, but should be implemented in the old solver as well.

#### Fields

§`defined_opaque_types: &'tcx RawList<(), LocalDefId>`
§

### PostAnalysis

After analysis, mostly during codegen and MIR optimizations, we’re able to reveal all opaque types. As the hidden type should never be observable directly by the user, this should not be used by checks which may expose such details to the user.

There are some exceptions to this as for example `layout_of` and const-evaluation always run in `PostAnalysis` mode, even when used during analysis. This exposes some information about the underlying type to users, but not the type itself.

## Layout§

Note: Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.