Skip to content

Commit f77f07c

Browse files
committed
Canonicalize inputs to const eval where needed.
1 parent a2fb0c2 commit f77f07c

File tree

3 files changed

+50
-35
lines changed

3 files changed

+50
-35
lines changed

src/librustc_infer/infer/mod.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToTy
1515
use rustc::middle::free_region::RegionRelations;
1616
use rustc::middle::lang_items;
1717
use rustc::middle::region;
18+
use rustc::mir;
19+
use rustc::mir::interpret::ConstEvalResult;
1820
use rustc::session::config::BorrowckMode;
1921
use rustc::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
2022
use rustc::ty::fold::{TypeFoldable, TypeFolder};
@@ -63,6 +65,7 @@ pub mod resolve;
6365
mod sub;
6466
pub mod type_variable;
6567

68+
use crate::infer::canonical::OriginalQueryValues;
6669
pub use rustc::infer::unify_key;
6770

6871
#[must_use]
@@ -1565,6 +1568,35 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15651568
self.universe.set(u);
15661569
u
15671570
}
1571+
1572+
/// Resolves and evaluates a constant.
1573+
///
1574+
/// The constant can be located on a trait like `<A as B>::C`, in which case the given
1575+
/// substitutions and environment are used to resolve the constant. Alternatively if the
1576+
/// constant has generic parameters in scope the substitutions are used to evaluate the value of
1577+
/// the constant. For example in `fn foo<T>() { let _ = [0; bar::<T>()]; }` the repeat count
1578+
/// constant `bar::<T>()` requires a substitution for `T`, if the substitution for `T` is still
1579+
/// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
1580+
/// returned.
1581+
///
1582+
/// This handles inferences variables within both `param_env` and `substs` by
1583+
/// performing the operation on their respective canonical forms.
1584+
pub fn const_eval_resolve(
1585+
&self,
1586+
param_env: ty::ParamEnv<'tcx>,
1587+
def_id: DefId,
1588+
substs: SubstsRef<'tcx>,
1589+
promoted: Option<mir::Promoted>,
1590+
span: Option<Span>,
1591+
) -> ConstEvalResult<'tcx> {
1592+
let mut original_values = OriginalQueryValues::default();
1593+
let canonical = self.canonicalize_query(&(param_env, substs), &mut original_values);
1594+
1595+
let (param_env, substs) = canonical.value;
1596+
// The return value is the evaluated value which doesn't contain any reference to inference
1597+
// variables, thus we don't need to substitute back the original values.
1598+
self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, span)
1599+
}
15681600
}
15691601

15701602
pub struct ShallowResolver<'a, 'tcx> {

src/librustc_infer/traits/fulfill.rs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -510,27 +510,15 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
510510
}
511511

512512
ty::Predicate::ConstEvaluatable(def_id, substs) => {
513-
if obligation.param_env.has_local_value() {
514-
ProcessResult::Unchanged
515-
} else {
516-
if !substs.has_local_value() {
517-
match self.selcx.tcx().const_eval_resolve(
518-
obligation.param_env,
519-
def_id,
520-
substs,
521-
None,
522-
Some(obligation.cause.span),
523-
) {
524-
Ok(_) => ProcessResult::Changed(vec![]),
525-
Err(err) => {
526-
ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err)))
527-
}
528-
}
529-
} else {
530-
pending_obligation.stalled_on =
531-
substs.types().map(|ty| infer_ty(ty)).collect();
532-
ProcessResult::Unchanged
533-
}
513+
match self.selcx.infcx().const_eval_resolve(
514+
obligation.param_env,
515+
def_id,
516+
substs,
517+
None,
518+
Some(obligation.cause.span),
519+
) {
520+
Ok(_) => ProcessResult::Changed(vec![]),
521+
Err(err) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err))),
534522
}
535523
}
536524
}

src/librustc_infer/traits/select.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -532,20 +532,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
532532
}
533533

534534
ty::Predicate::ConstEvaluatable(def_id, substs) => {
535-
if !(obligation.param_env, substs).has_local_value() {
536-
match self.tcx().const_eval_resolve(
537-
obligation.param_env,
538-
def_id,
539-
substs,
540-
None,
541-
None,
542-
) {
543-
Ok(_) => Ok(EvaluatedToOk),
544-
Err(_) => Ok(EvaluatedToErr),
545-
}
546-
} else {
547-
// Inference variables still left in param_env or substs.
548-
Ok(EvaluatedToAmbig)
535+
match self.tcx().const_eval_resolve(
536+
obligation.param_env,
537+
def_id,
538+
substs,
539+
None,
540+
None,
541+
) {
542+
Ok(_) => Ok(EvaluatedToOk),
543+
Err(_) => Ok(EvaluatedToErr),
549544
}
550545
}
551546
}

0 commit comments

Comments
 (0)