Skip to content

Commit 93f53e5

Browse files
committed
size_and_align_of can return no result for extern types
1 parent f79a22c commit 93f53e5

File tree

3 files changed

+26
-23
lines changed

3 files changed

+26
-23
lines changed

src/librustc_mir/interpret/eval_context.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -332,22 +332,16 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
332332
}
333333

334334
/// Return the actual dynamic size and alignment of the place at the given type.
335-
/// Only the `meta` part of the place matters.
335+
/// Only the "meta" (metadata) part of the place matters.
336+
/// This can fail to provide an answer for extern types.
336337
pub(super) fn size_and_align_of(
337338
&self,
338339
metadata: Option<Scalar<M::PointerTag>>,
339340
layout: TyLayout<'tcx>,
340-
) -> EvalResult<'tcx, (Size, Align)> {
341-
let metadata = match metadata {
342-
None => {
343-
assert!(!layout.is_unsized());
344-
return Ok(layout.size_and_align())
345-
}
346-
Some(metadata) => {
347-
assert!(layout.is_unsized());
348-
metadata
349-
}
350-
};
341+
) -> EvalResult<'tcx, Option<(Size, Align)>> {
342+
if !layout.is_unsized() {
343+
return Ok(Some(layout.size_and_align()));
344+
}
351345
match layout.ty.sty {
352346
ty::Adt(..) | ty::Tuple(..) => {
353347
// First get the size of all statically known fields.
@@ -367,9 +361,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
367361
);
368362

369363
// Recurse to get the size of the dynamically sized field (must be
370-
// the last field).
364+
// the last field). Can't have foreign types here, how would we
365+
// adjust alignment and size for them?
371366
let field = layout.field(self, layout.fields.count() - 1)?;
372-
let (unsized_size, unsized_align) = self.size_and_align_of(Some(metadata), field)?;
367+
let (unsized_size, unsized_align) = self.size_and_align_of(metadata, field)?
368+
.expect("Fields cannot be extern types");
373369

374370
// FIXME (#26403, #27023): We should be adding padding
375371
// to `sized_size` (to accommodate the `unsized_align`
@@ -396,18 +392,22 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
396392
//
397393
// `(size + (align-1)) & -align`
398394

399-
Ok((size.abi_align(align), align))
395+
Ok(Some((size.abi_align(align), align)))
400396
}
401397
ty::Dynamic(..) => {
402-
let vtable = metadata.to_ptr()?;
398+
let vtable = metadata.expect("dyn trait fat ptr must have vtable").to_ptr()?;
403399
// the second entry in the vtable is the dynamic size of the object.
404-
self.read_size_and_align_from_vtable(vtable)
400+
Ok(Some(self.read_size_and_align_from_vtable(vtable)?))
405401
}
406402

407403
ty::Slice(_) | ty::Str => {
408-
let len = metadata.to_usize(self)?;
404+
let len = metadata.expect("slice fat ptr must have vtable").to_usize(self)?;
409405
let (elem_size, align) = layout.field(self, 0)?.size_and_align();
410-
Ok((elem_size * len, align))
406+
Ok(Some((elem_size * len, align)))
407+
}
408+
409+
ty::Foreign(_) => {
410+
Ok(None)
411411
}
412412

413413
_ => bug!("size_and_align_of::<{:?}> not supported", layout.ty),
@@ -417,7 +417,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
417417
pub fn size_and_align_of_mplace(
418418
&self,
419419
mplace: MPlaceTy<'tcx, M::PointerTag>
420-
) -> EvalResult<'tcx, (Size, Align)> {
420+
) -> EvalResult<'tcx, Option<(Size, Align)>> {
421421
self.size_and_align_of(mplace.meta, mplace.layout)
422422
}
423423

src/librustc_mir/interpret/place.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,9 @@ where
319319
// Offset may need adjustment for unsized fields
320320
let (meta, offset) = if field_layout.is_unsized() {
321321
// re-use parent metadata to determine dynamic field layout
322-
let (_, align) = self.size_and_align_of(base.meta, field_layout)?;
322+
let (_, align) = self.size_and_align_of(base.meta, field_layout)?
323+
.expect("Fields cannot be extern types");
323324
(base.meta, offset.abi_align(align))
324-
325325
} else {
326326
// base.meta could be present; we might be accessing a sized field of an unsized
327327
// struct.

src/librustc_mir/interpret/validity.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
208208
// for safe ptrs, also check the ptr values itself
209209
if !ty.is_unsafe_ptr() {
210210
// Make sure this is non-NULL and aligned
211-
let (size, align) = self.size_and_align_of(place.meta, place.layout)?;
211+
let (size, align) = self.size_and_align_of(place.meta, place.layout)?
212+
// for the purpose of validity, consider foreign types to have
213+
// alignment 1 and size 0.
214+
.unwrap_or_else(|| (Size::ZERO, Align::from_bytes(1, 1).unwrap()));
212215
match self.memory.check_align(place.ptr, align) {
213216
Ok(_) => {},
214217
Err(err) => match err.kind {

0 commit comments

Comments
 (0)