11//! FIXME: write short doc here
2- use std:: sync:: Arc ;
2+ use std:: { iter , sync:: Arc } ;
33
44use arrayvec:: ArrayVec ;
55use either:: Either ;
@@ -12,6 +12,7 @@ use hir_def::{
1212 import_map,
1313 per_ns:: PerNs ,
1414 resolver:: { HasResolver , Resolver } ,
15+ src:: HasSource as _,
1516 type_ref:: { Mutability , TypeRef } ,
1617 AdtId , AssocContainerId , ConstId , DefWithBodyId , EnumId , FunctionId , GenericDefId , HasModule ,
1718 ImplId , LocalEnumVariantId , LocalFieldId , LocalModuleId , Lookup , ModuleId , StaticId , StructId ,
@@ -25,8 +26,8 @@ use hir_expand::{
2526use hir_ty:: {
2627 autoderef,
2728 display:: { HirDisplayError , HirFormatter } ,
28- method_resolution, ApplicationTy , Canonical , GenericPredicate , InEnvironment , Substs ,
29- TraitEnvironment , Ty , TyDefId , TypeCtor ,
29+ method_resolution, ApplicationTy , CallableDefId , Canonical , FnSig , GenericPredicate ,
30+ InEnvironment , Substs , TraitEnvironment , Ty , TyDefId , TypeCtor ,
3031} ;
3132use ra_db:: { CrateId , Edition , FileId } ;
3233use ra_prof:: profile;
@@ -40,7 +41,7 @@ use stdx::impl_from;
4041use crate :: {
4142 db:: { DefDatabase , HirDatabase } ,
4243 has_source:: HasSource ,
43- CallableDefId , HirDisplay , InFile , Name ,
44+ HirDisplay , InFile , Name ,
4445} ;
4546
4647/// hir::Crate describes a single crate. It's the main interface with which
@@ -1168,6 +1169,12 @@ impl Type {
11681169 Type :: new ( db, krate, def, ty)
11691170 }
11701171
1172+ pub fn is_unit ( & self ) -> bool {
1173+ matches ! (
1174+ self . ty. value,
1175+ Ty :: Apply ( ApplicationTy { ctor: TypeCtor :: Tuple { cardinality: 0 } , .. } )
1176+ )
1177+ }
11711178 pub fn is_bool ( & self ) -> bool {
11721179 matches ! ( self . ty. value, Ty :: Apply ( ApplicationTy { ctor: TypeCtor :: Bool , .. } ) )
11731180 }
@@ -1225,9 +1232,10 @@ impl Type {
12251232 db. trait_solve ( self . krate , goal) . is_some ( )
12261233 }
12271234
1228- // FIXME: this method is broken, as it doesn't take closures into account.
1229- pub fn as_callable ( & self ) -> Option < CallableDefId > {
1230- Some ( self . ty . value . as_callable ( ) ?. 0 )
1235+ pub fn as_callable ( & self , db : & dyn HirDatabase ) -> Option < Callable > {
1236+ let ( id, substs) = self . ty . value . as_callable ( ) ?;
1237+ let sig = db. callable_item_signature ( id) . subst ( substs) ;
1238+ Some ( Callable { ty : self . clone ( ) , sig, id, is_bound_method : false } )
12311239 }
12321240
12331241 pub fn is_closure ( & self ) -> bool {
@@ -1512,6 +1520,70 @@ impl HirDisplay for Type {
15121520 }
15131521}
15141522
1523+ // FIXME: closures
1524+ #[ derive( Debug ) ]
1525+ pub struct Callable {
1526+ ty : Type ,
1527+ sig : FnSig ,
1528+ id : CallableDefId ,
1529+ pub ( crate ) is_bound_method : bool ,
1530+ }
1531+
1532+ pub enum CallableKind {
1533+ Function ( Function ) ,
1534+ TupleStruct ( Struct ) ,
1535+ TupleEnumVariant ( EnumVariant ) ,
1536+ }
1537+
1538+ impl Callable {
1539+ pub fn kind ( & self ) -> CallableKind {
1540+ match self . id {
1541+ CallableDefId :: FunctionId ( it) => CallableKind :: Function ( it. into ( ) ) ,
1542+ CallableDefId :: StructId ( it) => CallableKind :: TupleStruct ( it. into ( ) ) ,
1543+ CallableDefId :: EnumVariantId ( it) => CallableKind :: TupleEnumVariant ( it. into ( ) ) ,
1544+ }
1545+ }
1546+ pub fn receiver_param ( & self , db : & dyn HirDatabase ) -> Option < ast:: SelfParam > {
1547+ let func = match self . id {
1548+ CallableDefId :: FunctionId ( it) if self . is_bound_method => it,
1549+ _ => return None ,
1550+ } ;
1551+ let src = func. lookup ( db. upcast ( ) ) . source ( db. upcast ( ) ) ;
1552+ let param_list = src. value . param_list ( ) ?;
1553+ param_list. self_param ( )
1554+ }
1555+ pub fn params (
1556+ & self ,
1557+ db : & dyn HirDatabase ,
1558+ ) -> Vec < ( Option < Either < ast:: SelfParam , ast:: Pat > > , Type ) > {
1559+ let types = self
1560+ . sig
1561+ . params ( )
1562+ . iter ( )
1563+ . skip ( if self . is_bound_method { 1 } else { 0 } )
1564+ . map ( |ty| self . ty . derived ( ty. clone ( ) ) ) ;
1565+ let patterns = match self . id {
1566+ CallableDefId :: FunctionId ( func) => {
1567+ let src = func. lookup ( db. upcast ( ) ) . source ( db. upcast ( ) ) ;
1568+ src. value . param_list ( ) . map ( |param_list| {
1569+ param_list
1570+ . self_param ( )
1571+ . map ( |it| Some ( Either :: Left ( it) ) )
1572+ . filter ( |_| !self . is_bound_method )
1573+ . into_iter ( )
1574+ . chain ( param_list. params ( ) . map ( |it| it. pat ( ) . map ( Either :: Right ) ) )
1575+ } )
1576+ }
1577+ CallableDefId :: StructId ( _) => None ,
1578+ CallableDefId :: EnumVariantId ( _) => None ,
1579+ } ;
1580+ patterns. into_iter ( ) . flatten ( ) . chain ( iter:: repeat ( None ) ) . zip ( types) . collect ( )
1581+ }
1582+ pub fn return_type ( & self ) -> Type {
1583+ self . ty . derived ( self . sig . ret ( ) . clone ( ) )
1584+ }
1585+ }
1586+
15151587/// For IDE only
15161588#[ derive( Debug ) ]
15171589pub enum ScopeDef {
0 commit comments