Skip to content

Commit 2c26c17

Browse files
authored
Merge pull request #6586 from dotty-staging/fix-6585
Fix #6585: implement Type.isFunctionType in tasty reflect API
2 parents 185c842 + 7218284 commit 2c26c17

File tree

5 files changed

+170
-0
lines changed

5 files changed

+170
-0
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,20 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
10771077
def Type_derivesFrom(self: Type)(cls: ClassDefSymbol)(implicit ctx: Context): Boolean =
10781078
self.derivesFrom(cls)
10791079

1080+
def Type_isFunctionType(self: Type)(implicit ctx: Context): Boolean =
1081+
defn.isFunctionType(self)
1082+
1083+
def Type_isImplicitFunctionType(self: Type)(implicit ctx: Context): Boolean =
1084+
defn.isImplicitFunctionType(self)
1085+
1086+
def Type_isErasedFunctionType(self: Type)(implicit ctx: Context): Boolean =
1087+
defn.isErasedFunctionType(self)
1088+
1089+
def Type_isDependentFunctionType(self: Type)(implicit ctx: Context): Boolean = {
1090+
val tpNoRefinement = self.dropDependentRefinement
1091+
tpNoRefinement != self && defn.isNonRefinedFunction(tpNoRefinement)
1092+
}
1093+
10801094
type ConstantType = Types.ConstantType
10811095

10821096
def matchConstantType(tpe: TypeOrBounds)(implicit ctx: Context): Option[ConstantType] = tpe match {

library/src/scala/tasty/reflect/Kernel.scala

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,36 @@ trait Kernel {
865865
/** Is this type an instance of a non-bottom subclass of the given class `cls`? */
866866
def Type_derivesFrom(self: Type)(cls: ClassDefSymbol)(implicit ctx: Context): Boolean
867867

868+
/** Is this type a function type?
869+
*
870+
* @return true if the dealised type of `self` without refinement is `FunctionN[T1, T2, ..., Tn]`
871+
*
872+
* @note The function
873+
*
874+
* - returns true for `given Int => Int` and `erased Int => Int`
875+
* - returns false for `List[Int]`, despite that `List[Int] <:< Int => Int`.
876+
*/
877+
def Type_isFunctionType(self: Type)(implicit ctx: Context): Boolean
878+
879+
880+
/** Is this type an implicit function type?
881+
*
882+
* @see `Type_isFunctionType`
883+
*/
884+
def Type_isImplicitFunctionType(self: Type)(implicit ctx: Context): Boolean
885+
886+
/** Is this type an erased function type?
887+
*
888+
* @see `Type_isFunctionType`
889+
*/
890+
def Type_isErasedFunctionType(self: Type)(implicit ctx: Context): Boolean
891+
892+
/** Is this type a dependent function type?
893+
*
894+
* @see `Type_isFunctionType`
895+
*/
896+
def Type_isDependentFunctionType(self: Type)(implicit ctx: Context): Boolean
897+
868898
/** A singleton type representing a known constant value */
869899
type ConstantType <: Type
870900

library/src/scala/tasty/reflect/TypeOrBoundsOps.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,34 @@ trait TypeOrBoundsOps extends Core {
2727
def derivesFrom(cls: ClassDefSymbol)(implicit ctx: Context): Boolean =
2828
kernel.Type_derivesFrom(self)(cls)
2929

30+
/** Is this type a function type?
31+
*
32+
* @return true if the dealised type of `self` without refinement is `FunctionN[T1, T2, ..., Tn]`
33+
*
34+
* @note The function
35+
*
36+
* - returns true for `given Int => Int` and `erased Int => Int`
37+
* - returns false for `List[Int]`, despite that `List[Int] <:< Int => Int`.
38+
*/
39+
def isFunctionType(implicit ctx: Context): Boolean = kernel.Type_isFunctionType(self)
40+
41+
/** Is this type an implicit function type?
42+
*
43+
* @see `isFunctionType`
44+
*/
45+
def isImplicitFunctionType(implicit ctx: Context): Boolean = kernel.Type_isImplicitFunctionType(self)
46+
47+
/** Is this type an erased function type?
48+
*
49+
* @see `isFunctionType`
50+
*/
51+
def isErasedFunctionType(implicit ctx: Context): Boolean = kernel.Type_isErasedFunctionType(self)
52+
53+
/** Is this type a dependent function type?
54+
*
55+
* @see `isFunctionType`
56+
*/
57+
def isDependentFunctionType(implicit ctx: Context): Boolean = kernel.Type_isDependentFunctionType(self)
3058
}
3159

3260
object IsType {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import scala.quoted._
2+
import scala.tasty._
3+
4+
5+
inline def isFunctionType[T:Type]: Boolean = ${ isFunctionTypeImpl('[T]) }
6+
7+
def isFunctionTypeImpl[T](tp: Type[T])(implicit refl: Reflection): Expr[Boolean] = {
8+
import refl._
9+
tp.unseal.tpe.isFunctionType.toExpr
10+
}
11+
12+
13+
inline def isImplicitFunctionType[T:Type]: Boolean = ${ isImplicitFunctionTypeImpl('[T]) }
14+
15+
def isImplicitFunctionTypeImpl[T](tp: Type[T])(implicit refl: Reflection): Expr[Boolean] = {
16+
import refl._
17+
tp.unseal.tpe.isImplicitFunctionType.toExpr
18+
}
19+
20+
21+
inline def isErasedFunctionType[T:Type]: Boolean = ${ isErasedFunctionTypeImpl('[T]) }
22+
23+
def isErasedFunctionTypeImpl[T](tp: Type[T])(implicit refl: Reflection): Expr[Boolean] = {
24+
import refl._
25+
tp.unseal.tpe.isErasedFunctionType.toExpr
26+
}
27+
28+
inline def isDependentFunctionType[T:Type]: Boolean = ${ isDependentFunctionTypeImpl('[T]) }
29+
30+
def isDependentFunctionTypeImpl[T](tp: Type[T])(implicit refl: Reflection): Expr[Boolean] = {
31+
import refl._
32+
tp.unseal.tpe.isDependentFunctionType.toExpr
33+
}
34+
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
trait Box {
2+
type T
3+
}
4+
5+
object Test {
6+
def main(args: Array[String]): Unit = {
7+
assert(!isFunctionType[Option[Int]])
8+
assert(!isFunctionType[String])
9+
10+
assert(!isFunctionType[List[Int]])
11+
assert(!isFunctionType[Set[Int]])
12+
13+
// TODO: compiler failed to synthesize Type[T]
14+
// type T = given Set[Int] => Int
15+
// assert(isFunctionType[T])
16+
17+
// TODO: compiler failed to synthesize Type[T]
18+
// type T = Int => Int
19+
// assert(isFunctionType[T])
20+
21+
assert(isFunctionType[(b: Box) => b.T])
22+
assert(isFunctionType[() => Int])
23+
assert(isFunctionType[(Int) => Int])
24+
assert(isFunctionType[(Int, Int) => Int])
25+
assert(isFunctionType[(Int, Int, Int) => Int])
26+
assert(isFunctionType[(Int, Int, Int, Int) => Int])
27+
assert(isFunctionType[(Int, Int, Int, Int, Int) => Int])
28+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int) => Int])
29+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int) => Int])
30+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int) => Int])
31+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
32+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
33+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
34+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
35+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
36+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
37+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
38+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
39+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
40+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
41+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
42+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
43+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
44+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
45+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
46+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
47+
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int])
48+
49+
assert(isDependentFunctionType[(b: Box) => b.T])
50+
assert(!isDependentFunctionType[Int => Int])
51+
// type A = (b: Box) => b.T
52+
// assert(isDependentFunctionType[A])
53+
54+
assert(isImplicitFunctionType[given Int => Int])
55+
assert(!isImplicitFunctionType[Int => Int])
56+
// type B = given Set[Int] => Int
57+
// assert(isImplicitFunctionType[B])
58+
59+
assert(isErasedFunctionType[erased Int => Int])
60+
assert(!isErasedFunctionType[Int => Int])
61+
// type C = erased Set[Int] => Int
62+
// assert(isErasedFunctionType[C])
63+
}
64+
}

0 commit comments

Comments
 (0)