@@ -228,7 +228,7 @@ impl<'tcx> Mir<'tcx> {
228228 pub fn temps_iter < ' a > ( & ' a self ) -> impl Iterator < Item =Local > + ' a {
229229 ( self . arg_count +1 ..self . local_decls . len ( ) ) . filter_map ( move |index| {
230230 let local = Local :: new ( index) ;
231- if self . local_decls [ local] . is_user_variable {
231+ if self . local_decls [ local] . is_user_variable . is_some ( ) {
232232 None
233233 } else {
234234 Some ( local)
@@ -241,7 +241,7 @@ impl<'tcx> Mir<'tcx> {
241241 pub fn vars_iter < ' a > ( & ' a self ) -> impl Iterator < Item =Local > + ' a {
242242 ( self . arg_count +1 ..self . local_decls . len ( ) ) . filter_map ( move |index| {
243243 let local = Local :: new ( index) ;
244- if self . local_decls [ local] . is_user_variable {
244+ if self . local_decls [ local] . is_user_variable . is_some ( ) {
245245 Some ( local)
246246 } else {
247247 None
@@ -255,7 +255,7 @@ impl<'tcx> Mir<'tcx> {
255255 ( 1 ..self . local_decls . len ( ) ) . filter_map ( move |index| {
256256 let local = Local :: new ( index) ;
257257 let decl = & self . local_decls [ local] ;
258- if ( decl. is_user_variable || index < self . arg_count + 1 )
258+ if ( decl. is_user_variable . is_some ( ) || index < self . arg_count + 1 )
259259 && decl. mutability == Mutability :: Mut
260260 {
261261 Some ( local)
@@ -351,7 +351,7 @@ impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> {
351351 }
352352}
353353
354- #[ derive( Clone , Debug ) ]
354+ #[ derive( Copy , Clone , Debug ) ]
355355pub enum ClearCrossCrate < T > {
356356 Clear ,
357357 Set ( T )
@@ -382,6 +382,16 @@ pub enum Mutability {
382382 Not ,
383383}
384384
385+ impl From < Mutability > for hir:: Mutability {
386+ fn from ( m : Mutability ) -> Self {
387+ match m {
388+ Mutability :: Mut => hir:: MutMutable ,
389+ Mutability :: Not => hir:: MutImmutable ,
390+ }
391+ }
392+ }
393+
394+
385395#[ derive( Copy , Clone , Debug , PartialEq , Eq , RustcEncodable , RustcDecodable ) ]
386396pub enum BorrowKind {
387397 /// Data must be immutable and is aliasable.
@@ -463,6 +473,33 @@ pub enum LocalKind {
463473 ReturnPointer ,
464474}
465475
476+ #[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug , RustcEncodable , RustcDecodable ) ]
477+ pub struct VarBindingForm {
478+ /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
479+ pub binding_mode : ty:: BindingMode ,
480+ /// If an explicit type was provided for this variable binding,
481+ /// this holds the source Span of that type.
482+ ///
483+ /// NOTE: If you want to change this to a `HirId`, be wary that
484+ /// doing so breaks incremental compilation (as of this writing),
485+ /// while a `Span` does not cause our tests to fail.
486+ pub opt_ty_info : Option < Span > ,
487+ }
488+
489+ #[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug , RustcEncodable , RustcDecodable ) ]
490+ pub enum BindingForm {
491+ /// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
492+ Var ( VarBindingForm ) ,
493+ /// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
494+ ImplicitSelf ,
495+ }
496+
497+ CloneTypeFoldableAndLiftImpls ! { BindingForm , }
498+
499+ impl_stable_hash_for ! ( struct self :: VarBindingForm { binding_mode, opt_ty_info } ) ;
500+
501+ impl_stable_hash_for ! ( enum self :: BindingForm { Var ( binding) , ImplicitSelf , } ) ;
502+
466503/// A MIR local.
467504///
468505/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
@@ -474,8 +511,14 @@ pub struct LocalDecl<'tcx> {
474511 /// Temporaries and the return place are always mutable.
475512 pub mutability : Mutability ,
476513
477- /// True if this corresponds to a user-declared local variable.
478- pub is_user_variable : bool ,
514+ /// Some(binding_mode) if this corresponds to a user-declared local variable.
515+ ///
516+ /// This is solely used for local diagnostics when generating
517+ /// warnings/errors when compiling the current crate, and
518+ /// therefore it need not be visible across crates. pnkfelix
519+ /// currently hypothesized we *need* to wrap this in a
520+ /// `ClearCrossCrate` as long as it carries as `HirId`.
521+ pub is_user_variable : Option < ClearCrossCrate < BindingForm > > ,
479522
480523 /// True if this is an internal local
481524 ///
@@ -592,6 +635,45 @@ pub struct LocalDecl<'tcx> {
592635}
593636
594637impl < ' tcx > LocalDecl < ' tcx > {
638+ /// Returns true only if local is a binding that can itself be
639+ /// made mutable via the addition of the `mut` keyword, namely
640+ /// something like the occurrences of `x` in:
641+ /// - `fn foo(x: Type) { ... }`,
642+ /// - `let x = ...`,
643+ /// - or `match ... { C(x) => ... }`
644+ pub fn can_be_made_mutable ( & self ) -> bool
645+ {
646+ match self . is_user_variable {
647+ Some ( ClearCrossCrate :: Set ( BindingForm :: Var ( VarBindingForm {
648+ binding_mode : ty:: BindingMode :: BindByValue ( _) ,
649+ opt_ty_info : _,
650+ } ) ) ) => true ,
651+
652+ // FIXME: might be able to thread the distinction between
653+ // `self`/`mut self`/`&self`/`&mut self` into the
654+ // `BindingForm::ImplicitSelf` variant, (and then return
655+ // true here for solely the first case).
656+ _ => false ,
657+ }
658+ }
659+
660+ /// Returns true if local is definitely not a `ref ident` or
661+ /// `ref mut ident` binding. (Such bindings cannot be made into
662+ /// mutable bindings, but the inverse does not necessarily hold).
663+ pub fn is_nonref_binding ( & self ) -> bool
664+ {
665+ match self . is_user_variable {
666+ Some ( ClearCrossCrate :: Set ( BindingForm :: Var ( VarBindingForm {
667+ binding_mode : ty:: BindingMode :: BindByValue ( _) ,
668+ opt_ty_info : _,
669+ } ) ) ) => true ,
670+
671+ Some ( ClearCrossCrate :: Set ( BindingForm :: ImplicitSelf ) ) => true ,
672+
673+ _ => false ,
674+ }
675+ }
676+
595677 /// Create a new `LocalDecl` for a temporary.
596678 #[ inline]
597679 pub fn new_temp ( ty : Ty < ' tcx > , span : Span ) -> Self {
@@ -605,7 +687,7 @@ impl<'tcx> LocalDecl<'tcx> {
605687 } ,
606688 visibility_scope : OUTERMOST_SOURCE_SCOPE ,
607689 internal : false ,
608- is_user_variable : false
690+ is_user_variable : None ,
609691 }
610692 }
611693
@@ -622,7 +704,7 @@ impl<'tcx> LocalDecl<'tcx> {
622704 } ,
623705 visibility_scope : OUTERMOST_SOURCE_SCOPE ,
624706 internal : true ,
625- is_user_variable : false
707+ is_user_variable : None ,
626708 }
627709 }
628710
@@ -641,7 +723,7 @@ impl<'tcx> LocalDecl<'tcx> {
641723 visibility_scope : OUTERMOST_SOURCE_SCOPE ,
642724 internal : false ,
643725 name : None , // FIXME maybe we do want some name here?
644- is_user_variable : false
726+ is_user_variable : None ,
645727 }
646728 }
647729}
0 commit comments