提交 2e6bf092 编写于 作者: B Bastian Kauschke

const_eval_resolve

上级 58031c7c
......@@ -28,7 +28,7 @@ pub fn eval_mir_constant(
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 @@ pub fn create_next_universe(&self) -> ty::UniverseIndex {
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 @@ pub fn const_eval_resolve(
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 @@ pub fn const_eval_poly(self, def_id: DefId) -> ConstEvalResult<'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 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
) -> 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 @@ pub fn resolve(
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>,
......
......@@ -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 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
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 @@ pub fn print_only_trait_path(self) -> ty::Binder<TraitRefPrintOnlyTraitPath<'tcx
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 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
}
}
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 @@ pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'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 @@ fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location)
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 @@ fn process_obligation(
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 @@ fn evaluate_predicate_recursively<'o>(
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 @@ fn compute(&mut self, arg: GenericArg<'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)))
}
}
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_id={:?}, substs={:?})", def_id, substs);
let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
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,8 +423,11 @@ 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)
.to_predicate(fcx.tcx),
ty::PredicateKind::ConstEvaluatable(
ty::WithOptParam::dummy(discr_def_id.to_def_id()),
discr_substs,
)
.to_predicate(fcx.tcx),
));
}
}
......
......@@ -332,7 +332,7 @@ fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option<C
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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册