Remove even more redundant builtin candidates

This commit is contained in:
Michael Goulet 2023-06-16 02:10:10 +00:00
parent 2835d9d1d3
commit d97d4ebecc
6 changed files with 96 additions and 138 deletions

View file

@ -177,83 +177,6 @@ fn resolve_associated_item<'tcx>(
Some(ty::Instance::new(leaf_def.item.def_id, substs))
}
traits::ImplSource::Generator(_) => {
let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else {
unreachable!()
};
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_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_def_id), substs })
}
traits::ImplSource::Future(_) => {
let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else {
unreachable!()
};
if Some(trait_item_id) == tcx.lang_items().future_poll_fn() {
// `Future::poll` is generated by the compiler.
Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs: 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.defaultness(trait_item_id).has_value());
Some(Instance::new(trait_item_id, rcvr_substs))
}
}
traits::ImplSource::Closure(_) => {
let ty::Closure(closure_def_id, substs) = *rcvr_substs.type_at(0).kind() else {
unreachable!()
};
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_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, closure_def_id, substs, trait_closure_kind)
}
traits::ImplSource::FnPointer(_) => match rcvr_substs.type_at(0).kind() {
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, rcvr_substs.type_at(0)),
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| {
Instance {
@ -306,6 +229,66 @@ fn resolve_associated_item<'tcx>(
span: tcx.def_span(trait_item_id),
})
}
} else if Some(trait_ref.def_id) == lang_items.future_trait() {
let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else {
bug!()
};
if Some(trait_item_id) == tcx.lang_items().future_poll_fn() {
// `Future::poll` is generated by the compiler.
Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs: substs })
} else {
// All other methods are default methods of the `Future` trait.
// (this assumes that `ImplSource::Builtin` is only used for methods on `Future`)
debug_assert!(tcx.defaultness(trait_item_id).has_value());
Some(Instance::new(trait_item_id, rcvr_substs))
}
} else if Some(trait_ref.def_id) == lang_items.gen_trait() {
let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else {
bug!()
};
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_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_def_id), substs })
} else if tcx.fn_trait_kind_from_def_id(trait_ref.def_id).is_some() {
// FIXME: This doesn't check for malformed libcore that defines, e.g.,
// `trait Fn { fn call_once(&self) { .. } }`. This is mostly for extension
// methods.
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 callable type",
tcx.item_name(trait_item_id)
)
}
match *rcvr_substs.type_at(0).kind() {
ty::Closure(closure_def_id, substs) => {
let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap();
Instance::resolve_closure(tcx, closure_def_id, substs, trait_closure_kind)
}
ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_substs.type_at(0)),
substs: rcvr_substs,
}),
_ => bug!(
"no built-in definition for `{trait_ref}::{}` for non-fn type",
tcx.item_name(trait_item_id)
),
}
} else {
None
}