Auto merge of #56160 - oli-obk:const_fn_let, r=nikomatsakis
Fix various aspects around `let` bindings inside const functions * forbid `let` bindings in const contexts that use short circuiting operators * harden analysis code against derefs of mutable references Initially this PR was about stabilizing `let` bindings, but too many flaws were exposed that need some more testing on nightly
This commit is contained in:
@@ -121,7 +121,6 @@
|
|||||||
#![feature(const_slice_len)]
|
#![feature(const_slice_len)]
|
||||||
#![feature(const_str_as_bytes)]
|
#![feature(const_str_as_bytes)]
|
||||||
#![feature(const_str_len)]
|
#![feature(const_str_len)]
|
||||||
#![feature(const_let)]
|
|
||||||
#![feature(const_int_rotate)]
|
#![feature(const_int_rotate)]
|
||||||
#![feature(const_int_wrapping)]
|
#![feature(const_int_wrapping)]
|
||||||
#![feature(const_int_sign)]
|
#![feature(const_int_sign)]
|
||||||
|
|||||||
@@ -149,6 +149,14 @@ pub struct Mir<'tcx> {
|
|||||||
/// This is used for the "rust-call" ABI.
|
/// This is used for the "rust-call" ABI.
|
||||||
pub spread_arg: Option<Local>,
|
pub spread_arg: Option<Local>,
|
||||||
|
|
||||||
|
/// Mark this MIR of a const context other than const functions as having converted a `&&` or
|
||||||
|
/// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
|
||||||
|
/// this conversion from happening and use short circuiting, we will cause the following code
|
||||||
|
/// to change the value of `x`: `let mut x = 42; false && { x = 55; true };`
|
||||||
|
///
|
||||||
|
/// List of places where control flow was destroyed. Used for error reporting.
|
||||||
|
pub control_flow_destroyed: Vec<(Span, String)>,
|
||||||
|
|
||||||
/// A span representing this MIR, for error reporting
|
/// A span representing this MIR, for error reporting
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|
||||||
@@ -167,6 +175,7 @@ impl<'tcx> Mir<'tcx> {
|
|||||||
arg_count: usize,
|
arg_count: usize,
|
||||||
upvar_decls: Vec<UpvarDecl>,
|
upvar_decls: Vec<UpvarDecl>,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
control_flow_destroyed: Vec<(Span, String)>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// We need `arg_count` locals, and one for the return place
|
// We need `arg_count` locals, and one for the return place
|
||||||
assert!(
|
assert!(
|
||||||
@@ -191,6 +200,7 @@ impl<'tcx> Mir<'tcx> {
|
|||||||
spread_arg: None,
|
spread_arg: None,
|
||||||
span,
|
span,
|
||||||
cache: cache::Cache::new(),
|
cache: cache::Cache::new(),
|
||||||
|
control_flow_destroyed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,6 +431,7 @@ impl_stable_hash_for!(struct Mir<'tcx> {
|
|||||||
arg_count,
|
arg_count,
|
||||||
upvar_decls,
|
upvar_decls,
|
||||||
spread_arg,
|
spread_arg,
|
||||||
|
control_flow_destroyed,
|
||||||
span,
|
span,
|
||||||
cache
|
cache
|
||||||
});
|
});
|
||||||
@@ -1748,6 +1759,9 @@ pub enum StatementKind<'tcx> {
|
|||||||
/// (e.g., inspecting constants and discriminant values), and the
|
/// (e.g., inspecting constants and discriminant values), and the
|
||||||
/// kind of pattern it comes from. This is in order to adapt potential
|
/// kind of pattern it comes from. This is in order to adapt potential
|
||||||
/// error messages to these specific patterns.
|
/// error messages to these specific patterns.
|
||||||
|
///
|
||||||
|
/// Note that this also is emitted for regular `let` bindings to ensure that locals that are
|
||||||
|
/// never accessed still get some sanity checks for e.g. `let x: ! = ..;`
|
||||||
FakeRead(FakeReadCause, Place<'tcx>),
|
FakeRead(FakeReadCause, Place<'tcx>),
|
||||||
|
|
||||||
/// Write the discriminant for a variant to the enum Place.
|
/// Write the discriminant for a variant to the enum Place.
|
||||||
@@ -2984,6 +2998,7 @@ BraceStructTypeFoldableImpl! {
|
|||||||
arg_count,
|
arg_count,
|
||||||
upvar_decls,
|
upvar_decls,
|
||||||
spread_arg,
|
spread_arg,
|
||||||
|
control_flow_destroyed,
|
||||||
span,
|
span,
|
||||||
cache,
|
cache,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ CloneTypeFoldableAndLiftImpls! {
|
|||||||
usize,
|
usize,
|
||||||
::ty::layout::VariantIdx,
|
::ty::layout::VariantIdx,
|
||||||
u64,
|
u64,
|
||||||
|
String,
|
||||||
::middle::region::Scope,
|
::middle::region::Scope,
|
||||||
::syntax::ast::FloatTy,
|
::syntax::ast::FloatTy,
|
||||||
::syntax::ast::NodeId,
|
::syntax::ast::NodeId,
|
||||||
|
|||||||
@@ -849,15 +849,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mir::new(self.cfg.basic_blocks,
|
Mir::new(
|
||||||
self.source_scopes,
|
self.cfg.basic_blocks,
|
||||||
ClearCrossCrate::Set(self.source_scope_local_data),
|
self.source_scopes,
|
||||||
IndexVec::new(),
|
ClearCrossCrate::Set(self.source_scope_local_data),
|
||||||
yield_ty,
|
IndexVec::new(),
|
||||||
self.local_decls,
|
yield_ty,
|
||||||
self.arg_count,
|
self.local_decls,
|
||||||
self.upvar_decls,
|
self.arg_count,
|
||||||
self.fn_span
|
self.upvar_decls,
|
||||||
|
self.fn_span,
|
||||||
|
self.hir.control_flow_destroyed(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -372,6 +372,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
// FIXME(eddyb) use logical ops in constants when
|
// FIXME(eddyb) use logical ops in constants when
|
||||||
// they can handle that kind of control-flow.
|
// they can handle that kind of control-flow.
|
||||||
(hir::BinOpKind::And, hir::Constness::Const) => {
|
(hir::BinOpKind::And, hir::Constness::Const) => {
|
||||||
|
cx.control_flow_destroyed.push((
|
||||||
|
op.span,
|
||||||
|
"`&&` operator".into(),
|
||||||
|
));
|
||||||
ExprKind::Binary {
|
ExprKind::Binary {
|
||||||
op: BinOp::BitAnd,
|
op: BinOp::BitAnd,
|
||||||
lhs: lhs.to_ref(),
|
lhs: lhs.to_ref(),
|
||||||
@@ -379,6 +383,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(hir::BinOpKind::Or, hir::Constness::Const) => {
|
(hir::BinOpKind::Or, hir::Constness::Const) => {
|
||||||
|
cx.control_flow_destroyed.push((
|
||||||
|
op.span,
|
||||||
|
"`||` operator".into(),
|
||||||
|
));
|
||||||
ExprKind::Binary {
|
ExprKind::Binary {
|
||||||
op: BinOp::BitOr,
|
op: BinOp::BitOr,
|
||||||
lhs: lhs.to_ref(),
|
lhs: lhs.to_ref(),
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
|||||||
|
|
||||||
/// True if this constant/function needs overflow checks.
|
/// True if this constant/function needs overflow checks.
|
||||||
check_overflow: bool,
|
check_overflow: bool,
|
||||||
|
|
||||||
|
/// See field with the same name on `Mir`
|
||||||
|
control_flow_destroyed: Vec<(Span, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
@@ -96,9 +99,13 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||||||
constness,
|
constness,
|
||||||
body_owner_kind,
|
body_owner_kind,
|
||||||
check_overflow,
|
check_overflow,
|
||||||
|
control_flow_destroyed: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn control_flow_destroyed(self) -> Vec<(Span, String)> {
|
||||||
|
self.control_flow_destroyed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
|
|||||||
@@ -219,7 +219,8 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
local_decls_for_sig(&sig, span),
|
local_decls_for_sig(&sig, span),
|
||||||
sig.inputs().len(),
|
sig.inputs().len(),
|
||||||
vec![],
|
vec![],
|
||||||
span
|
span,
|
||||||
|
vec![],
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(..) = ty {
|
if let Some(..) = ty {
|
||||||
@@ -396,7 +397,8 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
|||||||
self.local_decls,
|
self.local_decls,
|
||||||
self.sig.inputs().len(),
|
self.sig.inputs().len(),
|
||||||
vec![],
|
vec![],
|
||||||
self.span
|
self.span,
|
||||||
|
vec![],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -844,7 +846,8 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
local_decls,
|
local_decls,
|
||||||
sig.inputs().len(),
|
sig.inputs().len(),
|
||||||
vec![],
|
vec![],
|
||||||
span
|
span,
|
||||||
|
vec![],
|
||||||
);
|
);
|
||||||
if let Abi::RustCall = sig.abi {
|
if let Abi::RustCall = sig.abi {
|
||||||
mir.spread_arg = Some(Local::new(sig.inputs().len()));
|
mir.spread_arg = Some(Local::new(sig.inputs().len()));
|
||||||
@@ -921,6 +924,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
|||||||
local_decls,
|
local_decls,
|
||||||
sig.inputs().len(),
|
sig.inputs().len(),
|
||||||
vec![],
|
vec![],
|
||||||
span
|
span,
|
||||||
|
vec![],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -412,7 +412,8 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
|
|||||||
initial_locals,
|
initial_locals,
|
||||||
0,
|
0,
|
||||||
vec![],
|
vec![],
|
||||||
mir.span
|
mir.span,
|
||||||
|
vec![],
|
||||||
),
|
),
|
||||||
tcx,
|
tcx,
|
||||||
source: mir,
|
source: mir,
|
||||||
|
|||||||
@@ -553,7 +553,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
|||||||
this.super_place(place, context, location);
|
this.super_place(place, context, location);
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
ProjectionElem::Deref => {
|
ProjectionElem::Deref => {
|
||||||
this.add(Qualif::NOT_CONST);
|
if context.is_mutating_use() {
|
||||||
|
// `not_const` errors out in const contexts
|
||||||
|
this.not_const()
|
||||||
|
} else {
|
||||||
|
// just make sure this doesn't get promoted
|
||||||
|
this.add(Qualif::NOT_CONST);
|
||||||
|
}
|
||||||
let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
|
let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
|
||||||
match this.mode {
|
match this.mode {
|
||||||
Mode::Fn => {},
|
Mode::Fn => {},
|
||||||
@@ -1178,7 +1184,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
|||||||
if self.mir.local_kind(index) == LocalKind::Var &&
|
if self.mir.local_kind(index) == LocalKind::Var &&
|
||||||
self.const_fn_arg_vars.insert(index) &&
|
self.const_fn_arg_vars.insert(index) &&
|
||||||
!self.tcx.features().const_let {
|
!self.tcx.features().const_let {
|
||||||
|
|
||||||
// Direct use of an argument is permitted.
|
// Direct use of an argument is permitted.
|
||||||
match *rvalue {
|
match *rvalue {
|
||||||
Rvalue::Use(Operand::Copy(Place::Local(local))) |
|
Rvalue::Use(Operand::Copy(Place::Local(local))) |
|
||||||
@@ -1189,7 +1194,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid a generic error for other uses of arguments.
|
// Avoid a generic error for other uses of arguments.
|
||||||
if self.qualif.contains(Qualif::FN_ARGUMENT) {
|
if self.qualif.contains(Qualif::FN_ARGUMENT) {
|
||||||
let decl = &self.mir.local_decls[index];
|
let decl = &self.mir.local_decls[index];
|
||||||
@@ -1348,6 +1352,37 @@ impl MirPass for QualifyAndPromoteConstants {
|
|||||||
// Do the actual promotion, now that we know what's viable.
|
// Do the actual promotion, now that we know what's viable.
|
||||||
promote_consts::promote_candidates(mir, tcx, temps, candidates);
|
promote_consts::promote_candidates(mir, tcx, temps, candidates);
|
||||||
} else {
|
} else {
|
||||||
|
if !mir.control_flow_destroyed.is_empty() {
|
||||||
|
let mut locals = mir.vars_iter();
|
||||||
|
if let Some(local) = locals.next() {
|
||||||
|
let span = mir.local_decls[local].source_info.span;
|
||||||
|
let mut error = tcx.sess.struct_span_err(
|
||||||
|
span,
|
||||||
|
&format!(
|
||||||
|
"new features like let bindings are not permitted in {}s \
|
||||||
|
which also use short circuiting operators",
|
||||||
|
mode,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
for (span, kind) in mir.control_flow_destroyed.iter() {
|
||||||
|
error.span_note(
|
||||||
|
*span,
|
||||||
|
&format!("use of {} here does not actually short circuit due to \
|
||||||
|
the const evaluator presently not being able to do control flow. \
|
||||||
|
See https://github.com/rust-lang/rust/issues/49146 for more \
|
||||||
|
information.", kind),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for local in locals {
|
||||||
|
let span = mir.local_decls[local].source_info.span;
|
||||||
|
error.span_note(
|
||||||
|
span,
|
||||||
|
"more locals defined here",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
error.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
let promoted_temps = if mode == Mode::Const {
|
let promoted_temps = if mode == Mode::Const {
|
||||||
// Already computed by `mir_const_qualif`.
|
// Already computed by `mir_const_qualif`.
|
||||||
const_promoted_temps.unwrap()
|
const_promoted_temps.unwrap()
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ fn check_statement(
|
|||||||
check_rvalue(tcx, mir, rval, span)
|
check_rvalue(tcx, mir, rval, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
StatementKind::FakeRead(..) => Err((span, "match in const fn is unstable".into())),
|
StatementKind::FakeRead(_, place) => check_place(tcx, mir, place, span, PlaceMode::Read),
|
||||||
|
|
||||||
// just an assignment
|
// just an assignment
|
||||||
StatementKind::SetDiscriminant { .. } => Ok(()),
|
StatementKind::SetDiscriminant { .. } => Ok(()),
|
||||||
|
|||||||
@@ -8,14 +8,12 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn, const_let)]
|
||||||
|
|
||||||
const X : usize = 2;
|
const X : usize = 2;
|
||||||
|
|
||||||
const fn f(x: usize) -> usize {
|
const fn f(x: usize) -> usize {
|
||||||
let mut sum = 0;
|
let mut sum = 0;
|
||||||
//~^ let bindings in constant functions are unstable
|
|
||||||
//~| statements in constant functions are unstable
|
|
||||||
for i in 0..x {
|
for i in 0..x {
|
||||||
//~^ ERROR E0015
|
//~^ ERROR E0015
|
||||||
//~| ERROR E0019
|
//~| ERROR E0019
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// run-pass
|
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
// 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() {}
|
|
||||||
@@ -24,7 +24,7 @@ unsafe impl Sync for Foo {}
|
|||||||
static FOO: Foo = Foo(UnsafeCell::new(42));
|
static FOO: Foo = Foo(UnsafeCell::new(42));
|
||||||
|
|
||||||
static BAR: () = unsafe {
|
static BAR: () = unsafe {
|
||||||
*FOO.0.get() = 5; //~ ERROR could not evaluate static initializer
|
*FOO.0.get() = 5; //~ ERROR contains unimplemented expression type
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
error[E0080]: could not evaluate static initializer
|
error[E0019]: static contains unimplemented expression type
|
||||||
--> $DIR/assign-to-static-within-other-static-2.rs:27:5
|
--> $DIR/assign-to-static-within-other-static-2.rs:27:5
|
||||||
|
|
|
|
||||||
LL | *FOO.0.get() = 5; //~ ERROR could not evaluate static initializer
|
LL | *FOO.0.get() = 5; //~ ERROR contains unimplemented expression type
|
||||||
| ^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0080`.
|
For more information about this error, try `rustc --explain E0019`.
|
||||||
|
|||||||
@@ -27,9 +27,7 @@ fn foo() {}
|
|||||||
|
|
||||||
static BAR: () = unsafe {
|
static BAR: () = unsafe {
|
||||||
*FOO.0.get() = 5;
|
*FOO.0.get() = 5;
|
||||||
// we do not error on the above access, because that is not detectable statically. Instead,
|
//~^ contains unimplemented expression
|
||||||
// const evaluation will error when trying to evaluate it. Due to the error below, we never even
|
|
||||||
// attempt to const evaluate `BAR`, so we don't see the error
|
|
||||||
|
|
||||||
foo();
|
foo();
|
||||||
//~^ 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
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
|
error[E0019]: static contains unimplemented expression type
|
||||||
|
--> $DIR/mod-static-with-const-fn.rs:29:5
|
||||||
|
|
|
||||||
|
LL | *FOO.0.get() = 5;
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
|
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||||
--> $DIR/mod-static-with-const-fn.rs:34:5
|
--> $DIR/mod-static-with-const-fn.rs:32:5
|
||||||
|
|
|
|
||||||
LL | foo();
|
LL | foo();
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0015`.
|
Some errors occurred: E0015, E0019.
|
||||||
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
|||||||
@@ -37,15 +37,13 @@ const fn get_Y_addr() -> &'static u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fn get() -> u32 {
|
const fn get() -> u32 {
|
||||||
let x = 22;
|
let x = 22; //~ ERROR let bindings in constant functions are unstable
|
||||||
//~^ ERROR let bindings in constant functions are unstable
|
//~^ ERROR statements in constant functions
|
||||||
//~| ERROR statements in constant functions are unstable
|
let y = 44; //~ ERROR let bindings in constant functions are unstable
|
||||||
let y = 44;
|
//~^ ERROR statements in constant functions
|
||||||
//~^ ERROR let bindings in constant functions are unstable
|
|
||||||
//~| ERROR statements in constant functions are unstable
|
|
||||||
x + y
|
x + y
|
||||||
//~^ ERROR let bindings in constant functions are unstable
|
//~^ ERROR let bindings in constant functions are unstable
|
||||||
//~| ERROR let bindings in constant functions are unstable
|
//~| ERROR let bindings in constant functions are unstable
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ LL | &Y
|
|||||||
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
||||||
--> $DIR/const-fn-not-safe-for-const.rs:40:13
|
--> $DIR/const-fn-not-safe-for-const.rs:40:13
|
||||||
|
|
|
|
||||||
LL | let x = 22;
|
LL | let x = 22; //~ ERROR let bindings in constant functions are unstable
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
@@ -27,29 +27,29 @@ LL | let x = 22;
|
|||||||
error[E0658]: statements in constant functions are unstable (see issue #48821)
|
error[E0658]: statements in constant functions are unstable (see issue #48821)
|
||||||
--> $DIR/const-fn-not-safe-for-const.rs:40:13
|
--> $DIR/const-fn-not-safe-for-const.rs:40:13
|
||||||
|
|
|
|
||||||
LL | let x = 22;
|
LL | let x = 22; //~ ERROR let bindings in constant functions are unstable
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
||||||
--> $DIR/const-fn-not-safe-for-const.rs:43:13
|
--> $DIR/const-fn-not-safe-for-const.rs:42:13
|
||||||
|
|
|
|
||||||
LL | let y = 44;
|
LL | let y = 44; //~ ERROR let bindings in constant functions are unstable
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
error[E0658]: statements in constant functions are unstable (see issue #48821)
|
error[E0658]: statements in constant functions are unstable (see issue #48821)
|
||||||
--> $DIR/const-fn-not-safe-for-const.rs:43:13
|
--> $DIR/const-fn-not-safe-for-const.rs:42:13
|
||||||
|
|
|
|
||||||
LL | let y = 44;
|
LL | let y = 44; //~ ERROR let bindings in constant functions are unstable
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
||||||
--> $DIR/const-fn-not-safe-for-const.rs:46:5
|
--> $DIR/const-fn-not-safe-for-const.rs:44:5
|
||||||
|
|
|
|
||||||
LL | x + y
|
LL | x + y
|
||||||
| ^
|
| ^
|
||||||
@@ -57,7 +57,7 @@ LL | x + y
|
|||||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
||||||
--> $DIR/const-fn-not-safe-for-const.rs:46:9
|
--> $DIR/const-fn-not-safe-for-const.rs:44:9
|
||||||
|
|
|
|
||||||
LL | x + y
|
LL | x + y
|
||||||
| ^
|
| ^
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ struct S {
|
|||||||
impl S {
|
impl S {
|
||||||
const fn foo(&mut self, x: u32) {
|
const fn foo(&mut self, x: u32) {
|
||||||
self.state = x;
|
self.state = x;
|
||||||
|
//~^ contains unimplemented expression
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
|
error[E0019]: constant function contains unimplemented expression type
|
||||||
|
--> $DIR/const_let_assign3.rs:10:9
|
||||||
|
|
|
||||||
|
LL | self.state = x;
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0017]: references in constants may only refer to immutable values
|
error[E0017]: references in constants may only refer to immutable values
|
||||||
--> $DIR/const_let_assign3.rs:16:5
|
--> $DIR/const_let_assign3.rs:17:5
|
||||||
|
|
|
|
||||||
LL | s.foo(3); //~ ERROR references in constants may only refer to immutable values
|
LL | s.foo(3); //~ ERROR references in constants may only refer to immutable values
|
||||||
| ^ constants require immutable values
|
| ^ constants require immutable values
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0017`.
|
Some errors occurred: E0017, E0019.
|
||||||
|
For more information about an error, try `rustc --explain E0017`.
|
||||||
|
|||||||
470
src/test/ui/consts/const_let_eq.rs
Normal file
470
src/test/ui/consts/const_let_eq.rs
Normal file
@@ -0,0 +1,470 @@
|
|||||||
|
#![feature(const_let, const_fn)]
|
||||||
|
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
struct Foo<T>(T);
|
||||||
|
struct Bar<T> { x: T }
|
||||||
|
struct W(u32);
|
||||||
|
struct A { a: u32 }
|
||||||
|
|
||||||
|
const fn basics((a,): (u32,)) -> u32 {
|
||||||
|
// Deferred assignment:
|
||||||
|
let b: u32;
|
||||||
|
b = a + 1;
|
||||||
|
|
||||||
|
// Immediate assignment:
|
||||||
|
let c: u32 = b + 1;
|
||||||
|
|
||||||
|
// Mutables:
|
||||||
|
let mut d: u32 = c + 1;
|
||||||
|
d = d + 1;
|
||||||
|
// +4 so far.
|
||||||
|
|
||||||
|
// No effect statements work:
|
||||||
|
; ;
|
||||||
|
1;
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [u32; 1] = [0];
|
||||||
|
arr[0] = 1;
|
||||||
|
d = d + arr[0];
|
||||||
|
// +5
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<u32> = Foo(0);
|
||||||
|
let mut bar: Bar<u32> = Bar { x: 0 };
|
||||||
|
foo.0 = 1;
|
||||||
|
bar.x = 1;
|
||||||
|
d = d + foo.0 + bar.x;
|
||||||
|
// +7
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<u32>; 1] = [Foo(0)];
|
||||||
|
arr[0].0 = 1;
|
||||||
|
d = d + arr[0].0;
|
||||||
|
let mut arr: [Bar<u32>; 1] = [Bar { x: 0 }];
|
||||||
|
arr[0].x = 1;
|
||||||
|
d = d + arr[0].x;
|
||||||
|
// +9
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[u32; 1]> = Foo([0]);
|
||||||
|
(arr.0)[0] = 1;
|
||||||
|
d = d + (arr.0)[0];
|
||||||
|
let mut arr: Bar<[u32; 1]> = Bar { x: [0] };
|
||||||
|
arr.x[0] = 1;
|
||||||
|
d = d + arr.x[0];
|
||||||
|
// +11
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn add_assign(W(a): W) -> u32 {
|
||||||
|
// Mutables:
|
||||||
|
let mut d: u32 = a + 1;
|
||||||
|
d += 1;
|
||||||
|
// +2 so far.
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [u32; 1] = [0];
|
||||||
|
arr[0] += 1;
|
||||||
|
d += arr[0];
|
||||||
|
// +3
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<u32> = Foo(0);
|
||||||
|
let mut bar: Bar<u32> = Bar { x: 0 };
|
||||||
|
foo.0 += 1;
|
||||||
|
bar.x += 1;
|
||||||
|
d += foo.0 + bar.x;
|
||||||
|
// +5
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<u32>; 1] = [Foo(0)];
|
||||||
|
arr[0].0 += 1;
|
||||||
|
d += arr[0].0;
|
||||||
|
let mut arr: [Bar<u32>; 1] = [Bar { x: 0 }];
|
||||||
|
arr[0].x += 1;
|
||||||
|
d += arr[0].x;
|
||||||
|
// +7
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[u32; 1]> = Foo([0]);
|
||||||
|
(arr.0)[0] += 1;
|
||||||
|
d += (arr.0)[0];
|
||||||
|
let mut arr: Bar<[u32; 1]> = Bar { x: [0] };
|
||||||
|
arr.x[0] += 1;
|
||||||
|
d += arr.x[0];
|
||||||
|
// +9
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn mul_assign(A { a }: A) -> u32 {
|
||||||
|
// Mutables:
|
||||||
|
let mut d: u32 = a + 1;
|
||||||
|
d *= 2;
|
||||||
|
// 2^1 * (a + 1)
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [u32; 1] = [1];
|
||||||
|
arr[0] *= 2;
|
||||||
|
d *= arr[0];
|
||||||
|
// 2^2 * (a + 1)
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<u32> = Foo(1);
|
||||||
|
let mut bar: Bar<u32> = Bar { x: 1 };
|
||||||
|
foo.0 *= 2;
|
||||||
|
bar.x *= 2;
|
||||||
|
d *= foo.0 + bar.x;
|
||||||
|
// 2^4 * (a + 1)
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<u32>; 1] = [Foo(1)];
|
||||||
|
arr[0].0 *= 2;
|
||||||
|
d *= arr[0].0;
|
||||||
|
let mut arr: [Bar<u32>; 1] = [Bar { x: 1 }];
|
||||||
|
arr[0].x *= 2;
|
||||||
|
d *= arr[0].x;
|
||||||
|
// 2^6 * (a + 1)
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[u32; 1]> = Foo([1]);
|
||||||
|
(arr.0)[0] *= 2;
|
||||||
|
d *= (arr.0)[0];
|
||||||
|
let mut arr: Bar<[u32; 1]> = Bar { x: [1] };
|
||||||
|
arr.x[0] *= 2;
|
||||||
|
d *= arr.x[0];
|
||||||
|
// 2^8 * (a + 1)
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn div_assign(a: [u32; 1]) -> u32 {
|
||||||
|
let a = a[0];
|
||||||
|
// Mutables:
|
||||||
|
let mut d: u32 = 1024 * a;
|
||||||
|
d /= 2;
|
||||||
|
// 512
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [u32; 1] = [4];
|
||||||
|
arr[0] /= 2;
|
||||||
|
d /= arr[0];
|
||||||
|
// 256
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<u32> = Foo(4);
|
||||||
|
let mut bar: Bar<u32> = Bar { x: 4 };
|
||||||
|
foo.0 /= 2;
|
||||||
|
bar.x /= 2;
|
||||||
|
d /= foo.0;
|
||||||
|
d /= bar.x;
|
||||||
|
// 64
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<u32>; 1] = [Foo(4)];
|
||||||
|
arr[0].0 /= 2;
|
||||||
|
d /= arr[0].0;
|
||||||
|
let mut arr: [Bar<u32>; 1] = [Bar { x: 4 }];
|
||||||
|
arr[0].x /= 2;
|
||||||
|
d /= arr[0].x;
|
||||||
|
// 16
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[u32; 1]> = Foo([4]);
|
||||||
|
(arr.0)[0] /= 2;
|
||||||
|
d /= (arr.0)[0];
|
||||||
|
let mut arr: Bar<[u32; 1]> = Bar { x: [4] };
|
||||||
|
arr.x[0] /= 2;
|
||||||
|
d /= arr.x[0];
|
||||||
|
// 4
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn rem_assign(W(a): W) -> u32 {
|
||||||
|
// Mutables:
|
||||||
|
let mut d: u32 = a;
|
||||||
|
d %= 10;
|
||||||
|
d += 10;
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [u32; 1] = [3];
|
||||||
|
arr[0] %= 2;
|
||||||
|
d %= 9 + arr[0];
|
||||||
|
d += 10;
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<u32> = Foo(5);
|
||||||
|
let mut bar: Bar<u32> = Bar { x: 7 };
|
||||||
|
foo.0 %= 2;
|
||||||
|
bar.x %= 2;
|
||||||
|
d %= 8 + foo.0 + bar.x;
|
||||||
|
d += 10;
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<u32>; 1] = [Foo(4)];
|
||||||
|
arr[0].0 %= 3;
|
||||||
|
d %= 9 + arr[0].0;
|
||||||
|
d += 10;
|
||||||
|
let mut arr: [Bar<u32>; 1] = [Bar { x: 7 }];
|
||||||
|
arr[0].x %= 3;
|
||||||
|
d %= 9 + arr[0].x;
|
||||||
|
d += 10;
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[u32; 1]> = Foo([6]);
|
||||||
|
(arr.0)[0] %= 5;
|
||||||
|
d %= 9 + (arr.0)[0];
|
||||||
|
let mut arr: Bar<[u32; 1]> = Bar { x: [11] };
|
||||||
|
arr.x[0] %= 5;
|
||||||
|
d %= 9 + arr.x[0];
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn sub_assign(W(a): W) -> u32 {
|
||||||
|
// Mutables:
|
||||||
|
let mut d: u32 = a;
|
||||||
|
d -= 1;
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [u32; 1] = [2];
|
||||||
|
arr[0] -= 1;
|
||||||
|
d -= arr[0];
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<u32> = Foo(2);
|
||||||
|
let mut bar: Bar<u32> = Bar { x: 2 };
|
||||||
|
foo.0 -= 1;
|
||||||
|
bar.x -= 1;
|
||||||
|
d -= foo.0 + bar.x;
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<u32>; 1] = [Foo(2)];
|
||||||
|
arr[0].0 -= 1;
|
||||||
|
d -= arr[0].0;
|
||||||
|
let mut arr: [Bar<u32>; 1] = [Bar { x: 2 }];
|
||||||
|
arr[0].x -= 1;
|
||||||
|
d -= arr[0].x;
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[u32; 1]> = Foo([2]);
|
||||||
|
(arr.0)[0] -= 1;
|
||||||
|
d -= (arr.0)[0];
|
||||||
|
let mut arr: Bar<[u32; 1]> = Bar { x: [2] };
|
||||||
|
arr.x[0] -= 1;
|
||||||
|
d -= arr.x[0];
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn shl_assign(W(a): W) -> u32 {
|
||||||
|
// Mutables:
|
||||||
|
let mut d: u32 = a;
|
||||||
|
d <<= 1; // 10
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [u32; 1] = [1];
|
||||||
|
arr[0] <<= 1;
|
||||||
|
d <<= arr[0]; // 10 << 2
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<u32> = Foo(1);
|
||||||
|
let mut bar: Bar<u32> = Bar { x: 1 };
|
||||||
|
foo.0 <<= 1;
|
||||||
|
bar.x <<= 1;
|
||||||
|
d <<= foo.0 + bar.x; // 1000 << 4
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<u32>; 1] = [Foo(1)];
|
||||||
|
arr[0].0 <<= 1;
|
||||||
|
d <<= arr[0].0; // 1000_0000 << 2
|
||||||
|
let mut arr: [Bar<u32>; 1] = [Bar { x: 1 }];
|
||||||
|
arr[0].x <<= 1;
|
||||||
|
d <<= arr[0].x; // 1000_0000_00 << 2
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[u32; 1]> = Foo([1]);
|
||||||
|
(arr.0)[0] <<= 1;
|
||||||
|
d <<= (arr.0)[0]; // 1000_0000_0000 << 2
|
||||||
|
let mut arr: Bar<[u32; 1]> = Bar { x: [1] };
|
||||||
|
arr.x[0] <<= 1;
|
||||||
|
d <<= arr.x[0]; // 1000_0000_0000_00 << 2
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn shr_assign(W(a): W) -> u32 {
|
||||||
|
// Mutables:
|
||||||
|
let mut d: u32 = a;
|
||||||
|
d >>= 1; // /= 2
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [u32; 1] = [2];
|
||||||
|
arr[0] >>= 1;
|
||||||
|
d >>= arr[0]; // /= 4
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<u32> = Foo(2);
|
||||||
|
let mut bar: Bar<u32> = Bar { x: 2 };
|
||||||
|
foo.0 >>= 1;
|
||||||
|
bar.x >>= 1;
|
||||||
|
d >>= foo.0 + bar.x; // /= 16
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<u32>; 1] = [Foo(2)];
|
||||||
|
arr[0].0 >>= 1;
|
||||||
|
d >>= arr[0].0; // /= 32
|
||||||
|
let mut arr: [Bar<u32>; 1] = [Bar { x: 2 }];
|
||||||
|
arr[0].x >>= 1;
|
||||||
|
d >>= arr[0].x; // /= 64
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[u32; 1]> = Foo([2]);
|
||||||
|
(arr.0)[0] >>= 1;
|
||||||
|
d >>= (arr.0)[0]; // /= 128
|
||||||
|
let mut arr: Bar<[u32; 1]> = Bar { x: [2] };
|
||||||
|
arr.x[0] >>= 1;
|
||||||
|
d >>= arr.x[0]; // /= 256
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn bit_and_assign(W(a): W) -> u32 {
|
||||||
|
let f = 0b1111_1111_1111_1111;
|
||||||
|
|
||||||
|
// Mutables:
|
||||||
|
let mut d: u32 = a;
|
||||||
|
d &= 0b1111_1111_1111_1110;
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [u32; 1] = [f];
|
||||||
|
arr[0] &= 0b1111_1111_1111_1101;
|
||||||
|
d &= arr[0];
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<u32> = Foo(f);
|
||||||
|
let mut bar: Bar<u32> = Bar { x: f };
|
||||||
|
foo.0 &= 0b1111_1111_1111_0111;
|
||||||
|
bar.x &= 0b1111_1111_1101_1111;
|
||||||
|
d &= foo.0 & bar.x;
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<u32>; 1] = [Foo(f)];
|
||||||
|
arr[0].0 &= 0b1111_1110_1111_1111;
|
||||||
|
d &= arr[0].0;
|
||||||
|
let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
|
||||||
|
arr[0].x &= 0b1111_1101_1111_1111;
|
||||||
|
d &= arr[0].x;
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[u32; 1]> = Foo([f]);
|
||||||
|
(arr.0)[0] &= 0b1011_1111_1111_1111;
|
||||||
|
d &= (arr.0)[0];
|
||||||
|
let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
|
||||||
|
arr.x[0] &= 0b0111_1111_1111_1111;
|
||||||
|
d &= arr.x[0];
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn bit_or_assign(W(a): W) -> u32 {
|
||||||
|
let f = 0b0000_0000_0000_0000;
|
||||||
|
|
||||||
|
// Mutables:
|
||||||
|
let mut d: u32 = a;
|
||||||
|
d |= 0b0000_0000_0000_0001;
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [u32; 1] = [f];
|
||||||
|
arr[0] |= 0b0000_0000_0000_1001;
|
||||||
|
d |= arr[0];
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<u32> = Foo(f);
|
||||||
|
let mut bar: Bar<u32> = Bar { x: f };
|
||||||
|
foo.0 |= 0b0000_0000_0001_0000;
|
||||||
|
bar.x |= 0b0000_0000_0100_0000;
|
||||||
|
d |= foo.0 | bar.x;
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<u32>; 1] = [Foo(f)];
|
||||||
|
arr[0].0 |= 0b0000_0001_0000_0000;
|
||||||
|
d |= arr[0].0;
|
||||||
|
let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
|
||||||
|
arr[0].x |= 0b0000_0010_0000_0000;
|
||||||
|
d |= arr[0].x;
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[u32; 1]> = Foo([f]);
|
||||||
|
(arr.0)[0] |= 0b1000_0000_0000_0000;
|
||||||
|
d |= (arr.0)[0]; // /= 128
|
||||||
|
let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
|
||||||
|
arr.x[0] |= 0b1100_0000_0000_0000;
|
||||||
|
d |= arr.x[0]; // /= 256
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn bit_xor_assign(W(a): W) -> u32 {
|
||||||
|
let f = 0b0000_0000_0000_0000;
|
||||||
|
|
||||||
|
// Mutables:
|
||||||
|
let mut d: u32 = a;
|
||||||
|
d ^= 0b0000_0000_0000_0001;
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [u32; 1] = [f];
|
||||||
|
arr[0] ^= 0b0000_0000_0000_0010;
|
||||||
|
d ^= arr[0];
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<u32> = Foo(f);
|
||||||
|
let mut bar: Bar<u32> = Bar { x: f };
|
||||||
|
foo.0 ^= 0b0000_0000_0001_0000;
|
||||||
|
bar.x ^= 0b0000_0000_1000_0000;
|
||||||
|
d ^= foo.0 ^ bar.x;
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<u32>; 1] = [Foo(f)];
|
||||||
|
arr[0].0 ^= 0b0000_0001_0000_0000;
|
||||||
|
d ^= arr[0].0;
|
||||||
|
let mut arr: [Bar<u32>; 1] = [Bar { x: f }];
|
||||||
|
arr[0].x ^= 0b0000_0010_0000_0000;
|
||||||
|
d ^= arr[0].x;
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[u32; 1]> = Foo([f]);
|
||||||
|
(arr.0)[0] ^= 0b0100_0000_0000_0000;
|
||||||
|
d ^= (arr.0)[0];
|
||||||
|
let mut arr: Bar<[u32; 1]> = Bar { x: [f] };
|
||||||
|
arr.x[0] ^= 0b1000_0000_0000_0000;
|
||||||
|
d ^= arr.x[0];
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! test {
|
||||||
|
($c:ident, $e:expr, $r:expr) => {
|
||||||
|
const $c: u32 = $e;
|
||||||
|
assert_eq!($c, $r);
|
||||||
|
assert_eq!($e, $r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test!(BASICS, basics((2,)), 13);
|
||||||
|
test!(ADD, add_assign(W(1)), 10);
|
||||||
|
test!(MUL, mul_assign(A { a: 0 }), 256);
|
||||||
|
test!(DIV, div_assign([1]), 4);
|
||||||
|
test!(REM, rem_assign(W(5)), 5);
|
||||||
|
test!(SUB, sub_assign(W(8)), 0);
|
||||||
|
test!(SHL, shl_assign(W(1)), 0b1000_0000_0000_0000);
|
||||||
|
test!(SHR, shr_assign(W(256)), 1);
|
||||||
|
test!(AND, bit_and_assign(W(0b1011_1111_1111_1111_1111)), 0b0011_1100_1101_0100);
|
||||||
|
test!(OR, bit_or_assign(W(0b1011_0000_0000_0000)), 0b1111_0011_0101_1001);
|
||||||
|
test!(XOR, bit_xor_assign(W(0b0000_0000_0000_0000)), 0b1100_0011_1001_0011);
|
||||||
|
}
|
||||||
279
src/test/ui/consts/const_let_eq_float.rs
Normal file
279
src/test/ui/consts/const_let_eq_float.rs
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
// compile-pass
|
||||||
|
|
||||||
|
#![feature(const_let, const_fn)]
|
||||||
|
|
||||||
|
struct Foo<T>(T);
|
||||||
|
struct Bar<T> { x: T }
|
||||||
|
struct W(f32);
|
||||||
|
struct A { a: f32 }
|
||||||
|
|
||||||
|
const fn basics((a,): (f32,)) -> f32 {
|
||||||
|
// Deferred assignment:
|
||||||
|
let b: f32;
|
||||||
|
b = a + 1.0;
|
||||||
|
|
||||||
|
// Immediate assignment:
|
||||||
|
let c: f32 = b + 1.0;
|
||||||
|
|
||||||
|
// Mutables:
|
||||||
|
let mut d: f32 = c + 1.0;
|
||||||
|
d = d + 1.0;
|
||||||
|
// +4 so far.
|
||||||
|
|
||||||
|
// No effect statements work:
|
||||||
|
; ;
|
||||||
|
1;
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [f32; 1] = [0.0];
|
||||||
|
arr[0] = 1.0;
|
||||||
|
d = d + arr[0];
|
||||||
|
// +5
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<f32> = Foo(0.0);
|
||||||
|
let mut bar: Bar<f32> = Bar { x: 0.0 };
|
||||||
|
foo.0 = 1.0;
|
||||||
|
bar.x = 1.0;
|
||||||
|
d = d + foo.0 + bar.x;
|
||||||
|
// +7
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<f32>; 1] = [Foo(0.0)];
|
||||||
|
arr[0].0 = 1.0;
|
||||||
|
d = d + arr[0].0;
|
||||||
|
let mut arr: [Bar<f32>; 1] = [Bar { x: 0.0 }];
|
||||||
|
arr[0].x = 1.0;
|
||||||
|
d = d + arr[0].x;
|
||||||
|
// +9
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[f32; 1]> = Foo([0.0]);
|
||||||
|
(arr.0)[0] = 1.0;
|
||||||
|
d = d + (arr.0)[0];
|
||||||
|
let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] };
|
||||||
|
arr.x[0] = 1.0;
|
||||||
|
d = d + arr.x[0];
|
||||||
|
// +11
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn add_assign(W(a): W) -> f32 {
|
||||||
|
// Mutables:
|
||||||
|
let mut d: f32 = a + 1.0;
|
||||||
|
d += 1.0;
|
||||||
|
// +2 so far.
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [f32; 1] = [0.0];
|
||||||
|
arr[0] += 1.0;
|
||||||
|
d += arr[0];
|
||||||
|
// +3
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<f32> = Foo(0.0);
|
||||||
|
let mut bar: Bar<f32> = Bar { x: 0.0 };
|
||||||
|
foo.0 += 1.0;
|
||||||
|
bar.x += 1.0;
|
||||||
|
d += foo.0 + bar.x;
|
||||||
|
// +5
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<f32>; 1] = [Foo(0.0)];
|
||||||
|
arr[0].0 += 1.0;
|
||||||
|
d += arr[0].0;
|
||||||
|
let mut arr: [Bar<f32>; 1] = [Bar { x: 0.0 }];
|
||||||
|
arr[0].x += 1.0;
|
||||||
|
d += arr[0].x;
|
||||||
|
// +7
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[f32; 1]> = Foo([0.0]);
|
||||||
|
(arr.0)[0] += 1.0;
|
||||||
|
d += (arr.0)[0];
|
||||||
|
let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] };
|
||||||
|
arr.x[0] += 1.0;
|
||||||
|
d += arr.x[0];
|
||||||
|
// +9
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn mul_assign(A { a }: A) -> f32 {
|
||||||
|
// Mutables:
|
||||||
|
let mut d: f32 = a + 1.0;
|
||||||
|
d *= 2.0;
|
||||||
|
// 2^1 * (a + 1)
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [f32; 1] = [1.0];
|
||||||
|
arr[0] *= 2.0;
|
||||||
|
d *= arr[0];
|
||||||
|
// 2^2 * (a + 1)
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<f32> = Foo(1.0);
|
||||||
|
let mut bar: Bar<f32> = Bar { x: 1.0 };
|
||||||
|
foo.0 *= 2.0;
|
||||||
|
bar.x *= 2.0;
|
||||||
|
d *= foo.0 + bar.x;
|
||||||
|
// 2^4 * (a + 1)
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<f32>; 1] = [Foo(1.0)];
|
||||||
|
arr[0].0 *= 2.0;
|
||||||
|
d *= arr[0].0;
|
||||||
|
let mut arr: [Bar<f32>; 1] = [Bar { x: 1.0 }];
|
||||||
|
arr[0].x *= 2.0;
|
||||||
|
d *= arr[0].x;
|
||||||
|
// 2^6 * (a + 1)
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[f32; 1]> = Foo([1.0]);
|
||||||
|
(arr.0)[0] *= 2.0;
|
||||||
|
d *= (arr.0)[0];
|
||||||
|
let mut arr: Bar<[f32; 1]> = Bar { x: [1.0] };
|
||||||
|
arr.x[0] *= 2.0;
|
||||||
|
d *= arr.x[0];
|
||||||
|
// 2^8 * (a + 1)
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn div_assign(a: [f32; 1]) -> f32 {
|
||||||
|
let a = a[0];
|
||||||
|
// Mutables:
|
||||||
|
let mut d: f32 = 1024.0 * a;
|
||||||
|
d /= 2.0;
|
||||||
|
// 512
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [f32; 1] = [4.0];
|
||||||
|
arr[0] /= 2.0;
|
||||||
|
d /= arr[0];
|
||||||
|
// 256
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<f32> = Foo(4.0);
|
||||||
|
let mut bar: Bar<f32> = Bar { x: 4.0 };
|
||||||
|
foo.0 /= 2.0;
|
||||||
|
bar.x /= 2.0;
|
||||||
|
d /= foo.0;
|
||||||
|
d /= bar.x;
|
||||||
|
// 64
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<f32>; 1] = [Foo(4.0)];
|
||||||
|
arr[0].0 /= 2.0;
|
||||||
|
d /= arr[0].0;
|
||||||
|
let mut arr: [Bar<f32>; 1] = [Bar { x: 4.0 }];
|
||||||
|
arr[0].x /= 2.0;
|
||||||
|
d /= arr[0].x;
|
||||||
|
// 16
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[f32; 1]> = Foo([4.0]);
|
||||||
|
(arr.0)[0] /= 2.0;
|
||||||
|
d /= (arr.0)[0];
|
||||||
|
let mut arr: Bar<[f32; 1]> = Bar { x: [4.0] };
|
||||||
|
arr.x[0] /= 2.0;
|
||||||
|
d /= arr.x[0];
|
||||||
|
// 4
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn rem_assign(W(a): W) -> f32 {
|
||||||
|
// Mutables:
|
||||||
|
let mut d: f32 = a;
|
||||||
|
d %= 10.0;
|
||||||
|
d += 10.0;
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [f32; 1] = [3.0];
|
||||||
|
arr[0] %= 2.0;
|
||||||
|
d %= 9.0 + arr[0];
|
||||||
|
d += 10.0;
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<f32> = Foo(5.0);
|
||||||
|
let mut bar: Bar<f32> = Bar { x: 7.0 };
|
||||||
|
foo.0 %= 2.0;
|
||||||
|
bar.x %= 2.0;
|
||||||
|
d %= 8.0 + foo.0 + bar.x;
|
||||||
|
d += 10.0;
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<f32>; 1] = [Foo(4.0)];
|
||||||
|
arr[0].0 %= 3.0;
|
||||||
|
d %= 9.0 + arr[0].0;
|
||||||
|
d += 10.0;
|
||||||
|
let mut arr: [Bar<f32>; 1] = [Bar { x: 7.0 }];
|
||||||
|
arr[0].x %= 3.0;
|
||||||
|
d %= 9.0 + arr[0].x;
|
||||||
|
d += 10.0;
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[f32; 1]> = Foo([6.0]);
|
||||||
|
(arr.0)[0] %= 5.0;
|
||||||
|
d %= 9.0 + (arr.0)[0];
|
||||||
|
let mut arr: Bar<[f32; 1]> = Bar { x: [11.0] };
|
||||||
|
arr.x[0] %= 5.0;
|
||||||
|
d %= 9.0 + arr.x[0];
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn sub_assign(W(a): W) -> f32 {
|
||||||
|
// Mutables:
|
||||||
|
let mut d: f32 = a;
|
||||||
|
d -= 1.0;
|
||||||
|
|
||||||
|
// Array projection
|
||||||
|
let mut arr: [f32; 1] = [2.0];
|
||||||
|
arr[0] -= 1.0;
|
||||||
|
d -= arr[0];
|
||||||
|
|
||||||
|
// Field projection:
|
||||||
|
let mut foo: Foo<f32> = Foo(2.0);
|
||||||
|
let mut bar: Bar<f32> = Bar { x: 2.0 };
|
||||||
|
foo.0 -= 1.0;
|
||||||
|
bar.x -= 1.0;
|
||||||
|
d -= foo.0 + bar.x;
|
||||||
|
|
||||||
|
// Array + Field projection:
|
||||||
|
let mut arr: [Foo<f32>; 1] = [Foo(2.0)];
|
||||||
|
arr[0].0 -= 1.0;
|
||||||
|
d -= arr[0].0;
|
||||||
|
let mut arr: [Bar<f32>; 1] = [Bar { x: 2.0 }];
|
||||||
|
arr[0].x -= 1.0;
|
||||||
|
d -= arr[0].x;
|
||||||
|
|
||||||
|
// Field + Array projection:
|
||||||
|
let mut arr: Foo<[f32; 1]> = Foo([2.0]);
|
||||||
|
(arr.0)[0] -= 1.0;
|
||||||
|
d -= (arr.0)[0];
|
||||||
|
let mut arr: Bar<[f32; 1]> = Bar { x: [2.0] };
|
||||||
|
arr.x[0] -= 1.0;
|
||||||
|
d -= arr.x[0];
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! test {
|
||||||
|
($c:ident, $e:expr, $r:expr) => {
|
||||||
|
const $c: f32 = $e;
|
||||||
|
assert_eq!($c, $r);
|
||||||
|
assert_eq!($e, $r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test!(BASICS, basics((2.0,)), 13.0);
|
||||||
|
test!(ADD, add_assign(W(1.0)), 10.0);
|
||||||
|
test!(MUL, mul_assign(A { a: 0.0 }), 256.0);
|
||||||
|
test!(DIV, div_assign([1.0]), 4.0);
|
||||||
|
test!(REM, rem_assign(W(5.0)), 5.0);
|
||||||
|
test!(SUB, sub_assign(W(8.0)), 0.0);
|
||||||
|
}
|
||||||
16
src/test/ui/consts/const_short_circuit.rs
Normal file
16
src/test/ui/consts/const_short_circuit.rs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#![feature(underscore_const_names, const_let)]
|
||||||
|
|
||||||
|
const _: bool = false && false;
|
||||||
|
const _: bool = true && false;
|
||||||
|
const _: bool = {
|
||||||
|
let mut x = true && false;
|
||||||
|
//~^ ERROR new features like let bindings are not permitted
|
||||||
|
x
|
||||||
|
};
|
||||||
|
const _: bool = {
|
||||||
|
let x = true && false;
|
||||||
|
//~^ ERROR new features like let bindings are not permitted
|
||||||
|
x
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
26
src/test/ui/consts/const_short_circuit.stderr
Normal file
26
src/test/ui/consts/const_short_circuit.stderr
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
error: new features like let bindings are not permitted in constants which also use short circuiting operators
|
||||||
|
--> $DIR/const_short_circuit.rs:6:9
|
||||||
|
|
|
||||||
|
LL | let mut x = true && false;
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
note: use of `&&` operator here does not actually short circuit due to the const evaluator presently not being able to do control flow. See https://github.com/rust-lang/rust/issues/49146 for more information.
|
||||||
|
--> $DIR/const_short_circuit.rs:6:22
|
||||||
|
|
|
||||||
|
LL | let mut x = true && false;
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: new features like let bindings are not permitted in constants which also use short circuiting operators
|
||||||
|
--> $DIR/const_short_circuit.rs:11:9
|
||||||
|
|
|
||||||
|
LL | let x = true && false;
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
note: use of `&&` operator here does not actually short circuit due to the const evaluator presently not being able to do control flow. See https://github.com/rust-lang/rust/issues/49146 for more information.
|
||||||
|
--> $DIR/const_short_circuit.rs:11:18
|
||||||
|
|
|
||||||
|
LL | let x = true && false;
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
|
|||||||
error: local variables in const fn are unstable
|
error: local variables in const fn are unstable
|
||||||
--> $DIR/min_const_fn.rs:109:34
|
--> $DIR/min_const_fn.rs:109:34
|
||||||
|
|
|
|
||||||
LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
|
LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: `if`, `match`, `&&` and `||` are not stable in const fn
|
error: `if`, `match`, `&&` and `||` are not stable in const fn
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ const fn foo30_2(x: *mut u32) -> usize { x as usize }
|
|||||||
const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
|
const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
|
||||||
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
|
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
|
||||||
const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
|
const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
|
||||||
const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
|
const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
|
||||||
const fn foo36(a: bool, b: bool) -> bool { a && b }
|
const fn foo36(a: bool, b: bool) -> bool { a && b }
|
||||||
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
|
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
|
||||||
const fn foo37(a: bool, b: bool) -> bool { a || b }
|
const fn foo37(a: bool, b: bool) -> bool { a || b }
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
|
|||||||
error: local variables in const fn are unstable
|
error: local variables in const fn are unstable
|
||||||
--> $DIR/min_const_fn.rs:109:34
|
--> $DIR/min_const_fn.rs:109:34
|
||||||
|
|
|
|
||||||
LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
|
LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: `if`, `match`, `&&` and `||` are not stable in const fn
|
error: `if`, `match`, `&&` and `||` are not stable in const fn
|
||||||
|
|||||||
17
src/test/ui/consts/min_const_fn/mutable_borrow.rs
Normal file
17
src/test/ui/consts/min_const_fn/mutable_borrow.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
const fn mutable_ref_in_const() -> u8 {
|
||||||
|
let mut a = 0; //~ ERROR local variables in const fn
|
||||||
|
let b = &mut a;
|
||||||
|
*b
|
||||||
|
}
|
||||||
|
|
||||||
|
struct X;
|
||||||
|
|
||||||
|
impl X {
|
||||||
|
const fn inherent_mutable_ref_in_const() -> u8 {
|
||||||
|
let mut a = 0; //~ ERROR local variables in const fn
|
||||||
|
let b = &mut a;
|
||||||
|
*b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
14
src/test/ui/consts/min_const_fn/mutable_borrow.stderr
Normal file
14
src/test/ui/consts/min_const_fn/mutable_borrow.stderr
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
error: local variables in const fn are unstable
|
||||||
|
--> $DIR/mutable_borrow.rs:2:9
|
||||||
|
|
|
||||||
|
LL | let mut a = 0; //~ ERROR local variables in const fn
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: local variables in const fn are unstable
|
||||||
|
--> $DIR/mutable_borrow.rs:11:13
|
||||||
|
|
|
||||||
|
LL | let mut a = 0; //~ ERROR local variables in const fn
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
@@ -7,6 +7,7 @@ const FOO: &u32 = {
|
|||||||
{
|
{
|
||||||
let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
|
let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
|
||||||
unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
|
unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
|
||||||
|
//~^ contains unimplemented expression
|
||||||
}
|
}
|
||||||
&{a}
|
&{a}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,12 @@ error[E0017]: references in constants may only refer to immutable values
|
|||||||
LL | let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
|
LL | let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
|
||||||
| ^^^^^^ constants require immutable values
|
| ^^^^^^ constants require immutable values
|
||||||
|
|
||||||
|
error[E0019]: constant contains unimplemented expression type
|
||||||
|
--> $DIR/projection_qualif.rs:9:18
|
||||||
|
|
|
||||||
|
LL | unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911)
|
error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911)
|
||||||
--> $DIR/projection_qualif.rs:9:18
|
--> $DIR/projection_qualif.rs:9:18
|
||||||
|
|
|
|
||||||
@@ -12,7 +18,7 @@ LL | unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constant
|
|||||||
|
|
|
|
||||||
= help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
|
= help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
Some errors occurred: E0017, E0658.
|
Some errors occurred: E0017, E0019, E0658.
|
||||||
For more information about an error, try `rustc --explain E0017`.
|
For more information about an error, try `rustc --explain E0017`.
|
||||||
|
|||||||
@@ -2,6 +2,14 @@ enum Foo {
|
|||||||
Prob,
|
Prob,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FOO: u32 = match Foo::Prob {
|
||||||
|
Foo::Prob => 42, //~ ERROR unimplemented expression type
|
||||||
|
};
|
||||||
|
|
||||||
|
const BAR: u32 = match Foo::Prob {
|
||||||
|
x => 42, //~ ERROR unimplemented expression type
|
||||||
|
};
|
||||||
|
|
||||||
impl Foo {
|
impl Foo {
|
||||||
pub const fn as_val(&self) -> u8 {
|
pub const fn as_val(&self) -> u8 {
|
||||||
use self::Foo::*;
|
use self::Foo::*;
|
||||||
|
|||||||
@@ -1,8 +1,21 @@
|
|||||||
|
error[E0019]: constant contains unimplemented expression type
|
||||||
|
--> $DIR/single_variant_match_ice.rs:6:5
|
||||||
|
|
|
||||||
|
LL | Foo::Prob => 42, //~ ERROR unimplemented expression type
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0019]: constant contains unimplemented expression type
|
||||||
|
--> $DIR/single_variant_match_ice.rs:10:5
|
||||||
|
|
|
||||||
|
LL | x => 42, //~ ERROR unimplemented expression type
|
||||||
|
| ^
|
||||||
|
|
||||||
error: `if`, `match`, `&&` and `||` are not stable in const fn
|
error: `if`, `match`, `&&` and `||` are not stable in const fn
|
||||||
--> $DIR/single_variant_match_ice.rs:10:13
|
--> $DIR/single_variant_match_ice.rs:18:13
|
||||||
|
|
|
|
||||||
LL | Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
|
LL | Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0019`.
|
||||||
|
|||||||
@@ -10,13 +10,22 @@
|
|||||||
|
|
||||||
// Test use of const let without feature gate.
|
// Test use of const let without feature gate.
|
||||||
|
|
||||||
#![feature(const_fn)]
|
const FOO: usize = {
|
||||||
|
//~^ ERROR statements in constants are unstable
|
||||||
const fn foo() -> usize {
|
//~| ERROR: let bindings in constants are unstable
|
||||||
let x = 42;
|
let x = 42;
|
||||||
//~^ ERROR statements in constant functions are unstable
|
//~^ ERROR statements in constants are unstable
|
||||||
//~| ERROR: let bindings in constant functions are unstable
|
//~| ERROR: let bindings in constants are unstable
|
||||||
42
|
42
|
||||||
}
|
};
|
||||||
|
|
||||||
|
static BAR: usize = {
|
||||||
|
//~^ ERROR statements in statics are unstable
|
||||||
|
//~| ERROR: let bindings in statics are unstable
|
||||||
|
let x = 42;
|
||||||
|
//~^ ERROR statements in statics are unstable
|
||||||
|
//~| ERROR: let bindings in statics are unstable
|
||||||
|
42
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
error[E0658]: let bindings in constants are unstable (see issue #48821)
|
||||||
--> $DIR/feature-gate-const_let.rs:16:13
|
--> $DIR/feature-gate-const_let.rs:16:13
|
||||||
|
|
|
|
||||||
LL | let x = 42;
|
LL | let x = 42;
|
||||||
@@ -6,7 +6,7 @@ LL | let x = 42;
|
|||||||
|
|
|
|
||||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
error[E0658]: statements in constant functions are unstable (see issue #48821)
|
error[E0658]: statements in constants are unstable (see issue #48821)
|
||||||
--> $DIR/feature-gate-const_let.rs:16:13
|
--> $DIR/feature-gate-const_let.rs:16:13
|
||||||
|
|
|
|
||||||
LL | let x = 42;
|
LL | let x = 42;
|
||||||
@@ -14,6 +14,78 @@ LL | let x = 42;
|
|||||||
|
|
|
|
||||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error[E0658]: let bindings in constants are unstable (see issue #48821)
|
||||||
|
--> $DIR/feature-gate-const_let.rs:13:1
|
||||||
|
|
|
||||||
|
LL | / const FOO: usize = {
|
||||||
|
LL | | //~^ ERROR statements in constants are unstable
|
||||||
|
LL | | //~| ERROR: let bindings in constants are unstable
|
||||||
|
LL | | let x = 42;
|
||||||
|
... |
|
||||||
|
LL | | 42
|
||||||
|
LL | | };
|
||||||
|
| |__^
|
||||||
|
|
|
||||||
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0658]: statements in constants are unstable (see issue #48821)
|
||||||
|
--> $DIR/feature-gate-const_let.rs:13:1
|
||||||
|
|
|
||||||
|
LL | / const FOO: usize = {
|
||||||
|
LL | | //~^ ERROR statements in constants are unstable
|
||||||
|
LL | | //~| ERROR: let bindings in constants are unstable
|
||||||
|
LL | | let x = 42;
|
||||||
|
... |
|
||||||
|
LL | | 42
|
||||||
|
LL | | };
|
||||||
|
| |__^
|
||||||
|
|
|
||||||
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0658]: let bindings in statics are unstable (see issue #48821)
|
||||||
|
--> $DIR/feature-gate-const_let.rs:25:13
|
||||||
|
|
|
||||||
|
LL | let x = 42;
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0658]: statements in statics are unstable (see issue #48821)
|
||||||
|
--> $DIR/feature-gate-const_let.rs:25:13
|
||||||
|
|
|
||||||
|
LL | let x = 42;
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0658]: let bindings in statics are unstable (see issue #48821)
|
||||||
|
--> $DIR/feature-gate-const_let.rs:22:1
|
||||||
|
|
|
||||||
|
LL | / static BAR: usize = {
|
||||||
|
LL | | //~^ ERROR statements in statics are unstable
|
||||||
|
LL | | //~| ERROR: let bindings in statics are unstable
|
||||||
|
LL | | let x = 42;
|
||||||
|
... |
|
||||||
|
LL | | 42
|
||||||
|
LL | | };
|
||||||
|
| |__^
|
||||||
|
|
|
||||||
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0658]: statements in statics are unstable (see issue #48821)
|
||||||
|
--> $DIR/feature-gate-const_let.rs:22:1
|
||||||
|
|
|
||||||
|
LL | / static BAR: usize = {
|
||||||
|
LL | | //~^ ERROR statements in statics are unstable
|
||||||
|
LL | | //~| ERROR: let bindings in statics are unstable
|
||||||
|
LL | | let x = 42;
|
||||||
|
... |
|
||||||
|
LL | | 42
|
||||||
|
LL | | };
|
||||||
|
| |__^
|
||||||
|
|
|
||||||
|
= help: add #![feature(const_let)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
|||||||
@@ -8,15 +8,9 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(const_fn)]
|
|
||||||
|
|
||||||
const fn x() {
|
const fn x() {
|
||||||
let t = true;
|
let t = true; //~ ERROR local variables in const fn
|
||||||
//~^ ERROR let bindings in constant functions are unstable
|
|
||||||
//~| ERROR statements in constant functions are unstable
|
|
||||||
let x = || t;
|
let x = || t;
|
||||||
//~^ ERROR let bindings in constant functions are unstable
|
|
||||||
//~| ERROR statements in constant functions are unstable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -1,35 +1,8 @@
|
|||||||
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
error: local variables in const fn are unstable
|
||||||
--> $DIR/issue-37550.rs:14:13
|
--> $DIR/issue-37550.rs:12:9
|
||||||
|
|
|
|
||||||
LL | let t = true;
|
LL | let t = true; //~ ERROR local variables in const fn
|
||||||
| ^^^^
|
| ^
|
||||||
|
|
|
||||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: statements in constant functions are unstable (see issue #48821)
|
error: aborting due to previous error
|
||||||
--> $DIR/issue-37550.rs:14:13
|
|
||||||
|
|
|
||||||
LL | let t = true;
|
|
||||||
| ^^^^
|
|
||||||
|
|
|
||||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
|
|
||||||
--> $DIR/issue-37550.rs:17:13
|
|
||||||
|
|
|
||||||
LL | let x = || t;
|
|
||||||
| ^^^^
|
|
||||||
|
|
|
||||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: statements in constant functions are unstable (see issue #48821)
|
|
||||||
--> $DIR/issue-37550.rs:17:13
|
|
||||||
|
|
|
||||||
LL | let x = || t;
|
|
||||||
| ^^^^
|
|
||||||
|
|
|
||||||
= help: add #![feature(const_let)] to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user