about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2018-08-16 00:41:26 +0200
committerRalf Jung <post@ralfj.de>2018-08-22 09:06:28 +0200
commite314a4e75f18a77392ae3d316b777c1523908acf (patch)
treee43803e55ee6dd1066e2acfe7cdc8b67daf96085
parent1e137a796685c149903fcaa52444ab0d6a949b00 (diff)
downloadrust-e314a4e75f18a77392ae3d316b777c1523908acf.tar.gz
rust-e314a4e75f18a77392ae3d316b777c1523908acf.zip
fix accessing unsized fields
-rw-r--r--src/librustc_mir/interpret/place.rs29
1 files changed, 15 insertions, 14 deletions
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index b53aa4e2e65..e8321adb4fa 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -283,31 +283,32 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
         };
         // the only way conversion can fail if is this is an array (otherwise we already panicked
         // above). In that case, all fields are equal.
-        let field = base.layout.field(self, usize::try_from(field).unwrap_or(0))?;
+        let field_layout = base.layout.field(self, usize::try_from(field).unwrap_or(0))?;
 
         // Adjust offset
-        let offset = if field.is_unsized() {
-            let vtable = match base.extra {
-                PlaceExtra::Vtable(tab) => tab,
-                _ => bug!("Unsized place with unsized field must come with vtable"),
-            };
-            let (_, align) = self.read_size_and_align_from_vtable(vtable)?;
-            offset.abi_align(align)
-        } else {
-            // No adjustment needed
-            offset
+        let offset = match base.extra {
+            PlaceExtra::Vtable(vtable) => {
+                let (_, align) = self.read_size_and_align_from_vtable(vtable)?;
+                // FIXME: Is this right? Should we always do this, or only when actually
+                // accessing the field to which the vtable applies?
+                offset.abi_align(align)
+            }
+            _ => {
+                // No adjustment needed
+                offset
+            }
         };
 
         let ptr = base.ptr.ptr_offset(offset, self)?;
-        let align = base.align.min(field.align);
-        let extra = if !field.is_unsized() {
+        let align = base.align.min(field_layout.align);
+        let extra = if !field_layout.is_unsized() {
             PlaceExtra::None
         } else {
             assert!(base.extra != PlaceExtra::None, "Expected fat ptr");
             base.extra
         };
 
-        Ok(MPlaceTy { mplace: MemPlace { ptr, align, extra }, layout: field })
+        Ok(MPlaceTy { mplace: MemPlace { ptr, align, extra }, layout: field_layout })
     }
 
     pub fn mplace_subslice(