`as` is very complicated and do a lot of different things. See https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html#type-cast-expressions. This doc goes through the ways in which `as` casts are implemented from source (where they all look the same) to codegen (where they are all resolved). The motivation is finding the proper way to fix https://github.com/rust-lang/rust/pull/113262, possibly revealing ways in which casts could be improved and made less confusing. # AST/HIR `as` casts are parsed into the AST, where they are of course still represented as a simple `ExprKind::Cast`. HIR is the same, as `as` is dependent on the types. # Typeck The first interesting interaction is typeck. Typeck is responsible for ensuring that all casts are well-formed. This happens in the `cast` module: https://github.com/rust-lang/rust/blob/e4cd1610067501fa4d347eba7b18f77137dbbf48/compiler/rustc_hir_typeck/src/cast.rs#L3. It [first tries](https://github.com/rust-lang/rust/blob/e4cd1610067501fa4d347eba7b18f77137dbbf48/compiler/rustc_hir_typeck/src/cast.rs#L732) to resolve the cast with a coercion. If that works, the cast is marked as a coercion cast for later. If it doesn't, then the complicated casting machinery is called to make sure that the cast is valid. Importantly, the result of this analysis is simply discarded. Additionally, the coercion code also stores the necessary adjustments required for the coercion. # THIR THIR still has a mostly unified `Cast` expression, except for some pointer related _coercions_, for which it uses `ExprKind::PointerCoercion` which contains some casts that come from _coercions_. The enum inside is shared with the coercion typeck code. Additionally it also contains `ExprKind::NeverToAny` for that coercion. THIR lowering first loweres the HIR expression directly and then applies adjustments. When lowering the cast itself, it checks whether typeck deemed the cast to be a coercion cast (using `TypeckResults::is_coercion_cast`). If it is one, it is not treated as an `ExprKind::Cast` anymore but simple a `Use`. There is a curious special case with `ExprKind::Pointer(PointerCast::ArrayToPointer)`. If the source is a reference (and it's not a coercion cast), then this expr is constructed. It also does some special casing for enum variant casts to prevent cycles but that's not too important here. All non-coercion casts are turned into `ExprKind::Cast`. This means that even ptr->ptr casts end up as `ExprKind::Cast` instead of `ExprKind::Pointer`! Other than the special case above, only pointer related casts from adjustments are turned into that THIR expr. # MIR MIR knows the `Rvalue::Cast`. But unlike the previous "does anything" casts, MIR's cast is fully resolved. As we've seen at the start, there are many different [kinds of casts](https://github.com/rust-lang/rust/blob/e4cd1610067501fa4d347eba7b18f77137dbbf48/compiler/rustc_middle/src/mir/syntax.rs#L1225), but they're now exhaustively listed. MIR building for `Cast` computes the `mir::CastKind` based on the types. MIR casts are a little weirdly organized due to the sharing of the `PointerCoercion` enum with adjustments. # codegen Codegen looks at the MIR casts and deals with them.