diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs index 935a8ebad1..17ff736aae 100644 --- a/crates/hir-def/src/hir/type_ref.rs +++ b/crates/hir-def/src/hir/type_ref.rs @@ -10,7 +10,7 @@ use hir_expand::{ AstId, }; use intern::Interned; -use syntax::ast::{self, HasName}; +use syntax::ast::{self, HasName, IsString}; use crate::{ builtin_type::{BuiltinInt, BuiltinType, BuiltinUint}, @@ -120,7 +120,12 @@ pub enum TypeRef { Array(Box, ConstRef), Slice(Box), /// A fn pointer. Last element of the vector is the return type. - Fn(Vec<(Option, TypeRef)>, bool /*varargs*/, bool /*is_unsafe*/), + Fn( + Vec<(Option, TypeRef)>, + bool, /*varargs*/ + bool, /*is_unsafe*/ + Option>, /* abi */ + ), ImplTrait(Vec>), DynTrait(Vec>), Macro(AstId), @@ -225,8 +230,17 @@ impl TypeRef { } else { Vec::new() }; + fn lower_abi(abi: ast::Abi) -> Interned { + match abi.abi_string() { + Some(tok) => Interned::new_str(tok.text_without_quotes()), + // `extern` default to be `extern "C"`. + _ => Interned::new_str("C"), + } + } + + let abi = inner.abi().map(lower_abi); params.push((None, ret_ty)); - TypeRef::Fn(params, is_varargs, inner.unsafe_token().is_some()) + TypeRef::Fn(params, is_varargs, inner.unsafe_token().is_some(), abi) } // for types are close enough for our purposes to the inner type for now... ast::Type::ForType(inner) => TypeRef::from_ast_opt(ctx, inner.ty()), @@ -260,7 +274,7 @@ impl TypeRef { fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) { f(type_ref); match type_ref { - TypeRef::Fn(params, _, _) => { + TypeRef::Fn(params, _, _, _) => { params.iter().for_each(|(_, param_type)| go(param_type, f)) } TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)), diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index f6086ed6d9..b500f56b6c 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -3,7 +3,7 @@ use std::collections::hash_map::Entry; use hir_expand::{ast_id_map::AstIdMap, span_map::SpanMapRef, HirFileId}; -use syntax::ast::{self, HasModuleItem, HasTypeBounds}; +use syntax::ast::{self, HasModuleItem, HasTypeBounds, IsString}; use crate::{ generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance}, @@ -721,16 +721,10 @@ enum HasImplicitSelf { } fn lower_abi(abi: ast::Abi) -> Interned { - // FIXME: Abi::abi() -> Option? - match abi.syntax().last_token() { - Some(tok) if tok.kind() == SyntaxKind::STRING => { - // FIXME: Better way to unescape? - Interned::new_str(tok.text().trim_matches('"')) - } - _ => { - // `extern` default to be `extern "C"`. - Interned::new_str("C") - } + match abi.abi_string() { + Some(tok) => Interned::new_str(tok.text_without_quotes()), + // `extern` default to be `extern "C"`. + _ => Interned::new_str("C"), } } diff --git a/crates/hir-def/src/pretty.rs b/crates/hir-def/src/pretty.rs index 8e0df46970..d3135bba96 100644 --- a/crates/hir-def/src/pretty.rs +++ b/crates/hir-def/src/pretty.rs @@ -192,12 +192,17 @@ pub(crate) fn print_type_ref( print_type_ref(db, elem, buf)?; write!(buf, "]")?; } - TypeRef::Fn(args_and_ret, varargs, is_unsafe) => { + TypeRef::Fn(args_and_ret, varargs, is_unsafe, abi) => { let ((_, return_type), args) = args_and_ret.split_last().expect("TypeRef::Fn is missing return type"); if *is_unsafe { write!(buf, "unsafe ")?; } + if let Some(abi) = abi { + buf.write_str("extern ")?; + buf.write_str(abi)?; + buf.write_char(' ')?; + } write!(buf, "fn(")?; for (i, (_, typeref)) in args.iter().enumerate() { if i != 0 { diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index f475c1c178..4d509f20d0 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -819,7 +819,11 @@ pub(crate) fn fn_def_datum_query( }; let datum = FnDefDatum { id: fn_def_id, - sig: chalk_ir::FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: sig.is_varargs }, + sig: chalk_ir::FnSig { + abi: sig.abi, + safety: chalk_ir::Safety::Safe, + variadic: sig.is_varargs, + }, binders: chalk_ir::Binders::new(binders, bound), }; Arc::new(datum) diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs index d6d0b34934..795a599691 100644 --- a/crates/hir-ty/src/chalk_ext.rs +++ b/crates/hir-ty/src/chalk_ext.rs @@ -202,11 +202,7 @@ impl TyExt for Ty { fn callable_sig(&self, db: &dyn HirDatabase) -> Option { match self.kind(Interner) { TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)), - TyKind::FnDef(def, parameters) => { - let callable_def = db.lookup_intern_callable_def((*def).into()); - let sig = db.callable_item_signature(callable_def); - Some(sig.substitute(Interner, parameters)) - } + TyKind::FnDef(def, parameters) => Some(CallableSig::from_def(db, *def, parameters)), TyKind::Closure(.., substs) => ClosureSubst(substs).sig_ty().callable_sig(db), _ => None, } diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 750e159727..a630db05de 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -8,7 +8,7 @@ use std::{ }; use base_db::CrateId; -use chalk_ir::{BoundVar, TyKind}; +use chalk_ir::{BoundVar, Safety, TyKind}; use hir_def::{ data::adt::VariantData, db::DefDatabase, @@ -41,7 +41,7 @@ use crate::{ primitive, to_assoc_type_id, utils::{self, detect_variant_from_bytes, generics, ClosureSubst}, AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstScalar, ConstValue, - DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives, + DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause, }; @@ -879,16 +879,27 @@ impl HirDisplay for Ty { // function pointer type. return sig.hir_fmt(f); } + if let Safety::Unsafe = sig.safety { + write!(f, "unsafe ")?; + } + if !matches!(sig.abi, FnAbi::Rust) { + f.write_str("extern \"")?; + f.write_str(sig.abi.as_str())?; + f.write_str("\" ")?; + } - f.start_location_link(def.into()); match def { CallableDefId::FunctionId(ff) => { - write!(f, "fn {}", db.function_data(ff).name.display(f.db.upcast()))? + write!(f, "fn ")?; + f.start_location_link(def.into()); + write!(f, "{}", db.function_data(ff).name.display(f.db.upcast()))? } CallableDefId::StructId(s) => { + f.start_location_link(def.into()); write!(f, "{}", db.struct_data(s).name.display(f.db.upcast()))? } CallableDefId::EnumVariantId(e) => { + f.start_location_link(def.into()); write!(f, "{}", db.enum_variant_data(e).name.display(f.db.upcast()))? } }; @@ -1316,9 +1327,19 @@ fn hir_fmt_generics( impl HirDisplay for CallableSig { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { + let CallableSig { params_and_return: _, is_varargs, safety, abi: _ } = *self; + if let Safety::Unsafe = safety { + write!(f, "unsafe ")?; + } + // FIXME: Enable this when the FIXME on FnAbi regarding PartialEq is fixed. + // if !matches!(abi, FnAbi::Rust) { + // f.write_str("extern \"")?; + // f.write_str(abi.as_str())?; + // f.write_str("\" ")?; + // } write!(f, "fn(")?; f.write_joined(self.params(), ", ")?; - if self.is_varargs { + if is_varargs { if self.params().is_empty() { write!(f, "...")?; } else { @@ -1683,11 +1704,15 @@ impl HirDisplay for TypeRef { inner.hir_fmt(f)?; write!(f, "]")?; } - &TypeRef::Fn(ref parameters, is_varargs, is_unsafe) => { - // FIXME: Function pointer qualifiers. + &TypeRef::Fn(ref parameters, is_varargs, is_unsafe, ref abi) => { if is_unsafe { write!(f, "unsafe ")?; } + if let Some(abi) = abi { + f.write_str("extern \"")?; + f.write_str(abi)?; + f.write_str("\" ")?; + } write!(f, "fn(")?; if let Some(((_, return_type), function_parameters)) = parameters.split_last() { for index in 0..function_parameters.len() { diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index c3ef6c9b35..0d89269b32 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -1453,10 +1453,10 @@ impl Expectation { match self { Expectation::HasType(ety) => { let ety = table.resolve_ty_shallow(ety); - if !ety.is_ty_var() { - Expectation::HasType(ety) - } else { + if ety.is_ty_var() { Expectation::None + } else { + Expectation::HasType(ety) } } Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()), diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 4ec82865ac..d6d021340d 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -27,8 +27,8 @@ use crate::{ static_lifetime, to_chalk_trait_id, traits::FnTrait, utils::{self, generics, Generics}, - Adjust, Adjustment, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, FnPointer, FnSig, - Interner, Substitution, Ty, TyExt, + Adjust, Adjustment, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, FnAbi, FnPointer, + FnSig, Interner, Substitution, Ty, TyExt, }; use super::{Expectation, InferenceContext}; @@ -98,7 +98,11 @@ impl InferenceContext<'_> { cov_mark::hit!(dyn_fn_param_informs_call_site_closure_signature); return Some(FnPointer { num_binders: bound.len(Interner), - sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, + sig: FnSig { + abi: FnAbi::RustCall, + safety: chalk_ir::Safety::Safe, + variadic: false, + }, substitution: FnSubst(Substitution::from_iter(Interner, sig_tys)), }); } diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs index 8e7e62c496..61638c43d9 100644 --- a/crates/hir-ty/src/infer/coerce.rs +++ b/crates/hir-ty/src/infer/coerce.rs @@ -24,7 +24,7 @@ use crate::{ }, static_lifetime, utils::ClosureSubst, - Canonical, DomainGoal, FnPointer, FnSig, Guidance, InEnvironment, Interner, Solution, + Canonical, DomainGoal, FnAbi, FnPointer, FnSig, Guidance, InEnvironment, Interner, Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, }; @@ -691,7 +691,7 @@ fn coerce_closure_fn_ty(closure_substs: &Substitution, safety: chalk_ir::Safety) match closure_sig.kind(Interner) { TyKind::Function(fn_ty) => TyKind::Function(FnPointer { num_binders: fn_ty.num_binders, - sig: FnSig { safety, ..fn_ty.sig }, + sig: FnSig { safety, abi: FnAbi::Rust, variadic: fn_ty.sig.variadic }, substitution: fn_ty.substitution.clone(), }) .intern(Interner), diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index a655d1614a..bf64795a4b 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -39,9 +39,9 @@ use crate::{ static_lifetime, to_chalk_trait_id, traits::FnTrait, utils::{generics, Generics}, - Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnPointer, FnSig, FnSubst, - Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, - TyKind, + Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnAbi, FnPointer, FnSig, + FnSubst, Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, + TyExt, TyKind, }; use super::{ @@ -224,7 +224,11 @@ impl InferenceContext<'_> { let sig_ty = TyKind::Function(FnPointer { num_binders: 0, - sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, + sig: FnSig { + abi: FnAbi::RustCall, + safety: chalk_ir::Safety::Safe, + variadic: false, + }, substitution: FnSubst( Substitution::from_iter(Interner, sig_tys.iter().cloned()) .shifted_in(Interner), diff --git a/crates/hir-ty/src/interner.rs b/crates/hir-ty/src/interner.rs index 3d16fec790..7f994783c1 100644 --- a/crates/hir-ty/src/interner.rs +++ b/crates/hir-ty/src/interner.rs @@ -3,8 +3,8 @@ use crate::{ chalk_db, tls, AliasTy, CanonicalVarKind, CanonicalVarKinds, ClosureId, Const, ConstData, - ConstScalar, Constraint, Constraints, FnDefId, GenericArg, GenericArgData, Goal, GoalData, - Goals, InEnvironment, Lifetime, LifetimeData, OpaqueTy, OpaqueTyId, ProgramClause, + ConstScalar, Constraint, Constraints, FnAbi, FnDefId, GenericArg, GenericArgData, Goal, + GoalData, Goals, InEnvironment, Lifetime, LifetimeData, OpaqueTy, OpaqueTyId, ProgramClause, ProgramClauseData, ProgramClauses, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution, Ty, TyData, TyKind, VariableKind, VariableKinds, }; @@ -71,7 +71,7 @@ impl chalk_ir::interner::Interner for Interner { type DefId = InternId; type InternedAdtId = hir_def::AdtId; type Identifier = TypeAliasId; - type FnAbi = (); + type FnAbi = FnAbi; fn debug_adt_id( type_kind_id: chalk_db::AdtId, diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index a50e1b1c07..61055583fc 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -351,10 +351,156 @@ pub struct CallableSig { params_and_return: Arc<[Ty]>, is_varargs: bool, safety: Safety, + abi: FnAbi, } has_interner!(CallableSig); +#[derive(Debug, Copy, Clone, Eq)] +pub enum FnAbi { + Aapcs, + AapcsUnwind, + AmdgpuKernel, + AvrInterrupt, + AvrNonBlockingInterrupt, + C, + CCmseNonsecureCall, + CDecl, + CDeclUnwind, + CUnwind, + Efiapi, + Fastcall, + FastcallUnwind, + Msp430Interrupt, + PlatformIntrinsic, + PtxKernel, + RiscvInterruptM, + RiscvInterruptS, + Rust, + RustCall, + RustCold, + RustIntrinsic, + Stdcall, + StdcallUnwind, + System, + SystemUnwind, + Sysv64, + Sysv64Unwind, + Thiscall, + ThiscallUnwind, + Unadjusted, + Vectorcall, + VectorcallUnwind, + Wasm, + Win64, + Win64Unwind, + X86Interrupt, + Unknown, +} + +impl PartialEq for FnAbi { + fn eq(&self, _other: &Self) -> bool { + // FIXME: Proper equality breaks `coercion::two_closures_lub` test + true + } +} + +impl Hash for FnAbi { + fn hash(&self, state: &mut H) { + // Required because of the FIXME above and due to us implementing `Eq`, without this + // we would break the `Hash` + `Eq` contract + core::mem::discriminant(&Self::Unknown).hash(state); + } +} + +impl FnAbi { + pub fn from_str(s: &str) -> FnAbi { + match s { + "aapcs-unwind" => FnAbi::AapcsUnwind, + "aapcs" => FnAbi::Aapcs, + "amdgpu-kernel" => FnAbi::AmdgpuKernel, + "avr-interrupt" => FnAbi::AvrInterrupt, + "avr-non-blocking-interrupt" => FnAbi::AvrNonBlockingInterrupt, + "C-cmse-nonsecure-call" => FnAbi::CCmseNonsecureCall, + "C-unwind" => FnAbi::CUnwind, + "C" => FnAbi::C, + "cdecl-unwind" => FnAbi::CDeclUnwind, + "cdecl" => FnAbi::CDecl, + "efiapi" => FnAbi::Efiapi, + "fastcall-unwind" => FnAbi::FastcallUnwind, + "fastcall" => FnAbi::Fastcall, + "msp430-interrupt" => FnAbi::Msp430Interrupt, + "platform-intrinsic" => FnAbi::PlatformIntrinsic, + "ptx-kernel" => FnAbi::PtxKernel, + "riscv-interrupt-m" => FnAbi::RiscvInterruptM, + "riscv-interrupt-s" => FnAbi::RiscvInterruptS, + "rust-call" => FnAbi::RustCall, + "rust-cold" => FnAbi::RustCold, + "rust-intrinsic" => FnAbi::RustIntrinsic, + "Rust" => FnAbi::Rust, + "stdcall-unwind" => FnAbi::StdcallUnwind, + "stdcall" => FnAbi::Stdcall, + "system-unwind" => FnAbi::SystemUnwind, + "system" => FnAbi::System, + "sysv64-unwind" => FnAbi::Sysv64Unwind, + "sysv64" => FnAbi::Sysv64, + "thiscall-unwind" => FnAbi::ThiscallUnwind, + "thiscall" => FnAbi::Thiscall, + "unadjusted" => FnAbi::Unadjusted, + "vectorcall-unwind" => FnAbi::VectorcallUnwind, + "vectorcall" => FnAbi::Vectorcall, + "wasm" => FnAbi::Wasm, + "win64-unwind" => FnAbi::Win64Unwind, + "win64" => FnAbi::Win64, + "x86-interrupt" => FnAbi::X86Interrupt, + _ => FnAbi::Unknown, + } + } + + pub fn as_str(self) -> &'static str { + match self { + FnAbi::Aapcs => "aapcs", + FnAbi::AapcsUnwind => "aapcs-unwind", + FnAbi::AmdgpuKernel => "amdgpu-kernel", + FnAbi::AvrInterrupt => "avr-interrupt", + FnAbi::AvrNonBlockingInterrupt => "avr-non-blocking-interrupt", + FnAbi::C => "C", + FnAbi::CCmseNonsecureCall => "C-cmse-nonsecure-call", + FnAbi::CDecl => "C-decl", + FnAbi::CDeclUnwind => "cdecl-unwind", + FnAbi::CUnwind => "C-unwind", + FnAbi::Efiapi => "efiapi", + FnAbi::Fastcall => "fastcall", + FnAbi::FastcallUnwind => "fastcall-unwind", + FnAbi::Msp430Interrupt => "msp430-interrupt", + FnAbi::PlatformIntrinsic => "platform-intrinsic", + FnAbi::PtxKernel => "ptx-kernel", + FnAbi::RiscvInterruptM => "riscv-interrupt-m", + FnAbi::RiscvInterruptS => "riscv-interrupt-s", + FnAbi::Rust => "Rust", + FnAbi::RustCall => "rust-call", + FnAbi::RustCold => "rust-cold", + FnAbi::RustIntrinsic => "rust-intrinsic", + FnAbi::Stdcall => "stdcall", + FnAbi::StdcallUnwind => "stdcall-unwind", + FnAbi::System => "system", + FnAbi::SystemUnwind => "system-unwind", + FnAbi::Sysv64 => "sysv64", + FnAbi::Sysv64Unwind => "sysv64-unwind", + FnAbi::Thiscall => "thiscall", + FnAbi::ThiscallUnwind => "thiscall-unwind", + FnAbi::Unadjusted => "unadjusted", + FnAbi::Vectorcall => "vectorcall", + FnAbi::VectorcallUnwind => "vectorcall-unwind", + FnAbi::Wasm => "wasm", + FnAbi::Win64 => "win64", + FnAbi::Win64Unwind => "win64-unwind", + FnAbi::X86Interrupt => "x86-interrupt", + FnAbi::Unknown => "unknown-abi", + } + } +} + /// A polymorphic function signature. pub type PolyFnSig = Binders; @@ -364,11 +510,17 @@ impl CallableSig { ret: Ty, is_varargs: bool, safety: Safety, + abi: FnAbi, ) -> CallableSig { params.push(ret); - CallableSig { params_and_return: params.into(), is_varargs, safety } + CallableSig { params_and_return: params.into(), is_varargs, safety, abi } } + pub fn from_def(db: &dyn HirDatabase, def: FnDefId, substs: &Substitution) -> CallableSig { + let callable_def = db.lookup_intern_callable_def(def.into()); + let sig = db.callable_item_signature(callable_def); + sig.substitute(Interner, substs) + } pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { CallableSig { // FIXME: what to do about lifetime params? -> return PolyFnSig @@ -385,13 +537,14 @@ impl CallableSig { ), is_varargs: fn_ptr.sig.variadic, safety: fn_ptr.sig.safety, + abi: fn_ptr.sig.abi, } } pub fn to_fn_ptr(&self) -> FnPointer { FnPointer { num_binders: 0, - sig: FnSig { abi: (), safety: self.safety, variadic: self.is_varargs }, + sig: FnSig { abi: self.abi, safety: self.safety, variadic: self.is_varargs }, substitution: FnSubst(Substitution::from_iter( Interner, self.params_and_return.iter().cloned(), @@ -420,6 +573,7 @@ impl TypeFoldable for CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs, safety: self.safety, + abi: self.abi, }) } } @@ -704,7 +858,7 @@ pub fn callable_sig_from_fnonce( let params = args_ty.as_tuple()?.iter(Interner).map(|it| it.assert_ty_ref(Interner)).cloned().collect(); - Some(CallableSig::from_params_and_return(params, ret_ty, false, Safety::Safe)) + Some(CallableSig::from_params_and_return(params, ret_ty, false, Safety::Safe, FnAbi::RustCall)) } struct PlaceholderCollector<'db> { diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 2d43fffa6a..46f5830ef7 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -58,7 +58,7 @@ use crate::{ InTypeConstIdMetadata, }, AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, - FnPointer, FnSig, FnSubst, ImplTraitId, Interner, ParamKind, PolyFnSig, ProjectionTy, + FnAbi, FnPointer, FnSig, FnSubst, ImplTraitId, Interner, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, }; @@ -279,14 +279,14 @@ impl<'a> TyLoweringContext<'a> { .intern(Interner) } TypeRef::Placeholder => TyKind::Error.intern(Interner), - &TypeRef::Fn(ref params, variadic, is_unsafe) => { + &TypeRef::Fn(ref params, variadic, is_unsafe, ref abi) => { let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { Substitution::from_iter(Interner, params.iter().map(|(_, tr)| ctx.lower_ty(tr))) }); TyKind::Function(FnPointer { num_binders: 0, // FIXME lower `for<'a> fn()` correctly sig: FnSig { - abi: (), + abi: abi.as_deref().map_or(FnAbi::Rust, FnAbi::from_str), safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe }, variadic, }, @@ -1675,6 +1675,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { ret, data.is_varargs(), if data.has_unsafe_kw() { Safety::Unsafe } else { Safety::Safe }, + data.abi.as_deref().map_or(FnAbi::Rust, FnAbi::from_str), ); make_binders(db, &generics, sig) } @@ -1719,7 +1720,10 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS .with_type_param_mode(ParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::>(); let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders(); - Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe)) + Binders::new( + binders, + CallableSig::from_params_and_return(params, ret, false, Safety::Safe, FnAbi::RustCall), + ) } /// Build the type of a tuple struct constructor. @@ -1749,7 +1753,10 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::>(); let (ret, binders) = type_for_adt(db, def.lookup(db.upcast()).parent.into()).into_value_and_skipped_binders(); - Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe)) + Binders::new( + binders, + CallableSig::from_params_and_return(params, ret, false, Safety::Safe, FnAbi::RustCall), + ) } /// Build the type of a tuple enum variant constructor. diff --git a/crates/hir-ty/src/tests/coercion.rs b/crates/hir-ty/src/tests/coercion.rs index f020247167..d56b15b9b7 100644 --- a/crates/hir-ty/src/tests/coercion.rs +++ b/crates/hir-ty/src/tests/coercion.rs @@ -574,6 +574,7 @@ fn two_closures_lub() { r#" fn foo(c: i32) { let add = |a: i32, b: i32| a + b; + //^^^^^^^^^^^^^^^^^^^^^^ impl Fn(i32, i32) -> i32 let sub = |a, b| a - b; //^^^^^^^^^^^^ impl Fn(i32, i32) -> i32 if c > 42 { add } else { sub }; diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs index 622b4f56d4..b0a9361f1c 100644 --- a/crates/hir-ty/src/tests/macros.rs +++ b/crates/hir-ty/src/tests/macros.rs @@ -64,7 +64,7 @@ fn infer_macros_expanded() { "#, expect![[r#" !0..17 '{Foo(v...,2,])}': Foo - !1..4 'Foo': Foo({unknown}) -> Foo + !1..4 'Foo': extern "rust-call" Foo({unknown}) -> Foo !1..16 'Foo(vec![1,2,])': Foo !5..15 'vec![1,2,]': {unknown} 155..181 '{ ...,2); }': () @@ -97,7 +97,7 @@ fn infer_legacy_textual_scoped_macros_expanded() { "#, expect![[r#" !0..17 '{Foo(v...,2,])}': Foo - !1..4 'Foo': Foo({unknown}) -> Foo + !1..4 'Foo': extern "rust-call" Foo({unknown}) -> Foo !1..16 'Foo(vec![1,2,])': Foo !5..15 'vec![1,2,]': {unknown} 194..250 '{ ...,2); }': () diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs index 548f782f4f..0690073082 100644 --- a/crates/hir-ty/src/tests/patterns.rs +++ b/crates/hir-ty/src/tests/patterns.rs @@ -210,13 +210,13 @@ fn infer_pattern_match_ergonomics() { 37..41 'A(n)': A 39..40 'n': &i32 44..49 '&A(1)': &A - 45..46 'A': A(i32) -> A + 45..46 'A': extern "rust-call" A(i32) -> A 45..49 'A(1)': A 47..48 '1': i32 59..63 'A(n)': A 61..62 'n': &mut i32 66..75 '&mut A(1)': &mut A - 71..72 'A': A(i32) -> A + 71..72 'A': extern "rust-call" A(i32) -> A 71..75 'A(1)': A 73..74 '1': i32 "#]], @@ -531,18 +531,18 @@ impl Foo { 56..64 'Self(s,)': Foo 61..62 's': &usize 67..75 '&Foo(0,)': &Foo - 68..71 'Foo': Foo(usize) -> Foo + 68..71 'Foo': extern "rust-call" Foo(usize) -> Foo 68..75 'Foo(0,)': Foo 72..73 '0': usize 89..97 'Self(s,)': Foo 94..95 's': &mut usize 100..112 '&mut Foo(0,)': &mut Foo - 105..108 'Foo': Foo(usize) -> Foo + 105..108 'Foo': extern "rust-call" Foo(usize) -> Foo 105..112 'Foo(0,)': Foo 109..110 '0': usize 126..134 'Self(s,)': Foo 131..132 's': usize - 137..140 'Foo': Foo(usize) -> Foo + 137..140 'Foo': extern "rust-call" Foo(usize) -> Foo 137..144 'Foo(0,)': Foo 141..142 '0': usize "#]], @@ -916,7 +916,7 @@ fn foo(foo: Foo) { 48..51 'foo': Foo 62..84 'const ... 32) }': Foo 68..84 '{ Foo(... 32) }': Foo - 70..73 'Foo': Foo(usize) -> Foo + 70..73 'Foo': extern "rust-call" Foo(usize) -> Foo 70..82 'Foo(15 + 32)': Foo 74..76 '15': usize 74..81 '15 + 32': usize diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index b0532ddcb3..2ad9a7fe52 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -644,7 +644,7 @@ fn issue_4953() { "#, expect![[r#" 58..72 '{ Self(0i64) }': Foo - 60..64 'Self': Foo(i64) -> Foo + 60..64 'Self': extern "rust-call" Foo(i64) -> Foo 60..70 'Self(0i64)': Foo 65..69 '0i64': i64 "#]], @@ -658,7 +658,7 @@ fn issue_4953() { "#, expect![[r#" 64..78 '{ Self(0i64) }': Foo - 66..70 'Self': Foo(i64) -> Foo + 66..70 'Self': extern "rust-call" Foo(i64) -> Foo 66..76 'Self(0i64)': Foo 71..75 '0i64': i64 "#]], @@ -858,7 +858,7 @@ fn main() { 94..96 '{}': () 109..160 '{ ...10); }': () 119..120 's': S - 123..124 'S': S() -> S + 123..124 'S': extern "rust-call" S() -> S 123..126 'S()': S 132..133 's': S 132..144 's.g(|_x| {})': () @@ -1689,18 +1689,18 @@ fn main() { } "#, expect![[r#" - 27..85 '{ ...1,); }': () - 37..48 'S(.., a, b)': S - 43..44 'a': usize - 46..47 'b': {unknown} - 51..52 'S': S(usize) -> S - 51..55 'S(1)': S - 53..54 '1': usize - 65..75 '(.., a, b)': (i32, {unknown}) - 70..71 'a': i32 - 73..74 'b': {unknown} - 78..82 '(1,)': (i32,) - 79..80 '1': i32 + 27..85 '{ ...1,); }': () + 37..48 'S(.., a, b)': S + 43..44 'a': usize + 46..47 'b': {unknown} + 51..52 'S': extern "rust-call" S(usize) -> S + 51..55 'S(1)': S + 53..54 '1': usize + 65..75 '(.., a, b)': (i32, {unknown}) + 70..71 'a': i32 + 73..74 'b': {unknown} + 78..82 '(1,)': (i32,) + 79..80 '1': i32 "#]], ); } diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs index f9ab6d8dc8..8474782282 100644 --- a/crates/hir-ty/src/tests/simple.rs +++ b/crates/hir-ty/src/tests/simple.rs @@ -236,14 +236,14 @@ fn test() { expect![[r#" 71..153 '{ ...a.c; }': () 81..82 'c': C - 85..86 'C': C(usize) -> C + 85..86 'C': extern "rust-call" C(usize) -> C 85..89 'C(1)': C 87..88 '1': usize 95..96 'B': B 106..107 'a': A 113..132 'A { b:...C(1) }': A 120..121 'B': B - 126..127 'C': C(usize) -> C + 126..127 'C': extern "rust-call" C(usize) -> C 126..130 'C(1)': C 128..129 '1': usize 138..139 'a': A @@ -303,14 +303,14 @@ unsafe fn baz(u: MyUnion) { 71..89 'MyUnio...o: 0 }': MyUnion 86..87 '0': u32 95..113 'unsafe...(u); }': () - 104..107 'baz': fn baz(MyUnion) + 104..107 'baz': unsafe fn baz(MyUnion) 104..110 'baz(u)': () 108..109 'u': MyUnion 122..123 'u': MyUnion 126..146 'MyUnio... 0.0 }': MyUnion 141..144 '0.0': f32 152..170 'unsafe...(u); }': () - 161..164 'baz': fn baz(MyUnion) + 161..164 'baz': unsafe fn baz(MyUnion) 161..167 'baz(u)': () 165..166 'u': MyUnion 188..189 'u': MyUnion @@ -625,12 +625,12 @@ impl E { 86..107 '{ ... }': () 96..100 'Self': S1 134..158 '{ ... }': () - 144..148 'Self': S2(isize) -> S2 + 144..148 'Self': extern "rust-call" S2(isize) -> S2 144..151 'Self(1)': S2 149..150 '1': isize 184..230 '{ ... }': () 194..202 'Self::V1': E - 212..220 'Self::V2': V2(u32) -> E + 212..220 'Self::V2': extern "rust-call" V2(u32) -> E 212..223 'Self::V2(1)': E 221..222 '1': u32 "#]], @@ -856,11 +856,11 @@ fn test() { 256..277 'A::foo...42))))': &i32 263..276 '&&B(B(A(42)))': &&B>> 264..276 '&B(B(A(42)))': &B>> - 265..266 'B': B>>(B>) -> B>> + 265..266 'B': extern "rust-call" B>>(B>) -> B>> 265..276 'B(B(A(42)))': B>> - 267..268 'B': B>(A) -> B> + 267..268 'B': extern "rust-call" B>(A) -> B> 267..275 'B(A(42))': B> - 269..270 'A': A(i32) -> A + 269..270 'A': extern "rust-call" A(i32) -> A 269..274 'A(42)': A 271..273 '42': i32 "#]], @@ -910,16 +910,16 @@ fn test(a: A) { 253..254 'a': A 264..310 '{ ...))); }': () 274..275 't': &i32 - 278..279 'A': A(*mut i32) -> A + 278..279 'A': extern "rust-call" A(*mut i32) -> A 278..292 'A(0 as *mut _)': A 278..307 'A(0 as...B(a)))': &i32 280..281 '0': i32 280..291 '0 as *mut _': *mut i32 297..306 '&&B(B(a))': &&B>> 298..306 '&B(B(a))': &B>> - 299..300 'B': B>>(B>) -> B>> + 299..300 'B': extern "rust-call" B>>(B>) -> B>> 299..306 'B(B(a))': B>> - 301..302 'B': B>(A) -> B> + 301..302 'B': extern "rust-call" B>(A) -> B> 301..305 'B(a)': B> 303..304 'a': A "#]], @@ -1273,16 +1273,16 @@ fn infer_tuple_struct_generics() { "#, expect![[r#" 75..183 '{ ...one; }': () - 81..82 'A': A(i32) -> A + 81..82 'A': extern "rust-call" A(i32) -> A 81..86 'A(42)': A 83..85 '42': i32 - 92..93 'A': A(u128) -> A + 92..93 'A': extern "rust-call" A(u128) -> A 92..101 'A(42u128)': A 94..100 '42u128': u128 - 107..111 'Some': Some<&str>(&str) -> Option<&str> + 107..111 'Some': extern "rust-call" Some<&str>(&str) -> Option<&str> 107..116 'Some("x")': Option<&str> 112..115 '"x"': &str - 122..134 'Option::Some': Some<&str>(&str) -> Option<&str> + 122..134 'Option::Some': extern "rust-call" Some<&str>(&str) -> Option<&str> 122..139 'Option...e("x")': Option<&str> 135..138 '"x"': &str 145..149 'None': Option<{unknown}> @@ -1568,7 +1568,7 @@ fn infer_type_alias() { 204..207 'z.y': i8 298..362 '{ ... &e; }': () 308..309 'e': Enum - 312..325 'm::Alias::Foo': Foo(u8) -> Enum + 312..325 'm::Alias::Foo': extern "rust-call" Foo(u8) -> Enum 312..328 'm::Ali...Foo(0)': Enum 326..327 '0': u8 338..354 'm::Ali...Foo(x)': Enum @@ -2184,10 +2184,10 @@ fn main() { 103..231 '{ ... }); }': () 109..161 'async ... }': impl Future> 125..139 'return Err(())': ! - 132..135 'Err': Err<(), ()>(()) -> Result<(), ()> + 132..135 'Err': extern "rust-call" Err<(), ()>(()) -> Result<(), ()> 132..139 'Err(())': Result<(), ()> 136..138 '()': () - 149..151 'Ok': Ok<(), ()>(()) -> Result<(), ()> + 149..151 'Ok': extern "rust-call" Ok<(), ()>(()) -> Result<(), ()> 149..155 'Ok(())': Result<(), ()> 152..154 '()': () 167..171 'test': fn test<(), (), impl Fn() -> impl Future>, impl Future>>(impl Fn() -> impl Future>) @@ -2195,10 +2195,10 @@ fn main() { 172..227 '|| asy... }': impl Fn() -> impl Future> 175..227 'async ... }': impl Future> 191..205 'return Err(())': ! - 198..201 'Err': Err<(), ()>(()) -> Result<(), ()> + 198..201 'Err': extern "rust-call" Err<(), ()>(()) -> Result<(), ()> 198..205 'Err(())': Result<(), ()> 202..204 '()': () - 215..217 'Ok': Ok<(), ()>(()) -> Result<(), ()> + 215..217 'Ok': extern "rust-call" Ok<(), ()>(()) -> Result<(), ()> 215..221 'Ok(())': Result<(), ()> 218..220 '()': () "#]], @@ -2227,7 +2227,7 @@ fn infer_generic_from_later_assignment() { 94..127 '{ ... }': () 104..107 'end': Option 104..120 'end = ...(true)': () - 110..114 'Some': Some(bool) -> Option + 110..114 'Some': extern "rust-call" Some(bool) -> Option 110..120 'Some(true)': Option 115..119 'true': bool "#]], @@ -2262,7 +2262,7 @@ fn infer_loop_break_with_val() { 111..121 'break None': ! 117..121 'None': Option 142..158 'break ...(true)': ! - 148..152 'Some': Some(bool) -> Option + 148..152 'Some': extern "rust-call" Some(bool) -> Option 148..158 'Some(true)': Option 153..157 'true': bool "#]], @@ -2509,7 +2509,7 @@ fn generic_default_in_struct_literal() { 254..281 'OtherT...1i32 }': OtherThing 275..279 '1i32': i32 291..292 'b': OtherThing - 295..310 'OtherThing::Two': Two(i32) -> OtherThing + 295..310 'OtherThing::Two': extern "rust-call" Two(i32) -> OtherThing 295..316 'OtherT...(1i32)': OtherThing 311..315 '1i32': i32 "#]], @@ -2984,7 +2984,7 @@ fn f() { expect![[r#" 72..166 '{ ... } }': () 78..164 'match ... }': () - 84..92 'Foo::Bar': Bar(i32) -> Foo + 84..92 'Foo::Bar': extern "rust-call" Bar(i32) -> Foo 84..95 'Foo::Bar(3)': Foo 93..94 '3': i32 106..119 'Qux::Bar(bar)': Foo @@ -3043,9 +3043,9 @@ fn main() { 322..324 '{}': Foo 338..559 '{ ...r(); }': () 348..353 'boxed': Box> - 356..359 'Box': Box>(Foo) -> Box> + 356..359 'Box': extern "rust-call" Box>(Foo) -> Box> 356..371 'Box(Foo(0_i32))': Box> - 360..363 'Foo': Foo(i32) -> Foo + 360..363 'Foo': extern "rust-call" Foo(i32) -> Foo 360..370 'Foo(0_i32)': Foo 364..369 '0_i32': i32 382..386 'bad1': &i32 diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index d270328605..e4756ee9e2 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -522,7 +522,7 @@ fn test() -> u64 { expect![[r#" 37..86 '{ ... a.1 }': u64 47..48 'a': S - 51..52 'S': S(i32, u64) -> S + 51..52 'S': extern "rust-call" S(i32, u64) -> S 51..58 'S(4, 6)': S 53..54 '4': i32 56..57 '6': u64 @@ -548,7 +548,7 @@ fn test() -> u64 { expect![[r#" 43..108 '{ ...0(2) }': u64 53..54 'a': S - 57..58 'S': S(fn(u32) -> u64) -> S + 57..58 'S': extern "rust-call" S(fn(u32) -> u64) -> S 57..74 'S(|i| ...s u64)': S 59..73 '|i| 2*i as u64': impl Fn(u32) -> u64 60..61 'i': u32 @@ -1026,7 +1026,7 @@ fn test(x: impl Trait, y: &impl Trait) { 201..202 'x': impl Trait 208..209 'y': &impl Trait 219..220 'z': S - 223..224 'S': S(u16) -> S + 223..224 'S': extern "rust-call" S(u16) -> S 223..227 'S(1)': S 225..226 '1': u16 233..236 'bar': fn bar(S) @@ -1339,7 +1339,7 @@ fn foo() -> (impl FnOnce(&str, T), impl Trait) { 142..147 'input': &str 149..150 't': T 152..154 '{}': () - 156..159 'Bar': Bar(u8) -> Bar + 156..159 'Bar': extern "rust-call" Bar(u8) -> Bar 156..162 'Bar(C)': Bar 160..161 'C': u8 "#]], @@ -1958,7 +1958,7 @@ fn test() { 118..120 '{}': () 136..255 '{ ... 1); }': () 146..147 'x': Option - 150..162 'Option::Some': Some(u32) -> Option + 150..162 'Option::Some': extern "rust-call" Some(u32) -> Option 150..168 'Option...(1u32)': Option 163..167 '1u32': u32 174..175 'x': Option @@ -2514,7 +2514,7 @@ fn test() -> impl Trait { 178..180 '{}': () 213..309 '{ ...t()) }': S 223..225 's1': S - 228..229 'S': S(u32) -> S + 228..229 'S': extern "rust-call" S(u32) -> S 228..240 'S(default())': S 230..237 'default': fn default() -> u32 230..239 'default()': u32 @@ -2524,11 +2524,11 @@ fn test() -> impl Trait { 263..264 'x': i32 272..275 'bar': fn bar(S) -> i32 272..289 'bar(S(...lt()))': i32 - 276..277 'S': S(i32) -> S + 276..277 'S': extern "rust-call" S(i32) -> S 276..288 'S(default())': S 278..285 'default': fn default() -> i32 278..287 'default()': i32 - 295..296 'S': S(i32) -> S + 295..296 'S': extern "rust-call" S(i32) -> S 295..307 'S(default())': S 297..304 'default': fn default() -> i32 297..306 'default()': i32 @@ -2758,7 +2758,7 @@ fn main() { 1036..1041 'x > 0': bool 1040..1041 '0': i32 1042..1060 '{ Some...u32) }': Option - 1044..1048 'Some': Some(u32) -> Option + 1044..1048 'Some': extern "rust-call" Some(u32) -> Option 1044..1058 'Some(x as u32)': Option 1049..1050 'x': i32 1049..1057 'x as u32': u32 @@ -2894,9 +2894,9 @@ fn test() { 175..185 'foo.test()': bool 191..194 'bar': fn bar<{unknown}>({unknown}) -> {unknown} 191..201 'bar.test()': bool - 207..213 'Struct': Struct(usize) -> Struct + 207..213 'Struct': extern "rust-call" Struct(usize) -> Struct 207..220 'Struct.test()': bool - 226..239 'Enum::Variant': Variant(usize) -> Enum + 226..239 'Enum::Variant': extern "rust-call" Variant(usize) -> Enum 226..246 'Enum::...test()': bool "#]], ); @@ -3475,12 +3475,12 @@ fn main(){ 95..99 'self': Wrapper 101..104 'rhs': u32 122..150 '{ ... }': Wrapper - 132..139 'Wrapper': Wrapper(u32) -> Wrapper + 132..139 'Wrapper': extern "rust-call" Wrapper(u32) -> Wrapper 132..144 'Wrapper(rhs)': Wrapper 140..143 'rhs': u32 162..248 '{ ...um; }': () 172..179 'wrapped': Wrapper - 182..189 'Wrapper': Wrapper(u32) -> Wrapper + 182..189 'Wrapper': extern "rust-call" Wrapper(u32) -> Wrapper 182..193 'Wrapper(10)': Wrapper 190..192 '10': u32 203..206 'num': u32 diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index f7c7327776..ce01ee1c35 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -53,6 +53,12 @@ fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> { } } +impl ast::Abi { + pub fn abi_string(&self) -> Option { + support::token(&self.syntax, SyntaxKind::STRING).and_then(ast::String::cast) + } +} + impl ast::HasModuleItem for ast::StmtList {} impl ast::BlockExpr {