8cc9a912d7
Similar to methods on a trait object, the most common way to indirectly call a closure or coroutine is through the vtable on the appropriate trait. This uses the same approach as we use for trait methods, after backing out the trait arguments from the type.
34 lines
991 B
Rust
34 lines
991 B
Rust
// Check various forms of dynamic closure calls
|
|
|
|
//@ edition: 2021
|
|
//@ revisions: cfi kcfi
|
|
// FIXME(#122848) Remove only-linux once OSX CFI binaries work
|
|
//@ only-linux
|
|
//@ [cfi] needs-sanitizer-cfi
|
|
//@ [kcfi] needs-sanitizer-kcfi
|
|
//@ compile-flags: -C target-feature=-crt-static
|
|
//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
|
|
//@ [cfi] compile-flags: -Z sanitizer=cfi
|
|
//@ [kcfi] compile-flags: -Z sanitizer=kcfi
|
|
//@ [kcfi] compile-flags: -C panic=abort -Z panic-abort-tests -C prefer-dynamic=off
|
|
//@ run-pass
|
|
|
|
#![feature(async_closure)]
|
|
#![feature(async_fn_traits)]
|
|
|
|
use std::ops::AsyncFn;
|
|
|
|
#[inline(never)]
|
|
fn identity<T>(x: T) -> T { x }
|
|
|
|
// We can't actually create a `dyn AsyncFn()`, because it's not object-safe, but we should check
|
|
// that we don't bug out when we encounter one.
|
|
|
|
fn main() {
|
|
let f = identity(async || ());
|
|
let _ = f.async_call(());
|
|
let _ = f();
|
|
let g: Box<dyn FnOnce() -> _> = Box::new(f) as _;
|
|
let _ = g();
|
|
}
|