diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 9df55e5206163..d2e04ef31c86a 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -170,6 +170,40 @@ impl<'hir> MapEntry<'hir> { }) } + fn fn_decl(&self) -> Option<&FnDecl> { + match self { + EntryItem(_, _, ref item) => { + match item.node { + ItemFn(ref fn_decl, _, _, _, _, _) => Some(&fn_decl), + _ => None, + } + } + + EntryTraitItem(_, _, ref item) => { + match item.node { + TraitItemKind::Method(ref method_sig, _) => Some(&method_sig.decl), + _ => None + } + } + + EntryImplItem(_, _, ref item) => { + match item.node { + ImplItemKind::Method(ref method_sig, _) => Some(&method_sig.decl), + _ => None, + } + } + + EntryExpr(_, _, ref expr) => { + match expr.node { + ExprClosure(_, ref fn_decl, ..) => Some(&fn_decl), + _ => None, + } + } + + _ => None + } + } + fn associated_body(self) -> Option { match self { EntryItem(_, _, item) => { @@ -502,6 +536,14 @@ impl<'hir> Map<'hir> { self.forest.krate.body(id) } + pub fn fn_decl(&self, node_id: ast::NodeId) -> Option { + if let Some(entry) = self.find_entry(node_id) { + entry.fn_decl().map(|fd| fd.clone()) + } else { + bug!("no entry for node_id `{}`", node_id) + } + } + /// Returns the `NodeId` that corresponds to the definition of /// which this is the body of, i.e. a `fn`, `const` or `static` /// item (possibly associated), a closure, or a `hir::AnonConst`. diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index b2ff36cb87c78..20a0df2a17177 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -228,7 +228,7 @@ impl<'tcx> Mir<'tcx> { pub fn temps_iter<'a>(&'a self) -> impl Iterator + 'a { (self.arg_count+1..self.local_decls.len()).filter_map(move |index| { let local = Local::new(index); - if self.local_decls[local].is_user_variable { + if self.local_decls[local].is_user_variable.is_some() { None } else { Some(local) @@ -241,7 +241,7 @@ impl<'tcx> Mir<'tcx> { pub fn vars_iter<'a>(&'a self) -> impl Iterator + 'a { (self.arg_count+1..self.local_decls.len()).filter_map(move |index| { let local = Local::new(index); - if self.local_decls[local].is_user_variable { + if self.local_decls[local].is_user_variable.is_some() { Some(local) } else { None @@ -255,7 +255,7 @@ impl<'tcx> Mir<'tcx> { (1..self.local_decls.len()).filter_map(move |index| { let local = Local::new(index); let decl = &self.local_decls[local]; - if (decl.is_user_variable || index < self.arg_count + 1) + if (decl.is_user_variable.is_some() || index < self.arg_count + 1) && decl.mutability == Mutability::Mut { Some(local) @@ -351,7 +351,7 @@ impl<'tcx> IndexMut for Mir<'tcx> { } } -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] pub enum ClearCrossCrate { Clear, Set(T) @@ -382,6 +382,16 @@ pub enum Mutability { Not, } +impl From for hir::Mutability { + fn from(m: Mutability) -> Self { + match m { + Mutability::Mut => hir::MutMutable, + Mutability::Not => hir::MutImmutable, + } + } +} + + #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. @@ -463,6 +473,33 @@ pub enum LocalKind { ReturnPointer, } +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +pub struct VarBindingForm { + /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`? + pub binding_mode: ty::BindingMode, + /// If an explicit type was provided for this variable binding, + /// this holds the source Span of that type. + /// + /// NOTE: If you want to change this to a `HirId`, be wary that + /// doing so breaks incremental compilation (as of this writing), + /// while a `Span` does not cause our tests to fail. + pub opt_ty_info: Option, +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +pub enum BindingForm { + /// This is a binding for a non-`self` binding, or a `self` that has an explicit type. + Var(VarBindingForm), + /// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit. + ImplicitSelf, +} + +CloneTypeFoldableAndLiftImpls! { BindingForm, } + +impl_stable_hash_for!(struct self::VarBindingForm { binding_mode, opt_ty_info }); + +impl_stable_hash_for!(enum self::BindingForm { Var(binding), ImplicitSelf, }); + /// A MIR local. /// /// This can be a binding declared by the user, a temporary inserted by the compiler, a function @@ -474,8 +511,14 @@ pub struct LocalDecl<'tcx> { /// Temporaries and the return place are always mutable. pub mutability: Mutability, - /// True if this corresponds to a user-declared local variable. - pub is_user_variable: bool, + /// Some(binding_mode) if this corresponds to a user-declared local variable. + /// + /// This is solely used for local diagnostics when generating + /// warnings/errors when compiling the current crate, and + /// therefore it need not be visible across crates. pnkfelix + /// currently hypothesized we *need* to wrap this in a + /// `ClearCrossCrate` as long as it carries as `HirId`. + pub is_user_variable: Option>, /// True if this is an internal local /// @@ -592,6 +635,45 @@ pub struct LocalDecl<'tcx> { } impl<'tcx> LocalDecl<'tcx> { + /// Returns true only if local is a binding that can itself be + /// made mutable via the addition of the `mut` keyword, namely + /// something like the occurrences of `x` in: + /// - `fn foo(x: Type) { ... }`, + /// - `let x = ...`, + /// - or `match ... { C(x) => ... }` + pub fn can_be_made_mutable(&self) -> bool + { + match self.is_user_variable { + Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + binding_mode: ty::BindingMode::BindByValue(_), + opt_ty_info: _, + }))) => true, + + // FIXME: might be able to thread the distinction between + // `self`/`mut self`/`&self`/`&mut self` into the + // `BindingForm::ImplicitSelf` variant, (and then return + // true here for solely the first case). + _ => false, + } + } + + /// Returns true if local is definitely not a `ref ident` or + /// `ref mut ident` binding. (Such bindings cannot be made into + /// mutable bindings, but the inverse does not necessarily hold). + pub fn is_nonref_binding(&self) -> bool + { + match self.is_user_variable { + Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + binding_mode: ty::BindingMode::BindByValue(_), + opt_ty_info: _, + }))) => true, + + Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf)) => true, + + _ => false, + } + } + /// Create a new `LocalDecl` for a temporary. #[inline] pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self { @@ -605,7 +687,7 @@ impl<'tcx> LocalDecl<'tcx> { }, visibility_scope: OUTERMOST_SOURCE_SCOPE, internal: false, - is_user_variable: false + is_user_variable: None, } } @@ -622,7 +704,7 @@ impl<'tcx> LocalDecl<'tcx> { }, visibility_scope: OUTERMOST_SOURCE_SCOPE, internal: true, - is_user_variable: false + is_user_variable: None, } } @@ -641,7 +723,7 @@ impl<'tcx> LocalDecl<'tcx> { visibility_scope: OUTERMOST_SOURCE_SCOPE, internal: false, name: None, // FIXME maybe we do want some name here? - is_user_variable: false + is_user_variable: None, } } } diff --git a/src/librustc/ty/binding.rs b/src/librustc/ty/binding.rs index 3db61b76cc55c..971b3c3d14aeb 100644 --- a/src/librustc/ty/binding.rs +++ b/src/librustc/ty/binding.rs @@ -18,6 +18,8 @@ pub enum BindingMode { BindByValue(Mutability), } +CloneTypeFoldableAndLiftImpls! { BindingMode, } + impl BindingMode { pub fn convert(ba: BindingAnnotation) -> BindingMode { match ba { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 9061af1b68ca4..38d1ac2cb4ad0 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -593,11 +593,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.emit(); } + /// Reports an illegal reassignment; for example, an assignment to + /// (part of) a non-`mut` local that occurs potentially after that + /// local has already been initialized. `place` is the path being + /// assigned; `err_place` is a place providing a reason why + /// `place` is not mutable (e.g. the non-`mut` local `x` in an + /// assignment to `x.f`). pub(super) fn report_illegal_reassignment( &mut self, _context: Context, (place, span): (&Place<'tcx>, Span), assigned_span: Span, + err_place: &Place<'tcx>, ) { let is_arg = if let Place::Local(local) = place { if let LocalKind::Arg = self.mir.local_kind(*local) { @@ -621,9 +628,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "cannot assign twice to immutable variable" }; if span != assigned_span { - if is_arg { - err.span_label(assigned_span, "argument not declared as `mut`"); - } else { + if !is_arg { let value_msg = match self.describe_place(place) { Some(name) => format!("`{}`", name), None => "value".to_owned(), @@ -631,6 +636,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(assigned_span, format!("first assignment to {}", value_msg)); } } + if let Place::Local(local) = err_place { + let local_decl = &self.mir.local_decls[*local]; + if let Some(name) = local_decl.name { + if local_decl.can_be_made_mutable() { + err.span_label(local_decl.source_info.span, + format!("consider changing this to `mut {}`", name)); + } + } + } err.span_label(span, msg); err.emit(); } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index c43ea0360ee13..122b2df4766ad 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -18,7 +18,7 @@ use rustc::infer::InferCtxt; use rustc::ty::{self, ParamEnv, TyCtxt}; use rustc::ty::query::Providers; use rustc::lint::builtin::UNUSED_MUT; -use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; +use rustc::mir::{self, AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc::mir::{ClearCrossCrate, Local, Location, Place, Mir, Mutability, Operand}; use rustc::mir::{Projection, ProjectionElem, Rvalue, Field, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; @@ -278,7 +278,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // to the set. let temporary_used_locals: FxHashSet = mbcx.used_mut.iter() - .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable) + .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some()) .cloned() .collect(); @@ -1398,9 +1398,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ) { debug!("check_if_reassignment_to_immutable_state({:?})", place); // determine if this path has a non-mut owner (and thus needs checking). - if let Ok(..) = self.is_mutable(place, LocalMutationIsAllowed::No) { - return; - } + let err_place = match self.is_mutable(place, LocalMutationIsAllowed::No) { + Ok(..) => return, + Err(place) => place, + }; debug!( "check_if_reassignment_to_immutable_state({:?}) - is an imm local", place @@ -1410,7 +1411,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let init = self.move_data.inits[i]; let init_place = &self.move_data.move_paths[init.path].place; if places_conflict(self.tcx, self.mir, &init_place, place, Deep) { - self.report_illegal_reassignment(context, (place, span), init.span); + self.report_illegal_reassignment(context, (place, span), init.span, err_place); break; } } @@ -1658,36 +1659,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - fn specialized_description(&self, place:&Place<'tcx>) -> Option{ - if let Some(_name) = self.describe_place(place) { - Some(format!("data in a `&` reference")) - } else { - None - } - } - - fn get_default_err_msg(&self, place:&Place<'tcx>) -> String{ - match self.describe_place(place) { - Some(name) => format!("immutable item `{}`", name), - None => "immutable item".to_owned(), - } - } - - fn get_secondary_err_msg(&self, place:&Place<'tcx>) -> String{ - match self.specialized_description(place) { - Some(_) => format!("data in a `&` reference"), - None => self.get_default_err_msg(place) - } - } - - fn get_primary_err_msg(&self, place:&Place<'tcx>) -> String{ - if let Some(name) = self.describe_place(place) { - format!("`{}` is a `&` reference, so the data it refers to cannot be written", name) - } else { - format!("cannot assign through `&`-reference") - } - } - /// Check the permissions for the given place and read or write kind /// /// Returns true if an error is reported, false otherwise. @@ -1702,7 +1673,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "check_access_permissions({:?}, {:?}, {:?})", place, kind, is_local_mutation_allowed ); - let mut error_reported = false; + + #[derive(Copy, Clone, Debug)] + enum AccessKind { + MutableBorrow, + Mutate, + } + let error_access; + let the_place_err; + match kind { Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Unique)) | Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. })) @@ -1715,91 +1694,29 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { BorrowKind::Shared => unreachable!(), }; match self.is_mutable(place, is_local_mutation_allowed) { - Ok(root_place) => self.add_used_mut(root_place, flow_state), + Ok(root_place) => { + self.add_used_mut(root_place, flow_state); + return false; + } Err(place_err) => { - error_reported = true; - let item_msg = self.get_default_err_msg(place); - let mut err = self.tcx - .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir); - err.span_label(span, "cannot borrow as mutable"); - - if place != place_err { - if let Some(name) = self.describe_place(place_err) { - err.note(&format!("the value which is causing this path not to be \ - mutable is...: `{}`", name)); - } - } - - err.emit(); + error_access = AccessKind::MutableBorrow; + the_place_err = place_err; } } } Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => { match self.is_mutable(place, is_local_mutation_allowed) { - Ok(root_place) => self.add_used_mut(root_place, flow_state), + Ok(root_place) => { + self.add_used_mut(root_place, flow_state); + return false; + } Err(place_err) => { - error_reported = true; - - let err_info = if let Place::Projection( - box Projection { - base: Place::Local(local), - elem: ProjectionElem::Deref - } - ) = *place_err { - let locations = self.mir.find_assignments(local); - if locations.len() > 0 { - let item_msg = if error_reported { - self.get_secondary_err_msg(&Place::Local(local)) - } else { - self.get_default_err_msg(place) - }; - let sp = self.mir.source_info(locations[0]).span; - let mut to_suggest_span = String::new(); - if let Ok(src) = - self.tcx.sess.codemap().span_to_snippet(sp) { - to_suggest_span = src[1..].to_string(); - }; - Some((sp, - "consider changing this to be a \ - mutable reference", - to_suggest_span, - item_msg, - self.get_primary_err_msg(&Place::Local(local)))) - } else { - None - } - } else { - None - }; - - if let Some((err_help_span, - err_help_stmt, - to_suggest_span, - item_msg, - sec_span)) = err_info { - let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir); - err.span_suggestion(err_help_span, - err_help_stmt, - format!("&mut {}", to_suggest_span)); - if place != place_err { - err.span_label(span, sec_span); - } - err.emit() - } else { - let item_msg = self.get_default_err_msg(place); - let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir); - err.span_label(span, "cannot mutate"); - if place != place_err { - if let Some(name) = self.describe_place(place_err) { - err.note(&format!("the value which is causing this path not \ - to be mutable is...: `{}`", name)); - } - } - err.emit(); - } + error_access = AccessKind::Mutate; + the_place_err = place_err; } } } + Reservation(WriteKind::Move) | Write(WriteKind::Move) | Reservation(WriteKind::StorageDeadOrDrop) @@ -1815,15 +1732,174 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ), ); } + return false; + } + Activation(..) => { + // permission checks are done at Reservation point. + return false; } - Activation(..) => {} // permission checks are done at Reservation point. Read(ReadKind::Borrow(BorrowKind::Unique)) | Read(ReadKind::Borrow(BorrowKind::Mut { .. })) | Read(ReadKind::Borrow(BorrowKind::Shared)) - | Read(ReadKind::Copy) => {} // Access authorized + | Read(ReadKind::Copy) => { + // Access authorized + return false; + } } - error_reported + // at this point, we have set up the error reporting state. + + let mut err; + let item_msg = match self.describe_place(place) { + Some(name) => format!("immutable item `{}`", name), + None => "immutable item".to_owned(), + }; + + // `act` and `acted_on` are strings that let us abstract over + // the verbs used in some diagnostic messages. + let act; let acted_on; + + match error_access { + AccessKind::Mutate => { + let item_msg = match the_place_err { + Place::Projection(box Projection { + base: _, + elem: ProjectionElem::Deref } + ) => match self.describe_place(place) { + Some(description) => + format!("`{}` which is behind a `&` reference", description), + None => format!("data in a `&` reference"), + }, + _ => item_msg, + }; + err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir); + act = "assign"; acted_on = "written"; + } + AccessKind::MutableBorrow => { + err = self.tcx + .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir); + act = "borrow as mutable"; acted_on = "borrowed as mutable"; + } + } + + match the_place_err { + // We want to suggest users use `let mut` for local (user + // variable) mutations... + Place::Local(local) if self.mir.local_decls[*local].can_be_made_mutable() => { + // ... but it doesn't make sense to suggest it on + // variables that are `ref x`, `ref mut x`, `&self`, + // or `&mut self` (such variables are simply not + // mutable).. + let local_decl = &self.mir.local_decls[*local]; + assert_eq!(local_decl.mutability, Mutability::Not); + + err.span_label(span, format!("cannot {ACT}", ACT=act)); + err.span_suggestion(local_decl.source_info.span, + "consider changing this to be mutable", + format!("mut {}", local_decl.name.unwrap())); + } + + // complete hack to approximate old AST-borrowck + // diagnostic: if the span starts with a mutable borrow of + // a local variable, then just suggest the user remove it. + Place::Local(_) if { + if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { + snippet.starts_with("&mut ") + } else { + false + } + } => { + err.span_label(span, format!("cannot {ACT}", ACT=act)); + err.span_label(span, "try removing `&mut` here"); + } + + // We want to point out when a `&` can be readily replaced + // with an `&mut`. + // + // FIXME: can this case be generalized to work for an + // arbitrary base for the projection? + Place::Projection(box Projection { base: Place::Local(local), + elem: ProjectionElem::Deref }) + if self.mir.local_decls[*local].is_nonref_binding() => + { + let (err_help_span, suggested_code) = + find_place_to_suggest_ampmut(self.tcx, self.mir, *local); + err.span_suggestion(err_help_span, + "consider changing this to be a mutable reference", + suggested_code); + + let local_decl = &self.mir.local_decls[*local]; + if let Some(name) = local_decl.name { + err.span_label( + span, format!("`{NAME}` is a `&` reference, \ + so the data it refers to cannot be {ACTED_ON}", + NAME=name, ACTED_ON=acted_on)); + } else { + err.span_label(span, format!("cannot {ACT} through `&`-reference", ACT=act)); + } + } + + _ => { + err.span_label(span, format!("cannot {ACT}", ACT=act)); + } + } + + err.emit(); + return true; + + // Returns the span to highlight and the associated text to + // present when suggesting that the user use an `&mut`. + // + // When we want to suggest a user change a local variable to be a `&mut`, there + // are three potential "obvious" things to highlight: + // + // let ident [: Type] [= RightHandSideExresssion]; + // ^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ + // (1.) (2.) (3.) + // + // We can always fallback on highlighting the first. But chances are good that + // the user experience will be better if we highlight one of the others if possible; + // for example, if the RHS is present and the Type is not, then the type is going to + // be inferred *from* the RHS, which means we should highlight that (and suggest + // that they borrow the RHS mutably). + fn find_place_to_suggest_ampmut<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>, + mir: &Mir<'tcx>, + local: Local) -> (Span, String) + { + // This implementation attempts to emulate AST-borrowck prioritization + // by trying (3.), then (2.) and finally falling back on (1.). + let locations = mir.find_assignments(local); + if locations.len() > 0 { + let assignment_rhs_span = mir.source_info(locations[0]).span; + let snippet = tcx.sess.codemap().span_to_snippet(assignment_rhs_span); + if let Ok(src) = snippet { + // pnkfelix inherited code; believes intention is + // highlighted text will always be `&` and + // thus can transform to `&mut` by slicing off + // first ASCII character and prepending "&mut ". + let borrowed_expr = src[1..].to_string(); + return (assignment_rhs_span, format!("&mut {}", borrowed_expr)); + } + } + + let local_decl = &mir.local_decls[local]; + let highlight_span = match local_decl.is_user_variable { + // if this is a variable binding with an explicit type, + // try to highlight that for the suggestion. + Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { + opt_ty_info: Some(ty_span), .. }))) => ty_span, + + Some(ClearCrossCrate::Clear) => bug!("saw cleared local state"), + + // otherwise, just highlight the span associated with + // the (MIR) LocalDecl. + _ => local_decl.source_info.span, + }; + + let ty_mut = local_decl.ty.builtin_deref(true).unwrap(); + assert_eq!(ty_mut.mutbl, hir::MutImmutable); + return (highlight_span, format!("&mut {}", ty_mut.ty)); + } } /// Adds the place into the used mutable variables set diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 7096f91dc1ddb..0fd55f752b84f 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -137,7 +137,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| { + this.visit_bindings(&pattern, &mut |this, _, _, _, node, span, _| { this.storage_live_binding(block, node, span, OutsideGuard); this.schedule_drop_for_binding(node, span, OutsideGuard); }) diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index fbd771fbe500d..94b387abe3c13 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -249,7 +249,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { source_info, visibility_scope: source_info.scope, internal: true, - is_user_variable: false + is_user_variable: None, }); let ptr_temp = Place::Local(ptr_temp); let block = unpack!(this.into(&ptr_temp, block, ptr)); diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 062a48a8c434d..b6af0ed2a4a1c 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -307,7 +307,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { assert!(!(visibility_scope.is_some() && lint_level.is_explicit()), "can't have both a visibility and a lint scope at the same time"); let mut scope = self.source_scope; - self.visit_bindings(pattern, &mut |this, mutability, name, var, span, ty| { + self.visit_bindings(pattern, &mut |this, mutability, name, mode, var, span, ty| { if visibility_scope.is_none() { visibility_scope = Some(this.new_source_scope(scope_span, LintLevel::Inherited, @@ -325,7 +325,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { scope, }; let visibility_scope = visibility_scope.unwrap(); - this.declare_binding(source_info, visibility_scope, mutability, name, var, + this.declare_binding(source_info, visibility_scope, mutability, name, mode, var, ty, has_guard); }); visibility_scope @@ -359,11 +359,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } pub fn visit_bindings(&mut self, pattern: &Pattern<'tcx>, f: &mut F) - where F: FnMut(&mut Self, Mutability, Name, NodeId, Span, Ty<'tcx>) + where F: FnMut(&mut Self, Mutability, Name, BindingMode, NodeId, Span, Ty<'tcx>) { match *pattern.kind { - PatternKind::Binding { mutability, name, var, ty, ref subpattern, .. } => { - f(self, mutability, name, var, pattern.span, ty); + PatternKind::Binding { mutability, name, mode, var, ty, ref subpattern, .. } => { + f(self, mutability, name, mode, var, pattern.span, ty); if let Some(subpattern) = subpattern.as_ref() { self.visit_bindings(subpattern, f); } @@ -1118,15 +1118,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { visibility_scope: SourceScope, mutability: Mutability, name: Name, + mode: BindingMode, var_id: NodeId, var_ty: Ty<'tcx>, has_guard: ArmHasGuard) { - debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, visibility_scope={:?}, \ - source_info={:?})", - var_id, name, var_ty, visibility_scope, source_info); + debug!("declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \ + visibility_scope={:?}, source_info={:?})", + var_id, name, mode, var_ty, visibility_scope, source_info); let tcx = self.hir.tcx(); + let binding_mode = match mode { + BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()), + BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()), + }; let local = LocalDecl::<'tcx> { mutability, ty: var_ty.clone(), @@ -1134,7 +1139,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { source_info, visibility_scope, internal: false, - is_user_variable: true, + is_user_variable: Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + binding_mode, + // hypothetically, `visit_bindings` could try to unzip + // an outermost hir::Ty as we descend, matching up + // idents in pat; but complex w/ unclear UI payoff. + // Instead, just abandon providing diagnostic info. + opt_ty_info: None, + }))), }; let for_arm_body = self.local_decls.push(local.clone()); let locals = if has_guard.0 && tcx.all_pat_vars_are_implicit_refs_within_guards() { @@ -1145,8 +1157,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { name: Some(name), source_info, visibility_scope, + // FIXME: should these secretly injected ref_for_guard's be marked as `internal`? internal: false, - is_user_variable: true, + is_user_variable: None, }); LocalsForNode::Three { val_for_guard, ref_for_guard, for_arm_body } } else { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index ca7a2daf39d2e..8567141461803 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -70,11 +70,11 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t // HACK(eddyb) Avoid having RustCall on closures, // as it adds unnecessary (and wrong) auto-tupling. abi = Abi::Rust; - Some((liberated_closure_env_ty(tcx, id, body_id), None)) + Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)) } ty::TyGenerator(..) => { let gen_ty = tcx.body_tables(body_id).node_id_to_type(fn_hir_id); - Some((gen_ty, None)) + Some(ArgInfo(gen_ty, None, None, None)) } _ => None, }; @@ -91,7 +91,23 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t .iter() .enumerate() .map(|(index, arg)| { - (fn_sig.inputs()[index], Some(&*arg.pat)) + let owner_id = tcx.hir.body_owner(body_id); + let opt_ty_info; + let self_arg; + if let Some(ref fn_decl) = tcx.hir.fn_decl(owner_id) { + let ty_hir_id = fn_decl.inputs[index].hir_id; + let ty_span = tcx.hir.span(tcx.hir.hir_to_node_id(ty_hir_id)); + opt_ty_info = Some(ty_span); + self_arg = if index == 0 && fn_decl.has_implicit_self { + Some(ImplicitSelfBinding) + } else { + None + }; + } else { + opt_ty_info = None; + self_arg = None; + } + ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg) }); let arguments = implicit_argument.into_iter().chain(explicit_arguments); @@ -433,6 +449,13 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, /////////////////////////////////////////////////////////////////////////// /// the main entry point for building MIR for a function +struct ImplicitSelfBinding; + +struct ArgInfo<'gcx>(Ty<'gcx>, + Option, + Option<&'gcx hir::Pat>, + Option); + fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, fn_id: ast::NodeId, arguments: A, @@ -442,7 +465,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, yield_ty: Option>, body: &'gcx hir::Body) -> Mir<'tcx> - where A: Iterator, Option<&'gcx hir::Pat>)> + where A: Iterator> { let arguments: Vec<_> = arguments.collect(); @@ -642,13 +665,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn args_and_body(&mut self, mut block: BasicBlock, - arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)], + arguments: &[ArgInfo<'gcx>], argument_scope: region::Scope, ast_body: &'gcx hir::Expr) -> BlockAnd<()> { // Allocate locals for the function arguments - for &(ty, pattern) in arguments.iter() { + for &ArgInfo(ty, _, pattern, _) in arguments.iter() { // If this is a simple binding pattern, give the local a nice name for debuginfo. let mut name = None; if let Some(pat) = pattern { @@ -668,16 +691,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { visibility_scope: source_info.scope, name, internal: false, - is_user_variable: false, + is_user_variable: None, }); } let mut scope = None; // Bind the argument patterns - for (index, &(ty, pattern)) in arguments.iter().enumerate() { + for (index, arg_info) in arguments.iter().enumerate() { // Function arguments always get the first Local indices after the return place let local = Local::new(index + 1); let place = Place::Local(local); + let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info; if let Some(pattern) = pattern { let pattern = self.hir.pattern_from_hir(pattern); @@ -686,6 +710,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Don't introduce extra copies for simple bindings PatternKind::Binding { mutability, var, mode: BindingMode::ByValue, .. } => { self.local_decls[local].mutability = mutability; + self.local_decls[local].is_user_variable = + if let Some(ImplicitSelfBinding) = self_binding { + Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf)) + } else { + let binding_mode = ty::BindingMode::BindByValue(mutability.into()); + Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + binding_mode, opt_ty_info }))) + }; self.var_indices.insert(var, LocalsForNode::One(local)); } _ => { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index f11d80201c28b..c703486560dcd 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -144,7 +144,7 @@ fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl { source_info, visibility_scope: source_info.scope, internal: false, - is_user_variable: false + is_user_variable: None, } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 7ac3b7beb06d5..a6017fafcc8d4 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -303,7 +303,7 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>, source_info, visibility_scope: source_info.scope, internal: false, - is_user_variable: false, + is_user_variable: None, }; let new_ret_local = Local::new(mir.local_decls.len()); mir.local_decls.push(new_ret); @@ -644,7 +644,7 @@ fn create_generator_drop_shim<'a, 'tcx>( source_info, visibility_scope: source_info.scope, internal: false, - is_user_variable: false, + is_user_variable: None, }; make_generator_state_argument_indirect(tcx, def_id, &mut mir); @@ -660,7 +660,7 @@ fn create_generator_drop_shim<'a, 'tcx>( source_info, visibility_scope: source_info.scope, internal: false, - is_user_variable: false, + is_user_variable: None, }; no_landing_pads(tcx, &mut mir); diff --git a/src/test/compile-fail/assign-imm-local-twice.rs b/src/test/compile-fail/assign-imm-local-twice.rs index d5e412c3745e0..ee9dafdd49eb8 100644 --- a/src/test/compile-fail/assign-imm-local-twice.rs +++ b/src/test/compile-fail/assign-imm-local-twice.rs @@ -13,6 +13,7 @@ fn test() { let v: isize; + //[mir]~^ NOTE consider changing this to `mut v` v = 1; //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment println!("v={}", v); diff --git a/src/test/compile-fail/borrowck/borrowck-issue-14498.rs b/src/test/compile-fail/borrowck/borrowck-issue-14498.rs index fbdd013024db5..3c5f932af47ce 100644 --- a/src/test/compile-fail/borrowck/borrowck-issue-14498.rs +++ b/src/test/compile-fail/borrowck/borrowck-issue-14498.rs @@ -27,7 +27,7 @@ fn indirect_write_to_imm_box() { let y: Box<_> = box &mut x; let p = &y; ***p = 2; //[ast]~ ERROR cannot assign to data in a `&` reference - //[mir]~^ ERROR cannot assign to data in a `&` reference + //[mir]~^ ERROR cannot assign to `***p` drop(p); } diff --git a/src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs b/src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs index 109fe3d1128e1..f4f40e0407fde 100644 --- a/src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs +++ b/src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs @@ -70,6 +70,6 @@ fn main() { }; s[2] = 20; //[ast]~^ ERROR cannot assign to immutable indexed content - //[mir]~^^ ERROR cannot assign to immutable item + //[mir]~^^ ERROR cannot assign to data in a `&` reference drop(rs); } diff --git a/src/test/compile-fail/issue-45199.rs b/src/test/compile-fail/issue-45199.rs index ecddb4c101fdf..61e19ffc0d293 100644 --- a/src/test/compile-fail/issue-45199.rs +++ b/src/test/compile-fail/issue-45199.rs @@ -13,6 +13,7 @@ fn test_drop_replace() { let b: Box; + //[mir]~^ NOTE consider changing this to `mut b` b = Box::new(1); //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable @@ -24,6 +25,7 @@ fn test_drop_replace() { fn test_call() { let b = Box::new(1); //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment + //[mir]~| NOTE consider changing this to `mut b` b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable //[mir]~^ ERROR cannot assign twice to immutable variable `b` //[ast]~| NOTE cannot assign twice to immutable @@ -31,7 +33,7 @@ fn test_call() { } fn test_args(b: Box) { //[ast]~ NOTE first assignment - //[mir]~^ NOTE argument not declared as `mut` + //[mir]~^ NOTE consider changing this to `mut b` b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable //[mir]~^ ERROR cannot assign to immutable argument `b` //[ast]~| NOTE cannot assign twice to immutable diff --git a/src/test/compile-fail/liveness-assign-imm-local-in-loop.rs b/src/test/compile-fail/liveness-assign-imm-local-in-loop.rs index f28906ddb955f..7bc3680ca7723 100644 --- a/src/test/compile-fail/liveness-assign-imm-local-in-loop.rs +++ b/src/test/compile-fail/liveness-assign-imm-local-in-loop.rs @@ -13,6 +13,7 @@ fn test() { let v: isize; + //[mir]~^ NOTE consider changing this to `mut v` loop { v = 1; //[ast]~ ERROR cannot assign twice to immutable variable //[mir]~^ ERROR cannot assign twice to immutable variable `v` diff --git a/src/test/compile-fail/liveness-assign-imm-local-in-op-eq.rs b/src/test/compile-fail/liveness-assign-imm-local-in-op-eq.rs index 594cc0761214a..7812cdd8684f6 100644 --- a/src/test/compile-fail/liveness-assign-imm-local-in-op-eq.rs +++ b/src/test/compile-fail/liveness-assign-imm-local-in-op-eq.rs @@ -13,6 +13,7 @@ fn test() { let v: isize; + //[mir]~^ NOTE consider changing this to `mut v` v = 2; //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment v += 1; //[ast]~ ERROR cannot assign twice to immutable variable diff --git a/src/test/compile-fail/liveness-assign-imm-local-with-drop.rs b/src/test/compile-fail/liveness-assign-imm-local-with-drop.rs index b4fb33ca15e26..bb61a9037d906 100644 --- a/src/test/compile-fail/liveness-assign-imm-local-with-drop.rs +++ b/src/test/compile-fail/liveness-assign-imm-local-with-drop.rs @@ -14,6 +14,7 @@ fn test() { let b = Box::new(1); //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment + //[mir]~| NOTE consider changing this to `mut b` drop(b); b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable //[mir]~^ ERROR cannot assign twice to immutable variable `b` diff --git a/src/test/compile-fail/liveness-assign-imm-local-with-init.rs b/src/test/compile-fail/liveness-assign-imm-local-with-init.rs index 7204b5d5f2e16..672e9fab83743 100644 --- a/src/test/compile-fail/liveness-assign-imm-local-with-init.rs +++ b/src/test/compile-fail/liveness-assign-imm-local-with-init.rs @@ -14,6 +14,7 @@ fn test() { let v: isize = 1; //[ast]~ NOTE first assignment //[mir]~^ NOTE first assignment + //[mir]~| NOTE consider changing this to `mut v` v.clone(); v = 2; //[ast]~ ERROR cannot assign twice to immutable variable //[mir]~^ ERROR cannot assign twice to immutable variable `v` diff --git a/src/test/compile-fail/unboxed-closures-mutated-upvar-from-fn-closure.rs b/src/test/compile-fail/unboxed-closures-mutated-upvar-from-fn-closure.rs index 0dbd61413e053..f20719ec7fab7 100644 --- a/src/test/compile-fail/unboxed-closures-mutated-upvar-from-fn-closure.rs +++ b/src/test/compile-fail/unboxed-closures-mutated-upvar-from-fn-closure.rs @@ -23,6 +23,6 @@ fn main() { call(|| { counter += 1; //[ast]~^ ERROR cannot assign to data in a captured outer variable in an `Fn` closure - //[mir]~^^ ERROR cannot assign to immutable item `counter` + //[mir]~^^ ERROR cannot assign to `counter` }); } diff --git a/src/test/ui/asm-out-assign-imm.nll.stderr b/src/test/ui/asm-out-assign-imm.nll.stderr new file mode 100644 index 0000000000000..fbd58cd4c2260 --- /dev/null +++ b/src/test/ui/asm-out-assign-imm.nll.stderr @@ -0,0 +1,14 @@ +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/asm-out-assign-imm.rs:33:9 + | +LL | let x: isize; + | - consider changing this to `mut x` +LL | x = 1; + | ----- first assignment to `x` +... +LL | asm!("mov $1, $0" : "=r"(x) : "r"(5)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0384`. diff --git a/src/test/ui/augmented-assignments.nll.stderr b/src/test/ui/augmented-assignments.nll.stderr index deb2e7ed4a33d..592f666eff8f3 100644 --- a/src/test/ui/augmented-assignments.nll.stderr +++ b/src/test/ui/augmented-assignments.nll.stderr @@ -17,6 +17,9 @@ LL | | x; //~ value moved here error[E0596]: cannot borrow immutable item `y` as mutable --> $DIR/augmented-assignments.rs:30:5 | +LL | let y = Int(2); + | - help: consider changing this to be mutable: `mut y` +LL | //~^ consider changing this to `mut y` LL | y //~ error: cannot borrow immutable local variable `y` as mutable | ^ cannot borrow as mutable diff --git a/src/test/ui/borrowck/immutable-arg.stderr b/src/test/ui/borrowck/immutable-arg.stderr index b7506849b817d..1cf68795bf07f 100644 --- a/src/test/ui/borrowck/immutable-arg.stderr +++ b/src/test/ui/borrowck/immutable-arg.stderr @@ -10,7 +10,7 @@ error[E0384]: cannot assign to immutable argument `_x` (Mir) --> $DIR/immutable-arg.rs:14:5 | LL | fn foo(_x: u32) { - | -- argument not declared as `mut` + | -- consider changing this to `mut _x` LL | _x = 4; | ^^^^^^ cannot assign to immutable argument diff --git a/src/test/ui/borrowck/issue-45983.nll.stderr b/src/test/ui/borrowck/issue-45983.nll.stderr index 1aec71fee347b..a008a408d9711 100644 --- a/src/test/ui/borrowck/issue-45983.nll.stderr +++ b/src/test/ui/borrowck/issue-45983.nll.stderr @@ -14,13 +14,13 @@ error[E0594]: cannot assign to immutable item `x` --> $DIR/issue-45983.rs:17:18 | LL | give_any(|y| x = Some(y)); - | ^^^^^^^^^^^ cannot mutate - | - = note: the value which is causing this path not to be mutable is...: `x` + | ^^^^^^^^^^^ cannot assign error[E0596]: cannot borrow immutable item `x` as mutable --> $DIR/issue-45983.rs:17:14 | +LL | let x = None; + | - help: consider changing this to be mutable: `mut x` LL | give_any(|y| x = Some(y)); | ^^^^^^^^^^^^^^^ cannot borrow as mutable diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr b/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr index f8b84bce04ecf..0674c8230165a 100644 --- a/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr +++ b/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr @@ -1,6 +1,8 @@ error[E0596]: cannot borrow immutable item `b` as mutable --> $DIR/mut-borrow-of-mut-ref.rs:18:7 | +LL | fn f(b: &mut i32) { + | - help: consider changing this to be mutable: `mut b` LL | g(&mut b) //~ ERROR cannot borrow | ^^^^^^ cannot borrow as mutable diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr index 4526616e48899..da0b201f5d4e1 100644 --- a/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr +++ b/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr @@ -1,6 +1,9 @@ error[E0596]: cannot borrow immutable item `x` as mutable --> $DIR/huge_multispan_highlight.rs:100:13 | +LL | let x = "foo"; + | - help: consider changing this to be mutable: `mut x` +... LL | let y = &mut x; //~ ERROR cannot borrow | ^^^^^^ cannot borrow as mutable diff --git a/src/test/ui/command-line-diagnostics.nll.stderr b/src/test/ui/command-line-diagnostics.nll.stderr index 2d5a31f0586b1..10dcf7d0e657a 100644 --- a/src/test/ui/command-line-diagnostics.nll.stderr +++ b/src/test/ui/command-line-diagnostics.nll.stderr @@ -2,7 +2,9 @@ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/command-line-diagnostics.rs:16:5 | LL | let x = 42; - | -- first assignment to `x` + | - -- first assignment to `x` + | | + | consider changing this to `mut x` LL | x = 43; | ^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/did_you_mean/issue-31424.nll.stderr b/src/test/ui/did_you_mean/issue-31424.nll.stderr index 6b63f64c699e2..21c5e3608c00b 100644 --- a/src/test/ui/did_you_mean/issue-31424.nll.stderr +++ b/src/test/ui/did_you_mean/issue-31424.nll.stderr @@ -7,6 +7,8 @@ LL | (&mut self).bar(); //~ ERROR cannot borrow error[E0596]: cannot borrow immutable item `self` as mutable --> $DIR/issue-31424.rs:23:9 | +LL | fn bar(self: &mut Self) { + | ---- help: consider changing this to be mutable: `mut self` LL | (&mut self).bar(); //~ ERROR cannot borrow | ^^^^^^^^^^^ cannot borrow as mutable diff --git a/src/test/ui/did_you_mean/issue-34126.nll.stderr b/src/test/ui/did_you_mean/issue-34126.nll.stderr index 81f858f6bfcb0..8dedb6ec4db80 100644 --- a/src/test/ui/did_you_mean/issue-34126.nll.stderr +++ b/src/test/ui/did_you_mean/issue-34126.nll.stderr @@ -2,7 +2,10 @@ error[E0596]: cannot borrow immutable item `self` as mutable --> $DIR/issue-34126.rs:16:18 | LL | self.run(&mut self); //~ ERROR cannot borrow - | ^^^^^^^^^ cannot borrow as mutable + | ^^^^^^^^^ + | | + | cannot borrow as mutable + | try removing `&mut` here error[E0502]: cannot borrow `self` as mutable because it is also borrowed as immutable --> $DIR/issue-34126.rs:16:18 diff --git a/src/test/ui/did_you_mean/issue-34337.nll.stderr b/src/test/ui/did_you_mean/issue-34337.nll.stderr index 258e1bb1ad7da..d2271e8e7de76 100644 --- a/src/test/ui/did_you_mean/issue-34337.nll.stderr +++ b/src/test/ui/did_you_mean/issue-34337.nll.stderr @@ -2,7 +2,10 @@ error[E0596]: cannot borrow immutable item `key` as mutable --> $DIR/issue-34337.rs:16:9 | LL | get(&mut key); //~ ERROR cannot borrow - | ^^^^^^^^ cannot borrow as mutable + | ^^^^^^^^ + | | + | cannot borrow as mutable + | try removing `&mut` here error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-35937.nll.stderr b/src/test/ui/did_you_mean/issue-35937.nll.stderr index 40b640b63cf32..0c1dcb29d4d2c 100644 --- a/src/test/ui/did_you_mean/issue-35937.nll.stderr +++ b/src/test/ui/did_you_mean/issue-35937.nll.stderr @@ -1,16 +1,18 @@ error[E0596]: cannot borrow immutable item `f.v` as mutable --> $DIR/issue-35937.rs:17:5 | +LL | let f = Foo { v: Vec::new() }; + | - help: consider changing this to be mutable: `mut f` LL | f.v.push("cat".to_string()); //~ ERROR cannot borrow | ^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `f` error[E0384]: cannot assign twice to immutable variable `s.x` --> $DIR/issue-35937.rs:26:5 | LL | let s = S { x: 42 }; - | ----------- first assignment to `s.x` + | - ----------- first assignment to `s.x` + | | + | consider changing this to `mut s` LL | s.x += 1; //~ ERROR cannot assign | ^^^^^^^^ cannot assign twice to immutable variable @@ -18,7 +20,10 @@ error[E0384]: cannot assign twice to immutable variable `s.x` --> $DIR/issue-35937.rs:30:5 | LL | fn bar(s: S) { - | - first assignment to `s.x` + | - + | | + | first assignment to `s.x` + | consider changing this to `mut s` LL | s.x += 1; //~ ERROR cannot assign | ^^^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/did_you_mean/issue-37139.nll.stderr b/src/test/ui/did_you_mean/issue-37139.nll.stderr index 29c7192a98bc6..e51a1baad25f2 100644 --- a/src/test/ui/did_you_mean/issue-37139.nll.stderr +++ b/src/test/ui/did_you_mean/issue-37139.nll.stderr @@ -2,7 +2,10 @@ error[E0596]: cannot borrow immutable item `x` as mutable --> $DIR/issue-37139.rs:22:18 | LL | test(&mut x); //~ ERROR cannot borrow immutable - | ^^^^^^ cannot borrow as mutable + | ^^^^^^ + | | + | cannot borrow as mutable + | try removing `&mut` here error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-1.nll.stderr b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr index 8e4426779517c..76b8c8ebf6029 100644 --- a/src/test/ui/did_you_mean/issue-38147-1.nll.stderr +++ b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr @@ -1,10 +1,10 @@ error[E0596]: cannot borrow immutable item `*self.s` as mutable --> $DIR/issue-38147-1.rs:27:9 | +LL | fn f(&self) { + | ----- help: consider changing this to be a mutable reference: `&mut Foo<'_>` LL | self.s.push('x'); //~ ERROR cannot borrow data mutably - | ^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*self` + | ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-4.nll.stderr b/src/test/ui/did_you_mean/issue-38147-4.nll.stderr index 6808222cc3241..c875957623b62 100644 --- a/src/test/ui/did_you_mean/issue-38147-4.nll.stderr +++ b/src/test/ui/did_you_mean/issue-38147-4.nll.stderr @@ -1,10 +1,10 @@ error[E0596]: cannot borrow immutable item `*f.s` as mutable --> $DIR/issue-38147-4.rs:16:5 | +LL | fn f(x: usize, f: &Foo) { + | ---- help: consider changing this to be a mutable reference: `&mut Foo<'_>` LL | f.s.push('x'); //~ ERROR cannot borrow data mutably - | ^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*f` + | ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-39544.nll.stderr b/src/test/ui/did_you_mean/issue-39544.nll.stderr index f5f5b675e7727..02c1debca69b2 100644 --- a/src/test/ui/did_you_mean/issue-39544.nll.stderr +++ b/src/test/ui/did_you_mean/issue-39544.nll.stderr @@ -1,96 +1,100 @@ error[E0596]: cannot borrow immutable item `z.x` as mutable --> $DIR/issue-39544.rs:21:13 | +LL | let z = Z { x: X::Y }; + | - help: consider changing this to be mutable: `mut z` LL | let _ = &mut z.x; //~ ERROR cannot borrow | ^^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `z` error[E0596]: cannot borrow immutable item `self.x` as mutable --> $DIR/issue-39544.rs:26:17 | +LL | fn foo<'z>(&'z self) { + | -------- help: consider changing this to be a mutable reference: `&mut Z` LL | let _ = &mut self.x; //~ ERROR cannot borrow - | ^^^^^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*self` + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `self.x` as mutable --> $DIR/issue-39544.rs:30:17 | +LL | fn foo1(&self, other: &Z) { + | ----- help: consider changing this to be a mutable reference: `&mut Z` LL | let _ = &mut self.x; //~ ERROR cannot borrow - | ^^^^^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*self` + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `other.x` as mutable --> $DIR/issue-39544.rs:31:17 | +LL | fn foo1(&self, other: &Z) { + | -- help: consider changing this to be a mutable reference: `&mut Z` +LL | let _ = &mut self.x; //~ ERROR cannot borrow LL | let _ = &mut other.x; //~ ERROR cannot borrow - | ^^^^^^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*other` + | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `self.x` as mutable --> $DIR/issue-39544.rs:35:17 | +LL | fn foo2<'a>(&'a self, other: &Z) { + | -------- help: consider changing this to be a mutable reference: `&mut Z` LL | let _ = &mut self.x; //~ ERROR cannot borrow - | ^^^^^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*self` + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `other.x` as mutable --> $DIR/issue-39544.rs:36:17 | +LL | fn foo2<'a>(&'a self, other: &Z) { + | -- help: consider changing this to be a mutable reference: `&mut Z` +LL | let _ = &mut self.x; //~ ERROR cannot borrow LL | let _ = &mut other.x; //~ ERROR cannot borrow - | ^^^^^^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*other` + | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `self.x` as mutable --> $DIR/issue-39544.rs:40:17 | +LL | fn foo3<'a>(self: &'a Self, other: &Z) { + | -------- help: consider changing this to be a mutable reference: `&mut Z` LL | let _ = &mut self.x; //~ ERROR cannot borrow - | ^^^^^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*self` + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `other.x` as mutable --> $DIR/issue-39544.rs:41:17 | +LL | fn foo3<'a>(self: &'a Self, other: &Z) { + | -- help: consider changing this to be a mutable reference: `&mut Z` +LL | let _ = &mut self.x; //~ ERROR cannot borrow LL | let _ = &mut other.x; //~ ERROR cannot borrow - | ^^^^^^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*other` + | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `other.x` as mutable --> $DIR/issue-39544.rs:45:17 | +LL | fn foo4(other: &Z) { + | -- help: consider changing this to be a mutable reference: `&mut Z` LL | let _ = &mut other.x; //~ ERROR cannot borrow - | ^^^^^^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*other` + | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `z.x` as mutable --> $DIR/issue-39544.rs:51:13 | +LL | pub fn with_arg(z: Z, w: &Z) { + | - help: consider changing this to be mutable: `mut z` LL | let _ = &mut z.x; //~ ERROR cannot borrow | ^^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `z` error[E0596]: cannot borrow immutable item `w.x` as mutable --> $DIR/issue-39544.rs:52:13 | +LL | pub fn with_arg(z: Z, w: &Z) { + | -- help: consider changing this to be a mutable reference: `&mut Z` +LL | let _ = &mut z.x; //~ ERROR cannot borrow LL | let _ = &mut w.x; //~ ERROR cannot borrow - | ^^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*w` + | ^^^^^^^^ `w` is a `&` reference, so the data it refers to cannot be borrowed as mutable -error[E0594]: cannot assign to immutable item `*x.0` +error[E0594]: cannot assign to `*x.0` which is behind a `&` reference --> $DIR/issue-39544.rs:58:5 | LL | *x.0 = 1; - | ^^^^^^^^ cannot mutate + | ^^^^^^^^ cannot assign error: aborting due to 12 previous errors diff --git a/src/test/ui/did_you_mean/issue-40823.nll.stderr b/src/test/ui/did_you_mean/issue-40823.nll.stderr index 489e1c39c46b9..1fd75de81284f 100644 --- a/src/test/ui/did_you_mean/issue-40823.nll.stderr +++ b/src/test/ui/did_you_mean/issue-40823.nll.stderr @@ -1,8 +1,10 @@ error[E0596]: cannot borrow immutable item `*buf` as mutable --> $DIR/issue-40823.rs:13:5 | +LL | let mut buf = &[1, 2, 3, 4]; + | ------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4]` LL | buf.iter_mut(); //~ ERROR cannot borrow immutable borrowed content - | ^^^ cannot borrow as mutable + | ^^^ `buf` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0389.nll.stderr b/src/test/ui/error-codes/E0389.nll.stderr index 0525e16239d2c..66e46dfe29d70 100644 --- a/src/test/ui/error-codes/E0389.nll.stderr +++ b/src/test/ui/error-codes/E0389.nll.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to data in a `&` reference +error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference --> $DIR/E0389.rs:18:5 | LL | let fancy_ref = &(&mut fancy); diff --git a/src/test/ui/issue-36400.nll.stderr b/src/test/ui/issue-36400.nll.stderr index 8045993747934..be10b1d517bdc 100644 --- a/src/test/ui/issue-36400.nll.stderr +++ b/src/test/ui/issue-36400.nll.stderr @@ -1,10 +1,10 @@ error[E0596]: cannot borrow immutable item `*x` as mutable --> $DIR/issue-36400.rs:15:7 | +LL | let x = Box::new(3); + | - help: consider changing this to be mutable: `mut x` LL | f(&mut *x); //~ ERROR cannot borrow immutable | ^^^^^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `x` error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr index 9d6d68f518d72..93f2837c0fc11 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr @@ -18,7 +18,7 @@ error[E0384]: cannot assign to immutable argument `y` --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:5 | LL | fn foo(mut x: Ref, y: &u32) { - | - argument not declared as `mut` + | - consider changing this to `mut y` LL | y = x.b; //~ ERROR lifetime mismatch | ^^^^^^^ cannot assign to immutable argument diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr index f58f33c9a9adb..01e2698032394 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr @@ -15,6 +15,8 @@ LL | y.push(z); //~ ERROR lifetime mismatch error[E0596]: cannot borrow immutable item `y` as mutable --> $DIR/ex3-both-anon-regions-using-fn-items.rs:11:3 | +LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { + | - help: consider changing this to be mutable: `mut y` LL | y.push(z); //~ ERROR lifetime mismatch | ^ cannot borrow as mutable diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr index 4bfb4ac2833c8..a61d49fc953db 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr @@ -15,6 +15,8 @@ LL | y.push(z); //~ ERROR lifetime mismatch error[E0596]: cannot borrow immutable item `y` as mutable --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:11:3 | +LL | fn foo(x:Box , y: Vec<&u8>, z: &u8) { + | - help: consider changing this to be mutable: `mut y` LL | y.push(z); //~ ERROR lifetime mismatch | ^ cannot borrow as mutable diff --git a/src/test/ui/lifetime-errors/liveness-assign-imm-local-notes.stderr b/src/test/ui/lifetime-errors/liveness-assign-imm-local-notes.stderr index 4374311896659..0620235371a39 100644 --- a/src/test/ui/lifetime-errors/liveness-assign-imm-local-notes.stderr +++ b/src/test/ui/lifetime-errors/liveness-assign-imm-local-notes.stderr @@ -32,6 +32,9 @@ LL | x = 2; //~ ERROR (Ast) [E0384] error[E0384]: cannot assign twice to immutable variable `x` (Mir) --> $DIR/liveness-assign-imm-local-notes.rs:23:9 | +LL | let x; + | - consider changing this to `mut x` +... LL | x = 2; | ----- first assignment to `x` LL | x = 3; //~ ERROR (Ast) [E0384] @@ -40,6 +43,9 @@ LL | x = 3; //~ ERROR (Ast) [E0384] error[E0384]: cannot assign twice to immutable variable `x` (Mir) --> $DIR/liveness-assign-imm-local-notes.rs:35:13 | +LL | let x; + | - consider changing this to `mut x` +... LL | x = 2; | ----- first assignment to `x` LL | x = 3; //~ ERROR (Ast) [E0384] @@ -48,12 +54,18 @@ LL | x = 3; //~ ERROR (Ast) [E0384] error[E0384]: cannot assign twice to immutable variable `x` (Mir) --> $DIR/liveness-assign-imm-local-notes.rs:45:13 | +LL | let x; + | - consider changing this to `mut x` +... LL | x = 1; //~ ERROR (Ast) [E0384] | ^^^^^ cannot assign twice to immutable variable error[E0384]: cannot assign twice to immutable variable `x` (Mir) --> $DIR/liveness-assign-imm-local-notes.rs:48:13 | +LL | let x; + | - consider changing this to `mut x` +... LL | x = 1; //~ ERROR (Ast) [E0384] | ----- first assignment to `x` ... diff --git a/src/test/ui/macros/span-covering-argument-1.nll.stderr b/src/test/ui/macros/span-covering-argument-1.nll.stderr index a12baab415907..213eddee720d3 100644 --- a/src/test/ui/macros/span-covering-argument-1.nll.stderr +++ b/src/test/ui/macros/span-covering-argument-1.nll.stderr @@ -1,6 +1,8 @@ error[E0596]: cannot borrow immutable item `foo` as mutable --> $DIR/span-covering-argument-1.rs:15:14 | +LL | let $s = 0; + | -- help: consider changing this to be mutable: `mut foo` LL | *&mut $s = 0; | ^^^^^^^ cannot borrow as mutable ... diff --git a/src/test/ui/nll/issue-47388.stderr b/src/test/ui/nll/issue-47388.stderr index f3952c49a2a36..96e9f15541447 100644 --- a/src/test/ui/nll/issue-47388.stderr +++ b/src/test/ui/nll/issue-47388.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to data in a `&` reference +error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference --> $DIR/issue-47388.rs:18:5 | LL | let fancy_ref = &(&mut fancy); diff --git a/src/test/ui/reassign-ref-mut.rs b/src/test/ui/reassign-ref-mut.rs new file mode 100644 index 0000000000000..c045720a84013 --- /dev/null +++ b/src/test/ui/reassign-ref-mut.rs @@ -0,0 +1,26 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests how we behave when the user attempts to mutate an immutable +// binding that was introduced by either `ref` or `ref mut` +// patterns. +// +// Such bindings cannot be made mutable via the mere addition of the +// `mut` keyword, and thus we want to check that the compiler does not +// suggest doing so. + +fn main() { + let (mut one_two, mut three_four) = ((1, 2), (3, 4)); + let &mut (ref a, ref mut b) = &mut one_two; + a = &three_four.0; + //~^ ERROR cannot assign twice to immutable variable `a` [E0384] + b = &mut three_four.1; + //~^ ERROR cannot assign twice to immutable variable `b` [E0384] +} diff --git a/src/test/ui/reassign-ref-mut.stderr b/src/test/ui/reassign-ref-mut.stderr new file mode 100644 index 0000000000000..bf627dde720b1 --- /dev/null +++ b/src/test/ui/reassign-ref-mut.stderr @@ -0,0 +1,20 @@ +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/reassign-ref-mut.rs:22:5 + | +LL | let &mut (ref a, ref mut b) = &mut one_two; + | ----- first assignment to `a` +LL | a = &three_four.0; + | ^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `b` + --> $DIR/reassign-ref-mut.rs:24:5 + | +LL | let &mut (ref a, ref mut b) = &mut one_two; + | --------- first assignment to `b` +... +LL | b = &mut three_four.1; + | ^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0384`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr index b97bdeea409c6..8aa7e8a417c2b 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr @@ -1,26 +1,20 @@ -error[E0594]: cannot assign to data in a `&` reference +error[E0594]: cannot assign to `*x` which is behind a `&` reference --> $DIR/enum.rs:19:5 | -LL | let Wrap(x) = &Wrap(3); - | - help: consider changing this to be a mutable reference: `&mut` LL | *x += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ + | ^^^^^^^ cannot assign -error[E0594]: cannot assign to data in a `&` reference +error[E0594]: cannot assign to `*x` which is behind a `&` reference --> $DIR/enum.rs:23:9 | -LL | if let Some(x) = &Some(3) { - | - help: consider changing this to be a mutable reference: `&mut` LL | *x += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ + | ^^^^^^^ cannot assign -error[E0594]: cannot assign to data in a `&` reference +error[E0594]: cannot assign to `*x` which is behind a `&` reference --> $DIR/enum.rs:29:9 | -LL | while let Some(x) = &Some(3) { - | - help: consider changing this to be a mutable reference: `&mut` LL | *x += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ + | ^^^^^^^ cannot assign error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr index 3ee4dc07bb8bb..4e00dec761621 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr @@ -1,26 +1,20 @@ -error[E0594]: cannot assign to data in a `&` reference +error[E0594]: cannot assign to `*n` which is behind a `&` reference --> $DIR/explicit-mut.rs:17:13 | -LL | Some(n) => { - | - help: consider changing this to be a mutable reference: `&mut` LL | *n += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ + | ^^^^^^^ cannot assign -error[E0594]: cannot assign to data in a `&` reference +error[E0594]: cannot assign to `*n` which is behind a `&` reference --> $DIR/explicit-mut.rs:25:13 | -LL | Some(n) => { - | - help: consider changing this to be a mutable reference: `&mut` LL | *n += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ + | ^^^^^^^ cannot assign -error[E0594]: cannot assign to data in a `&` reference +error[E0594]: cannot assign to `*n` which is behind a `&` reference --> $DIR/explicit-mut.rs:33:13 | -LL | Some(n) => { - | - help: consider changing this to be a mutable reference: `&mut` LL | *n += 1; //~ ERROR cannot assign to immutable - | ^^^^^^^ + | ^^^^^^^ cannot assign error: aborting due to 3 previous errors diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr index 172828b9a40f9..3282fbba6c5cf 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr @@ -1,50 +1,66 @@ error[E0596]: cannot borrow immutable item `x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:63:24 | +LL | fn deref_mut_field1(x: Own) { + | - help: consider changing this to be mutable: `mut x` LL | let __isize = &mut x.y; //~ ERROR cannot borrow | ^ cannot borrow as mutable error[E0596]: cannot borrow immutable item `*x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:75:10 | +LL | fn deref_extend_mut_field1(x: &Own) -> &mut isize { + | ----------- help: consider changing this to be a mutable reference: `&mut Own` LL | &mut x.y //~ ERROR cannot borrow - | ^ cannot borrow as mutable + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:98:5 | +LL | fn assign_field1<'a>(x: Own) { + | - help: consider changing this to be mutable: `mut x` LL | x.y = 3; //~ ERROR cannot borrow | ^ cannot borrow as mutable error[E0596]: cannot borrow immutable item `*x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:102:5 | +LL | fn assign_field2<'a>(x: &'a Own) { + | -------------- help: consider changing this to be a mutable reference: `&mut Own` LL | x.y = 3; //~ ERROR cannot borrow - | ^ cannot borrow as mutable + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:119:5 | +LL | fn deref_mut_method1(x: Own) { + | - help: consider changing this to be mutable: `mut x` LL | x.set(0, 0); //~ ERROR cannot borrow | ^ cannot borrow as mutable error[E0596]: cannot borrow immutable item `*x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:131:5 | +LL | fn deref_extend_mut_method1(x: &Own) -> &mut isize { + | ----------- help: consider changing this to be a mutable reference: `&mut Own` LL | x.y_mut() //~ ERROR cannot borrow - | ^ cannot borrow as mutable + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:139:6 | +LL | fn assign_method1<'a>(x: Own) { + | - help: consider changing this to be mutable: `mut x` LL | *x.y_mut() = 3; //~ ERROR cannot borrow | ^ cannot borrow as mutable error[E0596]: cannot borrow immutable item `*x` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:143:6 | +LL | fn assign_method2<'a>(x: &'a Own) { + | -------------- help: consider changing this to be a mutable reference: `&mut Own` LL | *x.y_mut() = 3; //~ ERROR cannot borrow - | ^ cannot borrow as mutable + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to 8 previous errors diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr index 24abe85de76f7..0b1bfd8cee673 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr @@ -1,26 +1,34 @@ error[E0596]: cannot borrow immutable item `x` as mutable --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:39:25 | +LL | fn deref_mut1(x: Own) { + | - help: consider changing this to be mutable: `mut x` LL | let __isize = &mut *x; //~ ERROR cannot borrow | ^ cannot borrow as mutable error[E0596]: cannot borrow immutable item `*x` as mutable --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:51:11 | +LL | fn deref_extend_mut1<'a>(x: &'a Own) -> &'a mut isize { + | -------------- help: consider changing this to be a mutable reference: `&mut Own` LL | &mut **x //~ ERROR cannot borrow - | ^^ cannot borrow as mutable + | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `x` as mutable --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:59:6 | +LL | fn assign1<'a>(x: Own) { + | - help: consider changing this to be mutable: `mut x` LL | *x = 3; //~ ERROR cannot borrow | ^ cannot borrow as mutable error[E0596]: cannot borrow immutable item `*x` as mutable --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:63:6 | +LL | fn assign2<'a>(x: &'a Own) { + | -------------- help: consider changing this to be a mutable reference: `&mut Own` LL | **x = 3; //~ ERROR cannot borrow - | ^^ cannot borrow as mutable + | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to 4 previous errors diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr index 26e9ea4dc0bc8..c4bdef21de4ba 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr @@ -15,16 +15,18 @@ LL | | })); error[E0596]: cannot borrow immutable item `*f` as mutable --> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5 | +LL | fn test2(f: &F) where F: FnMut() { + | -- help: consider changing this to be a mutable reference: `&mut F` LL | (*f)(); - | ^^^^ cannot borrow as mutable + | ^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `*f.f` as mutable --> $DIR/borrowck-call-is-borrow-issue-12224.rs:44:5 | +LL | fn test4(f: &Test) { + | ----- help: consider changing this to be a mutable reference: `&mut Test<'_>` LL | f.f.call_mut(()) - | ^^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*f` + | ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0507]: cannot move out of borrowed content --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13 diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr index 43934bf4aeec1..0bc614589e3d2 100644 --- a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr +++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr @@ -1,8 +1,11 @@ error[E0596]: cannot borrow immutable item `*x` as mutable --> $DIR/borrowck-call-method-from-mut-aliasable.rs:27:5 | +LL | fn b(x: &Foo) { + | ---- help: consider changing this to be a mutable reference: `&mut Foo` +LL | x.f(); LL | x.h(); //~ ERROR cannot borrow - | ^ cannot borrow as mutable + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr b/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr index d3c6fd6659947..1cb2c92833c16 100644 --- a/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr +++ b/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr @@ -1,8 +1,10 @@ error[E0596]: cannot borrow immutable item `*x` as mutable --> $DIR/borrowck-fn-in-const-b.rs:17:9 | +LL | fn broken(x: &Vec) { + | ------------ help: consider changing this to be a mutable reference: `&mut std::vec::Vec` LL | x.push(format!("this is broken")); - | ^ cannot borrow as mutable + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-object-mutability.nll.stderr b/src/test/ui/span/borrowck-object-mutability.nll.stderr index 9b5e084bd3751..cf615eed55691 100644 --- a/src/test/ui/span/borrowck-object-mutability.nll.stderr +++ b/src/test/ui/span/borrowck-object-mutability.nll.stderr @@ -1,16 +1,20 @@ error[E0596]: cannot borrow immutable item `*x` as mutable --> $DIR/borrowck-object-mutability.rs:19:5 | +LL | fn borrowed_receiver(x: &Foo) { + | ---- help: consider changing this to be a mutable reference: `&mut Foo` +LL | x.borrowed(); LL | x.borrowed_mut(); //~ ERROR cannot borrow - | ^ cannot borrow as mutable + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `*x` as mutable --> $DIR/borrowck-object-mutability.rs:29:5 | +LL | fn owned_receiver(x: Box) { + | - help: consider changing this to be mutable: `mut x` +LL | x.borrowed(); LL | x.borrowed_mut(); //~ ERROR cannot borrow | ^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `x` error: aborting due to 2 previous errors diff --git a/src/test/ui/span/mut-arg-hint.nll.stderr b/src/test/ui/span/mut-arg-hint.nll.stderr index 8e1cb9720e236..cd19059fdae32 100644 --- a/src/test/ui/span/mut-arg-hint.nll.stderr +++ b/src/test/ui/span/mut-arg-hint.nll.stderr @@ -1,20 +1,26 @@ error[E0596]: cannot borrow immutable item `*a` as mutable --> $DIR/mut-arg-hint.rs:13:9 | +LL | fn foo(mut a: &String) { + | ------- help: consider changing this to be a mutable reference: `&mut std::string::String` LL | a.push_str("bar"); //~ ERROR cannot borrow immutable borrowed content - | ^ cannot borrow as mutable + | ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `*a` as mutable --> $DIR/mut-arg-hint.rs:18:5 | +LL | pub fn foo<'a>(mut a: &'a String) { + | ---------- help: consider changing this to be a mutable reference: `&mut std::string::String` LL | a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content - | ^ cannot borrow as mutable + | ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `*a` as mutable --> $DIR/mut-arg-hint.rs:25:9 | +LL | pub fn foo(mut a: &String) { + | ------- help: consider changing this to be a mutable reference: `&mut std::string::String` LL | a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content - | ^ cannot borrow as mutable + | ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to 3 previous errors diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr index bc655114c2b47..335ccefe8a0b1 100644 --- a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr +++ b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr @@ -2,7 +2,7 @@ error[E0594]: cannot assign to immutable item `y` --> $DIR/closure-immutable-outer-variable.rs:21:26 | LL | foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable - | ^^^^^^^^^ cannot mutate + | ^^^^^^^^^ cannot assign error: aborting due to previous error diff --git a/src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr b/src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr index ed691843f9b26..7ef21d3720d88 100644 --- a/src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr +++ b/src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr @@ -1,8 +1,8 @@ -error[E0594]: cannot assign to immutable item `x` +error[E0594]: cannot assign to `x` which is behind a `&` reference --> $DIR/fn-closure-mutable-capture.rs:15:17 | LL | bar(move || x = 1); - | ^^^^^ cannot mutate + | ^^^^^ cannot assign error: aborting due to previous error diff --git a/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr b/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr index 66547863db2fd..1a36b0c4839b6 100644 --- a/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr +++ b/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr @@ -1,18 +1,18 @@ error[E0596]: cannot borrow immutable item `**t` as mutable --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:16:5 | +LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + | --------------- help: consider changing this to be a mutable reference: `&mut &mut i32` LL | *t //~ ERROR - | ^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*t` + | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow immutable item `**t` as mutable --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:20:6 | +LL | fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + | --------------- help: consider changing this to be a mutable reference: `&mut &mut i32` LL | {*t} //~ ERROR - | ^^ cannot borrow as mutable - | - = note: the value which is causing this path not to be mutable is...: `*t` + | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to 2 previous errors