Skip to content

fix error for unsized packed struct field #53342

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1472,11 +1472,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ObligationCauseCode::StructInitializerSized => {
err.note("structs must have a statically known size to be initialized");
}
ObligationCauseCode::FieldSized(ref item) => {
ObligationCauseCode::FieldSized { adt_kind: ref item, last } => {
match *item {
AdtKind::Struct => {
err.note("only the last field of a struct may have a dynamically \
sized type");
if last {
err.note("the last field of a packed struct may only have a \
dynamically sized type if it does not need drop to be run");
} else {
err.note("only the last field of a struct may have a dynamically \
sized type");
}
}
AdtKind::Union => {
err.note("no field of a union may have a dynamically sized type");
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ pub enum ObligationCauseCode<'tcx> {
/// [T,..n] --> T must be Copy
RepeatVec,

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

/// Constant expressions must be sized.
ConstSized,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
super::SizedReturnType => Some(super::SizedReturnType),
super::SizedYieldType => Some(super::SizedYieldType),
super::RepeatVec => Some(super::RepeatVec),
super::FieldSized(item) => Some(super::FieldSized(item)),
super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }),
super::ConstSized => Some(super::ConstSized),
super::SharedStatic => Some(super::SharedStatic),
super::BuiltinDerivedObligation(ref cause) => {
Expand Down
30 changes: 20 additions & 10 deletions src/librustc_typeck/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,25 +258,35 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))
}
};
let unsized_len = if
let all_sized =
all_sized ||
variant.fields.is_empty() ||
needs_drop_copy()
{
needs_drop_copy();
let unsized_len = if all_sized {
0
} else {
1
};
for field in &variant.fields[..variant.fields.len() - unsized_len] {
for (idx, field) in variant.fields[..variant.fields.len() - unsized_len]
.iter()
.enumerate()
{
let last = idx == variant.fields.len() - 1;
fcx.register_bound(
field.ty,
fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
traits::ObligationCause::new(field.span,
fcx.body_id,
traits::FieldSized(match item.node.adt_kind() {
Some(i) => i,
None => bug!(),
})));
traits::ObligationCause::new(
field.span,
fcx.body_id,
traits::FieldSized {
adt_kind: match item.node.adt_kind() {
Some(i) => i,
None => bug!(),
},
last
}
)
);
}

// All field types must be well-formed.
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-27060-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ LL | data: T, //~ ERROR the size for values of type
= help: the trait `std::marker::Sized` is not implemented for `T`
= 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>
= help: consider adding a `where T: std::marker::Sized` bound
= note: only the last field of a struct may have a dynamically sized type
= note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run

error: aborting due to previous error

Expand Down