{"id":"5c7644a72f61a750","repo":"rust-lang/rust","slug":"expected-subslice-projection-on-fixed-size-array","errorCode":null,"errorMessage":"expected subslice projection on fixed-size array","messagePattern":"expected subslice projection on fixed-size array","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_middle/src/mir/statement.rs","lineNumber":235,"sourceCode":"        }\n        let answer = match *elem {\n            ProjectionElem::Deref => {\n                let ty = structurally_normalize(self.ty).builtin_deref(true).unwrap_or_else(|| {\n                    bug!(\"deref projection of non-dereferenceable ty {:?}\", self)\n                });\n                PlaceTy::from_ty(ty)\n            }\n            ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {\n                PlaceTy::from_ty(structurally_normalize(self.ty).builtin_index().unwrap())\n            }\n            ProjectionElem::Subslice { from, to, from_end } => {\n                PlaceTy::from_ty(match structurally_normalize(self.ty).kind() {\n                    ty::Slice(..) => self.ty,\n                    ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from),\n                    ty::Array(inner, size) if from_end => {\n                        let size = size\n                            .try_to_target_usize(tcx)\n                            .expect(\"expected subslice projection on fixed-size array\");\n                        let len = size - from - to;\n                        Ty::new_array(tcx, *inner, len)\n                    }\n                    _ => bug!(\"cannot subslice non-array type: `{:?}`\", self),\n                })\n            }\n            ProjectionElem::Downcast(_name, index) => {\n                PlaceTy { ty: self.ty, variant_index: Some(index) }\n            }\n            ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(\n                structurally_normalize(self.ty),\n                self.variant_index,\n                f,\n                fty,\n            )),\n            ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty)),\n\n            // FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general.","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_middle/src/mir/statement.rs#L217-L253","documentation":"In `PlaceTy::projection_ty`, handling a `Subslice { from, to, from_end: true }` projection on a `ty::Array(inner, size)` calls `size.try_to_target_usize(tcx)` and `.expect`s `Some`. rustc_middle throws this when an from-end subslice is applied to an array whose length constant is not a monomorphic `Const` evaluating to a concrete usize (i.e. a generic/abstract array size).","triggerScenarios":"Triggered by MIR containing `&arr[from .. arr.len() - to]` (from_end subslice) where `arr` has type `[T; N]` with `N` still generic or otherwise not a concrete `usize` at the point of projection (e.g. evaluating MIR before monomorphization filled in `N`).","commonSituations":"Const generics code subslicing `[T; N]` inside a generic fn before monomorphization; mir-opt pass that re-orders subslice evaluation; nightly mir-level evaluation of generic array code; user code that depends on slice patterns of generic arrays in const context.","solutions":["Move the subslicing operation out of the generic context into a monomorphic call site so `N` is concrete when the projection is evaluated.","Use a `&[T]` slice (or `array::AsSlice`) instead of subslicing `[T; N]` directly so the projection goes through the `ty::Slice` arm which doesn't need a concrete length.","If writing/testing mir-opt, ensure subslice projections are only emitted after monomorphization, or guard `from_end` array subslices behind a concrete-length check.","Report a rustc bug with the generic-array subslice repro if it occurs in stock code (this is supposed to be handled by monomorphization before projection)."],"exampleFix":"// before: generic from-end array subslice\nfn tail<T, const N: usize>(a: [T; N]) -> &[T] { &a[1..] }\n// panic: expected subslice projection on fixed-size array (N is generic)\n\n// after\nfn tail<T, const N: usize>(a: [T; N]) -> &[T] { a[1..].as_ref() }","handlingStrategy":"type-guard","validationCode":"// ProjectionElem::Subslice { from_end: true } on an Array requires the\n// array length to be a concrete target-usize. Pre-check before projecting.\nuse rustc_middle::mir::PlaceTy;\nuse rustc_middle::ty::{self, Ty, TyCtxt};\nfn array_supports_from_end_subslice<'tcx>(pty: &PlaceTy<'tcx>, tcx: TyCtxt<'tcx>) -> bool {\n    if let ty::Array(_, len) = pty.ty.kind() {\n        len.try_to_target_usize(tcx).is_some() // concrete length resolvable\n    } else {\n        false // not an array at all\n    }\n}\n// Usage:\n//   if array_supports_from_end_subslice(&pty, tcx) {\n//       pty.projection_ty(tcx, ProjectionElem::Subslice { from, to, from_end: true })\n//   } else {\n//       // array length is generic/unknown: lower differently or reject\n//   }","typeGuard":"// Narrow a PlaceTy to 'Array with a statically-known length'.\nuse rustc_middle::mir::PlaceTy;\nuse rustc_middle::ty::{self, TyCtxt};\nfn as_fixed_array<'tcx>(pty: &PlaceTy<'tcx>, tcx: TyCtxt<'tcx>) -> Option<(ty::Ty<'tcx>, u64)> {\n    match pty.ty.kind() {\n        ty::Array(inner, len) => len.try_to_target_usize(tcx).map(|n| (*inner, n)),\n        _ => None,\n    }\n}","tryCatchPattern":null,"preventionTips":["A Subslice projection with `from_end: true` is only valid when the base is a fixed-size array whose length is a monomorphic const; never emit it for `[T]` slices or arrays with a generic length.","When lowering source-level `x[a..]` / `x[..b]` patterns onto arrays whose length depends on a generic const, defer or reject the pattern instead of emitting a from_end subslice.","In any MIR transformation that introduces Subslice, compute the array length first and fail soft (not panic) when it isn't a concrete usize.","Keep slices and arrays distinct in your mental model: slices use `ty::Slice(..)` (no length needed); only arrays hit this expect()."],"tags":["rustc","mir","const-generics","internal-invariant"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}