Skip to content

Commit

Permalink
Fix missing function declaration issue (#3862)
Browse files Browse the repository at this point in the history
In cases where a function pointer is created, but its value is never
used, Kani crashes due to missing function declaration.

For now, collect any instance that has its address taken even if its
never used.

Fixes #3799

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 and MIT licenses.
  • Loading branch information
celinval authored Jan 29, 2025
1 parent ad91bfa commit 53013f3
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
16 changes: 16 additions & 0 deletions kani-compiler/src/kani_middle/reachability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,22 @@ impl MirVisitor for MonoItemsFnCollector<'_, '_> {

self.super_terminator(terminator, location);
}

/// Collect any function definition that may occur as a type.
///
/// The codegen stage will require the definition to be available.
/// This is a conservative approach, since there are cases where the function is never
/// actually used, so we don't need the body.
///
/// Another alternative would be to lazily declare functions, but it would require a bigger
/// change to codegen.
fn visit_ty(&mut self, ty: &Ty, _: Location) {
if let TyKind::RigidTy(RigidTy::FnDef(def, args)) = ty.kind() {
let instance = Instance::resolve(def, &args).unwrap();
self.collect_instance(instance, true);
}
self.super_ty(ty);
}
}

fn extract_unsize_coercion(tcx: TyCtxt, orig_ty: Ty, dst_trait: Ty) -> (Ty, Ty) {
Expand Down
27 changes: 27 additions & 0 deletions tests/kani/CodegenMisc/missing_mut_fn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! Ensure Kani can codegen code with a pointer to a function that is never used
//! See <https://github.com/model-checking/kani/issues/3799> for more details.
fn foo<F: Fn()>(_func: &mut F) {}
fn foo_dyn(_func: &mut dyn Fn()) {}

#[kani::proof]
fn check_foo() {
fn f() {}

foo(&mut f);
}

#[kani::proof]
fn check_foo_dyn() {
fn f() {}

foo_dyn(&mut f);
}

#[kani::proof]
fn check_foo_unused() {
fn f() {}

let ptr = &mut f;
}

0 comments on commit 53013f3

Please sign in to comment.