Uplift ClosureKind

This commit is contained in:
Michael Goulet 2023-12-12 18:54:49 +00:00
parent 835ed0021e
commit b8ea6e686f
7 changed files with 107 additions and 76 deletions

View file

@ -378,3 +378,9 @@ pub struct IndicateAnonymousLifetime {
pub count: usize,
pub suggestion: String,
}
impl IntoDiagnosticArg for type_ir::ClosureKind {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(self.as_str().into())
}
}

View file

@ -7,14 +7,13 @@ use std::fmt::Write;
use crate::query::Providers;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, LangItem};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_span::def_id::LocalDefIdMap;
use rustc_span::symbol::Ident;
use rustc_span::{Span, Symbol};
use super::{Ty, TyCtxt};
use super::TyCtxt;
use self::BorrowKind::*;
@ -73,72 +72,6 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<hir::HirId, MinCaptureLis
/// Part of `MinCaptureInformationMap`; List of `CapturePlace`s.
pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>;
/// Represents the various closure traits in the language. This
/// will determine the type of the environment (`self`, in the
/// desugaring) argument that the closure expects.
///
/// You can get the environment type of a closure using
/// `tcx.closure_env_ty()`.
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable)]
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,
}
impl ClosureKind {
/// This is the initial value used when doing upvar inference.
pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn;
pub const fn as_str(self) -> &'static str {
match self {
ClosureKind::Fn => "Fn",
ClosureKind::FnMut => "FnMut",
ClosureKind::FnOnce => "FnOnce",
}
}
/// Returns `true` if a type that impls this closure kind
/// must also implement `other`.
pub fn extends(self, other: ty::ClosureKind) -> bool {
self <= other
}
/// Converts `self` to a [`DefId`] of the corresponding trait.
///
/// Note: the inverse of this function is [`TyCtxt::fn_trait_kind_from_def_id`].
pub fn to_def_id(&self, tcx: TyCtxt<'_>) -> DefId {
tcx.require_lang_item(
match self {
ClosureKind::Fn => LangItem::Fn,
ClosureKind::FnMut => LangItem::FnMut,
ClosureKind::FnOnce => LangItem::FnOnce,
},
None,
)
}
/// Returns the representative scalar type for this closure kind.
/// See `Ty::to_opt_closure_kind` for more details.
pub fn to_ty<'tcx>(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self {
ClosureKind::Fn => tcx.types.i8,
ClosureKind::FnMut => tcx.types.i16,
ClosureKind::FnOnce => tcx.types.i32,
}
}
}
impl IntoDiagnosticArg for ClosureKind {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(self.as_str().into())
}
}
/// A composite describing a `Place` that is captured by a closure.
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]

View file

@ -158,6 +158,30 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
) -> Self::Const {
Const::new_bound(self, debruijn, var, ty)
}
fn fn_def_id(self) -> Self::DefId {
self.require_lang_item(hir::LangItem::Fn, None)
}
fn fn_mut_def_id(self) -> Self::DefId {
self.require_lang_item(hir::LangItem::FnMut, None)
}
fn fn_once_def_id(self) -> Self::DefId {
self.require_lang_item(hir::LangItem::FnOnce, None)
}
fn i8_type(self) -> Self::Ty {
self.types.i8
}
fn i16_type(self) -> Self::Ty {
self.types.i16
}
fn i32_type(self) -> Self::Ty {
self.types.i32
}
}
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;

View file

@ -75,7 +75,7 @@ pub use self::binding::BindingMode;
pub use self::binding::BindingMode::*;
pub use self::closure::{
is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
CapturedPlace, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL,
};
pub use self::consts::{Const, ConstData, ConstInt, Expr, ScalarInt, UnevaluatedConst, ValTree};

View file

@ -1680,7 +1680,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
self.wrap_binder(&sig, |sig, cx| {
define_scoped_cx!(cx);
p!(print(kind), "(");
p!(write("{kind}("));
for (i, arg) in sig.inputs()[0].tuple_fields().iter().enumerate() {
if i > 0 {
p!(", ");
@ -2943,10 +2943,6 @@ define_print_and_forward_display! {
}
}
ty::ClosureKind {
p!(write("{}", self.as_str()))
}
ty::Predicate<'tcx> {
p!(print(self.kind()))
}

View file

@ -89,6 +89,15 @@ pub trait Interner: Sized {
fn mk_bound_ty(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Ty;
fn mk_bound_region(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Region;
fn mk_bound_const(self, debruijn: DebruijnIndex, var: BoundVar, ty: Self::Ty) -> Self::Const;
// FIXME: these could be consolidated into some "WellKnownTraits" thing like chalk does.
fn fn_def_id(self) -> Self::DefId;
fn fn_mut_def_id(self) -> Self::DefId;
fn fn_once_def_id(self) -> Self::DefId;
fn i8_type(self) -> Self::Ty;
fn i16_type(self) -> Self::Ty;
fn i32_type(self) -> Self::Ty;
}
/// Common capabilities of placeholder kinds

View file

@ -359,3 +359,66 @@ rustc_index::newtype_index! {
#[gate_rustc_only]
pub struct BoundVar {}
}
/// Represents the various closure traits in the language. This
/// will determine the type of the environment (`self`, in the
/// desugaring) argument that the closure expects.
///
/// You can get the environment type of a closure using
/// `tcx.closure_env_ty()`.
#[derive(Clone, Copy, PartialOrd, Ord, 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,
}
impl ClosureKind {
/// This is the initial value used when doing upvar inference.
pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn;
pub const fn as_str(self) -> &'static str {
match self {
ClosureKind::Fn => "Fn",
ClosureKind::FnMut => "FnMut",
ClosureKind::FnOnce => "FnOnce",
}
}
/// Returns `true` if a type that impls this closure kind
/// must also implement `other`.
pub fn extends(self, other: ClosureKind) -> bool {
self <= other
}
/// Converts `self` to a `DefId` of the corresponding trait.
///
/// Note: the inverse of this function is `TyCtxt::fn_trait_kind_from_def_id`.
pub fn to_def_id<I: Interner>(self, interner: I) -> I::DefId {
match self {
ClosureKind::Fn => interner.fn_def_id(),
ClosureKind::FnMut => interner.fn_mut_def_id(),
ClosureKind::FnOnce => interner.fn_once_def_id(),
}
}
/// Returns the representative scalar type for this closure kind.
/// See `Ty::to_opt_closure_kind` for more details.
pub fn to_ty<I: Interner>(self, interner: I) -> I::Ty {
match self {
ClosureKind::Fn => interner.i8_type(),
ClosureKind::FnMut => interner.i16_type(),
ClosureKind::FnOnce => interner.i32_type(),
}
}
}
impl fmt::Display for ClosureKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_str().fmt(f)
}
}