diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 1c31e29ac02..5a1691effe5 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs @@ -31,9 +31,9 @@ display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter}, method_resolution, traits::{FnTrait, Solution, SolutionVariables}, - BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate, InEnvironment, - Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, Ty, TyDefId, - TyKind, + BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, + InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, + Ty, TyDefId, TyKind, }; use rustc_hash::FxHashSet; use stdx::{format_to, impl_from}; @@ -1692,7 +1692,7 @@ pub fn is_closure(&self) -> bool { } pub fn is_fn(&self) -> bool { - matches!(&self.ty.value, Ty::FnDef(..) | Ty::FnPtr { .. }) + matches!(&self.ty.value, Ty::FnDef(..) | Ty::Function { .. }) } pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { @@ -1974,7 +1974,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { #[derive(Debug)] pub struct Callable { ty: Type, - sig: FnSig, + sig: CallableSig, def: Option, pub(crate) is_bound_method: bool, } diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 4a25a49e3f5..179f7ff442a 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -3,8 +3,8 @@ use std::{borrow::Cow, fmt}; use crate::{ - db::HirDatabase, primitive, utils::generics, CallableDefId, FnSig, GenericPredicate, Lifetime, - Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, TraitRef, Ty, + db::HirDatabase, primitive, utils::generics, CallableDefId, CallableSig, GenericPredicate, + Lifetime, Obligation, OpaqueTy, OpaqueTyId, ProjectionTy, Scalar, Substs, TraitRef, Ty, }; use arrayvec::ArrayVec; use hir_def::{ @@ -341,8 +341,8 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { write!(f, ")")?; } } - Ty::FnPtr { is_varargs, substs, .. } => { - let sig = FnSig::from_fn_ptr_substs(&substs, *is_varargs); + Ty::Function(fn_ptr) => { + let sig = CallableSig::from_fn_ptr(fn_ptr); sig.hir_fmt(f)?; } Ty::FnDef(def, parameters) => { @@ -494,7 +494,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { } } } - Ty::Closure { substs, .. } => { + Ty::Closure(.., substs) => { let sig = substs[0].callable_sig(f.db); if let Some(sig) = sig { if sig.params().is_empty() { @@ -571,7 +571,7 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { } } -impl HirDisplay for FnSig { +impl HirDisplay for CallableSig { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { write!(f, "fn(")?; f.write_joined(self.params(), ", ")?; diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index cd5fb325287..4cca3590481 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -89,14 +89,14 @@ fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { | (Ty::Ref(Mutability::Shared, ..), Ty::Ref(Mutability::Mut, ..)) => return false, // `{function_type}` -> `fn()` - (Ty::FnDef(..), Ty::FnPtr { .. }) => match from_ty.callable_sig(self.db) { + (Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) { None => return false, Some(sig) => { from_ty = Ty::fn_ptr(sig); } }, - (Ty::Closure { substs, .. }, Ty::FnPtr { .. }) => { + (Ty::Closure(.., substs), Ty::Function { .. }) => { from_ty = substs[0].clone(); } diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 13240f79082..b75d32b8508 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -18,8 +18,8 @@ primitive::{self, UintTy}, traits::{FnTrait, InEnvironment}, utils::{generics, variant_data, Generics}, - Binders, CallableDefId, InferTy, Mutability, Obligation, OpaqueTyId, Rawness, Scalar, Substs, - TraitRef, Ty, + Binders, CallableDefId, FnPointer, FnSig, InferTy, Mutability, Obligation, OpaqueTyId, Rawness, + Scalar, Substs, TraitRef, Ty, }; use super::{ @@ -247,13 +247,12 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { None => self.table.new_type_var(), }; sig_tys.push(ret_ty.clone()); - let sig_ty = Ty::FnPtr { - num_args: sig_tys.len() as u16 - 1, - is_varargs: false, + let sig_ty = Ty::Function(FnPointer { + num_args: sig_tys.len() - 1, + sig: FnSig { variadic: false }, substs: Substs(sig_tys.clone().into()), - }; - let closure_ty = - Ty::Closure { def: self.owner, expr: tgt_expr, substs: Substs::single(sig_ty) }; + }); + let closure_ty = Ty::Closure(self.owner, tgt_expr, Substs::single(sig_ty)); // Eagerly try to relate the closure type with the expected // type, otherwise we often won't have enough information to diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 4c0ebcfe334..1abb0440fda 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -99,6 +99,18 @@ fn walk_mut_binders( } } +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub struct FnSig { + pub variadic: bool, +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct FnPointer { + pub num_args: usize, + pub sig: FnSig, + pub substs: Substs, +} + /// A type. /// /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents @@ -166,7 +178,7 @@ pub enum Ty { /// /// The closure signature is stored in a `FnPtr` type in the first type /// parameter. - Closure { def: DefWithBodyId, expr: ExprId, substs: Substs }, + Closure(DefWithBodyId, ExprId, Substs), /// Represents a foreign type declared in external blocks. ForeignType(TypeAliasId), @@ -179,8 +191,7 @@ pub enum Ty { /// fn foo() -> i32 { 1 } /// let bar: fn() -> i32 = foo; /// ``` - // FIXME make this a Ty variant like in Chalk - FnPtr { num_args: u16, is_varargs: bool, substs: Substs }, + Function(FnPointer), /// A "projection" type corresponds to an (unnormalized) /// projection like `>::Foo`. Note that the @@ -535,22 +546,29 @@ pub enum TyKind { /// A function signature as seen by type inference: Several parameter types and /// one return type. #[derive(Clone, PartialEq, Eq, Debug)] -pub struct FnSig { +pub struct CallableSig { params_and_return: Arc<[Ty]>, is_varargs: bool, } /// A polymorphic function signature. -pub type PolyFnSig = Binders; +pub type PolyFnSig = Binders; -impl FnSig { - pub fn from_params_and_return(mut params: Vec, ret: Ty, is_varargs: bool) -> FnSig { +impl CallableSig { + pub fn from_params_and_return(mut params: Vec, ret: Ty, is_varargs: bool) -> CallableSig { params.push(ret); - FnSig { params_and_return: params.into(), is_varargs } + CallableSig { params_and_return: params.into(), is_varargs } } - pub fn from_fn_ptr_substs(substs: &Substs, is_varargs: bool) -> FnSig { - FnSig { params_and_return: Arc::clone(&substs.0), is_varargs } + pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { + CallableSig { + params_and_return: Arc::clone(&fn_ptr.substs.0), + is_varargs: fn_ptr.sig.variadic, + } + } + + pub fn from_substs(substs: &Substs) -> CallableSig { + CallableSig { params_and_return: Arc::clone(&substs.0), is_varargs: false } } pub fn params(&self) -> &[Ty] { @@ -562,7 +580,7 @@ pub fn ret(&self) -> &Ty { } } -impl TypeWalk for FnSig { +impl TypeWalk for CallableSig { fn walk(&self, f: &mut impl FnMut(&Ty)) { for t in self.params_and_return.iter() { t.walk(f); @@ -585,12 +603,12 @@ pub fn unit() -> Self { Ty::Tuple(0, Substs::empty()) } - pub fn fn_ptr(sig: FnSig) -> Self { - Ty::FnPtr { - num_args: sig.params().len() as u16, - is_varargs: sig.is_varargs, + pub fn fn_ptr(sig: CallableSig) -> Self { + Ty::Function(FnPointer { + num_args: sig.params().len(), + sig: FnSig { variadic: sig.is_varargs }, substs: Substs(sig.params_and_return), - } + }) } pub fn builtin(builtin: BuiltinType) -> Self { @@ -673,7 +691,7 @@ pub fn equals_ctor(&self, other: &Ty) -> bool { (Ty::OpaqueType(ty_id, ..), Ty::OpaqueType(ty_id2, ..)) => ty_id == ty_id2, (Ty::AssociatedType(ty_id, ..), Ty::AssociatedType(ty_id2, ..)) | (Ty::ForeignType(ty_id, ..), Ty::ForeignType(ty_id2, ..)) => ty_id == ty_id2, - (Ty::Closure { def, expr, .. }, Ty::Closure { def: def2, expr: expr2, .. }) => { + (Ty::Closure(def, expr, _), Ty::Closure(def2, expr2, _)) => { expr == expr2 && def == def2 } (Ty::Ref(mutability, ..), Ty::Ref(mutability2, ..)) @@ -681,9 +699,9 @@ pub fn equals_ctor(&self, other: &Ty) -> bool { mutability == mutability2 } ( - Ty::FnPtr { num_args, is_varargs, .. }, - Ty::FnPtr { num_args: num_args2, is_varargs: is_varargs2, .. }, - ) => num_args == num_args2 && is_varargs == is_varargs2, + Ty::Function(FnPointer { num_args, sig, .. }), + Ty::Function(FnPointer { num_args: num_args2, sig: sig2, .. }), + ) => num_args == num_args2 && sig == sig2, (Ty::Tuple(cardinality, _), Ty::Tuple(cardinality2, _)) => cardinality == cardinality2, (Ty::Str, Ty::Str) | (Ty::Never, Ty::Never) => true, (Ty::Scalar(scalar), Ty::Scalar(scalar2)) => scalar == scalar2, @@ -722,17 +740,15 @@ pub fn as_fn_def(&self) -> Option { } } - pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option { + pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option { match self { - Ty::FnPtr { is_varargs, substs: parameters, .. } => { - Some(FnSig::from_fn_ptr_substs(¶meters, *is_varargs)) - } + Ty::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)), Ty::FnDef(def, parameters) => { let sig = db.callable_item_signature(*def); Some(sig.subst(¶meters)) } - Ty::Closure { substs: parameters, .. } => { - let sig_param = ¶meters[0]; + Ty::Closure(.., substs) => { + let sig_param = &substs[0]; sig_param.callable_sig(db) } _ => None, @@ -751,11 +767,11 @@ pub fn apply_substs(mut self, new_substs: Substs) -> Ty { | Ty::RawPtr(_, substs) | Ty::Ref(_, substs) | Ty::FnDef(_, substs) - | Ty::FnPtr { substs, .. } + | Ty::Function(FnPointer { substs, .. }) | Ty::Tuple(_, substs) | Ty::OpaqueType(_, substs) | Ty::AssociatedType(_, substs) - | Ty::Closure { substs, .. } => { + | Ty::Closure(.., substs) => { assert_eq!(substs.len(), new_substs.len()); *substs = new_substs; } @@ -774,11 +790,11 @@ pub fn substs(&self) -> Option<&Substs> { | Ty::RawPtr(_, substs) | Ty::Ref(_, substs) | Ty::FnDef(_, substs) - | Ty::FnPtr { substs, .. } + | Ty::Function(FnPointer { substs, .. }) | Ty::Tuple(_, substs) | Ty::OpaqueType(_, substs) | Ty::AssociatedType(_, substs) - | Ty::Closure { substs, .. } => Some(substs), + | Ty::Closure(.., substs) => Some(substs), _ => None, } } @@ -791,11 +807,11 @@ pub fn substs_mut(&mut self) -> Option<&mut Substs> { | Ty::RawPtr(_, substs) | Ty::Ref(_, substs) | Ty::FnDef(_, substs) - | Ty::FnPtr { substs, .. } + | Ty::Function(FnPointer { substs, .. }) | Ty::Tuple(_, substs) | Ty::OpaqueType(_, substs) | Ty::AssociatedType(_, substs) - | Ty::Closure { substs, .. } => Some(substs), + | Ty::Closure(.., substs) => Some(substs), _ => None, } } diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 84734bc0bd1..44bd95a9ab2 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -31,9 +31,9 @@ all_super_trait_refs, associated_type_by_name_including_super_traits, generics, make_mut_slice, variant_data, }, - Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, OpaqueTy, OpaqueTyId, PolyFnSig, - ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substs, - TraitEnvironment, TraitRef, Ty, TypeWalk, + Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate, OpaqueTy, + OpaqueTyId, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, + ReturnTypeImplTraits, Substs, TraitEnvironment, TraitRef, Ty, TypeWalk, }; #[derive(Debug)] @@ -173,8 +173,12 @@ pub fn from_hir_ext(ctx: &TyLoweringContext<'_>, type_ref: &TypeRef) -> (Self, O } TypeRef::Placeholder => Ty::Unknown, TypeRef::Fn(params, is_varargs) => { - let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); - Ty::FnPtr { num_args: sig.len() as u16 - 1, is_varargs: *is_varargs, substs: sig } + let substs = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); + Ty::Function(FnPointer { + num_args: substs.len() - 1, + sig: FnSig { variadic: *is_varargs }, + substs, + }) } TypeRef::DynTrait(bounds) => { let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); @@ -1010,7 +1014,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { let ret = Ty::from_hir(&ctx_ret, &data.ret_type); let generics = generics(db.upcast(), def.into()); let num_binders = generics.len(); - Binders::new(num_binders, FnSig::from_params_and_return(params, ret, data.is_varargs)) + Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs)) } /// Build the declared type of a function. This should not need to look at the @@ -1050,7 +1054,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS let params = fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::>(); let ret = type_for_adt(db, def.into()); - Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false)) + Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false)) } /// Build the type of a tuple struct constructor. @@ -1074,7 +1078,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) let params = fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::>(); let ret = type_for_adt(db, def.parent.into()); - Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false)) + Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false)) } /// Build the type of a tuple enum variant constructor. diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index ff8ce5599b1..c8a0ad5f1f7 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -18,8 +18,8 @@ db::HirDatabase, primitive::{self, FloatTy, IntTy, UintTy}, utils::all_super_traits, - Canonical, DebruijnIndex, InEnvironment, Scalar, Substs, TraitEnvironment, TraitRef, Ty, - TyKind, TypeWalk, + Canonical, DebruijnIndex, FnPointer, FnSig, InEnvironment, Scalar, Substs, TraitEnvironment, + TraitRef, Ty, TyKind, TypeWalk, }; /// This is used as a key for indexing impls. @@ -35,7 +35,7 @@ pub enum TyFingerprint { Dyn(TraitId), Tuple(usize), ForeignType(TypeAliasId), - FnPtr { num_args: u16, is_varargs: bool }, + FnPtr(usize, FnSig), } impl TyFingerprint { @@ -53,9 +53,7 @@ pub(crate) fn for_impl(ty: &Ty) -> Option { &Ty::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality), &Ty::RawPtr(mutability, ..) => TyFingerprint::RawPtr(mutability), &Ty::ForeignType(alias_id, ..) => TyFingerprint::ForeignType(alias_id), - &Ty::FnPtr { num_args, is_varargs, .. } => { - TyFingerprint::FnPtr { num_args, is_varargs } - } + &Ty::Function(FnPointer { num_args, sig, .. }) => TyFingerprint::FnPtr(num_args, sig), Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?, _ => return None, }; diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index c53e327daf7..3f5f5091f97 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs @@ -19,7 +19,7 @@ display::HirDisplay, method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, utils::generics, - BoundVar, CallableDefId, DebruijnIndex, FnSig, GenericPredicate, ProjectionPredicate, + BoundVar, CallableDefId, CallableSig, DebruijnIndex, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, }; use mapping::{ @@ -286,9 +286,8 @@ fn closure_inputs_and_output( ) -> chalk_ir::Binders> { let sig_ty: Ty = from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone()); - let sig = FnSig::from_fn_ptr_substs( + let sig = CallableSig::from_substs( &sig_ty.substs().expect("first closure param should be fn ptr"), - false, ); let io = rust_ir::FnDefInputsAndOutputDatum { argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(), diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index c17c196385f..60d74e21abd 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs @@ -16,8 +16,8 @@ db::HirDatabase, primitive::UintTy, traits::{Canonical, Obligation}, - CallableDefId, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId, ProjectionPredicate, - ProjectionTy, Scalar, Substs, TraitEnvironment, TraitRef, Ty, TyKind, + CallableDefId, FnPointer, FnSig, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId, + ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, TraitRef, Ty, TyKind, }; use super::interner::*; @@ -29,15 +29,11 @@ fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty { match self { Ty::Ref(m, parameters) => ref_to_chalk(db, m, parameters), Ty::Array(parameters) => array_to_chalk(db, parameters), - Ty::FnPtr { num_args: _, is_varargs, substs } => { + Ty::Function(FnPointer { sig: FnSig { variadic }, substs, .. }) => { let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner)); chalk_ir::TyKind::Function(chalk_ir::FnPointer { num_binders: 0, - sig: chalk_ir::FnSig { - abi: (), - safety: chalk_ir::Safety::Safe, - variadic: is_varargs, - }, + sig: chalk_ir::FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic }, substitution, }) .intern(&Interner) @@ -82,7 +78,7 @@ fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty { } Ty::Never => chalk_ir::TyKind::Never.intern(&Interner), - Ty::Closure { def, expr, substs } => { + Ty::Closure(def, expr, substs) => { let closure_id = db.intern_closure((def, expr)); let substitution = substs.to_chalk(db); chalk_ir::TyKind::Closure(closure_id.into(), substitution).intern(&Interner) @@ -164,15 +160,15 @@ fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty) -> Self { .. }) => { assert_eq!(num_binders, 0); - let parameters: Substs = from_chalk( + let substs: Substs = from_chalk( db, substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"), ); - Ty::FnPtr { - num_args: (parameters.len() - 1) as u16, - is_varargs: variadic, - substs: parameters, - } + Ty::Function(FnPointer { + num_args: (substs.len() - 1), + sig: FnSig { variadic }, + substs, + }) } chalk_ir::TyKind::BoundVar(idx) => Ty::Bound(idx), chalk_ir::TyKind::InferenceVar(_iv, _kind) => Ty::Unknown, @@ -218,7 +214,7 @@ fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty) -> Self { chalk_ir::TyKind::Closure(id, subst) => { let id: crate::db::ClosureId = id.into(); let (def, expr) = db.lookup_intern_closure(id); - Ty::Closure { def, expr, substs: from_chalk(db, subst) } + Ty::Closure(def, expr, from_chalk(db, subst)) } chalk_ir::TyKind::Foreign(foreign_def_id) => {