diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index b5ed68009b5fd892289685be60e2a97c84289d66..09153ca24799a9dada0afd8fa4ced467ce6e6937 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -253,8 +253,8 @@ pub fn expr_into_pattern( irrefutable_pat: Pattern<'tcx>, initializer: ExprRef<'tcx>, ) -> BlockAnd<()> { - // optimize the case of `let x = ...` match *irrefutable_pat.kind { + // Optimize the case of `let x = ...` to write directly into `x` PatternKind::Binding { mode: BindingMode::ByValue, var, @@ -267,6 +267,47 @@ pub fn expr_into_pattern( self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } + + // Optimize the case of `let x: T = ...` to write directly + // into `x` and then require that `T == typeof(x)`. + // + // Weirdly, this is needed to prevent the + // `intrinsic-move-val.rs` test case from crashing. That + // test works with uninitialized values in a rather + // dubious way, so it may be that the test is kind of + // broken. + PatternKind::AscribeUserType { + subpattern: Pattern { + kind: box PatternKind::Binding { + mode: BindingMode::ByValue, + var, + subpattern: None, + .. + }, + .. + }, + user_ty: ascription_user_ty, + } => { + let place = + self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard); + unpack!(block = self.into(&place, block, initializer)); + + let source_info = self.source_info(irrefutable_pat.span); + self.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::AscribeUserType( + place.clone(), + ty::Variance::Invariant, + ascription_user_ty, + ), + }, + ); + + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); + block.unit() + } _ => { let place = unpack!(block = self.as_place(block, initializer)); self.place_into_pattern(block, irrefutable_pat, &place, true) diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index 503e8e009b9b13e7858470f75b9d1629875bc6f4..f04d4328929686a856ce14b605a80963c885d782 100644 --- a/src/test/mir-opt/basic_assignment.rs +++ b/src/test/mir-opt/basic_assignment.rs @@ -19,9 +19,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// check that codegen of assignment expressions is sane. Assignments -// tend to be absent in simple code, so subtle breakage in them can -// leave a quite hard-to-find trail of destruction. +// Check codegen for assignments (`a = b`) where the left-hand-side is +// not yet initialized. Assignments tend to be absent in simple code, +// so subtle breakage in them can leave a quite hard-to-find trail of +// destruction. // ignore-tidy-linelength @@ -29,60 +30,42 @@ fn main() { let nodrop_x = false; let nodrop_y; + // Since boolean does not require drop, this can be a simple + // assignment: nodrop_y = nodrop_x; let drop_x : Option> = None; let drop_y; + // Since the type of `drop_y` has drop, we generate a `replace` + // terminator: drop_y = drop_x; } // END RUST SOURCE // START rustc.main.SimplifyCfg-initial.after.mir -// bb0: { -// StorageLive(_1); -// _1 = const false; -// StorageLive(_2); -// StorageLive(_3); -// _3 = _1; -// _2 = move _3; -// StorageDead(_3); -// StorageLive(_4); -// AscribeUserType(_4, Canonical { variables: [], value: std::option::Option> }); -// _4 = std::option::Option>::None; -// StorageLive(_5); -// StorageLive(_6); -// _6 = move _4; -// replace(_5 <-move _6) -> [return: bb2, unwind: bb5]; -// } -// bb1: { -// resume; -// } -// bb2: { -// drop(_6) -> [return: bb6, unwind: bb4]; -// } -// bb3: { -// drop(_4) -> bb1; -// } -// bb4: { -// drop(_5) -> bb3; -// } -// bb5: { -// drop(_6) -> bb4; -// } -// bb6: { -// StorageDead(_6); -// _0 = (); -// drop(_5) -> [return: bb7, unwind: bb3]; -// } -// bb7: { -// StorageDead(_5); -// drop(_4) -> [return: bb8, unwind: bb1]; -// } -// bb8: { -// StorageDead(_4); -// StorageDead(_2); -// StorageDead(_1); -// return; -// } +// bb0: { +// StorageLive(_1); +// _1 = const false; +// StorageLive(_2); +// StorageLive(_3); +// _3 = _1; +// _2 = move _3; +// StorageDead(_3); +// StorageLive(_4); +// _4 = std::option::Option>::None; +// AscribeUserType(_4, o, Canonical { variables: [], value: std::option::Option> }); +// StorageLive(_5); +// StorageLive(_6); +// _6 = move _4; +// replace(_5 <- move _6) -> [return: bb2, unwind: bb5]; +// } +// ... +// bb2: { +// drop(_6) -> [return: bb6, unwind: bb4]; +// } +// ... +// bb5: { +// drop(_6) -> bb4; +// } // END rustc.main.SimplifyCfg-initial.after.mir diff --git a/src/test/mir-opt/nll/reborrow-basic.rs b/src/test/mir-opt/nll/reborrow-basic.rs deleted file mode 100644 index 8a7ea8962fc5d6ba21f626d5fd7d08d058ec2cf9..0000000000000000000000000000000000000000 --- a/src/test/mir-opt/nll/reborrow-basic.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Basic test for reborrow constraints: the region (`R5`) that appears -// in the type of `r_a` must outlive the region (`R7`) that appears in -// the type of `r_b` - -// compile-flags:-Zborrowck=mir -Zverbose -// ^^^^^^^^^ force compiler to dump more region information - -#![allow(warnings)] - -fn use_x(_: &mut i32) -> bool { true } - -fn main() { - let mut foo: i32 = 22; - let r_a: &mut i32 = &mut foo; - let r_b: &mut i32 = &mut *r_a; - use_x(r_b); -} - -// END RUST SOURCE -// START rustc.main.nll.0.mir -// | '_#7r | U0 | {bb0[4], bb0[8..=17]} -// ... -// | '_#9r | U0 | {bb0[10], bb0[14..=17]} -// ... -// let _4: &'_#9r mut i32; -// ... -// let _2: &'_#7r mut i32; -// END rustc.main.nll.0.mir diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.nll.stderr b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.nll.stderr index d2388c377fc02beb15df0bdd3bf595c2bcfb5b76..674d85d95911260ccb9e87fe9a821424733c1bb5 100644 --- a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.nll.stderr +++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.nll.stderr @@ -1,5 +1,5 @@ error: unsatisfied lifetime constraints - --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:32:19 + --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:32:29 | LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( | -- -- lifetime `'b` defined here @@ -7,10 +7,10 @@ LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( | lifetime `'a` defined here ... LL | let z: I::A = if cond { x } else { y }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b` + | ^ assignment requires that `'a` must outlive `'b` error: unsatisfied lifetime constraints - --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:32:19 + --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:32:40 | LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( | -- -- lifetime `'b` defined here @@ -18,7 +18,7 @@ LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( | lifetime `'a` defined here ... LL | let z: I::A = if cond { x } else { y }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | ^ assignment requires that `'b` must outlive `'a` error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr b/src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr index bedbc744dd3ce1d4fe7be8be4056ab0f2754c29c..0df5e0c6e66925f32341bcdf3e0f8ad0cb4a3d24 100644 --- a/src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-access-permissions.ast.nll.stderr @@ -35,7 +35,7 @@ error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` poin --> $DIR/borrowck-access-permissions.rs:56:23 | LL | let ptr_x : *const _ = &x; - | ----- help: consider changing this to be a mutable pointer: `*mut i32` + | -- help: consider changing this to be a mutable pointer: `&mut x` ... LL | let _y1 = &mut *ptr_x; //[ast]~ ERROR [E0596] | ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable diff --git a/src/test/ui/borrowck/borrowck-access-permissions.mir.stderr b/src/test/ui/borrowck/borrowck-access-permissions.mir.stderr index bedbc744dd3ce1d4fe7be8be4056ab0f2754c29c..0df5e0c6e66925f32341bcdf3e0f8ad0cb4a3d24 100644 --- a/src/test/ui/borrowck/borrowck-access-permissions.mir.stderr +++ b/src/test/ui/borrowck/borrowck-access-permissions.mir.stderr @@ -35,7 +35,7 @@ error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` poin --> $DIR/borrowck-access-permissions.rs:56:23 | LL | let ptr_x : *const _ = &x; - | ----- help: consider changing this to be a mutable pointer: `*mut i32` + | -- help: consider changing this to be a mutable pointer: `&mut x` ... LL | let _y1 = &mut *ptr_x; //[ast]~ ERROR [E0596] | ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable diff --git a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs index c1a46a2f1b560979f278444532822f3352b758dd..dd1c2a447300b5d16e879913d69f57b41c365593 100644 --- a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs +++ b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs @@ -20,9 +20,17 @@ fn make_it() -> for<'a> fn(&'a u32, &'a u32) -> &'a u32 { panic!() } -fn main() { +fn foo() { let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); //~^ ERROR higher-ranked subtype error - //~| ERROR higher-ranked subtype error drop(a); } + +fn bar() { + // The code path for patterns is mildly different, so go ahead and + // test that too: + let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); + //~^ ERROR higher-ranked subtype error +} + +fn main() { } diff --git a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr index bd5d1f44512a2ed335432bac10deb5660ac936ca..c9195395b878c47ffefd1df4fb1dfe26b6a1c2f0 100644 --- a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr +++ b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr @@ -5,10 +5,10 @@ LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); | ^^^^^^^^^ error: higher-ranked subtype error - --> $DIR/hr-fn-aaa-as-aba.rs:24:9 + --> $DIR/hr-fn-aaa-as-aba.rs:32:58 | -LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); - | ^ +LL | let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); + | ^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/relate_tys/universe-violation.stderr b/src/test/ui/nll/relate_tys/universe-violation.stderr index 9de885f6aae01778753f28b9d0fe8f4b0ee85f8e..6dc78789564c71f496898c02885c9c190b96b268 100644 --- a/src/test/ui/nll/relate_tys/universe-violation.stderr +++ b/src/test/ui/nll/relate_tys/universe-violation.stderr @@ -1,14 +1,8 @@ error: higher-ranked subtype error - --> $DIR/universe-violation.rs:14:9 - | -LL | let a: fn(_) -> _ = make_it(); - | ^ - -error: higher-ranked subtype error - --> $DIR/universe-violation.rs:15:9 + --> $DIR/universe-violation.rs:15:31 | LL | let b: fn(&u32) -> &u32 = a; - | ^ + | ^ -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr index ed51cc38d5a6ca92c90cc31bafdd3c54a26a7f0a..e8c1d7e74a038a9477acfcac8bc8d962397cdfae 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr @@ -1,11 +1,10 @@ error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:20:5 + --> $DIR/region-object-lifetime-in-coercion.rs:18:33 | LL | fn a(v: &[u8]) -> Box { | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` -... -LL | x - | ^ lifetime `'static` required +LL | let x: Box = Box::new(v); + | ^^^^^^^^^^^ lifetime `'static` required error[E0621]: explicit lifetime required in the type of `v` --> $DIR/region-object-lifetime-in-coercion.rs:24:5 diff --git a/src/test/ui/slice-mut-2.nll.stderr b/src/test/ui/slice-mut-2.nll.stderr index 9678430060b2730828012b6759c9868b6458815d..98d9297e112a4e47a68dc76f900e34d57d2b31fa 100644 --- a/src/test/ui/slice-mut-2.nll.stderr +++ b/src/test/ui/slice-mut-2.nll.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/slice-mut-2.rs:17:18 | LL | let x: &[isize] = &[1, 2, 3, 4, 5]; - | - help: consider changing this to be a mutable reference: `&mut [isize]` + | ---------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4, 5]` ... LL | let _ = &mut x[2..4]; //~ERROR cannot borrow immutable borrowed content `*x` as mutable | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.nll.stderr index a4527e793923f567f9966e56d52460a3e4e95142..8cda1e60ba988284ddee1bdca2558c03d0e82da5 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.nll.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.nll.stderr @@ -38,12 +38,9 @@ LL | let g = factorial.as_ref().unwrap(); | ^^^^^^^^^ borrowed value does not live long enough ... LL | } - | - - | | - | `factorial` dropped here while still borrowed - | borrow later used here, when `factorial` is dropped + | - `factorial` dropped here while still borrowed | - = note: values in a scope are dropped in the opposite order they are defined + = note: borrowed value must be valid for the static lifetime... error[E0506]: cannot assign to `factorial` because it is borrowed --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:42:5 @@ -55,10 +52,9 @@ LL | let g = factorial.as_ref().unwrap(); | --------- borrow occurs due to use in closure ... LL | factorial = Some(Box::new(f)); - | ^^^^^^^^^ - | | - | assignment to borrowed `factorial` occurs here - | borrow later used here + | ^^^^^^^^^ assignment to borrowed `factorial` occurs here + | + = note: borrowed value must be valid for the static lifetime... error: aborting due to 4 previous errors