Skip to content

Commit 36db3de

Browse files
celinvaltedinski
authored andcommitted
Fix issue with value_of / align_of traits (rust-lang#1089)
We were trying to figure out the values of those properties during runtime, which is not possible. Fix the code to look for the information in the vtable instead.
1 parent 625298b commit 36db3de

File tree

5 files changed

+73
-17
lines changed

5 files changed

+73
-17
lines changed

kani-compiler/src/codegen_cprover_gotoc/codegen/intrinsic.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,10 @@ impl<'tcx> GotocCtx<'tcx> {
8484
let intrinsic = self.symbol_name(instance);
8585
let intrinsic = intrinsic.as_str();
8686
let loc = self.codegen_span_option(span);
87-
debug!(
88-
"codegen_intrinsic:\n\tinstance {:?}\n\tfargs {:?}\n\tp {:?}\n\tspan {:?}",
89-
instance, fargs, p, span
90-
);
87+
debug!(?instance, "codegen_intrinsic");
88+
debug!(?fargs, "codegen_intrinsic");
89+
debug!(?p, "codegen_intrinsic");
90+
debug!(?span, "codegen_intrinsic");
9191
let sig = instance.ty(self.tcx, ty::ParamEnv::reveal_all()).fn_sig(self.tcx);
9292
let sig = self.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
9393
let ret_ty = self.monomorphize(sig.output());
@@ -972,15 +972,12 @@ impl<'tcx> GotocCtx<'tcx> {
972972
}
973973
match t.kind() {
974974
ty::Dynamic(..) => {
975-
//TODO figure out if this needs to be done, or if the result we want here is for the fat pointer.
976-
//We need to get the actual value from the vtable like in codegen_ssa/glue.rs
977-
// let vs = self.layout_of(self.tcx.vtable_methods(binder.principal().unwrap().with_self_ty(self.tcx, t)));
978-
// https://rust-lang.github.io/unsafe-code-guidelines/layout/pointers.html
979-
// The size of &dyn Trait is two words.
980-
let size = Expr::int_constant((layout.size.bytes_usize()) * 2, Type::size_t());
981-
// The alignment of &dyn Trait is the word size.
982-
let align = Expr::int_constant(layout.align.abi.bytes(), usizet);
983-
SizeAlign { size, align }
975+
// For traits, we need to retrieve the size and alignment from the vtable.
976+
let vtable = arg.member("vtable", &self.symbol_table).dereference();
977+
SizeAlign {
978+
size: vtable.clone().member("size", &self.symbol_table),
979+
align: vtable.member("align", &self.symbol_table),
980+
}
984981
}
985982
ty::Slice(_) | ty::Str => {
986983
let unit_t = match t.kind() {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
//! This test case checks the behavior of align_of_val for traits.
5+
#![allow(dead_code)]
6+
7+
use std::mem::align_of_val;
8+
9+
trait T {}
10+
11+
struct A {
12+
id: u128,
13+
}
14+
15+
impl T for A {}
16+
17+
#[cfg_attr(kani, kani::proof)]
18+
fn check_align_simple() {
19+
let a = A { id: 0 };
20+
let t: &dyn T = &a;
21+
assert_eq!(align_of_val(t), 8);
22+
assert_eq!(align_of_val(&t), 8);
23+
}
24+
25+
trait Wrapper<T: ?Sized> {
26+
fn inner(&self) -> &T;
27+
}
28+
29+
struct Concrete<T: ?Sized> {
30+
id: i16,
31+
inner: T,
32+
}
33+
34+
impl<T: ?Sized> Wrapper<T> for Concrete<T> {
35+
fn inner(&self) -> &T {
36+
&self.inner
37+
}
38+
}
39+
40+
#[cfg_attr(kani, kani::proof)]
41+
fn check_align_inner() {
42+
let val = 10u8;
43+
let conc_wrapper: Concrete<u8> = Concrete { id: 0, inner: val };
44+
let trait_wrapper = &conc_wrapper as &dyn Wrapper<u8>;
45+
46+
assert_eq!(align_of_val(conc_wrapper.inner()), 1); // This is the alignment of val.
47+
assert_eq!(align_of_val(&conc_wrapper), 2); // This is the alignment of Concrete.
48+
assert_eq!(align_of_val(trait_wrapper), 2); // This is also the alignment of Concrete.
49+
assert_eq!(align_of_val(&trait_wrapper), 8); // This is the alignment of the fat pointer.
50+
}
51+
52+
// This can be run with rustc for comparison.
53+
fn main() {
54+
check_align_simple();
55+
check_align_inner();
56+
}

tests/kani/Intrinsics/SizeOfVal/fixme_size_of_fat_ptr.rs renamed to tests/kani/Intrinsics/SizeOfVal/size_of_fat_ptr.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
3-
// kani-flags: --default-unwind 3
43

54
//! This test case checks the behavior of size_of_val for traits.
5+
#![allow(dead_code)]
6+
67
use std::mem::size_of_val;
78

89
trait T {}
910

10-
struct A {}
11+
struct A {
12+
id: u128,
13+
}
1114

1215
impl T for A {}
1316

1417
#[cfg_attr(kani, kani::proof)]
1518
fn check_size_simple() {
16-
let a = A {};
19+
let a = A { id: 0 };
1720
let t: &dyn T = &a;
18-
assert_eq!(size_of_val(t), 0);
21+
assert_eq!(size_of_val(t), 16);
1922
assert_eq!(size_of_val(&t), 16);
2023
}
2124

0 commit comments

Comments
 (0)