@@ -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:: traits:: { self , Reveal } ;
2423use rustc:: ty:: { self , TyCtxt , Ty , TypeFoldable } ;
@@ -196,91 +195,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
196195 self . add ( original) ;
197196 }
198197
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-
284198 /// Check if an Lvalue with the current qualifications could
285199 /// be consumed, by either an operand or a Deref projection.
286200 fn try_consume ( & mut self ) -> bool {
@@ -457,25 +371,17 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
457371 }
458372 }
459373
460- let return_ty = mir. return_ty ;
461374 self . qualif = self . return_qualif . unwrap_or ( Qualif :: NOT_CONST ) ;
462375
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) ;
477382 }
478383
384+
479385 // Collect all the temps we need to promote.
480386 let mut promoted_temps = IdxSetBuf :: new_empty ( self . temp_promotion_state . len ( ) ) ;
481387
@@ -637,12 +543,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
637543 // with type parameters, take it into account.
638544 self . qualif . restrict ( constant. ty , self . tcx , self . param_env ) ;
639545 }
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- }
646546 }
647547 }
648548 }
@@ -687,12 +587,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
687587 let allow = if self . mode == Mode :: StaticMut {
688588 // Inside a `static mut`, &mut [...] is also allowed.
689589 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 ,
696591 _ => false
697592 }
698593 } else if let ty:: TyArray ( _, 0 ) = ty. sty {
@@ -794,18 +689,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
794689 if let AggregateKind :: Adt ( def, ..) = * * kind {
795690 if def. has_dtor ( self . tcx ) {
796691 self . add ( Qualif :: NEEDS_DROP ) ;
797- self . deny_drop ( ) ;
798692 }
799693
800694 if Some ( def. did ) == self . tcx . lang_items ( ) . unsafe_cell_type ( ) {
801695 let ty = rvalue. ty ( self . mir , self . tcx ) ;
802696 self . add_type ( ty) ;
803697 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- }
809698 }
810699 }
811700 }
@@ -915,12 +804,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
915804 let ty = dest. ty ( self . mir , tcx) . to_ty ( tcx) ;
916805 self . qualif = Qualif :: empty ( ) ;
917806 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- }
924807 }
925808 self . assign ( dest, location) ;
926809 }
@@ -938,14 +821,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
938821 } ;
939822
940823 if let Some ( span) = needs_drop {
824+ // Double-check the type being dropped, to minimize false positives.
941825 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+ }
949833 }
950834 }
951835 } else {
0 commit comments