@@ -16,7 +16,7 @@ use rustc::hir::def_id::DefId;
16
16
use rustc:: hir:: map:: definitions:: DefPathData ;
17
17
use rustc:: infer:: InferCtxt ;
18
18
use rustc:: lint:: builtin:: UNUSED_MUT ;
19
- use rustc:: mir:: { self , AggregateKind , BasicBlock , BorrowCheckResult , BorrowKind } ;
19
+ use rustc:: mir:: { AggregateKind , BasicBlock , BorrowCheckResult , BorrowKind } ;
20
20
use rustc:: mir:: { ClearCrossCrate , Local , Location , Mir , Mutability , Operand , Place } ;
21
21
use rustc:: mir:: { Field , Projection , ProjectionElem , Rvalue , Statement , StatementKind } ;
22
22
use rustc:: mir:: { Terminator , TerminatorKind } ;
@@ -43,27 +43,27 @@ use dataflow::{do_dataflow, DebugFormatted};
43
43
use dataflow:: { EverInitializedPlaces , MovingOutStatements } ;
44
44
use dataflow:: { MaybeInitializedPlaces , MaybeUninitializedPlaces } ;
45
45
use util:: borrowck_errors:: { BorrowckErrors , Origin } ;
46
- use util:: collect_writes:: FindAssignments ;
47
- use util:: suggest_ref_mut;
48
46
49
47
use self :: borrow_set:: { BorrowData , BorrowSet } ;
50
48
use self :: flows:: Flows ;
51
49
use self :: location:: LocationTable ;
52
50
use self :: prefixes:: PrefixSet ;
53
51
use self :: MutateMode :: { JustWrite , WriteAndRead } ;
52
+ use self :: mutability_errors:: AccessKind ;
54
53
55
54
use self :: path_utils:: * ;
56
55
57
56
crate mod borrow_set;
58
57
mod error_reporting;
59
58
mod flows;
60
59
mod location;
60
+ mod move_errors;
61
+ mod mutability_errors;
61
62
mod path_utils;
62
63
crate mod place_ext;
63
64
mod places_conflict;
64
65
mod prefixes;
65
66
mod used_muts;
66
- mod move_errors;
67
67
68
68
pub ( crate ) mod nll;
69
69
@@ -922,7 +922,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
922
922
}
923
923
924
924
let mutability_error =
925
- self . check_access_permissions ( place_span, rw, is_local_mutation_allowed, flow_state) ;
925
+ self . check_access_permissions (
926
+ place_span,
927
+ rw,
928
+ is_local_mutation_allowed,
929
+ flow_state,
930
+ context. loc ,
931
+ ) ;
926
932
let conflict_error =
927
933
self . check_access_for_conflict ( context, place_span, sd, rw, flow_state) ;
928
934
@@ -1668,6 +1674,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1668
1674
}
1669
1675
}
1670
1676
1677
+
1671
1678
/// Check the permissions for the given place and read or write kind
1672
1679
///
1673
1680
/// Returns true if an error is reported, false otherwise.
@@ -1677,17 +1684,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1677
1684
kind : ReadOrWrite ,
1678
1685
is_local_mutation_allowed : LocalMutationIsAllowed ,
1679
1686
flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
1687
+ location : Location ,
1680
1688
) -> bool {
1681
1689
debug ! (
1682
1690
"check_access_permissions({:?}, {:?}, {:?})" ,
1683
1691
place, kind, is_local_mutation_allowed
1684
1692
) ;
1685
1693
1686
- #[ derive( Copy , Clone , Debug ) ]
1687
- enum AccessKind {
1688
- MutableBorrow ,
1689
- Mutate ,
1690
- }
1691
1694
let error_access;
1692
1695
let the_place_err;
1693
1696
@@ -1756,206 +1759,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1756
1759
}
1757
1760
1758
1761
// at this point, we have set up the error reporting state.
1759
-
1760
- let mut err;
1761
- let item_msg = match self . describe_place ( place) {
1762
- Some ( name) => format ! ( "immutable item `{}`" , name) ,
1763
- None => "immutable item" . to_owned ( ) ,
1764
- } ;
1765
-
1766
- // `act` and `acted_on` are strings that let us abstract over
1767
- // the verbs used in some diagnostic messages.
1768
- let act;
1769
- let acted_on;
1770
-
1771
- match error_access {
1772
- AccessKind :: Mutate => {
1773
- let item_msg = match the_place_err {
1774
- Place :: Projection ( box Projection {
1775
- base : _,
1776
- elem : ProjectionElem :: Deref ,
1777
- } ) => match self . describe_place ( place) {
1778
- Some ( description) => {
1779
- format ! ( "`{}` which is behind a `&` reference" , description)
1780
- }
1781
- None => format ! ( "data in a `&` reference" ) ,
1782
- } ,
1783
- _ => item_msg,
1784
- } ;
1785
- err = self . tcx . cannot_assign ( span, & item_msg, Origin :: Mir ) ;
1786
- act = "assign" ;
1787
- acted_on = "written" ;
1788
- }
1789
- AccessKind :: MutableBorrow => {
1790
- err = self
1791
- . tcx
1792
- . cannot_borrow_path_as_mutable ( span, & item_msg, Origin :: Mir ) ;
1793
- act = "borrow as mutable" ;
1794
- acted_on = "borrowed as mutable" ;
1795
- }
1796
- }
1797
-
1798
- match the_place_err {
1799
- // We want to suggest users use `let mut` for local (user
1800
- // variable) mutations...
1801
- Place :: Local ( local) if self . mir . local_decls [ * local] . can_be_made_mutable ( ) => {
1802
- // ... but it doesn't make sense to suggest it on
1803
- // variables that are `ref x`, `ref mut x`, `&self`,
1804
- // or `&mut self` (such variables are simply not
1805
- // mutable)..
1806
- let local_decl = & self . mir . local_decls [ * local] ;
1807
- assert_eq ! ( local_decl. mutability, Mutability :: Not ) ;
1808
-
1809
- err. span_label ( span, format ! ( "cannot {ACT}" , ACT = act) ) ;
1810
- err. span_suggestion (
1811
- local_decl. source_info . span ,
1812
- "consider changing this to be mutable" ,
1813
- format ! ( "mut {}" , local_decl. name. unwrap( ) ) ,
1814
- ) ;
1815
- }
1816
-
1817
- // complete hack to approximate old AST-borrowck
1818
- // diagnostic: if the span starts with a mutable borrow of
1819
- // a local variable, then just suggest the user remove it.
1820
- Place :: Local ( _)
1821
- if {
1822
- if let Ok ( snippet) = self . tcx . sess . codemap ( ) . span_to_snippet ( span) {
1823
- snippet. starts_with ( "&mut " )
1824
- } else {
1825
- false
1826
- }
1827
- } =>
1828
- {
1829
- err. span_label ( span, format ! ( "cannot {ACT}" , ACT = act) ) ;
1830
- err. span_label ( span, "try removing `&mut` here" ) ;
1831
- }
1832
-
1833
- // We want to point out when a `&` can be readily replaced
1834
- // with an `&mut`.
1835
- //
1836
- // FIXME: can this case be generalized to work for an
1837
- // arbitrary base for the projection?
1838
- Place :: Projection ( box Projection {
1839
- base : Place :: Local ( local) ,
1840
- elem : ProjectionElem :: Deref ,
1841
- } ) if self . mir . local_decls [ * local] . is_user_variable . is_some ( ) => {
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
-
1876
- if let Some ( name) = local_decl. name {
1877
- err. span_label (
1878
- span,
1879
- format ! (
1880
- "`{NAME}` is a `&` reference, \
1881
- so the data it refers to cannot be {ACTED_ON}",
1882
- NAME = name,
1883
- ACTED_ON = acted_on
1884
- ) ,
1885
- ) ;
1886
- } else {
1887
- err. span_label (
1888
- span,
1889
- format ! ( "cannot {ACT} through `&`-reference" , ACT = act) ,
1890
- ) ;
1891
- }
1892
- }
1893
-
1894
- _ => {
1895
- err. span_label ( span, format ! ( "cannot {ACT}" , ACT = act) ) ;
1896
- }
1897
- }
1898
-
1899
- err. emit ( ) ;
1762
+ self . report_mutability_error (
1763
+ place,
1764
+ span,
1765
+ the_place_err,
1766
+ error_access,
1767
+ location,
1768
+ ) ;
1900
1769
return true ;
1901
-
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
-
1908
- // When we want to suggest a user change a local variable to be a `&mut`, there
1909
- // are three potential "obvious" things to highlight:
1910
- //
1911
- // let ident [: Type] [= RightHandSideExpression];
1912
- // ^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
1913
- // (1.) (2.) (3.)
1914
- //
1915
- // We can always fallback on highlighting the first. But chances are good that
1916
- // the user experience will be better if we highlight one of the others if possible;
1917
- // for example, if the RHS is present and the Type is not, then the type is going to
1918
- // be inferred *from* the RHS, which means we should highlight that (and suggest
1919
- // that they borrow the RHS mutably).
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 > (
1924
- tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
1925
- mir : & Mir < ' tcx > ,
1926
- local : Local ,
1927
- local_decl : & mir:: LocalDecl < ' tcx > ,
1928
- opt_ty_info : Option < Span > ,
1929
- ) -> ( Span , String ) {
1930
- let locations = mir. find_assignments ( local) ;
1931
- if locations. len ( ) > 0 {
1932
- let assignment_rhs_span = mir. source_info ( locations[ 0 ] ) . span ;
1933
- let snippet = tcx. sess . codemap ( ) . span_to_snippet ( assignment_rhs_span) ;
1934
- if let Ok ( src) = snippet {
1935
- if src. starts_with ( '&' ) {
1936
- let borrowed_expr = src[ 1 ..] . to_string ( ) ;
1937
- return (
1938
- assignment_rhs_span,
1939
- format ! ( "&mut {}" , borrowed_expr) ,
1940
- ) ;
1941
- }
1942
- }
1943
- }
1944
-
1945
- let highlight_span = match opt_ty_info {
1946
- // if this is a variable binding with an explicit type,
1947
- // try to highlight that for the suggestion.
1948
- Some ( ty_span) => ty_span,
1949
-
1950
- // otherwise, just highlight the span associated with
1951
- // the (MIR) LocalDecl.
1952
- None => local_decl. source_info . span ,
1953
- } ;
1954
-
1955
- let ty_mut = local_decl. ty . builtin_deref ( true ) . unwrap ( ) ;
1956
- assert_eq ! ( ty_mut. mutbl, hir:: MutImmutable ) ;
1957
- ( highlight_span, format ! ( "&mut {}" , ty_mut. ty) )
1958
- }
1959
1770
}
1960
1771
1961
1772
/// Adds the place into the used mutable variables set
0 commit comments