diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 4f77f09b26e..558262460c7 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -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()) + } +} diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index fa087d0a4b0..7e43d67587b 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -141,7 +141,7 @@ fn check_closure( 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`) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index bb393e27a5b..2ab7bb86354 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2018,7 +2018,7 @@ fn label_fn_like( 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 { diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index f5bed834eba..998ee339ae2 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -261,7 +261,11 @@ fn analyze_closure( // 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 { diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index 9a633e04ce7..2899e629d79 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -36,6 +36,17 @@ pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option { } } + /// 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 { + 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() diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index ea6b44d62b0..93a9bbf64c9 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -15,7 +15,6 @@ UserTypeAnnotationIndex, BorrowKind, CastKind, - hir::Movability, BasicBlock, SwitchTargets, CoroutineKind, diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index eaf5da130dd..8c29bc5a428 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -7,14 +7,13 @@ 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 enum UpvarCapture { /// Part of `MinCaptureInformationMap`; List of `CapturePlace`s. pub type MinCaptureList<'tcx> = Vec>; -/// 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)] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8faf5811343..5e61847a37a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -28,7 +28,7 @@ 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}; @@ -88,7 +88,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Term = ty::Term<'tcx>; type Binder = Binder<'tcx, T>; - type TypeAndMut = TypeAndMut<'tcx>; type CanonicalVars = CanonicalVarInfos<'tcx>; type Ty = Ty<'tcx>; @@ -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::CanonicalVars { self.mk_canonical_var_infos(infos) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 71ff7021ca5..a09a5115386 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -75,7 +75,7 @@ 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}; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 39adfac55ce..8e045397b0f 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1680,7 +1680,7 @@ fn pretty_closure_as_impl(&mut self, closure: ty::ClosureArgs<'tcx>) -> Result<( 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!(", "); @@ -2754,6 +2754,10 @@ macro_rules! define_print_and_forward_display { 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) => { @@ -2799,10 +2803,6 @@ macro_rules! 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); @@ -2943,10 +2943,6 @@ macro_rules! define_print_and_forward_display { } } - ty::ClosureKind { - p!(write("{}", self.as_str())) - } - ty::Predicate<'tcx> { p!(print(self.kind())) } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 0cff6b77eb6..1c75d73e552 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -440,7 +440,6 @@ fn fmt>>( // interners). TrivialTypeTraversalAndLiftImpls! { ::rustc_hir::def_id::DefId, - ::rustc_hir::Mutability, ::rustc_hir::Unsafety, ::rustc_target::spec::abi::Abi, crate::ty::ClosureKind, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 297a0be6a27..a0debc8a165 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -44,23 +44,18 @@ 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>; pub type RegionKind<'tcx> = IrRegionKind>; pub type ConstKind<'tcx> = IrConstKind>; pub type PredicateKind<'tcx> = IrPredicateKind>; pub type ClauseKind<'tcx> = IrClauseKind>; - -#[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>; #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] #[derive(HashStable)] @@ -2818,6 +2813,15 @@ pub fn to_opt_closure_kind(self) -> Option { } } + /// 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 diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index c262302133b..188910ecc52 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -3,8 +3,8 @@ 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 { @@ -20,7 +20,6 @@ pub trait Interner: Sized { type Term: Copy + Debug + Hash + Ord; type Binder; - type TypeAndMut: Copy + Debug + Hash + Ord; type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator>; // Kinds of tys @@ -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::CanonicalVars; // FIXME: We should not have all these constructors on `Interner`, but as functions on some trait. diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 200963ff7c5..bff93859645 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -359,3 +359,45 @@ fn default() -> Self { #[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) + } +} diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index cfed84a35c6..82bb1bf2916 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -51,4 +51,6 @@ fn visit_with>( crate::DebruijnIndex, crate::AliasRelationDirection, crate::UniverseIndex, + crate::Mutability, + crate::Movability, } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 72ca9199a53..70adfbee2ed 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -4,6 +4,8 @@ use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; use std::fmt; +use crate::fold::{FallibleTypeFolder, TypeFoldable}; +use crate::visit::{TypeVisitable, TypeVisitor}; use crate::Interner; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx}; @@ -158,7 +160,7 @@ pub enum TyKind { Slice(I::Ty), /// A raw pointer. Written as `*mut T` or `*const T` - RawPtr(I::TypeAndMut), + RawPtr(TypeAndMut), /// A reference; a pointer with an associated lifetime. Written as /// `&'a mut T` or `&'a T`. @@ -410,8 +412,7 @@ fn fmt>( Str => write!(f, "str"), Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)), Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), - RawPtr(p) => { - let (ty, mutbl) = I::ty_and_mut_to_parts(*p); + RawPtr(TypeAndMut { ty, mutbl }) => { match mutbl { Mutability::Mut => write!(f, "*mut "), Mutability::Not => write!(f, "*const "), @@ -831,3 +832,42 @@ fn fmt>( } } } + +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + PartialOrd(bound = ""), + Ord(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Hash(bound = ""), + Debug(bound = "") +)] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +pub struct TypeAndMut { + pub ty: I::Ty, + pub mutbl: Mutability, +} + +impl TypeFoldable for TypeAndMut +where + I::Ty: TypeFoldable, +{ + fn try_fold_with>(self, folder: &mut F) -> Result { + Ok(TypeAndMut { + ty: self.ty.try_fold_with(folder)?, + mutbl: self.mutbl.try_fold_with(folder)?, + }) + } +} + +impl TypeVisitable for TypeAndMut +where + I::Ty: TypeVisitable, +{ + fn visit_with>(&self, visitor: &mut V) -> std::ops::ControlFlow { + self.ty.visit_with(visitor)?; + self.mutbl.visit_with(visitor) + } +} diff --git a/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs b/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs index 55294f5f386..b55cd8833b7 100644 --- a/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs +++ b/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs @@ -10,8 +10,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>) { if let ty::RawPtr( - ptrty @ TypeAndMut { - mutbl: Mutability::Mut, .. + TypeAndMut { + mutbl: Mutability::Mut, ty: ptrty, }, ) = cast_to.kind() && let ty::RawPtr(TypeAndMut { @@ -34,7 +34,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cx, AS_PTR_CAST_MUT, expr.span, - &format!("casting the result of `as_ptr` to *{ptrty}"), + &format!("casting the result of `as_ptr` to *mut {ptrty}"), "replace with", format!("{recv}.as_mut_ptr()"), applicability,