Skip to content

Commit 3cb24bd

Browse files
committed
Auto merge of #44275 - eddyb:deferred-ctfe, r=nikomatsakis
Evaluate fixed-length array length expressions lazily. This is in preparation for polymorphic array lengths (aka `[T; T::A]`) and const generics. We need deferred const-evaluation to break cycles when array types show up in positions which require knowing the array type to typeck the array length, e.g. the array type is in a `where` clause. The final step - actually passing bounds in scope to array length expressions from the parent - is not done because it still produces cycles when *normalizing* `ParamEnv`s, and @nikomatsakis' in-progress lazy normalization work is needed to deal with that uniformly. However, the changes here are still useful to unlock work on const generics, which @EpicatSupercell manifested interest in, and I might be mentoring them for that, but we need this baseline first. r? @nikomatsakis cc @oli-obk
2 parents 11f64d8 + 57ebd28 commit 3cb24bd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+1605
-785
lines changed

src/librustc/hir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ pub enum BindingAnnotation {
611611
RefMut,
612612
}
613613

614-
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
614+
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
615615
pub enum RangeEnd {
616616
Included,
617617
Excluded,

src/librustc/ich/impls_mir.rs

-4
Original file line numberDiff line numberDiff line change
@@ -493,10 +493,6 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::L
493493
hasher: &mut StableHasher<W>) {
494494
mem::discriminant(self).hash_stable(hcx, hasher);
495495
match *self {
496-
mir::Literal::Item { def_id, substs } => {
497-
def_id.hash_stable(hcx, hasher);
498-
substs.hash_stable(hcx, hasher);
499-
}
500496
mir::Literal::Value { ref value } => {
501497
value.hash_stable(hcx, hasher);
502498
}

src/librustc/ich/impls_ty.rs

+32-19
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
1616
StableHasherResult};
1717
use std::hash as std_hash;
1818
use std::mem;
19-
use syntax_pos::symbol::InternedString;
2019
use middle::region;
2120
use ty;
2221

@@ -236,6 +235,10 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Pr
236235
def_id.hash_stable(hcx, hasher);
237236
closure_kind.hash_stable(hcx, hasher);
238237
}
238+
ty::Predicate::ConstEvaluatable(def_id, substs) => {
239+
def_id.hash_stable(hcx, hasher);
240+
substs.hash_stable(hcx, hasher);
241+
}
239242
}
240243
}
241244
}
@@ -272,59 +275,69 @@ for ::middle::const_val::ConstVal<'gcx> {
272275
fn hash_stable<W: StableHasherResult>(&self,
273276
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
274277
hasher: &mut StableHasher<W>) {
275-
use middle::const_val::ConstVal;
278+
use middle::const_val::ConstVal::*;
279+
use middle::const_val::ConstAggregate::*;
276280

277281
mem::discriminant(self).hash_stable(hcx, hasher);
278282

279283
match *self {
280-
ConstVal::Float(ref value) => {
284+
Integral(ref value) => {
281285
value.hash_stable(hcx, hasher);
282286
}
283-
ConstVal::Integral(ref value) => {
287+
Float(ref value) => {
284288
value.hash_stable(hcx, hasher);
285289
}
286-
ConstVal::Str(ref value) => {
290+
Str(ref value) => {
287291
value.hash_stable(hcx, hasher);
288292
}
289-
ConstVal::ByteStr(ref value) => {
293+
ByteStr(ref value) => {
290294
value.hash_stable(hcx, hasher);
291295
}
292-
ConstVal::Bool(value) => {
296+
Bool(value) => {
293297
value.hash_stable(hcx, hasher);
294298
}
295-
ConstVal::Char(value) => {
299+
Char(value) => {
296300
value.hash_stable(hcx, hasher);
297301
}
298-
ConstVal::Variant(def_id) => {
302+
Variant(def_id) => {
299303
def_id.hash_stable(hcx, hasher);
300304
}
301-
ConstVal::Function(def_id, substs) => {
305+
Function(def_id, substs) => {
302306
def_id.hash_stable(hcx, hasher);
303307
substs.hash_stable(hcx, hasher);
304308
}
305-
ConstVal::Struct(ref name_value_map) => {
306-
let mut values: Vec<(InternedString, &ConstVal)> =
307-
name_value_map.iter()
308-
.map(|(name, val)| (name.as_str(), val))
309-
.collect();
310-
309+
Aggregate(Struct(ref name_values)) => {
310+
let mut values = name_values.to_vec();
311311
values.sort_unstable_by_key(|&(ref name, _)| name.clone());
312312
values.hash_stable(hcx, hasher);
313313
}
314-
ConstVal::Tuple(ref value) => {
314+
Aggregate(Tuple(ref value)) => {
315315
value.hash_stable(hcx, hasher);
316316
}
317-
ConstVal::Array(ref value) => {
317+
Aggregate(Array(ref value)) => {
318318
value.hash_stable(hcx, hasher);
319319
}
320-
ConstVal::Repeat(ref value, times) => {
320+
Aggregate(Repeat(ref value, times)) => {
321321
value.hash_stable(hcx, hasher);
322322
times.hash_stable(hcx, hasher);
323323
}
324+
Unevaluated(def_id, substs) => {
325+
def_id.hash_stable(hcx, hasher);
326+
substs.hash_stable(hcx, hasher);
327+
}
324328
}
325329
}
326330
}
327331

332+
impl_stable_hash_for!(struct ::middle::const_val::ByteArray<'tcx> {
333+
data
334+
});
335+
336+
impl_stable_hash_for!(struct ty::Const<'tcx> {
337+
ty,
338+
val
339+
});
340+
328341
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
329342

330343
impl_stable_hash_for!(struct ty::GeneratorInterior<'tcx> { witness });

src/librustc/infer/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ macro_rules! impl_trans_normalize {
442442

443443
impl_trans_normalize!('gcx,
444444
Ty<'gcx>,
445+
&'gcx ty::Const<'gcx>,
445446
&'gcx Substs<'gcx>,
446447
ty::FnSig<'gcx>,
447448
ty::PolyFnSig<'gcx>,
@@ -493,7 +494,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
493494
let param_env = ty::ParamEnv::empty(Reveal::All);
494495
let value = self.erase_regions(value);
495496

496-
if !value.has_projection_types() {
497+
if !value.has_projections() {
497498
return value;
498499
}
499500

@@ -515,7 +516,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
515516

516517
let value = self.erase_regions(value);
517518

518-
if !value.has_projection_types() {
519+
if !value.has_projections() {
519520
return value;
520521
}
521522

src/librustc/middle/const_val.rs

+33-70
Original file line numberDiff line numberDiff line change
@@ -8,64 +8,66 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use self::ConstVal::*;
1211
pub use rustc_const_math::ConstInt;
1312

14-
use hir;
15-
use hir::def::Def;
1613
use hir::def_id::DefId;
17-
use traits::Reveal;
1814
use ty::{self, TyCtxt, layout};
1915
use ty::subst::Substs;
20-
use util::common::ErrorReported;
2116
use rustc_const_math::*;
2217

2318
use graphviz::IntoCow;
2419
use errors::DiagnosticBuilder;
20+
use serialize::{self, Encodable, Encoder, Decodable, Decoder};
2521
use syntax::symbol::InternedString;
2622
use syntax::ast;
2723
use syntax_pos::Span;
2824

2925
use std::borrow::Cow;
30-
use std::collections::BTreeMap;
31-
use std::rc::Rc;
3226

33-
pub type EvalResult<'tcx> = Result<ConstVal<'tcx>, ConstEvalErr<'tcx>>;
27+
pub type EvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ConstEvalErr<'tcx>>;
3428

35-
#[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
29+
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
3630
pub enum ConstVal<'tcx> {
37-
Float(ConstFloat),
3831
Integral(ConstInt),
32+
Float(ConstFloat),
3933
Str(InternedString),
40-
ByteStr(Rc<Vec<u8>>),
34+
ByteStr(ByteArray<'tcx>),
4135
Bool(bool),
4236
Char(char),
4337
Variant(DefId),
4438
Function(DefId, &'tcx Substs<'tcx>),
45-
Struct(BTreeMap<ast::Name, ConstVal<'tcx>>),
46-
Tuple(Vec<ConstVal<'tcx>>),
47-
Array(Vec<ConstVal<'tcx>>),
48-
Repeat(Box<ConstVal<'tcx>>, u64),
39+
Aggregate(ConstAggregate<'tcx>),
40+
Unevaluated(DefId, &'tcx Substs<'tcx>),
4941
}
5042

51-
impl<'tcx> ConstVal<'tcx> {
52-
pub fn description(&self) -> &'static str {
53-
match *self {
54-
Float(f) => f.description(),
55-
Integral(i) => i.description(),
56-
Str(_) => "string literal",
57-
ByteStr(_) => "byte string literal",
58-
Bool(_) => "boolean",
59-
Char(..) => "char",
60-
Variant(_) => "enum variant",
61-
Struct(_) => "struct",
62-
Tuple(_) => "tuple",
63-
Function(..) => "function definition",
64-
Array(..) => "array",
65-
Repeat(..) => "repeat",
66-
}
43+
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, Eq, PartialEq)]
44+
pub struct ByteArray<'tcx> {
45+
pub data: &'tcx [u8],
46+
}
47+
48+
impl<'tcx> serialize::UseSpecializedDecodable for ByteArray<'tcx> {}
49+
50+
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
51+
pub enum ConstAggregate<'tcx> {
52+
Struct(&'tcx [(ast::Name, &'tcx ty::Const<'tcx>)]),
53+
Tuple(&'tcx [&'tcx ty::Const<'tcx>]),
54+
Array(&'tcx [&'tcx ty::Const<'tcx>]),
55+
Repeat(&'tcx ty::Const<'tcx>, u64),
56+
}
57+
58+
impl<'tcx> Encodable for ConstAggregate<'tcx> {
59+
fn encode<S: Encoder>(&self, _: &mut S) -> Result<(), S::Error> {
60+
bug!("should never encode ConstAggregate::{:?}", self)
61+
}
62+
}
63+
64+
impl<'tcx> Decodable for ConstAggregate<'tcx> {
65+
fn decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
66+
bug!("should never decode ConstAggregate")
6767
}
68+
}
6869

70+
impl<'tcx> ConstVal<'tcx> {
6971
pub fn to_const_int(&self) -> Option<ConstInt> {
7072
match *self {
7173
ConstVal::Integral(i) => Some(i),
@@ -86,8 +88,6 @@ pub struct ConstEvalErr<'tcx> {
8688
pub enum ErrKind<'tcx> {
8789
CannotCast,
8890
MissingStructField,
89-
NegateOn(ConstVal<'tcx>),
90-
NotOn(ConstVal<'tcx>),
9191

9292
NonConstPath,
9393
UnimplementedConstVal(&'static str),
@@ -146,9 +146,6 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
146146

147147
match self.kind {
148148
CannotCast => simple!("can't cast this type"),
149-
NegateOn(ref const_val) => simple!("negate on {}", const_val.description()),
150-
NotOn(ref const_val) => simple!("not on {}", const_val.description()),
151-
152149
MissingStructField => simple!("nonexistent struct field"),
153150
NonConstPath => simple!("non-constant path in constant expression"),
154151
UnimplementedConstVal(what) =>
@@ -221,37 +218,3 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
221218
self.struct_error(tcx, primary_span, primary_kind).emit();
222219
}
223220
}
224-
225-
/// Returns the value of the length-valued expression
226-
pub fn eval_length(tcx: TyCtxt,
227-
count: hir::BodyId,
228-
reason: &str)
229-
-> Result<usize, ErrorReported>
230-
{
231-
let count_expr = &tcx.hir.body(count).value;
232-
let count_def_id = tcx.hir.body_owner_def_id(count);
233-
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
234-
let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
235-
match tcx.at(count_expr.span).const_eval(param_env.and((count_def_id, substs))) {
236-
Ok(Integral(Usize(count))) => {
237-
let val = count.as_u64(tcx.sess.target.uint_type);
238-
assert_eq!(val as usize as u64, val);
239-
Ok(val as usize)
240-
},
241-
Ok(_) |
242-
Err(ConstEvalErr { kind: ErrKind::TypeckError, .. }) => Err(ErrorReported),
243-
Err(err) => {
244-
let mut diag = err.struct_error(tcx, count_expr.span, reason);
245-
246-
if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node {
247-
if let Def::Local(..) = path.def {
248-
diag.note(&format!("`{}` is a variable",
249-
tcx.hir.node_to_pretty_string(count_expr.id)));
250-
}
251-
}
252-
253-
diag.emit();
254-
Err(ErrorReported)
255-
}
256-
}
257-
}

src/librustc/middle/free_region.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ impl<'tcx> FreeRegionMap<'tcx> {
147147
ty::Predicate::WellFormed(..) |
148148
ty::Predicate::ObjectSafe(..) |
149149
ty::Predicate::ClosureKind(..) |
150-
ty::Predicate::TypeOutlives(..) => {
150+
ty::Predicate::TypeOutlives(..) |
151+
ty::Predicate::ConstEvaluatable(..) => {
151152
// No region bounds here
152153
}
153154
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => {

src/librustc/middle/mem_categorization.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
876876

877877
// Always promote `[T; 0]` (even when e.g. borrowed mutably).
878878
let promotable = match expr_ty.sty {
879-
ty::TyArray(_, 0) => true,
879+
ty::TyArray(_, len) if
880+
len.val.to_const_int().and_then(|i| i.to_u64()) == Some(0) => true,
880881
_ => promotable,
881882
};
882883

0 commit comments

Comments
 (0)