Auto merge of #54941 - pnkfelix:issue-21232-reject-partial-reinit, r=nikomatsakis

reject partial init and reinit of uninitialized data

Reject partial initialization of uninitialized structured types (i.e. structs and tuples) and also reject partial *reinitialization* of such types.

Fix #54986

Fix #54499

cc #21232
This commit is contained in:
bors 2018-10-17 09:13:51 +00:00
commit cbbd70d4f2
53 changed files with 1689 additions and 206 deletions

View File

@ -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<Local> {
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<Local> {
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> {

View File

@ -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();

View File

@ -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;
@ -853,6 +852,7 @@ enum InitializationRequiringAction {
MatchOn,
Use,
Assignment,
PartialAssignment,
}
struct RootPlace<'d, 'tcx: 'd> {
@ -868,6 +868,7 @@ impl InitializationRequiringAction {
InitializationRequiringAction::MatchOn => "use", // no good noun
InitializationRequiringAction::Use => "use",
InitializationRequiringAction::Assignment => "assign",
InitializationRequiringAction::PartialAssignment => "assign to part",
}
}
@ -878,6 +879,7 @@ impl InitializationRequiringAction {
InitializationRequiringAction::MatchOn => "matched on",
InitializationRequiringAction::Use => "used",
InitializationRequiringAction::Assignment => "assigned",
InitializationRequiringAction::PartialAssignment => "partially assigned",
}
}
}
@ -1439,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);
@ -1498,12 +1497,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 +1560,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 +1578,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<MovePathIndex, NoMovePathFound> {
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 +1666,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 +1696,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
///
@ -1692,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 { .. }))
@ -1791,14 +1885,33 @@ 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,
local: Local,
flow_state: &Flows<'cx, 'gcx, 'tcx>)
-> Option<InitIndex>
{
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
@ -1812,18 +1925,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 {
@ -1849,7 +1957,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,
@ -1927,14 +2035,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,
});
})
}
}
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {}

View File

@ -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`.

View File

@ -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<isize>`, 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`
Some errors occurred: E0382, E0499, E0505.
For more information about an error, try `rustc --explain E0382`.
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: E0381, E0382, E0499, E0505.
For more information about an error, try `rustc --explain E0381`.

View File

@ -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};

View File

@ -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};

View File

@ -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;

View File

@ -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;

View File

@ -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`.

View File

@ -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`.

View File

@ -31,23 +31,23 @@ fn main() {
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<&&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<i32, i32>;
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]
}

View File

@ -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;

View File

@ -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;

View File

@ -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`.

View File

@ -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]

View File

@ -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]

View File

@ -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`

View File

@ -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`

View File

@ -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]

View File

@ -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]

View File

@ -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`.

View File

@ -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`.

View File

@ -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]
}
}

View File

@ -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`.

View File

@ -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`.

View File

@ -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);
}
}

View File

@ -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`.

View File

@ -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`.

View File

@ -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]
}
}

View File

@ -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`.

View File

@ -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`.

View File

@ -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]
}
}

View File

@ -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
| ^^^^^^^ use of possibly uninitialized `x`
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: aborting due to 2 previous errors
error[E0381]: use of possibly uninitialized variable: `x`
--> $DIR/reassignment_immutable_fields.rs:27:10
|
LL | drop(x); //~ ERROR
| ^ use of possibly uninitialized `x`
error: aborting due to 5 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`.

View File

@ -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 previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0594`.
For more information about this error, try `rustc --explain E0381`.

View File

@ -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
| ^^^^^^^ use of possibly uninitialized `x`
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: aborting due to 2 previous errors
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
error: aborting due to 4 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`.

View File

@ -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);

View File

@ -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."),
}
}

View File

@ -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; })();

View File

@ -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;

View File

@ -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() { }

View File

@ -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`.

View File

@ -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<Y> {
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<u32>;
impl S<B> { fn new() -> Self { S { x: 0, y: Box::new(0) } } }
fn borrow_s(s: &S<B>) { assert_eq!(s.x, 10); assert_eq!(*s.y, 20); }
fn move_s(s: S<B>) { 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<F> {
v: u32,
r: R<F>,
}
struct R<F> {
w: u32,
f: F,
}
impl<F> Q<F> { fn new(f: F) -> Self { Q { v: 0, r: R::new(f) } } }
impl<F> R<F> { 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<B>;
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<B> = 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<B>;
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<B> = 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<Void>;
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<S<B>>;
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<T>;
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<S<B>> = 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<T> = 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<S<B>>;
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<T>;
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<S<B>> = 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<T> = 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<S<Void>>;
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<Tvoid>;
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();
}

View File

@ -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<B> = 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<std::boxed::Box<u32>>`, 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<u32>)`, 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<B> = 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<std::boxed::Box<u32>>`, 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<u32>)`, 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<S<B>> = 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<S<std::boxed::Box<u32>>>`, 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<T> = 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<u32>)>`, 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<S<B>> = 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<S<std::boxed::Box<u32>>>`, 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<T> = 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<u32>)>`, 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`.

View File

@ -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]
}

View File

@ -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;

View File

@ -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;

View File

@ -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`.

View File

@ -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();

View File

@ -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()};