11use rustc_middle:: mir:: visit:: Visitor ;
22use rustc_middle:: mir:: { self , BasicBlock , Location } ;
3- use rustc_middle:: ty:: { Ty , TyCtxt } ;
4- use rustc_span:: Span ;
3+ use rustc_middle:: ty:: TyCtxt ;
54use rustc_span:: symbol:: sym;
65use tracing:: trace;
76
87use super :: ConstCx ;
98use super :: check:: Qualifs ;
10- use super :: ops:: { self , NonConstOp } ;
9+ use super :: ops:: { self } ;
1110use super :: qualifs:: { NeedsNonConstDrop , Qualif } ;
11+ use crate :: check_consts:: check:: Checker ;
12+ use crate :: check_consts:: qualifs:: NeedsDrop ;
1213use crate :: check_consts:: rustc_allow_const_fn_unstable;
1314
1415/// Returns `true` if we should use the more precise live drop checker that runs after drop
@@ -66,12 +67,6 @@ impl<'mir, 'tcx> std::ops::Deref for CheckLiveDrops<'mir, 'tcx> {
6667 }
6768}
6869
69- impl < ' tcx > CheckLiveDrops < ' _ , ' tcx > {
70- fn check_live_drop ( & self , span : Span , dropped_ty : Ty < ' tcx > ) {
71- ops:: LiveDrop { dropped_at : None , dropped_ty } . build_error ( self . ccx , span) . emit ( ) ;
72- }
73- }
74-
7570impl < ' tcx > Visitor < ' tcx > for CheckLiveDrops < ' _ , ' tcx > {
7671 fn visit_basic_block_data ( & mut self , bb : BasicBlock , block : & mir:: BasicBlockData < ' tcx > ) {
7772 trace ! ( "visit_basic_block_data: bb={:?} is_cleanup={:?}" , bb, block. is_cleanup) ;
@@ -89,28 +84,39 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
8984
9085 match & terminator. kind {
9186 mir:: TerminatorKind :: Drop { place : dropped_place, .. } => {
92- let dropped_ty = dropped_place. ty ( self . body , self . tcx ) . ty ;
93-
94- if !NeedsNonConstDrop :: in_any_value_of_ty ( self . ccx , dropped_ty) {
95- // Instead of throwing a bug, we just return here. This is because we have to
96- // run custom `const Drop` impls.
87+ let ty_of_dropped_place = dropped_place. ty ( self . body , self . tcx ) . ty ;
88+
89+ let needs_drop = if let Some ( local) = dropped_place. as_local ( ) {
90+ self . qualifs . needs_drop ( self . ccx , local, location)
91+ } else {
92+ NeedsDrop :: in_any_value_of_ty ( self . ccx , ty_of_dropped_place)
93+ } ;
94+ // If this type doesn't need a drop at all, then there's nothing to enforce.
95+ if !needs_drop {
9796 return ;
9897 }
9998
100- if dropped_place. is_indirect ( ) {
101- self . check_live_drop ( terminator. source_info . span , dropped_ty) ;
102- return ;
103- }
104-
105- // Drop elaboration is not precise enough to accept code like
106- // `tests/ui/consts/control-flow/drop-pass.rs`; e.g., when an `Option<Vec<T>>` is
107- // initialized with `None` and never changed, it still emits drop glue.
108- // Hence we additionally check the qualifs here to allow more code to pass.
109- if self . qualifs . needs_non_const_drop ( self . ccx , dropped_place. local , location) {
110- // Use the span where the dropped local was declared for the error.
111- let span = self . body . local_decls [ dropped_place. local ] . source_info . span ;
112- self . check_live_drop ( span, dropped_ty) ;
113- }
99+ let mut err_span = terminator. source_info . span ;
100+
101+ let needs_non_const_drop = if let Some ( local) = dropped_place. as_local ( ) {
102+ // Use the span where the local was declared as the span of the drop error.
103+ err_span = self . body . local_decls [ local] . source_info . span ;
104+ self . qualifs . needs_non_const_drop ( self . ccx , local, location)
105+ } else {
106+ NeedsNonConstDrop :: in_any_value_of_ty ( self . ccx , ty_of_dropped_place)
107+ } ;
108+
109+ // I know it's not great to be creating a new const checker, but I'd
110+ // rather use it so we can deduplicate the error emitting logic that
111+ // it contains.
112+ Checker :: new ( self . ccx ) . check_op_spanned_post (
113+ ops:: LiveDrop {
114+ dropped_at : Some ( terminator. source_info . span ) ,
115+ dropped_ty : ty_of_dropped_place,
116+ needs_non_const_drop,
117+ } ,
118+ err_span,
119+ ) ;
114120 }
115121
116122 mir:: TerminatorKind :: UnwindTerminate ( _)
0 commit comments