1
Fork 0

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

@ -781,7 +781,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
); );
return; return;
} }
Ok(Some(ImplSource::Closure(_))) => { // Closure: Fn{Once|Mut}
Ok(Some(ImplSource::Builtin(_)))
if poly_trait_pred.self_ty().skip_binder().is_closure()
&& tcx.fn_trait_kind_from_def_id(trait_id).is_some() =>
{
let ty::Closure(closure_def_id, substs) = let ty::Closure(closure_def_id, substs) =
*poly_trait_pred.self_ty().no_bound_vars().unwrap().kind() *poly_trait_pred.self_ty().no_bound_vars().unwrap().kind()
else { else {

View file

@ -661,20 +661,6 @@ pub enum ImplSource<'tcx, N> {
/// ImplSource for trait upcasting coercion /// ImplSource for trait upcasting coercion
TraitUpcasting(ImplSourceTraitUpcastingData<N>), TraitUpcasting(ImplSourceTraitUpcastingData<N>),
/// ImplSource automatically generated for a closure. The `DefId` is the ID
/// of the closure expression. This is an `ImplSource::UserDefined` in spirit, but the
/// impl is generated by the compiler and does not appear in the source.
Closure(Vec<N>),
/// Same as above, but for a function pointer type with the given signature.
FnPointer(Vec<N>),
/// ImplSource automatically generated for a generator.
Generator(Vec<N>),
/// ImplSource automatically generated for a generator backing an async future.
Future(Vec<N>),
/// ImplSource for a trait alias. /// ImplSource for a trait alias.
TraitAlias(ImplSourceTraitAliasData<'tcx, N>), TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
} }
@ -683,12 +669,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
pub fn nested_obligations(self) -> Vec<N> { pub fn nested_obligations(self) -> Vec<N> {
match self { match self {
ImplSource::UserDefined(i) => i.nested, ImplSource::UserDefined(i) => i.nested,
ImplSource::Param(n, _) ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
| ImplSource::Builtin(n)
| ImplSource::FnPointer(n)
| ImplSource::Closure(n)
| ImplSource::Generator(n)
| ImplSource::Future(n) => n,
ImplSource::Object(d) => d.nested, ImplSource::Object(d) => d.nested,
ImplSource::TraitAlias(d) => d.nested, ImplSource::TraitAlias(d) => d.nested,
ImplSource::TraitUpcasting(d) => d.nested, ImplSource::TraitUpcasting(d) => d.nested,
@ -698,12 +679,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
pub fn borrow_nested_obligations(&self) -> &[N] { pub fn borrow_nested_obligations(&self) -> &[N] {
match self { match self {
ImplSource::UserDefined(i) => &i.nested, ImplSource::UserDefined(i) => &i.nested,
ImplSource::Param(n, _) ImplSource::Param(n, _) | ImplSource::Builtin(n) => &n,
| ImplSource::Builtin(n)
| ImplSource::FnPointer(n)
| ImplSource::Closure(n)
| ImplSource::Generator(n)
| ImplSource::Future(n) => &n,
ImplSource::Object(d) => &d.nested, ImplSource::Object(d) => &d.nested,
ImplSource::TraitAlias(d) => &d.nested, ImplSource::TraitAlias(d) => &d.nested,
ImplSource::TraitUpcasting(d) => &d.nested, ImplSource::TraitUpcasting(d) => &d.nested,
@ -713,12 +689,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] { pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] {
match self { match self {
ImplSource::UserDefined(i) => &mut i.nested, ImplSource::UserDefined(i) => &mut i.nested,
ImplSource::Param(n, _) ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
| ImplSource::Builtin(n)
| ImplSource::FnPointer(n)
| ImplSource::Closure(n)
| ImplSource::Generator(n)
| ImplSource::Future(n) => n,
ImplSource::Object(d) => &mut d.nested, ImplSource::Object(d) => &mut d.nested,
ImplSource::TraitAlias(d) => &mut d.nested, ImplSource::TraitAlias(d) => &mut d.nested,
ImplSource::TraitUpcasting(d) => &mut d.nested, ImplSource::TraitUpcasting(d) => &mut d.nested,
@ -742,10 +713,6 @@ impl<'tcx, N> ImplSource<'tcx, N> {
vtable_base: o.vtable_base, vtable_base: o.vtable_base,
nested: o.nested.into_iter().map(f).collect(), nested: o.nested.into_iter().map(f).collect(),
}), }),
ImplSource::Closure(n) => ImplSource::Closure(n.into_iter().map(f).collect()),
ImplSource::Generator(n) => ImplSource::Generator(n.into_iter().map(f).collect()),
ImplSource::Future(n) => ImplSource::Future(n.into_iter().map(f).collect()),
ImplSource::FnPointer(n) => ImplSource::FnPointer(n.into_iter().map(f).collect()),
ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData { ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData {
alias_def_id: d.alias_def_id, alias_def_id: d.alias_def_id,
substs: d.substs, substs: d.substs,

View file

@ -9,13 +9,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
match *self { match *self {
super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v), super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v),
super::ImplSource::Closure(ref d) => write!(f, "{:?}", d), super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d),
super::ImplSource::Generator(ref d) => write!(f, "{:?}", d),
super::ImplSource::Future(ref d) => write!(f, "{:?}", d),
super::ImplSource::FnPointer(ref d) => write!(f, "({:?})", d),
super::ImplSource::Object(ref d) => write!(f, "{:?}", d), super::ImplSource::Object(ref d) => write!(f, "{:?}", d),
@ -23,8 +17,6 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
write!(f, "ImplSourceParamData({:?}, {:?})", n, ct) write!(f, "ImplSourceParamData({:?}, {:?})", n, ct)
} }
super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d),
super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d), super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d),
super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d), super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),

View file

@ -1717,11 +1717,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
}; };
let eligible = match &impl_source { let eligible = match &impl_source {
super::ImplSource::Closure(_) super::ImplSource::TraitAlias(_) => true,
| super::ImplSource::Generator(_)
| super::ImplSource::Future(_)
| super::ImplSource::FnPointer(_)
| super::ImplSource::TraitAlias(_) => true,
super::ImplSource::UserDefined(impl_data) => { super::ImplSource::UserDefined(impl_data) => {
// We have to be careful when projecting out of an // We have to be careful when projecting out of an
// impl because of specialization. If we are not in // impl because of specialization. If we are not in
@ -1779,7 +1775,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
let lang_items = selcx.tcx().lang_items(); let lang_items = selcx.tcx().lang_items();
if lang_items.discriminant_kind_trait() == Some(poly_trait_ref.def_id()) { if [lang_items.gen_trait(), lang_items.future_trait()].contains(&Some(poly_trait_ref.def_id()))
|| selcx.tcx().fn_trait_kind_from_def_id(poly_trait_ref.def_id()).is_some()
{
true
} else if lang_items.discriminant_kind_trait() == Some(poly_trait_ref.def_id()) {
match self_ty.kind() { match self_ty.kind() {
ty::Bool ty::Bool
| ty::Char | ty::Char
@ -1990,11 +1990,23 @@ fn confirm_select_candidate<'cx, 'tcx>(
) -> Progress<'tcx> { ) -> Progress<'tcx> {
match impl_source { match impl_source {
super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data), super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
super::ImplSource::Generator(data) => confirm_generator_candidate(selcx, obligation, data), super::ImplSource::Builtin(data) => {
super::ImplSource::Future(data) => confirm_future_candidate(selcx, obligation, data), let trait_def_id = obligation.predicate.trait_def_id(selcx.tcx());
super::ImplSource::Closure(data) => confirm_closure_candidate(selcx, obligation, data), let lang_items = selcx.tcx().lang_items();
super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data), if lang_items.gen_trait() == Some(trait_def_id) {
super::ImplSource::Builtin(data) => confirm_builtin_candidate(selcx, obligation, data), confirm_generator_candidate(selcx, obligation, data)
} else if lang_items.future_trait() == Some(trait_def_id) {
confirm_future_candidate(selcx, obligation, data)
} else if selcx.tcx().fn_trait_kind_from_def_id(trait_def_id).is_some() {
if obligation.predicate.self_ty().is_closure() {
confirm_closure_candidate(selcx, obligation, data)
} else {
confirm_fn_pointer_candidate(selcx, obligation, data)
}
} else {
confirm_builtin_candidate(selcx, obligation, data)
}
}
super::ImplSource::Object(_) super::ImplSource::Object(_)
| super::ImplSource::Param(..) | super::ImplSource::Param(..)
| super::ImplSource::TraitUpcasting(_) | super::ImplSource::TraitUpcasting(_)

View file

@ -85,22 +85,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ClosureCandidate { .. } => { ClosureCandidate { .. } => {
let vtable_closure = self.confirm_closure_candidate(obligation)?; let vtable_closure = self.confirm_closure_candidate(obligation)?;
ImplSource::Closure(vtable_closure) ImplSource::Builtin(vtable_closure)
} }
GeneratorCandidate => { GeneratorCandidate => {
let vtable_generator = self.confirm_generator_candidate(obligation)?; let vtable_generator = self.confirm_generator_candidate(obligation)?;
ImplSource::Generator(vtable_generator) ImplSource::Builtin(vtable_generator)
} }
FutureCandidate => { FutureCandidate => {
let vtable_future = self.confirm_future_candidate(obligation)?; let vtable_future = self.confirm_future_candidate(obligation)?;
ImplSource::Future(vtable_future) ImplSource::Builtin(vtable_future)
} }
FnPointerCandidate { is_const } => { FnPointerCandidate { is_const } => {
let data = self.confirm_fn_pointer_candidate(obligation, is_const)?; let data = self.confirm_fn_pointer_candidate(obligation, is_const)?;
ImplSource::FnPointer(data) ImplSource::Builtin(data)
} }
TraitAliasCandidate => { TraitAliasCandidate => {

View file

@ -177,83 +177,6 @@ fn resolve_associated_item<'tcx>(
Some(ty::Instance::new(leaf_def.item.def_id, substs)) 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::ImplSource::Object(ref data) => {
traits::get_vtable_index_of_object_method(tcx, data, trait_item_id).map(|index| { traits::get_vtable_index_of_object_method(tcx, data, trait_item_id).map(|index| {
Instance { Instance {
@ -306,6 +229,66 @@ fn resolve_associated_item<'tcx>(
span: tcx.def_span(trait_item_id), 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 { } else {
None None
} }