1
1
//! FIXME: write short doc here
2
- use std:: sync:: Arc ;
2
+ use std:: { iter , sync:: Arc } ;
3
3
4
4
use arrayvec:: ArrayVec ;
5
5
use either:: Either ;
@@ -12,6 +12,7 @@ use hir_def::{
12
12
import_map,
13
13
per_ns:: PerNs ,
14
14
resolver:: { HasResolver , Resolver } ,
15
+ src:: HasSource as _,
15
16
type_ref:: { Mutability , TypeRef } ,
16
17
AdtId , AssocContainerId , ConstId , DefWithBodyId , EnumId , FunctionId , GenericDefId , HasModule ,
17
18
ImplId , LocalEnumVariantId , LocalFieldId , LocalModuleId , Lookup , ModuleId , StaticId , StructId ,
@@ -25,8 +26,8 @@ use hir_expand::{
25
26
use hir_ty:: {
26
27
autoderef,
27
28
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 ,
30
31
} ;
31
32
use ra_db:: { CrateId , Edition , FileId } ;
32
33
use ra_prof:: profile;
@@ -40,7 +41,7 @@ use stdx::impl_from;
40
41
use crate :: {
41
42
db:: { DefDatabase , HirDatabase } ,
42
43
has_source:: HasSource ,
43
- CallableDefId , HirDisplay , InFile , Name ,
44
+ HirDisplay , InFile , Name ,
44
45
} ;
45
46
46
47
/// hir::Crate describes a single crate. It's the main interface with which
@@ -1168,6 +1169,12 @@ impl Type {
1168
1169
Type :: new ( db, krate, def, ty)
1169
1170
}
1170
1171
1172
+ pub fn is_unit ( & self ) -> bool {
1173
+ matches ! (
1174
+ self . ty. value,
1175
+ Ty :: Apply ( ApplicationTy { ctor: TypeCtor :: Tuple { cardinality: 0 } , .. } )
1176
+ )
1177
+ }
1171
1178
pub fn is_bool ( & self ) -> bool {
1172
1179
matches ! ( self . ty. value, Ty :: Apply ( ApplicationTy { ctor: TypeCtor :: Bool , .. } ) )
1173
1180
}
@@ -1225,9 +1232,10 @@ impl Type {
1225
1232
db. trait_solve ( self . krate , goal) . is_some ( )
1226
1233
}
1227
1234
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 } )
1231
1239
}
1232
1240
1233
1241
pub fn is_closure ( & self ) -> bool {
@@ -1512,6 +1520,70 @@ impl HirDisplay for Type {
1512
1520
}
1513
1521
}
1514
1522
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
+
1515
1587
/// For IDE only
1516
1588
#[ derive( Debug ) ]
1517
1589
pub enum ScopeDef {
0 commit comments