Auto merge of #49172 - oli-obk:const_let, r=eddyb
Allow let bindings and destructuring in constants and const fn r? @eddyb cc https://github.com/rust-lang/rust/issues/48821
This commit is contained in:
commit
9f80ea3281
@ -597,21 +597,6 @@ See [RFC 911] for more details on the design of `const fn`s.
|
||||
[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
|
||||
"##,
|
||||
|
||||
E0016: r##"
|
||||
Blocks in constants may only contain items (such as constant, function
|
||||
definition, etc...) and a tail expression. Erroneous code example:
|
||||
|
||||
```compile_fail,E0016
|
||||
const FOO: i32 = { let x = 0; x }; // 'x' isn't an item!
|
||||
```
|
||||
|
||||
To avoid it, you have to replace the non-item object:
|
||||
|
||||
```
|
||||
const FOO: i32 = { const X : i32 = 0; X };
|
||||
```
|
||||
"##,
|
||||
|
||||
E0017: r##"
|
||||
References in statics and constants may only refer to immutable values.
|
||||
Erroneous code example:
|
||||
|
@ -32,7 +32,7 @@ use rustc::middle::lang_items;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::attr;
|
||||
use syntax::ast::LitKind;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use syntax::feature_gate::{UnstableFeatures, feature_err, emit_feature_err, GateIssue};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
use std::fmt;
|
||||
@ -120,8 +120,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
rpo: ReversePostorder<'a, 'tcx>,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
temp_qualif: IndexVec<Local, Option<Qualif>>,
|
||||
return_qualif: Option<Qualif>,
|
||||
local_qualif: IndexVec<Local, Option<Qualif>>,
|
||||
qualif: Qualif,
|
||||
const_fn_arg_vars: BitVector,
|
||||
temp_promotion_state: IndexVec<Local, TempState>,
|
||||
@ -140,11 +139,11 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
|
||||
let param_env = tcx.param_env(def_id);
|
||||
|
||||
let mut temp_qualif = IndexVec::from_elem(None, &mir.local_decls);
|
||||
let mut local_qualif = IndexVec::from_elem(None, &mir.local_decls);
|
||||
for arg in mir.args_iter() {
|
||||
let mut qualif = Qualif::NEEDS_DROP;
|
||||
qualif.restrict(mir.local_decls[arg].ty, tcx, param_env);
|
||||
temp_qualif[arg] = Some(qualif);
|
||||
local_qualif[arg] = Some(qualif);
|
||||
}
|
||||
|
||||
Qualifier {
|
||||
@ -155,8 +154,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
rpo,
|
||||
tcx,
|
||||
param_env,
|
||||
temp_qualif,
|
||||
return_qualif: None,
|
||||
local_qualif,
|
||||
qualif: Qualif::empty(),
|
||||
const_fn_arg_vars: BitVector::new(mir.local_decls.len()),
|
||||
temp_promotion_state: temps,
|
||||
@ -191,12 +189,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
fn statement_like(&mut self) {
|
||||
self.add(Qualif::NOT_CONST);
|
||||
if self.mode != Mode::Fn {
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
let mut err = feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
"const_let",
|
||||
self.span,
|
||||
E0016,
|
||||
"blocks in {}s are limited to items and tail expressions",
|
||||
self.mode
|
||||
GateIssue::Language,
|
||||
&format!("statements in {}s are unstable", self.mode),
|
||||
);
|
||||
if self.tcx.sess.teach(&err.get_code().unwrap()) {
|
||||
err.note("Blocks in constants may only contain items (such as constant, function \
|
||||
@ -266,6 +264,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
|
||||
/// Assign the current qualification to the given destination.
|
||||
fn assign(&mut self, dest: &Place<'tcx>, location: Location) {
|
||||
trace!("assign: {:?}", dest);
|
||||
let qualif = self.qualif;
|
||||
let span = self.span;
|
||||
let store = |slot: &mut Option<Qualif>| {
|
||||
@ -281,20 +280,23 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
if self.mir.local_kind(index) == LocalKind::Temp
|
||||
&& self.temp_promotion_state[index].is_promotable() {
|
||||
debug!("store to promotable temp {:?}", index);
|
||||
store(&mut self.temp_qualif[index]);
|
||||
store(&mut self.local_qualif[index]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
match *dest {
|
||||
Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp => {
|
||||
debug!("store to temp {:?}", index);
|
||||
store(&mut self.temp_qualif[index])
|
||||
Place::Local(index) if (self.mir.local_kind(index) == LocalKind::Var ||
|
||||
self.mir.local_kind(index) == LocalKind::Arg) &&
|
||||
self.tcx.sess.features_untracked().const_let => {
|
||||
debug!("store to var {:?}", index);
|
||||
self.local_qualif[index] = Some(self.qualif);
|
||||
}
|
||||
Place::Local(index) if self.mir.local_kind(index) == LocalKind::ReturnPointer => {
|
||||
debug!("store to return place {:?}", index);
|
||||
store(&mut self.return_qualif)
|
||||
Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp ||
|
||||
self.mir.local_kind(index) == LocalKind::ReturnPointer => {
|
||||
debug!("store to {:?} (temp or return pointer)", index);
|
||||
store(&mut self.local_qualif[index])
|
||||
}
|
||||
|
||||
Place::Projection(box Projection {
|
||||
@ -302,7 +304,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
elem: ProjectionElem::Deref
|
||||
}) if self.mir.local_kind(index) == LocalKind::Temp
|
||||
&& self.mir.local_decls[index].ty.is_box()
|
||||
&& self.temp_qualif[index].map_or(false, |qualif| {
|
||||
&& self.local_qualif[index].map_or(false, |qualif| {
|
||||
qualif.intersects(Qualif::NOT_CONST)
|
||||
}) => {
|
||||
// Part of `box expr`, we should've errored
|
||||
@ -355,40 +357,42 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
TerminatorKind::FalseUnwind { .. } => None,
|
||||
|
||||
TerminatorKind::Return => {
|
||||
// Check for unused values. This usually means
|
||||
// there are extra statements in the AST.
|
||||
for temp in mir.temps_iter() {
|
||||
if self.temp_qualif[temp].is_none() {
|
||||
continue;
|
||||
if !self.tcx.sess.features_untracked().const_let {
|
||||
// Check for unused values. This usually means
|
||||
// there are extra statements in the AST.
|
||||
for temp in mir.temps_iter() {
|
||||
if self.local_qualif[temp].is_none() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let state = self.temp_promotion_state[temp];
|
||||
if let TempState::Defined { location, uses: 0 } = state {
|
||||
let data = &mir[location.block];
|
||||
let stmt_idx = location.statement_index;
|
||||
|
||||
// Get the span for the initialization.
|
||||
let source_info = if stmt_idx < data.statements.len() {
|
||||
data.statements[stmt_idx].source_info
|
||||
} else {
|
||||
data.terminator().source_info
|
||||
};
|
||||
self.span = source_info.span;
|
||||
|
||||
// Treat this as a statement in the AST.
|
||||
self.statement_like();
|
||||
}
|
||||
}
|
||||
|
||||
let state = self.temp_promotion_state[temp];
|
||||
if let TempState::Defined { location, uses: 0 } = state {
|
||||
let data = &mir[location.block];
|
||||
let stmt_idx = location.statement_index;
|
||||
|
||||
// Get the span for the initialization.
|
||||
let source_info = if stmt_idx < data.statements.len() {
|
||||
data.statements[stmt_idx].source_info
|
||||
} else {
|
||||
data.terminator().source_info
|
||||
};
|
||||
self.span = source_info.span;
|
||||
|
||||
// Treat this as a statement in the AST.
|
||||
self.statement_like();
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure there are no extra unassigned variables.
|
||||
self.qualif = Qualif::NOT_CONST;
|
||||
for index in mir.vars_iter() {
|
||||
if !self.const_fn_arg_vars.contains(index.index()) {
|
||||
debug!("unassigned variable {:?}", index);
|
||||
self.assign(&Place::Local(index), Location {
|
||||
block: bb,
|
||||
statement_index: usize::MAX,
|
||||
});
|
||||
// Make sure there are no extra unassigned variables.
|
||||
self.qualif = Qualif::NOT_CONST;
|
||||
for index in mir.vars_iter() {
|
||||
if !self.const_fn_arg_vars.contains(index.index()) {
|
||||
debug!("unassigned variable {:?}", index);
|
||||
self.assign(&Place::Local(index), Location {
|
||||
block: bb,
|
||||
statement_index: usize::MAX,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,7 +412,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
self.qualif = self.return_qualif.unwrap_or(Qualif::NOT_CONST);
|
||||
self.qualif = self.local_qualif[RETURN_PLACE].unwrap_or(Qualif::NOT_CONST);
|
||||
|
||||
// Account for errors in consts by using the
|
||||
// conservative type qualification instead.
|
||||
@ -453,9 +457,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||
LocalKind::ReturnPointer => {
|
||||
self.not_const();
|
||||
}
|
||||
LocalKind::Var => {
|
||||
LocalKind::Var if !self.tcx.sess.features_untracked().const_let => {
|
||||
if self.mode != Mode::Fn {
|
||||
emit_feature_err(&self.tcx.sess.parse_sess, "const_let",
|
||||
self.span, GateIssue::Language,
|
||||
&format!("let bindings in {}s are unstable",self.mode));
|
||||
}
|
||||
self.add(Qualif::NOT_CONST);
|
||||
}
|
||||
LocalKind::Var |
|
||||
LocalKind::Arg |
|
||||
LocalKind::Temp => {
|
||||
if let LocalKind::Arg = kind {
|
||||
@ -466,7 +476,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||
self.add(Qualif::NOT_PROMOTABLE);
|
||||
}
|
||||
|
||||
if let Some(qualif) = self.temp_qualif[local] {
|
||||
if let Some(qualif) = self.local_qualif[local] {
|
||||
self.add(qualif);
|
||||
} else {
|
||||
self.not_const();
|
||||
@ -588,7 +598,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||
|
||||
// Mark the consumed locals to indicate later drops are noops.
|
||||
if let Operand::Move(Place::Local(local)) = *operand {
|
||||
self.temp_qualif[local] = self.temp_qualif[local].map(|q|
|
||||
self.local_qualif[local] = self.local_qualif[local].map(|q|
|
||||
q - Qualif::NEEDS_DROP
|
||||
);
|
||||
}
|
||||
@ -759,7 +769,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||
}
|
||||
if let Place::Local(local) = *place {
|
||||
if self.mir.local_kind(local) == LocalKind::Temp {
|
||||
if let Some(qualif) = self.temp_qualif[local] {
|
||||
if let Some(qualif) = self.local_qualif[local] {
|
||||
// `forbidden_mut` is false, so we can safely ignore
|
||||
// `MUTABLE_INTERIOR` from the local's qualifications.
|
||||
// This allows borrowing fields which don't have
|
||||
@ -1033,7 +1043,7 @@ This does not pose a problem by itself because they can't be accessed directly."
|
||||
// HACK(eddyb) Emulate a bit of dataflow analysis,
|
||||
// conservatively, that drop elaboration will do.
|
||||
let needs_drop = if let Place::Local(local) = *place {
|
||||
if self.temp_qualif[local].map_or(true, |q| q.intersects(Qualif::NEEDS_DROP)) {
|
||||
if self.local_qualif[local].map_or(true, |q| q.intersects(Qualif::NEEDS_DROP)) {
|
||||
Some(self.mir.local_decls[local].source_info.span)
|
||||
} else {
|
||||
None
|
||||
@ -1070,7 +1080,8 @@ This does not pose a problem by itself because they can't be accessed directly."
|
||||
// Check the allowed const fn argument forms.
|
||||
if let (Mode::ConstFn, &Place::Local(index)) = (self.mode, dest) {
|
||||
if self.mir.local_kind(index) == LocalKind::Var &&
|
||||
self.const_fn_arg_vars.insert(index.index()) {
|
||||
self.const_fn_arg_vars.insert(index.index()) &&
|
||||
!self.tcx.sess.features_untracked().const_let {
|
||||
|
||||
// Direct use of an argument is permitted.
|
||||
match *rvalue {
|
||||
@ -1086,10 +1097,11 @@ This does not pose a problem by itself because they can't be accessed directly."
|
||||
// Avoid a generic error for other uses of arguments.
|
||||
if self.qualif.intersects(Qualif::FN_ARGUMENT) {
|
||||
let decl = &self.mir.local_decls[index];
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
let mut err = feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
"const_let",
|
||||
decl.source_info.span,
|
||||
E0022,
|
||||
GateIssue::Language,
|
||||
"arguments of constant functions can only be immutable by-value bindings"
|
||||
);
|
||||
if self.tcx.sess.teach(&err.get_code().unwrap()) {
|
||||
|
@ -214,6 +214,9 @@ declare_features! (
|
||||
// Allows the definition of `const fn` functions.
|
||||
(active, const_fn, "1.2.0", Some(24111), None),
|
||||
|
||||
// Allows let bindings and destructuring in `const fn` functions and constants.
|
||||
(active, const_let, "1.22.1", Some(48821), None),
|
||||
|
||||
// Allows using #[prelude_import] on glob `use` items.
|
||||
//
|
||||
// rustc internal
|
||||
|
@ -9,18 +9,20 @@
|
||||
// except according to those terms.
|
||||
|
||||
const A: usize = { 1; 2 };
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
//~^ ERROR statements in constants are unstable
|
||||
|
||||
const B: usize = { { } 2 };
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
//~^ ERROR statements in constants are unstable
|
||||
|
||||
macro_rules! foo {
|
||||
() => (()) //~ ERROR: blocks in constants are limited to items and tail expressions
|
||||
() => (()) //~ ERROR statements in constants are unstable
|
||||
}
|
||||
const C: usize = { foo!(); 2 };
|
||||
|
||||
const D: usize = { let x = 4; 2 };
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
//~^^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
//~^ ERROR let bindings in constants are unstable
|
||||
//~| ERROR statements in constants are unstable
|
||||
//~| ERROR let bindings in constants are unstable
|
||||
//~| ERROR statements in constants are unstable
|
||||
|
||||
pub fn main() {}
|
||||
|
@ -9,7 +9,9 @@
|
||||
// except according to those terms.
|
||||
|
||||
type Array = [u32; { let x = 2; 5 }];
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
//~^^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
//~^ ERROR let bindings in constants are unstable
|
||||
//~| ERROR statements in constants are unstable
|
||||
//~| ERROR let bindings in constants are unstable
|
||||
//~| ERROR statements in constants are unstable
|
||||
|
||||
pub fn main() {}
|
||||
|
@ -10,8 +10,10 @@
|
||||
|
||||
enum Foo {
|
||||
Bar = { let x = 1; 3 }
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
//~^^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
//~^ ERROR let bindings in constants are unstable
|
||||
//~| ERROR statements in constants are unstable
|
||||
//~| ERROR let bindings in constants are unstable
|
||||
//~| ERROR statements in constants are unstable
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
@ -8,16 +8,20 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// test that certain things are disallowed in const fn signatures
|
||||
// test that certain things are disallowed in constant functions
|
||||
|
||||
#![feature(const_fn)]
|
||||
|
||||
// no destructuring
|
||||
const fn i((
|
||||
a, //~ ERROR: E0022
|
||||
b //~ ERROR: E0022
|
||||
a,
|
||||
//~^ ERROR arguments of constant functions can only be immutable by-value bindings
|
||||
b
|
||||
//~^ ERROR arguments of constant functions can only be immutable by-value bindings
|
||||
): (u32, u32)) -> u32 {
|
||||
a + b
|
||||
//~^ ERROR let bindings in constant functions are unstable
|
||||
//~| ERROR let bindings in constant functions are unstable
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -38,9 +38,15 @@ const fn get_Y_addr() -> &'static u32 {
|
||||
}
|
||||
|
||||
const fn get() -> u32 {
|
||||
let x = 22; //~ ERROR E0016
|
||||
let y = 44; //~ ERROR E0016
|
||||
let x = 22;
|
||||
//~^ ERROR let bindings in constant functions are unstable
|
||||
//~| ERROR statements in constant functions are unstable
|
||||
let y = 44;
|
||||
//~^ ERROR let bindings in constant functions are unstable
|
||||
//~| ERROR statements in constant functions are unstable
|
||||
x + y
|
||||
//~^ ERROR let bindings in constant functions are unstable
|
||||
//~| ERROR let bindings in constant functions are unstable
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -10,9 +10,12 @@
|
||||
|
||||
pub fn main() {
|
||||
const z: &'static isize = {
|
||||
//~^ ERROR blocks in constants are limited to items and tail expressions
|
||||
//~^ ERROR let bindings in constants are unstable
|
||||
//~| ERROR statements in constants are unstable
|
||||
let p = 3;
|
||||
//~^ ERROR blocks in constants are limited to items and tail expressions
|
||||
//~^ ERROR let bindings in constants are unstable
|
||||
//~| ERROR statements in constants are unstable
|
||||
&p //~ ERROR `p` does not live long enough
|
||||
//~^ ERROR let bindings in constants are unstable
|
||||
};
|
||||
}
|
||||
|
@ -11,8 +11,12 @@
|
||||
#![feature(const_fn)]
|
||||
|
||||
const fn x() {
|
||||
let t = true; //~ ERROR blocks in constant functions are limited to items and tail expressions
|
||||
let x = || t; //~ ERROR blocks in constant functions are limited to items and tail expressions
|
||||
let t = true;
|
||||
//~^ ERROR let bindings in constant functions are unstable
|
||||
//~| ERROR statements in constant functions are unstable
|
||||
let x = || t;
|
||||
//~^ ERROR let bindings in constant functions are unstable
|
||||
//~| ERROR statements in constant functions are unstable
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -14,7 +14,8 @@
|
||||
|
||||
const bad : u32 = {
|
||||
{
|
||||
5; //~ ERROR: blocks in constants are limited to items and tail expressions
|
||||
5;
|
||||
//~^ ERROR statements in constants are unstable
|
||||
0
|
||||
}
|
||||
};
|
||||
@ -22,7 +23,7 @@ const bad : u32 = {
|
||||
const bad_two : u32 = {
|
||||
{
|
||||
invalid();
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
//~^ ERROR statements in constants are unstable
|
||||
//~^^ ERROR: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||
0
|
||||
}
|
||||
@ -31,14 +32,15 @@ const bad_two : u32 = {
|
||||
const bad_three : u32 = {
|
||||
{
|
||||
valid();
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
//~^ ERROR statements in constants are unstable
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
static bad_four : u32 = {
|
||||
{
|
||||
5; //~ ERROR: blocks in statics are limited to items and tail expressions
|
||||
5;
|
||||
//~^ ERROR statements in statics are unstable
|
||||
0
|
||||
}
|
||||
};
|
||||
@ -46,8 +48,8 @@ static bad_four : u32 = {
|
||||
static bad_five : u32 = {
|
||||
{
|
||||
invalid();
|
||||
//~^ ERROR: blocks in statics are limited to items and tail expressions
|
||||
//~^^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
//~^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
//~| ERROR statements in statics are unstable
|
||||
0
|
||||
}
|
||||
};
|
||||
@ -55,14 +57,15 @@ static bad_five : u32 = {
|
||||
static bad_six : u32 = {
|
||||
{
|
||||
valid();
|
||||
//~^ ERROR: blocks in statics are limited to items and tail expressions
|
||||
//~^ ERROR statements in statics are unstable
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
static mut bad_seven : u32 = {
|
||||
{
|
||||
5; //~ ERROR: blocks in statics are limited to items and tail expressions
|
||||
5;
|
||||
//~^ ERROR statements in statics are unstable
|
||||
0
|
||||
}
|
||||
};
|
||||
@ -70,8 +73,8 @@ static mut bad_seven : u32 = {
|
||||
static mut bad_eight : u32 = {
|
||||
{
|
||||
invalid();
|
||||
//~^ ERROR: blocks in statics are limited to items and tail expressions
|
||||
//~^^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
//~^ ERROR statements in statics are unstable
|
||||
//~| ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
0
|
||||
}
|
||||
};
|
||||
@ -79,7 +82,7 @@ static mut bad_eight : u32 = {
|
||||
static mut bad_nine : u32 = {
|
||||
{
|
||||
valid();
|
||||
//~^ ERROR: blocks in statics are limited to items and tail expressions
|
||||
//~^ ERROR statements in statics are unstable
|
||||
0
|
||||
}
|
||||
};
|
||||
|
15
src/test/run-pass/ctfe/const-block-non-item-statement-3.rs
Normal file
15
src/test/run-pass/ctfe/const-block-non-item-statement-3.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#![feature(const_let)]
|
||||
|
||||
type Array = [u32; { let x = 2; 5 }];
|
||||
|
||||
pub fn main() {}
|
17
src/test/run-pass/ctfe/const-block-non-item-statement.rs
Normal file
17
src/test/run-pass/ctfe/const-block-non-item-statement.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#![feature(const_let)]
|
||||
|
||||
enum Foo {
|
||||
Bar = { let x = 1; 3 }
|
||||
}
|
||||
|
||||
pub fn main() {}
|
23
src/test/run-pass/ctfe/const-fn-destructuring-arg.rs
Normal file
23
src/test/run-pass/ctfe/const-fn-destructuring-arg.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// test that certain things are disallowed in constant functions
|
||||
|
||||
#![feature(const_fn, const_let)]
|
||||
|
||||
// no destructuring
|
||||
const fn i((
|
||||
a,
|
||||
b
|
||||
): (u32, u32)) -> u32 {
|
||||
a + b
|
||||
}
|
||||
|
||||
fn main() {}
|
18
src/test/run-pass/ctfe/issue-37550.rs
Normal file
18
src/test/run-pass/ctfe/issue-37550.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// 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.
|
||||
|
||||
#![feature(const_fn, const_let)]
|
||||
|
||||
const fn x() {
|
||||
let t = true;
|
||||
let x = || t;
|
||||
}
|
||||
|
||||
fn main() {}
|
45
src/test/run-pass/ctfe/locals-in-const-fn.rs
Normal file
45
src/test/run-pass/ctfe/locals-in-const-fn.rs
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/48821
|
||||
|
||||
#![feature(const_fn, const_let)]
|
||||
|
||||
const fn foo(i: usize) -> usize {
|
||||
let x = i;
|
||||
x
|
||||
}
|
||||
|
||||
static FOO: usize = foo(42);
|
||||
|
||||
const fn bar(mut i: usize) -> usize {
|
||||
i += 8;
|
||||
let x = &i;
|
||||
*x
|
||||
}
|
||||
|
||||
static BAR: usize = bar(42);
|
||||
|
||||
const fn boo(mut i: usize) -> usize {
|
||||
{
|
||||
let mut x = i;
|
||||
x += 10;
|
||||
i = x;
|
||||
}
|
||||
i
|
||||
}
|
||||
|
||||
static BOO: usize = boo(42);
|
||||
|
||||
fn main() {
|
||||
assert!(FOO == 42);
|
||||
assert!(BAR == 50);
|
||||
assert!(BOO == 52);
|
||||
}
|
30
src/test/ui/const-eval/const_let.rs
Normal file
30
src/test/ui/const-eval/const_let.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
#![feature(const_let)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
struct FakeNeedsDrop;
|
||||
|
||||
impl Drop for FakeNeedsDrop {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
// ok
|
||||
const X: FakeNeedsDrop = { let x = FakeNeedsDrop; x };
|
||||
|
||||
// error
|
||||
const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
|
||||
//~^ ERROR constant contains unimplemented expression type
|
||||
|
||||
// error
|
||||
const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
|
||||
//~^ ERROR constant contains unimplemented expression type
|
15
src/test/ui/const-eval/const_let.stderr
Normal file
15
src/test/ui/const-eval/const_let.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0019]: constant contains unimplemented expression type
|
||||
--> $DIR/const_let.rs:25:55
|
||||
|
|
||||
LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
|
||||
| ^
|
||||
|
||||
error[E0019]: constant contains unimplemented expression type
|
||||
--> $DIR/const_let.rs:29:35
|
||||
|
|
||||
LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0019`.
|
@ -14,7 +14,8 @@ const X : usize = 2;
|
||||
|
||||
const fn f(x: usize) -> usize {
|
||||
let mut sum = 0;
|
||||
//~^ ERROR E0016
|
||||
//~^ let bindings in constant functions are unstable
|
||||
//~| statements in constant functions are unstable
|
||||
for i in 0..x {
|
||||
//~^ ERROR E0015
|
||||
//~| ERROR E0019
|
||||
|
@ -1,23 +1,33 @@
|
||||
error[E0016]: blocks in constant functions are limited to items and tail expressions
|
||||
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:18:14
|
||||
--> $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:18:14
|
||||
--> $DIR/const-fn-error.rs:19:14
|
||||
|
|
||||
LL | for i in 0..x {
|
||||
| ^^^^
|
||||
|
||||
error[E0080]: constant evaluation error
|
||||
--> $DIR/const-fn-error.rs:18:14
|
||||
--> $DIR/const-fn-error.rs:19:14
|
||||
|
|
||||
LL | for i in 0..x {
|
||||
| ^^^^ calling non-const fn `<I as std::iter::IntoIterator><std::ops::Range<usize>>::into_iter`
|
||||
@ -26,12 +36,12 @@ LL | let a : [i32; f(X)];
|
||||
| ---- inside call to `f`
|
||||
|
|
||||
note: for constant expression here
|
||||
--> $DIR/const-fn-error.rs:29:13
|
||||
--> $DIR/const-fn-error.rs:30:13
|
||||
|
|
||||
LL | let a : [i32; f(X)];
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors occurred: E0015, E0016, E0019, E0080.
|
||||
Some errors occurred: E0015, E0019, E0080, E0658.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
|
22
src/test/ui/feature-gate-const_let.rs
Normal file
22
src/test/ui/feature-gate-const_let.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// Test use of const let without feature gate.
|
||||
|
||||
#![feature(const_fn)]
|
||||
|
||||
const fn foo() -> usize {
|
||||
let x = 42;
|
||||
//~^ ERROR statements in constant functions are unstable
|
||||
//~| ERROR: let bindings in constant functions are unstable
|
||||
42
|
||||
}
|
||||
|
||||
fn main() {}
|
19
src/test/ui/feature-gate-const_let.stderr
Normal file
19
src/test/ui/feature-gate-const_let.stderr
Normal file
@ -0,0 +1,19 @@
|
||||
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
||||
--> $DIR/feature-gate-const_let.rs:16:13
|
||||
|
|
||||
LL | let x = 42;
|
||||
| ^^
|
||||
|
|
||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||
|
||||
error[E0658]: statements in constant functions are unstable (see issue #48821)
|
||||
--> $DIR/feature-gate-const_let.rs:16:13
|
||||
|
|
||||
LL | let x = 42;
|
||||
| ^^
|
||||
|
|
||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
Loading…
Reference in New Issue
Block a user