Skip to content

Commit acd89e7

Browse files
committed
rustc: evaluate fixed-length array length expressions lazily.
1 parent 99f0df0 commit acd89e7

Some content is hidden

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

44 files changed

+486
-76
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,10 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Pr
234234
def_id.hash_stable(hcx, hasher);
235235
closure_kind.hash_stable(hcx, hasher);
236236
}
237+
ty::Predicate::ConstEvaluatable(def_id, substs) => {
238+
def_id.hash_stable(hcx, hasher);
239+
substs.hash_stable(hcx, hasher);
240+
}
237241
}
238242
}
239243
}
@@ -316,6 +320,10 @@ for ::middle::const_val::ConstVal<'gcx> {
316320
value.hash_stable(hcx, hasher);
317321
times.hash_stable(hcx, hasher);
318322
}
323+
Unevaluated(def_id, substs) => {
324+
def_id.hash_stable(hcx, hasher);
325+
substs.hash_stable(hcx, hasher);
326+
}
319327
}
320328
}
321329
}

src/librustc/infer/mod.rs

Lines changed: 3 additions & 2 deletions
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub enum ConstVal<'tcx> {
4141
Variant(DefId),
4242
Function(DefId, &'tcx Substs<'tcx>),
4343
Aggregate(ConstAggregate<'tcx>),
44+
Unevaluated(DefId, &'tcx Substs<'tcx>),
4445
}
4546

4647
#[derive(Copy, Clone, Debug, Hash, RustcEncodable, Eq, PartialEq)]

src/librustc/middle/free_region.rs

Lines changed: 2 additions & 1 deletion
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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
879879

880880
// Always promote `[T; 0]` (even when e.g. borrowed mutably).
881881
let promotable = match expr_ty.sty {
882-
ty::TyArray(_, len) if len.val.to_const_int().unwrap().to_u64().unwrap() == 0 => true,
882+
ty::TyArray(_, len) if
883+
len.val.to_const_int().and_then(|i| i.to_u64()) == Some(0) => true,
883884
_ => promotable,
884885
};
885886

src/librustc/mir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,6 +1539,7 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
15391539
Variant(def_id) |
15401540
Function(def_id, _) => write!(fmt, "{}", item_path_str(def_id)),
15411541
Aggregate(_) => bug!("`ConstVal::{:?}` should not be in MIR", const_val),
1542+
Unevaluated(..) => write!(fmt, "{:?}", const_val)
15421543
}
15431544
}
15441545

src/librustc/traits/error_reporting.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use super::{
1717
ObligationCauseCode,
1818
OutputTypeParameterMismatch,
1919
TraitNotObjectSafe,
20+
ConstEvalFailure,
2021
PredicateObligation,
2122
Reveal,
2223
SelectionContext,
@@ -30,6 +31,7 @@ use hir;
3031
use hir::def_id::DefId;
3132
use infer::{self, InferCtxt};
3233
use infer::type_variable::TypeVariableOrigin;
34+
use middle::const_val;
3335
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
3436
use std::fmt;
3537
use syntax::ast;
@@ -712,6 +714,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
712714
// (which may fail).
713715
span_bug!(span, "WF predicate not satisfied for {:?}", ty);
714716
}
717+
718+
ty::Predicate::ConstEvaluatable(..) => {
719+
// Errors for `ConstEvaluatable` predicates show up as
720+
// `SelectionError::ConstEvalFailure`,
721+
// not `Unimplemented`.
722+
span_bug!(span,
723+
"const-evaluatable requirement gave wrong error: `{:?}`", obligation)
724+
}
715725
}
716726
}
717727

@@ -776,6 +786,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
776786
self.tcx.report_object_safety_error(span, did,
777787
violations)
778788
}
789+
790+
ConstEvalFailure(ref err) => {
791+
if let const_val::ErrKind::TypeckError = err.kind {
792+
return;
793+
}
794+
err.struct_error(self.tcx, span, "constant expression")
795+
}
779796
};
780797
self.note_obligation_cause(&mut err, obligation);
781798
err.emit();

src/librustc/traits/fulfill.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use super::{FulfillmentError, FulfillmentErrorCode};
2525
use super::{ObligationCause, PredicateObligation, Obligation};
2626
use super::project;
2727
use super::select::SelectionContext;
28-
use super::Unimplemented;
28+
use super::{Unimplemented, ConstEvalFailure};
2929

3030
impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
3131
type Predicate = ty::Predicate<'tcx>;
@@ -540,6 +540,29 @@ fn process_predicate<'a, 'gcx, 'tcx>(
540540
}
541541
}
542542
}
543+
544+
ty::Predicate::ConstEvaluatable(def_id, substs) => {
545+
match selcx.tcx().lift_to_global(&obligation.param_env) {
546+
None => {
547+
Ok(None)
548+
}
549+
Some(param_env) => {
550+
match selcx.tcx().lift_to_global(&substs) {
551+
None => {
552+
pending_obligation.stalled_on = substs.types().collect();
553+
Ok(None)
554+
}
555+
Some(substs) => {
556+
match selcx.tcx().at(obligation.cause.span)
557+
.const_eval(param_env.and((def_id, substs))) {
558+
Ok(_) => Ok(Some(vec![])),
559+
Err(e) => Err(CodeSelectionError(ConstEvalFailure(e)))
560+
}
561+
}
562+
}
563+
}
564+
}
565+
}
543566
}
544567
}
545568

src/librustc/traits/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub use self::ObligationCauseCode::*;
1717

1818
use hir;
1919
use hir::def_id::DefId;
20+
use middle::const_val::ConstEvalErr;
2021
use middle::region::RegionMaps;
2122
use middle::free_region::FreeRegionMap;
2223
use ty::subst::Substs;
@@ -217,6 +218,7 @@ pub enum SelectionError<'tcx> {
217218
ty::PolyTraitRef<'tcx>,
218219
ty::error::TypeError<'tcx>),
219220
TraitNotObjectSafe(DefId),
221+
ConstEvalFailure(ConstEvalErr<'tcx>),
220222
}
221223

222224
pub struct FulfillmentError<'tcx> {

src/librustc/traits/object_safety.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
169169
ty::Predicate::RegionOutlives(..) |
170170
ty::Predicate::ClosureKind(..) |
171171
ty::Predicate::Subtype(..) |
172-
ty::Predicate::Equate(..) => {
172+
ty::Predicate::Equate(..) |
173+
ty::Predicate::ConstEvaluatable(..) => {
173174
false
174175
}
175176
}
@@ -203,7 +204,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
203204
ty::Predicate::WellFormed(..) |
204205
ty::Predicate::ObjectSafe(..) |
205206
ty::Predicate::ClosureKind(..) |
206-
ty::Predicate::TypeOutlives(..) => {
207+
ty::Predicate::TypeOutlives(..) |
208+
ty::Predicate::ConstEvaluatable(..) => {
207209
false
208210
}
209211
}

0 commit comments

Comments
 (0)