1 // Variant of diverging-falllback-control-flow that tests
2 // the specific case of a free function with an unconstrained
3 // return type. This captures the pattern we saw in the wild
4 // in the objc crate, where changing the fallback from `!` to `()`
5 // resulted in unsoundness.
9 // revisions: nofallback fallback
11 #![cfg_attr(fallback, feature(never_type, never_type_fallback))]
17 impl UnitReturn for i32 {}
18 impl UnitReturn for () {}
20 fn unconstrained_return<T: UnitReturn>() -> T {
22 let make_unit_fn: fn() = make_unit;
23 let ffi: fn() -> T = std::mem::transmute(make_unit_fn);
29 // In Ye Olde Days, the `T` parameter of `unconstrained_return`
30 // winds up "entangled" with the `!` type that results from
31 // `panic!`, and hence falls back to `()`. This is kind of unfortunate
32 // and unexpected. When we introduced the `!` type, the original
33 // idea was to change that fallback to `!`, but that would have resulted
34 // in this code no longer compiling (or worse, in some cases it injected
36 let _ = if true { unconstrained_return() } else { panic!() };