mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #43838 - eddyb:stable-rvalue-promotion, r=arielb1
Stabilize rvalue promotion to 'static. Closes #38865. Documentation PR at rust-lang-nursery/reference#98.
This commit is contained in:
commit
7ac979d8cb
@ -1 +1 @@
|
||||
Subproject commit 1abfbaa70313fdf527cf799ffd9b9a096a62105c
|
||||
Subproject commit 266d429a48468371d2d90669f6a30dd659bb4bdb
|
@ -1,23 +0,0 @@
|
||||
# `rvalue_static_promotion`
|
||||
|
||||
The tracking issue for this feature is: [#38865]
|
||||
|
||||
[#38865]: https://github.com/rust-lang/rust/issues/38865
|
||||
|
||||
------------------------
|
||||
|
||||
The `rvalue_static_promotion` feature allows directly creating `'static` references to
|
||||
constant `rvalue`s, which in particular allowing for more concise code in the common case
|
||||
in which a `'static` reference is all that's needed.
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
```rust
|
||||
#![feature(rvalue_static_promotion)]
|
||||
|
||||
fn main() {
|
||||
let DEFAULT_VALUE: &'static u32 = &42;
|
||||
assert_eq!(*DEFAULT_VALUE, 42);
|
||||
}
|
||||
```
|
@ -873,10 +873,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
let promotable = self.tcx.rvalue_promotable_to_static.borrow().get(&id).cloned()
|
||||
.unwrap_or(false);
|
||||
|
||||
// When the corresponding feature isn't toggled, only promote `[T; 0]`.
|
||||
// Always promote `[T; 0]` (even when e.g. borrowed mutably).
|
||||
let promotable = match expr_ty.sty {
|
||||
ty::TyArray(_, 0) => true,
|
||||
_ => promotable && self.tcx.sess.features.borrow().rvalue_static_promotion,
|
||||
_ => promotable,
|
||||
};
|
||||
|
||||
// Compute maximum lifetime of this rvalue. This is 'static if
|
||||
|
@ -345,9 +345,6 @@ declare_features! (
|
||||
// Allows `repr(align(u16))` struct attribute (RFC 1358)
|
||||
(active, repr_align, "1.17.0", Some(33626)),
|
||||
|
||||
// See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
|
||||
(active, rvalue_static_promotion, "1.15.1", Some(38865)),
|
||||
|
||||
// Used to preserve symbols (see llvm.used)
|
||||
(active, used, "1.18.0", Some(40289)),
|
||||
|
||||
@ -457,6 +454,8 @@ declare_features! (
|
||||
(accepted, associated_consts, "1.20.0", Some(29646)),
|
||||
// Usage of the `compile_error!` macro
|
||||
(accepted, compile_error, "1.20.0", Some(40872)),
|
||||
// See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
|
||||
(accepted, rvalue_static_promotion, "1.21.0", Some(38865)),
|
||||
);
|
||||
|
||||
// If you change this, please modify src/doc/unstable-book as well. You must
|
||||
|
@ -11,10 +11,12 @@
|
||||
// Test lifetimes are linked properly when we take reference
|
||||
// to interior.
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
struct Foo(isize);
|
||||
|
||||
fn foo<'a>() -> &'a isize {
|
||||
let &Foo(ref x) = &Foo(3); //~ ERROR borrowed value does not live long enough
|
||||
let &Foo(ref x) = &id(Foo(3)); //~ ERROR borrowed value does not live long enough
|
||||
x
|
||||
}
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
// Copyright 2017 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn main() {
|
||||
let x: &'static u32 = &42; //~ error: does not live long enough
|
||||
let y: &'static Option<u32> = &None; //~ error: does not live long enough
|
||||
}
|
@ -10,7 +10,9 @@
|
||||
|
||||
// This file must never have a trailing newline
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
fn main() {
|
||||
let x = Some(3);
|
||||
let y = x.as_ref().unwrap_or(&5); //~ ERROR: borrowed value does not live long enough
|
||||
let y = x.as_ref().unwrap_or(&id(5)); //~ ERROR: borrowed value does not live long enough
|
||||
}
|
||||
|
@ -10,9 +10,11 @@
|
||||
|
||||
#![feature(fn_traits)]
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
|
||||
bar.call((
|
||||
&(), //~ ERROR borrowed value does not live long enough
|
||||
&id(()), //~ ERROR borrowed value does not live long enough
|
||||
));
|
||||
}
|
||||
fn main() {}
|
||||
|
@ -8,9 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
const FOO: usize = 3;
|
||||
|
||||
fn foo() -> &'static usize { &FOO }
|
||||
fn foo() -> &'static usize { &id(FOO) }
|
||||
//~^ ERROR: borrowed value does not live long enough
|
||||
|
||||
fn main() {
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Regression test for issue #27591.
|
||||
// Regression test for issue #27592.
|
||||
|
||||
fn write<'a, F: ::std::ops::FnOnce()->::std::fmt::Arguments<'a> + 'a>(fcn: F) {
|
||||
use std::fmt::Write;
|
||||
@ -23,7 +23,7 @@ impl ::std::fmt::Write for Stream {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
write(|| format_args!("{}", "Hello world"));
|
||||
write(|| format_args!("{}", String::from("Hello world")));
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
//~| ERROR borrowed value does not live long enough
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
// are treated as rvalues and their lifetime is not bounded to
|
||||
// the static scope.
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
struct Test;
|
||||
|
||||
enum MyEnum {
|
||||
@ -19,12 +21,14 @@ enum MyEnum {
|
||||
}
|
||||
|
||||
fn structLifetime<'a>() -> &'a Test {
|
||||
let testValue = &Test; //~ ERROR borrowed value does not live long enough
|
||||
let testValue = &id(Test);
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
testValue
|
||||
}
|
||||
|
||||
fn variantLifetime<'a>() -> &'a MyEnum {
|
||||
let testValue = &MyEnum::Variant1; //~ ERROR borrowed value does not live long enough
|
||||
let testValue = &id(MyEnum::Variant1);
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
testValue
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
fn f(_x: &isize) -> &isize {
|
||||
return &3; //~ ERROR borrowed value does not live long enough
|
||||
return &id(3); //~ ERROR borrowed value does not live long enough
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -8,13 +8,15 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
fn foo(cond: bool) {
|
||||
// Here we will infer a type that uses the
|
||||
// region of the if stmt then block:
|
||||
let mut x;
|
||||
|
||||
if cond {
|
||||
x = &3; //~ ERROR borrowed value does not live long enough
|
||||
x = &id(3); //~ ERROR borrowed value does not live long enough
|
||||
assert_eq!(*x, 3);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
struct StateMachineIter<'a> {
|
||||
statefn: &'a StateMachineFunc<'a>
|
||||
}
|
||||
@ -23,19 +25,19 @@ impl<'a> Iterator for StateMachineIter<'a> {
|
||||
}
|
||||
|
||||
fn state1(self_: &mut StateMachineIter) -> Option<&'static str> {
|
||||
self_.statefn = &(state2 as StateMachineFunc);
|
||||
self_.statefn = &id(state2 as StateMachineFunc);
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
return Some("state1");
|
||||
}
|
||||
|
||||
fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> {
|
||||
self_.statefn = &(state3 as StateMachineFunc);
|
||||
self_.statefn = &id(state3 as StateMachineFunc);
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
return Some("state2");
|
||||
}
|
||||
|
||||
fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> {
|
||||
self_.statefn = &(finished as StateMachineFunc);
|
||||
self_.statefn = &id(finished as StateMachineFunc);
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
return Some("state3");
|
||||
}
|
||||
@ -46,7 +48,8 @@ fn finished(_: &mut StateMachineIter) -> Option<(&'static str)> {
|
||||
|
||||
fn state_iter() -> StateMachineIter<'static> {
|
||||
StateMachineIter {
|
||||
statefn: &(state1 as StateMachineFunc) //~ ERROR borrowed value does not live long enough
|
||||
statefn: &id(state1 as StateMachineFunc)
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,11 +10,13 @@
|
||||
|
||||
#![feature(box_syntax)]
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
fn f<T:'static>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
let x: Box<_> = box 3;
|
||||
f(x);
|
||||
let x = &3; //~ ERROR borrowed value does not live long enough
|
||||
let x = &id(3); //~ ERROR borrowed value does not live long enough
|
||||
f(x);
|
||||
}
|
||||
|
@ -8,8 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rvalue_static_promotion)]
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn main() {
|
||||
let x: &'static u32 = &42;
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn f() {
|
||||
let x = [1].iter();
|
||||
let x = vec![1].iter();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -1,14 +1,15 @@
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/borrowck-let-suggestion.rs:12:23
|
||||
--> $DIR/borrowck-let-suggestion.rs:12:27
|
||||
|
|
||||
12 | let x = [1].iter();
|
||||
| --- ^ temporary value dropped here while still borrowed
|
||||
12 | let x = vec![1].iter();
|
||||
| ------- ^ temporary value dropped here while still borrowed
|
||||
| |
|
||||
| temporary value created here
|
||||
13 | }
|
||||
| - temporary value needs to live until here
|
||||
|
|
||||
= note: consider using a `let` binding to increase its lifetime
|
||||
= note: this error originates in a macro outside of the current crate
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
fn f() {
|
||||
let old = ['o']; // statement 0
|
||||
let mut v1 = Vec::new(); // statement 1
|
||||
@ -21,7 +23,7 @@ fn f() {
|
||||
|
||||
let mut v3 = Vec::new(); // statement 5
|
||||
|
||||
v3.push(&'x'); // statement 6
|
||||
v3.push(&id('x')); // statement 6
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
//~| NOTE temporary value created here
|
||||
//~| NOTE temporary value only lives until here
|
||||
@ -31,7 +33,7 @@ fn f() {
|
||||
|
||||
let mut v4 = Vec::new(); // (sub) statement 0
|
||||
|
||||
v4.push(&'y');
|
||||
v4.push(&id('y'));
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
//~| NOTE temporary value created here
|
||||
//~| NOTE temporary value only lives until here
|
||||
@ -42,7 +44,7 @@ fn f() {
|
||||
|
||||
let mut v5 = Vec::new(); // statement 8
|
||||
|
||||
v5.push(&'z');
|
||||
v5.push(&id('z'));
|
||||
//~^ ERROR borrowed value does not live long enough
|
||||
//~| NOTE temporary value created here
|
||||
//~| NOTE temporary value only lives until here
|
||||
|
@ -1,49 +1,49 @@
|
||||
error[E0597]: `young[..]` does not live long enough
|
||||
--> $DIR/borrowck-let-suggestion-suffixes.rs:52:1
|
||||
--> $DIR/borrowck-let-suggestion-suffixes.rs:54:1
|
||||
|
|
||||
19 | v2.push(&young[0]); // statement 4
|
||||
21 | v2.push(&young[0]); // statement 4
|
||||
| -------- borrow occurs here
|
||||
...
|
||||
52 | }
|
||||
54 | }
|
||||
| ^ `young[..]` dropped here while still borrowed
|
||||
|
|
||||
= note: values in a scope are dropped in the opposite order they are created
|
||||
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/borrowck-let-suggestion-suffixes.rs:24:18
|
||||
--> $DIR/borrowck-let-suggestion-suffixes.rs:26:22
|
||||
|
|
||||
24 | v3.push(&'x'); // statement 6
|
||||
| --- ^ temporary value dropped here while still borrowed
|
||||
26 | v3.push(&id('x')); // statement 6
|
||||
| ------- ^ temporary value dropped here while still borrowed
|
||||
| |
|
||||
| temporary value created here
|
||||
...
|
||||
52 | }
|
||||
54 | }
|
||||
| - temporary value needs to live until here
|
||||
|
|
||||
= note: consider using a `let` binding to increase its lifetime
|
||||
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/borrowck-let-suggestion-suffixes.rs:34:22
|
||||
--> $DIR/borrowck-let-suggestion-suffixes.rs:36:26
|
||||
|
|
||||
34 | v4.push(&'y');
|
||||
| --- ^ temporary value dropped here while still borrowed
|
||||
36 | v4.push(&id('y'));
|
||||
| ------- ^ temporary value dropped here while still borrowed
|
||||
| |
|
||||
| temporary value created here
|
||||
...
|
||||
40 | } // (statement 7)
|
||||
42 | } // (statement 7)
|
||||
| - temporary value needs to live until here
|
||||
|
|
||||
= note: consider using a `let` binding to increase its lifetime
|
||||
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/borrowck-let-suggestion-suffixes.rs:45:18
|
||||
--> $DIR/borrowck-let-suggestion-suffixes.rs:47:22
|
||||
|
|
||||
45 | v5.push(&'z');
|
||||
| --- ^ temporary value dropped here while still borrowed
|
||||
47 | v5.push(&id('z'));
|
||||
| ------- ^ temporary value dropped here while still borrowed
|
||||
| |
|
||||
| temporary value created here
|
||||
...
|
||||
52 | }
|
||||
54 | }
|
||||
| - temporary value needs to live until here
|
||||
|
|
||||
= note: consider using a `let` binding to increase its lifetime
|
||||
|
@ -8,9 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
fn main() {
|
||||
let v = vec![
|
||||
&3
|
||||
&id(3)
|
||||
];
|
||||
|
||||
for &&x in &v {
|
||||
|
@ -1,12 +1,12 @@
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/issue-15480.rs:14:6
|
||||
--> $DIR/issue-15480.rs:16:6
|
||||
|
|
||||
13 | &3
|
||||
| - temporary value created here
|
||||
14 | ];
|
||||
15 | &id(3)
|
||||
| ----- temporary value created here
|
||||
16 | ];
|
||||
| ^ temporary value dropped here while still borrowed
|
||||
...
|
||||
19 | }
|
||||
21 | }
|
||||
| - temporary value needs to live until here
|
||||
|
|
||||
= note: consider using a `let` binding to increase its lifetime
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#![feature(box_syntax)]
|
||||
|
||||
fn id<T>(x: T) -> T { x }
|
||||
|
||||
trait Foo { }
|
||||
|
||||
impl<'a> Foo for &'a isize { }
|
||||
@ -17,7 +19,7 @@ impl<'a> Foo for &'a isize { }
|
||||
fn main() {
|
||||
let blah;
|
||||
{
|
||||
let ss: &isize = &1;
|
||||
let ss: &isize = &id(1);
|
||||
blah = box ss as Box<Foo>;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/regions-close-over-borrowed-ref-in-obj.rs:22:5
|
||||
--> $DIR/regions-close-over-borrowed-ref-in-obj.rs:24:5
|
||||
|
|
||||
20 | let ss: &isize = &1;
|
||||
| - temporary value created here
|
||||
21 | blah = box ss as Box<Foo>;
|
||||
22 | }
|
||||
22 | let ss: &isize = &id(1);
|
||||
| ----- temporary value created here
|
||||
23 | blah = box ss as Box<Foo>;
|
||||
24 | }
|
||||
| ^ temporary value dropped here while still borrowed
|
||||
23 | }
|
||||
25 | }
|
||||
| - temporary value needs to live until here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -13,7 +13,7 @@
|
||||
fn main() {
|
||||
let y;
|
||||
{
|
||||
let x: &[isize] = &[1, 2, 3, 4, 5];
|
||||
let x: &[isize] = &vec![1, 2, 3, 4, 5];
|
||||
y = &x[1..];
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/slice-borrow.rs:18:5
|
||||
|
|
||||
16 | let x: &[isize] = &[1, 2, 3, 4, 5];
|
||||
| --------------- temporary value created here
|
||||
16 | let x: &[isize] = &vec![1, 2, 3, 4, 5];
|
||||
| ------------------- temporary value created here
|
||||
17 | y = &x[1..];
|
||||
18 | }
|
||||
| ^ temporary value dropped here while still borrowed
|
||||
19 | }
|
||||
| - temporary value needs to live until here
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user