Auto merge of #53851 - oli-obk:local_promotion, r=eddyb
Limit the promotion of const fns to the libstd and the `rustc_promotable` attribute There are so many questions around promoting const fn calls... it seems saner to try to limit automatic promotion to const fns which were explicitly opted in for promotion. I added the attribute to all public stable const fns that were already promotable (e.g. not Cell::new) in order to not cause any breakage r? @eddyb cc @nikomatsakis
This commit is contained in:
commit
088fc7384c
45 changed files with 484 additions and 335 deletions
|
|
@ -14,7 +14,8 @@
|
|||
|
||||
// compile-flags: -C debug_assertions=yes
|
||||
|
||||
#![feature(const_fn, libc)]
|
||||
#![stable(feature = "rustc", since = "1.0.0")]
|
||||
#![feature(const_fn, libc, staged_api, rustc_attrs)]
|
||||
#![allow(const_err)]
|
||||
|
||||
extern crate libc;
|
||||
|
|
@ -23,6 +24,8 @@ use std::env;
|
|||
use std::process::{Command, Stdio};
|
||||
|
||||
// this will panic in debug mode and overflow in release mode
|
||||
#[stable(feature = "rustc", since = "1.0.0")]
|
||||
#[rustc_promotable]
|
||||
const fn bar() -> usize { 0 - 1 }
|
||||
|
||||
fn foo() {
|
||||
|
|
|
|||
|
|
@ -13,13 +13,15 @@
|
|||
|
||||
use std::cell::Cell;
|
||||
|
||||
const FIVE: Cell<i32> = Cell::new(5);
|
||||
|
||||
#[inline(never)]
|
||||
fn tuple_field() -> &'static u32 {
|
||||
// This test is MIR-borrowck-only because the old borrowck
|
||||
// doesn't agree that borrows of "frozen" (i.e. without any
|
||||
// interior mutability) fields of non-frozen temporaries,
|
||||
// should be promoted, while MIR promotion does promote them.
|
||||
&(Cell::new(5), 42).1
|
||||
&(FIVE, 42).1
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -15,5 +15,4 @@ fn f(x: usize) -> usize {
|
|||
fn main() {
|
||||
let _ = [0; f(2)];
|
||||
//~^ ERROR calls in constants are limited to constant functions
|
||||
//~| E0080
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,6 @@ error[E0015]: calls in constants are limited to constant functions, tuple struct
|
|||
LL | let _ = [0; f(2)];
|
||||
| ^^^^
|
||||
|
||||
error[E0080]: could not evaluate repeat length
|
||||
--> $DIR/const-call.rs:16:17
|
||||
|
|
||||
LL | let _ = [0; f(2)];
|
||||
| ^^^^ calling non-const fn `f`
|
||||
error: aborting due to previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors occurred: E0015, E0080.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
For more information about this error, try `rustc --explain E0015`.
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ error[E0716]: temporary value dropped while borrowed
|
|||
|
|
||||
LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
LL | //~^ does not live long enough
|
||||
LL | //~^ ERROR does not live long enough
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
|
||||
|
|
|
|||
|
|
@ -31,5 +31,5 @@ fn a() {
|
|||
fn main() {
|
||||
let _: &'static u32 = &meh(); //~ ERROR does not live long enough
|
||||
let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
|
||||
//~^ does not live long enough
|
||||
//~^ ERROR does not live long enough
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ error[E0597]: borrowed value does not live long enough
|
|||
|
|
||||
LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
|
||||
LL | //~^ does not live long enough
|
||||
LL | //~^ ERROR does not live long enough
|
||||
LL | }
|
||||
| - temporary value only lives until here
|
||||
|
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-52443.rs:12:10
|
||||
|
|
||||
LL | [(); & { loop { continue } } ]; //~ ERROR mismatched types
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected usize, found reference
|
||||
| help: consider removing the borrow: `{ loop { continue } }`
|
||||
|
|
||||
= note: expected type `usize`
|
||||
found type `&_`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-52443.rs:13:17
|
||||
|
|
||||
LL | [(); loop { break }]; //~ ERROR mismatched types
|
||||
| ^^^^^ expected (), found usize
|
||||
|
|
||||
= note: expected type `()`
|
||||
found type `usize`
|
||||
|
||||
error[E0019]: constant contains unimplemented expression type
|
||||
--> $DIR/issue-52443.rs:14:11
|
||||
|
|
||||
LL | [(); {while true {break}; 0}]; //~ ERROR constant contains unimplemented expression type
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||
--> $DIR/issue-52443.rs:15:21
|
||||
|
|
||||
LL | [(); { for _ in 0usize.. {}; 0}]; //~ ERROR calls in constants are limited to constant functions
|
||||
| ^^^^^^^^
|
||||
|
||||
error[E0019]: constant contains unimplemented expression type
|
||||
--> $DIR/issue-52443.rs:15:21
|
||||
|
|
||||
LL | [(); { for _ in 0usize.. {}; 0}]; //~ ERROR calls in constants are limited to constant functions
|
||||
| ^^^^^^^^
|
||||
|
||||
error[E0080]: could not evaluate repeat length
|
||||
--> $DIR/issue-52443.rs:15:10
|
||||
|
|
||||
LL | [(); { for _ in 0usize.. {}; 0}]; //~ ERROR calls in constants are limited to constant functions
|
||||
| ^^^^^^^^^^^--------^^^^^^^
|
||||
| |
|
||||
| calling non-const fn `<I as std::iter::IntoIterator><std::ops::RangeFrom<usize>>::into_iter`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors occurred: E0015, E0019, E0080, E0308.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promoted_const_fn_fail.rs:30:27
|
||||
|
|
||||
LL | let x: &'static u8 = &(bar() + 1); //~ ERROR does not live long enough
|
||||
| ^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
...
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0716`.
|
||||
|
|
@ -8,8 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![feature(const_fn, const_fn_union)]
|
||||
|
||||
#![deny(const_err)]
|
||||
|
|
@ -29,10 +27,7 @@ const fn bar() -> u8 {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
// FIXME(oli-obk): this should panic at runtime
|
||||
// this will actually compile, but then
|
||||
// abort at runtime (not panic, hard abort).
|
||||
let x: &'static u8 = &(bar() + 1);
|
||||
let x: &'static u8 = &(bar() + 1); //~ ERROR does not live long enough
|
||||
let y = *x;
|
||||
unreachable!();
|
||||
}
|
||||
|
|
|
|||
14
src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
Normal file
14
src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/promoted_const_fn_fail.rs:30:27
|
||||
|
|
||||
LL | let x: &'static u8 = &(bar() + 1); //~ ERROR does not live long enough
|
||||
| ^^^^^^^^^^^ temporary value does not live long enough
|
||||
...
|
||||
LL | }
|
||||
| - temporary value only lives until here
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0597`.
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
||||
--> $DIR/const-fn-error.rs:16:19
|
||||
|
|
||||
LL | let mut sum = 0;
|
||||
| ^
|
||||
|
|
||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: statements in constant functions are unstable (see issue #48821)
|
||||
--> $DIR/const-fn-error.rs:16:19
|
||||
|
|
||||
LL | let mut sum = 0;
|
||||
| ^
|
||||
|
|
||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||
|
||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
--> $DIR/const-fn-error.rs:19:14
|
||||
|
|
||||
LL | for i in 0..x {
|
||||
| ^^^^
|
||||
|
||||
error[E0019]: constant function contains unimplemented expression type
|
||||
--> $DIR/const-fn-error.rs:19:14
|
||||
|
|
||||
LL | for i in 0..x {
|
||||
| ^^^^
|
||||
|
||||
error[E0080]: could not evaluate constant expression
|
||||
--> $DIR/const-fn-error.rs:29:13
|
||||
|
|
||||
LL | for i in 0..x {
|
||||
| ---- calling non-const fn `<I as std::iter::IntoIterator><std::ops::Range<usize>>::into_iter`
|
||||
...
|
||||
LL | let a : [i32; f(X)]; //~ ERROR E0080
|
||||
| ^^^^^^----^
|
||||
| |
|
||||
| inside call to `f`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors occurred: E0015, E0019, E0080, E0658.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
68
src/test/ui/consts/min_const_fn/promotion.nll.stderr
Normal file
68
src/test/ui/consts/min_const_fn/promotion.nll.stderr
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promotion.rs:13:27
|
||||
|
|
||||
LL | let x: &'static () = &foo1(); //~ ERROR does not live long enough
|
||||
| ^^^^^^ creates a temporary which is freed while still in use
|
||||
...
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promotion.rs:14:28
|
||||
|
|
||||
LL | let y: &'static i32 = &foo2(42); //~ ERROR does not live long enough
|
||||
| ^^^^^^^^ creates a temporary which is freed while still in use
|
||||
...
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promotion.rs:15:28
|
||||
|
|
||||
LL | let z: &'static i32 = &foo3(); //~ ERROR does not live long enough
|
||||
| ^^^^^^ creates a temporary which is freed while still in use
|
||||
...
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promotion.rs:16:34
|
||||
|
|
||||
LL | let a: &'static Cell<i32> = &foo4(); //~ ERROR does not live long enough
|
||||
| ^^^^^^ creates a temporary which is freed while still in use
|
||||
...
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promotion.rs:17:42
|
||||
|
|
||||
LL | let a: &'static Option<Cell<i32>> = &foo5(); //~ ERROR does not live long enough
|
||||
| ^^^^^^ creates a temporary which is freed while still in use
|
||||
LL | let a: &'static Option<Cell<i32>> = &foo6(); //~ ERROR does not live long enough
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promotion.rs:18:42
|
||||
|
|
||||
LL | let a: &'static Option<Cell<i32>> = &foo6(); //~ ERROR does not live long enough
|
||||
| ^^^^^^ creates a temporary which is freed while still in use
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0716`.
|
||||
19
src/test/ui/consts/min_const_fn/promotion.rs
Normal file
19
src/test/ui/consts/min_const_fn/promotion.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#![feature(min_const_fn)]
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
const fn foo1() {}
|
||||
const fn foo2(x: i32) -> i32 { x }
|
||||
const fn foo3() -> i32 { 42 }
|
||||
const fn foo4() -> Cell<i32> { Cell::new(42) }
|
||||
const fn foo5() -> Option<Cell<i32>> { Some(Cell::new(42)) }
|
||||
const fn foo6() -> Option<Cell<i32>> { None }
|
||||
|
||||
fn main() {
|
||||
let x: &'static () = &foo1(); //~ ERROR does not live long enough
|
||||
let y: &'static i32 = &foo2(42); //~ ERROR does not live long enough
|
||||
let z: &'static i32 = &foo3(); //~ ERROR does not live long enough
|
||||
let a: &'static Cell<i32> = &foo4(); //~ ERROR does not live long enough
|
||||
let a: &'static Option<Cell<i32>> = &foo5(); //~ ERROR does not live long enough
|
||||
let a: &'static Option<Cell<i32>> = &foo6(); //~ ERROR does not live long enough
|
||||
}
|
||||
68
src/test/ui/consts/min_const_fn/promotion.stderr
Normal file
68
src/test/ui/consts/min_const_fn/promotion.stderr
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/promotion.rs:13:27
|
||||
|
|
||||
LL | let x: &'static () = &foo1(); //~ ERROR does not live long enough
|
||||
| ^^^^^^ temporary value does not live long enough
|
||||
...
|
||||
LL | }
|
||||
| - temporary value only lives until here
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/promotion.rs:14:28
|
||||
|
|
||||
LL | let y: &'static i32 = &foo2(42); //~ ERROR does not live long enough
|
||||
| ^^^^^^^^ temporary value does not live long enough
|
||||
...
|
||||
LL | }
|
||||
| - temporary value only lives until here
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/promotion.rs:15:28
|
||||
|
|
||||
LL | let z: &'static i32 = &foo3(); //~ ERROR does not live long enough
|
||||
| ^^^^^^ temporary value does not live long enough
|
||||
...
|
||||
LL | }
|
||||
| - temporary value only lives until here
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/promotion.rs:16:34
|
||||
|
|
||||
LL | let a: &'static Cell<i32> = &foo4(); //~ ERROR does not live long enough
|
||||
| ^^^^^^ temporary value does not live long enough
|
||||
...
|
||||
LL | }
|
||||
| - temporary value only lives until here
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/promotion.rs:17:42
|
||||
|
|
||||
LL | let a: &'static Option<Cell<i32>> = &foo5(); //~ ERROR does not live long enough
|
||||
| ^^^^^^ temporary value does not live long enough
|
||||
LL | let a: &'static Option<Cell<i32>> = &foo6(); //~ ERROR does not live long enough
|
||||
LL | }
|
||||
| - temporary value only lives until here
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/promotion.rs:18:42
|
||||
|
|
||||
LL | let a: &'static Option<Cell<i32>> = &foo6(); //~ ERROR does not live long enough
|
||||
| ^^^^^^ temporary value does not live long enough
|
||||
LL | }
|
||||
| - temporary value only lives until here
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0597`.
|
||||
|
|
@ -23,8 +23,6 @@ impl Dim for Dim3 {
|
|||
fn main() {
|
||||
let array: [usize; Dim3::dim()]
|
||||
//~^ ERROR E0015
|
||||
//~| ERROR E0080
|
||||
= [0; Dim3::dim()];
|
||||
//~^ ERROR E0015
|
||||
//~| ERROR E0080
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,26 +5,11 @@ LL | let array: [usize; Dim3::dim()]
|
|||
| ^^^^^^^^^^^
|
||||
|
||||
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||
--> $DIR/issue-39559-2.rs:27:15
|
||||
--> $DIR/issue-39559-2.rs:26:15
|
||||
|
|
||||
LL | = [0; Dim3::dim()];
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error[E0080]: could not evaluate repeat length
|
||||
--> $DIR/issue-39559-2.rs:27:15
|
||||
|
|
||||
LL | = [0; Dim3::dim()];
|
||||
| ^^^^^^^^^^^ calling non-const fn `<Dim3 as Dim>::dim`
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
error[E0080]: could not evaluate constant expression
|
||||
--> $DIR/issue-39559-2.rs:24:16
|
||||
|
|
||||
LL | let array: [usize; Dim3::dim()]
|
||||
| ^^^^^^^^-----------^
|
||||
| |
|
||||
| calling non-const fn `<Dim3 as Dim>::dim`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors occurred: E0015, E0080.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
For more information about this error, try `rustc --explain E0015`.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ const NUM: u8 = xyz();
|
|||
fn main() {
|
||||
match 1 {
|
||||
NUM => unimplemented!(),
|
||||
//~^ ERROR could not evaluate constant pattern
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,16 +4,6 @@ error[E0015]: calls in constants are limited to constant functions, tuple struct
|
|||
LL | const NUM: u8 = xyz();
|
||||
| ^^^^^
|
||||
|
||||
error[E0080]: could not evaluate constant pattern
|
||||
--> $DIR/issue-43105.rs:18:9
|
||||
|
|
||||
LL | const NUM: u8 = xyz();
|
||||
| ----- calling non-const fn `xyz`
|
||||
...
|
||||
LL | NUM => unimplemented!(),
|
||||
| ^^^
|
||||
error: aborting due to previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors occurred: E0015, E0080.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
For more information about this error, try `rustc --explain E0015`.
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ const fn baz() -> i32 {
|
|||
fn main() {
|
||||
foo(2);
|
||||
foo(2 + 3);
|
||||
foo(baz());
|
||||
const BAZ: i32 = baz();
|
||||
foo(BAZ);
|
||||
let a = 4;
|
||||
foo(A);
|
||||
foo(a); //~ ERROR: argument 1 is required to be a constant
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error: argument 1 is required to be a constant
|
||||
--> $DIR/rustc-args-required-const.rs:33:5
|
||||
--> $DIR/rustc-args-required-const.rs:34:5
|
||||
|
|
||||
LL | foo(a); //~ ERROR: argument 1 is required to be a constant
|
||||
| ^^^^^^
|
||||
|
||||
error: argument 2 is required to be a constant
|
||||
--> $DIR/rustc-args-required-const.rs:35:5
|
||||
--> $DIR/rustc-args-required-const.rs:36:5
|
||||
|
|
||||
LL | bar(a, a); //~ ERROR: argument 2 is required to be a constant
|
||||
| ^^^^^^^^^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue