From 44a2f681a988eb5587bd98a0cb37730fbd33f576 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 16 Oct 2018 15:39:07 +0200 Subject: [PATCH 1/9] Add `Place::base_local` method and improve doc for `Place::local` to clarify why we need the former. --- src/librustc/mir/mod.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 2587e19b1cb62..883a9d6497b0b 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1967,7 +1967,10 @@ impl<'tcx> Place<'tcx> { Place::Projection(Box::new(PlaceProjection { base: self, elem })) } - /// Find the innermost `Local` from this `Place`. + /// Find the innermost `Local` from this `Place`, *if* it is either a local itself or + /// a single deref of a local. + /// + /// FIXME: can we safely swap the semantics of `fn base_local` below in here instead? pub fn local(&self) -> Option { match self { Place::Local(local) | @@ -1978,6 +1981,15 @@ impl<'tcx> Place<'tcx> { _ => None, } } + + /// Find the innermost `Local` from this `Place`. + pub fn base_local(&self) -> Option { + match self { + Place::Local(local) => Some(*local), + Place::Projection(box Projection { base, elem: _ }) => base.base_local(), + Place::Promoted(..) | Place::Static(..) => None, + } + } } impl<'tcx> Debug for Place<'tcx> { From bc61541423a3281b6305de1616939c9ead42364d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 9 Oct 2018 23:14:31 +0200 Subject: [PATCH 2/9] Make us error consistently in issue #21232, to fix #54986. Treat attempt to partially intialize local `l` as uses of a `mut` in `let mut l;`, to fix #54499. --- .../borrow_check/error_reporting.rs | 25 +++-- src/librustc_mir/borrow_check/mod.rs | 104 ++++++++++++++++-- 2 files changed, 109 insertions(+), 20 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 53a190efb5835..546746aa72ebb 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -51,16 +51,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &mut self, context: Context, desired_action: InitializationRequiringAction, - (place, span): (&Place<'tcx>, Span), + (moved_place, used_place, span): (&Place<'tcx>, &Place<'tcx>, Span), mpi: MovePathIndex, ) { debug!( - "report_use_of_moved_or_uninitialized: context={:?} desired_action={:?} place={:?} \ - span={:?} mpi={:?}", - context, desired_action, place, span, mpi + "report_use_of_moved_or_uninitialized: context={:?} desired_action={:?} \ + moved_place={:?} used_place={:?} span={:?} mpi={:?}", + context, desired_action, moved_place, used_place, span, mpi ); - let use_spans = self.move_spans(place, context.loc) + let use_spans = self.move_spans(moved_place, context.loc) .or_else(|| self.borrow_spans(span, context.loc)); let span = use_spans.args_or_use(); @@ -75,7 +75,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .collect(); if move_out_indices.is_empty() { - let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap(); + let root_place = self.prefixes(&used_place, PrefixSet::All).last().unwrap(); if self.uninitialized_error_reported .contains(&root_place.clone()) @@ -89,14 +89,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.uninitialized_error_reported.insert(root_place.clone()); - let item_msg = match self.describe_place_with_options(place, IncludingDowncast(true)) { + let item_msg = match self.describe_place_with_options(used_place, + IncludingDowncast(true)) { Some(name) => format!("`{}`", name), None => "value".to_owned(), }; let mut err = self.infcx.tcx.cannot_act_on_uninitialized_variable( span, desired_action.as_noun(), - &self.describe_place_with_options(place, IncludingDowncast(true)) + &self.describe_place_with_options(moved_place, IncludingDowncast(true)) .unwrap_or("_".to_owned()), Origin::Mir, ); @@ -111,7 +112,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } else { if let Some((reported_place, _)) = self.move_error_reported.get(&move_out_indices) { if self.prefixes(&reported_place, PrefixSet::All) - .any(|p| p == place) + .any(|p| p == used_place) { debug!( "report_use_of_moved_or_uninitialized place: error suppressed \ @@ -128,7 +129,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { span, desired_action.as_noun(), msg, - self.describe_place_with_options(&place, IncludingDowncast(true)), + self.describe_place_with_options(&moved_place, IncludingDowncast(true)), Origin::Mir, ); @@ -181,7 +182,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); } - if let Some(ty) = self.retrieve_type_for_place(place) { + if let Some(ty) = self.retrieve_type_for_place(used_place) { let needs_note = match ty.sty { ty::Closure(id, _) => { let tables = self.infcx.tcx.typeck_tables_of(id); @@ -219,7 +220,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } if let Some((_, mut old_err)) = self.move_error_reported - .insert(move_out_indices, (place.clone(), err)) + .insert(move_out_indices, (used_place.clone(), err)) { // Cancel the old error so it doesn't ICE. old_err.cancel(); diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 9cbaf35acd33f..108d480be9a33 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -853,6 +853,7 @@ enum InitializationRequiringAction { MatchOn, Use, Assignment, + PartialAssignment, } struct RootPlace<'d, 'tcx: 'd> { @@ -868,6 +869,7 @@ impl InitializationRequiringAction { InitializationRequiringAction::MatchOn => "use", // no good noun InitializationRequiringAction::Use => "use", InitializationRequiringAction::Assignment => "assign", + InitializationRequiringAction::PartialAssignment => "assign to part", } } @@ -878,6 +880,7 @@ impl InitializationRequiringAction { InitializationRequiringAction::MatchOn => "matched on", InitializationRequiringAction::Use => "used", InitializationRequiringAction::Assignment => "assigned", + InitializationRequiringAction::PartialAssignment => "partially assigned", } } } @@ -1498,12 +1501,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { debug!("check_if_full_path_is_moved place: {:?}", place_span.0); match self.move_path_closest_to(place_span.0) { - Ok(mpi) => { + Ok((prefix, mpi)) => { if maybe_uninits.contains(mpi) { self.report_use_of_moved_or_uninitialized( context, desired_action, - place_span, + (prefix, place_span.0, place_span.1), mpi, ); return; // don't bother finding other problems. @@ -1561,7 +1564,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.report_use_of_moved_or_uninitialized( context, desired_action, - place_span, + (place_span.0, place_span.0, place_span.1), child_mpi, ); return; // don't bother finding other problems. @@ -1579,14 +1582,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// An Err result includes a tag indicated why the search failed. /// Currently this can only occur if the place is built off of a /// static variable, as we do not track those in the MoveData. - fn move_path_closest_to( + fn move_path_closest_to<'a>( &mut self, - place: &Place<'tcx>, - ) -> Result { + place: &'a Place<'tcx>, + ) -> Result<(&'a Place<'tcx>, MovePathIndex), NoMovePathFound> where 'cx: 'a { let mut last_prefix = place; for prefix in self.prefixes(place, PrefixSet::All) { if let Some(mpi) = self.move_path_for_place(prefix) { - return Ok(mpi); + return Ok((prefix, mpi)); } last_prefix = prefix; } @@ -1667,6 +1670,26 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // recur further) break; } + + + // Once `let s; s.x = V; read(s.x);`, + // is allowed, remove this match arm. + ty::Adt(..) | ty::Tuple(..) => { + check_parent_of_field(self, context, base, span, flow_state); + + if let Some(local) = place.base_local() { + // rust-lang/rust#21232, + // #54499, #54986: during + // period where we reject + // partial initialization, do + // not complain about + // unnecessary `mut` on an + // attempt to do a partial + // initialization. + self.used_mut.insert(local); + } + } + _ => {} } } @@ -1677,8 +1700,73 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } } - } + fn check_parent_of_field<'cx, 'gcx, 'tcx>(this: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>, + context: Context, + base: &Place<'tcx>, + span: Span, + flow_state: &Flows<'cx, 'gcx, 'tcx>) + { + // rust-lang/rust#21232: Until Rust allows reads from the + // initialized parts of partially initialized structs, we + // will, starting with the 2018 edition, reject attempts + // to write to structs that are not fully initialized. + // + // In other words, *until* we allow this: + // + // 1. `let mut s; s.x = Val; read(s.x);` + // + // we will for now disallow this: + // + // 2. `let mut s; s.x = Val;` + // + // and also this: + // + // 3. `let mut s = ...; drop(s); s.x=Val;` + // + // This does not use check_if_path_or_subpath_is_moved, + // because we want to *allow* reinitializations of fields: + // e.g. want to allow + // + // `let mut s = ...; drop(s.x); s.x=Val;` + // + // This does not use check_if_full_path_is_moved on + // `base`, because that would report an error about the + // `base` as a whole, but in this scenario we *really* + // want to report an error about the actual thing that was + // moved, which may be some prefix of `base`. + + // Shallow so that we'll stop at any dereference; we'll + // report errors about issues with such bases elsewhere. + let maybe_uninits = &flow_state.uninits; + + // Find the shortest uninitialized prefix you can reach + // without going over a Deref. + let mut shortest_uninit_seen = None; + for prefix in this.prefixes(base, PrefixSet::Shallow) { + let mpi = match this.move_path_for_place(prefix) { + Some(mpi) => mpi, None => continue, + }; + + if maybe_uninits.contains(mpi) { + debug!("check_parent_of_field updating shortest_uninit_seen from {:?} to {:?}", + shortest_uninit_seen, Some((prefix, mpi))); + shortest_uninit_seen = Some((prefix, mpi)); + } else { + debug!("check_parent_of_field {:?} is definitely initialized", (prefix, mpi)); + } + } + + if let Some((prefix, mpi)) = shortest_uninit_seen { + this.report_use_of_moved_or_uninitialized( + context, + InitializationRequiringAction::PartialAssignment, + (prefix, base, span), + mpi, + ); + } + } + } /// Check the permissions for the given place and read or write kind /// From d0416cc093937473aa96908e2e574aa32a1ac12b Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 16 Oct 2018 15:45:24 +0200 Subject: [PATCH 3/9] Add helper method to determine if local had ever been initialized at current point in flow. --- src/librustc_mir/borrow_check/mod.rs | 44 ++++++++++++++++------------ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 108d480be9a33..f9a1e1e110825 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -36,9 +36,8 @@ use std::collections::BTreeMap; 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::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex}; +use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MoveError}; use dataflow::Borrows; use dataflow::DataflowResultsConsumer; use dataflow::FlowAtLocation; @@ -1442,10 +1441,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { debug!("check_if_reassignment_to_immutable_state({:?})", local); // 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)); - if let Some(&init_index) = first_init_index { + if let Some(init_index) = self.is_local_ever_initialized(local, flow_state) { // And, if so, report an error. let init = &self.move_data.inits[init_index]; let span = init.span(&self.mir); @@ -1889,6 +1885,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { return true; } + fn is_local_ever_initialized(&self, + local: Local, + flow_state: &Flows<'cx, 'gcx, 'tcx>) + -> Option + { + let mpi = self.move_data.rev_lookup.find_local(local); + let ii = &self.move_data.init_path_map[mpi]; + for &index in ii { + if flow_state.ever_inits.contains(index) { + return Some(index); + } + } + return None; + } + /// Adds the place into the used mutable variables set fn add_used_mut<'d>( &mut self, @@ -1900,18 +1911,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { place: Place::Local(local), is_local_mutation_allowed, } => { - if is_local_mutation_allowed != LocalMutationIsAllowed::Yes { - // If the local may be initialized, and it is now currently being - // mutated, then it is justified to be annotated with the `mut` - // keyword, since the mutation may be a possible reassignment. - let mpi = self.move_data.rev_lookup.find_local(*local); - let ii = &self.move_data.init_path_map[mpi]; - for &index in ii { - if flow_state.ever_inits.contains(index) { - self.used_mut.insert(*local); - break; - } - } + // If the local may have been initialized, and it is now currently being + // mutated, then it is justified to be annotated with the `mut` + // keyword, since the mutation may be a possible reassignment. + if is_local_mutation_allowed != LocalMutationIsAllowed::Yes && + self.is_local_ever_initialized(*local, flow_state).is_some() + { + self.used_mut.insert(*local); } } RootPlace { From 57c467824bf72e0346fc7bc7140e232664c4e891 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 16 Oct 2018 15:50:44 +0200 Subject: [PATCH 4/9] Cleanup `fn is_mutable` by removing some unnecessary control-flow breaks. (This makes it a little easier to add instrumentation of the entry and exit by adding `debug!` at the beginning and end, though note that the function body *does* use the `?` operator...) --- src/librustc_mir/borrow_check/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index f9a1e1e110825..ae79394dfebe0 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1943,7 +1943,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - /// Whether this value be written or borrowed mutably. + /// Whether this value can be written or borrowed mutably. /// Returns the root place if the place passed in is a projection. fn is_mutable<'d>( &self, @@ -2021,14 +2021,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ty::RawPtr(tnm) => { match tnm.mutbl { // `*const` raw pointers are not mutable - hir::MutImmutable => return Err(place), + hir::MutImmutable => Err(place), // `*mut` raw pointers are always mutable, regardless of // context. The users have to check by themselves. hir::MutMutable => { - return Ok(RootPlace { + Ok(RootPlace { place, is_local_mutation_allowed, - }); + }) } } } From 3587ff58cce2f00d1be4d4e09d85b4ca9b4baff7 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 16 Oct 2018 16:46:04 +0200 Subject: [PATCH 5/9] Don't complain re missing `mut` on attempt to partially initialize an uninitialized struct. Under the semantics of #54986 (our short term plan), the partial initialization itself will signal an error. We don't need to add noise to the output by also complaining about `mut`. (In particular, the user may well revise their code in a way that does not require `mut`.) --- src/librustc_mir/borrow_check/mod.rs | 32 ++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index ae79394dfebe0..1f8d077fb6904 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1776,13 +1776,23 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { location: Location, ) -> bool { debug!( - "check_access_permissions({:?}, {:?}, {:?})", + "check_access_permissions({:?}, {:?}, is_local_mutation_allowed: {:?})", place, kind, is_local_mutation_allowed ); let error_access; let the_place_err; + // rust-lang/rust#21232, #54986: during period where we reject + // partial initialization, do not complain about mutability + // errors except for actual mutation (as opposed to an attempt + // to do a partial initialization). + let previously_initialized = if let Some(local) = place.base_local() { + self.is_local_ever_initialized(local, flow_state).is_some() + } else { + true + }; + match kind { Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Unique)) | Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. })) @@ -1875,14 +1885,18 @@ 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, - ); - return true; + if previously_initialized { + self.report_mutability_error( + place, + span, + the_place_err, + error_access, + location, + ); + return true; + } else { + return false; + } } fn is_local_ever_initialized(&self, From 42297390386a9b3f55fec7299b27ee51f41796e3 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 16 Oct 2018 17:07:41 +0200 Subject: [PATCH 6/9] Add ignore-compare-mode-nll to some run-pass tests that become compile-fail under #54986. --- src/test/run-pass/issues/issue-26996.rs | 14 ++++++++++++++ src/test/run-pass/issues/issue-27021.rs | 16 ++++++++++++++++ src/test/run-pass/issues/issue-49298.rs | 16 ++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/src/test/run-pass/issues/issue-26996.rs b/src/test/run-pass/issues/issue-26996.rs index 8d53b739da293..83445c6657e93 100644 --- a/src/test/run-pass/issues/issue-26996.rs +++ b/src/test/run-pass/issues/issue-26996.rs @@ -9,6 +9,20 @@ // except according to those terms. // run-pass + +// This test is bogus (i.e. should be compile-fail) during the period +// where #54986 is implemented and #54987 is *not* implemented. For +// now: just ignore it under nll +// +// ignore-compare-mode-nll + +// This test is checking that the write to `c.0` (which has been moved out of) +// won't overwrite the state in `c2`. +// +// That's a fine thing to test when this code is accepted by the +// compiler, and this code is being transcribed accordingly into +// the ui test issue-21232-partial-init-and-use.rs + fn main() { let mut c = (1, "".to_owned()); match c { diff --git a/src/test/run-pass/issues/issue-27021.rs b/src/test/run-pass/issues/issue-27021.rs index addeebe9def16..dbad8556aeb23 100644 --- a/src/test/run-pass/issues/issue-27021.rs +++ b/src/test/run-pass/issues/issue-27021.rs @@ -9,6 +9,22 @@ // except according to those terms. // run-pass + +// This test is bogus (i.e. should be compile-fail) during the period +// where #54986 is implemented and #54987 is *not* implemented. For +// now: just ignore it under nll +// +// ignore-compare-mode-nll + +// These are variants of issue-26996.rs. In all cases we are writing +// into a record field that has been moved out of, and ensuring that +// such a write won't overwrite the state of the thing it was moved +// into. +// +// That's a fine thing to test when this code is accepted by the +// compiler, and this code is being transcribed accordingly into +// the ui test issue-21232-partial-init-and-use.rs + fn main() { let mut c = (1, (1, "".to_owned())); match c { diff --git a/src/test/run-pass/issues/issue-49298.rs b/src/test/run-pass/issues/issue-49298.rs index 6463adc48a8cb..db3c9792f3560 100644 --- a/src/test/run-pass/issues/issue-49298.rs +++ b/src/test/run-pass/issues/issue-49298.rs @@ -12,6 +12,22 @@ #![feature(test)] #![allow(unused_mut)] // under NLL we get warning about `x` below: rust-lang/rust#54499 +// This test is bogus (i.e. should be compile-fail) during the period +// where #54986 is implemented and #54987 is *not* implemented. For +// now: just ignore it under nll +// +// ignore-compare-mode-nll + +// This test is checking that the space allocated for `x.1` does not +// overlap with `y`. (The reason why such a thing happened at one +// point was because `x.0: Void` and thus the whole type of `x` was +// uninhabited, and so the compiler thought it was safe to use the +// space of `x.1` to hold `y`.) +// +// That's a fine thing to test when this code is accepted by the +// compiler, and this code is being transcribed accordingly into +// the ui test issue-21232-partial-init-and-use.rs + extern crate test; enum Void {} From b10beb3233afcb8622246fd0d5ae4b64e2281f20 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 16 Oct 2018 17:08:59 +0200 Subject: [PATCH 7/9] updates to existing ui/borrowck tests. --- .../borrowck/assign_mutable_fields.nll.stderr | 16 +++++--- .../borrowck-field-sensitivity.nll.stderr | 28 ++++++++++--- .../borrowck-init-in-fru.ast.nll.stderr | 2 +- .../borrowck/borrowck-init-in-fru.mir.stderr | 2 +- ...orrowck-uninit-field-access.ast.nll.stderr | 4 +- .../borrowck-uninit-field-access.mir.stderr | 4 +- .../borrowck-uninit-ref-chain.ast.nll.stderr | 36 ++++++++++------ .../borrowck-uninit-ref-chain.mir.stderr | 36 ++++++++++------ .../ui/borrowck/borrowck-uninit-ref-chain.rs | 16 ++++---- .../borrowck-union-move-assign.nll.stderr | 6 +-- .../borrowck/borrowck-union-move.nll.stderr | 8 ++-- .../borrowck-union-uninitialized.nll.stderr | 16 +++++--- ...orrowck-use-in-index-lvalue.ast.nll.stderr | 4 +- .../borrowck-use-in-index-lvalue.mir.stderr | 4 +- ...uninitialized-in-cast-trait.ast.nll.stderr | 2 +- ...use-uninitialized-in-cast-trait.mir.stderr | 2 +- ...k-use-uninitialized-in-cast.ast.nll.stderr | 2 +- ...rowck-use-uninitialized-in-cast.mir.stderr | 2 +- .../reassignment_immutable_fields.nll.stderr | 41 +++---------------- ...nt_immutable_fields_overlapping.nll.stderr | 19 ++------- ...signment_immutable_fields_twice.nll.stderr | 29 +++---------- 21 files changed, 137 insertions(+), 142 deletions(-) diff --git a/src/test/ui/borrowck/assign_mutable_fields.nll.stderr b/src/test/ui/borrowck/assign_mutable_fields.nll.stderr index 5147075347283..59af97d9f13db 100644 --- a/src/test/ui/borrowck/assign_mutable_fields.nll.stderr +++ b/src/test/ui/borrowck/assign_mutable_fields.nll.stderr @@ -1,9 +1,15 @@ -error[E0381]: use of possibly uninitialized variable: `x` - --> $DIR/assign_mutable_fields.rs:29:10 +error[E0381]: assign to part of possibly uninitialized variable: `x` + --> $DIR/assign_mutable_fields.rs:19:5 | -LL | drop(x); //~ ERROR - | ^ use of possibly uninitialized `x` +LL | x.0 = 1; + | ^^^^^^^ use of possibly uninitialized `x` -error: aborting due to previous error +error[E0381]: assign to part of possibly uninitialized variable: `x` + --> $DIR/assign_mutable_fields.rs:27:5 + | +LL | x.0 = 1; + | ^^^^^^^ use of possibly uninitialized `x` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr index 6ac5fef1416af..81d9e958e28e2 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr +++ b/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr @@ -1,4 +1,4 @@ -error[E0382]: use of moved value: `*x.b` +error[E0382]: use of moved value: `x.b` --> $DIR/borrowck-field-sensitivity.rs:18:10 | LL | drop(x.b); @@ -6,7 +6,7 @@ LL | drop(x.b); LL | drop(*x.b); //~ ERROR use of moved value: `*x.b` | ^^^^ value used here after move -error[E0382]: use of moved value: `*x.b` +error[E0382]: use of moved value: `x.b` --> $DIR/borrowck-field-sensitivity.rs:24:10 | LL | let y = A { a: 3, .. x }; @@ -104,7 +104,25 @@ LL | let _z = A { a: 4, .. x }; //~ ERROR use of moved value: `x.b` | = note: move occurs because `x.b` has type `std::boxed::Box`, which does not implement the `Copy` trait -error: aborting due to 11 previous errors +error[E0381]: assign to part of possibly uninitialized variable: `x` + --> $DIR/borrowck-field-sensitivity.rs:91:5 + | +LL | x.a = 1; + | ^^^^^^^ use of possibly uninitialized `x` + +error[E0381]: assign to part of possibly uninitialized variable: `x` + --> $DIR/borrowck-field-sensitivity.rs:97:5 + | +LL | x.a = 1; + | ^^^^^^^ use of possibly uninitialized `x` + +error[E0381]: assign to part of possibly uninitialized variable: `x` + --> $DIR/borrowck-field-sensitivity.rs:104:5 + | +LL | x.b = box 1; + | ^^^ use of possibly uninitialized `x` + +error: aborting due to 14 previous errors -Some errors occurred: E0382, E0499, E0505. -For more information about an error, try `rustc --explain E0382`. +Some errors occurred: E0381, E0382, E0499, E0505. +For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.ast.nll.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.ast.nll.stderr index cac9d890dae0f..e602597844457 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fru.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-fru.ast.nll.stderr @@ -1,4 +1,4 @@ -error[E0381]: use of possibly uninitialized variable: `origin.y` +error[E0381]: use of possibly uninitialized variable: `origin` --> $DIR/borrowck-init-in-fru.rs:22:5 | LL | origin = point {x: 10,.. origin}; diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.mir.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.mir.stderr index cac9d890dae0f..e602597844457 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fru.mir.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-fru.mir.stderr @@ -1,4 +1,4 @@ -error[E0381]: use of possibly uninitialized variable: `origin.y` +error[E0381]: use of possibly uninitialized variable: `origin` --> $DIR/borrowck-init-in-fru.rs:22:5 | LL | origin = point {x: 10,.. origin}; diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr index 9c7dbd7e77884..97eb83d0f14ef 100644 --- a/src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-field-access.ast.nll.stderr @@ -1,10 +1,10 @@ -error[E0381]: use of possibly uninitialized variable: `a.x` +error[E0381]: use of possibly uninitialized variable: `a` --> $DIR/borrowck-uninit-field-access.rs:34:13 | LL | let _ = a.x + 1; //[ast]~ ERROR use of possibly uninitialized variable: `a.x` | ^^^ use of possibly uninitialized `a.x` -error[E0382]: use of moved value: `line1.origin.x` +error[E0382]: use of moved value: `line1.origin` --> $DIR/borrowck-uninit-field-access.rs:39:13 | LL | let _moved = line1.origin; diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr index 9c7dbd7e77884..97eb83d0f14ef 100644 --- a/src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-field-access.mir.stderr @@ -1,10 +1,10 @@ -error[E0381]: use of possibly uninitialized variable: `a.x` +error[E0381]: use of possibly uninitialized variable: `a` --> $DIR/borrowck-uninit-field-access.rs:34:13 | LL | let _ = a.x + 1; //[ast]~ ERROR use of possibly uninitialized variable: `a.x` | ^^^ use of possibly uninitialized `a.x` -error[E0382]: use of moved value: `line1.origin.x` +error[E0382]: use of moved value: `line1.origin` --> $DIR/borrowck-uninit-field-access.rs:39:13 | LL | let _moved = line1.origin; diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr index bd9836e3174fb..e9caf7d9e1e7e 100644 --- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.ast.nll.stderr @@ -1,33 +1,45 @@ -error[E0381]: borrow of possibly uninitialized variable: `**x` +error[E0381]: borrow of possibly uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:21:14 | LL | let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381] | ^^^^ use of possibly uninitialized `**x` -error[E0381]: borrow of possibly uninitialized variable: `**x` +error[E0381]: borrow of possibly uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:25:14 | LL | let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381] | ^^^^ use of possibly uninitialized `**x` -error[E0381]: borrow of possibly uninitialized variable: `**x` +error[E0381]: borrow of possibly uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:29:14 | LL | let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381] | ^^^^ use of possibly uninitialized `**x` -error[E0381]: borrow of possibly uninitialized variable: `a.y` - --> $DIR/borrowck-uninit-ref-chain.rs:46:14 +error[E0381]: assign to part of possibly uninitialized variable: `a` + --> $DIR/borrowck-uninit-ref-chain.rs:34:5 | -LL | let _b = &a.y; //[ast]~ ERROR use of possibly uninitialized variable: `a.y` [E0381] - | ^^^^ use of possibly uninitialized `a.y` +LL | a.x = 0; //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + | ^^^^^^^ use of possibly uninitialized `a` -error[E0381]: borrow of possibly uninitialized variable: `**a.y` - --> $DIR/borrowck-uninit-ref-chain.rs:51:14 +error[E0381]: assign to part of possibly uninitialized variable: `a` + --> $DIR/borrowck-uninit-ref-chain.rs:39:5 | -LL | let _b = &**a.y; //[ast]~ ERROR use of possibly uninitialized variable: `**a.y` [E0381] - | ^^^^^^ use of possibly uninitialized `**a.y` +LL | a.x = &&0; //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + | ^^^^^^^^^ use of possibly uninitialized `a` -error: aborting due to 5 previous errors +error[E0381]: assign to part of possibly uninitialized variable: `a` + --> $DIR/borrowck-uninit-ref-chain.rs:45:5 + | +LL | a.x = 0; //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + | ^^^^^^^ use of possibly uninitialized `a` + +error[E0381]: assign to part of possibly uninitialized variable: `a` + --> $DIR/borrowck-uninit-ref-chain.rs:50:5 + | +LL | a.x = &&0; //[mir]~ assign to part of possibly uninitialized variable: `a` [E0381] + | ^^^^^^^^^ use of possibly uninitialized `a` + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0381`. 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..e9caf7d9e1e7e 100644 --- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.mir.stderr @@ -1,33 +1,45 @@ -error[E0381]: borrow of possibly uninitialized variable: `**x` +error[E0381]: borrow of possibly uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:21:14 | LL | let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381] | ^^^^ use of possibly uninitialized `**x` -error[E0381]: borrow of possibly uninitialized variable: `**x` +error[E0381]: borrow of possibly uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:25:14 | LL | let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381] | ^^^^ use of possibly uninitialized `**x` -error[E0381]: borrow of possibly uninitialized variable: `**x` +error[E0381]: borrow of possibly uninitialized variable: `x` --> $DIR/borrowck-uninit-ref-chain.rs:29:14 | LL | let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381] | ^^^^ use of possibly uninitialized `**x` -error[E0381]: borrow of possibly uninitialized variable: `a.y` - --> $DIR/borrowck-uninit-ref-chain.rs:46:14 +error[E0381]: assign to part of possibly uninitialized variable: `a` + --> $DIR/borrowck-uninit-ref-chain.rs:34:5 | -LL | let _b = &a.y; //[ast]~ ERROR use of possibly uninitialized variable: `a.y` [E0381] - | ^^^^ use of possibly uninitialized `a.y` +LL | a.x = 0; //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + | ^^^^^^^ use of possibly uninitialized `a` -error[E0381]: borrow of possibly uninitialized variable: `**a.y` - --> $DIR/borrowck-uninit-ref-chain.rs:51:14 +error[E0381]: assign to part of possibly uninitialized variable: `a` + --> $DIR/borrowck-uninit-ref-chain.rs:39:5 | -LL | let _b = &**a.y; //[ast]~ ERROR use of possibly uninitialized variable: `**a.y` [E0381] - | ^^^^^^ use of possibly uninitialized `**a.y` +LL | a.x = &&0; //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + | ^^^^^^^^^ use of possibly uninitialized `a` -error: aborting due to 5 previous errors +error[E0381]: assign to part of possibly uninitialized variable: `a` + --> $DIR/borrowck-uninit-ref-chain.rs:45:5 + | +LL | a.x = 0; //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] + | ^^^^^^^ use of possibly uninitialized `a` + +error[E0381]: assign to part of possibly uninitialized variable: `a` + --> $DIR/borrowck-uninit-ref-chain.rs:50:5 + | +LL | a.x = &&0; //[mir]~ assign to part of possibly uninitialized variable: `a` [E0381] + | ^^^^^^^^^ use of possibly uninitialized `a` + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs index c52b1f0bf64c0..dc9d8405102ee 100644 --- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs +++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs @@ -31,23 +31,23 @@ fn main() { let mut a: S; - a.x = 0; + a.x = 0; //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] let _b = &a.x; //[ast]~ ERROR use of possibly uninitialized variable: `a.x` [E0381] - // (deliberately *not* an error under MIR-borrowck) + let mut a: S<&&i32, &&i32>; - a.x = &&0; + a.x = &&0; //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] let _b = &**a.x; //[ast]~ ERROR use of possibly uninitialized variable: `**a.x` [E0381] - // (deliberately *not* an error under MIR-borrowck) + let mut a: S; - a.x = 0; + a.x = 0; //[mir]~ ERROR assign to part of possibly uninitialized variable: `a` [E0381] let _b = &a.y; //[ast]~ ERROR use of possibly uninitialized variable: `a.y` [E0381] - //[mir]~^ ERROR [E0381] + let mut a: S<&&i32, &&i32>; - a.x = &&0; + a.x = &&0; //[mir]~ assign to part of possibly uninitialized variable: `a` [E0381] let _b = &**a.y; //[ast]~ ERROR use of possibly uninitialized variable: `**a.y` [E0381] - //[mir]~^ ERROR [E0381] + } diff --git a/src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr b/src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr index 2a877050e4c87..423a44514db81 100644 --- a/src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr +++ b/src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr @@ -1,4 +1,4 @@ -error[E0382]: use of moved value: `u.a` +error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move-assign.rs:27:21 | LL | let a = u.a; @@ -8,7 +8,7 @@ LL | let a = u.a; //~ ERROR use of moved value: `u.a` | = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `u.a` +error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move-assign.rs:33:21 | LL | let a = u.a; @@ -19,7 +19,7 @@ LL | let a = u.a; // OK | = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `u.a` +error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move-assign.rs:39:21 | LL | let a = u.a; diff --git a/src/test/ui/borrowck/borrowck-union-move.nll.stderr b/src/test/ui/borrowck/borrowck-union-move.nll.stderr index 6fd6a1c82a1a0..8597117dbcc8a 100644 --- a/src/test/ui/borrowck/borrowck-union-move.nll.stderr +++ b/src/test/ui/borrowck/borrowck-union-move.nll.stderr @@ -1,4 +1,4 @@ -error[E0382]: use of moved value: `u.n1` +error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move.rs:36:21 | LL | let a = u.n1; @@ -18,7 +18,7 @@ LL | let a = u; //~ ERROR use of partially moved value: `u` | = note: move occurs because `u` has type `Unn`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `u.n2` +error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move.rs:46:21 | LL | let a = u.n1; @@ -28,7 +28,7 @@ LL | let a = u.n2; //~ ERROR use of moved value: `u.n2` | = note: move occurs because `u` has type `Unn`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `u.n` +error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move.rs:73:21 | LL | let a = u.n; @@ -38,7 +38,7 @@ LL | let a = u.n; //~ ERROR use of moved value: `u.n` | = note: move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `u.c` +error[E0382]: use of moved value: `u` --> $DIR/borrowck-union-move.rs:78:21 | LL | let a = u.n; diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.nll.stderr b/src/test/ui/borrowck/borrowck-union-uninitialized.nll.stderr index 49bc6d3263660..94a7a4866e6b9 100644 --- a/src/test/ui/borrowck/borrowck-union-uninitialized.nll.stderr +++ b/src/test/ui/borrowck/borrowck-union-uninitialized.nll.stderr @@ -1,9 +1,15 @@ -error[E0381]: use of possibly uninitialized variable: `u.a` - --> $DIR/borrowck-union-uninitialized.rs:26:18 +error[E0381]: assign to part of possibly uninitialized variable: `s` + --> $DIR/borrowck-union-uninitialized.rs:23:9 | -LL | let ua = u.a; //~ ERROR use of possibly uninitialized variable: `u.a` - | ^^^ use of possibly uninitialized `u.a` +LL | s.a = 0; + | ^^^^^^^ use of possibly uninitialized `s` -error: aborting due to previous error +error[E0381]: assign to part of possibly uninitialized variable: `u` + --> $DIR/borrowck-union-uninitialized.rs:24:9 + | +LL | u.a = 0; + | ^^^^^^^ use of possibly uninitialized `u` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr index d69693eb03532..502978f25be94 100644 --- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.ast.nll.stderr @@ -1,10 +1,10 @@ -error[E0381]: use of possibly uninitialized variable: `*w` +error[E0381]: use of possibly uninitialized variable: `w` --> $DIR/borrowck-use-in-index-lvalue.rs:16:5 | LL | w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381] | ^^^^ use of possibly uninitialized `*w` -error[E0381]: use of possibly uninitialized variable: `*w` +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] 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..502978f25be94 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 @@ -1,10 +1,10 @@ -error[E0381]: use of possibly uninitialized variable: `*w` +error[E0381]: use of possibly uninitialized variable: `w` --> $DIR/borrowck-use-in-index-lvalue.rs:16:5 | LL | w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381] | ^^^^ use of possibly uninitialized `*w` -error[E0381]: use of possibly uninitialized variable: `*w` +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] diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr index b96379db650bb..22e95ca3ad0e2 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.ast.nll.stderr @@ -1,4 +1,4 @@ -error[E0381]: borrow of possibly uninitialized variable: `*x` +error[E0381]: borrow of possibly uninitialized variable: `x` --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:22:13 | LL | let y = x as *const Foo; //[ast]~ ERROR use of possibly uninitialized variable: `*x` diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr index b96379db650bb..22e95ca3ad0e2 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.mir.stderr @@ -1,4 +1,4 @@ -error[E0381]: borrow of possibly uninitialized variable: `*x` +error[E0381]: borrow of possibly uninitialized variable: `x` --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:22:13 | LL | let y = x as *const Foo; //[ast]~ ERROR use of possibly uninitialized variable: `*x` diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr index 6eddbd934d54e..11897f50910e1 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.ast.nll.stderr @@ -1,4 +1,4 @@ -error[E0381]: borrow of possibly uninitialized variable: `*x` +error[E0381]: borrow of possibly uninitialized variable: `x` --> $DIR/borrowck-use-uninitialized-in-cast.rs:20:13 | LL | let y = x as *const i32; //[ast]~ ERROR use of possibly uninitialized variable: `*x` [E0381] diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr index 6eddbd934d54e..11897f50910e1 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.mir.stderr @@ -1,4 +1,4 @@ -error[E0381]: borrow of possibly uninitialized variable: `*x` +error[E0381]: borrow of possibly uninitialized variable: `x` --> $DIR/borrowck-use-uninitialized-in-cast.rs:20:13 | LL | let y = x as *const i32; //[ast]~ ERROR use of possibly uninitialized variable: `*x` [E0381] diff --git a/src/test/ui/borrowck/reassignment_immutable_fields.nll.stderr b/src/test/ui/borrowck/reassignment_immutable_fields.nll.stderr index 97f3bf5b81f66..1f0938dd3d27b 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields.nll.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields.nll.stderr @@ -1,44 +1,15 @@ -error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable +error[E0381]: assign to part of possibly uninitialized variable: `x` --> $DIR/reassignment_immutable_fields.rs:17:5 | -LL | let x: (u32, u32); - | - help: consider changing this to be mutable: `mut x` LL | x.0 = 1; //~ ERROR - | ^^^^^^^ cannot assign + | ^^^^^^^ use of possibly uninitialized `x` -error[E0594]: cannot assign to `x.1`, as `x` is not declared as mutable - --> $DIR/reassignment_immutable_fields.rs:18:5 - | -LL | let x: (u32, u32); - | - help: consider changing this to be mutable: `mut x` -LL | x.0 = 1; //~ ERROR -LL | x.1 = 22; //~ ERROR - | ^^^^^^^^ cannot assign - -error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable +error[E0381]: assign to part of possibly uninitialized variable: `x` --> $DIR/reassignment_immutable_fields.rs:25:5 | -LL | let x: (u32, u32); - | - help: consider changing this to be mutable: `mut x` -LL | x.0 = 1; //~ ERROR - | ^^^^^^^ cannot assign - -error[E0594]: cannot assign to `x.1`, as `x` is not declared as mutable - --> $DIR/reassignment_immutable_fields.rs:26:5 - | -LL | let x: (u32, u32); - | - help: consider changing this to be mutable: `mut x` LL | x.0 = 1; //~ ERROR -LL | x.1 = 22; //~ ERROR - | ^^^^^^^^ cannot assign - -error[E0381]: use of possibly uninitialized variable: `x` - --> $DIR/reassignment_immutable_fields.rs:27:10 - | -LL | drop(x); //~ ERROR - | ^ use of possibly uninitialized `x` + | ^^^^^^^ use of possibly uninitialized `x` -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors -Some errors occurred: E0381, E0594. -For more information about an error, try `rustc --explain E0381`. +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.nll.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.nll.stderr index c433d6e25c9de..7da9dbfc088cb 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.nll.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.nll.stderr @@ -1,20 +1,9 @@ -error[E0594]: cannot assign to `x.a`, as `x` is not declared as mutable +error[E0381]: assign to part of possibly uninitialized variable: `x` --> $DIR/reassignment_immutable_fields_overlapping.rs:22:5 | -LL | let x: Foo; - | - help: consider changing this to be mutable: `mut x` LL | x.a = 1; //~ ERROR - | ^^^^^^^ cannot assign + | ^^^^^^^ use of possibly uninitialized `x` -error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable - --> $DIR/reassignment_immutable_fields_overlapping.rs:23:5 - | -LL | let x: Foo; - | - help: consider changing this to be mutable: `mut x` -LL | x.a = 1; //~ ERROR -LL | x.b = 22; //~ ERROR - | ^^^^^^^^ cannot assign - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0594`. +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.nll.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.nll.stderr index 2160ae20c425a..96677be724131 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_twice.nll.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.nll.stderr @@ -7,32 +7,13 @@ LL | x = (22, 44); LL | x.0 = 1; //~ ERROR | ^^^^^^^ cannot assign -error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable +error[E0381]: assign to part of possibly uninitialized variable: `x` --> $DIR/reassignment_immutable_fields_twice.rs:22:5 | -LL | let x: (u32, u32); - | - help: consider changing this to be mutable: `mut x` -LL | x.0 = 1; //~ ERROR - | ^^^^^^^ cannot assign - -error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable - --> $DIR/reassignment_immutable_fields_twice.rs:23:5 - | -LL | let x: (u32, u32); - | - help: consider changing this to be mutable: `mut x` LL | x.0 = 1; //~ ERROR -LL | x.0 = 22; //~ ERROR - | ^^^^^^^^ cannot assign - -error[E0594]: cannot assign to `x.1`, as `x` is not declared as mutable - --> $DIR/reassignment_immutable_fields_twice.rs:24:5 - | -LL | let x: (u32, u32); - | - help: consider changing this to be mutable: `mut x` -... -LL | x.1 = 44; //~ ERROR - | ^^^^^^^^ cannot assign + | ^^^^^^^ use of possibly uninitialized `x` -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0594`. +Some errors occurred: E0381, E0594. +For more information about an error, try `rustc --explain E0381`. From 5b748434afe19c8ec8091413e843df9b3679da3e Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 16 Oct 2018 17:10:04 +0200 Subject: [PATCH 8/9] updates to expected output for other ui tests. --- src/test/ui/issues/issue-17385.nll.stderr | 2 +- .../issue-27282-move-match-input-into-guard.rs | 2 +- .../issue-27282-move-match-input-into-guard.stderr | 2 +- .../ui/liveness/liveness-use-after-move.nll.stderr | 2 +- src/test/ui/nll/issue-51512.rs | 2 +- src/test/ui/nll/issue-51512.stderr | 2 +- .../union-borrow-move-parent-sibling.nll.stderr | 6 +++--- .../use-after-move-self-based-on-type.nll.stderr | 13 +++++++++++++ src/test/ui/use/use-after-move-self.nll.stderr | 2 +- src/test/ui/walk-struct-literal-with.nll.stderr | 2 +- 10 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/use/use-after-move-self-based-on-type.nll.stderr diff --git a/src/test/ui/issues/issue-17385.nll.stderr b/src/test/ui/issues/issue-17385.nll.stderr index c7b0b57000f5e..cdc5a047c0724 100644 --- a/src/test/ui/issues/issue-17385.nll.stderr +++ b/src/test/ui/issues/issue-17385.nll.stderr @@ -1,4 +1,4 @@ -error[E0382]: use of moved value: `foo.0` +error[E0382]: use of moved value: `foo` --> $DIR/issue-17385.rs:29:11 | LL | drop(foo); diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.rs b/src/test/ui/issues/issue-27282-move-match-input-into-guard.rs index 909c369354bc3..769e5474e000a 100644 --- a/src/test/ui/issues/issue-27282-move-match-input-into-guard.rs +++ b/src/test/ui/issues/issue-27282-move-match-input-into-guard.rs @@ -26,7 +26,7 @@ fn main() { _ if { (|| { let bar = b; *bar = false; })(); false } => { }, &mut true => { println!("You might think we should get here"); }, - //~^ ERROR use of moved value: `*b` [E0382] + //~^ ERROR use of moved value: `b` [E0382] _ => panic!("surely we could never get here, since rustc warns it is unreachable."), } } diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr index 0b783e37615ee..5f3b07bd1e8b8 100644 --- a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr +++ b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr @@ -1,4 +1,4 @@ -error[E0382]: use of moved value: `*b` +error[E0382]: use of moved value: `b` --> $DIR/issue-27282-move-match-input-into-guard.rs:28:14 | LL | _ if { (|| { let bar = b; *bar = false; })(); diff --git a/src/test/ui/liveness/liveness-use-after-move.nll.stderr b/src/test/ui/liveness/liveness-use-after-move.nll.stderr index 62d9a8b115a19..463a64f4beca8 100644 --- a/src/test/ui/liveness/liveness-use-after-move.nll.stderr +++ b/src/test/ui/liveness/liveness-use-after-move.nll.stderr @@ -1,4 +1,4 @@ -error[E0382]: borrow of moved value: `*x` +error[E0382]: borrow of moved value: `x` --> $DIR/liveness-use-after-move.rs:16:20 | LL | let y = x; diff --git a/src/test/ui/nll/issue-51512.rs b/src/test/ui/nll/issue-51512.rs index 4543d2ba638c4..43debec69b5f2 100644 --- a/src/test/ui/nll/issue-51512.rs +++ b/src/test/ui/nll/issue-51512.rs @@ -15,5 +15,5 @@ fn main() { let range = 0..1; let r = range; let x = range.start; - //~^ ERROR use of moved value: `range.start` [E0382] + //~^ ERROR use of moved value: `range` [E0382] } diff --git a/src/test/ui/nll/issue-51512.stderr b/src/test/ui/nll/issue-51512.stderr index 102de43e5d710..49c419998a480 100644 --- a/src/test/ui/nll/issue-51512.stderr +++ b/src/test/ui/nll/issue-51512.stderr @@ -1,4 +1,4 @@ -error[E0382]: use of moved value: `range.start` +error[E0382]: use of moved value: `range` --> $DIR/issue-51512.rs:17:13 | LL | let r = range; diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr index 1ca2a56e757fb..a4f5e41b5291c 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr +++ b/src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr @@ -1,4 +1,4 @@ -error[E0382]: use of moved value: `u.y` +error[E0382]: use of moved value: `u` --> $DIR/union-borrow-move-parent-sibling.rs:29:13 | LL | let a = u.x.0; @@ -8,7 +8,7 @@ LL | let a = u.y; //~ ERROR use of moved value: `u.y` | = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `u.y` +error[E0382]: use of moved value: `u` --> $DIR/union-borrow-move-parent-sibling.rs:41:13 | LL | let a = (u.x.0).0; @@ -18,7 +18,7 @@ LL | let a = u.y; //~ ERROR use of moved value: `u.y` | = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `u.x` +error[E0382]: use of moved value: `u` --> $DIR/union-borrow-move-parent-sibling.rs:53:13 | LL | let a = *u.y; diff --git a/src/test/ui/use/use-after-move-self-based-on-type.nll.stderr b/src/test/ui/use/use-after-move-self-based-on-type.nll.stderr new file mode 100644 index 0000000000000..f13324955fab0 --- /dev/null +++ b/src/test/ui/use/use-after-move-self-based-on-type.nll.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `self` + --> $DIR/use-after-move-self-based-on-type.rs:22:16 + | +LL | self.bar(); + | ---- value moved here +LL | return self.x; //~ ERROR use of moved value: `self.x` + | ^^^^^^ value used here after move + | + = note: move occurs because `self` has type `S`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/use/use-after-move-self.nll.stderr b/src/test/ui/use/use-after-move-self.nll.stderr index 3b19e96d12cce..241dc32bb05e3 100644 --- a/src/test/ui/use/use-after-move-self.nll.stderr +++ b/src/test/ui/use/use-after-move-self.nll.stderr @@ -1,4 +1,4 @@ -error[E0382]: use of moved value: `*self.x` +error[E0382]: use of moved value: `self` --> $DIR/use-after-move-self.rs:20:16 | LL | self.bar(); diff --git a/src/test/ui/walk-struct-literal-with.nll.stderr b/src/test/ui/walk-struct-literal-with.nll.stderr index 668473882ab6e..e2c4a19debe4b 100644 --- a/src/test/ui/walk-struct-literal-with.nll.stderr +++ b/src/test/ui/walk-struct-literal-with.nll.stderr @@ -1,4 +1,4 @@ -error[E0382]: borrow of moved value: `start.test` +error[E0382]: borrow of moved value: `start` --> $DIR/walk-struct-literal-with.rs:26:20 | LL | let end = Mine{other_val:1, ..start.make_string_bar()}; From 233fdb4b1486b3b98bd1bb80f83138924a8a734e Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 12 Oct 2018 01:33:08 +0200 Subject: [PATCH 9/9] Some new tests I added. --- ...ield-mutation-marks-mut-as-used.ast.stderr | 39 +++ ...ield-mutation-marks-mut-as-used.nll.stderr | 21 ++ ...-54499-field-mutation-marks-mut-as-used.rs | 49 +++ ...-mutation-of-moved-out-with-mut.ast.stderr | 69 ++++ ...-mutation-of-moved-out-with-mut.nll.stderr | 33 ++ ...99-field-mutation-of-moved-out-with-mut.rs | 43 +++ ...499-field-mutation-of-moved-out.ast.stderr | 124 +++++++ ...499-field-mutation-of-moved-out.nll.stderr | 88 +++++ ...issue-54499-field-mutation-of-moved-out.rs | 64 ++++ ...99-field-mutation-of-never-init.ast.stderr | 91 +++++ ...99-field-mutation-of-never-init.nll.stderr | 21 ++ ...ssue-54499-field-mutation-of-never-init.rs | 55 ++++ ...ue-21232-partial-init-and-erroneous-use.rs | 66 ++++ ...1232-partial-init-and-erroneous-use.stderr | 48 +++ .../nll/issue-21232-partial-init-and-use.rs | 311 ++++++++++++++++++ .../issue-21232-partial-init-and-use.stderr | 186 +++++++++++ 16 files changed, 1308 insertions(+) create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.ast.stderr create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.nll.stderr create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.ast.stderr create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.ast.stderr create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.ast.stderr create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.nll.stderr create mode 100644 src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs create mode 100644 src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs create mode 100644 src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr create mode 100644 src/test/ui/nll/issue-21232-partial-init-and-use.rs create mode 100644 src/test/ui/nll/issue-21232-partial-init-and-use.stderr diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.ast.stderr new file mode 100644 index 0000000000000..d72cc20971b0e --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.ast.stderr @@ -0,0 +1,39 @@ +error[E0381]: use of possibly uninitialized variable: `t.0` + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:25:31 + | +LL | println!("{:?} {:?}", t.0, t.1); + | ^^^ use of possibly uninitialized `t.0` + +error[E0381]: use of possibly uninitialized variable: `t.1` + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:25:36 + | +LL | println!("{:?} {:?}", t.0, t.1); + | ^^^ use of possibly uninitialized `t.1` + +error[E0381]: use of possibly uninitialized variable: `u.0` + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:35:31 + | +LL | println!("{:?} {:?}", u.0, u.1); + | ^^^ use of possibly uninitialized `u.0` + +error[E0381]: use of possibly uninitialized variable: `u.1` + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:35:36 + | +LL | println!("{:?} {:?}", u.0, u.1); + | ^^^ use of possibly uninitialized `u.1` + +error[E0381]: use of possibly uninitialized variable: `v.x` + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:45:31 + | +LL | println!("{:?} {:?}", v.x, v.y); + | ^^^ use of possibly uninitialized `v.x` + +error[E0381]: use of possibly uninitialized variable: `v.y` + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:45:36 + | +LL | println!("{:?} {:?}", v.x, v.y); + | ^^^ use of possibly uninitialized `v.y` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.nll.stderr new file mode 100644 index 0000000000000..ebc6c7fca62b9 --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.nll.stderr @@ -0,0 +1,21 @@ +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:22:9 + | +LL | t.0 = S(1); + | ^^^^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `u` + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:32:9 + | +LL | u.0 = S(1); + | ^^^^^^^^^^ use of possibly uninitialized `u` + +error[E0381]: assign to part of possibly uninitialized variable: `v` + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:42:9 + | +LL | v.x = S(1); + | ^^^^^^^^^^ use of possibly uninitialized `v` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs new file mode 100644 index 0000000000000..4358e8e440237 --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs @@ -0,0 +1,49 @@ +// revisions: ast nll + +// Since we are testing nll migration explicitly as a separate +// revision, don't worry about the --compare-mode=nll on this test. + +// ignore-compare-mode-nll + +//[ast]compile-flags: -Z borrowck=ast +//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows + +#![warn(unused)] +#[derive(Debug)] +struct S(i32); + +type Tuple = (S, i32); +struct Tpair(S, i32); +struct Spair { x: S, y: i32 } + +fn main() { + { + let mut t: Tuple; + t.0 = S(1); + //[nll]~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + t.1 = 2; + println!("{:?} {:?}", t.0, t.1); + //[ast]~^ ERROR use of possibly uninitialized variable: `t.0` [E0381] + //[ast]~| ERROR use of possibly uninitialized variable: `t.1` [E0381] + } + + { + let mut u: Tpair; + u.0 = S(1); + //[nll]~^ ERROR assign to part of possibly uninitialized variable: `u` [E0381] + u.1 = 2; + println!("{:?} {:?}", u.0, u.1); + //[ast]~^ ERROR use of possibly uninitialized variable: `u.0` [E0381] + //[ast]~| ERROR use of possibly uninitialized variable: `u.1` [E0381] + } + + { + let mut v: Spair; + v.x = S(1); + //[nll]~^ ERROR assign to part of possibly uninitialized variable: `v` [E0381] + v.y = 2; + println!("{:?} {:?}", v.x, v.y); + //[ast]~^ ERROR use of possibly uninitialized variable: `v.x` [E0381] + //[ast]~| ERROR use of possibly uninitialized variable: `v.y` [E0381] + } +} diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.ast.stderr new file mode 100644 index 0000000000000..e3b5341d2bcff --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.ast.stderr @@ -0,0 +1,69 @@ +error[E0382]: use of moved value: `t.0` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:25:31 + | +LL | drop(t); + | - value moved here +... +LL | println!("{:?} {:?}", t.0, t.1); + | ^^^ value used here after move + | + = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `t.1` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:25:36 + | +LL | drop(t); + | - value moved here +... +LL | println!("{:?} {:?}", t.0, t.1); + | ^^^ value used here after move + | + = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `u.0` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:33:31 + | +LL | drop(u); + | - value moved here +... +LL | println!("{:?} {:?}", u.0, u.1); + | ^^^ value used here after move + | + = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `u.1` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:33:36 + | +LL | drop(u); + | - value moved here +... +LL | println!("{:?} {:?}", u.0, u.1); + | ^^^ value used here after move + | + = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `v.x` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:41:31 + | +LL | drop(v); + | - value moved here +... +LL | println!("{:?} {:?}", v.x, v.y); + | ^^^ value used here after move + | + = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `v.y` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:41:36 + | +LL | drop(v); + | - value moved here +... +LL | println!("{:?} {:?}", v.x, v.y); + | ^^^ value used here after move + | + = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr new file mode 100644 index 0000000000000..001ed59059cc8 --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr @@ -0,0 +1,33 @@ +error[E0382]: assign to part of moved value: `t` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:23:9 + | +LL | drop(t); + | - value moved here +LL | t.0 = S(1); + | ^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait + +error[E0382]: assign to part of moved value: `u` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:31:9 + | +LL | drop(u); + | - value moved here +LL | u.0 = S(1); + | ^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait + +error[E0382]: assign to part of moved value: `v` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:39:9 + | +LL | drop(v); + | - value moved here +LL | v.x = S(1); + | ^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs new file mode 100644 index 0000000000000..b6339c4a3c754 --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs @@ -0,0 +1,43 @@ +// revisions: ast nll + +// Since we are testing nll migration explicitly as a separate +// revision, don't worry about the --compare-mode=nll on this test. + +// ignore-compare-mode-nll + +//[ast]compile-flags: -Z borrowck=ast +//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows + +#![warn(unused)] +#[derive(Debug)] +struct S(i32); + +type Tuple = (S, i32); +struct Tpair(S, i32); +struct Spair { x: S, y: i32 } + +fn main() { + { + let mut t: Tuple = (S(0), 0); + drop(t); + t.0 = S(1); + t.1 = 2; + println!("{:?} {:?}", t.0, t.1); + } + + { + let mut u: Tpair = Tpair(S(0), 0); + drop(u); + u.0 = S(1); + u.1 = 2; + println!("{:?} {:?}", u.0, u.1); + } + + { + let mut v: Spair = Spair { x: S(0), y: 0 }; + drop(v); + v.x = S(1); + v.y = 2; + println!("{:?} {:?}", v.x, v.y); + } +} diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.ast.stderr new file mode 100644 index 0000000000000..565272af39049 --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.ast.stderr @@ -0,0 +1,124 @@ +error[E0594]: cannot assign to field `t.0` of immutable binding + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:23:9 + | +LL | let t: Tuple = (S(0), 0); + | - help: make this binding mutable: `mut t` +LL | drop(t); +LL | t.0 = S(1); + | ^^^^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0594]: cannot assign to field `t.1` of immutable binding + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:27:9 + | +LL | let t: Tuple = (S(0), 0); + | - help: make this binding mutable: `mut t` +... +LL | t.1 = 2; + | ^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0594]: cannot assign to field `u.0` of immutable binding + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9 + | +LL | let u: Tpair = Tpair(S(0), 0); + | - help: make this binding mutable: `mut u` +LL | drop(u); +LL | u.0 = S(1); + | ^^^^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0594]: cannot assign to field `u.1` of immutable binding + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:42:9 + | +LL | let u: Tpair = Tpair(S(0), 0); + | - help: make this binding mutable: `mut u` +... +LL | u.1 = 2; + | ^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0594]: cannot assign to field `v.x` of immutable binding + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:53:9 + | +LL | let v: Spair = Spair { x: S(0), y: 0 }; + | - help: make this binding mutable: `mut v` +LL | drop(v); +LL | v.x = S(1); + | ^^^^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0594]: cannot assign to field `v.y` of immutable binding + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:57:9 + | +LL | let v: Spair = Spair { x: S(0), y: 0 }; + | - help: make this binding mutable: `mut v` +... +LL | v.y = 2; + | ^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0382]: use of moved value: `t.0` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:30:31 + | +LL | drop(t); + | - value moved here +... +LL | println!("{:?} {:?}", t.0, t.1); + | ^^^ value used here after move + | + = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `t.1` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:30:36 + | +LL | drop(t); + | - value moved here +... +LL | println!("{:?} {:?}", t.0, t.1); + | ^^^ value used here after move + | + = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `u.0` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:45:31 + | +LL | drop(u); + | - value moved here +... +LL | println!("{:?} {:?}", u.0, u.1); + | ^^^ value used here after move + | + = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `u.1` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:45:36 + | +LL | drop(u); + | - value moved here +... +LL | println!("{:?} {:?}", u.0, u.1); + | ^^^ value used here after move + | + = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `v.x` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:60:31 + | +LL | drop(v); + | - value moved here +... +LL | println!("{:?} {:?}", v.x, v.y); + | ^^^ value used here after move + | + = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `v.y` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:60:36 + | +LL | drop(v); + | - value moved here +... +LL | println!("{:?} {:?}", v.x, v.y); + | ^^^ value used here after move + | + = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait + +error: aborting due to 12 previous errors + +Some errors occurred: E0382, E0594. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr new file mode 100644 index 0000000000000..d35d0058027d4 --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr @@ -0,0 +1,88 @@ +error[E0594]: cannot assign to `t.0`, as `t` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:23:9 + | +LL | let t: Tuple = (S(0), 0); + | - help: consider changing this to be mutable: `mut t` +LL | drop(t); +LL | t.0 = S(1); + | ^^^^^^^^^^ cannot assign + +error[E0382]: assign to part of moved value: `t` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:23:9 + | +LL | drop(t); + | - value moved here +LL | t.0 = S(1); + | ^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait + +error[E0594]: cannot assign to `t.1`, as `t` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:27:9 + | +LL | let t: Tuple = (S(0), 0); + | - help: consider changing this to be mutable: `mut t` +... +LL | t.1 = 2; + | ^^^^^^^ cannot assign + +error[E0594]: cannot assign to `u.0`, as `u` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9 + | +LL | let u: Tpair = Tpair(S(0), 0); + | - help: consider changing this to be mutable: `mut u` +LL | drop(u); +LL | u.0 = S(1); + | ^^^^^^^^^^ cannot assign + +error[E0382]: assign to part of moved value: `u` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9 + | +LL | drop(u); + | - value moved here +LL | u.0 = S(1); + | ^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait + +error[E0594]: cannot assign to `u.1`, as `u` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:42:9 + | +LL | let u: Tpair = Tpair(S(0), 0); + | - help: consider changing this to be mutable: `mut u` +... +LL | u.1 = 2; + | ^^^^^^^ cannot assign + +error[E0594]: cannot assign to `v.x`, as `v` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:53:9 + | +LL | let v: Spair = Spair { x: S(0), y: 0 }; + | - help: consider changing this to be mutable: `mut v` +LL | drop(v); +LL | v.x = S(1); + | ^^^^^^^^^^ cannot assign + +error[E0382]: assign to part of moved value: `v` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:53:9 + | +LL | drop(v); + | - value moved here +LL | v.x = S(1); + | ^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait + +error[E0594]: cannot assign to `v.y`, as `v` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:57:9 + | +LL | let v: Spair = Spair { x: S(0), y: 0 }; + | - help: consider changing this to be mutable: `mut v` +... +LL | v.y = 2; + | ^^^^^^^ cannot assign + +error: aborting due to 9 previous errors + +Some errors occurred: E0382, E0594. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs new file mode 100644 index 0000000000000..b19dcd65a6c7e --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs @@ -0,0 +1,64 @@ +// revisions: ast nll + +// Since we are testing nll migration explicitly as a separate +// revision, don't worry about the --compare-mode=nll on this test. + +// ignore-compare-mode-nll + +//[ast]compile-flags: -Z borrowck=ast +//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows + +#![warn(unused)] +#[derive(Debug)] +struct S(i32); + +type Tuple = (S, i32); +struct Tpair(S, i32); +struct Spair { x: S, y: i32 } + +fn main() { + { + let t: Tuple = (S(0), 0); + drop(t); + t.0 = S(1); + //[ast]~^ ERROR cannot assign to field `t.0` of immutable binding [E0594] + //[nll]~^^ ERROR assign to part of moved value: `t` [E0382] + //[nll]~| ERROR cannot assign to `t.0`, as `t` is not declared as mutable [E0594] + t.1 = 2; + //[ast]~^ ERROR cannot assign to field `t.1` of immutable binding [E0594] + //[nll]~^^ ERROR cannot assign to `t.1`, as `t` is not declared as mutable [E0594] + println!("{:?} {:?}", t.0, t.1); + //[ast]~^ ERROR use of moved value: `t.0` [E0382] + //[ast]~| ERROR use of moved value: `t.1` [E0382] + } + + { + let u: Tpair = Tpair(S(0), 0); + drop(u); + u.0 = S(1); + //[ast]~^ ERROR cannot assign to field `u.0` of immutable binding [E0594] + //[nll]~^^ ERROR assign to part of moved value: `u` [E0382] + //[nll]~| ERROR cannot assign to `u.0`, as `u` is not declared as mutable [E0594] + u.1 = 2; + //[ast]~^ ERROR cannot assign to field `u.1` of immutable binding [E0594] + //[nll]~^^ ERROR cannot assign to `u.1`, as `u` is not declared as mutable [E0594] + println!("{:?} {:?}", u.0, u.1); + //[ast]~^ ERROR use of moved value: `u.0` [E0382] + //[ast]~| ERROR use of moved value: `u.1` [E0382] + } + + { + let v: Spair = Spair { x: S(0), y: 0 }; + drop(v); + v.x = S(1); + //[ast]~^ ERROR cannot assign to field `v.x` of immutable binding [E0594] + //[nll]~^^ ERROR assign to part of moved value: `v` [E0382] + //[nll]~| ERROR cannot assign to `v.x`, as `v` is not declared as mutable [E0594] + v.y = 2; + //[ast]~^ ERROR cannot assign to field `v.y` of immutable binding [E0594] + //[nll]~^^ ERROR cannot assign to `v.y`, as `v` is not declared as mutable [E0594] + println!("{:?} {:?}", v.x, v.y); + //[ast]~^ ERROR use of moved value: `v.x` [E0382] + //[ast]~| ERROR use of moved value: `v.y` [E0382] + } +} diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.ast.stderr new file mode 100644 index 0000000000000..ea6b63b7a297d --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.ast.stderr @@ -0,0 +1,91 @@ +error[E0594]: cannot assign to field `t.0` of immutable binding + --> $DIR/issue-54499-field-mutation-of-never-init.rs:22:9 + | +LL | let t: Tuple; + | - help: make this binding mutable: `mut t` +LL | t.0 = S(1); + | ^^^^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0594]: cannot assign to field `t.1` of immutable binding + --> $DIR/issue-54499-field-mutation-of-never-init.rs:25:9 + | +LL | let t: Tuple; + | - help: make this binding mutable: `mut t` +... +LL | t.1 = 2; + | ^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0594]: cannot assign to field `u.0` of immutable binding + --> $DIR/issue-54499-field-mutation-of-never-init.rs:34:9 + | +LL | let u: Tpair; + | - help: make this binding mutable: `mut u` +LL | u.0 = S(1); + | ^^^^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0594]: cannot assign to field `u.1` of immutable binding + --> $DIR/issue-54499-field-mutation-of-never-init.rs:37:9 + | +LL | let u: Tpair; + | - help: make this binding mutable: `mut u` +... +LL | u.1 = 2; + | ^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0594]: cannot assign to field `v.x` of immutable binding + --> $DIR/issue-54499-field-mutation-of-never-init.rs:46:9 + | +LL | let v: Spair; + | - help: make this binding mutable: `mut v` +LL | v.x = S(1); + | ^^^^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0594]: cannot assign to field `v.y` of immutable binding + --> $DIR/issue-54499-field-mutation-of-never-init.rs:49:9 + | +LL | let v: Spair; + | - help: make this binding mutable: `mut v` +... +LL | v.y = 2; + | ^^^^^^^ cannot mutably borrow field of immutable binding + +error[E0381]: use of possibly uninitialized variable: `t.0` + --> $DIR/issue-54499-field-mutation-of-never-init.rs:27:31 + | +LL | println!("{:?} {:?}", t.0, t.1); + | ^^^ use of possibly uninitialized `t.0` + +error[E0381]: use of possibly uninitialized variable: `t.1` + --> $DIR/issue-54499-field-mutation-of-never-init.rs:27:36 + | +LL | println!("{:?} {:?}", t.0, t.1); + | ^^^ use of possibly uninitialized `t.1` + +error[E0381]: use of possibly uninitialized variable: `u.0` + --> $DIR/issue-54499-field-mutation-of-never-init.rs:39:31 + | +LL | println!("{:?} {:?}", u.0, u.1); + | ^^^ use of possibly uninitialized `u.0` + +error[E0381]: use of possibly uninitialized variable: `u.1` + --> $DIR/issue-54499-field-mutation-of-never-init.rs:39:36 + | +LL | println!("{:?} {:?}", u.0, u.1); + | ^^^ use of possibly uninitialized `u.1` + +error[E0381]: use of possibly uninitialized variable: `v.x` + --> $DIR/issue-54499-field-mutation-of-never-init.rs:51:31 + | +LL | println!("{:?} {:?}", v.x, v.y); + | ^^^ use of possibly uninitialized `v.x` + +error[E0381]: use of possibly uninitialized variable: `v.y` + --> $DIR/issue-54499-field-mutation-of-never-init.rs:51:36 + | +LL | println!("{:?} {:?}", v.x, v.y); + | ^^^ use of possibly uninitialized `v.y` + +error: aborting due to 12 previous errors + +Some errors occurred: E0381, E0594. +For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.nll.stderr new file mode 100644 index 0000000000000..3dc2b5b3b8f9f --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.nll.stderr @@ -0,0 +1,21 @@ +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/issue-54499-field-mutation-of-never-init.rs:22:9 + | +LL | t.0 = S(1); + | ^^^^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `u` + --> $DIR/issue-54499-field-mutation-of-never-init.rs:34:9 + | +LL | u.0 = S(1); + | ^^^^^^^^^^ use of possibly uninitialized `u` + +error[E0381]: assign to part of possibly uninitialized variable: `v` + --> $DIR/issue-54499-field-mutation-of-never-init.rs:46:9 + | +LL | v.x = S(1); + | ^^^^^^^^^^ use of possibly uninitialized `v` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs new file mode 100644 index 0000000000000..03eb9621ee215 --- /dev/null +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs @@ -0,0 +1,55 @@ +// revisions: ast nll + +// Since we are testing nll migration explicitly as a separate +// revision, don't worry about the --compare-mode=nll on this test. + +// ignore-compare-mode-nll + +//[ast]compile-flags: -Z borrowck=ast +//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows + +#![warn(unused)] +#[derive(Debug)] +struct S(i32); + +type Tuple = (S, i32); +struct Tpair(S, i32); +struct Spair { x: S, y: i32 } + +fn main() { + { + let t: Tuple; + t.0 = S(1); + //[ast]~^ ERROR cannot assign to field `t.0` of immutable binding [E0594] + //[nll]~^^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + t.1 = 2; + //[ast]~^ ERROR cannot assign to field `t.1` of immutable binding [E0594] + println!("{:?} {:?}", t.0, t.1); + //[ast]~^ ERROR use of possibly uninitialized variable: `t.0` [E0381] + //[ast]~| ERROR use of possibly uninitialized variable: `t.1` [E0381] + } + + { + let u: Tpair; + u.0 = S(1); + //[ast]~^ ERROR cannot assign to field `u.0` of immutable binding [E0594] + //[nll]~^^ ERROR assign to part of possibly uninitialized variable: `u` [E0381] + u.1 = 2; + //[ast]~^ ERROR cannot assign to field `u.1` of immutable binding [E0594] + println!("{:?} {:?}", u.0, u.1); + //[ast]~^ ERROR use of possibly uninitialized variable: `u.0` [E0381] + //[ast]~| ERROR use of possibly uninitialized variable: `u.1` [E0381] + } + + { + let v: Spair; + v.x = S(1); + //[ast]~^ ERROR cannot assign to field `v.x` of immutable binding [E0594] + //[nll]~^^ ERROR assign to part of possibly uninitialized variable: `v` [E0381] + v.y = 2; + //[ast]~^ ERROR cannot assign to field `v.y` of immutable binding [E0594] + println!("{:?} {:?}", v.x, v.y); + //[ast]~^ ERROR use of possibly uninitialized variable: `v.x` [E0381] + //[ast]~| ERROR use of possibly uninitialized variable: `v.y` [E0381] + } +} diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs new file mode 100644 index 0000000000000..abafd330573ee --- /dev/null +++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs @@ -0,0 +1,66 @@ +// This test enumerates various cases of interest where a ADT or tuple is +// partially initialized and then used in some way that is wrong *even* +// after rust-lang/rust#54987 is implemented. +// +// See rust-lang/rust#21232, rust-lang/rust#54986, and rust-lang/rust#54987. +// +// See issue-21232-partial-init-and-use.rs for cases of tests that are +// meant to compile and run successfully once rust-lang/rust#54987 is +// implemented. + +#![feature(nll)] + +struct D { + x: u32, + s: S, +} + +struct S { + y: u32, + z: u32, +} + + +impl Drop for D { + fn drop(&mut self) { } +} + +fn cannot_partially_init_adt_with_drop() { + let d: D; + d.x = 10; + //~^ ERROR assign of possibly uninitialized variable: `d` [E0381] +} + +fn cannot_partially_init_mutable_adt_with_drop() { + let mut d: D; + d.x = 10; + //~^ ERROR assign of possibly uninitialized variable: `d` [E0381] +} + +fn cannot_partially_reinit_adt_with_drop() { + let mut d = D { x: 0, s: S{ y: 0, z: 0 } }; + drop(d); + d.x = 10; + //~^ ERROR assign of moved value: `d` [E0382] +} + +fn cannot_partially_init_inner_adt_via_outer_with_drop() { + let d: D; + d.s.y = 20; + //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381] +} + +fn cannot_partially_init_inner_adt_via_mutable_outer_with_drop() { + let mut d: D; + d.s.y = 20; + //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381] +} + +fn cannot_partially_reinit_inner_adt_via_outer_with_drop() { + let mut d = D { x: 0, s: S{ y: 0, z: 0} }; + drop(d); + d.s.y = 20; + //~^ ERROR assign to part of moved value: `d` [E0382] +} + +fn main() { } diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr new file mode 100644 index 0000000000000..e29c44760a987 --- /dev/null +++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr @@ -0,0 +1,48 @@ +error[E0381]: assign of possibly uninitialized variable: `d` + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:30:5 + | +LL | d.x = 10; + | ^^^^^^^^ use of possibly uninitialized `d` + +error[E0381]: assign of possibly uninitialized variable: `d` + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:36:5 + | +LL | d.x = 10; + | ^^^^^^^^ use of possibly uninitialized `d` + +error[E0382]: assign of moved value: `d` + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:43:5 + | +LL | drop(d); + | - value moved here +LL | d.x = 10; + | ^^^^^^^^ value assigned here after move + | + = note: move occurs because `d` has type `D`, which does not implement the `Copy` trait + +error[E0381]: assign to part of possibly uninitialized variable: `d` + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:49:5 + | +LL | d.s.y = 20; + | ^^^^^^^^^^ use of possibly uninitialized `d.s` + +error[E0381]: assign to part of possibly uninitialized variable: `d` + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:55:5 + | +LL | d.s.y = 20; + | ^^^^^^^^^^ use of possibly uninitialized `d.s` + +error[E0382]: assign to part of moved value: `d` + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:62:5 + | +LL | drop(d); + | - value moved here +LL | d.s.y = 20; + | ^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `d` has type `D`, which does not implement the `Copy` trait + +error: aborting due to 6 previous errors + +Some errors occurred: E0381, E0382. +For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-use.rs new file mode 100644 index 0000000000000..e3ae4c0dcbe57 --- /dev/null +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.rs @@ -0,0 +1,311 @@ +// This test enumerates various cases of interest for partial +// [re]initialization of ADTs and tuples. +// +// See rust-lang/rust#21232, rust-lang/rust#54986, and rust-lang/rust#54987. +// +// All of tests in this file are expected to change from being +// rejected, at least under NLL (by rust-lang/rust#54986) to being +// **accepted** when rust-lang/rust#54987 is implemented. +// (That's why there are assertions in the code.) +// +// See issue-21232-partial-init-and-erroneous-use.rs for cases of +// tests that are meant to continue failing to compile once +// rust-lang/rust#54987 is implemented. + +#![feature(nll)] + +struct S { + x: u32, + + // Note that even though `y` may implement `Drop`, under #54987 we + // will still allow partial initialization of `S` itself. + y: Y, +} + +enum Void { } + +type B = Box; + +impl S { fn new() -> Self { S { x: 0, y: Box::new(0) } } } + +fn borrow_s(s: &S) { assert_eq!(s.x, 10); assert_eq!(*s.y, 20); } +fn move_s(s: S) { assert_eq!(s.x, 10); assert_eq!(*s.y, 20); } +fn borrow_field(x: &u32) { assert_eq!(*x, 10); } + +type T = (u32, B); +type Tvoid = (u32, Void); + +fn borrow_t(t: &T) { assert_eq!(t.0, 10); assert_eq!(*t.1, 20); } +fn move_t(t: T) { assert_eq!(t.0, 10); assert_eq!(*t.1, 20); } + +struct Q { + v: u32, + r: R, +} + +struct R { + w: u32, + f: F, +} + +impl Q { fn new(f: F) -> Self { Q { v: 0, r: R::new(f) } } } +impl R { fn new(f: F) -> Self { R { w: 0, f } } } + +// Axes to cover: +// * local/field: Is the structure in a local or a field +// * fully/partial/void: Are we fully initializing it before using any part? +// Is whole type empty due to a void component? +// * init/reinit: First initialization, or did we previously inititalize and then move out? +// * struct/tuple: Is this a struct or a (X, Y). +// +// As a shorthand for the cases above, adding a numeric summary to +// each test's fn name to denote each point on each axis. +// +// E.g. 1000 = field fully init struct; 0211 = local void reinit tuple + +// It got pretty monotonous writing the same code over and over, and I +// feared I would forget details. So I abstracted some desiderata into +// macros. But I left the initialization code inline, because that's +// where the errors for #54986 will be emited. + +macro_rules! use_fully { + (struct $s:expr) => { { + borrow_field(& $s.x ); + borrow_s(& $s ); + move_s( $s ); + } }; + + (tuple $t:expr) => { { + borrow_field(& $t.0 ); + borrow_t(& $t ); + move_t( $t ); + } } +} + +macro_rules! use_part { + (struct $s:expr) => { { + borrow_field(& $s.x ); + match $s { S { ref x, y: _ } => { borrow_field(x); } } + } }; + + (tuple $t:expr) => { { + borrow_field(& $t.0 ); + match $t { (ref x, _) => { borrow_field(x); } } + } } +} + +fn test_0000_local_fully_init_and_use_struct() { + let s: S; + s.x = 10; s.y = Box::new(20); + //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381] + use_fully!(struct s); +} + +fn test_0001_local_fully_init_and_use_tuple() { + let t: T; + t.0 = 10; t.1 = Box::new(20); + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + use_fully!(tuple t); +} + +fn test_0010_local_fully_reinit_and_use_struct() { + let mut s: S = S::new(); drop(s); + s.x = 10; s.y = Box::new(20); + //~^ ERROR assign to part of moved value: `s` [E0382] + use_fully!(struct s); +} + +fn test_0011_local_fully_reinit_and_use_tuple() { + let mut t: T = (0, Box::new(0)); drop(t); + t.0 = 10; t.1 = Box::new(20); + //~^ ERROR assign to part of moved value: `t` [E0382] + use_fully!(tuple t); +} + +fn test_0100_local_partial_init_and_use_struct() { + let s: S; + s.x = 10; + //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381] + use_part!(struct s); +} + +fn test_0101_local_partial_init_and_use_tuple() { + let t: T; + t.0 = 10; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + use_part!(tuple t); +} + +fn test_0110_local_partial_reinit_and_use_struct() { + let mut s: S = S::new(); drop(s); + s.x = 10; + //~^ ERROR assign to part of moved value: `s` [E0382] + use_part!(struct s); +} + +fn test_0111_local_partial_reinit_and_use_tuple() { + let mut t: T = (0, Box::new(0)); drop(t); + t.0 = 10; + //~^ ERROR assign to part of moved value: `t` [E0382] + use_part!(tuple t); +} + +fn test_0200_local_void_init_and_use_struct() { + let s: S; + s.x = 10; + //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381] + use_part!(struct s); +} + +fn test_0201_local_void_init_and_use_tuple() { + let t: Tvoid; + t.0 = 10; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + use_part!(tuple t); +} + +// NOTE: uniform structure of tests here makes n21n (aka combining +// Void with Reinit) an (even more) senseless case, as we cannot +// safely create initial instance containing Void to move out of and +// then reinitialize. While I was tempted to sidestep this via some +// unsafe code (eek), lets just instead not encode such tests. + +// fn test_0210_local_void_reinit_and_use_struct() { unimplemented!() } +// fn test_0211_local_void_reinit_and_use_tuple() { unimplemented!() } + +fn test_1000_field_fully_init_and_use_struct() { + let q: Q>; + q.r.f.x = 10; q.r.f.y = Box::new(20); + //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + use_fully!(struct q.r.f); +} + +fn test_1001_field_fully_init_and_use_tuple() { + let q: Q; + q.r.f.0 = 10; q.r.f.1 = Box::new(20); + //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + use_fully!(tuple q.r.f); +} + +fn test_1010_field_fully_reinit_and_use_struct() { + let mut q: Q> = Q::new(S::new()); drop(q.r); + q.r.f.x = 10; q.r.f.y = Box::new(20); + //~^ ERROR assign to part of moved value: `q.r` [E0382] + use_fully!(struct q.r.f); +} + +fn test_1011_field_fully_reinit_and_use_tuple() { + let mut q: Q = Q::new((0, Box::new(0))); drop(q.r); + q.r.f.0 = 10; q.r.f.1 = Box::new(20); + //~^ ERROR assign to part of moved value: `q.r` [E0382] + use_fully!(tuple q.r.f); +} + +fn test_1100_field_partial_init_and_use_struct() { + let q: Q>; + q.r.f.x = 10; + //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + use_part!(struct q.r.f); +} + +fn test_1101_field_partial_init_and_use_tuple() { + let q: Q; + q.r.f.0 = 10; + //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + use_part!(tuple q.r.f); +} + +fn test_1110_field_partial_reinit_and_use_struct() { + let mut q: Q> = Q::new(S::new()); drop(q.r); + q.r.f.x = 10; + //~^ ERROR assign to part of moved value: `q.r` [E0382] + use_part!(struct q.r.f); +} + +fn test_1111_field_partial_reinit_and_use_tuple() { + let mut q: Q = Q::new((0, Box::new(0))); drop(q.r); + q.r.f.0 = 10; + //~^ ERROR assign to part of moved value: `q.r` [E0382] + use_part!(tuple q.r.f); +} + +fn test_1200_field_void_init_and_use_struct() { + let mut q: Q>; + q.r.f.x = 10; + //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + use_part!(struct q.r.f); +} + +fn test_1201_field_void_init_and_use_tuple() { + let mut q: Q; + q.r.f.0 = 10; + //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381] + use_part!(tuple q.r.f); +} + +// See NOTE abve. + +// fn test_1210_field_void_reinit_and_use_struct() { unimplemented!() } +// fn test_1211_field_void_reinit_and_use_tuple() { unimplemented!() } + +// The below are some additional cases of interest that have been +// transcribed from other bugs based on old erroneous codegen when we +// encountered partial writes. + +fn issue_26996() { + let mut c = (1, "".to_owned()); + match c { + c2 => { + c.0 = 2; //~ ERROR assign to part of moved value + assert_eq!(c2.0, 1); + } + } +} + +fn issue_27021() { + let mut c = (1, (1, "".to_owned())); + match c { + c2 => { + (c.1).0 = 2; //~ ERROR assign to part of moved value + assert_eq!((c2.1).0, 1); + } + } + + let mut c = (1, (1, (1, "".to_owned()))); + match c.1 { + c2 => { + ((c.1).1).0 = 3; //~ ERROR assign to part of moved value + assert_eq!((c2.1).0, 1); + } + } +} + +fn main() { + test_0000_local_fully_init_and_use_struct(); + test_0001_local_fully_init_and_use_tuple(); + test_0010_local_fully_reinit_and_use_struct(); + test_0011_local_fully_reinit_and_use_tuple(); + test_0100_local_partial_init_and_use_struct(); + test_0101_local_partial_init_and_use_tuple(); + test_0110_local_partial_reinit_and_use_struct(); + test_0111_local_partial_reinit_and_use_tuple(); + test_0200_local_void_init_and_use_struct(); + test_0201_local_void_init_and_use_tuple(); + // test_0210_local_void_reinit_and_use_struct(); + // test_0211_local_void_reinit_and_use_tuple(); + test_1000_field_fully_init_and_use_struct(); + test_1001_field_fully_init_and_use_tuple(); + test_1010_field_fully_reinit_and_use_struct(); + test_1011_field_fully_reinit_and_use_tuple(); + test_1100_field_partial_init_and_use_struct(); + test_1101_field_partial_init_and_use_tuple(); + test_1110_field_partial_reinit_and_use_struct(); + test_1111_field_partial_reinit_and_use_tuple(); + test_1200_field_void_init_and_use_struct(); + test_1201_field_void_init_and_use_tuple(); + // test_1210_field_void_reinit_and_use_struct(); + // test_1211_field_void_reinit_and_use_tuple(); + + issue_26996(); + issue_27021(); +} diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr new file mode 100644 index 0000000000000..aec7f676fcebd --- /dev/null +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr @@ -0,0 +1,186 @@ +error[E0381]: assign to part of possibly uninitialized variable: `s` + --> $DIR/issue-21232-partial-init-and-use.rs:99:5 + | +LL | s.x = 10; s.y = Box::new(20); + | ^^^^^^^^ use of possibly uninitialized `s` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/issue-21232-partial-init-and-use.rs:106:5 + | +LL | t.0 = 10; t.1 = Box::new(20); + | ^^^^^^^^ use of possibly uninitialized `t` + +error[E0382]: assign to part of moved value: `s` + --> $DIR/issue-21232-partial-init-and-use.rs:113:5 + | +LL | let mut s: S = S::new(); drop(s); + | - value moved here +LL | s.x = 10; s.y = Box::new(20); + | ^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `s` has type `S>`, which does not implement the `Copy` trait + +error[E0382]: assign to part of moved value: `t` + --> $DIR/issue-21232-partial-init-and-use.rs:120:5 + | +LL | let mut t: T = (0, Box::new(0)); drop(t); + | - value moved here +LL | t.0 = 10; t.1 = Box::new(20); + | ^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `t` has type `(u32, std::boxed::Box)`, which does not implement the `Copy` trait + +error[E0381]: assign to part of possibly uninitialized variable: `s` + --> $DIR/issue-21232-partial-init-and-use.rs:127:5 + | +LL | s.x = 10; + | ^^^^^^^^ use of possibly uninitialized `s` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/issue-21232-partial-init-and-use.rs:134:5 + | +LL | t.0 = 10; + | ^^^^^^^^ use of possibly uninitialized `t` + +error[E0382]: assign to part of moved value: `s` + --> $DIR/issue-21232-partial-init-and-use.rs:141:5 + | +LL | let mut s: S = S::new(); drop(s); + | - value moved here +LL | s.x = 10; + | ^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `s` has type `S>`, which does not implement the `Copy` trait + +error[E0382]: assign to part of moved value: `t` + --> $DIR/issue-21232-partial-init-and-use.rs:148:5 + | +LL | let mut t: T = (0, Box::new(0)); drop(t); + | - value moved here +LL | t.0 = 10; + | ^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `t` has type `(u32, std::boxed::Box)`, which does not implement the `Copy` trait + +error[E0381]: assign to part of possibly uninitialized variable: `s` + --> $DIR/issue-21232-partial-init-and-use.rs:155:5 + | +LL | s.x = 10; + | ^^^^^^^^ use of possibly uninitialized `s` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/issue-21232-partial-init-and-use.rs:162:5 + | +LL | t.0 = 10; + | ^^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `q` + --> $DIR/issue-21232-partial-init-and-use.rs:178:5 + | +LL | q.r.f.x = 10; q.r.f.y = Box::new(20); + | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + +error[E0381]: assign to part of possibly uninitialized variable: `q` + --> $DIR/issue-21232-partial-init-and-use.rs:185:5 + | +LL | q.r.f.0 = 10; q.r.f.1 = Box::new(20); + | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + +error[E0382]: assign to part of moved value: `q.r` + --> $DIR/issue-21232-partial-init-and-use.rs:192:5 + | +LL | let mut q: Q> = Q::new(S::new()); drop(q.r); + | --- value moved here +LL | q.r.f.x = 10; q.r.f.y = Box::new(20); + | ^^^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `q.r` has type `R>>`, which does not implement the `Copy` trait + +error[E0382]: assign to part of moved value: `q.r` + --> $DIR/issue-21232-partial-init-and-use.rs:199:5 + | +LL | let mut q: Q = Q::new((0, Box::new(0))); drop(q.r); + | --- value moved here +LL | q.r.f.0 = 10; q.r.f.1 = Box::new(20); + | ^^^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box)>`, which does not implement the `Copy` trait + +error[E0381]: assign to part of possibly uninitialized variable: `q` + --> $DIR/issue-21232-partial-init-and-use.rs:206:5 + | +LL | q.r.f.x = 10; + | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + +error[E0381]: assign to part of possibly uninitialized variable: `q` + --> $DIR/issue-21232-partial-init-and-use.rs:213:5 + | +LL | q.r.f.0 = 10; + | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + +error[E0382]: assign to part of moved value: `q.r` + --> $DIR/issue-21232-partial-init-and-use.rs:220:5 + | +LL | let mut q: Q> = Q::new(S::new()); drop(q.r); + | --- value moved here +LL | q.r.f.x = 10; + | ^^^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `q.r` has type `R>>`, which does not implement the `Copy` trait + +error[E0382]: assign to part of moved value: `q.r` + --> $DIR/issue-21232-partial-init-and-use.rs:227:5 + | +LL | let mut q: Q = Q::new((0, Box::new(0))); drop(q.r); + | --- value moved here +LL | q.r.f.0 = 10; + | ^^^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box)>`, which does not implement the `Copy` trait + +error[E0381]: assign to part of possibly uninitialized variable: `q` + --> $DIR/issue-21232-partial-init-and-use.rs:234:5 + | +LL | q.r.f.x = 10; + | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + +error[E0381]: assign to part of possibly uninitialized variable: `q` + --> $DIR/issue-21232-partial-init-and-use.rs:241:5 + | +LL | q.r.f.0 = 10; + | ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f` + +error[E0382]: assign to part of moved value: `c` + --> $DIR/issue-21232-partial-init-and-use.rs:259:13 + | +LL | c2 => { + | -- value moved here +LL | c.0 = 2; //~ ERROR assign to part of moved value + | ^^^^^^^ value partially assigned here after move + | + = note: move occurs because `c` has type `(i32, std::string::String)`, which does not implement the `Copy` trait + +error[E0382]: assign to part of moved value: `c` + --> $DIR/issue-21232-partial-init-and-use.rs:269:13 + | +LL | c2 => { + | -- value moved here +LL | (c.1).0 = 2; //~ ERROR assign to part of moved value + | ^^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `c` has type `(i32, (i32, std::string::String))`, which does not implement the `Copy` trait + +error[E0382]: assign to part of moved value: `c.1` + --> $DIR/issue-21232-partial-init-and-use.rs:277:13 + | +LL | c2 => { + | -- value moved here +LL | ((c.1).1).0 = 3; //~ ERROR assign to part of moved value + | ^^^^^^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `c.1` has type `(i32, (i32, std::string::String))`, which does not implement the `Copy` trait + +error: aborting due to 23 previous errors + +Some errors occurred: E0381, E0382. +For more information about an error, try `rustc --explain E0381`.