about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDeadbeef <ent3rm4n@gmail.com>2024-03-09 21:16:18 +0800
committerDeadbeef <ent3rm4n@gmail.com>2024-03-09 21:16:43 +0800
commit7e1969ac13b94694bb6c9315dcecdc6b0ee344ad (patch)
tree15594d8127a5c4e4b4160e042b1e40e506ff4a8b
parent09bc67b9158392361780e779d32997f14cc75c39 (diff)
downloadrust-7e1969ac13b94694bb6c9315dcecdc6b0ee344ad.tar.gz
rust-7e1969ac13b94694bb6c9315dcecdc6b0ee344ad.zip
Remove `Ord` from `ClosureKind`
Using `Ord` to accomplish a meaning of subset relationship
can be hard to read. The existing uses for that are easily
replaced with a `match`, and in my opinion, more readable
without needing to resorting to comments to explain the
intention.
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs17
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs2
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs37
-rw-r--r--compiler/rustc_type_ir/src/lib.rs14
4 files changed, 42 insertions, 28 deletions
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 1ff961a9089..c17af666eb9 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -19,7 +19,7 @@ use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::ArgKind;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
-use std::cmp;
+use rustc_type_ir::ClosureKind;
 use std::iter;
 use std::ops::ControlFlow;
 
@@ -437,10 +437,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 };
 
                 if let Some(found_kind) = found_kind {
-                    expected_kind = Some(
-                        expected_kind
-                            .map_or_else(|| found_kind, |current| cmp::min(current, found_kind)),
-                    );
+                    // always use the closure kind that is more permissive.
+                    match (expected_kind, found_kind) {
+                        (None, _) => expected_kind = Some(found_kind),
+                        (Some(ClosureKind::FnMut), ClosureKind::Fn) => {
+                            expected_kind = Some(ClosureKind::Fn)
+                        }
+                        (Some(ClosureKind::FnOnce), ClosureKind::Fn | ClosureKind::FnMut) => {
+                            expected_kind = Some(found_kind)
+                        }
+                        _ => {}
+                    }
                 }
             }
         }
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 260d0885089..e381bffa395 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -30,7 +30,7 @@ pub struct Instance<'tcx> {
     pub args: GenericArgsRef<'tcx>,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 #[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub enum InstanceDef<'tcx> {
     /// A user-defined callable item.
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 381681fb1f4..2816bcc888b 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -7,6 +7,7 @@ use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt};
 use rustc_span::sym;
 use rustc_trait_selection::traits;
+use rustc_type_ir::ClosureKind;
 use traits::{translate_args, Reveal};
 
 use crate::errors::UnexpectedFnPtrAssociatedItem;
@@ -296,23 +297,25 @@ fn resolve_associated_item<'tcx>(
             {
                 match *rcvr_args.type_at(0).kind() {
                     ty::CoroutineClosure(coroutine_closure_def_id, args) => {
-                        // If we're computing `AsyncFnOnce`/`AsyncFnMut` for a by-ref closure,
-                        // or `AsyncFnOnce` for a by-mut closure, then construct a new body that
-                        // has the right return types.
-                        //
-                        // Specifically, `AsyncFnMut` for a by-ref coroutine-closure just needs
-                        // to have its input and output types fixed (`&mut self` and returning
-                        // `i16` coroutine kind).
-                        if target_kind > args.as_coroutine_closure().kind() {
-                            Some(Instance {
-                                def: ty::InstanceDef::ConstructCoroutineInClosureShim {
-                                    coroutine_closure_def_id,
-                                    target_kind,
-                                },
-                                args,
-                            })
-                        } else {
-                            Some(Instance::new(coroutine_closure_def_id, args))
+                        match (target_kind, args.as_coroutine_closure().kind()) {
+                            (ClosureKind::FnOnce | ClosureKind::FnMut, ClosureKind::Fn)
+                            | (ClosureKind::FnOnce, ClosureKind::FnMut) => {
+                                // If we're computing `AsyncFnOnce`/`AsyncFnMut` for a by-ref closure,
+                                // or `AsyncFnOnce` for a by-mut closure, then construct a new body that
+                                // has the right return types.
+                                //
+                                // Specifically, `AsyncFnMut` for a by-ref coroutine-closure just needs
+                                // to have its input and output types fixed (`&mut self` and returning
+                                // `i16` coroutine kind).
+                                Some(Instance {
+                                    def: ty::InstanceDef::ConstructCoroutineInClosureShim {
+                                        coroutine_closure_def_id,
+                                        target_kind,
+                                    },
+                                    args,
+                                })
+                            }
+                            _ => Some(Instance::new(coroutine_closure_def_id, args)),
                         }
                     }
                     ty::Closure(closure_def_id, args) => {
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 2ded1b956e5..c01baa58ae7 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -369,12 +369,9 @@ rustc_index::newtype_index! {
 ///
 /// You can get the environment type of a closure using
 /// `tcx.closure_env_ty()`.
-#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
 pub enum ClosureKind {
-    // Warning: Ordering is significant here! The ordering is chosen
-    // because the trait Fn is a subtrait of FnMut and so in turn, and
-    // hence we order it so that Fn < FnMut < FnOnce.
     Fn,
     FnMut,
     FnOnce,
@@ -394,8 +391,15 @@ impl ClosureKind {
 
     /// Returns `true` if a type that impls this closure kind
     /// must also implement `other`.
+    #[rustfmt::skip]
     pub fn extends(self, other: ClosureKind) -> bool {
-        self <= other
+        use ClosureKind::*;
+        match (self, other) {
+              (Fn, Fn | FnMut | FnOnce)
+            | (FnMut,   FnMut | FnOnce)
+            | (FnOnce,          FnOnce) => true,
+            _ => false,
+        }
     }
 }