rustc_const_eval: demand that the MIR qualify_consts ran on each evaluated body.
This commit is contained in:
parent
e7a48821c0
commit
d9f0a949fd
@ -361,6 +361,11 @@ define_maps! { <'tcx>
|
||||
/// (in the `RefCell` sense) to prevent accidental mutation.
|
||||
pub mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>>,
|
||||
|
||||
/// Maps DefId's that have an associated Mir to the result
|
||||
/// of the MIR qualify_consts pass. The actual meaning of
|
||||
/// the value isn't known except to the pass itself.
|
||||
pub mir_const_qualif: Mir(DefId) -> u8,
|
||||
|
||||
/// Records the type of each closure. The def ID is the ID of the
|
||||
/// expression defining the closure.
|
||||
pub closure_kind: ItemSignature(DefId) -> ty::ClosureKind,
|
||||
|
@ -27,7 +27,7 @@ use rustc::util::nodemap::DefIdMap;
|
||||
use graphviz::IntoCow;
|
||||
use syntax::ast;
|
||||
use rustc::hir::{self, Expr};
|
||||
use syntax_pos::Span;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering;
|
||||
@ -228,6 +228,7 @@ pub struct ConstContext<'a, 'tcx: 'a> {
|
||||
impl<'a, 'tcx> ConstContext<'a, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self {
|
||||
let def_id = tcx.hir.body_owner_def_id(body);
|
||||
ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id);
|
||||
ConstContext::with_tables(tcx, tcx.item_tables(def_id))
|
||||
}
|
||||
|
||||
|
@ -872,7 +872,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
let index = stability::Index::new(&hir_map);
|
||||
|
||||
let mut local_providers = ty::maps::Providers::default();
|
||||
mir::mir_map::provide(&mut local_providers);
|
||||
mir::provide(&mut local_providers);
|
||||
typeck::provide(&mut local_providers);
|
||||
|
||||
let mut extern_providers = ty::maps::Providers::default();
|
||||
@ -958,8 +958,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
// in stage 4 below.
|
||||
passes.push_hook(box mir::transform::dump_mir::DumpMir);
|
||||
passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("initial"));
|
||||
passes.push_pass(
|
||||
box mir::transform::qualify_consts::QualifyAndPromoteConstants::default());
|
||||
passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
|
||||
passes.push_pass(box mir::transform::type_check::TypeckMir);
|
||||
passes.push_pass(
|
||||
box mir::transform::simplify_branches::SimplifyBranches::new("initial"));
|
||||
|
@ -101,6 +101,7 @@ provide! { <'tcx> tcx, def_id, cdata
|
||||
|
||||
mir
|
||||
}
|
||||
mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
|
||||
typeck_tables => { cdata.item_body_tables(def_id.index, tcx) }
|
||||
closure_kind => { cdata.closure_kind(def_id.index) }
|
||||
closure_type => { cdata.closure_ty(def_id.index, tcx) }
|
||||
|
@ -411,8 +411,8 @@ impl<'a, 'tcx> MetadataBlob {
|
||||
impl<'tcx> EntryKind<'tcx> {
|
||||
fn to_def(&self, did: DefId) -> Option<Def> {
|
||||
Some(match *self {
|
||||
EntryKind::Const => Def::Const(did),
|
||||
EntryKind::AssociatedConst(_) => Def::AssociatedConst(did),
|
||||
EntryKind::Const(_) => Def::Const(did),
|
||||
EntryKind::AssociatedConst(..) => Def::AssociatedConst(did),
|
||||
EntryKind::ImmStatic |
|
||||
EntryKind::ForeignImmStatic => Def::Static(did, false),
|
||||
EntryKind::MutStatic |
|
||||
@ -825,6 +825,17 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mir_const_qualif(&self, id: DefIndex) -> u8 {
|
||||
match self.entry(id).kind {
|
||||
EntryKind::Const(qualif) |
|
||||
EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif) |
|
||||
EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif) => {
|
||||
qualif
|
||||
}
|
||||
_ => bug!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem {
|
||||
let item = self.entry(id);
|
||||
let def_key = self.def_key(id);
|
||||
@ -832,7 +843,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
let name = def_key.disambiguated_data.data.get_opt_name().unwrap();
|
||||
|
||||
let (kind, container, has_self) = match item.kind {
|
||||
EntryKind::AssociatedConst(container) => {
|
||||
EntryKind::AssociatedConst(container, _) => {
|
||||
(ty::AssociatedKind::Const, container, false)
|
||||
}
|
||||
EntryKind::Method(data) => {
|
||||
|
@ -457,7 +457,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
};
|
||||
|
||||
let kind = match trait_item.kind {
|
||||
ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
|
||||
ty::AssociatedKind::Const => {
|
||||
EntryKind::AssociatedConst(container, 0)
|
||||
}
|
||||
ty::AssociatedKind::Method => {
|
||||
let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node {
|
||||
let arg_names = match *m {
|
||||
@ -533,7 +535,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
};
|
||||
|
||||
let kind = match impl_item.kind {
|
||||
ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
|
||||
ty::AssociatedKind::Const => {
|
||||
EntryKind::AssociatedConst(container,
|
||||
ty::queries::mir_const_qualif::get(self.tcx, ast_item.span, def_id))
|
||||
}
|
||||
ty::AssociatedKind::Method => {
|
||||
let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
|
||||
FnData {
|
||||
@ -637,7 +642,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
let kind = match item.node {
|
||||
hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic,
|
||||
hir::ItemStatic(_, hir::MutImmutable, _) => EntryKind::ImmStatic,
|
||||
hir::ItemConst(..) => EntryKind::Const,
|
||||
hir::ItemConst(..) => {
|
||||
EntryKind::Const(ty::queries::mir_const_qualif::get(tcx, item.span, def_id))
|
||||
}
|
||||
hir::ItemFn(_, _, constness, .., body) => {
|
||||
let data = FnData {
|
||||
constness: constness,
|
||||
|
@ -221,7 +221,7 @@ pub struct Entry<'tcx> {
|
||||
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
pub enum EntryKind<'tcx> {
|
||||
Const,
|
||||
Const(u8),
|
||||
ImmStatic,
|
||||
MutStatic,
|
||||
ForeignImmStatic,
|
||||
@ -243,7 +243,7 @@ pub enum EntryKind<'tcx> {
|
||||
DefaultImpl(Lazy<ImplData<'tcx>>),
|
||||
Method(Lazy<MethodData>),
|
||||
AssociatedType(AssociatedContainer),
|
||||
AssociatedConst(AssociatedContainer),
|
||||
AssociatedConst(AssociatedContainer, u8),
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
|
@ -53,3 +53,9 @@ pub mod mir_map;
|
||||
pub mod pretty;
|
||||
pub mod transform;
|
||||
|
||||
use rustc::ty::maps::Providers;
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
mir_map::provide(providers);
|
||||
transform::qualify_consts::provide(providers);
|
||||
}
|
||||
|
@ -16,24 +16,24 @@
|
||||
|
||||
use rustc_data_structures::bitvec::BitVector;
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::hir;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::map::blocks::FnLikeNode;
|
||||
use rustc::traits::{self, Reveal};
|
||||
use rustc::ty::{self, TyCtxt, Ty};
|
||||
use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
|
||||
use rustc::ty::cast::CastTy;
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::traversal::ReversePostorder;
|
||||
use rustc::mir::transform::{Pass, MirPass, MirSource};
|
||||
use rustc::mir::transform::{Pass, MirMapPass, MirPassHook, MirSource};
|
||||
use rustc::mir::visit::{LvalueContext, Visitor};
|
||||
use rustc::util::nodemap::DefIdMap;
|
||||
use rustc::middle::lang_items;
|
||||
use syntax::abi::Abi;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use syntax_pos::Span;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::fmt;
|
||||
use std::usize;
|
||||
|
||||
@ -41,36 +41,32 @@ use super::promote_consts::{self, Candidate, TempState};
|
||||
|
||||
bitflags! {
|
||||
flags Qualif: u8 {
|
||||
// Const item's qualification while recursing.
|
||||
// Recursive consts are an error.
|
||||
const RECURSIVE = 1 << 0,
|
||||
|
||||
// Constant containing interior mutability (UnsafeCell).
|
||||
const MUTABLE_INTERIOR = 1 << 1,
|
||||
const MUTABLE_INTERIOR = 1 << 0,
|
||||
|
||||
// Constant containing an ADT that implements Drop.
|
||||
const NEEDS_DROP = 1 << 2,
|
||||
const NEEDS_DROP = 1 << 1,
|
||||
|
||||
// Function argument.
|
||||
const FN_ARGUMENT = 1 << 3,
|
||||
const FN_ARGUMENT = 1 << 2,
|
||||
|
||||
// Static lvalue or move from a static.
|
||||
const STATIC = 1 << 4,
|
||||
const STATIC = 1 << 3,
|
||||
|
||||
// Reference to a static.
|
||||
const STATIC_REF = 1 << 5,
|
||||
const STATIC_REF = 1 << 4,
|
||||
|
||||
// Not constant at all - non-`const fn` calls, asm!,
|
||||
// pointer comparisons, ptr-to-int casts, etc.
|
||||
const NOT_CONST = 1 << 6,
|
||||
const NOT_CONST = 1 << 5,
|
||||
|
||||
// Refers to temporaries which cannot be promoted as
|
||||
// promote_consts decided they weren't simple enough.
|
||||
const NOT_PROMOTABLE = 1 << 7,
|
||||
const NOT_PROMOTABLE = 1 << 6,
|
||||
|
||||
// Borrows of temporaries can be promoted only
|
||||
// if they have none of the above qualifications.
|
||||
const NEVER_PROMOTE = !0,
|
||||
const NEVER_PROMOTE = 0b111_1111,
|
||||
|
||||
// Const items can only have MUTABLE_INTERIOR
|
||||
// and NOT_PROMOTABLE without producing an error.
|
||||
@ -134,7 +130,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
rpo: ReversePostorder<'a, 'tcx>,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
param_env: ty::ParameterEnvironment<'tcx>,
|
||||
qualif_map: &'a mut DefIdMap<Qualif>,
|
||||
temp_qualif: IndexVec<Local, Option<Qualif>>,
|
||||
return_qualif: Option<Qualif>,
|
||||
qualif: Qualif,
|
||||
@ -146,7 +141,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParameterEnvironment<'tcx>,
|
||||
qualif_map: &'a mut DefIdMap<Qualif>,
|
||||
def_id: DefId,
|
||||
mir: &'a Mir<'tcx>,
|
||||
mode: Mode)
|
||||
@ -162,7 +156,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
rpo: rpo,
|
||||
tcx: tcx,
|
||||
param_env: param_env,
|
||||
qualif_map: qualif_map,
|
||||
temp_qualif: IndexVec::from_elem(None, &mir.local_decls),
|
||||
return_qualif: None,
|
||||
qualif: Qualif::empty(),
|
||||
@ -585,17 +578,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||
if substs.types().next().is_some() {
|
||||
self.add_type(constant.ty);
|
||||
} else {
|
||||
let qualif = qualify_const_item_cached(self.tcx,
|
||||
self.qualif_map,
|
||||
def_id);
|
||||
self.add(qualif);
|
||||
}
|
||||
let bits = ty::queries::mir_const_qualif::get(self.tcx,
|
||||
constant.span,
|
||||
def_id);
|
||||
|
||||
// FIXME(eddyb) check recursive constants here,
|
||||
// instead of rustc_passes::static_recursion.
|
||||
if self.qualif.intersects(Qualif::RECURSIVE) {
|
||||
span_bug!(constant.span,
|
||||
"recursive constant wasn't caught earlier");
|
||||
let qualif = Qualif::from_bits(bits).expect("invalid mir_const_qualif");
|
||||
self.add(qualif);
|
||||
}
|
||||
|
||||
// Let `const fn` transitively have destructors,
|
||||
@ -944,41 +932,64 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn qualify_const_item_cached<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
qualif_map: &mut DefIdMap<Qualif>,
|
||||
def_id: DefId)
|
||||
-> Qualif {
|
||||
match qualif_map.entry(def_id) {
|
||||
Entry::Occupied(entry) => return *entry.get(),
|
||||
Entry::Vacant(entry) => {
|
||||
// Guard against `const` recursion.
|
||||
entry.insert(Qualif::RECURSIVE);
|
||||
}
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
providers.mir_const_qualif = qualify_const_item;
|
||||
}
|
||||
|
||||
fn qualify_const_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> u8 {
|
||||
let mir = &tcx.item_mir(def_id);
|
||||
if mir.return_ty.references_error() {
|
||||
return Qualif::NOT_CONST.bits();
|
||||
}
|
||||
|
||||
let param_env = if def_id.is_local() {
|
||||
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
|
||||
ty::ParameterEnvironment::for_item(tcx, node_id)
|
||||
} else {
|
||||
// These should only be monomorphic constants.
|
||||
tcx.empty_parameter_environment()
|
||||
};
|
||||
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
|
||||
let param_env = ty::ParameterEnvironment::for_item(tcx, node_id);
|
||||
|
||||
let mir = &tcx.item_mir(def_id);
|
||||
let mut qualifier = Qualifier::new(tcx, param_env, qualif_map, def_id, mir, Mode::Const);
|
||||
let qualif = qualifier.qualify_const();
|
||||
qualifier.qualif_map.insert(def_id, qualif);
|
||||
qualif
|
||||
let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, Mode::Const);
|
||||
qualifier.qualify_const().bits()
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct QualifyAndPromoteConstants {
|
||||
qualif_map: DefIdMap<Qualif>
|
||||
}
|
||||
pub struct QualifyAndPromoteConstants;
|
||||
|
||||
impl Pass for QualifyAndPromoteConstants {}
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants {
|
||||
impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
|
||||
fn run_pass<'a>(&mut self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
hooks: &mut [Box<for<'s> MirPassHook<'s>>])
|
||||
{
|
||||
let def_ids = tcx.maps.mir.borrow().keys();
|
||||
for def_id in def_ids {
|
||||
if !def_id.is_local() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
|
||||
let id = tcx.hir.as_local_node_id(def_id).unwrap();
|
||||
let src = MirSource::from_node(tcx, id);
|
||||
|
||||
if let MirSource::Const(_) = src {
|
||||
ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
let mir = &mut tcx.maps.mir.borrow()[&def_id].borrow_mut();
|
||||
tcx.dep_graph.write(DepNode::Mir(def_id));
|
||||
|
||||
for hook in &mut *hooks {
|
||||
hook.on_mir_pass(tcx, src, mir, self, false);
|
||||
}
|
||||
self.run_pass(tcx, src, mir);
|
||||
for hook in &mut *hooks {
|
||||
hook.on_mir_pass(tcx, src, mir, self, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QualifyAndPromoteConstants {
|
||||
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
src: MirSource, mir: &mut Mir<'tcx>) {
|
||||
let id = src.item_id();
|
||||
@ -991,18 +1002,9 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants {
|
||||
Mode::Fn
|
||||
}
|
||||
}
|
||||
MirSource::Const(_) => {
|
||||
match self.qualif_map.entry(def_id) {
|
||||
Entry::Occupied(_) => return,
|
||||
Entry::Vacant(entry) => {
|
||||
// Guard against `const` recursion.
|
||||
entry.insert(Qualif::RECURSIVE);
|
||||
Mode::Const
|
||||
}
|
||||
}
|
||||
}
|
||||
MirSource::Static(_, hir::MutImmutable) => Mode::Static,
|
||||
MirSource::Static(_, hir::MutMutable) => Mode::StaticMut,
|
||||
MirSource::Const(_) |
|
||||
MirSource::Promoted(..) => return
|
||||
};
|
||||
let param_env = ty::ParameterEnvironment::for_item(tcx, id);
|
||||
@ -1012,7 +1014,6 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants {
|
||||
// which can't be mutated until its scope ends.
|
||||
let (temps, candidates) = {
|
||||
let mut qualifier = Qualifier::new(tcx, param_env,
|
||||
&mut self.qualif_map,
|
||||
def_id, mir, mode);
|
||||
if mode == Mode::ConstFn {
|
||||
// Enforce a constant-like CFG for `const fn`.
|
||||
@ -1029,14 +1030,8 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants {
|
||||
// Do the actual promotion, now that we know what's viable.
|
||||
promote_consts::promote_candidates(mir, tcx, temps, candidates);
|
||||
} else {
|
||||
let mut qualifier = Qualifier::new(tcx, param_env,
|
||||
&mut self.qualif_map,
|
||||
def_id, mir, mode);
|
||||
let qualif = qualifier.qualify_const();
|
||||
|
||||
if mode == Mode::Const {
|
||||
qualifier.qualif_map.insert(def_id, qualif);
|
||||
}
|
||||
let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, mode);
|
||||
qualifier.qualify_const();
|
||||
}
|
||||
|
||||
// Statics must be Sync.
|
||||
|
26
src/test/compile-fail/const-block-non-item-statement-2.rs
Normal file
26
src/test/compile-fail/const-block-non-item-statement-2.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// 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.
|
||||
|
||||
const A: usize = { 1; 2 };
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
|
||||
const B: usize = { { } 2 };
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
|
||||
macro_rules! foo {
|
||||
() => (()) //~ ERROR: blocks in constants are limited to items and tail expressions
|
||||
}
|
||||
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
|
||||
|
||||
pub fn main() {}
|
@ -8,21 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
const A: usize = { 1; 2 };
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
|
||||
const B: usize = { { } 2 };
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
|
||||
macro_rules! foo {
|
||||
() => (()) //~ ERROR: blocks in constants are limited to items and tail expressions
|
||||
}
|
||||
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
|
||||
|
||||
enum Foo {
|
||||
Bar = { let x = 1; 3 }
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
@ -33,8 +18,4 @@ 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
|
||||
|
||||
pub fn main() {
|
||||
let _: Array = [0; { let x = 3; 5 }];
|
||||
//~^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
//~^^ ERROR: blocks in constants are limited to items and tail expressions
|
||||
}
|
||||
pub fn main() {}
|
||||
|
@ -15,6 +15,8 @@ fn f(x: usize) -> usize {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = [0; f(2)]; //~ ERROR constant evaluation error [E0080]
|
||||
//~| non-constant path in constant expression
|
||||
let _ = [0; f(2)];
|
||||
//~^ ERROR calls in constants are limited to constant functions
|
||||
//~| ERROR constant evaluation error [E0080]
|
||||
//~| non-constant path in constant expression
|
||||
}
|
||||
|
@ -27,9 +27,11 @@ pub struct Vector<T, D: Dim> {
|
||||
|
||||
fn main() {
|
||||
let array: [usize; Dim3::dim()]
|
||||
//~^ ERROR constant evaluation error
|
||||
//~^ ERROR calls in constants are limited to constant functions
|
||||
//~| ERROR constant evaluation error
|
||||
//~| non-constant path in constant expression
|
||||
= [0; Dim3::dim()];
|
||||
//~^ ERROR constant evaluation error
|
||||
//~^ ERROR calls in constants are limited to constant functions
|
||||
//~| ERROR constant evaluation error
|
||||
//~| non-constant path in constant expression
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user