-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #6585: implement Type.isFunctionType in tasty reflect API #6586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -865,6 +865,36 @@ trait Kernel { | |
/** Is this type an instance of a non-bottom subclass of the given class `cls`? */ | ||
def Type_derivesFrom(self: Type)(cls: ClassDefSymbol)(implicit ctx: Context): Boolean | ||
|
||
/** Is this type a function type? | ||
* | ||
* @return true if the dealised type of `self` without refinement is `FunctionN[T1, T2, ..., Tn]` | ||
* | ||
* @note The function | ||
* | ||
* - returns true for `given Int => Int` and `erased Int => Int` | ||
* - returns false for `List[Int]`, despite that `List[Int] <:< Int => Int`. | ||
*/ | ||
def Type_isFunctionType(self: Type)(implicit ctx: Context): Boolean | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The specification of the method may raise some concerns. However, in the setting of meta-programming, this is can be justified, as it's well-known that reflection breaks referential transparency. E.g. |
||
|
||
/** Is this type an implicit function type? | ||
* | ||
* @see `Type_isFunctionType` | ||
*/ | ||
def Type_isImplicitFunctionType(self: Type)(implicit ctx: Context): Boolean | ||
|
||
/** Is this type an erased function type? | ||
* | ||
* @see `Type_isFunctionType` | ||
*/ | ||
def Type_isErasedFunctionType(self: Type)(implicit ctx: Context): Boolean | ||
|
||
/** Is this type a dependent function type? | ||
* | ||
* @see `Type_isFunctionType` | ||
*/ | ||
def Type_isDependentFunctionType(self: Type)(implicit ctx: Context): Boolean | ||
|
||
/** A singleton type representing a known constant value */ | ||
type ConstantType <: Type | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import scala.quoted._ | ||
import scala.tasty._ | ||
|
||
|
||
inline def isFunctionType[T:Type]: Boolean = ${ isFunctionTypeImpl('[T]) } | ||
|
||
def isFunctionTypeImpl[T](tp: Type[T])(implicit refl: Reflection): Expr[Boolean] = { | ||
import refl._ | ||
tp.unseal.tpe.isFunctionType.toExpr | ||
} | ||
|
||
|
||
inline def isImplicitFunctionType[T:Type]: Boolean = ${ isImplicitFunctionTypeImpl('[T]) } | ||
|
||
def isImplicitFunctionTypeImpl[T](tp: Type[T])(implicit refl: Reflection): Expr[Boolean] = { | ||
import refl._ | ||
tp.unseal.tpe.isImplicitFunctionType.toExpr | ||
} | ||
|
||
|
||
inline def isErasedFunctionType[T:Type]: Boolean = ${ isErasedFunctionTypeImpl('[T]) } | ||
|
||
def isErasedFunctionTypeImpl[T](tp: Type[T])(implicit refl: Reflection): Expr[Boolean] = { | ||
import refl._ | ||
tp.unseal.tpe.isErasedFunctionType.toExpr | ||
} | ||
|
||
inline def isDependentFunctionType[T:Type]: Boolean = ${ isDependentFunctionTypeImpl('[T]) } | ||
|
||
def isDependentFunctionTypeImpl[T](tp: Type[T])(implicit refl: Reflection): Expr[Boolean] = { | ||
import refl._ | ||
tp.unseal.tpe.isDependentFunctionType.toExpr | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
trait Box { | ||
type T | ||
} | ||
|
||
object Test { | ||
def main(args: Array[String]): Unit = { | ||
assert(!isFunctionType[Option[Int]]) | ||
assert(!isFunctionType[String]) | ||
|
||
assert(!isFunctionType[List[Int]]) | ||
assert(!isFunctionType[Set[Int]]) | ||
|
||
// TODO: compiler failed to synthesize Type[T] | ||
liufengyun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// type T = given Set[Int] => Int | ||
// assert(isFunctionType[T]) | ||
|
||
// TODO: compiler failed to synthesize Type[T] | ||
// type T = Int => Int | ||
// assert(isFunctionType[T]) | ||
|
||
assert(isFunctionType[(b: Box) => b.T]) | ||
assert(isFunctionType[() => Int]) | ||
assert(isFunctionType[(Int) => Int]) | ||
assert(isFunctionType[(Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
assert(isFunctionType[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int]) | ||
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]) | ||
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]) | ||
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]) | ||
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]) | ||
|
||
assert(isDependentFunctionType[(b: Box) => b.T]) | ||
assert(!isDependentFunctionType[Int => Int]) | ||
// type A = (b: Box) => b.T | ||
// assert(isDependentFunctionType[A]) | ||
|
||
assert(isImplicitFunctionType[given Int => Int]) | ||
assert(!isImplicitFunctionType[Int => Int]) | ||
// type B = given Set[Int] => Int | ||
// assert(isImplicitFunctionType[B]) | ||
|
||
assert(isErasedFunctionType[erased Int => Int]) | ||
assert(!isErasedFunctionType[Int => Int]) | ||
// type C = erased Set[Int] => Int | ||
// assert(isErasedFunctionType[C]) | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.