# 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),
}
}
```