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