const_eval_resolve

This commit is contained in:
Bastian Kauschke 2020-07-02 23:56:17 +02:00
parent 58031c7cb2
commit 2e6bf0923b
16 changed files with 96 additions and 28 deletions

View File

@ -28,7 +28,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
ty::ConstKind::Unevaluated(def, substs, promoted) => self
.cx
.tcx()
.const_eval_resolve(ty::ParamEnv::reveal_all(), def.did, substs, promoted, None)
.const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None)
.map_err(|err| {
if promoted.is_none() {
self.cx

View File

@ -1536,7 +1536,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn const_eval_resolve(
&self,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
def: ty::WithOptParam<DefId>,
substs: SubstsRef<'tcx>,
promoted: Option<mir::Promoted>,
span: Option<Span>,
@ -1547,7 +1547,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
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)
self.tcx.const_eval_resolve(param_env, def, substs, promoted, span)
}
/// If `typ` is a type variable of some kind, resolve it one level

View File

@ -34,12 +34,12 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn const_eval_resolve(
self,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
def: ty::WithOptParam<DefId>,
substs: SubstsRef<'tcx>,
promoted: Option<mir::Promoted>,
span: Option<Span>,
) -> ConstEvalResult<'tcx> {
match ty::Instance::resolve(self, param_env, def_id, substs) {
match ty::Instance::resolve_const_arg(self, param_env, def, substs) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted };
self.const_eval_global_id(param_env, cid, span)

View File

@ -1463,5 +1463,14 @@ rustc_queries! {
) -> Result<Option<ty::Instance<'tcx>>, ErrorReported> {
desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
}
query resolve_instance_of_const_arg(
key: ty::ParamEnvAnd<'tcx, (ty::WithOptParam<DefId>, SubstsRef<'tcx>)>
) -> Result<Option<ty::Instance<'tcx>>, ErrorReported> {
desc {
"resolving instance of the potential const argument `{}`",
ty::Instance::new(key.value.0.did, key.value.1),
}
}
}
}

View File

@ -336,6 +336,17 @@ impl<'tcx> Instance<'tcx> {
tcx.resolve_instance(tcx.erase_regions(&param_env.and((def_id, substs))))
}
// This should be kept up to date with `resolve`.
pub fn resolve_const_arg(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
def: ty::WithOptParam<DefId>,
substs: SubstsRef<'tcx>,
) -> Result<Option<Instance<'tcx>>, ErrorReported> {
let substs = tcx.erase_regions(&substs);
tcx.resolve_instance_of_const_arg(tcx.erase_regions(&param_env.and((def, substs))))
}
pub fn resolve_for_fn_ptr(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,

View File

@ -1100,7 +1100,7 @@ pub enum PredicateKind<'tcx> {
Subtype(PolySubtypePredicate<'tcx>),
/// Constant initializer must evaluate successfully.
ConstEvaluatable(DefId, SubstsRef<'tcx>),
ConstEvaluatable(ty::WithOptParam<DefId>, SubstsRef<'tcx>),
/// Constants must be equal. The first component is the const that is expected.
ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>),
@ -1571,7 +1571,7 @@ pub type PlaceholderType = Placeholder<BoundVar>;
pub type PlaceholderConst = Placeholder<BoundVar>;
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
#[derive(Copy, Clone, Debug, TypeFoldable, Lift, RustcEncodable, RustcDecodable)]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
#[derive(Hash, HashStable)]
pub struct WithOptParam<T> {

View File

@ -2027,9 +2027,9 @@ define_print_and_forward_display! {
print_value_path(closure_def_id, &[]),
write("` implements the trait `{}`", kind))
}
&ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
&ty::PredicateKind::ConstEvaluatable(def, substs) => {
p!(write("the constant `"),
print_value_path(def_id, substs),
print_value_path(def.did, substs),
write("` can be evaluated"))
}
ty::PredicateKind::ConstEquate(c1, c2) => {

View File

@ -171,6 +171,17 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
}
}
impl<'tcx> Key for (ty::WithOptParam<DefId>, SubstsRef<'tcx>) {
type CacheSelector = DefaultCacheSelector;
fn query_crate(&self) -> CrateNum {
LOCAL_CRATE
}
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.did.default_span(tcx)
}
}
impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
type CacheSelector = DefaultCacheSelector;

View File

@ -2373,7 +2373,7 @@ impl<'tcx> Const<'tcx> {
let (param_env, substs) = param_env_and_substs.into_parts();
// try to resolve e.g. associated constants to their definition on an impl, and then
// evaluate the const.
match tcx.const_eval_resolve(param_env, def.did, substs, promoted, None) {
match tcx.const_eval_resolve(param_env, def, substs, promoted, None) {
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
// and we use the original type, so nothing from `substs`
// (which may be identity substs, see above),

View File

@ -623,7 +623,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
match substituted_constant.val {
ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
ty::ConstKind::Unevaluated(def, substs, promoted) => {
match self.tcx.const_eval_resolve(param_env, def.did, substs, promoted, None) {
match self.tcx.const_eval_resolve(param_env, def, substs, promoted, None) {
Ok(val) => collect_const_value(self.tcx, val, self.output),
Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {}
Err(ErrorHandled::TooGeneric) => span_bug!(

View File

@ -527,7 +527,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
match self.selcx.infcx().const_eval_resolve(
obligation.param_env,
def.did,
def,
substs,
promoted,
Some(obligation.cause.span),

View File

@ -511,7 +511,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx
.const_eval_resolve(
obligation.param_env,
def.did,
def,
substs,
promoted,
Some(obligation.cause.span),

View File

@ -116,8 +116,8 @@ pub fn predicate_obligations<'a, 'tcx>(
wf.compute(data.skip_binder().a.into()); // (*)
wf.compute(data.skip_binder().b.into()); // (*)
}
&ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
let obligations = wf.nominal_obligations(def_id, substs);
&ty::PredicateKind::ConstEvaluatable(def, substs) => {
let obligations = wf.nominal_obligations(def.did, substs);
wf.out.extend(obligations);
for arg in substs.iter() {
@ -365,7 +365,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let obligations = self.nominal_obligations(def.did, substs);
self.out.extend(obligations);
let predicate = ty::PredicateKind::ConstEvaluatable(def.did, substs)
let predicate = ty::PredicateKind::ConstEvaluatable(def, substs)
.to_predicate(self.tcx());
let cause = self.cause(traits::MiscObligation);
self.out.push(traits::Obligation::new(

View File

@ -14,15 +14,48 @@ fn resolve_instance<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
) -> Result<Option<Instance<'tcx>>, ErrorReported> {
let (param_env, (def_id, substs)) = key.into_parts();
let (param_env, (did, substs)) = key.into_parts();
if let param_did @ Some(_) = did.as_local().and_then(|did| tcx.opt_const_param_of(did)) {
tcx.resolve_instance_of_const_arg(
param_env.and((ty::WithOptParam { did, param_did }, substs)),
)
} else {
inner_resolve_instance(tcx, param_env.and((ty::WithOptParam::dummy(did), substs)))
}
}
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
fn resolve_instance_of_const_arg<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, (ty::WithOptParam<DefId>, SubstsRef<'tcx>)>,
) -> Result<Option<Instance<'tcx>>, ErrorReported> {
let (param_env, (def, substs)) = key.into_parts();
if def.param_did.is_none() {
if let Some(did) = def.did.as_local() {
if let param_did @ Some(_) = tcx.opt_const_param_of(did) {
return tcx.resolve_instance_of_const_arg(
param_env.and((ty::WithOptParam { param_did, ..def }, substs)),
);
}
}
tcx.resolve_instance(param_env.and((def.did, substs)))
} else {
inner_resolve_instance(tcx, param_env.and((def, substs)))
}
}
fn inner_resolve_instance<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, (ty::WithOptParam<DefId>, SubstsRef<'tcx>)>,
) -> Result<Option<Instance<'tcx>>, ErrorReported> {
let (param_env, (def, substs)) = key.into_parts();
debug!("resolve(def={:?}, substs={:?})", def.did, substs);
let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
let item = tcx.associated_item(def_id);
let item = tcx.associated_item(def.did);
resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
} else {
let ty = tcx.type_of(def_id);
let ty = tcx.type_of(def.ty_def_id());
let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, &ty);
let def = match item_type.kind {
@ -33,7 +66,7 @@ fn resolve_instance<'tcx>(
} =>
{
debug!(" => intrinsic");
ty::InstanceDef::Intrinsic(def_id)
ty::InstanceDef::Intrinsic(def.did)
}
ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
let ty = substs.type_at(0);
@ -53,12 +86,12 @@ fn resolve_instance<'tcx>(
}
_ => {
debug!(" => free item");
ty::InstanceDef::Item(def_id)
ty::InstanceDef::Item(def.did)
}
};
Ok(Some(Instance { def, substs }))
};
debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result);
debug!("resolve(def.did={:?}, substs={:?}) = {:?}", def.did, substs, result);
result
}
@ -244,5 +277,6 @@ fn resolve_associated_item<'tcx>(
}
pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers { resolve_instance, ..*providers };
*providers =
ty::query::Providers { resolve_instance, resolve_instance_of_const_arg, ..*providers };
}

View File

@ -423,7 +423,10 @@ fn check_type_defn<'tcx, F>(
fcx.register_predicate(traits::Obligation::new(
cause,
fcx.param_env,
ty::PredicateKind::ConstEvaluatable(discr_def_id.to_def_id(), discr_substs)
ty::PredicateKind::ConstEvaluatable(
ty::WithOptParam::dummy(discr_def_id.to_def_id()),
discr_substs,
)
.to_predicate(fcx.tcx),
));
}

View File

@ -332,7 +332,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
let result = self
.lcx
.tcx
.const_eval_resolve(self.param_env, def_id, substs, None, None)
.const_eval_resolve(self.param_env, ty::WithOptParam::dummy(def_id), substs, None, None)
.ok()
.map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?;
let result = miri_to_const(&result);