Feed type_of query instead of using WithOptconstParam.

This commit is contained in:
Camille GILLOT 2023-02-19 10:02:00 +00:00
parent 4224b4b1f5
commit 0e017fc94a
7 changed files with 40 additions and 39 deletions

View file

@ -447,14 +447,9 @@ fn provided_kind(
handle_ty_args(has_default, &inf.to_ty())
}
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
ty::Const::from_opt_const_arg_anon_const(
tcx,
ty::WithOptConstParam {
did: ct.value.def_id,
const_param_did: Some(param.def_id),
},
)
.into()
let did = ct.value.def_id;
tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
ty::Const::from_anon_const(tcx, did).into()
}
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
let ty = tcx

View file

@ -420,9 +420,9 @@ pub fn const_arg_to_const(
ast_c: &hir::AnonConst,
param_def_id: DefId,
) -> ty::Const<'tcx> {
let const_def =
ty::WithOptConstParam { did: ast_c.def_id, const_param_did: Some(param_def_id) };
let c = ty::Const::from_opt_const_arg_anon_const(self.tcx, const_def);
let did = ast_c.def_id;
self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id));
let c = ty::Const::from_anon_const(self.tcx, did);
self.register_wf_obligation(
c.into(),
self.tcx.hir().span(ast_c.hir_id),

View file

@ -165,12 +165,8 @@ fn typeck_const_arg<'tcx>(
}
fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
if let Some(param_did) = tcx.opt_const_param_of(def_id) {
tcx.typeck_const_arg((def_id, param_did))
} else {
let fallback = move || tcx.type_of(def_id.to_def_id()).subst_identity();
typeck_with_fallback(tcx, def_id, fallback)
}
let fallback = move || tcx.type_of(def_id.to_def_id()).subst_identity();
typeck_with_fallback(tcx, def_id, fallback)
}
/// Used only to get `TypeckResults` for type inference during error recovery.

View file

@ -449,6 +449,14 @@ pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> {
pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
}
/// In order to break cycles involving `AnonConst`, we need to set the expected type by side
/// effect. However, we do not want this as a general capability, so this interface restricts
/// to the only allowed case.
pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<Ty<'tcx>>) {
debug_assert_eq!(self.def_kind(key), DefKind::AnonConst);
TyCtxtFeed { tcx: self, key }.type_of(value)
}
}
impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {

View file

@ -1548,20 +1548,14 @@ impl WithOptConstParam<LocalDefId> {
/// Returns `Some((did, param_did))` if `def_id` is a const argument,
/// `None` otherwise.
#[inline(always)]
pub fn try_lookup(did: LocalDefId, tcx: TyCtxt<'_>) -> Option<(LocalDefId, DefId)> {
tcx.opt_const_param_of(did).map(|param_did| (did, param_did))
pub fn try_lookup(_: LocalDefId, _: TyCtxt<'_>) -> Option<(LocalDefId, DefId)> {
None
}
/// In case `self` is unknown but `self.did` is a const argument, this returns
/// a `WithOptConstParam` with the correct `const_param_did`.
#[inline(always)]
pub fn try_upgrade(self, tcx: TyCtxt<'_>) -> Option<WithOptConstParam<LocalDefId>> {
if self.const_param_did.is_none() {
if let const_param_did @ Some(_) = tcx.opt_const_param_of(self.did) {
return Some(WithOptConstParam { did: self.did, const_param_did });
}
}
pub fn try_upgrade(self, _: TyCtxt<'_>) -> Option<WithOptConstParam<LocalDefId>> {
None
}
@ -1570,7 +1564,7 @@ pub fn to_global(self) -> WithOptConstParam<DefId> {
}
pub fn def_id_for_type_of(self) -> DefId {
if let Some(did) = self.const_param_did { did } else { self.did.to_def_id() }
self.did.to_def_id()
}
}

View file

@ -76,6 +76,9 @@
use std::path::PathBuf;
use std::sync::Arc;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_query_system::ich::StableHashingContext;
#[derive(Default)]
pub struct QuerySystem<'tcx> {
pub arenas: QueryArenas<'tcx>,
@ -477,7 +480,7 @@ macro_rules! define_feedable {
$(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
$(#[$attr])*
#[inline(always)]
pub fn $name(self, value: query_provided::$name<'tcx>) -> $V {
pub fn $name(self, value: query_provided::$name<'tcx>) {
let key = self.key().into_query_param();
let tcx = self.tcx;
@ -485,13 +488,25 @@ pub fn $name(self, value: query_provided::$name<'tcx>) -> $V {
let value = restore::<$V>(erased);
let cache = &tcx.query_system.caches.$name;
let hasher: Option<fn(&mut StableHashingContext<'_>, &_) -> _> = hash_result!([$($modifiers)*]);
match try_get_cached(tcx, cache, &key) {
Some(old) => {
let old = restore::<$V>(old);
bug!(
"Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
stringify!($name),
)
if let Some(hasher) = hasher {
let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx.with_stable_hashing_context(|mut hcx|
(hasher(&mut hcx, &value), hasher(&mut hcx, &old))
);
assert_eq!(
old_hash, value_hash,
"Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
stringify!($name),
)
} else {
bug!(
"Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
stringify!($name),
)
}
}
None => {
let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
@ -503,7 +518,6 @@ pub fn $name(self, value: query_provided::$name<'tcx>) -> $V {
hash_result!([$($modifiers)*]),
);
cache.complete(key, erased, dep_node_index);
value
}
}
}

View file

@ -15,12 +15,6 @@ fn resolve_instance<'tcx>(
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
let (param_env, (did, substs)) = key.into_parts();
if let Some(did) = did.as_local() {
if let Some(param_did) = tcx.opt_const_param_of(did) {
return tcx.resolve_instance_of_const_arg(param_env.and((did, param_did, substs)));
}
}
inner_resolve_instance(tcx, param_env.and((ty::WithOptConstParam::unknown(did), substs)))
}