mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Canonicalize inputs to const eval where needed.
This commit is contained in:
parent
a2fb0c28be
commit
f77f07c55b
@ -15,6 +15,8 @@ use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToTy
|
||||
use rustc::middle::free_region::RegionRelations;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::middle::region;
|
||||
use rustc::mir;
|
||||
use rustc::mir::interpret::ConstEvalResult;
|
||||
use rustc::session::config::BorrowckMode;
|
||||
use rustc::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
|
||||
use rustc::ty::fold::{TypeFoldable, TypeFolder};
|
||||
@ -63,6 +65,7 @@ pub mod resolve;
|
||||
mod sub;
|
||||
pub mod type_variable;
|
||||
|
||||
use crate::infer::canonical::OriginalQueryValues;
|
||||
pub use rustc::infer::unify_key;
|
||||
|
||||
#[must_use]
|
||||
@ -1565,6 +1568,35 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
self.universe.set(u);
|
||||
u
|
||||
}
|
||||
|
||||
/// Resolves and evaluates a constant.
|
||||
///
|
||||
/// The constant can be located on a trait like `<A as B>::C`, in which case the given
|
||||
/// substitutions and environment are used to resolve the constant. Alternatively if the
|
||||
/// constant has generic parameters in scope the substitutions are used to evaluate the value of
|
||||
/// the constant. For example in `fn foo<T>() { let _ = [0; bar::<T>()]; }` the repeat count
|
||||
/// constant `bar::<T>()` requires a substitution for `T`, if the substitution for `T` is still
|
||||
/// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
|
||||
/// returned.
|
||||
///
|
||||
/// This handles inferences variables within both `param_env` and `substs` by
|
||||
/// performing the operation on their respective canonical forms.
|
||||
pub fn const_eval_resolve(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
def_id: DefId,
|
||||
substs: SubstsRef<'tcx>,
|
||||
promoted: Option<mir::Promoted>,
|
||||
span: Option<Span>,
|
||||
) -> ConstEvalResult<'tcx> {
|
||||
let mut original_values = OriginalQueryValues::default();
|
||||
let canonical = self.canonicalize_query(&(param_env, substs), &mut original_values);
|
||||
|
||||
let (param_env, substs) = canonical.value;
|
||||
// The return value is the evaluated value which doesn't contain any reference to inference
|
||||
// variables, thus we don't need to substitute back the original values.
|
||||
self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, span)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ShallowResolver<'a, 'tcx> {
|
||||
|
@ -510,27 +510,15 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||
}
|
||||
|
||||
ty::Predicate::ConstEvaluatable(def_id, substs) => {
|
||||
if obligation.param_env.has_local_value() {
|
||||
ProcessResult::Unchanged
|
||||
} else {
|
||||
if !substs.has_local_value() {
|
||||
match self.selcx.tcx().const_eval_resolve(
|
||||
obligation.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
None,
|
||||
Some(obligation.cause.span),
|
||||
) {
|
||||
Ok(_) => ProcessResult::Changed(vec![]),
|
||||
Err(err) => {
|
||||
ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err)))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pending_obligation.stalled_on =
|
||||
substs.types().map(|ty| infer_ty(ty)).collect();
|
||||
ProcessResult::Unchanged
|
||||
}
|
||||
match self.selcx.infcx().const_eval_resolve(
|
||||
obligation.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
None,
|
||||
Some(obligation.cause.span),
|
||||
) {
|
||||
Ok(_) => ProcessResult::Changed(vec![]),
|
||||
Err(err) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -532,20 +532,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
ty::Predicate::ConstEvaluatable(def_id, substs) => {
|
||||
if !(obligation.param_env, substs).has_local_value() {
|
||||
match self.tcx().const_eval_resolve(
|
||||
obligation.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
None,
|
||||
None,
|
||||
) {
|
||||
Ok(_) => Ok(EvaluatedToOk),
|
||||
Err(_) => Ok(EvaluatedToErr),
|
||||
}
|
||||
} else {
|
||||
// Inference variables still left in param_env or substs.
|
||||
Ok(EvaluatedToAmbig)
|
||||
match self.tcx().const_eval_resolve(
|
||||
obligation.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
None,
|
||||
None,
|
||||
) {
|
||||
Ok(_) => Ok(EvaluatedToOk),
|
||||
Err(_) => Ok(EvaluatedToErr),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user