@@ -24,7 +24,7 @@ use self::InteriorKind::*;
2424
2525use rustc:: dep_graph:: DepNode ;
2626use rustc:: hir:: map as hir_map;
27- use rustc:: hir:: map:: blocks:: FnParts ;
27+ use rustc:: hir:: map:: blocks:: { FnParts , FnLikeNode } ;
2828use rustc:: cfg;
2929use rustc:: middle:: dataflow:: DataFlowContext ;
3030use rustc:: middle:: dataflow:: BitwiseOperator ;
@@ -970,51 +970,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
970970
971971 pub fn note_and_explain_bckerr ( & self , db : & mut DiagnosticBuilder , err : BckError < ' tcx > ,
972972 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) ,
1018975 err_out_of_scope( super_scope, sub_scope, cause) => {
1019976 let ( value_kind, value_msg) = match err. cmt . cat {
1020977 mc:: Categorization :: Rvalue ( _) =>
@@ -1135,6 +1092,86 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
11351092 }
11361093 }
11371094
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+ }
11381175 pub fn append_loan_path_to_string ( & self ,
11391176 loan_path : & LoanPath < ' tcx > ,
11401177 out : & mut String ) {
0 commit comments