@@ -292,7 +292,7 @@ impl<'tcx> Body<'tcx> {
292292 pub fn temps_iter < ' a > ( & ' a self ) -> impl Iterator < Item = Local > + ' a {
293293 ( self . arg_count + 1 ..self . local_decls . len ( ) ) . filter_map ( move |index| {
294294 let local = Local :: new ( index) ;
295- if self . local_decls [ local] . is_user_variable . is_some ( ) {
295+ if self . local_decls [ local] . is_user_variable ( ) {
296296 None
297297 } else {
298298 Some ( local)
@@ -305,7 +305,7 @@ impl<'tcx> Body<'tcx> {
305305 pub fn vars_iter < ' a > ( & ' a self ) -> impl Iterator < Item = Local > + ' a {
306306 ( self . arg_count + 1 ..self . local_decls . len ( ) ) . filter_map ( move |index| {
307307 let local = Local :: new ( index) ;
308- if self . local_decls [ local] . is_user_variable . is_some ( ) {
308+ if self . local_decls [ local] . is_user_variable ( ) {
309309 Some ( local)
310310 } else {
311311 None
@@ -319,7 +319,7 @@ impl<'tcx> Body<'tcx> {
319319 ( self . arg_count + 1 ..self . local_decls . len ( ) ) . filter_map ( move |index| {
320320 let local = Local :: new ( index) ;
321321 let decl = & self . local_decls [ local] ;
322- if decl. is_user_variable . is_some ( ) && decl. mutability == Mutability :: Mut {
322+ if decl. is_user_variable ( ) && decl. mutability == Mutability :: Mut {
323323 Some ( local)
324324 } else {
325325 None
@@ -333,7 +333,7 @@ impl<'tcx> Body<'tcx> {
333333 ( 1 ..self . local_decls . len ( ) ) . filter_map ( move |index| {
334334 let local = Local :: new ( index) ;
335335 let decl = & self . local_decls [ local] ;
336- if ( decl. is_user_variable . is_some ( ) || index < self . arg_count + 1 )
336+ if ( decl. is_user_variable ( ) || index < self . arg_count + 1 )
337337 && decl. mutability == Mutability :: Mut
338338 {
339339 Some ( local)
@@ -696,7 +696,8 @@ pub struct LocalDecl<'tcx> {
696696 /// therefore it need not be visible across crates. pnkfelix
697697 /// currently hypothesized we *need* to wrap this in a
698698 /// `ClearCrossCrate` as long as it carries as `HirId`.
699- pub is_user_variable : Option < ClearCrossCrate < BindingForm < ' tcx > > > ,
699+ // FIXME(matthewjasper) Don't store in this in `Body`
700+ pub local_info : LocalInfo < ' tcx > ,
700701
701702 /// `true` if this is an internal local.
702703 ///
@@ -721,6 +722,7 @@ pub struct LocalDecl<'tcx> {
721722 /// then it is a temporary created for evaluation of some
722723 /// subexpression of some block's tail expression (with no
723724 /// intervening statement context).
725+ // FIXME(matthewjasper) Don't store in this in `Body`
724726 pub is_block_tail : Option < BlockTailInfo > ,
725727
726728 /// The type of this local.
@@ -730,6 +732,7 @@ pub struct LocalDecl<'tcx> {
730732 /// e.g., via `let x: T`, then we carry that type here. The MIR
731733 /// borrow checker needs this information since it can affect
732734 /// region inference.
735+ // FIXME(matthewjasper) Don't store in this in `Body`
733736 pub user_ty : UserTypeProjections ,
734737
735738 /// The name of the local, used in debuginfo and pretty-printing.
@@ -824,6 +827,17 @@ pub struct LocalDecl<'tcx> {
824827 pub visibility_scope : SourceScope ,
825828}
826829
830+ /// Extra information about a local that's used for diagnostics.
831+ #[ derive( Clone , Debug , RustcEncodable , RustcDecodable , HashStable , TypeFoldable ) ]
832+ pub enum LocalInfo < ' tcx > {
833+ /// A user-defined local variable or function parameter
834+ User ( ClearCrossCrate < BindingForm < ' tcx > > ) ,
835+ /// A temporary created that references the static with the given `DefId`.
836+ StaticRef { def_id : DefId , is_thread_local : bool } ,
837+ /// Any other temporary, the return place, or an anonymous function parameter.
838+ Other ,
839+ }
840+
827841impl < ' tcx > LocalDecl < ' tcx > {
828842 /// Returns `true` only if local is a binding that can itself be
829843 /// made mutable via the addition of the `mut` keyword, namely
@@ -832,15 +846,17 @@ impl<'tcx> LocalDecl<'tcx> {
832846 /// - `let x = ...`,
833847 /// - or `match ... { C(x) => ... }`
834848 pub fn can_be_made_mutable ( & self ) -> bool {
835- match self . is_user_variable {
836- Some ( ClearCrossCrate :: Set ( BindingForm :: Var ( VarBindingForm {
849+ match self . local_info {
850+ LocalInfo :: User ( ClearCrossCrate :: Set ( BindingForm :: Var ( VarBindingForm {
837851 binding_mode : ty:: BindingMode :: BindByValue ( _) ,
838852 opt_ty_info : _,
839853 opt_match_place : _,
840854 pat_span : _,
841855 } ) ) ) => true ,
842856
843- Some ( ClearCrossCrate :: Set ( BindingForm :: ImplicitSelf ( ImplicitSelfKind :: Imm ) ) ) => true ,
857+ LocalInfo :: User (
858+ ClearCrossCrate :: Set ( BindingForm :: ImplicitSelf ( ImplicitSelfKind :: Imm ) ) ,
859+ ) => true ,
844860
845861 _ => false ,
846862 }
@@ -850,16 +866,26 @@ impl<'tcx> LocalDecl<'tcx> {
850866 /// `ref mut ident` binding. (Such bindings cannot be made into
851867 /// mutable bindings, but the inverse does not necessarily hold).
852868 pub fn is_nonref_binding ( & self ) -> bool {
853- match self . is_user_variable {
854- Some ( ClearCrossCrate :: Set ( BindingForm :: Var ( VarBindingForm {
869+ match self . local_info {
870+ LocalInfo :: User ( ClearCrossCrate :: Set ( BindingForm :: Var ( VarBindingForm {
855871 binding_mode : ty:: BindingMode :: BindByValue ( _) ,
856872 opt_ty_info : _,
857873 opt_match_place : _,
858874 pat_span : _,
859875 } ) ) ) => true ,
860876
861- Some ( ClearCrossCrate :: Set ( BindingForm :: ImplicitSelf ( _) ) ) => true ,
877+ LocalInfo :: User ( ClearCrossCrate :: Set ( BindingForm :: ImplicitSelf ( _) ) ) => true ,
878+
879+ _ => false ,
880+ }
881+ }
862882
883+ /// Returns `true` if this variable is a named variable or function
884+ /// parameter declared by the user.
885+ #[ inline]
886+ pub fn is_user_variable ( & self ) -> bool {
887+ match self . local_info {
888+ LocalInfo :: User ( _) => true ,
863889 _ => false ,
864890 }
865891 }
@@ -868,8 +894,26 @@ impl<'tcx> LocalDecl<'tcx> {
868894 /// expression that is used to access said variable for the guard of the
869895 /// match arm.
870896 pub fn is_ref_for_guard ( & self ) -> bool {
871- match self . is_user_variable {
872- Some ( ClearCrossCrate :: Set ( BindingForm :: RefForGuard ) ) => true ,
897+ match self . local_info {
898+ LocalInfo :: User ( ClearCrossCrate :: Set ( BindingForm :: RefForGuard ) ) => true ,
899+ _ => false ,
900+ }
901+ }
902+
903+ /// Returns `Some` if this is a reference to a static item that is used to
904+ /// access that static
905+ pub fn is_ref_to_static ( & self ) -> bool {
906+ match self . local_info {
907+ LocalInfo :: StaticRef { .. } => true ,
908+ _ => false ,
909+ }
910+ }
911+
912+ /// Returns `Some` if this is a reference to a static item that is used to
913+ /// access that static
914+ pub fn is_ref_to_thread_local ( & self ) -> bool {
915+ match self . local_info {
916+ LocalInfo :: StaticRef { is_thread_local, .. } => is_thread_local,
873917 _ => false ,
874918 }
875919 }
@@ -918,7 +962,7 @@ impl<'tcx> LocalDecl<'tcx> {
918962 source_info : SourceInfo { span, scope : OUTERMOST_SOURCE_SCOPE } ,
919963 visibility_scope : OUTERMOST_SOURCE_SCOPE ,
920964 internal,
921- is_user_variable : None ,
965+ local_info : LocalInfo :: Other ,
922966 is_block_tail : None ,
923967 }
924968 }
@@ -937,7 +981,7 @@ impl<'tcx> LocalDecl<'tcx> {
937981 internal : false ,
938982 is_block_tail : None ,
939983 name : None , // FIXME maybe we do want some name here?
940- is_user_variable : None ,
984+ local_info : LocalInfo :: Other ,
941985 }
942986 }
943987}
0 commit comments