11#![ feature( core_intrinsics) ]
22#![ feature( global_asm) ]
33#![ feature( lang_items) ]
4+ #![ feature( llvm_asm) ]
45#![ warn( rust_2018_idioms) ]
56#![ allow( unused_attributes) ]
67#![ no_std]
@@ -14,32 +15,32 @@ use core::panic::PanicInfo;
1415/// This is the executable start function, which directly follows the entry point.
1516#[ cfg_attr( not( test) , lang = "start" ) ]
1617#[ cfg( not( test) ) ]
17- extern "C" fn start < T > ( user_main : * const ( ) , _argc : isize , _argv : * const * const u8 ) -> isize
18+ extern "C" fn start < T > ( user_main : * const ( ) , _argc : isize , _argv : * const * const u8 ) -> !
1819where
1920 T : Termination ,
2021{
2122 let user_main: fn ( ) -> T = unsafe { core:: mem:: transmute ( user_main) } ;
22- user_main ( ) . report ( ) as isize
23+ user_main ( ) ;
24+
25+ panic ! ( "main() cannot return" ) ;
2326}
2427
2528/// Termination trait required for the start function.
2629#[ cfg_attr( not( test) , lang = "termination" ) ]
27- trait Termination {
28- fn report ( self ) -> i32 ;
29- }
30+ trait Termination { }
3031
3132/// This implementation does the bare minimum to satisfy the executable start function.
32- impl Termination for ( ) {
33- fn report ( self ) -> i32 {
34- 0
35- }
36- }
33+ impl Termination for ( ) { }
3734
3835/// This function is called on panic.
3936#[ cfg_attr( not( test) , panic_handler) ]
4037#[ no_mangle]
4138fn panic ( _info : & PanicInfo < ' _ > ) -> ! {
42- core:: intrinsics:: abort ( ) ;
39+ loop {
40+ // A loop without side effects may be optimized away by LLVM. This issue can be avoided with
41+ // a volatile no-op. See: https://github.com/rust-lang/rust/issues/28728
42+ unsafe { llvm_asm ! ( "" :: :: "volatile" ) } ;
43+ }
4344}
4445
4546/// Error handler personality language item (current no-op, to satisfy clippy).
0 commit comments