33## Step 1: Invocation of the ` panic! ` macro.
44
55There are actually two panic macros - one defined in ` core ` , and one defined in ` std ` .
6- This is due to the fact that code in ` core ` can panic. ` core ` is built before ` std ` ,
7- but we want panics to use the same machinery at runtime, whether they originate in ` core `
8- or ` std ` .
6+ This is due to the fact that code in ` core ` can panic.
7+ ` core ` is built before ` std ` ,
8+ but we want panics to use the same machinery at runtime, whether they originate in ` core ` or ` std ` .
99
1010### core definition of panic!
1111
@@ -30,8 +30,8 @@ unsafe { panic_impl(&pi) }
3030Actually resolving this goes through several layers of indirection:
3131
32321 . In [ ` compiler/rustc_hir/src/weak_lang_items.rs ` ] , ` panic_impl ` is
33- declared as 'weak lang item', with the symbol ` rust_begin_unwind ` . This is
34- used in ` rustc_hir_analysis/src/collect.rs ` to set the actual symbol name to
33+ declared as 'weak lang item', with the symbol ` rust_begin_unwind ` .
34+ This is used in ` rustc_hir_analysis/src/collect.rs ` to set the actual symbol name to
3535 ` rust_begin_unwind ` .
3636
3737 Note that ` panic_impl ` is declared in an ` extern "Rust" ` block,
@@ -52,26 +52,33 @@ pub fn panic_handler(info: &core::panic::PanicInfo<'_>) -> ! {
5252The special ` panic_handler ` attribute is resolved via [ ` compiler/rustc_passes/src/lang_items.rs ` ] .
5353The [ ` extract_ast ` ] function converts the ` panic_handler ` attribute to a ` panic_impl ` lang item.
5454
55- Now, we have a matching ` panic_handler ` lang item in the ` std ` . This function goes
55+ Now, we have a matching ` panic_handler ` lang item in the ` std ` .
56+ This function goes
5657through the same process as the ` extern { fn panic_impl } ` definition in ` core ` , ending
57- up with a symbol name of ` rust_begin_unwind ` . At link time, the symbol reference in ` core `
58+ up with a symbol name of ` rust_begin_unwind ` .
59+ At link time, the symbol reference in ` core `
5860will be resolved to the definition of ` std ` (the function called ` panic_handler ` in the
5961Rust source).
6062
61- Thus, control flow will pass from core to std at runtime. This allows panics from ` core `
63+ Thus, control flow will pass from core to std at runtime.
64+ This allows panics from ` core `
6265to go through the same infrastructure that other panics use (panic hooks, unwinding, etc)
6366
6467### std implementation of panic!
6568
66- This is where the actual panic-related logic begins. In [ ` library/std/src/panicking.rs ` ] ,
67- control passes to ` panic_with_hook ` . This method is responsible
68- for invoking the global panic hook, and checking for double panics. Finally,
69+ This is where the actual panic-related logic begins.
70+ In [ ` library/std/src/panicking.rs ` ] ,
71+ control passes to ` panic_with_hook ` .
72+ This method is responsible for invoking the global panic hook, and checking for double panics.
73+ Finally,
6974we call ` __rust_start_panic ` , which is provided by the panic runtime.
7075
7176The call to ` __rust_start_panic ` is very weird - it is passed a ` *mut &mut dyn PanicPayload ` ,
72- converted to an ` usize ` . Let's break this type down:
77+ converted to an ` usize ` .
78+ Let's break this type down:
7379
74- 1 . ` PanicPayload ` is an internal trait. It is implemented for ` PanicPayload `
80+ 1 . ` PanicPayload ` is an internal trait.
81+ It is implemented for ` PanicPayload `
7582(a wrapper around the user-supplied payload type), and has a method
7683` fn take_box(&mut self) -> *mut (dyn Any + Send) ` .
7784This method takes the user-provided payload (` T: Any + Send ` ),
@@ -81,16 +88,18 @@ boxes it, and converts the box to a raw pointer.
8188However, this is a fat pointer (twice the size of a ` usize ` ).
8289To pass this to the panic runtime across an FFI boundary, we take a mutable
8390reference * to this mutable reference* (` &mut &mut dyn PanicPayload ` ), and convert it to a raw
84- pointer (` *mut &mut dyn PanicPayload ` ). The outer raw pointer is a thin pointer, since it points to
85- a ` Sized ` type (a mutable reference). Therefore, we can convert this thin pointer into a ` usize ` ,
91+ pointer (` *mut &mut dyn PanicPayload ` ).
92+ The outer raw pointer is a thin pointer, since it points to a ` Sized ` type (a mutable reference).
93+ Therefore, we can convert this thin pointer into a ` usize ` ,
8694which is suitable for passing across an FFI boundary.
8795
88- Finally, we call ` __rust_start_panic ` with this ` usize ` . We have now entered the panic runtime.
96+ Finally, we call ` __rust_start_panic ` with this ` usize ` .
97+ We have now entered the panic runtime.
8998
9099## Step 2: The panic runtime
91100
92- Rust provides two panic runtimes: ` panic_abort ` and ` panic_unwind ` . The user chooses
93- between them at build time via their ` Cargo.toml `
101+ Rust provides two panic runtimes: ` panic_abort ` and ` panic_unwind ` .
102+ The user chooses between them at build time via their ` Cargo.toml `
94103
95104` panic_abort ` is extremely simple: its implementation of ` __rust_start_panic ` just aborts,
96105as you would expect.
@@ -99,13 +108,14 @@ as you would expect.
99108
100109In its implementation of ` __rust_start_panic ` , we take the ` usize ` , convert
101110it back to a ` *mut &mut dyn PanicPayload ` , dereference it, and call ` take_box `
102- on the ` &mut dyn PanicPayload ` . At this point, we have a raw pointer to the payload
111+ on the ` &mut dyn PanicPayload ` .
112+ At this point, we have a raw pointer to the payload
103113itself (a ` *mut (dyn Send + Any) ` ): that is, a raw pointer to the actual value
104114provided by the user who called ` panic! ` .
105115
106- At this point, the platform-independent code ends. We now call into
107- platform-specific unwinding logic (e.g ` unwind ` ). This code is
108- responsible for unwinding the stack, running any 'landing pads' associated
116+ At this point, the platform-independent code ends.
117+ We now call into platform-specific unwinding logic (e.g ` unwind ` ).
118+ This code is responsible for unwinding the stack, running any 'landing pads' associated
109119with each frame (currently, running destructors), and transferring control
110120to the ` catch_unwind ` frame.
111121
0 commit comments