Rollup merge of #113913 - dvdhrm:pr/transpalign, r=jackh726
error/E0691: include alignment in error message Include the computed alignment of the violating field when rejecting transparent types with non-trivially aligned ZSTs. ZST member fields in transparent types must have an alignment of 1 (to ensure it does not raise the layout requirements of the transparent field). The current error message looks like this: ```text LL | struct Foobar(u32, [u32; 0]); | ^^^^^^^^ has alignment larger than 1 ``` This patch changes the report to include the alignment of the violating field: ```text LL | struct Foobar(u32, [u32; 0]); | ^^^^^^^^ has alignment of 4, which is larger than 1 ``` In case of unknown alignments, it will yield: ```text LL | struct Foobar(u32, [u32; 0]); | ^^^^^^^^ may have alignment larger than 1 ``` This allows developers to get a better grasp why a specific field is rejected. Knowing the alignment of the violating field makes it easier to judge where that alignment-requirement originates, and thus hopefully provide better hints on how to mitigate the problem. This idea was proposed in 2022 in #98071 as part of a bigger change. This commit simply extracts this error-message change, to decouple it from the other diagnostic improvements. (Originally proposed by `@compiler-errors` in #98071)
This commit is contained in:
commit
4a90553717
@ -11,7 +11,8 @@ struct ForceAlign32;
|
||||
|
||||
#[repr(transparent)]
|
||||
struct Wrapper(f32, ForceAlign32); // error: zero-sized field in transparent
|
||||
// struct has alignment larger than 1
|
||||
// struct has alignment of 32, which
|
||||
// is larger than 1
|
||||
```
|
||||
|
||||
A transparent struct, enum, or union is supposed to be represented exactly like
|
||||
|
@ -1078,9 +1078,9 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
|
||||
// We are currently checking the type this field came from, so it must be local
|
||||
let span = tcx.hir().span_if_local(field.did).unwrap();
|
||||
let zst = layout.is_ok_and(|layout| layout.is_zst());
|
||||
let align1 = layout.is_ok_and(|layout| layout.align.abi.bytes() == 1);
|
||||
let align = layout.ok().map(|layout| layout.align.abi.bytes());
|
||||
if !zst {
|
||||
return (span, zst, align1, None);
|
||||
return (span, zst, align, None);
|
||||
}
|
||||
|
||||
fn check_non_exhaustive<'tcx>(
|
||||
@ -1115,12 +1115,12 @@ fn check_non_exhaustive<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
(span, zst, align1, check_non_exhaustive(tcx, ty).break_value())
|
||||
(span, zst, align, check_non_exhaustive(tcx, ty).break_value())
|
||||
});
|
||||
|
||||
let non_zst_fields = field_infos
|
||||
.clone()
|
||||
.filter_map(|(span, zst, _align1, _non_exhaustive)| if !zst { Some(span) } else { None });
|
||||
.filter_map(|(span, zst, _align, _non_exhaustive)| if !zst { Some(span) } else { None });
|
||||
let non_zst_count = non_zst_fields.clone().count();
|
||||
if non_zst_count >= 2 {
|
||||
bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, tcx.def_span(adt.did()));
|
||||
@ -1128,17 +1128,26 @@ fn check_non_exhaustive<'tcx>(
|
||||
let incompatible_zst_fields =
|
||||
field_infos.clone().filter(|(_, _, _, opt)| opt.is_some()).count();
|
||||
let incompat = incompatible_zst_fields + non_zst_count >= 2 && non_zst_count < 2;
|
||||
for (span, zst, align1, non_exhaustive) in field_infos {
|
||||
if zst && !align1 {
|
||||
struct_span_err!(
|
||||
for (span, zst, align, non_exhaustive) in field_infos {
|
||||
if zst && align != Some(1) {
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0691,
|
||||
"zero-sized field in transparent {} has alignment larger than 1",
|
||||
adt.descr(),
|
||||
)
|
||||
.span_label(span, "has alignment larger than 1")
|
||||
.emit();
|
||||
);
|
||||
|
||||
if let Some(align_bytes) = align {
|
||||
err.span_label(
|
||||
span,
|
||||
format!("has alignment of {align_bytes}, which is larger than 1"),
|
||||
);
|
||||
} else {
|
||||
err.span_label(span, "may have alignment larger than 1");
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
if incompat && let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive {
|
||||
tcx.struct_span_lint_hir(
|
||||
|
@ -20,13 +20,13 @@ error[E0691]: zero-sized field in transparent struct has alignment larger than 1
|
||||
--> $DIR/repr-transparent.rs:36:32
|
||||
|
|
||||
LL | struct NontrivialAlignZst(u32, [u16; 0]);
|
||||
| ^^^^^^^^ has alignment larger than 1
|
||||
| ^^^^^^^^ has alignment of 2, which is larger than 1
|
||||
|
||||
error[E0691]: zero-sized field in transparent struct has alignment larger than 1
|
||||
--> $DIR/repr-transparent.rs:42:24
|
||||
|
|
||||
LL | struct GenericAlign<T>(ZstAlign32<T>, u32);
|
||||
| ^^^^^^^^^^^^^ has alignment larger than 1
|
||||
| ^^^^^^^^^^^^^ has alignment of 32, which is larger than 1
|
||||
|
||||
error[E0084]: unsupported representation for zero-variant enum
|
||||
--> $DIR/repr-transparent.rs:44:1
|
||||
@ -66,13 +66,13 @@ error[E0691]: zero-sized field in transparent enum has alignment larger than 1
|
||||
--> $DIR/repr-transparent.rs:71:14
|
||||
|
|
||||
LL | Foo(u32, [u16; 0]),
|
||||
| ^^^^^^^^ has alignment larger than 1
|
||||
| ^^^^^^^^ has alignment of 2, which is larger than 1
|
||||
|
||||
error[E0691]: zero-sized field in transparent enum has alignment larger than 1
|
||||
--> $DIR/repr-transparent.rs:76:11
|
||||
|
|
||||
LL | Foo { bar: ZstAlign32<T>, baz: u32 }
|
||||
| ^^^^^^^^^^^^^^^^^^ has alignment larger than 1
|
||||
| ^^^^^^^^^^^^^^^^^^ has alignment of 32, which is larger than 1
|
||||
|
||||
error[E0690]: transparent union needs at most one non-zero-sized field, but has 2
|
||||
--> $DIR/repr-transparent.rs:85:1
|
||||
|
Loading…
Reference in New Issue
Block a user