Skip to content

Commit 06afdf8

Browse files
committed
Resize Allocations when doing field accesses into them
Otherwise the `Eq` impl of `ty::Const` is totally screwed up. We should do this properly as noted in the code, but that's another major refactoring and this PR is already big enough
1 parent fc82f3b commit 06afdf8

File tree

1 file changed

+37
-11
lines changed

1 file changed

+37
-11
lines changed

src/librustc_mir/const_eval.rs

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ use std::hash::Hash;
1717
use std::collections::hash_map::Entry;
1818

1919
use rustc::hir::{self, def_id::DefId};
20-
use rustc::mir::interpret::ConstEvalErr;
20+
use rustc::mir::interpret::{Relocations, UndefMask, ConstEvalErr};
2121
use rustc::mir;
2222
use rustc::ty::{self, Ty, TyCtxt, Instance, query::TyCtxtAt};
23-
use rustc::ty::layout::{self, Size, LayoutOf, TyLayout};
23+
use rustc::ty::layout::{Size, LayoutOf, TyLayout};
2424
use rustc::ty::subst::Subst;
2525
use rustc_data_structures::indexed_vec::IndexVec;
2626
use rustc_data_structures::fx::FxHashMap;
@@ -106,17 +106,43 @@ pub fn mplace_to_const<'tcx>(
106106
let alloc = ecx.memory.get(ptr.alloc_id)?;
107107
assert!(alloc.align.abi() >= mplace.align.abi());
108108
assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= mplace.layout.size.bytes());
109-
// FIXME: only clone the parts that interest us (starting at offset, going to offset + size)
110-
let mut alloc = alloc.clone();
111-
// we take `mplace.layout.align` instead of `mplace.align`
112-
// as this function is essentially copying the value
113-
// out of the larger allocation, so we lose all information about
114-
// potential surrounding types with different alignment.
115-
alloc.align = mplace.layout.align;
109+
// FIXME: stop cloning and refer to parts of allocations by giving `ConstValue::ByRef` fields
110+
// for alignment overrides and size of the referred to part
111+
let mut new_alloc = Allocation {
112+
bytes: alloc
113+
.bytes[ptr.offset.bytes() as usize..][..mplace.layout.size.bytes() as usize]
114+
.to_owned(),
115+
mutability: Mutability::Immutable,
116+
relocations: Relocations::from_presorted(alloc
117+
.relocations
118+
.iter()
119+
.filter_map(|&(offset, (tag, id))| if offset < ptr.offset {
120+
None
121+
} else {
122+
Some((
123+
offset - ptr.offset,
124+
(tag, id)
125+
))
126+
})
127+
.collect()),
128+
undef_mask: UndefMask::new(mplace.layout.size),
129+
// we take `mplace.layout.align` instead of `mplace.align`
130+
// as this function is essentially copying the value
131+
// out of the larger allocation, so we lose all information about
132+
// potential surrounding types with different alignment.
133+
align: mplace.layout.align,
134+
};
135+
for i in 0..mplace.layout.size.bytes() {
136+
let i = Size::from_bytes(i);
137+
let j = i + ptr.offset;
138+
new_alloc.undef_mask.set(i, alloc.undef_mask.get(j));
139+
}
140+
116141
// FIXME shouldnt it be the case that `intern_static` has already
117142
// interned this? I thought that is the entire point of that `FinishStatic` stuff?
118-
let alloc = ecx.tcx.intern_const_alloc(alloc);
119-
let val = ConstValue::ByRef(ptr.alloc_id, alloc, ptr.offset);
143+
let new_alloc = ecx.tcx.intern_const_alloc(new_alloc);
144+
let alloc_id = ecx.tcx.alloc_map.lock().allocate(new_alloc);
145+
let val = ConstValue::ByRef(alloc_id, new_alloc, Size::ZERO);
120146
Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, mplace.layout.ty))
121147
}
122148

0 commit comments

Comments
 (0)