From 301137d6f768d1fba633f4def15c03efb1ab32b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Fri, 15 Aug 2025 09:53:19 +0800 Subject: [PATCH 01/15] Fix E0793 error for packed structs with const generic parameters - Add fallback mechanism in is_disaligned() when layout computation fails - Handle TooGeneric errors by computing element alignment from type structure - Fix packed-array-const-generic.rs test to pass compilation - Resolves issue where const generic parameters couldn't be resolved during alignment checks --- .../rustc_const_eval/src/util/alignment.rs | 91 ++++++++++++++----- tests/ui/packed/packed-array-const-generic.rs | 19 ++++ 2 files changed, 89 insertions(+), 21 deletions(-) create mode 100644 tests/ui/packed/packed-array-const-generic.rs diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 9507b24f603eb..2899f3e3b2437 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -1,6 +1,6 @@ use rustc_abi::Align; use rustc_middle::mir::*; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use tracing::debug; /// Returns `true` if this place is allowed to be less aligned @@ -23,30 +23,79 @@ where let ty = place.ty(local_decls, tcx).ty; let unsized_tail = || tcx.struct_tail_for_codegen(ty, typing_env); - match tcx.layout_of(typing_env.as_query_input(ty)) { - Ok(layout) + + // Try to normalize the type to resolve any generic parameters + let normalized_ty = match tcx.try_normalize_erasing_regions(typing_env, ty) { + Ok(normalized) => normalized, + Err(_) => { + // If normalization fails, fall back to the original type + ty + } + }; + + match tcx.layout_of(typing_env.as_query_input(normalized_ty)) { + Ok(layout) => { if layout.align.abi <= pack && (layout.is_sized() - || matches!(unsized_tail().kind(), ty::Slice(..) | ty::Str)) => - { - // If the packed alignment is greater or equal to the field alignment, the type won't be - // further disaligned. - // However we need to ensure the field is sized; for unsized fields, `layout.align` is - // just an approximation -- except when the unsized tail is a slice, where the alignment - // is fully determined by the type. - debug!( - "is_disaligned({:?}) - align = {}, packed = {}; not disaligned", - place, - layout.align.abi.bytes(), - pack.bytes() - ); - false + || matches!(unsized_tail().kind(), ty::Slice(..) | ty::Str)) { + // If the packed alignment is greater or equal to the field alignment, the type won't be + // further disaligned. + // However we need to ensure the field is sized; for unsized fields, `layout.align` is + // just an approximation -- except when the unsized tail is a slice, where the alignment + // is fully determined by the type. + debug!( + "is_disaligned({:?}) - align = {}, packed = {}; not disaligned", + place, + layout.align.abi.bytes(), + pack.bytes() + ); + false + } else { + true + } + } + Err(_) => { + // We cannot figure out the layout. This often happens with generic types. + // For const generic arrays like [u8; CAP], we can make a reasonable assumption + // about their alignment based on the element type. + + // Try to determine alignment from the type structure + if let Some(element_align) = get_element_alignment(tcx, normalized_ty) { + if element_align <= pack { + false + } else { + true + } + } else { + // If we still can't determine alignment, conservatively assume disaligned + true + } + } + } +} + +/// Try to determine the alignment of an array element type +fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { + match ty.kind() { + ty::Array(element_ty, _) => { + // For arrays, the alignment is the same as the element type + let param_env = ty::ParamEnv::empty(); + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; + match tcx.layout_of(typing_env.as_query_input(*element_ty)) { + Ok(layout) => Some(layout.align.abi), + Err(_) => None, + } } - _ => { - // We cannot figure out the layout. Conservatively assume that this is disaligned. - debug!("is_disaligned({:?}) - true", place); - true + ty::Slice(element_ty) => { + // For slices, the alignment is the same as the element type + let param_env = ty::ParamEnv::empty(); + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; + match tcx.layout_of(typing_env.as_query_input(*element_ty)) { + Ok(layout) => Some(layout.align.abi), + Err(_) => None, + } } + _ => None, } } diff --git a/tests/ui/packed/packed-array-const-generic.rs b/tests/ui/packed/packed-array-const-generic.rs new file mode 100644 index 0000000000000..9215f37019033 --- /dev/null +++ b/tests/ui/packed/packed-array-const-generic.rs @@ -0,0 +1,19 @@ +//@ check-pass +#![allow(dead_code)] + +#[repr(C, packed)] +struct PascalString { + len: u8, + buf: [u8; CAP], +} + +fn bar(s: &PascalString) -> &str { + // 目标:这行不应触发 E0793 + std::str::from_utf8(&s.buf[0..s.len as usize]).unwrap() +} + +fn main() { + let p = PascalString::<10> { len: 3, buf: *b"abc\0\0\0\0\0\0\0" }; + let s = bar(&p); + assert_eq!(s, "abc"); +} From 19f51f27cd67d2efafae9170c8f4ee3c6a93e7a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Fri, 15 Aug 2025 10:41:21 +0800 Subject: [PATCH 02/15] Fix code formatting issues --- compiler/rustc_const_eval/src/util/alignment.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 2899f3e3b2437..41a4107d36d1b 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -23,7 +23,7 @@ where let ty = place.ty(local_decls, tcx).ty; let unsized_tail = || tcx.struct_tail_for_codegen(ty, typing_env); - + // Try to normalize the type to resolve any generic parameters let normalized_ty = match tcx.try_normalize_erasing_regions(typing_env, ty) { Ok(normalized) => normalized, @@ -32,12 +32,12 @@ where ty } }; - + match tcx.layout_of(typing_env.as_query_input(normalized_ty)) { Ok(layout) => { if layout.align.abi <= pack - && (layout.is_sized() - || matches!(unsized_tail().kind(), ty::Slice(..) | ty::Str)) { + && (layout.is_sized() || matches!(unsized_tail().kind(), ty::Slice(..) | ty::Str)) + { // If the packed alignment is greater or equal to the field alignment, the type won't be // further disaligned. // However we need to ensure the field is sized; for unsized fields, `layout.align` is @@ -58,7 +58,7 @@ where // We cannot figure out the layout. This often happens with generic types. // For const generic arrays like [u8; CAP], we can make a reasonable assumption // about their alignment based on the element type. - + // Try to determine alignment from the type structure if let Some(element_align) = get_element_alignment(tcx, normalized_ty) { if element_align <= pack { @@ -75,7 +75,7 @@ where } /// Try to determine the alignment of an array element type -fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { +fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { match ty.kind() { ty::Array(element_ty, _) => { // For arrays, the alignment is the same as the element type @@ -98,7 +98,6 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option _ => None, } } - pub fn is_within_packed<'tcx, L>( tcx: TyCtxt<'tcx>, local_decls: &L, From a2a94b9f21050ab848e65b42c085b220a736bda8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Fri, 15 Aug 2025 10:46:01 +0800 Subject: [PATCH 03/15] Fix remaining code formatting issues --- compiler/rustc_const_eval/src/util/alignment.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 41a4107d36d1b..110c2de3f181b 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -61,11 +61,7 @@ where // Try to determine alignment from the type structure if let Some(element_align) = get_element_alignment(tcx, normalized_ty) { - if element_align <= pack { - false - } else { - true - } + element_align > pack } else { // If we still can't determine alignment, conservatively assume disaligned true @@ -80,7 +76,10 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { // For arrays, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; + let typing_env = ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env, + }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), Err(_) => None, @@ -89,7 +88,10 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { // For slices, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; + let typing_env = ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env, + }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), Err(_) => None, From 2e84ab8c4430655eb0576dd09659ed62711dc9b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Fri, 15 Aug 2025 10:47:54 +0800 Subject: [PATCH 04/15] Fix TypingEnv formatting to match rustfmt requirements --- compiler/rustc_const_eval/src/util/alignment.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 110c2de3f181b..93530c3f037a8 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -76,10 +76,7 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { // For arrays, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = ty::TypingEnv { - typing_mode: ty::TypingMode::non_body_analysis(), - param_env, - }; + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), Err(_) => None, @@ -88,10 +85,7 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { // For slices, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = ty::TypingEnv { - typing_mode: ty::TypingMode::non_body_analysis(), - param_env, - }; + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), Err(_) => None, From d8785b98f52bf9feb7132c0005f9ba8927ea9247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Fri, 15 Aug 2025 10:50:13 +0800 Subject: [PATCH 05/15] Fix TypingEnv formatting to match rustfmt requirements --- compiler/rustc_const_eval/src/util/alignment.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 93530c3f037a8..110c2de3f181b 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -76,7 +76,10 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { // For arrays, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; + let typing_env = ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env, + }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), Err(_) => None, @@ -85,7 +88,10 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { // For slices, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; + let typing_env = ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env, + }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), Err(_) => None, From dd1537c2f937dad880905ea6f860d8b1df03c91e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Fri, 15 Aug 2025 10:52:05 +0800 Subject: [PATCH 06/15] Fix TypingEnv formatting to match rustfmt requirements --- compiler/rustc_const_eval/src/util/alignment.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 110c2de3f181b..d2b640c065e2e 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -76,10 +76,8 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { // For arrays, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = ty::TypingEnv { - typing_mode: ty::TypingMode::non_body_analysis(), - param_env, - }; + let typing_env = + ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), Err(_) => None, @@ -88,10 +86,8 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { // For slices, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = ty::TypingEnv { - typing_mode: ty::TypingMode::non_body_analysis(), - param_env, - }; + let typing_env = + ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), Err(_) => None, From 99dedb01583e1ea116e010968028e4cf7f0c5056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Fri, 15 Aug 2025 10:54:48 +0800 Subject: [PATCH 07/15] Fix TypingEnv formatting to match rustfmt requirements --- compiler/rustc_const_eval/src/util/alignment.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index d2b640c065e2e..58051ba235d42 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -76,7 +76,7 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { // For arrays, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), @@ -86,7 +86,7 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { // For slices, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), From 46205274f87ff281c29ae502516802f42d8a8bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Fri, 15 Aug 2025 11:37:40 +0800 Subject: [PATCH 08/15] fix: update is_disaligned check and tests --- compiler/rustc_const_eval/src/util/alignment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 58051ba235d42..7bd8976fbb53b 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -71,7 +71,7 @@ where } /// Try to determine the alignment of an array element type -fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: ty::Ty<'tcx>) -> Option { +fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { match ty.kind() { ty::Array(element_ty, _) => { // For arrays, the alignment is the same as the element type From 2fe4b7f5d555d7958f06889598af9d0ff95ccc61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Mon, 18 Aug 2025 13:16:43 +0800 Subject: [PATCH 09/15] =?UTF-8?q?Rename=20is=5Fdisaligned=20to=20is=5Fpote?= =?UTF-8?q?ntially=5Fdisaligned=20for=20better=20semantic=20clarity;=20Uni?= =?UTF-8?q?fied=20to=20ty::Array(element=5Fty,=20=5F)=20|=20ty::Slice(elem?= =?UTF-8?q?ent=5Fty)=20=3D>=20=E2=80=A6;=20Modify=20Chinese=20comments=20t?= =?UTF-8?q?o=20English=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rustc_const_eval/src/util/alignment.rs | 20 +++++-------------- compiler/rustc_const_eval/src/util/mod.rs | 2 +- .../src/add_moves_for_packed_drops.rs | 2 +- .../src/check_packed_ref.rs | 2 +- tests/ui/packed/packed-array-const-generic.rs | 2 +- 5 files changed, 9 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 7bd8976fbb53b..d9cc19ea150e5 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -6,7 +6,7 @@ use tracing::debug; /// Returns `true` if this place is allowed to be less aligned /// than its containing struct (because it is within a packed /// struct). -pub fn is_disaligned<'tcx, L>( +pub fn is_potentially_disaligned<'tcx, L>( tcx: TyCtxt<'tcx>, local_decls: &L, typing_env: ty::TypingEnv<'tcx>, @@ -73,21 +73,10 @@ where /// Try to determine the alignment of an array element type fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { match ty.kind() { - ty::Array(element_ty, _) => { - // For arrays, the alignment is the same as the element type + ty::Array(element_ty, _) | ty::Slice(element_ty) => { + // For arrays and slices, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = - ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; - match tcx.layout_of(typing_env.as_query_input(*element_ty)) { - Ok(layout) => Some(layout.align.abi), - Err(_) => None, - } - } - ty::Slice(element_ty) => { - // For slices, the alignment is the same as the element type - let param_env = ty::ParamEnv::empty(); - let typing_env = - ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), Err(_) => None, @@ -96,6 +85,7 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option _ => None, } } + pub fn is_within_packed<'tcx, L>( tcx: TyCtxt<'tcx>, local_decls: &L, diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs index 5be5ee8d1ae97..2a97e13c375b1 100644 --- a/compiler/rustc_const_eval/src/util/mod.rs +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -6,7 +6,7 @@ mod check_validity_requirement; mod compare_types; mod type_name; -pub use self::alignment::{is_disaligned, is_within_packed}; +pub use self::alignment::{is_potentially_disaligned, is_within_packed}; pub use self::check_validity_requirement::check_validity_requirement; pub(crate) use self::check_validity_requirement::validate_scalar_in_layout; pub use self::compare_types::{relate_types, sub_types}; diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 7ae2ebaf4ff09..1a18688c61dc0 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -51,7 +51,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { match terminator.kind { TerminatorKind::Drop { place, .. } - if util::is_disaligned(tcx, body, typing_env, place) => + if util::is_potentially_disaligned(tcx, body, typing_env, place) => { add_move_for_packed_drop( tcx, diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index dcb812c78993e..b01f44168fb11 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -37,7 +37,7 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { } fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { - if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.typing_env, *place) + if context.is_borrow() && util::is_potentially_disaligned(self.tcx, self.body, self.typing_env, *place) { let def_id = self.body.source.instance.def_id(); if let Some(impl_def_id) = self.tcx.impl_of_assoc(def_id) diff --git a/tests/ui/packed/packed-array-const-generic.rs b/tests/ui/packed/packed-array-const-generic.rs index 9215f37019033..c5b6a6e017ac7 100644 --- a/tests/ui/packed/packed-array-const-generic.rs +++ b/tests/ui/packed/packed-array-const-generic.rs @@ -8,7 +8,7 @@ struct PascalString { } fn bar(s: &PascalString) -> &str { - // 目标:这行不应触发 E0793 + // Goal: this line should not trigger E0793 std::str::from_utf8(&s.buf[0..s.len as usize]).unwrap() } From f0c8e9ecc40dcf5c24659154ce7d2c23df419ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Mon, 18 Aug 2025 13:19:33 +0800 Subject: [PATCH 10/15] Rename is_disaligned to is_potentially_disaligned for better semantic clarity --- compiler/rustc_const_eval/src/util/alignment.rs | 3 ++- compiler/rustc_mir_transform/src/check_packed_ref.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index d9cc19ea150e5..ae5995ab13644 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -76,7 +76,8 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option ty::Array(element_ty, _) | ty::Slice(element_ty) => { // For arrays and slices, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; + let typing_env = + ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), Err(_) => None, diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index b01f44168fb11..f1b54a7cf4531 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -37,7 +37,8 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { } fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { - if context.is_borrow() && util::is_potentially_disaligned(self.tcx, self.body, self.typing_env, *place) + if context.is_borrow() + && util::is_potentially_disaligned(self.tcx, self.body, self.typing_env, *place) { let def_id = self.body.source.instance.def_id(); if let Some(impl_def_id) = self.tcx.impl_of_assoc(def_id) From 4a65fdca1addf5da2196b50d71a563e8f1bb4b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Mon, 18 Aug 2025 13:21:04 +0800 Subject: [PATCH 11/15] Rename is_disaligned to is_potentially_disaligned for better semantic clarity --- compiler/rustc_const_eval/src/util/alignment.rs | 2 +- compiler/rustc_mir_transform/src/check_packed_ref.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index ae5995ab13644..87845ff44e1e4 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -76,7 +76,7 @@ fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option ty::Array(element_ty, _) | ty::Slice(element_ty) => { // For arrays and slices, the alignment is the same as the element type let param_env = ty::ParamEnv::empty(); - let typing_env = + let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; match tcx.layout_of(typing_env.as_query_input(*element_ty)) { Ok(layout) => Some(layout.align.abi), diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index f1b54a7cf4531..ab4f8761b438c 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -37,7 +37,7 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { } fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { - if context.is_borrow() + if context.is_borrow() && util::is_potentially_disaligned(self.tcx, self.body, self.typing_env, *place) { let def_id = self.body.source.instance.def_id(); From 585af058e9d12102e6ce5d018acba080b0c17c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Mon, 18 Aug 2025 16:38:06 +0800 Subject: [PATCH 12/15] Add test cases to verify u8/i8 array fix --- .../rustc_const_eval/src/util/alignment.rs | 48 +++++++++---------- compiler/rustc_const_eval/src/util/mod.rs | 2 +- .../src/add_moves_for_packed_drops.rs | 2 +- .../src/check_packed_ref.rs | 2 +- .../packed/packed-array-i8-const-generic.rs | 19 ++++++++ 5 files changed, 44 insertions(+), 29 deletions(-) create mode 100644 tests/ui/packed/packed-array-i8-const-generic.rs diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 87845ff44e1e4..a12a0d4f29dfb 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -6,7 +6,7 @@ use tracing::debug; /// Returns `true` if this place is allowed to be less aligned /// than its containing struct (because it is within a packed /// struct). -pub fn is_potentially_disaligned<'tcx, L>( +pub fn is_potentially_misaligned<'tcx, L>( tcx: TyCtxt<'tcx>, local_decls: &L, typing_env: ty::TypingEnv<'tcx>, @@ -15,25 +15,16 @@ pub fn is_potentially_disaligned<'tcx, L>( where L: HasLocalDecls<'tcx>, { - debug!("is_disaligned({:?})", place); + debug!("is_potentially_misaligned({:?})", place); let Some(pack) = is_within_packed(tcx, local_decls, place) else { - debug!("is_disaligned({:?}) - not within packed", place); + debug!("is_potentially_misaligned({:?}) - not within packed", place); return false; }; let ty = place.ty(local_decls, tcx).ty; let unsized_tail = || tcx.struct_tail_for_codegen(ty, typing_env); - // Try to normalize the type to resolve any generic parameters - let normalized_ty = match tcx.try_normalize_erasing_regions(typing_env, ty) { - Ok(normalized) => normalized, - Err(_) => { - // If normalization fails, fall back to the original type - ty - } - }; - - match tcx.layout_of(typing_env.as_query_input(normalized_ty)) { + match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(layout) => { if layout.align.abi <= pack && (layout.is_sized() || matches!(unsized_tail().kind(), ty::Slice(..) | ty::Str)) @@ -44,7 +35,7 @@ where // just an approximation -- except when the unsized tail is a slice, where the alignment // is fully determined by the type. debug!( - "is_disaligned({:?}) - align = {}, packed = {}; not disaligned", + "is_potentially_misaligned({:?}) - align = {}, packed = {}; not disaligned", place, layout.align.abi.bytes(), pack.bytes() @@ -55,12 +46,12 @@ where } } Err(_) => { - // We cannot figure out the layout. This often happens with generic types. - // For const generic arrays like [u8; CAP], we can make a reasonable assumption - // about their alignment based on the element type. + // Soundness-critical: this may return false positives (reporting potential misalignment), + // but must not return false negatives. When layout is unavailable, we stay conservative + // except for arrays of u8/i8 whose ABI alignment is provably 1. // Try to determine alignment from the type structure - if let Some(element_align) = get_element_alignment(tcx, normalized_ty) { + if let Some(element_align) = get_element_alignment(tcx, ty) { element_align > pack } else { // If we still can't determine alignment, conservatively assume disaligned @@ -71,16 +62,21 @@ where } /// Try to determine the alignment of an array element type -fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { +fn get_element_alignment<'tcx>(_tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { match ty.kind() { ty::Array(element_ty, _) | ty::Slice(element_ty) => { - // For arrays and slices, the alignment is the same as the element type - let param_env = ty::ParamEnv::empty(); - let typing_env = - ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env }; - match tcx.layout_of(typing_env.as_query_input(*element_ty)) { - Ok(layout) => Some(layout.align.abi), - Err(_) => None, + // Only allow u8 and i8 arrays when layout computation fails + // Other types are conservatively assumed to be misaligned + match element_ty.kind() { + ty::Uint(ty::UintTy::U8) | ty::Int(ty::IntTy::I8) => { + // For u8 and i8, we know their alignment is 1 + Some(Align::from_bytes(1).unwrap()) + } + _ => { + // For other types, we cannot safely determine alignment + // Conservatively return None to indicate potential misalignment + None + } } } _ => None, diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs index 2a97e13c375b1..fa582ef0d430b 100644 --- a/compiler/rustc_const_eval/src/util/mod.rs +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -6,7 +6,7 @@ mod check_validity_requirement; mod compare_types; mod type_name; -pub use self::alignment::{is_potentially_disaligned, is_within_packed}; +pub use self::alignment::{is_potentially_misaligned, is_within_packed}; pub use self::check_validity_requirement::check_validity_requirement; pub(crate) use self::check_validity_requirement::validate_scalar_in_layout; pub use self::compare_types::{relate_types, sub_types}; diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 1a18688c61dc0..dbc35087ba207 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -51,7 +51,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { match terminator.kind { TerminatorKind::Drop { place, .. } - if util::is_potentially_disaligned(tcx, body, typing_env, place) => + if util::is_potentially_misaligned(tcx, body, typing_env, place) => { add_move_for_packed_drop( tcx, diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index ab4f8761b438c..db67a43da5653 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -38,7 +38,7 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { if context.is_borrow() - && util::is_potentially_disaligned(self.tcx, self.body, self.typing_env, *place) + && util::is_potentially_misaligned(self.tcx, self.body, self.typing_env, *place) { let def_id = self.body.source.instance.def_id(); if let Some(impl_def_id) = self.tcx.impl_of_assoc(def_id) diff --git a/tests/ui/packed/packed-array-i8-const-generic.rs b/tests/ui/packed/packed-array-i8-const-generic.rs new file mode 100644 index 0000000000000..7a51f5f913150 --- /dev/null +++ b/tests/ui/packed/packed-array-i8-const-generic.rs @@ -0,0 +1,19 @@ +//@ check-pass +#![allow(dead_code)] + +#[repr(C, packed)] +struct PascalStringI8 { + len: u8, + buf: [i8; CAP], +} + +fn bar(s: &PascalStringI8) -> &[i8] { + // Goal: this line should not trigger E0793 for i8 arrays + &s.buf[0..s.len as usize] +} + +fn main() { + let p = PascalStringI8::<10> { len: 3, buf: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0] }; + let s = bar(&p); + assert_eq!(s, &[1, 2, 3]); +} From b37f57104a327e8686b3aeb67027de63257317b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Mon, 18 Aug 2025 16:47:01 +0800 Subject: [PATCH 13/15] updated the comment to formally justify that align([T]) == align(T) --- compiler/rustc_const_eval/src/util/alignment.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index a12a0d4f29dfb..04146a67c54c4 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -46,9 +46,12 @@ where } } Err(_) => { - // Soundness-critical: this may return false positives (reporting potential misalignment), - // but must not return false negatives. When layout is unavailable, we stay conservative - // except for arrays of u8/i8 whose ABI alignment is provably 1. + // Soundness: For any `T`, the ABI alignment requirement of `[T]` equals that of `T`. + // Proof sketch: + // (1) From `&[T]` we can obtain `&T`, hence align([T]) >= align(T). + // (2) Using `std::array::from_ref(&T)` we can obtain `&[T; 1]` (and thus `&[T]`), + // hence align(T) >= align([T]). + // Therefore align([T]) == align(T). Length does not affect alignment. // Try to determine alignment from the type structure if let Some(element_align) = get_element_alignment(tcx, ty) { From ef2538bb2a1eaa0c5d243ea32a14f9bd9b003ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Wed, 27 Aug 2025 10:31:22 +0800 Subject: [PATCH 14/15] refactor: improve get_element_alignment function for packed arrays --- .../rustc_const_eval/src/util/alignment.rs | 46 ++++-- tests/ui/packed/packed-array-const-generic.rs | 19 --- .../ui/packed/packed-array-generic-length.rs | 137 ++++++++++++++++++ .../packed/packed-array-generic-length.stderr | 33 +++++ .../packed/packed-array-i8-const-generic.rs | 19 --- 5 files changed, 200 insertions(+), 54 deletions(-) delete mode 100644 tests/ui/packed/packed-array-const-generic.rs create mode 100644 tests/ui/packed/packed-array-generic-length.rs create mode 100644 tests/ui/packed/packed-array-generic-length.stderr delete mode 100644 tests/ui/packed/packed-array-i8-const-generic.rs diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 04146a67c54c4..435985b2e1cf3 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -54,7 +54,7 @@ where // Therefore align([T]) == align(T). Length does not affect alignment. // Try to determine alignment from the type structure - if let Some(element_align) = get_element_alignment(tcx, ty) { + if let Some(element_align) = get_element_alignment(tcx, typing_env, ty) { element_align > pack } else { // If we still can't determine alignment, conservatively assume disaligned @@ -64,22 +64,36 @@ where } } -/// Try to determine the alignment of an array element type -fn get_element_alignment<'tcx>(_tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { +/// Returns the ABI alignment of the *element type* if `ty` is an array/slice, +/// otherwise `None`. +/// +/// Soundness note: +/// For any `T`, the ABI alignment of `[T]` (and `[T; N]`) equals that of `T` +/// and does not depend on the length `N`. +/// Proof sketch: +/// (1) From `&[T]` we can obtain `&T` ⇒ align([T]) ≥ align(T). +/// (2) From `&T` we can obtain `&[T; 1]` via `std::array::from_ref` +/// (and thus `&[T]`) ⇒ align(T) ≥ align([T]). +/// Hence `align([T]) == align(T)`. +/// +/// Therefore, when `layout_of([T; N])` is unavailable in generic contexts, +/// it is sufficient (and safe) to use `layout_of(T)` for alignment checks. +/// +/// Returns: +/// - `Some(align)` if `ty` is `Array(elem, _)` or `Slice(elem)` and +/// `layout_of(elem)` is available; +/// - `None` otherwise (caller should stay conservative). +fn get_element_alignment<'tcx>( + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, +) -> Option { match ty.kind() { - ty::Array(element_ty, _) | ty::Slice(element_ty) => { - // Only allow u8 and i8 arrays when layout computation fails - // Other types are conservatively assumed to be misaligned - match element_ty.kind() { - ty::Uint(ty::UintTy::U8) | ty::Int(ty::IntTy::I8) => { - // For u8 and i8, we know their alignment is 1 - Some(Align::from_bytes(1).unwrap()) - } - _ => { - // For other types, we cannot safely determine alignment - // Conservatively return None to indicate potential misalignment - None - } + ty::Array(elem_ty, _) | ty::Slice(elem_ty) => { + // Try to obtain the element's layout; if we can, use its ABI align. + match tcx.layout_of(typing_env.as_query_input(*elem_ty)) { + Ok(layout) => Some(layout.align.abi), + Err(_) => None, // stay conservative when even the element's layout is unknown } } _ => None, diff --git a/tests/ui/packed/packed-array-const-generic.rs b/tests/ui/packed/packed-array-const-generic.rs deleted file mode 100644 index c5b6a6e017ac7..0000000000000 --- a/tests/ui/packed/packed-array-const-generic.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ check-pass -#![allow(dead_code)] - -#[repr(C, packed)] -struct PascalString { - len: u8, - buf: [u8; CAP], -} - -fn bar(s: &PascalString) -> &str { - // Goal: this line should not trigger E0793 - std::str::from_utf8(&s.buf[0..s.len as usize]).unwrap() -} - -fn main() { - let p = PascalString::<10> { len: 3, buf: *b"abc\0\0\0\0\0\0\0" }; - let s = bar(&p); - assert_eq!(s, "abc"); -} diff --git a/tests/ui/packed/packed-array-generic-length.rs b/tests/ui/packed/packed-array-generic-length.rs new file mode 100644 index 0000000000000..dc205a9b44452 --- /dev/null +++ b/tests/ui/packed/packed-array-generic-length.rs @@ -0,0 +1,137 @@ +//! Borrowing from packed arrays with generic length: +//! - allowed if ABI align([T]) == align(T) <= packed alignment +//! - hard error (E0793) otherwise +#![allow(dead_code, unused_variables, unused_mut)] +use std::mem::MaybeUninit; +use std::num::{NonZeroU8, NonZeroU16}; + +// +// -------- PASS CASES -------- +// + +mod pass_u8 { + #[repr(C, packed)] + pub struct PascalString { + len: u8, + buf: [u8; N], + } + + pub fn bar(s: &PascalString) -> &str { + // should NOT trigger E0793 + std::str::from_utf8(&s.buf[0..s.len as usize]).unwrap() + } + + pub fn run() { + let p = PascalString::<10> { len: 3, buf: *b"abc\0\0\0\0\0\0\0" }; + let s = bar(&p); + assert_eq!(s, "abc"); + } +} + +mod pass_i8 { + #[repr(C, packed)] + pub struct S { + buf: [i8; N], + } + pub fn run() { + let s = S::<4> { buf: [1, 2, 3, 4] }; + let _ok = &s.buf[..]; // no E0793 + } +} + +mod pass_nonzero_u8 { + use super::*; + #[repr(C, packed)] + pub struct S { + buf: [NonZeroU8; N], + } + pub fn run() { + let s = S::<3> { + buf: [ + NonZeroU8::new(1).unwrap(), + NonZeroU8::new(2).unwrap(), + NonZeroU8::new(3).unwrap(), + ], + }; + let _ok = &s.buf[..]; // no E0793 + } +} + +mod pass_maybeuninit_u8 { + use super::*; + #[repr(C, packed)] + pub struct S { + buf: [MaybeUninit; N], + } + pub fn run() { + let s = S::<2> { buf: [MaybeUninit::new(1), MaybeUninit::new(2)] }; + let _ok = &s.buf[..]; // no E0793 + } +} + +mod pass_transparent_u8 { + #[repr(transparent)] + pub struct WrapU8(u8); + + #[repr(C, packed)] + pub struct S { + buf: [WrapU8; N], + } + pub fn run() { + let s = S::<2> { buf: [WrapU8(1), WrapU8(2)] }; + let _ok = &s.buf[..]; // no E0793 + } +} + +// +// -------- FAIL CASES (expect E0793) -------- +// + +mod fail_u16 { + #[repr(C, packed)] + pub struct S { + buf: [u16; N], + } + pub fn run() { + let s = S::<2> { buf: [1, 2] }; + let _err = &s.buf[..]; + //~^ ERROR: reference to packed field is unaligned + } +} + +mod fail_nonzero_u16 { + use super::*; + #[repr(C, packed)] + pub struct S { + buf: [NonZeroU16; N], + } + pub fn run() { + let s = S::<1> { buf: [NonZeroU16::new(1).unwrap()] }; + let _err = &s.buf[..]; + //~^ ERROR: reference to packed field is unaligned + } +} + +mod fail_transparent_u16 { + #[repr(transparent)] + pub struct WrapU16(u16); + + #[repr(C, packed)] + pub struct S { + buf: [WrapU16; N], + } + pub fn run() { + let s = S::<1> { buf: [WrapU16(42)] }; + let _err = &s.buf[..]; + //~^ ERROR: reference to packed field is unaligned + } +} + +fn main() { + // Run pass cases (fail cases only check diagnostics) + pass_u8::run(); + pass_i8::run(); + pass_nonzero_u8::run(); + pass_maybeuninit_u8::run(); + pass_transparent_u8::run(); +} diff --git a/tests/ui/packed/packed-array-generic-length.stderr b/tests/ui/packed/packed-array-generic-length.stderr new file mode 100644 index 0000000000000..937e21e7d948f --- /dev/null +++ b/tests/ui/packed/packed-array-generic-length.stderr @@ -0,0 +1,33 @@ +error[E0793]: reference to packed field is unaligned + --> $DIR/packed-array-generic-length.rs:97:21 + | +LL | let _err = &s.buf[..]; + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/packed-array-generic-length.rs:110:21 + | +LL | let _err = &s.buf[..]; + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/packed-array-generic-length.rs:125:21 + | +LL | let _err = &s.buf[..]; + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0793`. diff --git a/tests/ui/packed/packed-array-i8-const-generic.rs b/tests/ui/packed/packed-array-i8-const-generic.rs deleted file mode 100644 index 7a51f5f913150..0000000000000 --- a/tests/ui/packed/packed-array-i8-const-generic.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ check-pass -#![allow(dead_code)] - -#[repr(C, packed)] -struct PascalStringI8 { - len: u8, - buf: [i8; CAP], -} - -fn bar(s: &PascalStringI8) -> &[i8] { - // Goal: this line should not trigger E0793 for i8 arrays - &s.buf[0..s.len as usize] -} - -fn main() { - let p = PascalStringI8::<10> { len: 3, buf: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0] }; - let s = bar(&p); - assert_eq!(s, &[1, 2, 3]); -} From 8c07e0a003691fa502f41c4719db75130787e418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Wed, 27 Aug 2025 12:07:56 +0800 Subject: [PATCH 15/15] modify commit for check --- .../rustc_const_eval/src/util/alignment.rs | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 435985b2e1cf3..104044522b0f7 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -64,25 +64,8 @@ where } } -/// Returns the ABI alignment of the *element type* if `ty` is an array/slice, -/// otherwise `None`. -/// -/// Soundness note: -/// For any `T`, the ABI alignment of `[T]` (and `[T; N]`) equals that of `T` -/// and does not depend on the length `N`. -/// Proof sketch: -/// (1) From `&[T]` we can obtain `&T` ⇒ align([T]) ≥ align(T). -/// (2) From `&T` we can obtain `&[T; 1]` via `std::array::from_ref` -/// (and thus `&[T]`) ⇒ align(T) ≥ align([T]). -/// Hence `align([T]) == align(T)`. -/// -/// Therefore, when `layout_of([T; N])` is unavailable in generic contexts, -/// it is sufficient (and safe) to use `layout_of(T)` for alignment checks. -/// -/// Returns: -/// - `Some(align)` if `ty` is `Array(elem, _)` or `Slice(elem)` and -/// `layout_of(elem)` is available; -/// - `None` otherwise (caller should stay conservative). +// For arrays/slices, `align([T]) == align(T)` (independent of length). +// So if layout_of([T; N]) is unavailable, we can fall back to layout_of(T). fn get_element_alignment<'tcx>( tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>,