Auto merge of #103208 - cjgillot:match-fake-read, r=oli-obk,RalfJung
Allow partially moved values in match This PR attempts to unify the behaviour between `let _ = PLACE`, `let _: TY = PLACE;` and `match PLACE { _ => {} }`. The logical conclusion is that the `match` version should not check for uninitialised places nor check that borrows are still live. The `match PLACE {}` case is handled by keeping a `FakeRead` in the unreachable fallback case to verify that `PLACE` has a legal value. Schematically, `match PLACE { arms }` in surface rust becomes in MIR: ```rust PlaceMention(PLACE) match PLACE { // Decision tree for the explicit arms arms, // An extra fallback arm _ => { FakeRead(ForMatchedPlace, PLACE); unreachable } } ``` `match *borrow { _ => {} }` continues to check that `*borrow` is live, but does not read the value. `match *borrow {}` both checks that `*borrow` is live, and fake-reads the value. Continuation of ~https://github.com/rust-lang/rust/pull/102256~ ~https://github.com/rust-lang/rust/pull/104844~ Fixes https://github.com/rust-lang/rust/issues/99180 https://github.com/rust-lang/rust/issues/53114
This commit is contained in:
commit
59bb9505bc
@ -157,7 +157,7 @@ pub(crate) fn then_else_break(
|
||||
/// [ 0. Pre-match ]
|
||||
/// |
|
||||
/// [ 1. Evaluate Scrutinee (expression being matched on) ]
|
||||
/// [ (fake read of scrutinee) ]
|
||||
/// [ (PlaceMention of scrutinee) ]
|
||||
/// |
|
||||
/// [ 2. Decision tree -- check discriminants ] <--------+
|
||||
/// | |
|
||||
@ -184,7 +184,7 @@ pub(crate) fn then_else_break(
|
||||
///
|
||||
/// We generate MIR in the following steps:
|
||||
///
|
||||
/// 1. Evaluate the scrutinee and add the fake read of it ([Builder::lower_scrutinee]).
|
||||
/// 1. Evaluate the scrutinee and add the PlaceMention of it ([Builder::lower_scrutinee]).
|
||||
/// 2. Create the decision tree ([Builder::lower_match_tree]).
|
||||
/// 3. Determine the fake borrows that are needed from the places that were
|
||||
/// matched against and create the required temporaries for them
|
||||
@ -223,6 +223,7 @@ pub(crate) fn match_expr(
|
||||
let fake_borrow_temps = self.lower_match_tree(
|
||||
block,
|
||||
scrutinee_span,
|
||||
&scrutinee_place,
|
||||
match_start_span,
|
||||
match_has_guard,
|
||||
&mut candidates,
|
||||
@ -238,7 +239,7 @@ pub(crate) fn match_expr(
|
||||
)
|
||||
}
|
||||
|
||||
/// Evaluate the scrutinee and add the fake read of it.
|
||||
/// Evaluate the scrutinee and add the PlaceMention for it.
|
||||
fn lower_scrutinee(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
@ -246,26 +247,9 @@ fn lower_scrutinee(
|
||||
scrutinee_span: Span,
|
||||
) -> BlockAnd<PlaceBuilder<'tcx>> {
|
||||
let scrutinee_place_builder = unpack!(block = self.as_place_builder(block, scrutinee));
|
||||
// Matching on a `scrutinee_place` with an uninhabited type doesn't
|
||||
// generate any memory reads by itself, and so if the place "expression"
|
||||
// contains unsafe operations like raw pointer dereferences or union
|
||||
// field projections, we wouldn't know to require an `unsafe` block
|
||||
// around a `match` equivalent to `std::intrinsics::unreachable()`.
|
||||
// See issue #47412 for this hole being discovered in the wild.
|
||||
//
|
||||
// HACK(eddyb) Work around the above issue by adding a dummy inspection
|
||||
// of `scrutinee_place`, specifically by applying `ReadForMatch`.
|
||||
//
|
||||
// NOTE: ReadForMatch also checks that the scrutinee is initialized.
|
||||
// This is currently needed to not allow matching on an uninitialized,
|
||||
// uninhabited value. If we get never patterns, those will check that
|
||||
// the place is initialized, and so this read would only be used to
|
||||
// check safety.
|
||||
let cause_matched_place = FakeReadCause::ForMatchedPlace(None);
|
||||
let source_info = self.source_info(scrutinee_span);
|
||||
|
||||
if let Some(scrutinee_place) = scrutinee_place_builder.try_to_place(self) {
|
||||
self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
|
||||
let source_info = self.source_info(scrutinee_span);
|
||||
self.cfg.push_place_mention(block, source_info, scrutinee_place);
|
||||
}
|
||||
|
||||
block.and(scrutinee_place_builder)
|
||||
@ -304,6 +288,7 @@ fn lower_match_tree<'pat>(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
scrutinee_span: Span,
|
||||
scrutinee_place_builder: &PlaceBuilder<'tcx>,
|
||||
match_start_span: Span,
|
||||
match_has_guard: bool,
|
||||
candidates: &mut [&mut Candidate<'pat, 'tcx>],
|
||||
@ -331,6 +316,33 @@ fn lower_match_tree<'pat>(
|
||||
// otherwise block. Match checking will ensure this is actually
|
||||
// unreachable.
|
||||
let source_info = self.source_info(scrutinee_span);
|
||||
|
||||
// Matching on a `scrutinee_place` with an uninhabited type doesn't
|
||||
// generate any memory reads by itself, and so if the place "expression"
|
||||
// contains unsafe operations like raw pointer dereferences or union
|
||||
// field projections, we wouldn't know to require an `unsafe` block
|
||||
// around a `match` equivalent to `std::intrinsics::unreachable()`.
|
||||
// See issue #47412 for this hole being discovered in the wild.
|
||||
//
|
||||
// HACK(eddyb) Work around the above issue by adding a dummy inspection
|
||||
// of `scrutinee_place`, specifically by applying `ReadForMatch`.
|
||||
//
|
||||
// NOTE: ReadForMatch also checks that the scrutinee is initialized.
|
||||
// This is currently needed to not allow matching on an uninitialized,
|
||||
// uninhabited value. If we get never patterns, those will check that
|
||||
// the place is initialized, and so this read would only be used to
|
||||
// check safety.
|
||||
let cause_matched_place = FakeReadCause::ForMatchedPlace(None);
|
||||
|
||||
if let Some(scrutinee_place) = scrutinee_place_builder.try_to_place(self) {
|
||||
self.cfg.push_fake_read(
|
||||
otherwise_block,
|
||||
source_info,
|
||||
cause_matched_place,
|
||||
scrutinee_place,
|
||||
);
|
||||
}
|
||||
|
||||
self.cfg.terminate(otherwise_block, source_info, TerminatorKind::Unreachable);
|
||||
}
|
||||
|
||||
@ -599,13 +611,8 @@ pub(super) fn expr_into_pattern(
|
||||
}
|
||||
|
||||
_ => {
|
||||
let place_builder = unpack!(block = self.as_place_builder(block, initializer));
|
||||
|
||||
if let Some(place) = place_builder.try_to_place(self) {
|
||||
let source_info = self.source_info(initializer.span);
|
||||
self.cfg.push_place_mention(block, source_info, place);
|
||||
}
|
||||
|
||||
let place_builder =
|
||||
unpack!(block = self.lower_scrutinee(block, initializer, initializer.span));
|
||||
self.place_into_pattern(block, &irrefutable_pat, place_builder, true)
|
||||
}
|
||||
}
|
||||
@ -622,6 +629,7 @@ pub(crate) fn place_into_pattern(
|
||||
let fake_borrow_temps = self.lower_match_tree(
|
||||
block,
|
||||
irrefutable_pat.span,
|
||||
&initializer,
|
||||
irrefutable_pat.span,
|
||||
false,
|
||||
&mut [&mut candidate],
|
||||
@ -1841,6 +1849,7 @@ pub(crate) fn lower_let_expr(
|
||||
let fake_borrow_temps = self.lower_match_tree(
|
||||
block,
|
||||
pat.span,
|
||||
&expr_place_builder,
|
||||
pat.span,
|
||||
false,
|
||||
&mut [&mut guard_candidate, &mut otherwise_candidate],
|
||||
@ -2342,6 +2351,7 @@ pub(crate) fn ast_let_else(
|
||||
let fake_borrow_temps = this.lower_match_tree(
|
||||
block,
|
||||
initializer_span,
|
||||
&scrutinee,
|
||||
pattern.span,
|
||||
false,
|
||||
&mut [&mut candidate, &mut wildcard],
|
||||
|
@ -0,0 +1,17 @@
|
||||
// Make sure we find these even with many checks disabled.
|
||||
//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
|
||||
|
||||
#![allow(unreachable_code)]
|
||||
#![feature(never_type)]
|
||||
|
||||
fn main() {
|
||||
let p = {
|
||||
let b = Box::new(42);
|
||||
&*b as *const i32 as *const !
|
||||
};
|
||||
unsafe {
|
||||
match *p {} //~ ERROR: entering unreachable code
|
||||
}
|
||||
panic!("this should never print");
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
error: Undefined Behavior: entering unreachable code
|
||||
--> $DIR/dangling_pointer_deref_match_never.rs:LL:CC
|
||||
|
|
||||
LL | match *p {}
|
||||
| ^^ entering unreachable code
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at $DIR/dangling_pointer_deref_match_never.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
10
src/tools/miri/tests/fail/never_match_never.rs
Normal file
10
src/tools/miri/tests/fail/never_match_never.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// This should fail even without validation
|
||||
//@compile-flags: -Zmiri-disable-validation
|
||||
|
||||
#![feature(never_type)]
|
||||
#![allow(unreachable_code)]
|
||||
|
||||
fn main() {
|
||||
let ptr: *const (i32, !) = &0i32 as *const i32 as *const _;
|
||||
unsafe { match (*ptr).1 {} } //~ ERROR: entering unreachable code
|
||||
}
|
15
src/tools/miri/tests/fail/never_match_never.stderr
Normal file
15
src/tools/miri/tests/fail/never_match_never.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error: Undefined Behavior: entering unreachable code
|
||||
--> $DIR/never_match_never.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { match (*ptr).1 {} }
|
||||
| ^^^^^^^^ entering unreachable code
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at $DIR/never_match_never.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -0,0 +1,14 @@
|
||||
// A `_` binding in a match is a nop, so we do not detect that the pointer is dangling.
|
||||
//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
|
||||
|
||||
fn main() {
|
||||
let p = {
|
||||
let b = Box::new(42);
|
||||
&*b as *const i32
|
||||
};
|
||||
unsafe {
|
||||
match *p {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
fn main() {
|
||||
#[derive(Copy, Clone)]
|
||||
enum Void {}
|
||||
union Uninit<T: Copy> {
|
||||
value: T,
|
||||
uninit: (),
|
||||
}
|
||||
unsafe {
|
||||
let x: Uninit<Void> = Uninit { uninit: () };
|
||||
match x.value {
|
||||
// rustc warns about un unreachable pattern,
|
||||
// but is wrong in unsafe code.
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => println!("hi from the void!"),
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
hi from the void!
|
@ -127,6 +127,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
||||
|
||||
bb3: {
|
||||
StorageDead(_5);
|
||||
PlaceMention(_4);
|
||||
nop;
|
||||
(((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}) = move _4;
|
||||
goto -> bb4;
|
||||
@ -162,6 +163,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
||||
bb7: {
|
||||
StorageDead(_13);
|
||||
StorageDead(_10);
|
||||
PlaceMention(_9);
|
||||
_16 = discriminant(_9);
|
||||
switchInt(move _16) -> [0: bb10, 1: bb8, otherwise: bb9];
|
||||
}
|
||||
@ -223,6 +225,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
||||
|
||||
bb15: {
|
||||
StorageDead(_22);
|
||||
PlaceMention(_21);
|
||||
nop;
|
||||
(((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}) = move _21;
|
||||
goto -> bb16;
|
||||
@ -258,6 +261,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
||||
bb19: {
|
||||
StorageDead(_29);
|
||||
StorageDead(_26);
|
||||
PlaceMention(_25);
|
||||
_32 = discriminant(_25);
|
||||
switchInt(move _32) -> [0: bb21, 1: bb20, otherwise: bb9];
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ fn main() -> () {
|
||||
FakeRead(ForLet(None), _1);
|
||||
AscribeUserType(_1, o, UserTypeProjection { base: UserType(1), projs: [] });
|
||||
StorageLive(_5);
|
||||
FakeRead(ForMatchedPlace(None), _1);
|
||||
PlaceMention(_1);
|
||||
_6 = discriminant(_1);
|
||||
switchInt(move _6) -> [1: bb4, otherwise: bb3];
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ fn main() -> () {
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
_3 = const true;
|
||||
FakeRead(ForMatchedPlace(None), _3);
|
||||
PlaceMention(_3);
|
||||
switchInt(_3) -> [0: bb3, otherwise: bb4];
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ fn test_complex() -> () {
|
||||
}
|
||||
|
||||
bb1: {
|
||||
FakeRead(ForMatchedPlace(None), _2);
|
||||
PlaceMention(_2);
|
||||
_3 = discriminant(_2);
|
||||
switchInt(move _3) -> [0: bb2, otherwise: bb3];
|
||||
}
|
||||
@ -151,7 +151,7 @@ fn test_complex() -> () {
|
||||
}
|
||||
|
||||
bb25: {
|
||||
FakeRead(ForMatchedPlace(None), _12);
|
||||
PlaceMention(_12);
|
||||
_13 = discriminant(_12);
|
||||
switchInt(move _13) -> [1: bb27, otherwise: bb26];
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ fn full_tested_match() -> () {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
_2 = Option::<i32>::Some(const 42_i32);
|
||||
FakeRead(ForMatchedPlace(None), _2);
|
||||
PlaceMention(_2);
|
||||
_3 = discriminant(_2);
|
||||
switchInt(move _3) -> [0: bb1, 1: bb2, otherwise: bb4];
|
||||
}
|
||||
@ -45,6 +45,7 @@ fn full_tested_match() -> () {
|
||||
}
|
||||
|
||||
bb4: {
|
||||
FakeRead(ForMatchedPlace(None), _2);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ fn full_tested_match2() -> () {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
_2 = Option::<i32>::Some(const 42_i32);
|
||||
FakeRead(ForMatchedPlace(None), _2);
|
||||
PlaceMention(_2);
|
||||
_3 = discriminant(_2);
|
||||
switchInt(move _3) -> [0: bb1, 1: bb2, otherwise: bb4];
|
||||
}
|
||||
@ -51,6 +51,7 @@ fn full_tested_match2() -> () {
|
||||
}
|
||||
|
||||
bb4: {
|
||||
FakeRead(ForMatchedPlace(None), _2);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ fn main() -> () {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
_2 = Option::<i32>::Some(const 1_i32);
|
||||
FakeRead(ForMatchedPlace(None), _2);
|
||||
PlaceMention(_2);
|
||||
_4 = discriminant(_2);
|
||||
switchInt(move _4) -> [1: bb2, otherwise: bb1];
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ fn match_bool(_1: bool) -> usize {
|
||||
let mut _0: usize;
|
||||
|
||||
bb0: {
|
||||
FakeRead(ForMatchedPlace(None), _1);
|
||||
PlaceMention(_1);
|
||||
switchInt(_1) -> [0: bb2, otherwise: bb1];
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
fn unreachable_box() -> ! {
|
||||
let mut _0: !;
|
||||
let _1: std::boxed::Box<Never>;
|
||||
let mut _2: *const Never;
|
||||
scope 1 {
|
||||
debug x => _1;
|
||||
}
|
||||
@ -13,7 +14,9 @@
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
|
||||
- _2 = (((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>).0: *const Never);
|
||||
+ _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
|
||||
+ _2 = const {0x1 as *const Never};
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
fn unreachable_box() -> ! {
|
||||
let mut _0: !;
|
||||
let _1: std::boxed::Box<Never>;
|
||||
let mut _2: *const Never;
|
||||
scope 1 {
|
||||
debug x => _1;
|
||||
}
|
||||
@ -13,7 +14,9 @@
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
|
||||
- _2 = (((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>).0: *const Never);
|
||||
+ _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
|
||||
+ _2 = const {0x1 as *const Never};
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
fn unreachable_box() -> ! {
|
||||
let mut _0: !;
|
||||
let _1: std::boxed::Box<Never>;
|
||||
let mut _2: *const Never;
|
||||
scope 1 {
|
||||
debug x => _1;
|
||||
}
|
||||
@ -14,6 +15,7 @@
|
||||
StorageLive(_1);
|
||||
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
|
||||
+ _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
|
||||
_2 = (((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>).0: *const Never);
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
fn unreachable_box() -> ! {
|
||||
let mut _0: !;
|
||||
let _1: std::boxed::Box<Never>;
|
||||
let mut _2: *const Never;
|
||||
scope 1 {
|
||||
debug x => _1;
|
||||
}
|
||||
@ -14,6 +15,7 @@
|
||||
StorageLive(_1);
|
||||
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
|
||||
+ _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
|
||||
_2 = (((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>).0: *const Never);
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
bb1: {
|
||||
StorageDead(_2);
|
||||
PlaceMention(_1);
|
||||
StorageLive(_4);
|
||||
_4 = move _1;
|
||||
goto -> bb2;
|
||||
@ -52,6 +53,7 @@
|
||||
|
||||
bb3: {
|
||||
StorageDead(_8);
|
||||
PlaceMention(_7);
|
||||
_10 = discriminant(_7);
|
||||
switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5];
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
bb1: {
|
||||
StorageDead(_2);
|
||||
PlaceMention(_1);
|
||||
StorageLive(_4);
|
||||
_4 = move _1;
|
||||
goto -> bb2;
|
||||
@ -52,6 +53,7 @@
|
||||
|
||||
bb3: {
|
||||
StorageDead(_8);
|
||||
PlaceMention(_7);
|
||||
_10 = discriminant(_7);
|
||||
switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5];
|
||||
}
|
||||
|
@ -12,6 +12,9 @@
|
||||
+ let mut _10: &&&bool;
|
||||
+ let mut _11: &&bool;
|
||||
+ let mut _12: &bool;
|
||||
+ let mut _13: &&&bool;
|
||||
+ let mut _14: &&bool;
|
||||
+ let mut _15: &bool;
|
||||
scope 1 {
|
||||
debug b => _1;
|
||||
let _2: bool;
|
||||
@ -48,11 +51,16 @@
|
||||
_6 = &_7;
|
||||
_5 = &_6;
|
||||
_4 = &_5;
|
||||
- PlaceMention((*(*(*(*_4)))));
|
||||
- switchInt((*(*(*(*_4))))) -> [0: bb3, otherwise: bb4];
|
||||
+ _10 = deref_copy (*_4);
|
||||
+ _11 = deref_copy (*_10);
|
||||
+ _12 = deref_copy (*_11);
|
||||
+ switchInt((*_12)) -> [0: bb3, otherwise: bb4];
|
||||
+ PlaceMention((*_12));
|
||||
+ _13 = deref_copy (*_4);
|
||||
+ _14 = deref_copy (*_13);
|
||||
+ _15 = deref_copy (*_14);
|
||||
+ switchInt((*_15)) -> [0: bb3, otherwise: bb4];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
|
@ -12,6 +12,9 @@
|
||||
+ let mut _10: &&&bool;
|
||||
+ let mut _11: &&bool;
|
||||
+ let mut _12: &bool;
|
||||
+ let mut _13: &&&bool;
|
||||
+ let mut _14: &&bool;
|
||||
+ let mut _15: &bool;
|
||||
scope 1 {
|
||||
debug b => _1;
|
||||
let _2: bool;
|
||||
@ -48,11 +51,16 @@
|
||||
_6 = &_7;
|
||||
_5 = &_6;
|
||||
_4 = &_5;
|
||||
- PlaceMention((*(*(*(*_4)))));
|
||||
- switchInt((*(*(*(*_4))))) -> [0: bb3, otherwise: bb4];
|
||||
+ _10 = deref_copy (*_4);
|
||||
+ _11 = deref_copy (*_10);
|
||||
+ _12 = deref_copy (*_11);
|
||||
+ switchInt((*_12)) -> [0: bb3, otherwise: bb4];
|
||||
+ PlaceMention((*_12));
|
||||
+ _13 = deref_copy (*_4);
|
||||
+ _14 = deref_copy (*_13);
|
||||
+ _15 = deref_copy (*_14);
|
||||
+ switchInt((*_15)) -> [0: bb3, otherwise: bb4];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
|
@ -18,7 +18,7 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
|
||||
}
|
||||
|
||||
bb0: {
|
||||
FakeRead(ForMatchedPlace(None), _1);
|
||||
PlaceMention(_1);
|
||||
switchInt((_1.0: u32)) -> [1: bb2, 4: bb2, otherwise: bb1];
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,7 @@
|
||||
|
||||
bb5: {
|
||||
StorageDead(_3);
|
||||
PlaceMention(_1);
|
||||
_5 = discriminant(_1);
|
||||
switchInt(move _5) -> [0: bb6, otherwise: bb7];
|
||||
}
|
||||
|
@ -60,6 +60,7 @@
|
||||
|
||||
bb5: {
|
||||
StorageDead(_3);
|
||||
PlaceMention(_1);
|
||||
_5 = discriminant(_1);
|
||||
switchInt(move _5) -> [0: bb6, otherwise: bb7];
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ fn test() -> Option<Box<u32>> {
|
||||
|
||||
bb2: {
|
||||
StorageDead(_7);
|
||||
PlaceMention(_6);
|
||||
_8 = discriminant(_6);
|
||||
switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb4];
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ fn test() -> Option<Box<u32>> {
|
||||
|
||||
bb2: {
|
||||
StorageDead(_7);
|
||||
PlaceMention(_6);
|
||||
_8 = discriminant(_6);
|
||||
switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb4];
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ fn f(_1: Void) -> ! {
|
||||
let mut _0: !;
|
||||
|
||||
bb0: {
|
||||
PlaceMention(_1);
|
||||
FakeRead(ForMatchedPlace(None), _1);
|
||||
unreachable;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ fn main() -> () {
|
||||
_2 = (move _3, move _5);
|
||||
StorageDead(_5);
|
||||
StorageDead(_3);
|
||||
FakeRead(ForMatchedPlace(None), _2);
|
||||
PlaceMention(_2);
|
||||
StorageLive(_8);
|
||||
_8 = (_2.0: &&[u8]);
|
||||
StorageLive(_9);
|
||||
@ -180,7 +180,7 @@ fn main() -> () {
|
||||
_23 = (move _24, move _26);
|
||||
StorageDead(_26);
|
||||
StorageDead(_24);
|
||||
FakeRead(ForMatchedPlace(None), _23);
|
||||
PlaceMention(_23);
|
||||
StorageLive(_28);
|
||||
_28 = (_23.0: &&[u8]);
|
||||
StorageLive(_29);
|
||||
|
@ -81,7 +81,7 @@ fn main() -> () {
|
||||
_2 = (move _3, move _5);
|
||||
StorageDead(_5);
|
||||
StorageDead(_3);
|
||||
FakeRead(ForMatchedPlace(None), _2);
|
||||
PlaceMention(_2);
|
||||
StorageLive(_8);
|
||||
_8 = (_2.0: &&[u8]);
|
||||
StorageLive(_9);
|
||||
@ -180,7 +180,7 @@ fn main() -> () {
|
||||
_23 = (move _24, move _26);
|
||||
StorageDead(_26);
|
||||
StorageDead(_24);
|
||||
FakeRead(ForMatchedPlace(None), _23);
|
||||
PlaceMention(_23);
|
||||
StorageLive(_28);
|
||||
_28 = (_23.0: &&[u8]);
|
||||
StorageLive(_29);
|
||||
|
@ -4,6 +4,7 @@
|
||||
fn transmute_to_box_uninhabited() -> ! {
|
||||
let mut _0: !;
|
||||
let _1: std::boxed::Box<Never>;
|
||||
let mut _2: *const Never;
|
||||
scope 1 {
|
||||
debug x => _1;
|
||||
}
|
||||
@ -16,6 +17,8 @@
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_2 = (((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>).0: *const Never);
|
||||
PlaceMention((*_2));
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
fn transmute_to_box_uninhabited() -> ! {
|
||||
let mut _0: !;
|
||||
let _1: std::boxed::Box<Never>;
|
||||
let mut _2: *const Never;
|
||||
scope 1 {
|
||||
debug x => _1;
|
||||
}
|
||||
@ -16,6 +17,8 @@
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_2 = (((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>).0: *const Never);
|
||||
PlaceMention((*_2));
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
}
|
||||
|
||||
bb1: {
|
||||
PlaceMention((*_1));
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
}
|
||||
|
||||
bb1: {
|
||||
PlaceMention((*_1));
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
}
|
||||
|
||||
bb1: {
|
||||
PlaceMention((*_1));
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
}
|
||||
|
||||
bb1: {
|
||||
PlaceMention((*_1));
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
}
|
||||
|
||||
bb0: {
|
||||
- FakeRead(ForMatchedPlace(None), _2);
|
||||
PlaceMention(_2);
|
||||
- switchInt((_2.0: bool)) -> [0: bb1, otherwise: bb2];
|
||||
+ switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1];
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
}
|
||||
|
||||
bb0: {
|
||||
- FakeRead(ForMatchedPlace(None), _2);
|
||||
PlaceMention(_2);
|
||||
- switchInt((_2.0: bool)) -> [0: bb1, otherwise: bb2];
|
||||
+ switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1];
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ fn main() -> () {
|
||||
_2 = const true;
|
||||
FakeRead(ForLet(None), _2);
|
||||
StorageLive(_3);
|
||||
FakeRead(ForMatchedPlace(None), _1);
|
||||
PlaceMention(_1);
|
||||
_6 = Le(const 0_i32, _1);
|
||||
switchInt(move _6) -> [0: bb4, otherwise: bb1];
|
||||
}
|
||||
|
@ -13,8 +13,7 @@
|
||||
let mut _8: bool;
|
||||
|
||||
bb0: {
|
||||
- FakeRead(ForMatchedPlace(None), _1);
|
||||
+ nop;
|
||||
PlaceMention(_1);
|
||||
_3 = discriminant(_1);
|
||||
switchInt(move _3) -> [1: bb2, otherwise: bb1];
|
||||
}
|
||||
|
@ -13,8 +13,7 @@
|
||||
let mut _8: bool;
|
||||
|
||||
bb0: {
|
||||
- FakeRead(ForMatchedPlace(None), _1);
|
||||
+ nop;
|
||||
PlaceMention(_1);
|
||||
_3 = discriminant(_1);
|
||||
switchInt(move _3) -> [1: bb2, otherwise: bb1];
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
// check-pass
|
||||
// Issue #53114: NLL's borrow check had some deviations from the old borrow
|
||||
// checker, and both had some deviations from our ideal state. This test
|
||||
// captures the behavior of how `_` bindings are handled with respect to how we
|
||||
// flag expressions that are meant to request unsafe blocks.
|
||||
#![allow(irrefutable_let_patterns)]
|
||||
#![allow(irrefutable_let_patterns, dropping_references)]
|
||||
struct M;
|
||||
|
||||
fn let_wild_gets_moved_expr() {
|
||||
@ -19,29 +20,23 @@ fn let_wild_gets_moved_expr() {
|
||||
fn match_moved_expr_to_wild() {
|
||||
let m = M;
|
||||
drop(m);
|
||||
match m { _ => { } } // #53114: should eventually be accepted too
|
||||
//~^ ERROR [E0382]
|
||||
match m { _ => { } } // #53114: accepted too
|
||||
|
||||
let mm = (M, M); // variation on above with `_` in substructure
|
||||
match mm { (_x, _) => { } }
|
||||
match mm { (_, _y) => { } }
|
||||
//~^ ERROR [E0382]
|
||||
match mm { (_, _) => { } }
|
||||
//~^ ERROR [E0382]
|
||||
}
|
||||
|
||||
fn if_let_moved_expr_to_wild() {
|
||||
let m = M;
|
||||
drop(m);
|
||||
if let _ = m { } // #53114: should eventually be accepted too
|
||||
//~^ ERROR [E0382]
|
||||
if let _ = m { } // #53114: accepted too
|
||||
|
||||
let mm = (M, M); // variation on above with `_` in substructure
|
||||
if let (_x, _) = mm { }
|
||||
if let (_, _y) = mm { }
|
||||
//~^ ERROR [E0382]
|
||||
if let (_, _) = mm { }
|
||||
//~^ ERROR [E0382]
|
||||
}
|
||||
|
||||
fn let_wild_gets_borrowed_expr() {
|
||||
|
@ -1,81 +0,0 @@
|
||||
error[E0382]: use of moved value: `m`
|
||||
--> $DIR/issue-53114-borrow-checks.rs:22:11
|
||||
|
|
||||
LL | let m = M;
|
||||
| - move occurs because `m` has type `M`, which does not implement the `Copy` trait
|
||||
LL | drop(m);
|
||||
| - value moved here
|
||||
LL | match m { _ => { } } // #53114: should eventually be accepted too
|
||||
| ^ value used here after move
|
||||
|
||||
error[E0382]: use of partially moved value: `mm`
|
||||
--> $DIR/issue-53114-borrow-checks.rs:27:11
|
||||
|
|
||||
LL | match mm { (_x, _) => { } }
|
||||
| -- value partially moved here
|
||||
LL | match mm { (_, _y) => { } }
|
||||
| ^^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | match mm { (ref _x, _) => { } }
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `mm`
|
||||
--> $DIR/issue-53114-borrow-checks.rs:29:11
|
||||
|
|
||||
LL | match mm { (_, _y) => { } }
|
||||
| -- value partially moved here
|
||||
LL |
|
||||
LL | match mm { (_, _) => { } }
|
||||
| ^^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | match mm { (_, ref _y) => { } }
|
||||
| +++
|
||||
|
||||
error[E0382]: use of moved value: `m`
|
||||
--> $DIR/issue-53114-borrow-checks.rs:36:16
|
||||
|
|
||||
LL | let m = M;
|
||||
| - move occurs because `m` has type `M`, which does not implement the `Copy` trait
|
||||
LL | drop(m);
|
||||
| - value moved here
|
||||
LL | if let _ = m { } // #53114: should eventually be accepted too
|
||||
| ^ value used here after move
|
||||
|
||||
error[E0382]: use of partially moved value: `mm`
|
||||
--> $DIR/issue-53114-borrow-checks.rs:41:22
|
||||
|
|
||||
LL | if let (_x, _) = mm { }
|
||||
| -- value partially moved here
|
||||
LL | if let (_, _y) = mm { }
|
||||
| ^^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | if let (ref _x, _) = mm { }
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `mm`
|
||||
--> $DIR/issue-53114-borrow-checks.rs:43:21
|
||||
|
|
||||
LL | if let (_, _y) = mm { }
|
||||
| -- value partially moved here
|
||||
LL |
|
||||
LL | if let (_, _) = mm { }
|
||||
| ^^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | if let (_, ref _y) = mm { }
|
||||
| +++
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
@ -42,8 +42,8 @@ fn move_out_by_const_index_and_subslice() {
|
||||
[_x, _, _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_y @ .., _, _] => {}
|
||||
//~^ ERROR use of partially moved value
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,8 +53,8 @@ fn move_out_by_const_index_end_and_subslice() {
|
||||
[.., _x] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_, _, _y @ ..] => {}
|
||||
//~^ ERROR use of partially moved value
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,8 +64,8 @@ fn move_out_by_const_index_field_and_subslice() {
|
||||
[(_x, _), _, _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_y @ .., _, _] => {}
|
||||
//~^ ERROR use of partially moved value
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,8 +75,8 @@ fn move_out_by_const_index_end_field_and_subslice() {
|
||||
[.., (_x, _)] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_, _, _y @ ..] => {}
|
||||
//~^ ERROR use of partially moved value
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,8 +108,8 @@ fn move_out_by_subslice_and_subslice() {
|
||||
[x @ .., _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_, _y @ ..] => {}
|
||||
//~^ ERROR use of partially moved value
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,13 +44,13 @@ LL | [_, _, (ref _x, _)] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-match.rs:44:11
|
||||
--> $DIR/borrowck-move-out-from-array-match.rs:45:10
|
||||
|
|
||||
LL | [_x, _, _] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
...
|
||||
LL | [_y @ .., _, _] => {}
|
||||
| ^^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
@ -59,13 +59,13 @@ LL | [ref _x, _, _] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-match.rs:55:11
|
||||
--> $DIR/borrowck-move-out-from-array-match.rs:56:16
|
||||
|
|
||||
LL | [.., _x] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
...
|
||||
LL | [_, _, _y @ ..] => {}
|
||||
| ^^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
@ -74,13 +74,13 @@ LL | [.., ref _x] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-match.rs:66:11
|
||||
--> $DIR/borrowck-move-out-from-array-match.rs:67:10
|
||||
|
|
||||
LL | [(_x, _), _, _] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
...
|
||||
LL | [_y @ .., _, _] => {}
|
||||
| ^^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
@ -89,13 +89,13 @@ LL | [(ref _x, _), _, _] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-match.rs:77:11
|
||||
--> $DIR/borrowck-move-out-from-array-match.rs:78:16
|
||||
|
|
||||
LL | [.., (_x, _)] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
...
|
||||
LL | [_, _, _y @ ..] => {}
|
||||
| ^^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
@ -134,13 +134,13 @@ LL | [_, _, ref _y @ ..] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-match.rs:110:11
|
||||
--> $DIR/borrowck-move-out-from-array-match.rs:111:13
|
||||
|
|
||||
LL | [x @ .., _] => {}
|
||||
| - value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
...
|
||||
LL | [_, _y @ ..] => {}
|
||||
| ^^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
@ -1,3 +1,4 @@
|
||||
// check-pass
|
||||
// Due to #53114, which causes a "read" of the `_` patterns,
|
||||
// the borrow-checker refuses this code, while it should probably be allowed.
|
||||
// Once the bug is fixed, the test, which is derived from a
|
||||
@ -15,7 +16,6 @@ fn move_out_from_begin_and_one_from_end() {
|
||||
[_, _, _x] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[.., _y, _] => {}
|
||||
}
|
||||
}
|
||||
@ -26,7 +26,6 @@ fn move_out_from_begin_field_and_end_field() {
|
||||
[_, _, (_x, _)] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[.., (_, _y)] => {}
|
||||
}
|
||||
}
|
||||
@ -39,7 +38,6 @@ fn move_out_by_const_index_and_subslice() {
|
||||
[_x, _, _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_, _y @ ..] => {}
|
||||
}
|
||||
}
|
||||
@ -50,7 +48,6 @@ fn move_out_by_const_index_end_and_subslice() {
|
||||
[.., _x] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_y @ .., _] => {}
|
||||
}
|
||||
}
|
||||
@ -61,7 +58,6 @@ fn move_out_by_const_index_field_and_subslice() {
|
||||
[(_x, _), _, _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_, _y @ ..] => {}
|
||||
}
|
||||
}
|
||||
@ -72,7 +68,6 @@ fn move_out_by_const_index_end_field_and_subslice() {
|
||||
[.., (_x, _)] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_y @ .., _] => {}
|
||||
}
|
||||
}
|
||||
@ -83,7 +78,6 @@ fn move_out_by_const_subslice_and_index_field() {
|
||||
[_, _y @ ..] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[(_x, _), _, _] => {}
|
||||
}
|
||||
}
|
||||
@ -94,7 +88,6 @@ fn move_out_by_const_subslice_and_end_index_field() {
|
||||
[_y @ .., _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[.., (_x, _)] => {}
|
||||
}
|
||||
}
|
||||
@ -107,7 +100,6 @@ fn move_out_by_subslice_and_subslice() {
|
||||
[x @ .., _, _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_, _y @ ..] => {}
|
||||
}
|
||||
}
|
||||
|
@ -1,138 +0,0 @@
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:17:11
|
||||
|
|
||||
LL | [_, _, _x] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [_, _, ref _x] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:28:11
|
||||
|
|
||||
LL | [_, _, (_x, _)] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [_, _, (ref _x, _)] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:41:11
|
||||
|
|
||||
LL | [_x, _, _] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [ref _x, _, _] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:52:11
|
||||
|
|
||||
LL | [.., _x] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [.., ref _x] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:63:11
|
||||
|
|
||||
LL | [(_x, _), _, _] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [(ref _x, _), _, _] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:74:11
|
||||
|
|
||||
LL | [.., (_x, _)] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [.., (ref _x, _)] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:85:11
|
||||
|
|
||||
LL | [_, _y @ ..] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [_, ref _y @ ..] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:96:11
|
||||
|
|
||||
LL | [_y @ .., _] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [ref _y @ .., _] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:109:11
|
||||
|
|
||||
LL | [x @ .., _, _] => {}
|
||||
| - value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [ref x @ .., _, _] => {}
|
||||
| +++
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
@ -42,8 +42,8 @@ fn move_out_by_const_index_and_subslice() {
|
||||
[_x, _, _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR [E0382]
|
||||
[ref _y @ .., _, _] => {}
|
||||
//~^ ERROR [E0382]
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,8 +53,8 @@ fn move_out_by_const_index_end_and_subslice() {
|
||||
[.., _x] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR [E0382]
|
||||
[_, _, ref _y @ ..] => {}
|
||||
//~^ ERROR [E0382]
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,8 +64,8 @@ fn move_out_by_const_index_field_and_subslice() {
|
||||
[(_x, _), _, _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR [E0382]
|
||||
[ref _y @ .., _, _] => {}
|
||||
//~^ ERROR [E0382]
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,8 +75,8 @@ fn move_out_by_const_index_end_field_and_subslice() {
|
||||
[.., (_x, _)] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR [E0382]
|
||||
[_, _, ref _y @ ..] => {}
|
||||
//~^ ERROR [E0382]
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,8 +108,8 @@ fn move_out_by_subslice_and_subslice() {
|
||||
[x @ .., _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR [E0382]
|
||||
[_, ref _y @ ..] => {}
|
||||
//~^ ERROR [E0382]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,14 +43,14 @@ help: borrow this binding in the pattern to avoid moving the value
|
||||
LL | [_, _, (ref _x, _)] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-match.rs:44:11
|
||||
error[E0382]: borrow of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-match.rs:45:10
|
||||
|
|
||||
LL | [_x, _, _] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
...
|
||||
LL | [ref _y @ .., _, _] => {}
|
||||
| ^^^^^^ value borrowed here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
@ -58,14 +58,14 @@ help: borrow this binding in the pattern to avoid moving the value
|
||||
LL | [ref _x, _, _] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-match.rs:55:11
|
||||
error[E0382]: borrow of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-match.rs:56:16
|
||||
|
|
||||
LL | [.., _x] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
...
|
||||
LL | [_, _, ref _y @ ..] => {}
|
||||
| ^^^^^^ value borrowed here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
@ -73,14 +73,14 @@ help: borrow this binding in the pattern to avoid moving the value
|
||||
LL | [.., ref _x] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-match.rs:66:11
|
||||
error[E0382]: borrow of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-match.rs:67:10
|
||||
|
|
||||
LL | [(_x, _), _, _] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
...
|
||||
LL | [ref _y @ .., _, _] => {}
|
||||
| ^^^^^^ value borrowed here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
@ -88,14 +88,14 @@ help: borrow this binding in the pattern to avoid moving the value
|
||||
LL | [(ref _x, _), _, _] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-match.rs:77:11
|
||||
error[E0382]: borrow of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-match.rs:78:16
|
||||
|
|
||||
LL | [.., (_x, _)] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
...
|
||||
LL | [_, _, ref _y @ ..] => {}
|
||||
| ^^^^^^ value borrowed here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
@ -133,14 +133,14 @@ help: borrow this binding in the pattern to avoid moving the value
|
||||
LL | [_, _, ref _y @ ..] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-match.rs:110:11
|
||||
error[E0382]: borrow of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-match.rs:111:13
|
||||
|
|
||||
LL | [x @ .., _] => {}
|
||||
| - value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
...
|
||||
LL | [_, ref _y @ ..] => {}
|
||||
| ^^^^^^ value borrowed here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
@ -1,3 +1,4 @@
|
||||
// check-pass
|
||||
// Due to #53114, which causes a "read" of the `_` patterns,
|
||||
// the borrow-checker refuses this code, while it should probably be allowed.
|
||||
// Once the bug is fixed, the test, which is derived from a
|
||||
@ -15,7 +16,6 @@ fn move_out_from_begin_and_one_from_end() {
|
||||
[_, _, _x] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[.., ref _y, _] => {}
|
||||
}
|
||||
}
|
||||
@ -26,7 +26,6 @@ fn move_out_from_begin_field_and_end_field() {
|
||||
[_, _, (_x, _)] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[.., (_, ref _y)] => {}
|
||||
}
|
||||
}
|
||||
@ -39,7 +38,6 @@ fn move_out_by_const_index_and_subslice() {
|
||||
[_x, _, _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_, ref _y @ ..] => {}
|
||||
}
|
||||
}
|
||||
@ -50,7 +48,6 @@ fn move_out_by_const_index_end_and_subslice() {
|
||||
[.., _x] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[ref _y @ .., _] => {}
|
||||
}
|
||||
}
|
||||
@ -61,7 +58,6 @@ fn move_out_by_const_index_field_and_subslice() {
|
||||
[(_x, _), _, _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_, ref _y @ ..] => {}
|
||||
}
|
||||
}
|
||||
@ -72,7 +68,6 @@ fn move_out_by_const_index_end_field_and_subslice() {
|
||||
[.., (_x, _)] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[ref _y @ .., _] => {}
|
||||
}
|
||||
}
|
||||
@ -83,7 +78,6 @@ fn move_out_by_const_subslice_and_index_field() {
|
||||
[_, _y @ ..] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[(ref _x, _), _, _] => {}
|
||||
}
|
||||
}
|
||||
@ -94,7 +88,6 @@ fn move_out_by_const_subslice_and_end_index_field() {
|
||||
[_y @ .., _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[.., (ref _x, _)] => {}
|
||||
}
|
||||
}
|
||||
@ -107,7 +100,6 @@ fn move_out_by_subslice_and_subslice() {
|
||||
[x @ .., _, _] => {}
|
||||
}
|
||||
match a {
|
||||
//~^ ERROR use of partially moved value
|
||||
[_, ref _y @ ..] => {}
|
||||
}
|
||||
}
|
||||
|
@ -1,138 +0,0 @@
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:17:11
|
||||
|
|
||||
LL | [_, _, _x] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [_, _, ref _x] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:28:11
|
||||
|
|
||||
LL | [_, _, (_x, _)] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [_, _, (ref _x, _)] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:41:11
|
||||
|
|
||||
LL | [_x, _, _] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [ref _x, _, _] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:52:11
|
||||
|
|
||||
LL | [.., _x] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [.., ref _x] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:63:11
|
||||
|
|
||||
LL | [(_x, _), _, _] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [(ref _x, _), _, _] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:74:11
|
||||
|
|
||||
LL | [.., (_x, _)] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [.., (ref _x, _)] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:85:11
|
||||
|
|
||||
LL | [_, _y @ ..] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [_, ref _y @ ..] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:96:11
|
||||
|
|
||||
LL | [_y @ .., _] => {}
|
||||
| -- value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [ref _y @ .., _] => {}
|
||||
| +++
|
||||
|
||||
error[E0382]: use of partially moved value: `a`
|
||||
--> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:109:11
|
||||
|
|
||||
LL | [x @ .., _, _] => {}
|
||||
| - value partially moved here
|
||||
LL | }
|
||||
LL | match a {
|
||||
| ^ value used here after partial move
|
||||
|
|
||||
= note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | [ref x @ .., _, _] => {}
|
||||
| +++
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
@ -1,8 +1,8 @@
|
||||
fn main() {
|
||||
let e: i32;
|
||||
match e {
|
||||
//~^ ERROR E0381
|
||||
ref u if true => {}
|
||||
//~^ ERROR E0381
|
||||
ref v if true => {
|
||||
let tx = 0;
|
||||
&tx;
|
||||
|
@ -1,10 +1,11 @@
|
||||
error[E0381]: used binding `e` isn't initialized
|
||||
--> $DIR/issue-62107-match-arm-scopes.rs:3:11
|
||||
--> $DIR/issue-62107-match-arm-scopes.rs:4:9
|
||||
|
|
||||
LL | let e: i32;
|
||||
| - binding declared here but left uninitialized
|
||||
LL | match e {
|
||||
| ^ `e` used here but it isn't initialized
|
||||
LL | ref u if true => {}
|
||||
| ^^^^^ `e` used here but it isn't initialized
|
||||
|
|
||||
help: consider assigning a value
|
||||
|
|
||||
|
@ -52,4 +52,42 @@ fn let_ascribe(string: &Option<&str>, mut num: Option<i32>) {
|
||||
};
|
||||
}
|
||||
|
||||
fn matched(string: &Option<&str>, mut num: Option<i32>) {
|
||||
match if let Some(s) = *string { s.len() } else { 0 } {
|
||||
_ => {}
|
||||
};
|
||||
match if let Some(s) = &num { s } else { &0 } {
|
||||
_ => {}
|
||||
};
|
||||
match if let Some(s) = &mut num {
|
||||
*s += 1;
|
||||
s
|
||||
} else {
|
||||
&mut 0
|
||||
//~^ ERROR temporary value dropped while borrowed
|
||||
} {
|
||||
_ => {}
|
||||
};
|
||||
match if let Some(ref s) = num { s } else { &0 } {
|
||||
_ => {}
|
||||
};
|
||||
match if let Some(mut s) = num {
|
||||
s += 1;
|
||||
s
|
||||
} else {
|
||||
0
|
||||
} {
|
||||
_ => {}
|
||||
};
|
||||
match if let Some(ref mut s) = num {
|
||||
*s += 1;
|
||||
s
|
||||
} else {
|
||||
&mut 0
|
||||
//~^ ERROR temporary value dropped while borrowed
|
||||
} {
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -74,6 +74,44 @@ LL | | };
|
||||
|
|
||||
= note: consider using a `let` binding to create a longer lived value
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/let_underscore_temporary.rs:66:14
|
||||
|
|
||||
LL | match if let Some(s) = &mut num {
|
||||
| ___________-
|
||||
LL | | *s += 1;
|
||||
LL | | s
|
||||
LL | | } else {
|
||||
LL | | &mut 0
|
||||
| | ^ creates a temporary value which is freed while still in use
|
||||
LL | |
|
||||
LL | | } {
|
||||
| | -
|
||||
| | |
|
||||
| |_____temporary value is freed at the end of this statement
|
||||
| borrow later used here
|
||||
|
|
||||
= note: consider using a `let` binding to create a longer lived value
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/let_underscore_temporary.rs:86:14
|
||||
|
|
||||
LL | match if let Some(ref mut s) = num {
|
||||
| ___________-
|
||||
LL | | *s += 1;
|
||||
LL | | s
|
||||
LL | | } else {
|
||||
LL | | &mut 0
|
||||
| | ^ creates a temporary value which is freed while still in use
|
||||
LL | |
|
||||
LL | | } {
|
||||
| | -
|
||||
| | |
|
||||
| |_____temporary value is freed at the end of this statement
|
||||
| borrow later used here
|
||||
|
|
||||
= note: consider using a `let` binding to create a longer lived value
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0716`.
|
||||
|
@ -108,6 +108,11 @@ help: skipping check that does not even have a feature gate
|
||||
|
|
||||
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
||||
|
|
||||
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 8 previous errors; 1 warning emitted
|
||||
|
||||
|
@ -108,6 +108,11 @@ help: skipping check that does not even have a feature gate
|
||||
|
|
||||
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
||||
|
|
||||
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 8 previous errors; 1 warning emitted
|
||||
|
||||
|
@ -9,9 +9,11 @@
|
||||
const INFALLIBLE: *mut Infallible = &[] as *const [Infallible] as *const _ as _;
|
||||
match *INFALLIBLE {}
|
||||
//~^ ERROR dereferencing raw mutable pointers in constant functions is unstable
|
||||
//~| ERROR dereferencing raw mutable pointers in constant functions is unstable
|
||||
|
||||
const BAD: () = unsafe { match *INFALLIBLE {} };
|
||||
//~^ ERROR dereferencing raw mutable pointers in constants is unstable
|
||||
//~| ERROR dereferencing raw mutable pointers in constants is unstable
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -16,8 +16,18 @@ LL | match *INFALLIBLE {}
|
||||
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
|
||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: dereferencing raw mutable pointers in constant functions is unstable
|
||||
--> $DIR/E0396.rs:10:11
|
||||
|
|
||||
LL | match *INFALLIBLE {}
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
|
||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0658]: dereferencing raw mutable pointers in constants is unstable
|
||||
--> $DIR/E0396.rs:13:36
|
||||
--> $DIR/E0396.rs:14:36
|
||||
|
|
||||
LL | const BAD: () = unsafe { match *INFALLIBLE {} };
|
||||
| ^^^^^^^^^^^
|
||||
@ -25,6 +35,16 @@ LL | const BAD: () = unsafe { match *INFALLIBLE {} };
|
||||
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
|
||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error[E0658]: dereferencing raw mutable pointers in constants is unstable
|
||||
--> $DIR/E0396.rs:14:36
|
||||
|
|
||||
LL | const BAD: () = unsafe { match *INFALLIBLE {} };
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
|
||||
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/move-guard-if-let-chain.rs:12:27
|
||||
--> $DIR/move-guard-if-let-chain.rs:12:23
|
||||
|
|
||||
LL | let x: Box<_> = Box::new(1);
|
||||
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
|
||||
@ -7,7 +7,7 @@ LL | let x: Box<_> = Box::new(1);
|
||||
LL | (1, 2) if let y = x && c => (),
|
||||
| - value moved here
|
||||
LL | (1, 2) if let z = x => (),
|
||||
| ^ value used here after move
|
||||
| ^ value used here after move
|
||||
|
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
@ -15,7 +15,7 @@ LL | (1, 2) if let ref y = x && c => (),
|
||||
| +++
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/move-guard-if-let-chain.rs:36:27
|
||||
--> $DIR/move-guard-if-let-chain.rs:36:23
|
||||
|
|
||||
LL | let x: Box<_> = Box::new(1);
|
||||
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
|
||||
@ -23,7 +23,7 @@ LL | let x: Box<_> = Box::new(1);
|
||||
LL | (1, _) if let y = x && c => (),
|
||||
| - value moved here
|
||||
LL | (_, 2) if let z = x => (),
|
||||
| ^ value used here after move
|
||||
| ^ value used here after move
|
||||
|
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
@ -31,15 +31,13 @@ LL | (1, _) if let ref y = x && c => (),
|
||||
| +++
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/move-guard-if-let-chain.rs:59:36
|
||||
--> $DIR/move-guard-if-let-chain.rs:59:32
|
||||
|
|
||||
LL | let x: Box<_> = Box::new(1);
|
||||
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
|
||||
...
|
||||
LL | (1, _) | (_, 2) if let y = x && c => (),
|
||||
| - ^ value used here after move
|
||||
| |
|
||||
| value moved here
|
||||
| ^ value used here after move
|
||||
|
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
|
@ -1,13 +1,14 @@
|
||||
error[E0382]: use of moved value: `a`
|
||||
--> $DIR/dbg-macro-move-semantics.rs:9:18
|
||||
--> $DIR/dbg-macro-move-semantics.rs:9:13
|
||||
|
|
||||
LL | let a = NoCopy(0);
|
||||
| - move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait
|
||||
LL | let _ = dbg!(a);
|
||||
| ------- value moved here
|
||||
LL | let _ = dbg!(a);
|
||||
| ^ value used here after move
|
||||
| ^^^^^^^ value used here after move
|
||||
|
|
||||
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
10
tests/ui/uninhabited/diverging-guard.rs
Normal file
10
tests/ui/uninhabited/diverging-guard.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// check-pass
|
||||
|
||||
enum Void {}
|
||||
|
||||
fn main() {
|
||||
let x: Void;
|
||||
match x {
|
||||
_ if { loop {} } => (),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user