1
1
use rustc_middle:: mir:: visit:: Visitor ;
2
2
use rustc_middle:: mir:: { self , BasicBlock , Location } ;
3
- use rustc_middle:: ty:: { Ty , TyCtxt } ;
4
- use rustc_span:: Span ;
3
+ use rustc_middle:: ty:: TyCtxt ;
5
4
use rustc_span:: symbol:: sym;
6
5
use tracing:: trace;
7
6
8
7
use super :: ConstCx ;
9
8
use super :: check:: Qualifs ;
10
- use super :: ops:: { self , NonConstOp } ;
9
+ use super :: ops:: { self } ;
11
10
use super :: qualifs:: { NeedsNonConstDrop , Qualif } ;
11
+ use crate :: check_consts:: check:: Checker ;
12
+ use crate :: check_consts:: qualifs:: NeedsDrop ;
12
13
use crate :: check_consts:: rustc_allow_const_fn_unstable;
13
14
14
15
/// 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> {
66
67
}
67
68
}
68
69
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
-
75
70
impl < ' tcx > Visitor < ' tcx > for CheckLiveDrops < ' _ , ' tcx > {
76
71
fn visit_basic_block_data ( & mut self , bb : BasicBlock , block : & mir:: BasicBlockData < ' tcx > ) {
77
72
trace ! ( "visit_basic_block_data: bb={:?} is_cleanup={:?}" , bb, block. is_cleanup) ;
@@ -89,28 +84,39 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
89
84
90
85
match & terminator. kind {
91
86
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 {
97
96
return ;
98
97
}
99
98
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
+ ) ;
114
120
}
115
121
116
122
mir:: TerminatorKind :: UnwindTerminate ( _)
0 commit comments