Unnamed repository; edit this file 'description' to name the repository.
fix: MIR eval mixed bit and byte sizes
MIR eval was using .bit_width() and then Size::from_bytes(), leading to sizes that were out by a factor of 8. This led to crashes like "expected int of size 64, but got size 8" during const eval. I initially noticed this with u64 (a type of known size, so .bit_size() returned a non-None value) but I've fixed all the bit/byte mismatches in MIR evaluation. Also added a unit test with a minimal repro of the case I originally saw. Fixes rust-lang/rust-analyzer#22593 AI disclosure: Partially written with Codex and GPT 5.5.
Wilfred Hughes 4 weeks ago
parent 888f581 · commit f221318
-rw-r--r--crates/hir-ty/src/consteval/tests.rs13
-rw-r--r--crates/hir-ty/src/mir/eval.rs52
2 files changed, 44 insertions, 21 deletions
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index 5421b97db2..0e51594a78 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -2634,6 +2634,19 @@ fn const_generic_subst_fn() {
}
#[test]
+fn const_generic_fixed_width() {
+ check_number(
+ r#"
+ const fn m<const N: u64>() -> u64 {
+ N
+ }
+ const GOAL: u64 = m::<0>();
+ "#,
+ 0,
+ );
+}
+
+#[test]
fn layout_of_type_with_associated_type_field_defined_inside_body() {
check_number(
r#"
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index eb0e4c6020..c69febd019 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -1935,25 +1935,37 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> {
Ok(Interval::new(addr, 4))
}
TyKind::Int(int_ty) => {
- let size = int_ty.bit_width().unwrap_or(self.ptr_size() as u64);
- let value = valtree.inner().to_leaf().to_int(Size::from_bytes(size));
- let addr = self.heap_allocate(size as usize, size as usize)?;
- self.write_memory(addr, &value.to_le_bytes()[..size as usize])?;
- Ok(Interval::new(addr, size as usize))
+ let size = int_ty
+ .bit_width()
+ .map(Size::from_bits)
+ .unwrap_or_else(|| Size::from_bytes(self.ptr_size() as u64));
+ let bytes = size.bytes_usize();
+
+ let value = valtree.inner().to_leaf().to_int(size);
+ let addr = self.heap_allocate(bytes, bytes)?;
+ self.write_memory(addr, &value.to_le_bytes()[..bytes])?;
+ Ok(Interval::new(addr, bytes))
}
TyKind::Uint(uint_ty) => {
- let size = uint_ty.bit_width().unwrap_or(self.ptr_size() as u64);
- let value = valtree.inner().to_leaf().to_uint(Size::from_bytes(size));
- let addr = self.heap_allocate(size as usize, size as usize)?;
- self.write_memory(addr, &value.to_le_bytes()[..size as usize])?;
- Ok(Interval::new(addr, size as usize))
+ let size = uint_ty
+ .bit_width()
+ .map(Size::from_bits)
+ .unwrap_or_else(|| Size::from_bytes(self.ptr_size() as u64));
+ let bytes = size.bytes_usize();
+
+ let value = valtree.inner().to_leaf().to_uint(size);
+ let addr = self.heap_allocate(bytes, bytes)?;
+ self.write_memory(addr, &value.to_le_bytes()[..bytes])?;
+ Ok(Interval::new(addr, bytes))
}
TyKind::Float(float_ty) => {
- let size = float_ty.bit_width();
- let value = valtree.inner().to_leaf().to_uint(Size::from_bytes(size));
- let addr = self.heap_allocate(size as usize, size as usize)?;
- self.write_memory(addr, &value.to_le_bytes()[..size as usize])?;
- Ok(Interval::new(addr, size as usize))
+ let size = Size::from_bits(float_ty.bit_width());
+ let bytes = size.bytes_usize();
+
+ let value = valtree.inner().to_leaf().to_uint(size);
+ let addr = self.heap_allocate(bytes, bytes)?;
+ self.write_memory(addr, &value.to_le_bytes()[..bytes])?;
+ Ok(Interval::new(addr, bytes))
}
TyKind::RawPtr(..) => {
let size = self.ptr_size();
@@ -1995,15 +2007,13 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> {
_ => not_supported!("unsupported const"),
})
.collect::<Result<'_, Vec<_>>>()?;
+ let item_size = item_layout.size.bytes_usize();
let items_addr = self.heap_allocate(
- items.len() * (item_layout.size.bits() as usize),
- item_layout.align.bits_usize(),
+ items.len() * item_size,
+ item_layout.align.bytes() as usize,
)?;
for (i, item) in items.iter().enumerate() {
- self.copy_from_interval(
- items_addr.offset(i * (item_layout.size.bits() as usize)),
- *item,
- )?;
+ self.copy_from_interval(items_addr.offset(i * item_size), *item)?;
}
let ref_addr = self.heap_allocate(self.ptr_size() * 2, self.ptr_size())?;
self.write_memory(ref_addr, &items_addr.to_bytes())?;