---
# System prepended metadata

title: Const to pattern decomposition

---

# Const to pattern decomposition

[actual impl here](https://github.com/rust-lang/rust/blob/29d61427ac47dc16c83e1c66b929b1198a3ccc35/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs#L260)

Note that the "error" cases always create `_` patterns after hard erroring

```rust
fn recur(const, behind_ref: bool) -> Result<pat, Fallback> {
    match const.ty {
        float => lint + Ok(opaque),
        union => error,
        struct + !PartialEq + !StructuralEq => error,
        // Super hacky: this doesn't hard error, but unwinds to where
        // we can safely call PartialEq. So wherever we hit the
        // `other` branch in `check_ref`.
        // So even if we are somewhere deep in a field of a field of a field,
        // the entire pattern already created will be destroyed until we
        // get to a reference. There we then create an opaque pattern for the
        // reference, so `PartialEq` is used there.
        behind_ref + struct + !StructuralEq => lint + Err(Fallback),
        struct + PartialEq + !StructuralEq => error,
        array | tuple | struct | enum => Ok(destructure + for all fields: recur(field, behind_ref=false)?),
        bool | char | int | fn_def => Ok(non-opaque),
        reference(pointee_ty) => check_ref(const, pointee_ty, behind_ref)?,
        thin raw pointer => Ok(opaque),
        fn_ptr | wide raw ptr => lint + Ok(opaque),
        other => error,
    }
}

fn check_ref(const, pointee_ty, behind_ref: bool) -> Result<pat, Fallback> {
    match pointee_ty {
        str => non-opaque,
        array | slice => Ok(deref + destructure + for all fields: recur(field, behind_ref=false)?),
        // Note that we are at double-ref now, and only lint
        struct + !StructuralEq + behind_ref => lint + Ok(opaque),
        struct + !StructuralEq => error,
        // slices are handled above
        unsized => error,
        // Note that this is where "unwinding" stops for the really
        // weird edge case in `recur`.
        other => recur(deref(const), behind_ref=true).ok_or(opaque),
    }
}
```