Skip to content

Commit 9d31d52

Browse files
author
Carolyn Zech
authored
ty_mangled_name: only use non-mangled name if -Zcffi is enabled. (#4114)
See #4007 (comment). Ideally, we'd have a better solution for C structs more generally, but this solution is enough to fix this particular crash. Before this fix, the new diamond dependency test harness crashed with: ``` ------------------------------------------ stderr: ------------------------------------------ Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s Compiling main v0.1.0 (/Users/cmzech/kani/tests/cargo-kani/dependency-test/diamond-dependency/main) thread 'rustc' panicked at cprover_bindings/src/goto_program/expr.rs:887:9: Error in struct_expr; value type does not match field type. StructTag("tag-dependency3::ReprCStruct") [Field { name: "field", typ: StructTag("tag-_14480980443891294070469871430240215039") }] [Expr { value: Symbol { identifier: "_RNvCslFpuY9hqlfk_11dependency113create_struct::1::var_1" }, typ: StructTag("tag-_12679625102465156734981384663764492039"), location: None, size_of_annotation: None }] note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace Kani unexpectedly panicked during compilation. Please file an issue here: https://github.com/model-checking/kani/issues/new?labels=bug&template=bug_report.md [Kani] current codegen item: codegen_function: dependency1::create_struct _RNvCslFpuY9hqlfk_11dependency113create_struct [Kani] current codegen location: Loc { file: "/Users/cmzech/kani/tests/cargo-kani/dependency-test/diamond-dependency/dependency1/src/lib.rs", function: None, start_line: 15, start_col: Some(1), end_line: 15, end_col: Some(51), pragmas: [] } error: could not compile `main` (lib) ``` Resolves #4007 By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
1 parent 7694517 commit 9d31d52

File tree

6 files changed

+52
-4
lines changed
  • kani-compiler/src/codegen_cprover_gotoc/codegen
  • tests/cargo-kani/dependency-test

6 files changed

+52
-4
lines changed

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::codegen_cprover_gotoc::GotocCtx;
44
use cbmc::goto_program::{DatatypeComponent, Expr, Location, Parameter, Symbol, SymbolTable, Type};
55
use cbmc::utils::aggr_tag;
66
use cbmc::{InternString, InternedString};
7+
use kani_metadata::UnstableFeature;
78
use rustc_abi::{
89
BackendRepr::SimdVector, FieldIdx, FieldsShape, Float, Integer, LayoutData, Primitive, Size,
910
TagEncoding, TyAndLayout, VariantIdx, Variants,
@@ -487,9 +488,20 @@ impl<'tcx> GotocCtx<'tcx> {
487488
// This is not a restriction because C can only access non-generic types anyway.
488489
// TODO: Skipping name mangling is likely insufficient if a dependent crate has two versions of
489490
// linked C libraries
490-
// https://github.com/model-checking/kani/issues/450
491+
// https://github.com/model-checking/kani/issues/450.
492+
// Note that #[repr(C)] types are unmangled only if the unstable c-ffi feature is enabled; otherwise,
493+
// we assume that this struct is a #[repr(C)] in Rust code and mangle it,
494+
// c.f. https://github.com/model-checking/kani/issues/4007.
491495
match t.kind() {
492-
TyKind::Adt(def, args) if args.is_empty() && def.repr().c() => {
496+
TyKind::Adt(def, args)
497+
if args.is_empty()
498+
&& def.repr().c()
499+
&& self
500+
.queries
501+
.args()
502+
.unstable_features
503+
.contains(&UnstableFeature::CFfi.to_string()) =>
504+
{
493505
// For non-generic #[repr(C)] types, use the literal path instead of mangling it.
494506
self.tcx.def_path_str(def.did()).intern()
495507
}

tests/cargo-kani/dependency-test/dependency3/src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,18 @@ pub struct Foo {
55
x: i32,
66
}
77

8+
pub enum Field {
9+
Case1,
10+
Case2,
11+
}
12+
13+
#[repr(C)]
14+
pub struct ReprCStruct {
15+
pub field: Field,
16+
}
17+
818
// Export a function that takes a struct type which differs between this crate
9-
// and the other vesion
19+
// and the other version
1020
pub fn take_foo(foo: &Foo) -> i32 {
1121
foo.x
1222
}

tests/cargo-kani/dependency-test/diamond-dependency/dependency1/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ pub fn delegate_use_struct() -> i32 {
1111
let foo = dependency3::give_foo();
1212
dependency3::take_foo(&foo)
1313
}
14+
15+
pub fn create_struct() -> dependency3::ReprCStruct {
16+
dependency3::ReprCStruct { field: dependency3::Field::Case1 }
17+
}

tests/cargo-kani/dependency-test/diamond-dependency/dependency2/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ pub fn delegate_use_struct() -> i32 {
1111
let foo = dependency3::give_foo();
1212
dependency3::take_foo(&foo)
1313
}
14+
15+
pub fn create_struct() -> dependency3::ReprCStruct {
16+
dependency3::ReprCStruct { field: dependency3::Field::Case1 }
17+
}

tests/cargo-kani/dependency-test/diamond-dependency/dependency3/src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,18 @@ pub struct Foo {
77
y: i32,
88
}
99

10+
pub enum Field {
11+
Case1,
12+
Case2,
13+
}
14+
15+
#[repr(C)]
16+
pub struct ReprCStruct {
17+
pub field: Field,
18+
}
19+
1020
// Export a function that takes a struct type which differs between this crate
11-
// and the other vesion.
21+
// and the other version.
1222
pub fn take_foo(foo: &Foo) -> i32 {
1323
foo.x + foo.y
1424
}

tests/cargo-kani/dependency-test/diamond-dependency/main/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,11 @@ fn harness() {
1212
assert!(dependency1::delegate_use_struct() == 3);
1313
assert!(dependency2::delegate_use_struct() == 1);
1414
}
15+
16+
// Test that Kani can codegen repr(C) structs from two different versions of the same crate,
17+
// c.f. https://github.com/model-checking/kani/issues/4007
18+
#[kani::proof]
19+
fn reprc_harness() {
20+
dependency1::create_struct();
21+
dependency2::create_struct();
22+
}

0 commit comments

Comments
 (0)