@@ -926,125 +926,135 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
926
926
/// For functions (constant or not), it also records
927
927
/// candidates for promotion in `promotion_candidates`.
928
928
impl < ' 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") ;
951
950
}
951
+ return ;
952
+ }
952
953
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
+ ) ;
966
965
}
967
- unleash_miri ! ( self ) ;
966
+ return ;
967
+ }
968
+ unleash_miri ! ( self ) ;
968
969
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
+ ) ;
983
982
}
983
+ err. emit ( )
984
984
}
985
985
}
986
+ }
987
+ }
986
988
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
+ ) ;
1010
1020
}
1011
1021
}
1012
1022
}
1023
+ }
1024
+ }
1013
1025
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
+ ) ;
1037
1041
}
1038
- }
1039
- }
1040
- }
1042
+ } ,
1041
1043
1042
- ProjectionElem :: Downcast ( ..) => {
1043
- self . not_const ( )
1044
+ | Mode :: Fn
1045
+ | Mode :: Static
1046
+ | Mode :: StaticMut
1047
+ | Mode :: Const
1048
+ => { } ,
1049
+ }
1044
1050
}
1045
1051
}
1046
1052
}
1047
- } ) ;
1053
+
1054
+ ProjectionElem :: Downcast ( ..) => {
1055
+ self . not_const ( )
1056
+ }
1057
+ }
1048
1058
}
1049
1059
1050
1060
fn visit_operand ( & mut self , operand : & Operand < ' tcx > , location : Location ) {
@@ -1069,17 +1079,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
1069
1079
// Check nested operands and places.
1070
1080
if let Rvalue :: Ref ( _, kind, ref place) = * rvalue {
1071
1081
// Special-case reborrows.
1072
- let mut is_reborrow = false ;
1082
+ let mut reborrow_place = None ;
1073
1083
if let Place :: Projection ( ref proj) = * place {
1074
1084
if let ProjectionElem :: Deref = proj. elem {
1075
1085
let base_ty = proj. base . ty ( self . mir , self . tcx ) . ty ;
1076
1086
if let ty:: Ref ( ..) = base_ty. sty {
1077
- is_reborrow = true ;
1087
+ reborrow_place = Some ( & proj . base ) ;
1078
1088
}
1079
1089
}
1080
1090
}
1081
1091
1082
- if is_reborrow {
1092
+ if let Some ( place ) = reborrow_place {
1083
1093
let ctx = match kind {
1084
1094
BorrowKind :: Shared => PlaceContext :: NonMutatingUse (
1085
1095
NonMutatingUseContext :: SharedBorrow ,
@@ -1094,7 +1104,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
1094
1104
MutatingUseContext :: Borrow ,
1095
1105
) ,
1096
1106
} ;
1097
- self . super_place ( place, ctx, location) ;
1107
+ self . visit_place ( place, ctx, location) ;
1098
1108
} else {
1099
1109
self . super_rvalue ( rvalue, location) ;
1100
1110
}
0 commit comments