summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ty_utils/src/instance.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ty_utils/src/instance.rs')
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs149
1 files changed, 84 insertions, 65 deletions
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 0a6c11809..36a20c78f 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -1,6 +1,7 @@
use rustc_errors::ErrorGuaranteed;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::query::Providers;
use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt};
@@ -14,54 +15,25 @@ fn resolve_instance<'tcx>(
tcx: TyCtxt<'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)))
-}
-
-fn resolve_instance_of_const_arg<'tcx>(
- tcx: TyCtxt<'tcx>,
- key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)>,
-) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
- let (param_env, (did, const_param_did, substs)) = key.into_parts();
- inner_resolve_instance(
- tcx,
- param_env.and((
- ty::WithOptConstParam { did: did.to_def_id(), const_param_did: Some(const_param_did) },
- substs,
- )),
- )
-}
-
-fn inner_resolve_instance<'tcx>(
- tcx: TyCtxt<'tcx>,
- key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
-) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
let (param_env, (def, substs)) = key.into_parts();
- let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
+ let result = if let Some(trait_def_id) = tcx.trait_of_item(def) {
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
resolve_associated_item(
tcx,
- def.did,
+ def,
param_env,
trait_def_id,
tcx.normalize_erasing_regions(param_env, substs),
)
} else {
- let ty = tcx.type_of(def.def_id_for_type_of());
- let item_type =
- tcx.subst_and_normalize_erasing_regions(substs, param_env, ty.skip_binder());
+ let ty = tcx.type_of(def);
+ let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
let def = match *item_type.kind() {
ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => {
debug!(" => intrinsic");
- ty::InstanceDef::Intrinsic(def.did)
+ ty::InstanceDef::Intrinsic(def)
}
ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
let ty = substs.type_at(0);
@@ -113,7 +85,7 @@ fn resolve_associated_item<'tcx>(
Err(CodegenObligationError::Ambiguity) => {
let reported = tcx.sess.delay_span_bug(
tcx.def_span(trait_item_id),
- &format!(
+ format!(
"encountered ambiguity selecting `{trait_ref:?}` during codegen, presuming due to \
overflow or prior type error",
),
@@ -132,8 +104,8 @@ fn resolve_associated_item<'tcx>(
"resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}",
param_env, trait_item_id, rcvr_substs, impl_data
);
- assert!(!rcvr_substs.needs_infer());
- assert!(!trait_ref.needs_infer());
+ assert!(!rcvr_substs.has_infer());
+ assert!(!trait_ref.has_infer());
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
let trait_def = tcx.trait_def(trait_def_id);
@@ -205,19 +177,52 @@ fn resolve_associated_item<'tcx>(
Some(ty::Instance::new(leaf_def.item.def_id, substs))
}
- traits::ImplSource::Generator(generator_data) => Some(Instance {
- def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
- generator_data.generator_def_id,
- )),
- substs: generator_data.substs,
- }),
- traits::ImplSource::Future(future_data) => Some(Instance {
- def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
- future_data.generator_def_id,
- )),
- substs: future_data.substs,
- }),
+ traits::ImplSource::Generator(generator_data) => {
+ if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume {
+ // For compiler developers who'd like to add new items to `Generator`,
+ // you either need to generate a shim body, or perhaps return
+ // `InstanceDef::Item` pointing to a trait default method body if
+ // it is given a default implementation by the trait.
+ span_bug!(
+ tcx.def_span(generator_data.generator_def_id),
+ "no definition for `{trait_ref}::{}` for built-in generator type",
+ tcx.item_name(trait_item_id)
+ )
+ }
+ Some(Instance {
+ def: ty::InstanceDef::Item(generator_data.generator_def_id),
+ substs: generator_data.substs,
+ })
+ }
+ traits::ImplSource::Future(future_data) => {
+ if Some(trait_item_id) == tcx.lang_items().future_poll_fn() {
+ // `Future::poll` is generated by the compiler.
+ Some(Instance {
+ def: ty::InstanceDef::Item(future_data.generator_def_id),
+ substs: future_data.substs,
+ })
+ } else {
+ // All other methods are default methods of the `Future` trait.
+ // (this assumes that `ImplSource::Future` is only used for methods on `Future`)
+ debug_assert!(tcx.impl_defaultness(trait_item_id).has_value());
+ Some(Instance::new(trait_item_id, rcvr_substs))
+ }
+ }
traits::ImplSource::Closure(closure_data) => {
+ if cfg!(debug_assertions)
+ && ![sym::call, sym::call_mut, sym::call_once]
+ .contains(&tcx.item_name(trait_item_id))
+ {
+ // For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`,
+ // you either need to generate a shim body, or perhaps return
+ // `InstanceDef::Item` pointing to a trait default method body if
+ // it is given a default implementation by the trait.
+ span_bug!(
+ tcx.def_span(closure_data.closure_def_id),
+ "no definition for `{trait_ref}::{}` for built-in closure type",
+ tcx.item_name(trait_item_id)
+ )
+ }
let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap();
Instance::resolve_closure(
tcx,
@@ -227,22 +232,37 @@ fn resolve_associated_item<'tcx>(
)
}
traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() {
- ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
- def: ty::InstanceDef::FnPtrShim(trait_item_id, data.fn_ty),
- substs: rcvr_substs,
- }),
- _ => None,
- },
- traits::ImplSource::Object(ref data) => {
- if let Some(index) = traits::get_vtable_index_of_object_method(tcx, data, trait_item_id)
- {
+ ty::FnDef(..) | ty::FnPtr(..) => {
+ if cfg!(debug_assertions)
+ && ![sym::call, sym::call_mut, sym::call_once]
+ .contains(&tcx.item_name(trait_item_id))
+ {
+ // For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`,
+ // you either need to generate a shim body, or perhaps return
+ // `InstanceDef::Item` pointing to a trait default method body if
+ // it is given a default implementation by the trait.
+ bug!(
+ "no definition for `{trait_ref}::{}` for built-in fn type",
+ tcx.item_name(trait_item_id)
+ )
+ }
Some(Instance {
- def: ty::InstanceDef::Virtual(trait_item_id, index),
+ def: ty::InstanceDef::FnPtrShim(trait_item_id, data.fn_ty),
substs: rcvr_substs,
})
- } else {
- None
}
+ _ => bug!(
+ "no built-in definition for `{trait_ref}::{}` for non-fn type",
+ tcx.item_name(trait_item_id)
+ ),
+ },
+ traits::ImplSource::Object(ref data) => {
+ traits::get_vtable_index_of_object_method(tcx, data, trait_item_id).map(|index| {
+ Instance {
+ def: ty::InstanceDef::Virtual(trait_item_id, index),
+ substs: rcvr_substs,
+ }
+ })
}
traits::ImplSource::Builtin(..) => {
let lang_items = tcx.lang_items();
@@ -300,7 +320,6 @@ fn resolve_associated_item<'tcx>(
})
}
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers =
- ty::query::Providers { resolve_instance, resolve_instance_of_const_arg, ..*providers };
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers { resolve_instance, ..*providers };
}