Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uplift TypeAndMut and ClosureKind to rustc_type_ir #118888

Merged
merged 3 commits into from Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions compiler/rustc_errors/src/diagnostic_impls.rs
Expand Up @@ -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())
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/closure.rs
Expand Up @@ -141,7 +141,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!(?sig, ?opt_kind);

let closure_kind_ty = match opt_kind {
Some(kind) => kind.to_ty(self.tcx),
Some(kind) => Ty::from_closure_kind(self.tcx, kind),

// Create a type variable (for now) to represent the closure kind.
// It will be unified during the upvar inference phase (`upvar.rs`)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Expand Up @@ -2018,7 +2018,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let new_def_id = self.probe(|_| {
let trait_ref = ty::TraitRef::new(
self.tcx,
call_kind.to_def_id(self.tcx),
self.tcx.fn_trait_kind_to_def_id(call_kind)?,
[
callee_ty,
self.next_ty_var(TypeVariableOrigin {
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_hir_typeck/src/upvar.rs
Expand Up @@ -261,7 +261,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Unify the (as yet unbound) type variable in the closure
// args with the kind we inferred.
let closure_kind_ty = closure_args.as_closure().kind_ty();
self.demand_eqtype(span, closure_kind.to_ty(self.tcx), closure_kind_ty);
self.demand_eqtype(
span,
Ty::from_closure_kind(self.tcx, closure_kind),
closure_kind_ty,
);

// If we have an origin, store it.
if let Some(mut origin) = origin {
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_middle/src/middle/lang_items.rs
Expand Up @@ -36,6 +36,17 @@ impl<'tcx> TyCtxt<'tcx> {
}
}

/// Given a [`ty::ClosureKind`], get the [`DefId`] of its corresponding `Fn`-family
/// trait, if it is defined.
pub fn fn_trait_kind_to_def_id(self, kind: ty::ClosureKind) -> Option<DefId> {
let items = self.lang_items();
match kind {
ty::ClosureKind::Fn => items.fn_trait(),
ty::ClosureKind::FnMut => items.fn_mut_trait(),
ty::ClosureKind::FnOnce => items.fn_once_trait(),
}
}

/// Returns `true` if `id` is a `DefId` of [`Fn`], [`FnMut`] or [`FnOnce`] traits.
pub fn is_fn_trait(self, id: DefId) -> bool {
self.fn_trait_kind_from_def_id(id).is_some()
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/mir/type_foldable.rs
Expand Up @@ -15,7 +15,6 @@ TrivialTypeTraversalImpls! {
UserTypeAnnotationIndex,
BorrowKind,
CastKind,
hir::Movability,
BasicBlock,
SwitchTargets,
CoroutineKind,
Expand Down
73 changes: 3 additions & 70 deletions compiler/rustc_middle/src/ty/closure.rs
Expand Up @@ -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::*;

Expand Down Expand Up @@ -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)]
Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_middle/src/ty/context.rs
Expand Up @@ -28,7 +28,7 @@ use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind,
ImplPolarity, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate,
PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid,
TypeAndMut, Visibility,
Visibility,
};
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
use rustc_ast::{self as ast, attr};
Expand Down Expand Up @@ -88,7 +88,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type Term = ty::Term<'tcx>;

type Binder<T> = Binder<'tcx, T>;
type TypeAndMut = TypeAndMut<'tcx>;
type CanonicalVars = CanonicalVarInfos<'tcx>;

type Ty = Ty<'tcx>;
Expand Down Expand Up @@ -128,12 +127,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type CoercePredicate = ty::CoercePredicate<'tcx>;
type ClosureKind = ty::ClosureKind;

fn ty_and_mut_to_parts(
TypeAndMut { ty, mutbl }: TypeAndMut<'tcx>,
) -> (Self::Ty, ty::Mutability) {
(ty, mutbl)
}

fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
self.mk_canonical_var_infos(infos)
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Expand Up @@ -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};
Expand Down
14 changes: 5 additions & 9 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Expand Up @@ -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!(", ");
Expand Down Expand Up @@ -2754,6 +2754,10 @@ forward_display_to_print! {
define_print! {
(self, cx):

ty::TypeAndMut<'tcx> {
p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
}

ty::ClauseKind<'tcx> {
match *self {
ty::ClauseKind::Trait(ref data) => {
Expand Down Expand Up @@ -2799,10 +2803,6 @@ define_print_and_forward_display! {
p!("{{", comma_sep(self.iter()), "}}")
}

ty::TypeAndMut<'tcx> {
p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
}

ty::ExistentialTraitRef<'tcx> {
// Use a type that can't appear in defaults of type parameters.
let dummy_self = Ty::new_fresh(cx.tcx(),0);
Expand Down Expand Up @@ -2943,10 +2943,6 @@ define_print_and_forward_display! {
}
}

ty::ClosureKind {
p!(write("{}", self.as_str()))
}

ty::Predicate<'tcx> {
p!(print(self.kind()))
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/ty/structural_impls.rs
Expand Up @@ -440,7 +440,6 @@ TrivialTypeTraversalImpls! {
// interners).
TrivialTypeTraversalAndLiftImpls! {
::rustc_hir::def_id::DefId,
::rustc_hir::Mutability,
::rustc_hir::Unsafety,
::rustc_target::spec::abi::Abi,
crate::ty::ClosureKind,
Expand Down
20 changes: 12 additions & 8 deletions compiler/rustc_middle/src/ty/sty.rs
Expand Up @@ -42,23 +42,18 @@ use rustc_type_ir::PredicateKind as IrPredicateKind;
use rustc_type_ir::RegionKind as IrRegionKind;
use rustc_type_ir::TyKind as IrTyKind;
use rustc_type_ir::TyKind::*;
use rustc_type_ir::TypeAndMut as IrTypeAndMut;

use super::GenericParamDefKind;

// Re-export the `TyKind` from `rustc_type_ir` here for convenience
// Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
#[rustc_diagnostic_item = "TyKind"]
pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>;
pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>;
pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>;
pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>;
pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct TypeAndMut<'tcx> {
pub ty: Ty<'tcx>,
pub mutbl: hir::Mutability,
}
pub type TypeAndMut<'tcx> = IrTypeAndMut<TyCtxt<'tcx>>;

#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)]
#[derive(HashStable)]
Expand Down Expand Up @@ -2816,6 +2811,15 @@ impl<'tcx> Ty<'tcx> {
}
}

/// Inverse of [`Ty::to_opt_closure_kind`].
pub fn from_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> {
match kind {
ty::ClosureKind::Fn => tcx.types.i8,
ty::ClosureKind::FnMut => tcx.types.i16,
ty::ClosureKind::FnOnce => tcx.types.i32,
}
}

/// Fast path helper for testing if a type is `Sized`.
///
/// Returning true means the type is known to be sized. Returning
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_type_ir/src/interner.rs
Expand Up @@ -3,8 +3,8 @@ use std::fmt::Debug;
use std::hash::Hash;

use crate::{
BoundVar, CanonicalVarInfo, ConstKind, DebruijnIndex, DebugWithInfcx, Mutability, RegionKind,
TyKind, UniverseIndex,
BoundVar, CanonicalVarInfo, ConstKind, DebruijnIndex, DebugWithInfcx, RegionKind, TyKind,
UniverseIndex,
};

pub trait Interner: Sized {
Expand All @@ -20,7 +20,6 @@ pub trait Interner: Sized {
type Term: Copy + Debug + Hash + Ord;

type Binder<T>;
type TypeAndMut: Copy + Debug + Hash + Ord;
type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator<Item = CanonicalVarInfo<Self>>;

// Kinds of tys
Expand Down Expand Up @@ -81,8 +80,6 @@ pub trait Interner: Sized {
type CoercePredicate: Copy + Debug + Hash + Eq;
type ClosureKind: Copy + Debug + Hash + Eq;

fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability);

fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo<Self>]) -> Self::CanonicalVars;

// FIXME: We should not have all these constructors on `Interner`, but as functions on some trait.
Expand Down
42 changes: 42 additions & 0 deletions compiler/rustc_type_ir/src/lib.rs
Expand Up @@ -359,3 +359,45 @@ 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
}
}

impl fmt::Display for ClosureKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_str().fmt(f)
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_type_ir/src/macros.rs
Expand Up @@ -51,4 +51,6 @@ TrivialTypeTraversalImpls! {
crate::DebruijnIndex,
crate::AliasRelationDirection,
crate::UniverseIndex,
crate::Mutability,
crate::Movability,
}