Skip to content

Commit 2fd2f9c

Browse files
committed
fix error for unsized packed struct field
1 parent afd0a2f commit 2fd2f9c

File tree

5 files changed

+32
-17
lines changed

5 files changed

+32
-17
lines changed

src/librustc/traits/error_reporting.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1472,11 +1472,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
14721472
ObligationCauseCode::StructInitializerSized => {
14731473
err.note("structs must have a statically known size to be initialized");
14741474
}
1475-
ObligationCauseCode::FieldSized(ref item) => {
1475+
ObligationCauseCode::FieldSized { adt_kind: ref item, last } => {
14761476
match *item {
14771477
AdtKind::Struct => {
1478-
err.note("only the last field of a struct may have a dynamically \
1479-
sized type");
1478+
if last {
1479+
err.note("the last field of a packed struct may only have a \
1480+
dynamically sized type if it does not need drop to be run");
1481+
} else {
1482+
err.note("only the last field of a struct may have a dynamically \
1483+
sized type");
1484+
}
14801485
}
14811486
AdtKind::Union => {
14821487
err.note("no field of a union may have a dynamically sized type");

src/librustc/traits/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,8 @@ pub enum ObligationCauseCode<'tcx> {
192192
/// [T,..n] --> T must be Copy
193193
RepeatVec,
194194

195-
/// Types of fields (other than the last) in a struct must be sized.
196-
FieldSized(AdtKind),
195+
/// Types of fields (other than the last, except for packed structs) in a struct must be sized.
196+
FieldSized { adt_kind: AdtKind, last: bool },
197197

198198
/// Constant expressions must be sized.
199199
ConstSized,

src/librustc/traits/structural_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
206206
super::SizedReturnType => Some(super::SizedReturnType),
207207
super::SizedYieldType => Some(super::SizedYieldType),
208208
super::RepeatVec => Some(super::RepeatVec),
209-
super::FieldSized(item) => Some(super::FieldSized(item)),
209+
super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }),
210210
super::ConstSized => Some(super::ConstSized),
211211
super::SharedStatic => Some(super::SharedStatic),
212212
super::BuiltinDerivedObligation(ref cause) => {

src/librustc_typeck/check/wfcheck.rs

+20-10
Original file line numberDiff line numberDiff line change
@@ -258,25 +258,35 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
258258
ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))
259259
}
260260
};
261-
let unsized_len = if
261+
let all_sized =
262262
all_sized ||
263263
variant.fields.is_empty() ||
264-
needs_drop_copy()
265-
{
264+
needs_drop_copy();
265+
let unsized_len = if all_sized {
266266
0
267267
} else {
268268
1
269269
};
270-
for field in &variant.fields[..variant.fields.len() - unsized_len] {
270+
for (idx, field) in variant.fields[..variant.fields.len() - unsized_len]
271+
.iter()
272+
.enumerate()
273+
{
274+
let last = idx == variant.fields.len() - 1;
271275
fcx.register_bound(
272276
field.ty,
273277
fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
274-
traits::ObligationCause::new(field.span,
275-
fcx.body_id,
276-
traits::FieldSized(match item.node.adt_kind() {
277-
Some(i) => i,
278-
None => bug!(),
279-
})));
278+
traits::ObligationCause::new(
279+
field.span,
280+
fcx.body_id,
281+
traits::FieldSized {
282+
adt_kind: match item.node.adt_kind() {
283+
Some(i) => i,
284+
None => bug!(),
285+
},
286+
last
287+
}
288+
)
289+
);
280290
}
281291

282292
// All field types must be well-formed.

src/test/ui/issues/issue-27060-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | data: T, //~ ERROR the size for values of type
77
= help: the trait `std::marker::Sized` is not implemented for `T`
88
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
99
= help: consider adding a `where T: std::marker::Sized` bound
10-
= note: only the last field of a struct may have a dynamically sized type
10+
= note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run
1111

1212
error: aborting due to previous error
1313

0 commit comments

Comments
 (0)