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.
This commit is contained in:
Deadbeef 2024-03-09 21:16:18 +08:00
parent 09bc67b915
commit 7e1969ac13
4 changed files with 42 additions and 28 deletions

View File

@ -19,7 +19,7 @@ use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
use rustc_trait_selection::traits::error_reporting::ArgKind; use rustc_trait_selection::traits::error_reporting::ArgKind;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
use std::cmp; use rustc_type_ir::ClosureKind;
use std::iter; use std::iter;
use std::ops::ControlFlow; use std::ops::ControlFlow;
@ -437,10 +437,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}; };
if let Some(found_kind) = found_kind { if let Some(found_kind) = found_kind {
expected_kind = Some( // always use the closure kind that is more permissive.
expected_kind match (expected_kind, found_kind) {
.map_or_else(|| found_kind, |current| cmp::min(current, 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)
}
_ => {}
}
} }
} }
} }

View File

@ -30,7 +30,7 @@ pub struct Instance<'tcx> {
pub args: GenericArgsRef<'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)] #[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub enum InstanceDef<'tcx> { pub enum InstanceDef<'tcx> {
/// A user-defined callable item. /// A user-defined callable item.

View File

@ -7,6 +7,7 @@ use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt};
use rustc_span::sym; use rustc_span::sym;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
use rustc_type_ir::ClosureKind;
use traits::{translate_args, Reveal}; use traits::{translate_args, Reveal};
use crate::errors::UnexpectedFnPtrAssociatedItem; use crate::errors::UnexpectedFnPtrAssociatedItem;
@ -296,23 +297,25 @@ fn resolve_associated_item<'tcx>(
{ {
match *rcvr_args.type_at(0).kind() { match *rcvr_args.type_at(0).kind() {
ty::CoroutineClosure(coroutine_closure_def_id, args) => { ty::CoroutineClosure(coroutine_closure_def_id, args) => {
// If we're computing `AsyncFnOnce`/`AsyncFnMut` for a by-ref closure, match (target_kind, args.as_coroutine_closure().kind()) {
// or `AsyncFnOnce` for a by-mut closure, then construct a new body that (ClosureKind::FnOnce | ClosureKind::FnMut, ClosureKind::Fn)
// has the right return types. | (ClosureKind::FnOnce, ClosureKind::FnMut) => {
// // If we're computing `AsyncFnOnce`/`AsyncFnMut` for a by-ref closure,
// Specifically, `AsyncFnMut` for a by-ref coroutine-closure just needs // or `AsyncFnOnce` for a by-mut closure, then construct a new body that
// to have its input and output types fixed (`&mut self` and returning // has the right return types.
// `i16` coroutine kind). //
if target_kind > args.as_coroutine_closure().kind() { // Specifically, `AsyncFnMut` for a by-ref coroutine-closure just needs
Some(Instance { // to have its input and output types fixed (`&mut self` and returning
def: ty::InstanceDef::ConstructCoroutineInClosureShim { // `i16` coroutine kind).
coroutine_closure_def_id, Some(Instance {
target_kind, def: ty::InstanceDef::ConstructCoroutineInClosureShim {
}, coroutine_closure_def_id,
args, target_kind,
}) },
} else { args,
Some(Instance::new(coroutine_closure_def_id, args)) })
}
_ => Some(Instance::new(coroutine_closure_def_id, args)),
} }
} }
ty::Closure(closure_def_id, args) => { ty::Closure(closure_def_id, args) => {

View File

@ -369,12 +369,9 @@ rustc_index::newtype_index! {
/// ///
/// You can get the environment type of a closure using /// You can get the environment type of a closure using
/// `tcx.closure_env_ty()`. /// `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))] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
pub enum ClosureKind { 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, Fn,
FnMut, FnMut,
FnOnce, FnOnce,
@ -394,8 +391,15 @@ impl ClosureKind {
/// Returns `true` if a type that impls this closure kind /// Returns `true` if a type that impls this closure kind
/// must also implement `other`. /// must also implement `other`.
#[rustfmt::skip]
pub fn extends(self, other: ClosureKind) -> bool { 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,
}
} }
} }