@@ -926,125 +926,135 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
926926/// For functions (constant or not), it also records
927927/// candidates for promotion in `promotion_candidates`.
928928impl < ' a , ' tcx > Visitor < ' tcx > for Checker < ' a , ' tcx > {
929- fn visit_place ( & mut self ,
930- place : & Place < ' tcx > ,
931- context : PlaceContext ,
932- location : Location ) {
933- debug ! ( "visit_place: place={:?} context={:?} location={:?}" , place, context, location) ;
934- place. iterate ( |place_base, place_projections| {
935- match place_base {
936- PlaceBase :: Local ( _) => { }
937- PlaceBase :: Static ( box Static { kind : StaticKind :: Promoted ( _) , .. } ) => {
938- unreachable ! ( )
939- }
940- PlaceBase :: Static ( box Static { kind : StaticKind :: Static ( def_id) , .. } ) => {
941- if self . tcx
942- . get_attrs ( * def_id)
943- . iter ( )
944- . any ( |attr| attr. check_name ( sym:: thread_local) ) {
945- if self . mode != Mode :: Fn {
946- span_err ! ( self . tcx. sess, self . span, E0625 ,
947- "thread-local statics cannot be \
948- accessed at compile-time") ;
949- }
950- return ;
929+ fn visit_place_base (
930+ & mut self ,
931+ place_base : & PlaceBase < ' tcx > ,
932+ context : PlaceContext ,
933+ location : Location ,
934+ ) {
935+ self . super_place_base ( place_base, context, location) ;
936+ match place_base {
937+ PlaceBase :: Local ( _) => { }
938+ PlaceBase :: Static ( box Static { kind : StaticKind :: Promoted ( _) , .. } ) => {
939+ unreachable ! ( )
940+ }
941+ PlaceBase :: Static ( box Static { kind : StaticKind :: Static ( def_id) , .. } ) => {
942+ if self . tcx
943+ . get_attrs ( * def_id)
944+ . iter ( )
945+ . any ( |attr| attr. check_name ( sym:: thread_local) ) {
946+ if self . mode != Mode :: Fn {
947+ span_err ! ( self . tcx. sess, self . span, E0625 ,
948+ "thread-local statics cannot be \
949+ accessed at compile-time") ;
951950 }
951+ return ;
952+ }
952953
953- // Only allow statics (not consts) to refer to other statics.
954- if self . mode == Mode :: Static || self . mode == Mode :: StaticMut {
955- if self . mode == Mode :: Static && context. is_mutating_use ( ) {
956- // this is not strictly necessary as miri will also bail out
957- // For interior mutability we can't really catch this statically as that
958- // goes through raw pointers and intermediate temporaries, so miri has
959- // to catch this anyway
960- self . tcx . sess . span_err (
961- self . span ,
962- "cannot mutate statics in the initializer of another static" ,
963- ) ;
964- }
965- return ;
954+ // Only allow statics (not consts) to refer to other statics.
955+ if self . mode == Mode :: Static || self . mode == Mode :: StaticMut {
956+ if self . mode == Mode :: Static && context. is_mutating_use ( ) {
957+ // this is not strictly necessary as miri will also bail out
958+ // For interior mutability we can't really catch this statically as that
959+ // goes through raw pointers and intermediate temporaries, so miri has
960+ // to catch this anyway
961+ self . tcx . sess . span_err (
962+ self . span ,
963+ "cannot mutate statics in the initializer of another static" ,
964+ ) ;
966965 }
967- unleash_miri ! ( self ) ;
966+ return ;
967+ }
968+ unleash_miri ! ( self ) ;
968969
969- if self . mode != Mode :: Fn {
970- let mut err = struct_span_err ! ( self . tcx. sess, self . span, E0013 ,
971- "{}s cannot refer to statics, use \
972- a constant instead", self . mode) ;
973- if self . tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
974- err. note (
975- "Static and const variables can refer to other const variables. \
976- But a const variable cannot refer to a static variable."
977- ) ;
978- err. help (
979- "To fix this, the value can be extracted as a const and then used."
980- ) ;
981- }
982- err. emit ( )
970+ if self . mode != Mode :: Fn {
971+ let mut err = struct_span_err ! ( self . tcx. sess, self . span, E0013 ,
972+ "{}s cannot refer to statics, use \
973+ a constant instead", self . mode) ;
974+ if self . tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
975+ err. note (
976+ "Static and const variables can refer to other const variables. \
977+ But a const variable cannot refer to a static variable."
978+ ) ;
979+ err. help (
980+ "To fix this, the value can be extracted as a const and then used."
981+ ) ;
983982 }
983+ err. emit ( )
984984 }
985985 }
986+ }
987+ }
986988
987- for proj in place_projections {
988- match proj. elem {
989- ProjectionElem :: Deref => {
990- if context. is_mutating_use ( ) {
991- // `not_const` errors out in const contexts
992- self . not_const ( )
993- }
994- let base_ty = proj. base . ty ( self . mir , self . tcx ) . ty ;
995- match self . mode {
996- Mode :: Fn => { } ,
997- _ => {
998- if let ty:: RawPtr ( _) = base_ty. sty {
999- if !self . tcx . features ( ) . const_raw_ptr_deref {
1000- emit_feature_err (
1001- & self . tcx . sess . parse_sess , sym:: const_raw_ptr_deref,
1002- self . span , GateIssue :: Language ,
1003- & format ! (
1004- "dereferencing raw pointers in {}s is unstable" ,
1005- self . mode,
1006- ) ,
1007- ) ;
1008- }
1009- }
989+ fn visit_projection (
990+ & mut self ,
991+ proj : & Projection < ' tcx > ,
992+ context : PlaceContext ,
993+ location : Location ,
994+ ) {
995+ debug ! (
996+ "visit_place_projection: proj={:?} context={:?} location={:?}" ,
997+ proj, context, location,
998+ ) ;
999+ self . super_projection ( proj, context, location) ;
1000+ match proj. elem {
1001+ ProjectionElem :: Deref => {
1002+ if context. is_mutating_use ( ) {
1003+ // `not_const` errors out in const contexts
1004+ self . not_const ( )
1005+ }
1006+ let base_ty = proj. base . ty ( self . mir , self . tcx ) . ty ;
1007+ match self . mode {
1008+ Mode :: Fn => { } ,
1009+ _ => {
1010+ if let ty:: RawPtr ( _) = base_ty. sty {
1011+ if !self . tcx . features ( ) . const_raw_ptr_deref {
1012+ emit_feature_err (
1013+ & self . tcx . sess . parse_sess , sym:: const_raw_ptr_deref,
1014+ self . span , GateIssue :: Language ,
1015+ & format ! (
1016+ "dereferencing raw pointers in {}s is unstable" ,
1017+ self . mode,
1018+ ) ,
1019+ ) ;
10101020 }
10111021 }
10121022 }
1023+ }
1024+ }
10131025
1014- ProjectionElem :: ConstantIndex { ..} |
1015- ProjectionElem :: Subslice { ..} |
1016- ProjectionElem :: Field ( ..) |
1017- ProjectionElem :: Index ( _) => {
1018- let base_ty = proj. base . ty ( self . mir , self . tcx ) . ty ;
1019- if let Some ( def) = base_ty. ty_adt_def ( ) {
1020- if def. is_union ( ) {
1021- match self . mode {
1022- Mode :: ConstFn => {
1023- if !self . tcx . features ( ) . const_fn_union {
1024- emit_feature_err (
1025- & self . tcx . sess . parse_sess , sym:: const_fn_union,
1026- self . span , GateIssue :: Language ,
1027- "unions in const fn are unstable" ,
1028- ) ;
1029- }
1030- } ,
1031-
1032- | Mode :: Fn
1033- | Mode :: Static
1034- | Mode :: StaticMut
1035- | Mode :: Const
1036- => { } ,
1026+ ProjectionElem :: ConstantIndex { ..} |
1027+ ProjectionElem :: Subslice { ..} |
1028+ ProjectionElem :: Field ( ..) |
1029+ ProjectionElem :: Index ( _) => {
1030+ let base_ty = proj. base . ty ( self . mir , self . tcx ) . ty ;
1031+ if let Some ( def) = base_ty. ty_adt_def ( ) {
1032+ if def. is_union ( ) {
1033+ match self . mode {
1034+ Mode :: ConstFn => {
1035+ if !self . tcx . features ( ) . const_fn_union {
1036+ emit_feature_err (
1037+ & self . tcx . sess . parse_sess , sym:: const_fn_union,
1038+ self . span , GateIssue :: Language ,
1039+ "unions in const fn are unstable" ,
1040+ ) ;
10371041 }
1038- }
1039- }
1040- }
1042+ } ,
10411043
1042- ProjectionElem :: Downcast ( ..) => {
1043- self . not_const ( )
1044+ | Mode :: Fn
1045+ | Mode :: Static
1046+ | Mode :: StaticMut
1047+ | Mode :: Const
1048+ => { } ,
1049+ }
10441050 }
10451051 }
10461052 }
1047- } ) ;
1053+
1054+ ProjectionElem :: Downcast ( ..) => {
1055+ self . not_const ( )
1056+ }
1057+ }
10481058 }
10491059
10501060 fn visit_operand ( & mut self , operand : & Operand < ' tcx > , location : Location ) {
@@ -1069,17 +1079,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
10691079 // Check nested operands and places.
10701080 if let Rvalue :: Ref ( _, kind, ref place) = * rvalue {
10711081 // Special-case reborrows.
1072- let mut is_reborrow = false ;
1082+ let mut reborrow_place = None ;
10731083 if let Place :: Projection ( ref proj) = * place {
10741084 if let ProjectionElem :: Deref = proj. elem {
10751085 let base_ty = proj. base . ty ( self . mir , self . tcx ) . ty ;
10761086 if let ty:: Ref ( ..) = base_ty. sty {
1077- is_reborrow = true ;
1087+ reborrow_place = Some ( & proj . base ) ;
10781088 }
10791089 }
10801090 }
10811091
1082- if is_reborrow {
1092+ if let Some ( place ) = reborrow_place {
10831093 let ctx = match kind {
10841094 BorrowKind :: Shared => PlaceContext :: NonMutatingUse (
10851095 NonMutatingUseContext :: SharedBorrow ,
@@ -1094,7 +1104,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
10941104 MutatingUseContext :: Borrow ,
10951105 ) ,
10961106 } ;
1097- self . super_place ( place, ctx, location) ;
1107+ self . visit_place ( place, ctx, location) ;
10981108 } else {
10991109 self . super_rvalue ( rvalue, location) ;
11001110 }
0 commit comments