summaryrefslogtreecommitdiff
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.rs91
1 files changed, 73 insertions, 18 deletions
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 64586a6782b..36a20c78fcc 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;
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};
@@ -27,8 +28,7 @@ fn resolve_instance<'tcx>(
)
} else {
let ty = tcx.type_of(def);
- let item_type =
- tcx.subst_and_normalize_erasing_regions(substs, param_env, ty.skip_binder());
+ 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) => {
@@ -85,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",
),
@@ -177,15 +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(generator_data.generator_def_id),
- substs: generator_data.substs,
- }),
- traits::ImplSource::Future(future_data) => Some(Instance {
- def: ty::InstanceDef::Item(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,
@@ -195,11 +232,29 @@ 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,
+ 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::FnPtrShim(trait_item_id, data.fn_ty),
+ substs: rcvr_substs,
+ })
+ }
+ _ => 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| {
@@ -265,6 +320,6 @@ fn resolve_associated_item<'tcx>(
})
}
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { resolve_instance, ..*providers };
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers { resolve_instance, ..*providers };
}