@@ -24,7 +24,7 @@ use self::InteriorKind::*;
24
24
25
25
use rustc:: dep_graph:: DepNode ;
26
26
use rustc:: hir:: map as hir_map;
27
- use rustc:: hir:: map:: blocks:: FnParts ;
27
+ use rustc:: hir:: map:: blocks:: { FnParts , FnLikeNode } ;
28
28
use rustc:: cfg;
29
29
use rustc:: middle:: dataflow:: DataFlowContext ;
30
30
use rustc:: middle:: dataflow:: BitwiseOperator ;
@@ -970,51 +970,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
970
970
971
971
pub fn note_and_explain_bckerr ( & self , db : & mut DiagnosticBuilder , err : BckError < ' tcx > ,
972
972
error_span : Span ) {
973
- let code = err. code ;
974
- match code {
975
- err_mutbl => {
976
- match err. cmt . note {
977
- mc:: NoteClosureEnv ( upvar_id) | mc:: NoteUpvarRef ( upvar_id) => {
978
- // If this is an `Fn` closure, it simply can't mutate upvars.
979
- // If it's an `FnMut` closure, the original variable was declared immutable.
980
- // We need to determine which is the case here.
981
- let kind = match err. cmt . upvar ( ) . unwrap ( ) . cat {
982
- Categorization :: Upvar ( mc:: Upvar { kind, .. } ) => kind,
983
- _ => bug ! ( )
984
- } ;
985
- if kind == ty:: ClosureKind :: Fn {
986
- db. span_help (
987
- self . tcx . map . span ( upvar_id. closure_expr_id ) ,
988
- "consider changing this closure to take \
989
- self by mutable reference") ;
990
- }
991
- }
992
- _ => {
993
- if let Categorization :: Local ( local_id) = err. cmt . cat {
994
- let span = self . tcx . map . span ( local_id) ;
995
- if let Ok ( snippet) = self . tcx . sess . codemap ( ) . span_to_snippet ( span) {
996
- if snippet. starts_with ( "ref mut " ) || snippet. starts_with ( "&mut " ) {
997
- db. span_label ( error_span, & format ! ( "cannot reborrow mutably" ) ) ;
998
- db. span_label ( error_span, & format ! ( "try removing `&mut` here" ) ) ;
999
- } else {
1000
- if snippet. starts_with ( "ref " ) {
1001
- db. span_label ( span,
1002
- & format ! ( "use `{}` here to make mutable" ,
1003
- snippet. replace( "ref " , "ref mut " ) ) ) ;
1004
- } else if snippet != "self" {
1005
- db. span_label ( span,
1006
- & format ! ( "use `mut {}` here to make mutable" , snippet) ) ;
1007
- }
1008
- db. span_label ( error_span, & format ! ( "cannot borrow mutably" ) ) ;
1009
- }
1010
- } else {
1011
- db. span_label ( error_span, & format ! ( "cannot borrow mutably" ) ) ;
1012
- }
1013
- }
1014
- }
1015
- }
1016
- }
1017
-
973
+ match err. code {
974
+ err_mutbl => self . note_and_explain_mutbl_error ( db, & err, & error_span) ,
1018
975
err_out_of_scope( super_scope, sub_scope, cause) => {
1019
976
let ( value_kind, value_msg) = match err. cmt . cat {
1020
977
mc:: Categorization :: Rvalue ( _) =>
@@ -1135,6 +1092,86 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
1135
1092
}
1136
1093
}
1137
1094
1095
+ fn note_and_explain_mutbl_error ( & self , db : & mut DiagnosticBuilder , err : & BckError < ' tcx > ,
1096
+ error_span : & Span ) {
1097
+ match err. cmt . note {
1098
+ mc:: NoteClosureEnv ( upvar_id) | mc:: NoteUpvarRef ( upvar_id) => {
1099
+ // If this is an `Fn` closure, it simply can't mutate upvars.
1100
+ // If it's an `FnMut` closure, the original variable was declared immutable.
1101
+ // We need to determine which is the case here.
1102
+ let kind = match err. cmt . upvar ( ) . unwrap ( ) . cat {
1103
+ Categorization :: Upvar ( mc:: Upvar { kind, .. } ) => kind,
1104
+ _ => bug ! ( )
1105
+ } ;
1106
+ if kind == ty:: ClosureKind :: Fn {
1107
+ db. span_help ( self . tcx . map . span ( upvar_id. closure_expr_id ) ,
1108
+ "consider changing this closure to take \
1109
+ self by mutable reference") ;
1110
+ }
1111
+ }
1112
+ _ => {
1113
+ if let Categorization :: Deref ( ref inner_cmt, ..) = err. cmt . cat {
1114
+ if let Categorization :: Local ( local_id) = inner_cmt. cat {
1115
+ let parent = self . tcx . map . get_parent_node ( local_id) ;
1116
+ let opt_fn_decl = FnLikeNode :: from_node ( self . tcx . map . get ( parent) )
1117
+ . map ( |fn_like| fn_like. decl ( ) ) ;
1118
+
1119
+ if let Some ( fn_decl) = opt_fn_decl {
1120
+ if let Some ( ref arg) = fn_decl. inputs . iter ( )
1121
+ . find ( |ref arg| arg. pat . id == local_id) {
1122
+ if let hir:: TyRptr (
1123
+ opt_lifetime,
1124
+ hir:: MutTy { mutbl : hir:: Mutability :: MutImmutable , ref ty} ) =
1125
+ arg. ty . node {
1126
+ if let Some ( lifetime) = opt_lifetime {
1127
+ if let Ok ( snippet) = self . tcx . sess . codemap ( )
1128
+ . span_to_snippet ( ty. span ) {
1129
+ if let Ok ( lifetime_snippet) = self . tcx . sess . codemap ( )
1130
+ . span_to_snippet ( lifetime. span ) {
1131
+ db. span_label ( arg. ty . span ,
1132
+ & format ! ( "use `&{} mut {}` \
1133
+ here to make mutable",
1134
+ lifetime_snippet,
1135
+ snippet) ) ;
1136
+ }
1137
+ }
1138
+ }
1139
+ else if let Ok ( snippet) = self . tcx . sess . codemap ( )
1140
+ . span_to_snippet ( arg. ty . span ) {
1141
+ if snippet. starts_with ( "&" ) {
1142
+ db. span_label ( arg. ty . span ,
1143
+ & format ! ( "use `{}` here to make mutable" ,
1144
+ snippet. replace( "&" , "&mut " ) ) ) ;
1145
+ }
1146
+ }
1147
+ }
1148
+ }
1149
+ }
1150
+ }
1151
+ } else if let Categorization :: Local ( local_id) = err. cmt . cat {
1152
+ let span = self . tcx . map . span ( local_id) ;
1153
+ if let Ok ( snippet) = self . tcx . sess . codemap ( ) . span_to_snippet ( span) {
1154
+ if snippet. starts_with ( "ref mut " ) || snippet. starts_with ( "&mut " ) {
1155
+ db. span_label ( * error_span, & format ! ( "cannot reborrow mutably" ) ) ;
1156
+ db. span_label ( * error_span, & format ! ( "try removing `&mut` here" ) ) ;
1157
+ } else {
1158
+ if snippet. starts_with ( "ref " ) {
1159
+ db. span_label ( span, & format ! ( "use `{}` here to make mutable" ,
1160
+ snippet. replace( "ref " , "ref mut " ) ) ) ;
1161
+ } else if snippet != "self" {
1162
+ db. span_label ( span,
1163
+ & format ! ( "use `mut {}` here to make mutable" ,
1164
+ snippet) ) ;
1165
+ }
1166
+ db. span_label ( * error_span, & format ! ( "cannot borrow mutably" ) ) ;
1167
+ }
1168
+ } else {
1169
+ db. span_label ( * error_span, & format ! ( "cannot borrow mutably" ) ) ;
1170
+ }
1171
+ }
1172
+ }
1173
+ }
1174
+ }
1138
1175
pub fn append_loan_path_to_string ( & self ,
1139
1176
loan_path : & LoanPath < ' tcx > ,
1140
1177
out : & mut String ) {
0 commit comments