@@ -18,7 +18,6 @@ use rustc_data_structures::bitvec::BitVector;
1818use rustc_data_structures:: indexed_set:: IdxSetBuf ;
1919use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
2020use rustc:: hir;
21- use rustc:: hir:: map as hir_map;
2221use rustc:: hir:: def_id:: DefId ;
2322use rustc:: middle:: const_val:: ConstVal ;
2423use rustc:: traits:: { self , Reveal } ;
@@ -197,91 +196,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
197196 self . add ( original) ;
198197 }
199198
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-
285199 /// Check if an Lvalue with the current qualifications could
286200 /// be consumed, by either an operand or a Deref projection.
287201 fn try_consume ( & mut self ) -> bool {
@@ -458,25 +372,17 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
458372 }
459373 }
460374
461- let return_ty = mir. return_ty ;
462375 self . qualif = self . return_qualif . unwrap_or ( Qualif :: NOT_CONST ) ;
463376
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) ;
478383 }
479384
385+
480386 // Collect all the temps we need to promote.
481387 let mut promoted_temps = IdxSetBuf :: new_empty ( self . temp_promotion_state . len ( ) ) ;
482388
@@ -640,12 +546,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
640546 // with type parameters, take it into account.
641547 self . qualif . restrict ( ty, self . tcx , self . param_env ) ;
642548 }
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- }
649549 }
650550 }
651551 }
@@ -690,12 +590,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
690590 let allow = if self . mode == Mode :: StaticMut {
691591 // Inside a `static mut`, &mut [...] is also allowed.
692592 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 ,
699594 _ => false
700595 }
701596 } else if let ty:: TyArray ( _, len) = ty. sty {
@@ -798,18 +693,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
798693 if let AggregateKind :: Adt ( def, ..) = * * kind {
799694 if def. has_dtor ( self . tcx ) {
800695 self . add ( Qualif :: NEEDS_DROP ) ;
801- self . deny_drop ( ) ;
802696 }
803697
804698 if Some ( def. did ) == self . tcx . lang_items ( ) . unsafe_cell_type ( ) {
805699 let ty = rvalue. ty ( self . mir , self . tcx ) ;
806700 self . add_type ( ty) ;
807701 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- }
813702 }
814703 }
815704 }
@@ -919,12 +808,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
919808 let ty = dest. ty ( self . mir , tcx) . to_ty ( tcx) ;
920809 self . qualif = Qualif :: empty ( ) ;
921810 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- }
928811 }
929812 self . assign ( dest, location) ;
930813 }
@@ -942,14 +825,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
942825 } ;
943826
944827 if let Some ( span) = needs_drop {
828+ // Double-check the type being dropped, to minimize false positives.
945829 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+ }
953837 }
954838 }
955839 } else {
0 commit comments