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