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