@@ -18,7 +18,6 @@ use rustc_data_structures::bitvec::BitVector;
18
18
use rustc_data_structures:: indexed_set:: IdxSetBuf ;
19
19
use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
20
20
use rustc:: hir;
21
- use rustc:: hir:: map as hir_map;
22
21
use rustc:: hir:: def_id:: DefId ;
23
22
use rustc:: middle:: const_val:: ConstVal ;
24
23
use rustc:: traits:: { self , Reveal } ;
@@ -197,91 +196,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
197
196
self . add ( original) ;
198
197
}
199
198
200
- /// Check for NEEDS_DROP (from an ADT or const fn call) and
201
- /// error, unless we're in a function.
202
- fn always_deny_drop ( & self ) {
203
- self . deny_drop_with_feature_gate_override ( false ) ;
204
- }
205
-
206
- /// Check for NEEDS_DROP (from an ADT or const fn call) and
207
- /// error, unless we're in a function, or the feature-gate
208
- /// for constant with destructors is enabled.
209
- fn deny_drop ( & self ) {
210
- self . deny_drop_with_feature_gate_override ( true ) ;
211
- }
212
-
213
- fn deny_drop_with_feature_gate_override ( & self , allow_gate : bool ) {
214
- if self . mode == Mode :: Fn || !self . qualif . intersects ( Qualif :: NEEDS_DROP ) {
215
- return ;
216
- }
217
-
218
- // Constants allow destructors, but they're feature-gated.
219
- let msg = if allow_gate {
220
- // Feature-gate for constant with destructors is enabled.
221
- if self . tcx . sess . features . borrow ( ) . drop_types_in_const {
222
- return ;
223
- }
224
-
225
- // This comes from a macro that has #[allow_internal_unstable].
226
- if self . span . allows_unstable ( ) {
227
- return ;
228
- }
229
-
230
- format ! ( "destructors in {}s are an unstable feature" ,
231
- self . mode)
232
- } else {
233
- format ! ( "{}s are not allowed to have destructors" ,
234
- self . mode)
235
- } ;
236
-
237
- let mut err =
238
- struct_span_err ! ( self . tcx. sess, self . span, E0493 , "{}" , msg) ;
239
-
240
- if allow_gate {
241
- help ! ( & mut err,
242
- "in Nightly builds, add `#![feature(drop_types_in_const)]` \
243
- to the crate attributes to enable") ;
244
- } else {
245
- // FIXME(eddyb) this looks up `self.mir.return_ty`.
246
- // We probably want the actual return type here, if at all.
247
- self . find_drop_implementation_method_span ( )
248
- . map ( |span| err. span_label ( span, "destructor defined here" ) ) ;
249
-
250
- err. span_label ( self . span ,
251
- format ! ( "{}s cannot have destructors" , self . mode) ) ;
252
- }
253
-
254
- err. emit ( ) ;
255
- }
256
-
257
- fn find_drop_implementation_method_span ( & self ) -> Option < Span > {
258
- self . tcx . lang_items ( )
259
- . drop_trait ( )
260
- . and_then ( |drop_trait_id| {
261
- let mut span = None ;
262
-
263
- self . tcx
264
- . for_each_relevant_impl ( drop_trait_id, self . mir . return_ty , |impl_did| {
265
- self . tcx . hir
266
- . as_local_node_id ( impl_did)
267
- . and_then ( |impl_node_id| self . tcx . hir . find ( impl_node_id) )
268
- . map ( |node| {
269
- if let hir_map:: NodeItem ( item) = node {
270
- if let hir:: ItemImpl ( .., ref impl_item_refs) = item. node {
271
- span = impl_item_refs. first ( )
272
- . map ( |iiref| {
273
- self . tcx . hir . impl_item ( iiref. id )
274
- . span
275
- } ) ;
276
- }
277
- }
278
- } ) ;
279
- } ) ;
280
-
281
- span
282
- } )
283
- }
284
-
285
199
/// Check if an Lvalue with the current qualifications could
286
200
/// be consumed, by either an operand or a Deref projection.
287
201
fn try_consume ( & mut self ) -> bool {
@@ -458,25 +372,17 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
458
372
}
459
373
}
460
374
461
- let return_ty = mir. return_ty ;
462
375
self . qualif = self . return_qualif . unwrap_or ( Qualif :: NOT_CONST ) ;
463
376
464
- match self . mode {
465
- Mode :: StaticMut => {
466
- // Check for destructors in static mut.
467
- self . add_type ( return_ty) ;
468
- self . deny_drop ( ) ;
469
- }
470
- _ => {
471
- // Account for errors in consts by using the
472
- // conservative type qualification instead.
473
- if self . qualif . intersects ( Qualif :: CONST_ERROR ) {
474
- self . qualif = Qualif :: empty ( ) ;
475
- self . add_type ( return_ty) ;
476
- }
477
- }
377
+ // Account for errors in consts by using the
378
+ // conservative type qualification instead.
379
+ if self . qualif . intersects ( Qualif :: CONST_ERROR ) {
380
+ self . qualif = Qualif :: empty ( ) ;
381
+ let return_ty = mir. return_ty ;
382
+ self . add_type ( return_ty) ;
478
383
}
479
384
385
+
480
386
// Collect all the temps we need to promote.
481
387
let mut promoted_temps = IdxSetBuf :: new_empty ( self . temp_promotion_state . len ( ) ) ;
482
388
@@ -640,12 +546,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
640
546
// with type parameters, take it into account.
641
547
self . qualif . restrict ( ty, self . tcx , self . param_env ) ;
642
548
}
643
-
644
- // Let `const fn` transitively have destructors,
645
- // but they do get stopped in `const` or `static`.
646
- if self . mode != Mode :: ConstFn {
647
- self . deny_drop ( ) ;
648
- }
649
549
}
650
550
}
651
551
}
@@ -690,12 +590,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
690
590
let allow = if self . mode == Mode :: StaticMut {
691
591
// Inside a `static mut`, &mut [...] is also allowed.
692
592
match ty. sty {
693
- ty:: TyArray ( ..) | ty:: TySlice ( _) => {
694
- // Mutating can expose drops, be conservative.
695
- self . add_type ( ty) ;
696
- self . deny_drop ( ) ;
697
- true
698
- }
593
+ ty:: TyArray ( ..) | ty:: TySlice ( _) => true ,
699
594
_ => false
700
595
}
701
596
} else if let ty:: TyArray ( _, len) = ty. sty {
@@ -798,18 +693,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
798
693
if let AggregateKind :: Adt ( def, ..) = * * kind {
799
694
if def. has_dtor ( self . tcx ) {
800
695
self . add ( Qualif :: NEEDS_DROP ) ;
801
- self . deny_drop ( ) ;
802
696
}
803
697
804
698
if Some ( def. did ) == self . tcx . lang_items ( ) . unsafe_cell_type ( ) {
805
699
let ty = rvalue. ty ( self . mir , self . tcx ) ;
806
700
self . add_type ( ty) ;
807
701
assert ! ( self . qualif. intersects( Qualif :: MUTABLE_INTERIOR ) ) ;
808
- // Even if the value inside may not need dropping,
809
- // mutating it would change that.
810
- if !self . qualif . intersects ( Qualif :: NOT_CONST ) {
811
- self . deny_drop ( ) ;
812
- }
813
702
}
814
703
}
815
704
}
@@ -919,12 +808,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
919
808
let ty = dest. ty ( self . mir , tcx) . to_ty ( tcx) ;
920
809
self . qualif = Qualif :: empty ( ) ;
921
810
self . add_type ( ty) ;
922
-
923
- // Let `const fn` transitively have destructors,
924
- // but they do get stopped in `const` or `static`.
925
- if self . mode != Mode :: ConstFn {
926
- self . deny_drop ( ) ;
927
- }
928
811
}
929
812
self . assign ( dest, location) ;
930
813
}
@@ -942,14 +825,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
942
825
} ;
943
826
944
827
if let Some ( span) = needs_drop {
828
+ // Double-check the type being dropped, to minimize false positives.
945
829
let ty = lvalue. ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
946
- self . add_type ( ty ) ;
947
-
948
- // Use the original assignment span to be more precise.
949
- let old_span = self . span ;
950
- self . span = span ;
951
- self . always_deny_drop ( ) ;
952
- self . span = old_span ;
830
+ if ty . needs_drop ( self . tcx , self . param_env ) {
831
+ struct_span_err ! ( self . tcx . sess , span , E0493 ,
832
+ "destructors cannot be evaluated at compile-time" )
833
+ . span_label ( span, format ! ( "{}s cannot evaluate destructors" ,
834
+ self . mode ) )
835
+ . emit ( ) ;
836
+ }
953
837
}
954
838
}
955
839
} else {
0 commit comments