@@ -95,7 +95,7 @@ pub struct EarlyOtherwiseBranch;
9595
9696impl < ' tcx > MirPass < ' tcx > for EarlyOtherwiseBranch {
9797 fn is_enabled ( & self , sess : & rustc_session:: Session ) -> bool {
98- sess. mir_opt_level ( ) >= 2
98+ sess. mir_opt_level ( ) >= 3 && sess . opts . debugging_opts . unsound_mir_opts
9999 }
100100
101101 fn run_pass ( & self , tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
@@ -226,6 +226,37 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
226226
227227/// Returns true if computing the discriminant of `place` may be hoisted out of the branch
228228fn may_hoist < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & Body < ' tcx > , place : Place < ' tcx > ) -> bool {
229+ // FIXME(JakobDegen): This is unsound. Someone could write code like this:
230+ // ```rust
231+ // let Q = val;
232+ // if discriminant(P) == otherwise {
233+ // let ptr = &mut Q as *mut _ as *mut u8;
234+ // unsafe { *ptr = 10; } // Any invalid value for the type
235+ // }
236+ //
237+ // match P {
238+ // A => match Q {
239+ // A => {
240+ // // code
241+ // }
242+ // _ => {
243+ // // don't use Q
244+ // }
245+ // }
246+ // _ => {
247+ // // don't use Q
248+ // }
249+ // };
250+ // ```
251+ //
252+ // Hoisting the `discriminant(Q)` out of the `A` arm causes us to compute the discriminant of an
253+ // invalid value, which is UB.
254+ //
255+ // In order to fix this, we would either need to show that the discriminant computation of
256+ // `place` is computed in all branches, including the `otherwise` branch, or we would need
257+ // another analysis pass to determine that the place is fully initialized. It might even be best
258+ // to have the hoisting be performed in a different pass and just do the CFG changing in this
259+ // pass.
229260 for ( place, proj) in place. iter_projections ( ) {
230261 match proj {
231262 // Dereferencing in the computation of `place` might cause issues from one of two
0 commit comments