about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-17 06:26:55 +0000
committerbors <bors@rust-lang.org>2023-06-17 06:26:55 +0000
commitf90d57d06ebc7f250b60b9cab583f111d9a5fb9d (patch)
tree700356c39dce158d2b3c87d9593766137140fb14
parent1d7d82472617a4a0fea59c7e239c8a48c8ac5c34 (diff)
parentd97d4ebecc502bcb5eda2cdaa513e0e7922a377e (diff)
downloadrust-f90d57d06ebc7f250b60b9cab583f111d9a5fb9d.tar.gz
rust-f90d57d06ebc7f250b60b9cab583f111d9a5fb9d.zip
Auto merge of #112687 - compiler-errors:simplify-impl-source, r=lcnr
Simplify `ImplSource` candidates a bit

Reduce the number of impl source candidates, which will hopefully make our life easier when trying to adapt things like `SelectionContext::select` and `codegen_select_candidate` for the new solver.

r? `@lcnr` but feel free to reassign
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs13
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs2
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs156
-rw-r--r--compiler/rustc_middle/src/traits/structural_impls.rs82
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs91
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs77
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs4
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs145
8 files changed, 186 insertions, 384 deletions
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 57d939747aa..106cf111474 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -781,8 +781,17 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                             );
                             return;
                         }
-                        Ok(Some(ImplSource::Closure(data))) => {
-                            if !tcx.is_const_fn_raw(data.closure_def_id) {
+                        // 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) =
+                                *poly_trait_pred.self_ty().no_bound_vars().unwrap().kind()
+                            else {
+                                unreachable!()
+                            };
+                            if !tcx.is_const_fn_raw(closure_def_id) {
                                 self.check_op(ops::FnCallNonConst {
                                     caller,
                                     callee,
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 1da20579021..a2d23425f3b 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -172,7 +172,7 @@ impl Qualif for NeedsNonConstDrop {
 
         if !matches!(
             impl_src,
-            ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
+            ImplSource::Builtin(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
         ) {
             // If our const destruct candidate is not ConstDestruct or implied by the param env,
             // then it's bad
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index b63e049a520..492b7228488 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -646,12 +646,6 @@ pub enum ImplSource<'tcx, N> {
     /// ImplSource identifying a particular impl.
     UserDefined(ImplSourceUserDefinedData<'tcx, N>),
 
-    /// ImplSource for auto trait implementations.
-    /// This carries the information and nested obligations with regards
-    /// to an auto implementation for a trait `Trait`. The nested obligations
-    /// ensure the trait implementation holds for all the constituent types.
-    AutoImpl(ImplSourceAutoImplData<N>),
-
     /// Successful resolution to an obligation provided by the caller
     /// for some type parameter. The `Vec<N>` represents the
     /// obligations incurred from normalizing the where-clause (if
@@ -659,84 +653,46 @@ pub enum ImplSource<'tcx, N> {
     Param(Vec<N>, ty::BoundConstness),
 
     /// Virtual calls through an object.
-    Object(ImplSourceObjectData<'tcx, N>),
+    Object(ImplSourceObjectData<N>),
 
     /// Successful resolution for a builtin trait.
-    Builtin(ImplSourceBuiltinData<N>),
+    Builtin(Vec<N>),
 
     /// ImplSource for trait upcasting coercion
-    TraitUpcasting(ImplSourceTraitUpcastingData<'tcx, 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(ImplSourceClosureData<'tcx, N>),
-
-    /// Same as above, but for a function pointer type with the given signature.
-    FnPointer(ImplSourceFnPointerData<'tcx, N>),
-
-    /// ImplSource automatically generated for a generator.
-    Generator(ImplSourceGeneratorData<'tcx, N>),
-
-    /// ImplSource automatically generated for a generator backing an async future.
-    Future(ImplSourceFutureData<'tcx, N>),
+    TraitUpcasting(ImplSourceTraitUpcastingData<N>),
 
     /// ImplSource for a trait alias.
     TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
-
-    /// ImplSource for a `const Drop` implementation.
-    ConstDestruct(ImplSourceConstDestructData<N>),
 }
 
 impl<'tcx, N> ImplSource<'tcx, N> {
     pub fn nested_obligations(self) -> Vec<N> {
         match self {
             ImplSource::UserDefined(i) => i.nested,
-            ImplSource::Param(n, _) => n,
-            ImplSource::Builtin(i) => i.nested,
-            ImplSource::AutoImpl(d) => d.nested,
-            ImplSource::Closure(c) => c.nested,
-            ImplSource::Generator(c) => c.nested,
-            ImplSource::Future(c) => c.nested,
+            ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
             ImplSource::Object(d) => d.nested,
-            ImplSource::FnPointer(d) => d.nested,
             ImplSource::TraitAlias(d) => d.nested,
             ImplSource::TraitUpcasting(d) => d.nested,
-            ImplSource::ConstDestruct(i) => i.nested,
         }
     }
 
     pub fn borrow_nested_obligations(&self) -> &[N] {
         match self {
             ImplSource::UserDefined(i) => &i.nested,
-            ImplSource::Param(n, _) => n,
-            ImplSource::Builtin(i) => &i.nested,
-            ImplSource::AutoImpl(d) => &d.nested,
-            ImplSource::Closure(c) => &c.nested,
-            ImplSource::Generator(c) => &c.nested,
-            ImplSource::Future(c) => &c.nested,
+            ImplSource::Param(n, _) | ImplSource::Builtin(n) => &n,
             ImplSource::Object(d) => &d.nested,
-            ImplSource::FnPointer(d) => &d.nested,
             ImplSource::TraitAlias(d) => &d.nested,
             ImplSource::TraitUpcasting(d) => &d.nested,
-            ImplSource::ConstDestruct(i) => &i.nested,
         }
     }
 
     pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] {
         match self {
             ImplSource::UserDefined(i) => &mut i.nested,
-            ImplSource::Param(n, _) => n,
-            ImplSource::Builtin(i) => &mut i.nested,
-            ImplSource::AutoImpl(d) => &mut d.nested,
-            ImplSource::Closure(c) => &mut c.nested,
-            ImplSource::Generator(c) => &mut c.nested,
-            ImplSource::Future(c) => &mut c.nested,
+            ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
             ImplSource::Object(d) => &mut d.nested,
-            ImplSource::FnPointer(d) => &mut d.nested,
             ImplSource::TraitAlias(d) => &mut d.nested,
             ImplSource::TraitUpcasting(d) => &mut d.nested,
-            ImplSource::ConstDestruct(i) => &mut i.nested,
         }
     }
 
@@ -751,37 +707,12 @@ impl<'tcx, N> ImplSource<'tcx, N> {
                 nested: i.nested.into_iter().map(f).collect(),
             }),
             ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct),
-            ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData {
-                nested: i.nested.into_iter().map(f).collect(),
-            }),
+            ImplSource::Builtin(n) => ImplSource::Builtin(n.into_iter().map(f).collect()),
             ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData {
-                upcast_trait_ref: o.upcast_trait_ref,
+                upcast_trait_def_id: o.upcast_trait_def_id,
                 vtable_base: o.vtable_base,
                 nested: o.nested.into_iter().map(f).collect(),
             }),
-            ImplSource::AutoImpl(d) => ImplSource::AutoImpl(ImplSourceAutoImplData {
-                trait_def_id: d.trait_def_id,
-                nested: d.nested.into_iter().map(f).collect(),
-            }),
-            ImplSource::Closure(c) => ImplSource::Closure(ImplSourceClosureData {
-                closure_def_id: c.closure_def_id,
-                substs: c.substs,
-                nested: c.nested.into_iter().map(f).collect(),
-            }),
-            ImplSource::Generator(c) => ImplSource::Generator(ImplSourceGeneratorData {
-                generator_def_id: c.generator_def_id,
-                substs: c.substs,
-                nested: c.nested.into_iter().map(f).collect(),
-            }),
-            ImplSource::Future(c) => ImplSource::Future(ImplSourceFutureData {
-                generator_def_id: c.generator_def_id,
-                substs: c.substs,
-                nested: c.nested.into_iter().map(f).collect(),
-            }),
-            ImplSource::FnPointer(p) => ImplSource::FnPointer(ImplSourceFnPointerData {
-                fn_ty: p.fn_ty,
-                nested: p.nested.into_iter().map(f).collect(),
-            }),
             ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData {
                 alias_def_id: d.alias_def_id,
                 substs: d.substs,
@@ -789,16 +720,10 @@ impl<'tcx, N> ImplSource<'tcx, N> {
             }),
             ImplSource::TraitUpcasting(d) => {
                 ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData {
-                    upcast_trait_ref: d.upcast_trait_ref,
                     vtable_vptr_slot: d.vtable_vptr_slot,
                     nested: d.nested.into_iter().map(f).collect(),
                 })
             }
-            ImplSource::ConstDestruct(i) => {
-                ImplSource::ConstDestruct(ImplSourceConstDestructData {
-                    nested: i.nested.into_iter().map(f).collect(),
-                })
-            }
         }
     }
 }
@@ -823,47 +748,7 @@ pub struct ImplSourceUserDefinedData<'tcx, N> {
 
 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
 #[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceGeneratorData<'tcx, N> {
-    pub generator_def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
-    /// Nested obligations. This can be non-empty if the generator
-    /// signature contains associated types.
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceFutureData<'tcx, N> {
-    pub generator_def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
-    /// Nested obligations. This can be non-empty if the generator
-    /// signature contains associated types.
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceClosureData<'tcx, N> {
-    pub closure_def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
-    /// Nested obligations. This can be non-empty if the closure
-    /// signature contains associated types.
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceAutoImplData<N> {
-    pub trait_def_id: DefId,
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceTraitUpcastingData<'tcx, N> {
-    /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
-    pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
-
+pub struct ImplSourceTraitUpcastingData<N> {
     /// The vtable is formed by concatenating together the method lists of
     /// the base object trait and all supertraits, pointers to supertrait vtable will
     /// be provided when necessary; this is the position of `upcast_trait_ref`'s vtable
@@ -873,17 +758,11 @@ pub struct ImplSourceTraitUpcastingData<'tcx, N> {
     pub nested: Vec<N>,
 }
 
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceBuiltinData<N> {
-    pub nested: Vec<N>,
-}
-
 #[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, Lift)]
 #[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceObjectData<'tcx, N> {
+pub struct ImplSourceObjectData<N> {
     /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
-    pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
+    pub upcast_trait_def_id: DefId,
 
     /// The vtable is formed by concatenating together the method lists of
     /// the base object trait and all supertraits, pointers to supertrait vtable will
@@ -896,19 +775,6 @@ pub struct ImplSourceObjectData<'tcx, N> {
 
 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
 #[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceFnPointerData<'tcx, N> {
-    pub fn_ty: Ty<'tcx>,
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceConstDestructData<N> {
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
 pub struct ImplSourceTraitAliasData<'tcx, N> {
     pub alias_def_id: DefId,
     pub substs: SubstsRef<'tcx>,
diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs
index 6acb7745d65..ac02d6ed62f 100644
--- a/compiler/rustc_middle/src/traits/structural_impls.rs
+++ b/compiler/rustc_middle/src/traits/structural_impls.rs
@@ -9,15 +9,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
         match *self {
             super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v),
 
-            super::ImplSource::AutoImpl(ref t) => write!(f, "{:?}", t),
-
-            super::ImplSource::Closure(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::Builtin(ref d) => write!(f, "{:?}", d),
 
             super::ImplSource::Object(ref d) => write!(f, "{:?}", d),
 
@@ -25,13 +17,9 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
                 write!(f, "ImplSourceParamData({:?}, {:?})", n, ct)
             }
 
-            super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d),
-
             super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d),
 
             super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),
-
-            super::ImplSource::ConstDestruct(ref d) => write!(f, "{:?}", d),
         }
     }
 }
@@ -46,78 +34,26 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceUserDefinedData<'tcx,
     }
 }
 
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceGeneratorData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "ImplSourceGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})",
-            self.generator_def_id, self.substs, self.nested
-        )
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFutureData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "ImplSourceFutureData(generator_def_id={:?}, substs={:?}, nested={:?})",
-            self.generator_def_id, self.substs, self.nested
-        )
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceClosureData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "ImplSourceClosureData(closure_def_id={:?}, substs={:?}, nested={:?})",
-            self.closure_def_id, self.substs, self.nested
-        )
-    }
-}
-
-impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceBuiltinData<N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "ImplSourceBuiltinData(nested={:?})", self.nested)
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitUpcastingData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "ImplSourceTraitUpcastingData(upcast={:?}, vtable_vptr_slot={:?}, nested={:?})",
-            self.upcast_trait_ref, self.vtable_vptr_slot, self.nested
-        )
-    }
-}
-
-impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceAutoImplData<N> {
+impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitUpcastingData<N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
             f,
-            "ImplSourceAutoImplData(trait_def_id={:?}, nested={:?})",
-            self.trait_def_id, self.nested
+            "ImplSourceTraitUpcastingData(vtable_vptr_slot={:?}, nested={:?})",
+            self.vtable_vptr_slot, self.nested
         )
     }
 }
 
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceObjectData<'tcx, N> {
+impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceObjectData<N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
             f,
             "ImplSourceObjectData(upcast={:?}, vtable_base={}, nested={:?})",
-            self.upcast_trait_ref, self.vtable_base, self.nested
+            self.upcast_trait_def_id, self.vtable_base, self.nested
         )
     }
 }
 
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFnPointerData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "ImplSourceFnPointerData(fn_ty={:?}, nested={:?})", self.fn_ty, self.nested)
-    }
-}
-
 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx, N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
@@ -127,9 +63,3 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx,
         )
     }
 }
-
-impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDestructData<N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "ImplSourceConstDestructData(nested={:?})", self.nested)
-    }
-}
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 8466b3fc954..8399fbfc5be 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -3,6 +3,7 @@
 use super::specialization_graph;
 use super::translate_substs;
 use super::util;
+use super::ImplSourceUserDefinedData;
 use super::MismatchedProjectionTypes;
 use super::Obligation;
 use super::ObligationCause;
@@ -10,10 +11,6 @@ use super::PredicateObligation;
 use super::Selection;
 use super::SelectionContext;
 use super::SelectionError;
-use super::{
-    ImplSourceClosureData, ImplSourceFnPointerData, ImplSourceFutureData, ImplSourceGeneratorData,
-    ImplSourceUserDefinedData,
-};
 use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
 
 use crate::errors::InherentProjectionNormalizationOverflow;
@@ -30,7 +27,6 @@ use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::at::At;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_infer::infer::DefineOpaqueTypes;
-use rustc_infer::traits::ImplSourceBuiltinData;
 use rustc_infer::traits::ObligationCauseCode;
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@@ -1721,11 +1717,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
         };
 
         let eligible = match &impl_source {
-            super::ImplSource::Closure(_)
-            | super::ImplSource::Generator(_)
-            | super::ImplSource::Future(_)
-            | super::ImplSource::FnPointer(_)
-            | super::ImplSource::TraitAlias(_) => true,
+            super::ImplSource::TraitAlias(_) => true,
             super::ImplSource::UserDefined(impl_data) => {
                 // We have to be careful when projecting out of an
                 // impl because of specialization. If we are not in
@@ -1783,7 +1775,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
 
                 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() {
                         ty::Bool
                         | ty::Char
@@ -1930,9 +1926,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // why we special case object types.
                 false
             }
-            super::ImplSource::AutoImpl(..)
-            | super::ImplSource::TraitUpcasting(_)
-            | super::ImplSource::ConstDestruct(_) => {
+            | super::ImplSource::TraitUpcasting(_) => {
                 // These traits have no associated types.
                 selcx.tcx().sess.delay_span_bug(
                     obligation.cause.span,
@@ -1996,17 +1990,27 @@ fn confirm_select_candidate<'cx, 'tcx>(
 ) -> Progress<'tcx> {
     match impl_source {
         super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
-        super::ImplSource::Generator(data) => confirm_generator_candidate(selcx, obligation, data),
-        super::ImplSource::Future(data) => confirm_future_candidate(selcx, obligation, data),
-        super::ImplSource::Closure(data) => confirm_closure_candidate(selcx, obligation, data),
-        super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
-        super::ImplSource::Builtin(data) => confirm_builtin_candidate(selcx, obligation, data),
+        super::ImplSource::Builtin(data) => {
+            let trait_def_id = obligation.predicate.trait_def_id(selcx.tcx());
+            let lang_items = selcx.tcx().lang_items();
+            if lang_items.gen_trait() == Some(trait_def_id) {
+                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::AutoImpl(..)
         | super::ImplSource::Param(..)
         | super::ImplSource::TraitUpcasting(_)
-        | super::ImplSource::TraitAlias(..)
-        | super::ImplSource::ConstDestruct(_) => {
+        | super::ImplSource::TraitAlias(..) => {
             // we don't create Select candidates with this kind of resolution
             span_bug!(
                 obligation.cause.span,
@@ -2020,9 +2024,14 @@ fn confirm_select_candidate<'cx, 'tcx>(
 fn confirm_generator_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
-    impl_source: ImplSourceGeneratorData<'tcx, PredicateObligation<'tcx>>,
+    nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let gen_sig = impl_source.substs.as_generator().poly_sig();
+    let ty::Generator(_, substs, _) =
+        selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
+    else {
+        unreachable!()
+    };
+    let gen_sig = substs.as_generator().poly_sig();
     let Normalized { value: gen_sig, obligations } = normalize_with_depth(
         selcx,
         obligation.param_env,
@@ -2060,16 +2069,21 @@ fn confirm_generator_candidate<'cx, 'tcx>(
     });
 
     confirm_param_env_candidate(selcx, obligation, predicate, false)
-        .with_addl_obligations(impl_source.nested)
+        .with_addl_obligations(nested)
         .with_addl_obligations(obligations)
 }
 
 fn confirm_future_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
-    impl_source: ImplSourceFutureData<'tcx, PredicateObligation<'tcx>>,
+    nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let gen_sig = impl_source.substs.as_generator().poly_sig();
+    let ty::Generator(_, substs, _) =
+        selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
+    else {
+        unreachable!()
+    };
+    let gen_sig = substs.as_generator().poly_sig();
     let Normalized { value: gen_sig, obligations } = normalize_with_depth(
         selcx,
         obligation.param_env,
@@ -2099,14 +2113,14 @@ fn confirm_future_candidate<'cx, 'tcx>(
     });
 
     confirm_param_env_candidate(selcx, obligation, predicate, false)
-        .with_addl_obligations(impl_source.nested)
+        .with_addl_obligations(nested)
         .with_addl_obligations(obligations)
 }
 
 fn confirm_builtin_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
-    data: ImplSourceBuiltinData<PredicateObligation<'tcx>>,
+    data: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
     let tcx = selcx.tcx();
     let self_ty = obligation.predicate.self_ty();
@@ -2154,15 +2168,15 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
 
     confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
         .with_addl_obligations(obligations)
-        .with_addl_obligations(data.nested)
+        .with_addl_obligations(data)
 }
 
 fn confirm_fn_pointer_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
-    fn_pointer_impl_source: ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>,
+    nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let fn_type = selcx.infcx.shallow_resolve(fn_pointer_impl_source.fn_ty);
+    let fn_type = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
     let sig = fn_type.fn_sig(selcx.tcx());
     let Normalized { value: sig, obligations } = normalize_with_depth(
         selcx,
@@ -2173,16 +2187,21 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>(
     );
 
     confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
-        .with_addl_obligations(fn_pointer_impl_source.nested)
+        .with_addl_obligations(nested)
         .with_addl_obligations(obligations)
 }
 
 fn confirm_closure_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
-    impl_source: ImplSourceClosureData<'tcx, PredicateObligation<'tcx>>,
+    nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let closure_sig = impl_source.substs.as_closure().sig();
+    let ty::Closure(_, substs) =
+        selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
+    else {
+        unreachable!()
+    };
+    let closure_sig = substs.as_closure().sig();
     let Normalized { value: closure_sig, obligations } = normalize_with_depth(
         selcx,
         obligation.param_env,
@@ -2194,7 +2213,7 @@ fn confirm_closure_candidate<'cx, 'tcx>(
     debug!(?obligation, ?closure_sig, ?obligations, "confirm_closure_candidate");
 
     confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No)
-        .with_addl_obligations(impl_source.nested)
+        .with_addl_obligations(nested)
         .with_addl_obligations(obligations)
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index d2c2cadd617..3c356978d5c 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -27,11 +27,9 @@ use crate::traits::vtable::{
 };
 use crate::traits::{
     BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
-    ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
-    ImplSourceConstDestructData, ImplSourceFnPointerData, ImplSourceFutureData,
-    ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData,
-    ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, Obligation,
-    ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError,
+    ImplSourceObjectData, ImplSourceTraitAliasData, ImplSourceTraitUpcastingData,
+    ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause,
+    OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError,
     TraitNotObjectSafe, TraitObligation, Unimplemented,
 };
 
@@ -72,7 +70,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             AutoImplCandidate => {
                 let data = self.confirm_auto_impl_candidate(obligation);
-                ImplSource::AutoImpl(data)
+                ImplSource::Builtin(data)
             }
 
             ProjectionCandidate(idx, constness) => {
@@ -87,22 +85,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             ClosureCandidate { .. } => {
                 let vtable_closure = self.confirm_closure_candidate(obligation)?;
-                ImplSource::Closure(vtable_closure)
+                ImplSource::Builtin(vtable_closure)
             }
 
             GeneratorCandidate => {
                 let vtable_generator = self.confirm_generator_candidate(obligation)?;
-                ImplSource::Generator(vtable_generator)
+                ImplSource::Builtin(vtable_generator)
             }
 
             FutureCandidate => {
                 let vtable_future = self.confirm_future_candidate(obligation)?;
-                ImplSource::Future(vtable_future)
+                ImplSource::Builtin(vtable_future)
             }
 
             FnPointerCandidate { is_const } => {
                 let data = self.confirm_fn_pointer_candidate(obligation, is_const)?;
-                ImplSource::FnPointer(data)
+                ImplSource::Builtin(data)
             }
 
             TraitAliasCandidate => {
@@ -114,7 +112,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // This indicates something like `Trait + Send: Send`. In this case, we know that
                 // this holds because that's what the object type is telling us, and there's really
                 // no additional obligations to prove and no types in particular to unify, etc.
-                ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst)
+                ImplSource::Builtin(Vec::new())
             }
 
             BuiltinUnsizeCandidate => {
@@ -129,7 +127,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             ConstDestructCandidate(def_id) => {
                 let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
-                ImplSource::ConstDestruct(data)
+                ImplSource::Builtin(data)
             }
         };
 
@@ -244,7 +242,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &TraitObligation<'tcx>,
         has_nested: bool,
-    ) -> ImplSourceBuiltinData<PredicateObligation<'tcx>> {
+    ) -> Vec<PredicateObligation<'tcx>> {
         debug!(?obligation, ?has_nested, "confirm_builtin_candidate");
 
         let lang_items = self.tcx().lang_items();
@@ -277,14 +275,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         debug!(?obligations);
 
-        ImplSourceBuiltinData { nested: obligations }
+        obligations
     }
 
     #[instrument(level = "debug", skip(self))]
     fn confirm_transmutability_candidate(
         &mut self,
         obligation: &TraitObligation<'tcx>,
-    ) -> Result<ImplSourceBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         use rustc_transmute::{Answer, Condition};
         #[instrument(level = "debug", skip(tcx, obligation, predicate))]
         fn flatten_answer_tree<'tcx>(
@@ -369,7 +367,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         };
 
         debug!(?fully_flattened);
-        Ok(ImplSourceBuiltinData { nested: fully_flattened })
+        Ok(fully_flattened)
     }
 
     /// This handles the case where an `auto trait Foo` impl is being used.
@@ -380,7 +378,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn confirm_auto_impl_candidate(
         &mut self,
         obligation: &TraitObligation<'tcx>,
-    ) -> ImplSourceAutoImplData<PredicateObligation<'tcx>> {
+    ) -> Vec<PredicateObligation<'tcx>> {
         debug!(?obligation, "confirm_auto_impl_candidate");
 
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
@@ -394,7 +392,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &TraitObligation<'tcx>,
         trait_def_id: DefId,
         nested: ty::Binder<'tcx, Vec<Ty<'tcx>>>,
-    ) -> ImplSourceAutoImplData<PredicateObligation<'tcx>> {
+    ) -> Vec<PredicateObligation<'tcx>> {
         debug!(?nested, "vtable_auto_impl");
         ensure_sufficient_stack(|| {
             let cause = obligation.derived_cause(BuiltinDerivedObligation);
@@ -424,7 +422,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             debug!(?obligations, "vtable_auto_impl");
 
-            ImplSourceAutoImplData { trait_def_id, nested: obligations }
+            obligations
         })
     }
 
@@ -487,7 +485,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &TraitObligation<'tcx>,
         index: usize,
-    ) -> Result<ImplSourceObjectData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+    ) -> Result<ImplSourceObjectData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let tcx = self.tcx();
         debug!(?obligation, ?index, "confirm_object_candidate");
 
@@ -654,15 +652,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             (unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)),
         );
 
-        Ok(ImplSourceObjectData { upcast_trait_ref, vtable_base, nested })
+        Ok(ImplSourceObjectData {
+            upcast_trait_def_id: upcast_trait_ref.def_id(),
+            vtable_base,
+            nested,
+        })
     }
 
     fn confirm_fn_pointer_candidate(
         &mut self,
         obligation: &TraitObligation<'tcx>,
         is_const: bool,
-    ) -> Result<ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>>
-    {
+    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         debug!(?obligation, "confirm_fn_pointer_candidate");
 
         let tcx = self.tcx();
@@ -714,7 +715,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let tr = ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [output_ty]);
         nested.push(Obligation::new(self.infcx.tcx, cause, obligation.param_env, tr));
 
-        Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested })
+        Ok(nested)
     }
 
     fn confirm_trait_alias_candidate(
@@ -746,8 +747,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn confirm_generator_candidate(
         &mut self,
         obligation: &TraitObligation<'tcx>,
-    ) -> Result<ImplSourceGeneratorData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>>
-    {
+    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         // Okay to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
@@ -780,13 +780,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
         debug!(?trait_ref, ?nested, "generator candidate obligations");
 
-        Ok(ImplSourceGeneratorData { generator_def_id, substs, nested })
+        Ok(nested)
     }
 
     fn confirm_future_candidate(
         &mut self,
         obligation: &TraitObligation<'tcx>,
-    ) -> Result<ImplSourceFutureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         // Okay to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
@@ -810,14 +810,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
         debug!(?trait_ref, ?nested, "future candidate obligations");
 
-        Ok(ImplSourceFutureData { generator_def_id, substs, nested })
+        Ok(nested)
     }
 
     #[instrument(skip(self), level = "debug")]
     fn confirm_closure_candidate(
         &mut self,
         obligation: &TraitObligation<'tcx>,
-    ) -> Result<ImplSourceClosureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let kind = self
             .tcx()
             .fn_trait_kind_from_def_id(obligation.predicate.def_id())
@@ -844,7 +844,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ));
         }
 
-        Ok(ImplSourceClosureData { closure_def_id, substs, nested })
+        Ok(nested)
     }
 
     /// In the case of closure types and fn pointers,
@@ -912,8 +912,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &TraitObligation<'tcx>,
         idx: usize,
-    ) -> Result<ImplSourceTraitUpcastingData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>>
-    {
+    ) -> Result<ImplSourceTraitUpcastingData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let tcx = self.tcx();
 
         // `assemble_candidates_for_unsizing` should ensure there are no late-bound
@@ -1010,13 +1009,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let vtable_vptr_slot =
             prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback).unwrap();
 
-        Ok(ImplSourceTraitUpcastingData { upcast_trait_ref, vtable_vptr_slot, nested })
+        Ok(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested })
     }
 
     fn confirm_builtin_unsize_candidate(
         &mut self,
         obligation: &TraitObligation<'tcx>,
-    ) -> Result<ImplSourceBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let tcx = self.tcx();
 
         // `assemble_candidates_for_unsizing` should ensure there are no late-bound
@@ -1217,17 +1216,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             _ => bug!("source: {source}, target: {target}"),
         };
 
-        Ok(ImplSourceBuiltinData { nested })
+        Ok(nested)
     }
 
     fn confirm_const_destruct_candidate(
         &mut self,
         obligation: &TraitObligation<'tcx>,
         impl_def_id: Option<DefId>,
-    ) -> Result<ImplSourceConstDestructData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
         if !obligation.is_const() {
-            return Ok(ImplSourceConstDestructData { nested: vec![] });
+            return Ok(vec![]);
         }
 
         let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None);
@@ -1381,6 +1380,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
         }
 
-        Ok(ImplSourceConstDestructData { nested })
+        Ok(nested)
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 537405b7eb9..906c357e8ca 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -243,12 +243,12 @@ pub fn upcast_choices<'tcx>(
 /// `object.upcast_trait_ref`) within the vtable for `object`.
 pub fn get_vtable_index_of_object_method<'tcx, N>(
     tcx: TyCtxt<'tcx>,
-    object: &super::ImplSourceObjectData<'tcx, N>,
+    object: &super::ImplSourceObjectData<N>,
     method_def_id: DefId,
 ) -> Option<usize> {
     // Count number of methods preceding the one we are selecting and
     // add them to the total offset.
-    tcx.own_existential_vtable_entries(object.upcast_trait_ref.def_id())
+    tcx.own_existential_vtable_entries(object.upcast_trait_def_id)
         .iter()
         .copied()
         .position(|def_id| def_id == method_def_id)
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index dd911239ac4..45b1075b602 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -177,85 +177,6 @@ fn resolve_associated_item<'tcx>(
 
             Some(ty::Instance::new(leaf_def.item.def_id, 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.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,
-                closure_data.closure_def_id,
-                closure_data.substs,
-                trait_closure_kind,
-            )
-        }
-        traits::ImplSource::FnPointer(ref data) => match data.fn_ty.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, 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| {
                 Instance {
@@ -308,15 +229,73 @@ 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
             }
         }
-        traits::ImplSource::AutoImpl(..)
-        | traits::ImplSource::Param(..)
+        traits::ImplSource::Param(..)
         | traits::ImplSource::TraitAlias(..)
-        | traits::ImplSource::TraitUpcasting(_)
-        | traits::ImplSource::ConstDestruct(_) => None,
+        | traits::ImplSource::TraitUpcasting(_) => None,
     })
 }