Skip to content

Commit ff87cd5

Browse files
committed
Fix #6585: implement Type.isFunctionType in tasty reflect API
1 parent 2984e57 commit ff87cd5

File tree

5 files changed

+78
-0
lines changed

5 files changed

+78
-0
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,10 @@ 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+
10801084
type ConstantType = Types.ConstantType
10811085

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

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,14 @@ 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 `List[Int]` is not a function type, despite that `List[Int] <:< Int => Int`.
873+
*/
874+
def Type_isFunctionType(self: Type)(implicit ctx: Context): Boolean
875+
868876
/** A singleton type representing a known constant value */
869877
type ConstantType <: Type
870878

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ 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 `List[Int]` is not a function type, despite that `List[Int] <:< Int => Int`.
35+
*/
36+
def isFunctionType(implicit ctx: Context): Boolean = kernel.Type_isFunctionType(self)
3037
}
3138

3239
object IsType {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
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+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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+
}

0 commit comments

Comments
 (0)