diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ea4eb761964eb..471b7743f0c3a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -523,7 +523,9 @@ impl BorrowKind { pub fn allows_two_phase_borrow(&self) -> bool { match *self { BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false, - BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow, + BorrowKind::Mut { + allow_two_phase_borrow, + } => allow_two_phase_borrow, } } } @@ -596,7 +598,7 @@ pub enum ImplicitSelfKind { MutRef, /// Represents when a function does not have a self argument or /// when a function has a `self: X` argument. - None + None, } CloneTypeFoldableAndLiftImpls! { BindingForm<'tcx>, } @@ -820,8 +822,7 @@ impl<'tcx> LocalDecl<'tcx> { pat_span: _, }))) => true, - Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(ImplicitSelfKind::Imm))) - => true, + Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(ImplicitSelfKind::Imm))) => true, _ => false, } @@ -873,12 +874,7 @@ impl<'tcx> LocalDecl<'tcx> { } #[inline] - fn new_local( - ty: Ty<'tcx>, - mutability: Mutability, - internal: bool, - span: Span, - ) -> Self { + fn new_local(ty: Ty<'tcx>, mutability: Mutability, internal: bool, span: Span) -> Self { LocalDecl { mutability, ty, @@ -1603,13 +1599,15 @@ impl<'tcx> TerminatorKind<'tcx> { Scalar::Bits { bits: u, size: size.bytes() as u8, - }.into(), + } + .into(), ), ty: switch_ty, }; fmt_const_val(&mut s, &c).unwrap(); s.into() - }).chain(iter::once("otherwise".into())) + }) + .chain(iter::once("otherwise".into())) .collect() } Call { @@ -1843,9 +1841,11 @@ impl<'tcx> Debug for Statement<'tcx> { ref outputs, ref inputs, } => write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs), - AscribeUserType(ref place, ref variance, ref c_ty) => { - write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty) - } + AscribeUserType(ref place, ref variance, ref c_ty) => write!( + fmt, + "AscribeUserType({:?}, {:?}, {:?})", + place, variance, c_ty + ), Nop => write!(fmt, "nop"), } } @@ -1970,14 +1970,24 @@ impl<'tcx> Place<'tcx> { /// Find the innermost `Local` from this `Place`. pub fn local(&self) -> Option<Local> { match self { - Place::Local(local) | - Place::Projection(box Projection { + Place::Local(local) + | Place::Projection(box Projection { base: Place::Local(local), elem: ProjectionElem::Deref, }) => Some(*local), _ => None, } } + + /// Returns the local variable at the "base" of this place, if any. e.g., for a place like + /// a.b.c, returns Some(a). For a place based in a static or constant, returns None. + pub fn base_local(&self) -> Option<Local> { + match self { + Place::Projection(box Projection { base, .. }) => base.base_local(), + Place::Local(local) => Some(*local), + Place::Static(..) | Place::Promoted(..) => None, + } + } } impl<'tcx> Debug for Place<'tcx> { @@ -2691,7 +2701,9 @@ pub struct ClosureOutlivesRequirement<'tcx> { /// order of the category, thereby influencing diagnostic output. /// /// See also [rustc_mir::borrow_check::nll::constraints] -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive( + Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, +)] pub enum ConstraintCategory { Return, TypeAnnotation, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 0943b36440aa6..657ccdda718a7 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -12,9 +12,9 @@ use borrow_check::nll::region_infer::RegionInferenceContext; use rustc::hir; -use rustc::hir::Node; use rustc::hir::def_id::DefId; use rustc::hir::map::definitions::DefPathData; +use rustc::hir::Node; use rustc::infer::InferCtxt; use rustc::lint::builtin::UNUSED_MUT; use rustc::middle::borrowck::SignalledError; @@ -25,35 +25,35 @@ use rustc::mir::{Terminator, TerminatorKind}; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level}; use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::Dominators; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level}; use smallvec::SmallVec; -use std::rc::Rc; use std::collections::BTreeMap; +use std::rc::Rc; use syntax_pos::Span; use dataflow::indexes::BorrowIndex; -use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MoveError, MovePathIndex}; use dataflow::move_paths::indexes::MoveOutIndex; +use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MoveError, MovePathIndex}; use dataflow::Borrows; use dataflow::DataflowResultsConsumer; +use dataflow::EverInitializedPlaces; use dataflow::FlowAtLocation; use dataflow::MoveDataParamEnv; use dataflow::{do_dataflow, DebugFormatted}; -use dataflow::EverInitializedPlaces; use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use util::borrowck_errors::{BorrowckErrors, Origin}; use self::borrow_set::{BorrowData, BorrowSet}; use self::flows::Flows; use self::location::LocationTable; +use self::mutability_errors::AccessKind; use self::prefixes::PrefixSet; use self::MutateMode::{JustWrite, WriteAndRead}; -use self::mutability_errors::AccessKind; use self::path_utils::*; @@ -180,11 +180,15 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( )); let locals_are_invalidated_at_exit = match tcx.hir.body_owner_kind(id) { - hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false, - hir::BodyOwnerKind::Fn => true, + hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false, + hir::BodyOwnerKind::Fn => true, }; let borrow_set = Rc::new(BorrowSet::build( - tcx, mir, locals_are_invalidated_at_exit, &mdpe.move_data)); + tcx, + mir, + locals_are_invalidated_at_exit, + &mdpe.move_data, + )); // If we are in non-lexical mode, compute the non-lexical lifetimes. let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions( @@ -265,12 +269,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( dominators, }; - let mut state = Flows::new( - flow_borrows, - flow_uninits, - flow_ever_inits, - polonius_output, - ); + let mut state = Flows::new(flow_borrows, flow_uninits, flow_ever_inits, polonius_output); if let Some(errors) = move_errors { mbcx.report_move_errors(errors); @@ -309,9 +308,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // Skip over locals that begin with an underscore or have no name match local_decl.name { - Some(name) => if name.as_str().starts_with("_") { - continue; - }, + Some(name) => { + if name.as_str().starts_with("_") { + continue; + } + } None => continue, } @@ -332,7 +333,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( mut_span, "remove this `mut`", String::new(), - Applicability::MachineApplicable); + Applicability::MachineApplicable, + ); err.buffer(&mut mbcx.errors_buffer); } @@ -344,7 +346,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( } if mbcx.errors_buffer.len() > 0 { - mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span()); + mbcx.errors_buffer + .sort_by_key(|diag| diag.span.primary_span()); if tcx.migrate_borrowck() { match tcx.borrowck(def_id).signalled_any_error { @@ -355,10 +358,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( for err in &mut mbcx.errors_buffer { if err.is_error() { err.level = Level::Warning; - err.warn("This error has been downgraded to a warning \ - for backwards compatibility with previous releases.\n\ - It represents potential unsoundness in your code.\n\ - This warning will become a hard error in the future."); + err.warn( + "This error has been downgraded to a warning \ + for backwards compatibility with previous releases.\n\ + It represents potential unsoundness in your code.\n\ + This warning will become a hard error in the future.", + ); } } } @@ -627,7 +632,10 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx let drop_place_ty = drop_place.ty(self.mir, self.infcx.tcx); // Erase the regions. - let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty) + let drop_place_ty = self + .infcx + .tcx + .erase_regions(&drop_place_ty) .to_ty(self.infcx.tcx); // "Lift" into the gcx -- once regions are erased, this type should be in the @@ -635,9 +643,11 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx // that is useful later. let drop_place_ty = gcx.lift(&drop_place_ty).unwrap(); - debug!("visit_terminator_drop \ - loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}", - loc, term, drop_place, drop_place_ty, span); + debug!( + "visit_terminator_drop \ + loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}", + loc, term, drop_place, drop_place_ty, span + ); self.access_place( ContextKind::Drop.new(loc), @@ -762,8 +772,8 @@ enum MutateMode { WriteAndRead, } -use self::ReadOrWrite::{Activation, Read, Reservation, Write}; use self::AccessDepth::{Deep, Shallow}; +use self::ReadOrWrite::{Activation, Read, Reservation, Write}; #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum ArtificialField { @@ -912,8 +922,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Check is_empty() first because it's the common case, and doing that // way we avoid the clone() call. - if !self.access_place_error_reported.is_empty() && - self + if !self.access_place_error_reported.is_empty() && self .access_place_error_reported .contains(&(place_span.0.clone(), place_span.1)) { @@ -924,14 +933,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { return; } - let mutability_error = - self.check_access_permissions( - place_span, - rw, - is_local_mutation_allowed, - flow_state, - context.loc, - ); + let mutability_error = self.check_access_permissions( + place_span, + rw, + is_local_mutation_allowed, + flow_state, + context.loc, + ); let conflict_error = self.check_access_for_conflict(context, place_span, sd, rw, flow_state); @@ -990,10 +998,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Control::Continue } - (Read(_), BorrowKind::Shared) | (Reservation(..), BorrowKind::Shared) - | (Read(_), BorrowKind::Shallow) | (Reservation(..), BorrowKind::Shallow) => { - Control::Continue - } + (Read(_), BorrowKind::Shared) + | (Reservation(..), BorrowKind::Shared) + | (Read(_), BorrowKind::Shallow) + | (Reservation(..), BorrowKind::Shallow) => Control::Continue, (Write(WriteKind::Move), BorrowKind::Shallow) => { // Handled by initialization checks. @@ -1008,7 +1016,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } match kind { - ReadKind::Copy => { + ReadKind::Copy => { error_reported = true; this.report_use_while_mutably_borrowed(context, place_span, borrow) } @@ -1054,7 +1062,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context, borrow, place_span, - Some(kind)) + Some(kind), + ) } WriteKind::Mutate => { error_reported = true; @@ -1096,20 +1105,56 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - // Special case: you can assign a immutable local variable - // (e.g., `x = ...`) so long as it has never been initialized - // before (at this point in the flow). - if let &Place::Local(local) = place_span.0 { - if let Mutability::Not = self.mir.local_decls[local].mutability { - // check for reassignments to immutable local variables - self.check_if_reassignment_to_immutable_state( - context, - local, - place_span, - flow_state, - ); - return; + match place_span.0 { + // Special case: you can assign a immutable local variable + // (e.g., `x = ...`) so long as it has never been initialized + // before (at this point in the flow). + &Place::Local(local) => { + if let Mutability::Not = self.mir.local_decls[local].mutability { + // check for reassignments to immutable local variables + self.check_if_reassignment_to_immutable_state( + context, local, place_span, flow_state, + ); + return; + } } + + // FIXME(#21232). For now, error if assigning to a projection from an uninitialized + // local variable -- so e.g. doing a.b = 22 when a is not yet initialized is simply an + // error. In the future, we could sometimes support this. + place @ &Place::Projection(_) => { + if let Some(local) = place.base_local() { + let mpi = self.move_data.rev_lookup.find_local(local); + if flow_state.uninits.contains(mpi) { + let name = self.mir.local_decls[local].name.unwrap(); + let msg = match self.describe_place(place) { + Some(desc) => format!( + "cannot assign to `{}` when `{}` is not initialized", + desc, name, + ), + + None => format!("use of uninitialized variable `{}", name,), + }; + + let mut diag = + struct_span_err!(self.infcx.tcx.sess, place_span.1, E0718, "{}", msg); + + if let Mutability::Mut = self.mir.local_decls[local].mutability { + // Pre-emptively insert local into the used_mut set to avoid any + // warnings related to whether the mut declaration is used. + self.used_mut.insert(local); + } else { + diag.span_label(place_span.1, "will also have to be declared `mut`"); + } + + diag.buffer(&mut self.errors_buffer); + + return; + } + } + } + + _ => {} } // Otherwise, use the normal access permission rules. @@ -1132,9 +1177,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { match *rvalue { Rvalue::Ref(_ /*rgn*/, bk, ref place) => { let access_kind = match bk { - BorrowKind::Shallow => { - (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk))) - }, + BorrowKind::Shallow => ( + Shallow(Some(ArtificialField::ShallowBorrow)), + Read(ReadKind::Borrow(bk)), + ), BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))), BorrowKind::Unique | BorrowKind::Mut { .. } => { let wk = WriteKind::MutableBorrow(bk); @@ -1160,12 +1206,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { InitializationRequiringAction::Borrow }; - self.check_if_path_or_subpath_is_moved( - context, - action, - (place, span), - flow_state, - ); + self.check_if_path_or_subpath_is_moved(context, action, (place, span), flow_state); } Rvalue::Use(ref operand) @@ -1215,8 +1256,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // moved into the closure and subsequently used by the closure, // in order to populate our used_mut set. match **aggregate_kind { - AggregateKind::Closure(def_id, _) - | AggregateKind::Generator(def_id, _, _) => { + AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => { let BorrowCheckResult { used_mut_upvars, .. } = self.infcx.tcx.mir_borrowck(def_id); @@ -1232,8 +1272,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } Operand::Move(ref place @ Place::Projection(_)) | Operand::Copy(ref place @ Place::Projection(_)) => { - if let Some(field) = place.is_upvar_field_projection( - self.mir, &self.infcx.tcx) { + if let Some(field) = + place.is_upvar_field_projection(self.mir, &self.infcx.tcx) + { self.used_mut_upvars.push(field); } } @@ -1356,7 +1397,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { place, borrow.kind, root_place, - sd + sd, ) { debug!("check_for_invalidation_at_exit({:?}): INVALID", place); // FIXME: should be talking about the region lifetime instead @@ -1377,12 +1418,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { debug!("check_for_local_borrow({:?})", borrow); if borrow_of_local_data(&borrow.borrowed_place) { - let err = self.infcx.tcx - .cannot_borrow_across_generator_yield( - self.retrieve_borrow_spans(borrow).var_or_use(), - yield_span, - Origin::Mir, - ); + let err = self.infcx.tcx.cannot_borrow_across_generator_yield( + self.retrieve_borrow_spans(borrow).var_or_use(), + yield_span, + Origin::Mir, + ); err.buffer(&mut self.errors_buffer); } @@ -1441,14 +1481,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Check if any of the initializiations of `local` have happened yet: let mpi = self.move_data.rev_lookup.find_local(local); let init_indices = &self.move_data.init_path_map[mpi]; - let first_init_index = init_indices.iter().find(|&ii| flow_state.ever_inits.contains(*ii)); + let first_init_index = init_indices + .iter() + .find(|&ii| flow_state.ever_inits.contains(*ii)); if let Some(&init_index) = first_init_index { // And, if so, report an error. let init = &self.move_data.inits[init_index]; let span = init.span(&self.mir); - self.report_illegal_reassignment( - context, place_span, span, place_span.0 - ); + self.report_illegal_reassignment(context, place_span, span, place_span.0); } } @@ -1555,7 +1595,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // // This code covers scenario 1. - debug!("check_if_path_or_subpath_is_moved place: {:?}", place_span.0); + debug!( + "check_if_path_or_subpath_is_moved place: {:?}", + place_span.0 + ); if let Some(mpi) = self.move_path_for_place(place_span.0) { if let Some(child_mpi) = maybe_uninits.has_any_child_of(mpi) { self.report_use_of_moved_or_uninitialized( @@ -1593,8 +1636,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { match *last_prefix { Place::Local(_) => panic!("should have move path for every Local"), Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"), - Place::Promoted(_) | - Place::Static(_) => return Err(NoMovePathFound::ReachedStatic), + Place::Promoted(_) | Place::Static(_) => return Err(NoMovePathFound::ReachedStatic), } } @@ -1620,8 +1662,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut place = place; loop { match *place { - Place::Promoted(_) | - Place::Local(_) | Place::Static(_) => { + Place::Promoted(_) | Place::Local(_) | Place::Static(_) => { // assigning to `x` does not require `x` be initialized. break; } @@ -1679,7 +1720,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - /// Check the permissions for the given place and read or write kind /// /// Returns true if an error is reported, false otherwise. @@ -1754,8 +1794,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { error_access = match wk { WriteKind::MutableBorrow(_) => AccessKind::MutableBorrow, WriteKind::Move => AccessKind::Move, - WriteKind::StorageDeadOrDrop | - WriteKind::Mutate => AccessKind::Mutate, + WriteKind::StorageDeadOrDrop | WriteKind::Mutate => AccessKind::Mutate, }; self.report_mutability_error( place, @@ -1791,13 +1830,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } // at this point, we have set up the error reporting state. - self.report_mutability_error( - place, - span, - the_place_err, - error_access, - location, - ); + self.report_mutability_error(place, span, the_place_err, error_access, location); return true; } @@ -1907,8 +1940,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Mutably borrowed data is mutable, but only if we have a // unique path to the `&mut` hir::MutMutable => { - let mode = match place.is_upvar_field_projection( - self.mir, &self.infcx.tcx) + let mode = match place + .is_upvar_field_projection(self.mir, &self.infcx.tcx) { Some(field) if { @@ -1953,8 +1986,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } | ProjectionElem::Downcast(..) => { - let upvar_field_projection = place.is_upvar_field_projection( - self.mir, &self.infcx.tcx); + let upvar_field_projection = + place.is_upvar_field_projection(self.mir, &self.infcx.tcx); if let Some(field) = upvar_field_projection { let decl = &self.mir.upvar_decls[field.index()]; debug!( @@ -1994,7 +2027,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // }); // } // ``` - let _ = self.is_mutable(&proj.base, is_local_mutation_allowed)?; + let _ = + self.is_mutable(&proj.base, is_local_mutation_allowed)?; Ok(RootPlace { place, is_local_mutation_allowed, diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 56031054b9183..810fa322aa6c4 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -2344,4 +2344,5 @@ register_diagnostics! { E0594, // cannot assign to {} E0598, // lifetime of {} is too short to guarantee its contents can be... E0625, // thread-local statics cannot be accessed at compile-time + E0718, } diff --git a/src/test/ui/borrowck/borrowck-issue-48962.stderr b/src/test/ui/borrowck/borrowck-issue-48962.stderr index 4448cedda69af..b8fa7d48adb72 100644 --- a/src/test/ui/borrowck/borrowck-issue-48962.stderr +++ b/src/test/ui/borrowck/borrowck-issue-48962.stderr @@ -1,3 +1,9 @@ +error[E0718]: cannot assign to `src.next` when `src` is not initialized + --> $DIR/borrowck-issue-48962.rs:26:5 + | +LL | src.next = None; //~ ERROR use of moved value: `src` [E0382] + | ^^^^^^^^ + error[E0382]: use of moved value: `src` --> $DIR/borrowck-issue-48962.rs:26:5 | @@ -8,6 +14,12 @@ LL | src.next = None; //~ ERROR use of moved value: `src` [E0382] | = note: move occurs because `src` has type `&mut Node`, which does not implement the `Copy` trait +error[E0718]: cannot assign to `src.0` when `src` is not initialized + --> $DIR/borrowck-issue-48962.rs:32:5 + | +LL | src.0 = 66; //~ ERROR use of moved value: `src` [E0382] + | ^^^^^^^^^^ + error[E0382]: use of moved value: `src` --> $DIR/borrowck-issue-48962.rs:32:5 | @@ -18,6 +30,7 @@ LL | src.0 = 66; //~ ERROR use of moved value: `src` [E0382] | = note: move occurs because `src` has type `&mut (i32, i32)`, which does not implement the `Copy` trait -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0382`. +Some errors occurred: E0382, E0718. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr index bd9836e3174fb..6db14d8523dd2 100644 --- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr @@ -16,18 +16,43 @@ error[E0381]: borrow of possibly uninitialized variable: `**x` LL | let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381] | ^^^^ use of possibly uninitialized `**x` +error[E0718]: cannot assign to `a.x` when `a` is not initialized + --> $DIR/borrowck-uninit-ref-chain.rs:34:5 + | +LL | a.x = 0; + | ^^^^^^^ + +error[E0718]: cannot assign to `a.x` when `a` is not initialized + --> $DIR/borrowck-uninit-ref-chain.rs:39:5 + | +LL | a.x = &&0; + | ^^^^^^^^^ + +error[E0718]: cannot assign to `a.x` when `a` is not initialized + --> $DIR/borrowck-uninit-ref-chain.rs:45:5 + | +LL | a.x = 0; + | ^^^^^^^ + error[E0381]: borrow of possibly uninitialized variable: `a.y` --> $DIR/borrowck-uninit-ref-chain.rs:46:14 | LL | let _b = &a.y; //[ast]~ ERROR use of possibly uninitialized variable: `a.y` [E0381] | ^^^^ use of possibly uninitialized `a.y` +error[E0718]: cannot assign to `a.x` when `a` is not initialized + --> $DIR/borrowck-uninit-ref-chain.rs:50:5 + | +LL | a.x = &&0; + | ^^^^^^^^^ + error[E0381]: borrow of possibly uninitialized variable: `**a.y` --> $DIR/borrowck-uninit-ref-chain.rs:51:14 | LL | let _b = &**a.y; //[ast]~ ERROR use of possibly uninitialized variable: `**a.y` [E0381] | ^^^^^^ use of possibly uninitialized `**a.y` -error: aborting due to 5 previous errors +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0381`. +Some errors occurred: E0381, E0718. +For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr index d69693eb03532..7da6d595830f6 100644 --- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr +++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.mir.stderr @@ -4,12 +4,25 @@ error[E0381]: use of possibly uninitialized variable: `*w` LL | w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381] | ^^^^ use of possibly uninitialized `*w` +error[E0718]: cannot assign to `w[..]` when `w` is not initialized + --> $DIR/borrowck-use-in-index-lvalue.rs:16:5 + | +LL | w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381] + | ^^^^^^^^ will also have to be declared `mut` + error[E0381]: use of possibly uninitialized variable: `*w` --> $DIR/borrowck-use-in-index-lvalue.rs:20:5 | LL | w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381] | ^^^^ use of possibly uninitialized `*w` -error: aborting due to 2 previous errors +error[E0718]: cannot assign to `w[..]` when `w` is not initialized + --> $DIR/borrowck-use-in-index-lvalue.rs:20:5 + | +LL | w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381] + | ^^^^^^^^ + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0381`. +Some errors occurred: E0381, E0718. +For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/nll/issue-54499.rs b/src/test/ui/nll/issue-54499.rs new file mode 100644 index 0000000000000..5b669c9baf773 --- /dev/null +++ b/src/test/ui/nll/issue-54499.rs @@ -0,0 +1,27 @@ +// Copyright 2018 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] + +fn foo() { + let mut s: (i32, i32); + s.0 = 1; + s.1 = 2; + println!("{} {}", s.0, s.1); +} + +fn bar() { + let s: (i32, i32); + s.0 = 3; + s.1 = 4; + println!("{} {}", s.0, s.1); +} + +fn main() {} diff --git a/src/test/ui/nll/issue-54499.stderr b/src/test/ui/nll/issue-54499.stderr new file mode 100644 index 0000000000000..58e258c660412 --- /dev/null +++ b/src/test/ui/nll/issue-54499.stderr @@ -0,0 +1,27 @@ +error[E0718]: cannot assign to `s.0` when `s` is not initialized + --> $DIR/issue-54499.rs:15:5 + | +LL | s.0 = 1; + | ^^^^^^^ + +error[E0718]: cannot assign to `s.1` when `s` is not initialized + --> $DIR/issue-54499.rs:16:5 + | +LL | s.1 = 2; + | ^^^^^^^ + +error[E0718]: cannot assign to `s.0` when `s` is not initialized + --> $DIR/issue-54499.rs:22:5 + | +LL | s.0 = 3; + | ^^^^^^^ will also have to be declared `mut` + +error[E0718]: cannot assign to `s.1` when `s` is not initialized + --> $DIR/issue-54499.rs:23:5 + | +LL | s.1 = 4; + | ^^^^^^^ will also have to be declared `mut` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0718`.