@@ -44,6 +44,7 @@ use dataflow::{EverInitializedPlaces, MovingOutStatements};
44
44
use dataflow:: { MaybeInitializedPlaces , MaybeUninitializedPlaces } ;
45
45
use util:: borrowck_errors:: { BorrowckErrors , Origin } ;
46
46
use util:: collect_writes:: FindAssignments ;
47
+ use util:: suggest_ref_mut;
47
48
48
49
use self :: borrow_set:: { BorrowData , BorrowSet } ;
49
50
use self :: flows:: Flows ;
@@ -1837,17 +1838,41 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1837
1838
Place :: Projection ( box Projection {
1838
1839
base : Place :: Local ( local) ,
1839
1840
elem : ProjectionElem :: Deref ,
1840
- } ) if self . mir . local_decls [ * local] . is_nonref_binding ( ) =>
1841
- {
1842
- let ( err_help_span, suggested_code) =
1843
- find_place_to_suggest_ampmut ( self . tcx , self . mir , * local) ;
1844
- err. span_suggestion (
1845
- err_help_span,
1846
- "consider changing this to be a mutable reference" ,
1847
- suggested_code,
1848
- ) ;
1849
-
1841
+ } ) if self . mir . local_decls [ * local] . is_user_variable . is_some ( ) => {
1850
1842
let local_decl = & self . mir . local_decls [ * local] ;
1843
+ let suggestion = match local_decl. is_user_variable . as_ref ( ) . unwrap ( ) {
1844
+ ClearCrossCrate :: Set ( mir:: BindingForm :: ImplicitSelf ) => {
1845
+ Some ( suggest_ampmut_self ( local_decl) )
1846
+ } ,
1847
+
1848
+ ClearCrossCrate :: Set ( mir:: BindingForm :: Var ( mir:: VarBindingForm {
1849
+ binding_mode : ty:: BindingMode :: BindByValue ( _) ,
1850
+ opt_ty_info,
1851
+ ..
1852
+ } ) ) => Some ( suggest_ampmut (
1853
+ self . tcx ,
1854
+ self . mir ,
1855
+ * local,
1856
+ local_decl,
1857
+ * opt_ty_info,
1858
+ ) ) ,
1859
+
1860
+ ClearCrossCrate :: Set ( mir:: BindingForm :: Var ( mir:: VarBindingForm {
1861
+ binding_mode : ty:: BindingMode :: BindByReference ( _) ,
1862
+ ..
1863
+ } ) ) => suggest_ref_mut ( self . tcx , local_decl. source_info . span ) ,
1864
+
1865
+ ClearCrossCrate :: Clear => bug ! ( "saw cleared local state" ) ,
1866
+ } ;
1867
+
1868
+ if let Some ( ( err_help_span, suggested_code) ) = suggestion {
1869
+ err. span_suggestion (
1870
+ err_help_span,
1871
+ "consider changing this to be a mutable reference" ,
1872
+ suggested_code,
1873
+ ) ;
1874
+ }
1875
+
1851
1876
if let Some ( name) = local_decl. name {
1852
1877
err. span_label (
1853
1878
span,
@@ -1874,13 +1899,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1874
1899
err. emit ( ) ;
1875
1900
return true ;
1876
1901
1877
- // Returns the span to highlight and the associated text to
1878
- // present when suggesting that the user use an `&mut`.
1879
- //
1902
+ fn suggest_ampmut_self < ' cx , ' gcx , ' tcx > (
1903
+ local_decl : & mir:: LocalDecl < ' tcx > ,
1904
+ ) -> ( Span , String ) {
1905
+ ( local_decl. source_info . span , "&mut self" . to_string ( ) )
1906
+ }
1907
+
1880
1908
// When we want to suggest a user change a local variable to be a `&mut`, there
1881
1909
// are three potential "obvious" things to highlight:
1882
1910
//
1883
- // let ident [: Type] [= RightHandSideExresssion ];
1911
+ // let ident [: Type] [= RightHandSideExpression ];
1884
1912
// ^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
1885
1913
// (1.) (2.) (3.)
1886
1914
//
@@ -1889,48 +1917,44 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1889
1917
// for example, if the RHS is present and the Type is not, then the type is going to
1890
1918
// be inferred *from* the RHS, which means we should highlight that (and suggest
1891
1919
// that they borrow the RHS mutably).
1892
- fn find_place_to_suggest_ampmut < ' cx , ' gcx , ' tcx > (
1920
+ //
1921
+ // This implementation attempts to emulate AST-borrowck prioritization
1922
+ // by trying (3.), then (2.) and finally falling back on (1.).
1923
+ fn suggest_ampmut < ' cx , ' gcx , ' tcx > (
1893
1924
tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
1894
1925
mir : & Mir < ' tcx > ,
1895
1926
local : Local ,
1927
+ local_decl : & mir:: LocalDecl < ' tcx > ,
1928
+ opt_ty_info : Option < Span > ,
1896
1929
) -> ( Span , String ) {
1897
- // This implementation attempts to emulate AST-borrowck prioritization
1898
- // by trying (3.), then (2.) and finally falling back on (1.).
1899
1930
let locations = mir. find_assignments ( local) ;
1900
1931
if locations. len ( ) > 0 {
1901
1932
let assignment_rhs_span = mir. source_info ( locations[ 0 ] ) . span ;
1902
1933
let snippet = tcx. sess . codemap ( ) . span_to_snippet ( assignment_rhs_span) ;
1903
1934
if let Ok ( src) = snippet {
1904
- // pnkfelix inherited code; believes intention is
1905
- // highlighted text will always be `&<expr>` and
1906
- // thus can transform to `&mut` by slicing off
1907
- // first ASCII character and prepending "&mut ".
1908
1935
if src. starts_with ( '&' ) {
1909
1936
let borrowed_expr = src[ 1 ..] . to_string ( ) ;
1910
- return ( assignment_rhs_span, format ! ( "&mut {}" , borrowed_expr) ) ;
1937
+ return (
1938
+ assignment_rhs_span,
1939
+ format ! ( "&mut {}" , borrowed_expr) ,
1940
+ ) ;
1911
1941
}
1912
1942
}
1913
1943
}
1914
1944
1915
- let local_decl = & mir. local_decls [ local] ;
1916
- let highlight_span = match local_decl. is_user_variable {
1945
+ let highlight_span = match opt_ty_info {
1917
1946
// if this is a variable binding with an explicit type,
1918
1947
// try to highlight that for the suggestion.
1919
- Some ( ClearCrossCrate :: Set ( mir:: BindingForm :: Var ( mir:: VarBindingForm {
1920
- opt_ty_info : Some ( ty_span) ,
1921
- ..
1922
- } ) ) ) => ty_span,
1923
-
1924
- Some ( ClearCrossCrate :: Clear ) => bug ! ( "saw cleared local state" ) ,
1948
+ Some ( ty_span) => ty_span,
1925
1949
1926
1950
// otherwise, just highlight the span associated with
1927
1951
// the (MIR) LocalDecl.
1928
- _ => local_decl. source_info . span ,
1952
+ None => local_decl. source_info . span ,
1929
1953
} ;
1930
1954
1931
1955
let ty_mut = local_decl. ty . builtin_deref ( true ) . unwrap ( ) ;
1932
1956
assert_eq ! ( ty_mut. mutbl, hir:: MutImmutable ) ;
1933
- return ( highlight_span, format ! ( "&mut {}" , ty_mut. ty) ) ;
1957
+ ( highlight_span, format ! ( "&mut {}" , ty_mut. ty) )
1934
1958
}
1935
1959
}
1936
1960
0 commit comments