Skip to content

Add constructors for TypeOrBounds that are not refs or PolyType #7961

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

Merged
merged 1 commit into from
Jan 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend
case _ => None
}

def TypeBounds_apply(low: Type, hi: Type)(given ctx: Context): TypeBounds =
Types.TypeBounds(low, hi)

def TypeBounds_low(self: TypeBounds)(given Context): Type = self.lo
def TypeBounds_hi(self: TypeBounds)(given Context): Type = self.hi

Expand Down Expand Up @@ -1201,6 +1204,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend
case tpe: Types.ConstantType => Some(tpe)
case _ => None
}

def ConstantType_apply(const: Constant)(given Context): ConstantType =
Types.ConstantType(const)

def ConstantType_constant(self: ConstantType)(given Context): Constant = self.value

Expand Down Expand Up @@ -1305,6 +1311,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend
case _ => None
}

def AnnotatedType_apply(underlying: Type, annot: Term)(given Context): AnnotatedType =
Types.AnnotatedType(underlying, Annotations.Annotation(annot))

def AnnotatedType_underlying(self: AnnotatedType)(given Context): Type = self.underlying.stripTypeVar
def AnnotatedType_annot(self: AnnotatedType)(given Context): Term = self.annot.tree

Expand All @@ -1317,6 +1326,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend
case _ => None
}

def AndType_apply(lhs: Type, rhs: Type)(given Context): AndType =
Types.AndType(lhs, rhs)

def AndType_left(self: AndType)(given Context): Type = self.tp1.stripTypeVar
def AndType_right(self: AndType)(given Context): Type = self.tp2.stripTypeVar

Expand All @@ -1329,6 +1341,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend
case _ => None
}

def OrType_apply(lhs: Type, rhs: Type)(given Context): OrType =
Types.OrType(lhs, rhs)

def OrType_left(self: OrType)(given Context): Type = self.tp1.stripTypeVar
def OrType_right(self: OrType)(given Context): Type = self.tp2.stripTypeVar

Expand All @@ -1341,6 +1356,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend
case _ => None
}

def MatchType_apply(bound: Type, scrutinee: Type, cases: List[Type])(given Context): MatchType =
Types.MatchType(bound, scrutinee, cases)

def MatchType_bound(self: MatchType)(given Context): Type = self.bound
def MatchType_scrutinee(self: MatchType)(given Context): Type = self.scrutinee
def MatchType_cases(self: MatchType)(given Context): List[Type] = self.cases
Expand Down Expand Up @@ -1445,8 +1463,13 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend
case _ => None
}

def TypeLambda_apply(paramNames: List[String], boundsFn: TypeLambda => List[TypeBounds], bodyFn: TypeLambda => Type): TypeLambda =
Types.HKTypeLambda(paramNames.map(_.toTypeName))(boundsFn, bodyFn)

def TypeLambda_paramNames(self: TypeLambda)(given Context): List[String] = self.paramNames.map(_.toString)
def TypeLambda_paramBounds(self: TypeLambda)(given Context): List[TypeBounds] = self.paramInfos
def TypeLambda_param(self: TypeLambda, idx: Int)(given Context): Type =
self.newParamRef(idx)
def TypeLambda_resType(self: TypeLambda)(given Context): Type = self.resType

//
Expand Down
15 changes: 15 additions & 0 deletions library/src/scala/tasty/reflect/CompilerInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,8 @@ trait CompilerInterface {

def isInstanceOfTypeBounds(given ctx: Context): IsInstanceOf[TypeBounds]

def TypeBounds_apply(low: Type, hi: Type)(given ctx: Context): TypeBounds

def TypeBounds_low(self: TypeBounds)(given ctx: Context): Type
def TypeBounds_hi(self: TypeBounds)(given ctx: Context): Type

Expand Down Expand Up @@ -887,6 +889,8 @@ trait CompilerInterface {

def isInstanceOfConstantType(given ctx: Context): IsInstanceOf[ConstantType]

def ConstantType_apply(const : Constant)(given ctx : Context) : ConstantType

def ConstantType_constant(self: ConstantType)(given ctx: Context): Constant

/** Type of a reference to a term symbol */
Expand Down Expand Up @@ -941,6 +945,8 @@ trait CompilerInterface {

def isInstanceOfAnnotatedType(given ctx: Context): IsInstanceOf[AnnotatedType]

def AnnotatedType_apply(underlying: Type, annot: Term)(given ctx: Context): AnnotatedType

def AnnotatedType_underlying(self: AnnotatedType)(given ctx: Context): Type
def AnnotatedType_annot(self: AnnotatedType)(given ctx: Context): Term

Expand All @@ -949,6 +955,8 @@ trait CompilerInterface {

def isInstanceOfAndType(given ctx: Context): IsInstanceOf[AndType]

def AndType_apply(lhs: Type, rhs: Type)(given ctx: Context): AndType

def AndType_left(self: AndType)(given ctx: Context): Type
def AndType_right(self: AndType)(given ctx: Context): Type

Expand All @@ -957,6 +965,8 @@ trait CompilerInterface {

def isInstanceOfOrType(given ctx: Context): IsInstanceOf[OrType]

def OrType_apply(lhs : Type, rhs : Type)(given ctx : Context): OrType

def OrType_left(self: OrType)(given ctx: Context): Type
def OrType_right(self: OrType)(given ctx: Context): Type

Expand All @@ -965,6 +975,8 @@ trait CompilerInterface {

def isInstanceOfMatchType(given ctx: Context): IsInstanceOf[MatchType]

def MatchType_apply(bound: Type, scrutinee: Type, cases: List[Type])(given ctx: Context): MatchType

def MatchType_bound(self: MatchType)(given ctx: Context): Type
def MatchType_scrutinee(self: MatchType)(given ctx: Context): Type
def MatchType_cases(self: MatchType)(given ctx: Context): List[Type]
Expand Down Expand Up @@ -1037,8 +1049,11 @@ trait CompilerInterface {

def isInstanceOfTypeLambda(given ctx: Context): IsInstanceOf[TypeLambda]

def TypeLambda_apply(paramNames: List[String], boundsFn: TypeLambda => List[TypeBounds], bodyFn: TypeLambda => Type): TypeLambda

def TypeLambda_paramNames(self: TypeLambda)(given ctx: Context): List[String]
def TypeLambda_paramBounds(self: TypeLambda)(given ctx: Context): List[TypeBounds]
def TypeLambda_param(self: TypeLambda, idx: Int)(given ctx: Context): Type
def TypeLambda_resType(self: TypeLambda)(given ctx: Context): Type

//
Expand Down
21 changes: 21 additions & 0 deletions library/src/scala/tasty/reflect/TypeOrBoundsOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ trait TypeOrBoundsOps extends Core {
def unapply(x: ConstantType)(given ctx: Context): Option[ConstantType] = Some(x)

object ConstantType {
def apply(x : Constant)(given ctx: Context): ConstantType = internal.ConstantType_apply(x)
def unapply(x: ConstantType)(given ctx: Context): Option[Constant] = Some(x.constant)
}

Expand Down Expand Up @@ -205,6 +206,8 @@ trait TypeOrBoundsOps extends Core {
def unapply(x: AnnotatedType)(given ctx: Context): Option[AnnotatedType] = Some(x)

object AnnotatedType {
def apply(underlying: Type, annot: Term)(given ctx: Context): AnnotatedType =
internal.AnnotatedType_apply(underlying, annot)
def unapply(x: AnnotatedType)(given ctx: Context): Option[(Type, Term)] =
Some((x.underlying, x.annot))
}
Expand All @@ -221,6 +224,8 @@ trait TypeOrBoundsOps extends Core {
def unapply(x: AndType)(given ctx: Context): Option[AndType] = Some(x)

object AndType {
def apply(lhs: Type, rhs: Type)(given ctx: Context): AndType =
internal.AndType_apply(lhs, rhs)
def unapply(x: AndType)(given ctx: Context): Option[(Type, Type)] =
Some((x.left, x.right))
}
Expand All @@ -237,6 +242,7 @@ trait TypeOrBoundsOps extends Core {
def unapply(x: OrType)(given ctx: Context): Option[OrType] = Some(x)

object OrType {
def apply(lhs: Type, rhs: Type)(given ctx: Context): OrType = internal.OrType_apply(lhs, rhs)
def unapply(x: OrType)(given ctx: Context): Option[(Type, Type)] =
Some((x.left, x.right))
}
Expand All @@ -253,6 +259,8 @@ trait TypeOrBoundsOps extends Core {
def unapply(x: MatchType)(given ctx: Context): Option[MatchType] = Some(x)

object MatchType {
def apply(bound: Type, scrutinee: Type, cases: List[Type])(given ctx: Context): MatchType =
internal.MatchType_apply(bound, scrutinee, cases)
def unapply(x: MatchType)(given ctx: Context): Option[(Type, Type, List[Type])] =
Some((x.bound, x.scrutinee, x.cases))
}
Expand All @@ -263,6 +271,14 @@ trait TypeOrBoundsOps extends Core {
def cases(given ctx: Context): List[Type] = internal.MatchType_cases(self)
}

/**
* An accessor for `scala.internal.MatchCase[_,_]`, the representation of a `MatchType` case.
*/
def MatchCaseType(given Context): Type = {
import scala.internal.MatchCase
Type(classOf[MatchCase[_,_]])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too hacky. In the future, we won't have access to the classOf[MatchCase[_, _]]. This should probably be in the scala.internal interface (CompilerInterface).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is interesting. Even in the tests, I had to use Type(classOf[List[_]]) in order to get the type of List.

Actually writing typeOf[List] gives me missing type parameter(s) for List. Writing typeOf[List[_]] satisfies Dotty but gives me AppliedType(List, TypeBounds(Nothing,Any)), which is not helpful.

Is this a bug or am I doing it wrong?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(leaving is as-is for now since it makes more sense to change this and the tests at the same time once we figure out the above question)

}

given (given Context): IsInstanceOf[ByNameType] = internal.isInstanceOfByNameType

object IsByNameType
Expand Down Expand Up @@ -381,13 +397,16 @@ trait TypeOrBoundsOps extends Core {
def unapply(x: TypeLambda)(given ctx: Context): Option[TypeLambda] = Some(x)

object TypeLambda {
def apply(paramNames: List[String], boundsFn: TypeLambda => List[TypeBounds], bodyFn: TypeLambda => Type): TypeLambda =
internal.TypeLambda_apply(paramNames, boundsFn, bodyFn)
def unapply(x: TypeLambda)(given ctx: Context): Option[(List[String], List[TypeBounds], Type)] =
Some((x.paramNames, x.paramBounds, x.resType))
}

given TypeLambdaOps: extension (self: TypeLambda) {
def paramNames(given ctx: Context): List[String] = internal.TypeLambda_paramNames(self)
def paramBounds(given ctx: Context): List[TypeBounds] = internal.TypeLambda_paramBounds(self)
def param(idx: Int)(given ctx: Context) : Type = internal.TypeLambda_param(self, idx)
def resType(given ctx: Context): Type = internal.TypeLambda_resType(self)
}

Expand All @@ -400,6 +419,8 @@ trait TypeOrBoundsOps extends Core {
def unapply(x: TypeBounds)(given ctx: Context): Option[TypeBounds] = Some(x)

object TypeBounds {
def apply(low: Type, hi: Type)(given ctx: Context): TypeBounds =
internal.TypeBounds_apply(low, hi)
def unapply(x: TypeBounds)(given ctx: Context): Option[(Type, Type)] = Some((x.low, x.hi))
}

Expand Down
1 change: 1 addition & 0 deletions tests/run-macros/tasty-construct-types.check
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ok
57 changes: 57 additions & 0 deletions tests/run-macros/tasty-construct-types/Macro_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import tasty._
import quoted._

object Macros {
inline def theTestBlock : Unit = ${ theTestBlockImpl }

trait RefineMe {
type T
def foo : T
}

class TestAnnotation extends scala.annotation.Annotation

def theTestBlockImpl(given qctx : QuoteContext) : Expr[Unit] = {
import qctx.tasty.{_,given}

val x1T = ConstantType(Constant(1))
val x2T = OrType(ConstantType(Constant(1)), ConstantType(Constant(2)))
val x3T = AndType(ConstantType(Constant(3)), typeOf[Any])
val x4T =
TypeLambda(
List("A","B"),
_ => List(TypeBounds(typeOf[Nothing], typeOf[Any]), TypeBounds(typeOf[Nothing], typeOf[Any])),
(tl : TypeLambda) => tl.param(1))
val x5T =
Refinement(
typeOf[RefineMe],
"T",
TypeBounds(typeOf[Int], typeOf[Int]))
val x6T = AppliedType(Type(classOf[List[_]]), List(typeOf[Int]))
val x7T = AnnotatedType(ConstantType(Constant(7)), '{ new TestAnnotation }.unseal)
val x8T =
MatchType(
typeOf[Int],
typeOf[List[8]],
List(
TypeLambda(
List("t"),
_ => List(TypeBounds(typeOf[Nothing], typeOf[Any])),
tl => AppliedType(MatchCaseType, List(AppliedType(Type(classOf[List[_]]), List(tl.param(0))), tl.param(0)))))
)

assert(x1T =:= '[1].unseal.tpe)
assert(x2T =:= '[1|2].unseal.tpe)
assert(x3T =:= '[3&Any].unseal.tpe)
assert(x4T =:= '[[A,B] =>> B].unseal.tpe)
assert(x5T =:= '[RefineMe { type T = Int }].unseal.tpe)
assert(x6T =:= '[List[Int]].unseal.tpe)
assert(x7T =:= '[7 @TestAnnotation].unseal.tpe)
assert(x8T =:= '[List[8] match { case List[t] => t }].unseal.tpe)

'{
println("Ok")
}
}
}

6 changes: 6 additions & 0 deletions tests/run-macros/tasty-construct-types/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

object Test {
def main(args : Array[String]) : Unit =
Macros.theTestBlock
}