{"record":{"id":"81dfdc95b2a56459","repo":"rust-lang/rust","slug":"expected-pointee-to-have-a-layout","errorCode":null,"errorMessage":"expected pointee to have a layout","messagePattern":"expected pointee to have a layout","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_codegen_cranelift/src/base.rs","lineNumber":953,"sourceCode":"\n        StatementKind::Coverage { .. } => unreachable!(),\n        StatementKind::Intrinsic(intrinsic) => match &**intrinsic {\n            // We ignore `assume` intrinsics, they are only useful for optimizations\n            NonDivergingIntrinsic::Assume(_) => {}\n            NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {\n                src,\n                dst,\n                count,\n            }) => {\n                let dst = codegen_operand(fx, dst);\n\n                let &ty::RawPtr(pointee, _) = dst.layout().ty.kind() else {\n                    bug!(\"expected pointer\")\n                };\n                let pointee_layout = fx\n                    .tcx\n                    .layout_of(fx.typing_env().as_query_input(pointee))\n                    .expect(\"expected pointee to have a layout\");\n                let elem_size: u64 = pointee_layout.layout.size().bytes();\n\n                let dst = dst.load_scalar(fx);\n                let src = codegen_operand(fx, src).load_scalar(fx);\n                let count = codegen_operand(fx, count).load_scalar(fx);\n\n                let bytes = if elem_size != 1 {\n                    fx.bcx.ins().imul_imm_u(count, elem_size as i64)\n                } else {\n                    count\n                };\n\n                fx.bcx.call_memcpy(fx.target_config, dst, src, bytes);\n            }\n        },\n    }\n}\n","sourceCodeStart":935,"sourceCodeEnd":971,"githubUrl":"https://github.com/rust-lang/rust/blob/7088e4b63a9516ebfbfe2ab2d999cf01a528ac14/compiler/rustc_codegen_cranelift/src/base.rs#L935-L971","documentation":"This fires in Cranelift codegen when processing the `CopyNonOverlapping` non-diverging intrinsic. The code extracts the pointee type from the destination raw pointer (`dst.layout().ty`) and calls `fx.tcx.layout_of(pointee).expect(\"expected pointee to have a layout\")`. If the pointee type doesn't have a computable layout (e.g., it's unsized in an unsupported way, it's an extern type, or it's an error type from a prior compilation failure), `layout_of` returns `Err` and this panics.","triggerScenarios":"Calling `core::intrinsics::copy_nonoverlapping` (or code that desugars to the `CopyNonOverlapping` MIR intrinsic) with a raw pointer whose pointee type has no valid layout — extern types, `?Sized` types that aren't slices/str/trait objects, or types containing errors from failed compilation.","commonSituations":"Using raw pointers to extern types (`extern type`) or custom unsized types with `copy_nonoverlapping`. Also triggered when an earlier type-check error produces a type error (ty::Error) that propagates to codegen — the error type has no layout.","solutions":["Fix any preceding compilation errors first — a `ty::Error` leaking to codegen is often the root cause.","Avoid `copy_nonoverlapping` with pointers to extern types or unsupported unsized types; use a concrete sized type instead.","If the pointee is legitimately sized, file a bug — `layout_of` should succeed for all sized types at codegen time.","Use the LLVM backend (`-Zcodegen-backend=llvm`) to check if this is cg_clif-specific.","If contributing to cg_clif, handle `layout_of` errors with a proper diagnostic instead of panicking."],"exampleFix":"// before (extern type pointee → no layout → panic)\nextern \"C\" { type Opaque; }\nunsafe fn copy(ptr: *const Opaque, dst: *mut Opaque) {\n    std::ptr::copy_nonoverlapping(ptr, dst, 1);\n}\n\n// after (use a concrete sized type or byte buffer)\nunsafe fn copy(ptr: *const u8, dst: *mut u8, len: usize) {\n    std::ptr::copy_nonoverlapping(ptr, dst, len);\n}","handlingStrategy":"validation","validationCode":"// Before calling copy_nonoverlapping, ensure the pointee is sized\n// and has a valid layout:\nfn safe_copy_nonoverlapping<T: Sized>(src: *const T, dst: *mut T, count: usize) {\n    // T: Sized guarantees layout_of succeeds\n    unsafe { std::ptr::copy_nonoverlapping(src, dst, count); }\n}\n// Never call with pointers to extern types or ty::Error","typeGuard":"// Type guard: only allow copy_nonoverlapping on Sized types\nfn is_sized_pointee<T: ?Sized>() -> bool {\n    std::mem::size_of_val(&()) > 0 // placeholder\n}\n// Better: use a trait bound\ntrait SafeCopy: Sized {}\nimpl<T: Sized> SafeCopy for T {}\nfn copy_safe<T: SafeCopy>(src: *const T, dst: *mut T, len: usize) {\n    unsafe { std::ptr::copy_nonoverlapping(src, dst, len) }\n}","tryCatchPattern":null,"preventionTips":["Always use T: Sized bounds on functions that call copy_nonoverlapping with raw pointers.","Never create raw pointers to extern types for use with copy intrinsics.","Fix all preceding compilation errors before investigating codegen ICEs.","Use the LLVM backend as a fallback for code with unusual unsized types."],"tags":["rustc","cranelift","codegen","ice","layout","intrinsics","unsized","compiler-internal"],"backgroundTag":null,"analyzedSha":"7088e4b63a9516ebfbfe2ab2d999cf01a528ac14","analyzedAt":"2026-08-10T14:17:03.603Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}