add miri tests and a fixme
This commit is contained in:
parent
cda25e56c8
commit
6d4995f4e6
6 changed files with 112 additions and 0 deletions
|
@ -992,6 +992,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
bug!("can't tailcall as root");
|
bug!("can't tailcall as root");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// FIXME(explicit_tail_calls):
|
||||||
|
// we should check if both caller&callee can/n't unwind,
|
||||||
|
// see <https://github.com/rust-lang/rust/pull/113128#issuecomment-1614979803>
|
||||||
|
|
||||||
self.eval_fn_call(
|
self.eval_fn_call(
|
||||||
fn_val,
|
fn_val,
|
||||||
(caller_abi, caller_fn_abi),
|
(caller_abi, caller_fn_abi),
|
||||||
|
|
10
src/tools/miri/tests/fail/tail_calls/cc-mismatch.rs
Normal file
10
src/tools/miri/tests/fail/tail_calls/cc-mismatch.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
//@error-in-other-file: Undefined Behavior: calling a function with calling convention C using calling convention Rust
|
||||||
|
#![feature(explicit_tail_calls)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let f = unsafe { std::mem::transmute::<extern "C" fn(), fn()>(f) };
|
||||||
|
become f();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" fn f() {}
|
25
src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr
Normal file
25
src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
error: Undefined Behavior: calling a function with calling convention C using calling convention Rust
|
||||||
|
--> RUSTLIB/core/src/ops/function.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a function with calling convention C using calling convention Rust
|
||||||
|
|
|
||||||
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
= note: BACKTRACE:
|
||||||
|
= note: inside `<fn() as std::ops::FnOnce<()>>::call_once - shim(fn())` at RUSTLIB/core/src/ops/function.rs:LL:CC
|
||||||
|
= note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
||||||
|
= note: inside closure at RUSTLIB/std/src/rt.rs:LL:CC
|
||||||
|
= note: inside `std::ops::function::impls::<impl std::ops::FnOnce<()> for &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>::call_once` at RUSTLIB/core/src/ops/function.rs:LL:CC
|
||||||
|
= note: inside `std::panicking::r#try::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
|
= note: inside `std::panicking::r#try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
|
= note: inside `std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at RUSTLIB/std/src/panic.rs:LL:CC
|
||||||
|
= note: inside closure at RUSTLIB/std/src/rt.rs:LL:CC
|
||||||
|
= note: inside `std::panicking::r#try::do_call::<{closure@std::rt::lang_start_internal::{closure#2}}, isize>` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
|
= note: inside `std::panicking::r#try::<isize, {closure@std::rt::lang_start_internal::{closure#2}}>` at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
|
= note: inside `std::panic::catch_unwind::<{closure@std::rt::lang_start_internal::{closure#2}}, isize>` at RUSTLIB/std/src/panic.rs:LL:CC
|
||||||
|
= note: inside `std::rt::lang_start_internal` at RUSTLIB/std/src/rt.rs:LL:CC
|
||||||
|
= note: inside `std::rt::lang_start::<()>` at RUSTLIB/std/src/rt.rs:LL:CC
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#![feature(explicit_tail_calls)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// FIXME(explicit_tail_calls):
|
||||||
|
// the error should point to `become f(x)`,
|
||||||
|
// but tail calls mess up the backtrace it seems like...
|
||||||
|
f(0);
|
||||||
|
//~^ error: Undefined Behavior: calling a function with argument of type i32 passing data of type u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f(x: u32) {
|
||||||
|
let g = unsafe { std::mem::transmute::<fn(i32), fn(u32)>(g) };
|
||||||
|
become g(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g(_: i32) {}
|
|
@ -0,0 +1,17 @@
|
||||||
|
error: Undefined Behavior: calling a function with argument of type i32 passing data of type u32
|
||||||
|
--> $DIR/signature-mismatch-arg.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | f(0);
|
||||||
|
| ^^^^ calling a function with argument of type i32 passing data of type u32
|
||||||
|
|
|
||||||
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
|
||||||
|
= help: if you think this code should be accepted anyway, please report an issue
|
||||||
|
= note: BACKTRACE:
|
||||||
|
= note: inside `main` at $DIR/signature-mismatch-arg.rs:LL:CC
|
||||||
|
|
||||||
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
39
src/tools/miri/tests/pass/tail_call.rs
Normal file
39
src/tools/miri/tests/pass/tail_call.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(explicit_tail_calls)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(factorial(10), 3_628_800);
|
||||||
|
assert_eq!(mutually_recursive_identity(1000), 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn factorial(n: u32) -> u32 {
|
||||||
|
fn factorial_acc(n: u32, acc: u32) -> u32 {
|
||||||
|
match n {
|
||||||
|
0 => acc,
|
||||||
|
_ => become factorial_acc(n - 1, acc * n),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
factorial_acc(n, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is of course very silly, but we need to demonstrate mutual recursion somehow so...
|
||||||
|
fn mutually_recursive_identity(x: u32) -> u32 {
|
||||||
|
fn switch(src: u32, tgt: u32) -> u32 {
|
||||||
|
match src {
|
||||||
|
0 => tgt,
|
||||||
|
_ if src % 7 == 0 => become advance_with_extra_steps(src, tgt),
|
||||||
|
_ => become advance(src, tgt),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn advance(src: u32, tgt: u32) -> u32 {
|
||||||
|
become switch(src - 1, tgt + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn advance_with_extra_steps(src: u32, tgt: u32) -> u32 {
|
||||||
|
become advance(src, tgt)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(x, 0)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue