Skip to content

Commit 585af05

Browse files
committed
Add test cases to verify u8/i8 array fix
1 parent 4a65fdc commit 585af05

File tree

5 files changed

+44
-29
lines changed

5 files changed

+44
-29
lines changed

compiler/rustc_const_eval/src/util/alignment.rs

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use tracing::debug;
66
/// Returns `true` if this place is allowed to be less aligned
77
/// than its containing struct (because it is within a packed
88
/// struct).
9-
pub fn is_potentially_disaligned<'tcx, L>(
9+
pub fn is_potentially_misaligned<'tcx, L>(
1010
tcx: TyCtxt<'tcx>,
1111
local_decls: &L,
1212
typing_env: ty::TypingEnv<'tcx>,
@@ -15,25 +15,16 @@ pub fn is_potentially_disaligned<'tcx, L>(
1515
where
1616
L: HasLocalDecls<'tcx>,
1717
{
18-
debug!("is_disaligned({:?})", place);
18+
debug!("is_potentially_misaligned({:?})", place);
1919
let Some(pack) = is_within_packed(tcx, local_decls, place) else {
20-
debug!("is_disaligned({:?}) - not within packed", place);
20+
debug!("is_potentially_misaligned({:?}) - not within packed", place);
2121
return false;
2222
};
2323

2424
let ty = place.ty(local_decls, tcx).ty;
2525
let unsized_tail = || tcx.struct_tail_for_codegen(ty, typing_env);
2626

27-
// Try to normalize the type to resolve any generic parameters
28-
let normalized_ty = match tcx.try_normalize_erasing_regions(typing_env, ty) {
29-
Ok(normalized) => normalized,
30-
Err(_) => {
31-
// If normalization fails, fall back to the original type
32-
ty
33-
}
34-
};
35-
36-
match tcx.layout_of(typing_env.as_query_input(normalized_ty)) {
27+
match tcx.layout_of(typing_env.as_query_input(ty)) {
3728
Ok(layout) => {
3829
if layout.align.abi <= pack
3930
&& (layout.is_sized() || matches!(unsized_tail().kind(), ty::Slice(..) | ty::Str))
@@ -44,7 +35,7 @@ where
4435
// just an approximation -- except when the unsized tail is a slice, where the alignment
4536
// is fully determined by the type.
4637
debug!(
47-
"is_disaligned({:?}) - align = {}, packed = {}; not disaligned",
38+
"is_potentially_misaligned({:?}) - align = {}, packed = {}; not disaligned",
4839
place,
4940
layout.align.abi.bytes(),
5041
pack.bytes()
@@ -55,12 +46,12 @@ where
5546
}
5647
}
5748
Err(_) => {
58-
// We cannot figure out the layout. This often happens with generic types.
59-
// For const generic arrays like [u8; CAP], we can make a reasonable assumption
60-
// about their alignment based on the element type.
49+
// Soundness-critical: this may return false positives (reporting potential misalignment),
50+
// but must not return false negatives. When layout is unavailable, we stay conservative
51+
// except for arrays of u8/i8 whose ABI alignment is provably 1.
6152

6253
// Try to determine alignment from the type structure
63-
if let Some(element_align) = get_element_alignment(tcx, normalized_ty) {
54+
if let Some(element_align) = get_element_alignment(tcx, ty) {
6455
element_align > pack
6556
} else {
6657
// If we still can't determine alignment, conservatively assume disaligned
@@ -71,16 +62,21 @@ where
7162
}
7263

7364
/// Try to determine the alignment of an array element type
74-
fn get_element_alignment<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Align> {
65+
fn get_element_alignment<'tcx>(_tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Align> {
7566
match ty.kind() {
7667
ty::Array(element_ty, _) | ty::Slice(element_ty) => {
77-
// For arrays and slices, the alignment is the same as the element type
78-
let param_env = ty::ParamEnv::empty();
79-
let typing_env =
80-
ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env };
81-
match tcx.layout_of(typing_env.as_query_input(*element_ty)) {
82-
Ok(layout) => Some(layout.align.abi),
83-
Err(_) => None,
68+
// Only allow u8 and i8 arrays when layout computation fails
69+
// Other types are conservatively assumed to be misaligned
70+
match element_ty.kind() {
71+
ty::Uint(ty::UintTy::U8) | ty::Int(ty::IntTy::I8) => {
72+
// For u8 and i8, we know their alignment is 1
73+
Some(Align::from_bytes(1).unwrap())
74+
}
75+
_ => {
76+
// For other types, we cannot safely determine alignment
77+
// Conservatively return None to indicate potential misalignment
78+
None
79+
}
8480
}
8581
}
8682
_ => None,

compiler/rustc_const_eval/src/util/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod check_validity_requirement;
66
mod compare_types;
77
mod type_name;
88

9-
pub use self::alignment::{is_potentially_disaligned, is_within_packed};
9+
pub use self::alignment::{is_potentially_misaligned, is_within_packed};
1010
pub use self::check_validity_requirement::check_validity_requirement;
1111
pub(crate) use self::check_validity_requirement::validate_scalar_in_layout;
1212
pub use self::compare_types::{relate_types, sub_types};

compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
5151

5252
match terminator.kind {
5353
TerminatorKind::Drop { place, .. }
54-
if util::is_potentially_disaligned(tcx, body, typing_env, place) =>
54+
if util::is_potentially_misaligned(tcx, body, typing_env, place) =>
5555
{
5656
add_move_for_packed_drop(
5757
tcx,

compiler/rustc_mir_transform/src/check_packed_ref.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
3838

3939
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
4040
if context.is_borrow()
41-
&& util::is_potentially_disaligned(self.tcx, self.body, self.typing_env, *place)
41+
&& util::is_potentially_misaligned(self.tcx, self.body, self.typing_env, *place)
4242
{
4343
let def_id = self.body.source.instance.def_id();
4444
if let Some(impl_def_id) = self.tcx.impl_of_assoc(def_id)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ check-pass
2+
#![allow(dead_code)]
3+
4+
#[repr(C, packed)]
5+
struct PascalStringI8<const CAP: usize> {
6+
len: u8,
7+
buf: [i8; CAP],
8+
}
9+
10+
fn bar<const CAP: usize>(s: &PascalStringI8<CAP>) -> &[i8] {
11+
// Goal: this line should not trigger E0793 for i8 arrays
12+
&s.buf[0..s.len as usize]
13+
}
14+
15+
fn main() {
16+
let p = PascalStringI8::<10> { len: 3, buf: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0] };
17+
let s = bar(&p);
18+
assert_eq!(s, &[1, 2, 3]);
19+
}

0 commit comments

Comments
 (0)