about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-06-16 02:10:10 +0000
committerMichael Goulet <michael@errs.io>2023-06-17 03:32:46 +0000
commitd97d4ebecc502bcb5eda2cdaa513e0e7922a377e (patch)
treed30e65674b87510c2b93cf2860102d54738b5d6d
parent2835d9d1d3ab3f09f0117cad8f0a6e0abe142282 (diff)
downloadrust-d97d4ebecc502bcb5eda2cdaa513e0e7922a377e.tar.gz
rust-d97d4ebecc502bcb5eda2cdaa513e0e7922a377e.zip
Remove even more redundant builtin candidates
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs6
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs39
-rw-r--r--compiler/rustc_middle/src/traits/structural_impls.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs8
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs137
6 files changed, 96 insertions, 138 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 d4cde7e2c65..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,7 +781,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                             );
                             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) =
                                 *poly_trait_pred.self_ty().no_bound_vars().unwrap().kind()
                             else {
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 98179c0f933..492b7228488 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -661,20 +661,6 @@ pub enum ImplSource<'tcx, N> {
     /// ImplSource for trait upcasting coercion
     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.
     TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
 }
@@ -683,12 +669,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
     pub fn nested_obligations(self) -> Vec<N> {
         match self {
             ImplSource::UserDefined(i) => i.nested,
-            ImplSource::Param(n, _)
-            | ImplSource::Builtin(n)
-            | ImplSource::FnPointer(n)
-            | ImplSource::Closure(n)
-            | ImplSource::Generator(n)
-            | ImplSource::Future(n) => n,
+            ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
             ImplSource::Object(d) => d.nested,
             ImplSource::TraitAlias(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] {
         match self {
             ImplSource::UserDefined(i) => &i.nested,
-            ImplSource::Param(n, _)
-            | ImplSource::Builtin(n)
-            | ImplSource::FnPointer(n)
-            | ImplSource::Closure(n)
-            | ImplSource::Generator(n)
-            | ImplSource::Future(n) => &n,
+            ImplSource::Param(n, _) | ImplSource::Builtin(n) => &n,
             ImplSource::Object(d) => &d.nested,
             ImplSource::TraitAlias(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] {
         match self {
             ImplSource::UserDefined(i) => &mut i.nested,
-            ImplSource::Param(n, _)
-            | ImplSource::Builtin(n)
-            | ImplSource::FnPointer(n)
-            | ImplSource::Closure(n)
-            | ImplSource::Generator(n)
-            | ImplSource::Future(n) => n,
+            ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
             ImplSource::Object(d) => &mut d.nested,
             ImplSource::TraitAlias(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,
                 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 {
                 alias_def_id: d.alias_def_id,
                 substs: d.substs,
diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs
index bc0e656a656..ac02d6ed62f 100644
--- a/compiler/rustc_middle/src/traits/structural_impls.rs
+++ b/compiler/rustc_middle/src/traits/structural_impls.rs
@@ -9,13 +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::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),
 
@@ -23,8 +17,6 @@ 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),
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 1477c8957f6..8399fbfc5be 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1717,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
@@ -1779,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
@@ -1990,11 +1990,23 @@ 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::Param(..)
         | super::ImplSource::TraitUpcasting(_)
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index d369a087c9b..3c356978d5c 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -85,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 => {
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index cc7700f378a..45b1075b602 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -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
             }