diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 5d0e490ebea5a..b7e15bd8f7423 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -105,6 +105,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), ); + // This error should not be downgraded to a warning, + // even in migrate mode. + self.disable_error_downgrading(); err.buffer(&mut self.errors_buffer); } else { if let Some((reported_place, _)) = self.move_error_reported.get(&move_out_indices) { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 92774bbb7a6b4..548514081d6bf 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -252,6 +252,7 @@ fn do_mir_borrowck<'a, 'tcx>( move_error_reported: BTreeMap::new(), uninitialized_error_reported: Default::default(), errors_buffer, + disable_error_downgrading: false, nonlexical_regioncx: regioncx, used_mut: Default::default(), used_mut_upvars: SmallVec::new(), @@ -363,7 +364,7 @@ fn do_mir_borrowck<'a, 'tcx>( if !mbcx.errors_buffer.is_empty() { mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span()); - if tcx.migrate_borrowck() { + if !mbcx.disable_error_downgrading && tcx.migrate_borrowck() { // When borrowck=migrate, check if AST-borrowck would // error on the given code. @@ -479,6 +480,9 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { uninitialized_error_reported: FxHashSet>, /// Errors to be reported buffer errors_buffer: Vec, + /// If there are no errors reported by the HIR borrow checker, we downgrade + /// all NLL errors to warnings. Setting this flag disables downgrading. + disable_error_downgrading: bool, /// This field keeps track of all the local variables that are declared mut and are mutated. /// Used for the warning issued by an unused mutable local variable. used_mut: FxHashSet, @@ -919,6 +923,12 @@ impl InitializationRequiringAction { } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { + /// If there are no errors reported by the HIR borrow checker, we downgrade + /// all NLL errors to warnings. Calling this disables downgrading. + crate fn disable_error_downgrading(&mut self) { + self.disable_error_downgrading = true; + } + /// Checks an access to the given place to see if it is allowed. Examines the set of borrows /// that are in scope, as well as which paths have been initialized, to ensure that (a) the /// place is initialized and (b) it is not borrowed in some way that would prevent this diff --git a/src/test/ui/async-await/partial-initialization-across-await.rs b/src/test/ui/async-await/partial-initialization-across-await.rs new file mode 100644 index 0000000000000..40f9f5202e77c --- /dev/null +++ b/src/test/ui/async-await/partial-initialization-across-await.rs @@ -0,0 +1,44 @@ +// Test that we don't allow awaiting from an async fn while a local is partially +// initialized. + +// edition:2018 + +#![feature(async_await)] + +struct S { x: i32, y: i32 } +struct T(i32, i32); + +async fn noop() {} + +async fn test_tuple() { + let mut t: (i32, i32); + t.0 = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + noop().await; + t.1 = 88; + let _ = t; +} + +async fn test_tuple_struct() { + let mut t: T; + t.0 = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + noop().await; + t.1 = 88; + let _ = t; +} + +async fn test_struct() { + let mut t: S; + t.x = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + noop().await; + t.y = 88; + let _ = t; +} + +fn main() { + let _ = test_tuple(); + let _ = test_tuple_struct(); + let _ = test_struct(); +} diff --git a/src/test/ui/async-await/partial-initialization-across-await.stderr b/src/test/ui/async-await/partial-initialization-across-await.stderr new file mode 100644 index 0000000000000..fe79eb08befaa --- /dev/null +++ b/src/test/ui/async-await/partial-initialization-across-await.stderr @@ -0,0 +1,21 @@ +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-await.rs:15:5 + | +LL | t.0 = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-await.rs:24:5 + | +LL | t.0 = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-await.rs:33:5 + | +LL | t.x = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs new file mode 100644 index 0000000000000..a987c00b09191 --- /dev/null +++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs @@ -0,0 +1,22 @@ +// Test that we don't allow partial initialization. +// This may be relaxed in the future (see #54987). + +fn main() { + let mut t: (u64, u64); + t.0 = 1; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + t.1 = 1; + + let mut t: (u64, u64); + t.1 = 1; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + t.0 = 1; + + let mut t: (u64, u64); + t.0 = 1; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + + let mut t: (u64,); + t.0 = 1; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] +} diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr new file mode 100644 index 0000000000000..a32b17b165934 --- /dev/null +++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr @@ -0,0 +1,27 @@ +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/disallow-possibly-uninitialized.rs:6:5 + | +LL | t.0 = 1; + | ^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/disallow-possibly-uninitialized.rs:11:5 + | +LL | t.1 = 1; + | ^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/disallow-possibly-uninitialized.rs:16:5 + | +LL | t.0 = 1; + | ^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/disallow-possibly-uninitialized.rs:20:5 + | +LL | t.0 = 1; + | ^^^^^^^ use of possibly uninitialized `t` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/consts/const_let_refutable.nll.stderr b/src/test/ui/consts/const_let_refutable.nll.stderr deleted file mode 100644 index a61c9b0c9fef9..0000000000000 --- a/src/test/ui/consts/const_let_refutable.nll.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0005]: refutable pattern in function argument: `&[]` not covered - --> $DIR/const_let_refutable.rs:3:16 - | -LL | const fn slice([a, b]: &[i32]) -> i32 { - | ^^^^^^ pattern `&[]` not covered - -error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn` - --> $DIR/const_let_refutable.rs:4:5 - | -LL | a + b - | ^^^^^ - | - = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 - = help: add `#![feature(const_fn)]` to the crate attributes to enable - -error[E0381]: use of possibly uninitialized variable: `a` - --> $DIR/const_let_refutable.rs:4:5 - | -LL | a + b - | ^ use of possibly uninitialized `a` - -error[E0381]: use of possibly uninitialized variable: `b` - --> $DIR/const_let_refutable.rs:4:9 - | -LL | a + b - | ^ use of possibly uninitialized `b` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0005, E0381, E0723. -For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/consts/const_let_refutable.rs b/src/test/ui/consts/const_let_refutable.rs index 322048c7fbf3f..7b3a591223025 100644 --- a/src/test/ui/consts/const_let_refutable.rs +++ b/src/test/ui/consts/const_let_refutable.rs @@ -2,10 +2,6 @@ fn main() {} const fn slice([a, b]: &[i32]) -> i32 { //~ ERROR refutable pattern in function argument a + b //~ ERROR can only call other `const fn` within a `const fn` - //~^ WARN use of possibly uninitialized variable: `a` - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will - //~| WARN use of possibly uninitialized variable: `b` - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will + //~^ ERROR use of possibly uninitialized variable: `a` + //~| ERROR use of possibly uninitialized variable: `b` } diff --git a/src/test/ui/consts/const_let_refutable.stderr b/src/test/ui/consts/const_let_refutable.stderr index a848b20ed98f5..a61c9b0c9fef9 100644 --- a/src/test/ui/consts/const_let_refutable.stderr +++ b/src/test/ui/consts/const_let_refutable.stderr @@ -13,27 +13,19 @@ LL | a + b = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 = help: add `#![feature(const_fn)]` to the crate attributes to enable -warning[E0381]: use of possibly uninitialized variable: `a` +error[E0381]: use of possibly uninitialized variable: `a` --> $DIR/const_let_refutable.rs:4:5 | LL | a + b | ^ use of possibly uninitialized `a` - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -warning[E0381]: use of possibly uninitialized variable: `b` +error[E0381]: use of possibly uninitialized variable: `b` --> $DIR/const_let_refutable.rs:4:9 | LL | a + b | ^ use of possibly uninitialized `b` - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0005, E0381, E0723. For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/empty/empty-never-array.nll.stderr b/src/test/ui/empty/empty-never-array.nll.stderr deleted file mode 100644 index 01ee1c3a4d7fa..0000000000000 --- a/src/test/ui/empty/empty-never-array.nll.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0005]: refutable pattern in local binding: `T(_, _)` not covered - --> $DIR/empty-never-array.rs:10:9 - | -LL | / enum Helper { -LL | | T(T, [!; 0]), -LL | | #[allow(dead_code)] -LL | | U(U), -LL | | } - | |_- `Helper` defined here -... -LL | let Helper::U(u) = Helper::T(t, []); - | ^^^^^^^^^^^^ pattern `T(_, _)` not covered - -error[E0381]: use of possibly uninitialized variable: `u` - --> $DIR/empty-never-array.rs:12:5 - | -LL | u - | ^ use of possibly uninitialized `u` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0005, E0381. -For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/empty/empty-never-array.rs b/src/test/ui/empty/empty-never-array.rs index ce781da7d47e1..ffd2545b291e2 100644 --- a/src/test/ui/empty/empty-never-array.rs +++ b/src/test/ui/empty/empty-never-array.rs @@ -10,9 +10,7 @@ fn transmute(t: T) -> U { let Helper::U(u) = Helper::T(t, []); //~^ ERROR refutable pattern in local binding: `T(_, _)` not covered u - //~^ WARN use of possibly uninitialized variable: `u` - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will + //~^ ERROR use of possibly uninitialized variable: `u` } fn main() { diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr index 9911dd4683b66..01ee1c3a4d7fa 100644 --- a/src/test/ui/empty/empty-never-array.stderr +++ b/src/test/ui/empty/empty-never-array.stderr @@ -11,17 +11,13 @@ LL | | } LL | let Helper::U(u) = Helper::T(t, []); | ^^^^^^^^^^^^ pattern `T(_, _)` not covered -warning[E0381]: use of possibly uninitialized variable: `u` +error[E0381]: use of possibly uninitialized variable: `u` --> $DIR/empty-never-array.rs:12:5 | LL | u | ^ use of possibly uninitialized `u` - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -error: aborting due to previous error +error: aborting due to 2 previous errors Some errors have detailed explanations: E0005, E0381. For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/generator/partial-initialization-across-yield.rs b/src/test/ui/generator/partial-initialization-across-yield.rs new file mode 100644 index 0000000000000..1e4593002cb9a --- /dev/null +++ b/src/test/ui/generator/partial-initialization-across-yield.rs @@ -0,0 +1,46 @@ +// Test that we don't allow yielding from a generator while a local is partially +// initialized. + +#![feature(generators)] + +struct S { x: i32, y: i32 } +struct T(i32, i32); + +fn test_tuple() { + let _ = || { + let mut t: (i32, i32); + t.0 = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + yield; + t.1 = 88; + let _ = t; + }; +} + +fn test_tuple_struct() { + let _ = || { + let mut t: T; + t.0 = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + yield; + t.1 = 88; + let _ = t; + }; +} + +fn test_struct() { + let _ = || { + let mut t: S; + t.x = 42; + //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381] + yield; + t.y = 88; + let _ = t; + }; +} + +fn main() { + test_tuple(); + test_tuple_struct(); + test_struct(); +} diff --git a/src/test/ui/generator/partial-initialization-across-yield.stderr b/src/test/ui/generator/partial-initialization-across-yield.stderr new file mode 100644 index 0000000000000..8bf0037e07009 --- /dev/null +++ b/src/test/ui/generator/partial-initialization-across-yield.stderr @@ -0,0 +1,21 @@ +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-yield.rs:12:9 + | +LL | t.0 = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-yield.rs:23:9 + | +LL | t.0 = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error[E0381]: assign to part of possibly uninitialized variable: `t` + --> $DIR/partial-initialization-across-yield.rs:34:9 + | +LL | t.x = 42; + | ^^^^^^^^ use of possibly uninitialized `t` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/issues/issue-15381.nll.stderr b/src/test/ui/issues/issue-15381.nll.stderr deleted file mode 100644 index a8495846b3610..0000000000000 --- a/src/test/ui/issues/issue-15381.nll.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0005]: refutable pattern in `for` loop binding: `&[]` not covered - --> $DIR/issue-15381.rs:4:9 - | -LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { - | ^^^^^^^^ pattern `&[]` not covered - -error[E0381]: borrow of possibly uninitialized variable: `y` - --> $DIR/issue-15381.rs:6:26 - | -LL | println!("y={}", y); - | ^ use of possibly uninitialized `y` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0005, E0381. -For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/issues/issue-15381.rs b/src/test/ui/issues/issue-15381.rs index 3dbd4e717a0db..d21c321b09399 100644 --- a/src/test/ui/issues/issue-15381.rs +++ b/src/test/ui/issues/issue-15381.rs @@ -4,8 +4,6 @@ fn main() { for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { //~^ ERROR refutable pattern in `for` loop binding: `&[]` not covered println!("y={}", y); - //~^ WARN borrow of possibly uninitialized variable: `y` - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will + //~^ ERROR borrow of possibly uninitialized variable: `y` } } diff --git a/src/test/ui/issues/issue-15381.stderr b/src/test/ui/issues/issue-15381.stderr index 7b11d85ead874..a8495846b3610 100644 --- a/src/test/ui/issues/issue-15381.stderr +++ b/src/test/ui/issues/issue-15381.stderr @@ -4,17 +4,13 @@ error[E0005]: refutable pattern in `for` loop binding: `&[]` not covered LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { | ^^^^^^^^ pattern `&[]` not covered -warning[E0381]: borrow of possibly uninitialized variable: `y` +error[E0381]: borrow of possibly uninitialized variable: `y` --> $DIR/issue-15381.rs:6:26 | LL | println!("y={}", y); | ^ use of possibly uninitialized `y` - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -error: aborting due to previous error +error: aborting due to 2 previous errors Some errors have detailed explanations: E0005, E0381. For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.nll.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.nll.stderr deleted file mode 100644 index eee331d95b9bc..0000000000000 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.nll.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0005]: refutable pattern in local binding: `Err(_)` not covered - --> $DIR/recursive-types-are-not-uninhabited.rs:6:9 - | -LL | let Ok(x) = res; - | ^^^^^ pattern `Err(_)` not covered - -error[E0381]: use of possibly uninitialized variable: `x` - --> $DIR/recursive-types-are-not-uninhabited.rs:8:5 - | -LL | x - | ^ use of possibly uninitialized `x` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0005, E0381. -For more information about an error, try `rustc --explain E0005`. diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs index a618aba9413f0..45910c3c3a8c6 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.rs @@ -6,9 +6,7 @@ fn foo(res: Result) -> u32 { let Ok(x) = res; //~^ ERROR refutable pattern x - //~^ WARN use of possibly uninitialized variable: `x` - //~| WARN this error has been downgraded to a warning for backwards compatibility - //~| WARN this represents potential undefined behavior in your code and this warning will + //~^ ERROR use of possibly uninitialized variable: `x` } fn main() { diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr index 9203f893fdbf7..eee331d95b9bc 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -4,17 +4,13 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered LL | let Ok(x) = res; | ^^^^^ pattern `Err(_)` not covered -warning[E0381]: use of possibly uninitialized variable: `x` +error[E0381]: use of possibly uninitialized variable: `x` --> $DIR/recursive-types-are-not-uninhabited.rs:8:5 | LL | x | ^ use of possibly uninitialized `x` - | - = warning: this error has been downgraded to a warning for backwards compatibility with previous releases - = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future - = note: for more information, try `rustc --explain E0729` -error: aborting due to previous error +error: aborting due to 2 previous errors Some errors have detailed explanations: E0005, E0381. For more information about an error, try `rustc --explain E0005`.