@@ -56,19 +56,13 @@ bitflags! {
5656 // Function argument.
5757 const FN_ARGUMENT = 1 << 2 ;
5858
59- // Static place or move from a static.
60- const STATIC = 1 << 3 ;
61-
62- // Reference to a static.
63- const STATIC_REF = 1 << 4 ;
64-
6559 // Not constant at all - non-`const fn` calls, asm!,
6660 // pointer comparisons, ptr-to-int casts, etc.
67- const NOT_CONST = 1 << 5 ;
61+ const NOT_CONST = 1 << 3 ;
6862
6963 // Refers to temporaries which cannot be promoted as
7064 // promote_consts decided they weren't simple enough.
71- const NOT_PROMOTABLE = 1 << 6 ;
65+ const NOT_PROMOTABLE = 1 << 4 ;
7266
7367 // Const items can only have MUTABLE_INTERIOR
7468 // and NOT_PROMOTABLE without producing an error.
@@ -226,42 +220,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
226220 self . add ( original) ;
227221 }
228222
229- /// Check if a Local with the current qualifications is promotable.
230- fn can_promote ( & self , qualif : Qualif ) -> bool {
231- // References to statics are allowed, but only in other statics.
232- if self . mode == Mode :: Static || self . mode == Mode :: StaticMut {
233- ( qualif - Qualif :: STATIC_REF ) . is_empty ( )
234- } else {
235- qualif. is_empty ( )
236- }
237- }
238-
239- /// Check if a Place with the current qualifications could
240- /// be consumed, by either an operand or a Deref projection.
241- fn try_consume ( & mut self ) -> bool {
242- if self . qualif . intersects ( Qualif :: STATIC ) && self . mode != Mode :: Fn {
243- let msg = if self . mode == Mode :: Static ||
244- self . mode == Mode :: StaticMut {
245- "cannot refer to other statics by value, use the \
246- address-of operator or a constant instead"
247- } else {
248- "cannot refer to statics by value, use a constant instead"
249- } ;
250- struct_span_err ! ( self . tcx. sess, self . span, E0394 , "{}" , msg)
251- . span_label ( self . span , "referring to another static by value" )
252- . note ( "use the address-of operator or a constant instead" )
253- . emit ( ) ;
254-
255- // Replace STATIC with NOT_CONST to avoid further errors.
256- self . qualif = self . qualif - Qualif :: STATIC ;
257- self . add ( Qualif :: NOT_CONST ) ;
258-
259- false
260- } else {
261- true
262- }
263- }
264-
265223 /// Assign the current qualification to the given destination.
266224 fn assign ( & mut self , dest : & Place < ' tcx > , location : Location ) {
267225 trace ! ( "assign: {:?}" , dest) ;
@@ -305,7 +263,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
305263 } ) if self . mir . local_kind ( index) == LocalKind :: Temp
306264 && self . mir . local_decls [ index] . ty . is_box ( )
307265 && self . local_qualif [ index] . map_or ( false , |qualif| {
308- qualif. intersects ( Qualif :: NOT_CONST )
266+ qualif. contains ( Qualif :: NOT_CONST )
309267 } ) => {
310268 // Part of `box expr`, we should've errored
311269 // already for the Box allocation Rvalue.
@@ -492,17 +450,21 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
492450 match * place {
493451 Place :: Local ( ref local) => self . visit_local ( local, context, location) ,
494452 Place :: Static ( ref global) => {
495- self . add ( Qualif :: STATIC ) ;
453+ // Only allow statics (not consts) to refer to other statics.
454+ if !( self . mode == Mode :: Static || self . mode == Mode :: StaticMut ) {
455+ self . add ( Qualif :: NOT_CONST ) ;
456+ }
496457
497458 if self . mode != Mode :: Fn {
498- for attr in & self . tcx . get_attrs ( global. def_id ) [ ..] {
499- if attr. check_name ( "thread_local" ) {
500- span_err ! ( self . tcx. sess, self . span, E0625 ,
501- "thread-local statics cannot be \
502- accessed at compile-time") ;
503- self . add ( Qualif :: NOT_CONST ) ;
504- return ;
505- }
459+ if self . tcx
460+ . get_attrs ( global. def_id )
461+ . iter ( )
462+ . any ( |attr| attr. check_name ( "thread_local" ) ) {
463+ span_err ! ( self . tcx. sess, self . span, E0625 ,
464+ "thread-local statics cannot be \
465+ accessed at compile-time") ;
466+ self . add ( Qualif :: NOT_CONST ) ;
467+ return ;
506468 }
507469 }
508470
@@ -527,15 +489,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
527489 this. super_place ( place, context, location) ;
528490 match proj. elem {
529491 ProjectionElem :: Deref => {
530- if !this. try_consume ( ) {
531- return ;
532- }
533-
534- if this. qualif . intersects ( Qualif :: STATIC_REF ) {
535- this. qualif = this. qualif - Qualif :: STATIC_REF ;
536- this. add ( Qualif :: STATIC ) ;
537- }
538-
539492 this. add ( Qualif :: NOT_CONST ) ;
540493
541494 let base_ty = proj. base . ty ( this. mir , this. tcx ) . to_ty ( this. tcx ) ;
@@ -573,11 +526,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
573526 this. not_const ( ) ;
574527 }
575528 }
576- } else if this. qualif . intersects ( Qualif :: STATIC ) {
577- span_err ! ( this. tcx. sess, this. span, E0494 ,
578- "cannot refer to the interior of another \
579- static, use a constant instead") ;
580529 }
530+
581531 let ty = place. ty ( this. mir , this. tcx ) . to_ty ( this. tcx ) ;
582532 this. qualif . restrict ( ty, this. tcx , this. param_env ) ;
583533 }
@@ -599,7 +549,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
599549 Operand :: Move ( _) => {
600550 self . nest ( |this| {
601551 this. super_operand ( operand, location) ;
602- this. try_consume ( ) ;
603552 } ) ;
604553
605554 // Mark the consumed locals to indicate later drops are noops.
@@ -651,14 +600,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
651600 region,
652601 kind
653602 } , location) ;
654- if !this. try_consume ( ) {
655- return ;
656- }
657-
658- if this. qualif . intersects ( Qualif :: STATIC_REF ) {
659- this. qualif = this. qualif - Qualif :: STATIC_REF ;
660- this. add ( Qualif :: STATIC ) ;
661- }
662603 } ) ;
663604 } else {
664605 self . super_rvalue ( rvalue, location) ;
@@ -678,22 +619,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
678619 Rvalue :: Cast ( CastKind :: UnsafeFnPointer , ..) |
679620 Rvalue :: Cast ( CastKind :: ClosureFnPointer , ..) |
680621 Rvalue :: Cast ( CastKind :: Unsize , ..) |
681- Rvalue :: Discriminant ( ..) => { }
682-
683- Rvalue :: Len ( _) => {
684- // Static places in consts would have errored already,
685- // don't treat length checks as reads from statics.
686- self . qualif = self . qualif - Qualif :: STATIC ;
687- }
622+ Rvalue :: Discriminant ( ..) |
623+ Rvalue :: Len ( _) => { }
688624
689625 Rvalue :: Ref ( _, kind, ref place) => {
690- // Static places in consts would have errored already,
691- // only keep track of references to them here.
692- if self . qualif . intersects ( Qualif :: STATIC ) {
693- self . qualif = self . qualif - Qualif :: STATIC ;
694- self . add ( Qualif :: STATIC_REF ) ;
695- }
696-
697626 let ty = place. ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
698627
699628 // Default to forbidding the borrow and/or its promotion,
@@ -744,7 +673,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
744673 // Constants cannot be borrowed if they contain interior mutability as
745674 // it means that our "silent insertion of statics" could change
746675 // initializer values (very bad).
747- if self . qualif . intersects ( Qualif :: MUTABLE_INTERIOR ) {
676+ if self . qualif . contains ( Qualif :: MUTABLE_INTERIOR ) {
748677 // A reference of a MUTABLE_INTERIOR place is instead
749678 // NOT_CONST (see `if forbidden_mut` below), to avoid
750679 // duplicate errors (from reborrowing, for example).
@@ -781,7 +710,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
781710 // This allows borrowing fields which don't have
782711 // `MUTABLE_INTERIOR`, from a type that does, e.g.:
783712 // `let _: &'static _ = &(Cell::new(1), 2).1;`
784- if self . can_promote ( qualif - Qualif :: MUTABLE_INTERIOR ) {
713+ if ( qualif - Qualif :: MUTABLE_INTERIOR ) . is_empty ( ) {
785714 self . promotion_candidates . push ( candidate) ;
786715 }
787716 }
@@ -889,7 +818,7 @@ This does not pose a problem by itself because they can't be accessed directly."
889818 if Some ( def. did ) == self . tcx . lang_items ( ) . unsafe_cell_type ( ) {
890819 let ty = rvalue. ty ( self . mir , self . tcx ) ;
891820 self . add_type ( ty) ;
892- assert ! ( self . qualif. intersects ( Qualif :: MUTABLE_INTERIOR ) ) ;
821+ assert ! ( self . qualif. contains ( Qualif :: MUTABLE_INTERIOR ) ) ;
893822 }
894823 }
895824 }
@@ -949,7 +878,7 @@ This does not pose a problem by itself because they can't be accessed directly."
949878 }
950879 let candidate = Candidate :: Argument { bb, index : i } ;
951880 if is_shuffle && i == 2 {
952- if this. can_promote ( this . qualif ) {
881+ if this. qualif . is_empty ( ) {
953882 this. promotion_candidates . push ( candidate) ;
954883 } else {
955884 span_err ! ( this. tcx. sess, this. span, E0526 ,
@@ -965,7 +894,7 @@ This does not pose a problem by itself because they can't be accessed directly."
965894 if !constant_arguments. contains ( & i) {
966895 return
967896 }
968- if this. can_promote ( this . qualif ) {
897+ if this. qualif . is_empty ( ) {
969898 this. promotion_candidates . push ( candidate) ;
970899 } else {
971900 this. tcx . sess . span_err ( this. span ,
@@ -1059,7 +988,7 @@ This does not pose a problem by itself because they can't be accessed directly."
1059988 // HACK(eddyb) Emulate a bit of dataflow analysis,
1060989 // conservatively, that drop elaboration will do.
1061990 let needs_drop = if let Place :: Local ( local) = * place {
1062- if self . local_qualif [ local] . map_or ( true , |q| q. intersects ( Qualif :: NEEDS_DROP ) ) {
991+ if self . local_qualif [ local] . map_or ( true , |q| q. contains ( Qualif :: NEEDS_DROP ) ) {
1063992 Some ( self . mir . local_decls [ local] . source_info . span )
1064993 } else {
1065994 None
@@ -1111,7 +1040,7 @@ This does not pose a problem by itself because they can't be accessed directly."
11111040 }
11121041
11131042 // Avoid a generic error for other uses of arguments.
1114- if self . qualif . intersects ( Qualif :: FN_ARGUMENT ) {
1043+ if self . qualif . contains ( Qualif :: FN_ARGUMENT ) {
11151044 let decl = & self . mir . local_decls [ index] ;
11161045 let mut err = feature_err (
11171046 & self . tcx . sess . parse_sess ,
0 commit comments