mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-21 04:03:11 +00:00
const_eval_resolve
This commit is contained in:
parent
58031c7cb2
commit
2e6bf0923b
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -336,6 +336,17 @@ impl<'tcx> Instance<'tcx> {
|
||||
tcx.resolve_instance(tcx.erase_regions(¶m_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(¶m_env.and((def, substs))))
|
||||
}
|
||||
|
||||
pub fn resolve_for_fn_ptr(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
@ -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> {
|
||||
|
@ -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) => {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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!(
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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(
|
||||
|
@ -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 };
|
||||
}
|
||||
|
@ -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),
|
||||
));
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user