]> git.proxmox.com Git - rustc.git/blob - src/test/ui/never_type/diverging-fallback-unconstrained-return.rs
New upstream version 1.57.0+dfsg1
[rustc.git] / src / test / ui / never_type / diverging-fallback-unconstrained-return.rs
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.
6 //
7 // check-pass
8
9 // revisions: nofallback fallback
10
11 #![cfg_attr(fallback, feature(never_type, never_type_fallback))]
12
13
14 fn make_unit() {}
15
16 trait UnitReturn {}
17 impl UnitReturn for i32 {}
18 impl UnitReturn for () {}
19
20 fn unconstrained_return<T: UnitReturn>() -> T {
21 unsafe {
22 let make_unit_fn: fn() = make_unit;
23 let ffi: fn() -> T = std::mem::transmute(make_unit_fn);
24 ffi()
25 }
26 }
27
28 fn main() {
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
35 // unsound results).
36 let _ = if true { unconstrained_return() } else { panic!() };
37 }