mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Lower never patterns to Unreachable in mir
This commit is contained in:
parent
92d65a92e2
commit
57e8aebb6c
@ -581,8 +581,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
self.dcx().emit_err(NeverPatternWithGuard { span: g.span });
|
self.dcx().emit_err(NeverPatternWithGuard { span: g.span });
|
||||||
}
|
}
|
||||||
|
|
||||||
// We add a fake `loop {}` arm body so that it typecks to `!`.
|
// We add a fake `loop {}` arm body so that it typecks to `!`. The mir lowering of never
|
||||||
// FIXME(never_patterns): Desugar into a call to `unreachable_unchecked`.
|
// patterns ensures this loop is not reachable.
|
||||||
let block = self.arena.alloc(hir::Block {
|
let block = self.arena.alloc(hir::Block {
|
||||||
stmts: &[],
|
stmts: &[],
|
||||||
expr: None,
|
expr: None,
|
||||||
|
@ -682,6 +682,23 @@ impl<'tcx> Pat<'tcx> {
|
|||||||
true
|
true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this a never pattern.
|
||||||
|
pub fn is_never_pattern(&self) -> bool {
|
||||||
|
let mut is_never_pattern = false;
|
||||||
|
self.walk(|pat| match &pat.kind {
|
||||||
|
PatKind::Never => {
|
||||||
|
is_never_pattern = true;
|
||||||
|
false
|
||||||
|
}
|
||||||
|
PatKind::Or { pats } => {
|
||||||
|
is_never_pattern = pats.iter().all(|p| p.is_never_pattern());
|
||||||
|
false
|
||||||
|
}
|
||||||
|
_ => true,
|
||||||
|
});
|
||||||
|
is_never_pattern
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> IntoDiagArg for Pat<'tcx> {
|
impl<'tcx> IntoDiagArg for Pat<'tcx> {
|
||||||
|
@ -1016,6 +1016,9 @@ struct PatternExtraData<'tcx> {
|
|||||||
|
|
||||||
/// Types that must be asserted.
|
/// Types that must be asserted.
|
||||||
ascriptions: Vec<Ascription<'tcx>>,
|
ascriptions: Vec<Ascription<'tcx>>,
|
||||||
|
|
||||||
|
/// Whether this corresponds to a never pattern.
|
||||||
|
is_never: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> PatternExtraData<'tcx> {
|
impl<'tcx> PatternExtraData<'tcx> {
|
||||||
@ -1041,12 +1044,14 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
|
|||||||
pattern: &'pat Pat<'tcx>,
|
pattern: &'pat Pat<'tcx>,
|
||||||
cx: &mut Builder<'_, 'tcx>,
|
cx: &mut Builder<'_, 'tcx>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let is_never = pattern.is_never_pattern();
|
||||||
let mut flat_pat = FlatPat {
|
let mut flat_pat = FlatPat {
|
||||||
match_pairs: vec![MatchPair::new(place, pattern, cx)],
|
match_pairs: vec![MatchPair::new(place, pattern, cx)],
|
||||||
extra_data: PatternExtraData {
|
extra_data: PatternExtraData {
|
||||||
span: pattern.span,
|
span: pattern.span,
|
||||||
bindings: Vec::new(),
|
bindings: Vec::new(),
|
||||||
ascriptions: Vec::new(),
|
ascriptions: Vec::new(),
|
||||||
|
is_never,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cx.simplify_match_pairs(&mut flat_pat.match_pairs, &mut flat_pat.extra_data);
|
cx.simplify_match_pairs(&mut flat_pat.match_pairs, &mut flat_pat.extra_data);
|
||||||
@ -1062,6 +1067,8 @@ struct Candidate<'pat, 'tcx> {
|
|||||||
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
|
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
|
||||||
|
|
||||||
/// ...and if this is non-empty, one of these subcandidates also has to match...
|
/// ...and if this is non-empty, one of these subcandidates also has to match...
|
||||||
|
// Invariant: at the end of the algorithm, this must never contain a `is_never` candidate
|
||||||
|
// because that would break binding consistency.
|
||||||
subcandidates: Vec<Candidate<'pat, 'tcx>>,
|
subcandidates: Vec<Candidate<'pat, 'tcx>>,
|
||||||
|
|
||||||
/// ...and the guard must be evaluated if there is one.
|
/// ...and the guard must be evaluated if there is one.
|
||||||
@ -1172,6 +1179,7 @@ enum TestCase<'pat, 'tcx> {
|
|||||||
Range(&'pat PatRange<'tcx>),
|
Range(&'pat PatRange<'tcx>),
|
||||||
Slice { len: usize, variable_length: bool },
|
Slice { len: usize, variable_length: bool },
|
||||||
Deref { temp: Place<'tcx>, mutability: Mutability },
|
Deref { temp: Place<'tcx>, mutability: Mutability },
|
||||||
|
Never,
|
||||||
Or { pats: Box<[FlatPat<'pat, 'tcx>]> },
|
Or { pats: Box<[FlatPat<'pat, 'tcx>]> },
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1238,6 +1246,9 @@ enum TestKind<'tcx> {
|
|||||||
temp: Place<'tcx>,
|
temp: Place<'tcx>,
|
||||||
mutability: Mutability,
|
mutability: Mutability,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Assert unreachability of never patterns.
|
||||||
|
Never,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A test to perform to determine which [`Candidate`] matches a value.
|
/// A test to perform to determine which [`Candidate`] matches a value.
|
||||||
@ -1662,6 +1673,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
self.cfg.goto(or_block, source_info, any_matches);
|
self.cfg.goto(or_block, source_info, any_matches);
|
||||||
}
|
}
|
||||||
candidate.pre_binding_block = Some(any_matches);
|
candidate.pre_binding_block = Some(any_matches);
|
||||||
|
} else {
|
||||||
|
// Never subcandidates may have a set of bindings inconsistent with their siblings,
|
||||||
|
// which would break later code. So we filter them out. Note that we can't filter out
|
||||||
|
// top-level candidates this way.
|
||||||
|
candidate.subcandidates.retain_mut(|candidate| {
|
||||||
|
if candidate.extra_data.is_never {
|
||||||
|
candidate.visit_leaves(|subcandidate| {
|
||||||
|
let block = subcandidate.pre_binding_block.unwrap();
|
||||||
|
// That block is already unreachable but needs a terminator to make the MIR well-formed.
|
||||||
|
let source_info = self.source_info(subcandidate.extra_data.span);
|
||||||
|
self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
|
||||||
|
});
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if candidate.subcandidates.is_empty() {
|
||||||
|
// If `candidate` has become a leaf candidate, ensure it has a `pre_binding_block`.
|
||||||
|
candidate.pre_binding_block = Some(self.cfg.start_new_block());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2008,6 +2040,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
block = fresh_block;
|
block = fresh_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if candidate.extra_data.is_never {
|
||||||
|
// This arm has a dummy body, we don't need to generate code for it. `block` is already
|
||||||
|
// unreachable (except via false edge).
|
||||||
|
let source_info = self.source_info(candidate.extra_data.span);
|
||||||
|
self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
|
||||||
|
return self.cfg.start_new_block();
|
||||||
|
}
|
||||||
|
|
||||||
self.ascribe_types(
|
self.ascribe_types(
|
||||||
block,
|
block,
|
||||||
parent_data
|
parent_data
|
||||||
|
@ -44,6 +44,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
|
|
||||||
TestCase::Deref { temp, mutability } => TestKind::Deref { temp, mutability },
|
TestCase::Deref { temp, mutability } => TestKind::Deref { temp, mutability },
|
||||||
|
|
||||||
|
TestCase::Never => TestKind::Never,
|
||||||
|
|
||||||
TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
|
TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
|
||||||
|
|
||||||
TestCase::Irrefutable { .. } => span_bug!(
|
TestCase::Irrefutable { .. } => span_bug!(
|
||||||
@ -262,6 +264,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let target = target_block(TestBranch::Success);
|
let target = target_block(TestBranch::Success);
|
||||||
self.call_deref(block, target, place, mutability, ty, temp, test.span);
|
self.call_deref(block, target, place, mutability, ty, temp, test.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestKind::Never => {
|
||||||
|
// Check that the place is initialized.
|
||||||
|
// FIXME(never_patterns): Also assert validity of the data at `place`.
|
||||||
|
self.cfg.push_fake_read(
|
||||||
|
block,
|
||||||
|
source_info,
|
||||||
|
FakeReadCause::ForMatchedPlace(None),
|
||||||
|
place,
|
||||||
|
);
|
||||||
|
// A never pattern is only allowed on an uninhabited type, so validity of the data
|
||||||
|
// implies unreachability.
|
||||||
|
self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,6 +726,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
Some(TestBranch::Success)
|
Some(TestBranch::Success)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(TestKind::Never, _) => {
|
||||||
|
fully_matched = true;
|
||||||
|
Some(TestBranch::Success)
|
||||||
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
TestKind::Switch { .. }
|
TestKind::Switch { .. }
|
||||||
| TestKind::SwitchInt { .. }
|
| TestKind::SwitchInt { .. }
|
||||||
|
@ -124,7 +124,8 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
|||||||
let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None };
|
let default_irrefutable = || TestCase::Irrefutable { binding: None, ascription: None };
|
||||||
let mut subpairs = Vec::new();
|
let mut subpairs = Vec::new();
|
||||||
let test_case = match pattern.kind {
|
let test_case = match pattern.kind {
|
||||||
PatKind::Never | PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
|
PatKind::Wild | PatKind::Error(_) => default_irrefutable(),
|
||||||
|
|
||||||
PatKind::Or { ref pats } => TestCase::Or {
|
PatKind::Or { ref pats } => TestCase::Or {
|
||||||
pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(),
|
pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(),
|
||||||
},
|
},
|
||||||
@ -260,6 +261,8 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
|||||||
subpairs.push(MatchPair::new(PlaceBuilder::from(temp).deref(), subpattern, cx));
|
subpairs.push(MatchPair::new(PlaceBuilder::from(temp).deref(), subpattern, cx));
|
||||||
TestCase::Deref { temp, mutability }
|
TestCase::Deref { temp, mutability }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PatKind::Never => TestCase::Never,
|
||||||
};
|
};
|
||||||
|
|
||||||
MatchPair { place, test_case, subpairs, pattern }
|
MatchPair { place, test_case, subpairs, pattern }
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
//@ known-bug: #120421
|
|
||||||
//@ compile-flags: -Zlint-mir
|
|
||||||
|
|
||||||
#![feature(never_patterns)]
|
|
||||||
|
|
||||||
enum Void {}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let res_void: Result<bool, Void> = Ok(true);
|
|
||||||
|
|
||||||
for (Ok(mut _x) | Err(!)) in [res_void] {}
|
|
||||||
}
|
|
@ -27,8 +27,8 @@ fn opt1(_1: &Result<u32, Void>) -> &u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
StorageLive(_4);
|
FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void));
|
||||||
goto -> bb5;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
@ -38,17 +38,4 @@ fn opt1(_1: &Result<u32, Void>) -> &u32 {
|
|||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
|
||||||
falseUnwind -> [real: bb6, unwind: bb7];
|
|
||||||
}
|
|
||||||
|
|
||||||
bb6: {
|
|
||||||
_5 = const ();
|
|
||||||
goto -> bb5;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb7 (cleanup): {
|
|
||||||
resume;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
// MIR for `opt2` after SimplifyCfg-initial
|
||||||
|
|
||||||
|
fn opt2(_1: &Result<u32, Void>) -> &u32 {
|
||||||
|
debug res => _1;
|
||||||
|
let mut _0: &u32;
|
||||||
|
let mut _2: isize;
|
||||||
|
let _3: &u32;
|
||||||
|
scope 1 {
|
||||||
|
debug x => _3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
PlaceMention(_1);
|
||||||
|
_2 = discriminant((*_1));
|
||||||
|
switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
FakeRead(ForMatchedPlace(None), _1);
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
StorageLive(_3);
|
||||||
|
_3 = &(((*_1) as Ok).0: u32);
|
||||||
|
_0 = &(*_3);
|
||||||
|
StorageDead(_3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void));
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
// MIR for `opt3` after SimplifyCfg-initial
|
||||||
|
|
||||||
|
fn opt3(_1: &Result<u32, Void>) -> &u32 {
|
||||||
|
debug res => _1;
|
||||||
|
let mut _0: &u32;
|
||||||
|
let mut _2: isize;
|
||||||
|
let _3: &u32;
|
||||||
|
scope 1 {
|
||||||
|
debug x => _3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
PlaceMention(_1);
|
||||||
|
_2 = discriminant((*_1));
|
||||||
|
switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
FakeRead(ForMatchedPlace(None), _1);
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void));
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_3);
|
||||||
|
_3 = &(((*_1) as Ok).0: u32);
|
||||||
|
_0 = &(*_3);
|
||||||
|
StorageDead(_3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
// skip-filecheck
|
|
||||||
#![feature(never_patterns)]
|
#![feature(never_patterns)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
@ -6,12 +5,40 @@ enum Void {}
|
|||||||
|
|
||||||
// EMIT_MIR never_patterns.opt1.SimplifyCfg-initial.after.mir
|
// EMIT_MIR never_patterns.opt1.SimplifyCfg-initial.after.mir
|
||||||
fn opt1(res: &Result<u32, Void>) -> &u32 {
|
fn opt1(res: &Result<u32, Void>) -> &u32 {
|
||||||
|
// CHECK-LABEL: fn opt1(
|
||||||
|
// CHECK: bb0: {
|
||||||
|
// CHECK-NOT: {{bb.*}}: {
|
||||||
|
// CHECK: return;
|
||||||
match res {
|
match res {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(!),
|
Err(!),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
// EMIT_MIR never_patterns.opt2.SimplifyCfg-initial.after.mir
|
||||||
opt1(&Ok(0));
|
fn opt2(res: &Result<u32, Void>) -> &u32 {
|
||||||
|
// CHECK-LABEL: fn opt2(
|
||||||
|
// CHECK: bb0: {
|
||||||
|
// CHECK-NOT: {{bb.*}}: {
|
||||||
|
// CHECK: return;
|
||||||
|
match res {
|
||||||
|
Ok(x) | Err(!) => x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR never_patterns.opt3.SimplifyCfg-initial.after.mir
|
||||||
|
fn opt3(res: &Result<u32, Void>) -> &u32 {
|
||||||
|
// CHECK-LABEL: fn opt3(
|
||||||
|
// CHECK: bb0: {
|
||||||
|
// CHECK-NOT: {{bb.*}}: {
|
||||||
|
// CHECK: return;
|
||||||
|
match res {
|
||||||
|
Err(!) | Ok(x) => x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(opt1(&Ok(0)), &0);
|
||||||
|
assert_eq!(opt2(&Ok(0)), &0);
|
||||||
|
assert_eq!(opt3(&Ok(0)), &0);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
//@ check-pass
|
|
||||||
#![feature(never_patterns)]
|
#![feature(never_patterns)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
@ -9,4 +8,5 @@ fn main() {}
|
|||||||
fn anything<T>() -> T {
|
fn anything<T>() -> T {
|
||||||
let x: Void;
|
let x: Void;
|
||||||
match x { ! }
|
match x { ! }
|
||||||
|
//~^ ERROR used binding `x` isn't initialized
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
error[E0381]: used binding `x` isn't initialized
|
||||||
|
--> $DIR/check_place_is_initialized.rs:10:15
|
||||||
|
|
|
||||||
|
LL | let x: Void;
|
||||||
|
| - binding declared here but left uninitialized
|
||||||
|
LL | match x { ! }
|
||||||
|
| ^ `x` used here but it isn't initialized
|
||||||
|
|
|
||||||
|
help: consider assigning a value
|
||||||
|
|
|
||||||
|
LL | let x: Void = /* value */;
|
||||||
|
| +++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0381`.
|
@ -1,3 +1,4 @@
|
|||||||
|
//@ check-pass
|
||||||
#![feature(never_patterns)]
|
#![feature(never_patterns)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
@ -9,26 +10,20 @@ fn main() {
|
|||||||
|
|
||||||
let (Ok(x) | Err(!)) = res_void;
|
let (Ok(x) | Err(!)) = res_void;
|
||||||
println!("{x}");
|
println!("{x}");
|
||||||
//~^ ERROR: used binding `x` is possibly-uninitialized
|
|
||||||
let (Ok(x) | Err(!)) = &res_void;
|
let (Ok(x) | Err(!)) = &res_void;
|
||||||
println!("{x}");
|
println!("{x}");
|
||||||
//~^ ERROR: used binding `x` is possibly-uninitialized
|
|
||||||
let (Err(!) | Ok(x)) = res_void;
|
let (Err(!) | Ok(x)) = res_void;
|
||||||
println!("{x}");
|
println!("{x}");
|
||||||
//~^ ERROR: used binding `x` is possibly-uninitialized
|
|
||||||
|
|
||||||
match res_void {
|
match res_void {
|
||||||
Ok(x) | Err(!) => println!("{x}"),
|
Ok(x) | Err(!) => println!("{x}"),
|
||||||
//~^ ERROR: used binding `x` is possibly-uninitialized
|
|
||||||
}
|
}
|
||||||
match res_void {
|
match res_void {
|
||||||
Err(!) | Ok(x) => println!("{x}"),
|
Err(!) | Ok(x) => println!("{x}"),
|
||||||
//~^ ERROR: used binding `x` is possibly-uninitialized
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let res_res_void: Result<Result<bool, Void>, Void> = Ok(Ok(true));
|
let res_res_void: Result<Result<bool, Void>, Void> = Ok(Ok(true));
|
||||||
match res_res_void {
|
match res_res_void {
|
||||||
Ok(Ok(x) | Err(!)) | Err(!) => println!("{x}"),
|
Ok(Ok(x) | Err(!)) | Err(!) => println!("{x}"),
|
||||||
//~^ ERROR: used binding `x` is possibly-uninitialized
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
error[E0381]: used binding `x` is possibly-uninitialized
|
|
||||||
--> $DIR/use-bindings.rs:11:15
|
|
||||||
|
|
|
||||||
LL | let (Ok(x) | Err(!)) = res_void;
|
|
||||||
| -
|
|
||||||
| |
|
|
||||||
| binding initialized here in some conditions
|
|
||||||
| binding declared here but left uninitialized
|
|
||||||
LL | println!("{x}");
|
|
||||||
| ^^^ `x` used here but it is possibly-uninitialized
|
|
||||||
|
|
|
||||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0381]: used binding `x` is possibly-uninitialized
|
|
||||||
--> $DIR/use-bindings.rs:14:15
|
|
||||||
|
|
|
||||||
LL | let (Ok(x) | Err(!)) = &res_void;
|
|
||||||
| -
|
|
||||||
| |
|
|
||||||
| binding initialized here in some conditions
|
|
||||||
| binding declared here but left uninitialized
|
|
||||||
LL | println!("{x}");
|
|
||||||
| ^^^ `x` used here but it is possibly-uninitialized
|
|
||||||
|
|
|
||||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0381]: used binding `x` is possibly-uninitialized
|
|
||||||
--> $DIR/use-bindings.rs:17:15
|
|
||||||
|
|
|
||||||
LL | let (Err(!) | Ok(x)) = res_void;
|
|
||||||
| -
|
|
||||||
| |
|
|
||||||
| binding initialized here in some conditions
|
|
||||||
| binding declared here but left uninitialized
|
|
||||||
LL | println!("{x}");
|
|
||||||
| ^^^ `x` used here but it is possibly-uninitialized
|
|
||||||
|
|
|
||||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0381]: used binding `x` is possibly-uninitialized
|
|
||||||
--> $DIR/use-bindings.rs:21:37
|
|
||||||
|
|
|
||||||
LL | Ok(x) | Err(!) => println!("{x}"),
|
|
||||||
| - ^^^ `x` used here but it is possibly-uninitialized
|
|
||||||
| |
|
|
||||||
| binding initialized here in some conditions
|
|
||||||
| binding declared here but left uninitialized
|
|
||||||
|
|
|
||||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0381]: used binding `x` is possibly-uninitialized
|
|
||||||
--> $DIR/use-bindings.rs:25:37
|
|
||||||
|
|
|
||||||
LL | Err(!) | Ok(x) => println!("{x}"),
|
|
||||||
| - ^^^ `x` used here but it is possibly-uninitialized
|
|
||||||
| |
|
|
||||||
| binding initialized here in some conditions
|
|
||||||
| binding declared here but left uninitialized
|
|
||||||
|
|
|
||||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0381]: used binding `x` is possibly-uninitialized
|
|
||||||
--> $DIR/use-bindings.rs:31:50
|
|
||||||
|
|
|
||||||
LL | Ok(Ok(x) | Err(!)) | Err(!) => println!("{x}"),
|
|
||||||
| - ^^^ `x` used here but it is possibly-uninitialized
|
|
||||||
| |
|
|
||||||
| binding initialized here in some conditions
|
|
||||||
| binding declared here but left uninitialized
|
|
||||||
|
|
|
||||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0381`.
|
|
Loading…
Reference in New Issue
Block a user