diff options
-rw-r--r-- | bincompat-backward.whitelist.conf | 37 | ||||
-rw-r--r-- | bincompat-forward.whitelist.conf | 62 | ||||
-rw-r--r-- | src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala | 16 | ||||
-rw-r--r-- | src/reflect/scala/reflect/api/Internals.scala | 44 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/ReificationSupport.scala | 84 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/StdNames.scala | 80 | ||||
-rw-r--r-- | test/files/scalacheck/quasiquotes/TypecheckedProps.scala | 96 |
7 files changed, 349 insertions, 70 deletions
diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf index b799b17c21..703c5add42 100644 --- a/bincompat-backward.whitelist.conf +++ b/bincompat-backward.whitelist.conf @@ -144,6 +144,43 @@ filter { { matchName="scala.reflect.api.Mirror.weakTypeOf" problemName=MissingMethodProblem + }, + // see SI-8388 + { + matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticIdentExtractor" + problemName=MissingClassProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticIdent" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSingletonType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTermIdent" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeIdent" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticCompoundType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticAnnotatedType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeProjection" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticExistentialType" + problemName=MissingMethodProblem } ] } diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 58bf98a173..5e869e3215 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -149,6 +149,7 @@ filter { matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticPartialFunction" problemName=MissingMethodProblem }, + // see SI-8428 { matchName="scala.collection.Iterator#ConcatIterator.this" problemName=MissingMethodProblem @@ -164,6 +165,67 @@ filter { { matchName="scala.reflect.api.Mirror.weakTypeOf" problemName=MissingMethodProblem + }, + // see SI-8388 + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSingletonType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTermIdent" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeIdent" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticCompoundType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticAnnotatedType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeProjection" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticExistentialType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticIdent" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticAnnotatedTypeExtractor" + problemName=MissingClassProblem + }, + { + matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticTermIdentExtractor" + problemName=MissingClassProblem + }, + { + matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacitcSingletonTypeExtractor" + problemName=MissingClassProblem + }, + { + matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticTypeIdentExtractor" + problemName=MissingClassProblem + }, + { + matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticCompoundTypeExtractor" + problemName=MissingClassProblem + }, + { + matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticExistentialTypeExtractor" + problemName=MissingClassProblem + }, + { + matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticTypeProjectionExtractor" + problemName=MissingClassProblem } ] } diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala index 1b8b0686e8..95113d5b00 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala @@ -193,8 +193,6 @@ trait Reifiers { self: Quasiquotes => reifyBuildCall(nme.SyntacticAppliedType, tpt, targs) case SyntacticFunction(args, body) => reifyBuildCall(nme.SyntacticFunction, args, body) - case SyntacticIdent(name, isBackquoted) => - reifyBuildCall(nme.SyntacticIdent, name, isBackquoted) case SyntacticEmptyTypeTree() => reifyBuildCall(nme.SyntacticEmptyTypeTree) case SyntacticImport(expr, selectors) => @@ -203,6 +201,20 @@ trait Reifiers { self: Quasiquotes => reifyBuildCall(nme.SyntacticPartialFunction, cases) case SyntacticMatch(scrutinee, cases) => reifyBuildCall(nme.SyntacticMatch, scrutinee, cases) + case SyntacticTermIdent(name, isBackquoted) => + reifyBuildCall(nme.SyntacticTermIdent, name, isBackquoted) + case SyntacticTypeIdent(name) => + reifyBuildCall(nme.SyntacticTypeIdent, name) + case SyntacticCompoundType(parents, defns) => + reifyBuildCall(nme.SyntacticCompoundType, parents, defns) + case SyntacticSingletonType(ref) => + reifyBuildCall(nme.SyntacticSingletonType, ref) + case SyntacticTypeProjection(qual, name) => + reifyBuildCall(nme.SyntacticTypeProjection, qual, name) + case SyntacticAnnotatedType(tpt, annot) => + reifyBuildCall(nme.SyntacticAnnotatedType, tpt, annot) + case SyntacticExistentialType(tpt, where) => + reifyBuildCall(nme.SyntacticExistentialType, tpt, where) case Q(tree) if fillListHole.isDefinedAt(tree) => mirrorBuildCall(nme.SyntacticBlock, fillListHole(tree)) case Q(other) => diff --git a/src/reflect/scala/reflect/api/Internals.scala b/src/reflect/scala/reflect/api/Internals.scala index 7788dba63e..577cd09295 100644 --- a/src/reflect/scala/reflect/api/Internals.scala +++ b/src/reflect/scala/reflect/api/Internals.scala @@ -780,10 +780,16 @@ trait Internals { self: Universe => def unapply(tree: Try): Option[(Tree, List[CaseDef], Tree)] } - val SyntacticIdent: SyntacticIdentExtractor - trait SyntacticIdentExtractor { - def apply(name: Name, isBackquoted: Boolean = false): Ident - def unapply(tree: Ident): Option[(Name, Boolean)] + val SyntacticTermIdent: SyntacticTermIdentExtractor + trait SyntacticTermIdentExtractor { + def apply(name: TermName, isBackquoted: Boolean = false): Ident + def unapply(id: Ident): Option[(TermName, Boolean)] + } + + val SyntacticTypeIdent: SyntacticTypeIdentExtractor + trait SyntacticTypeIdentExtractor { + def apply(name: TypeName): Ident + def unapply(tree: Tree): Option[TypeName] } val SyntacticImport: SyntacticImportExtractor @@ -803,6 +809,36 @@ trait Internals { self: Universe => def apply(qual: Tree, name: TermName): Select def unapply(tree: Tree): Option[(Tree, TermName)] } + + val SyntacticCompoundType: SyntacticCompoundTypeExtractor + trait SyntacticCompoundTypeExtractor { + def apply(parents: List[Tree], defns: List[Tree]): CompoundTypeTree + def unapply(tree: Tree): Option[(List[Tree], List[Tree])] + } + + val SyntacticSingletonType: SyntacitcSingletonTypeExtractor + trait SyntacitcSingletonTypeExtractor { + def apply(tree: Tree): SingletonTypeTree + def unapply(tree: Tree): Option[Tree] + } + + val SyntacticTypeProjection: SyntacticTypeProjectionExtractor + trait SyntacticTypeProjectionExtractor { + def apply(qual: Tree, name: TypeName): SelectFromTypeTree + def unapply(tree: Tree): Option[(Tree, TypeName)] + } + + val SyntacticAnnotatedType: SyntacticAnnotatedTypeExtractor + trait SyntacticAnnotatedTypeExtractor { + def apply(tpt: Tree, annot: Tree): Annotated + def unapply(tree: Tree): Option[(Tree, Tree)] + } + + val SyntacticExistentialType: SyntacticExistentialTypeExtractor + trait SyntacticExistentialTypeExtractor { + def apply(tpt: Tree, where: List[Tree]): ExistentialTypeTree + def unapply(tree: Tree): Option[(Tree, List[MemberDef])] + } } @deprecated("Use `internal.reificationSupport` instead", "2.11.0") diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala index 8379ff1ec8..ad8a2594dd 100644 --- a/src/reflect/scala/reflect/internal/ReificationSupport.scala +++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala @@ -227,9 +227,9 @@ trait ReificationSupport { self: SymbolTable => else throw new IllegalArgumentException(s"can't create applied type from non-type $tree") def unapply(tree: Tree): Option[(Tree, List[Tree])] = tree match { - case AppliedTypeTree(tpe, targs) => Some((tpe, targs)) - case _ if tree.isType => Some((tree, Nil)) - case _ => None + case MaybeTypeTreeOriginal(AppliedTypeTree(tpe, targs)) => Some((tpe, targs)) + case _ if tree.isType => Some((tree, Nil)) + case _ => None } } @@ -908,13 +908,24 @@ trait ReificationSupport { self: SymbolTable => def unapply(tree: Try): Option[(Tree, List[CaseDef], Tree)] = Try.unapply(tree) } - object SyntacticIdent extends SyntacticIdentExtractor { - def apply(name: Name, isBackquoted: Boolean) = { + object SyntacticTermIdent extends SyntacticTermIdentExtractor { + def apply(name: TermName, isBackquoted: Boolean): Ident = { val id = self.Ident(name) if (isBackquoted) id updateAttachment BackquotedIdentifierAttachment id } - def unapply(tree: Ident): Some[(Name, Boolean)] = Some((tree.name, tree.hasAttachment[BackquotedIdentifierAttachment.type])) + def unapply(id: Ident): Option[(TermName, Boolean)] = id.name match { + case name: TermName => Some((name, id.hasAttachment[BackquotedIdentifierAttachment.type])) + case _ => None + } + } + + object SyntacticTypeIdent extends SyntacticTypeIdentExtractor { + def apply(name: TypeName): Ident = self.Ident(name) + def unapply(tree: Tree): Option[TypeName] = tree match { + case MaybeTypeTreeOriginal(Ident(name: TypeName)) => Some(name) + case _ => None + } } /** Facade over Imports and ImportSelectors that lets to structurally @@ -1060,8 +1071,8 @@ trait ReificationSupport { self: SymbolTable => object SyntacticSelectType extends SyntacticSelectTypeExtractor { def apply(qual: Tree, name: TypeName): Select = Select(qual, name) def unapply(tree: Tree): Option[(Tree, TypeName)] = tree match { - case Select(qual, name: TypeName) => Some((qual, name)) - case _ => None + case MaybeTypeTreeOriginal(Select(qual, name: TypeName)) => Some((qual, name)) + case _ => None } } @@ -1072,6 +1083,63 @@ trait ReificationSupport { self: SymbolTable => case _ => None } } + + object SyntacticCompoundType extends SyntacticCompoundTypeExtractor { + def apply(parents: List[Tree], defns: List[Tree]) = + CompoundTypeTree(Template(gen.mkParents(NoMods, parents), noSelfType, defns)) + def unapply(tree: Tree): Option[(List[Tree], List[Tree])] = tree match { + case MaybeTypeTreeOriginal(CompoundTypeTree(Template(parents, _, defns))) => + Some((parents, defns)) + case _ => + None + } + } + + object SyntacticSingletonType extends SyntacitcSingletonTypeExtractor { + def apply(ref: Tree): SingletonTypeTree = SingletonTypeTree(ref) + def unapply(tree: Tree): Option[Tree] = tree match { + case MaybeTypeTreeOriginal(SingletonTypeTree(ref)) => + Some(ref) + case _ => + None + } + } + + object SyntacticTypeProjection extends SyntacticTypeProjectionExtractor { + def apply(qual: Tree, name: TypeName): SelectFromTypeTree = + SelectFromTypeTree(qual, name) + def unapply(tree: Tree): Option[(Tree, TypeName)] = tree match { + case MaybeTypeTreeOriginal(SelectFromTypeTree(qual, name)) => + Some((qual, name)) + case _ => + None + } + } + + object SyntacticAnnotatedType extends SyntacticAnnotatedTypeExtractor { + def apply(tpt: Tree, annot: Tree): Annotated = + Annotated(annot, tpt) + def unapply(tree: Tree): Option[(Tree, Tree)] = tree match { + case MaybeTypeTreeOriginal(Annotated(annot, tpt)) => + Some((tpt, annot)) + case _ => + None + } + } + + object SyntacticExistentialType extends SyntacticExistentialTypeExtractor { + def apply(tpt: Tree, where: List[Tree]): ExistentialTypeTree = + ExistentialTypeTree(tpt, where.map { + case md: MemberDef => md + case tree => throw new IllegalArgumentException("$tree is not legal forSome definition") + }) + def unapply(tree: Tree): Option[(Tree, List[MemberDef])] = tree match { + case MaybeTypeTreeOriginal(ExistentialTypeTree(tpt, where)) => + Some((tpt, where)) + case _ => + None + } + } } val build = new ReificationSupportImpl diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 10959ff41f..6848c357c5 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -612,37 +612,6 @@ trait StdNames { val SelectFromTypeTree: NameType = "SelectFromTypeTree" val SingleType: NameType = "SingleType" val SuperType: NameType = "SuperType" - val SyntacticApplied: NameType = "SyntacticApplied" - val SyntacticAppliedType: NameType = "SyntacticAppliedType" - val SyntacticAssign: NameType = "SyntacticAssign" - val SyntacticBlock: NameType = "SyntacticBlock" - val SyntacticClassDef: NameType = "SyntacticClassDef" - val SyntacticDefDef: NameType = "SyntacticDefDef" - val SyntacticEmptyTypeTree: NameType = "SyntacticEmptyTypeTree" - val SyntacticFilter: NameType = "SyntacticFilter" - val SyntacticFor: NameType = "SyntacticFor" - val SyntacticForYield: NameType = "SyntacticForYield" - val SyntacticFunction: NameType = "SyntacticFunction" - val SyntacticFunctionType: NameType = "SyntacticFunctionType" - val SyntacticIdent: NameType = "SyntacticIdent" - val SyntacticImport: NameType = "SyntacticImport" - val SyntacticMatch: NameType = "SyntacticMatch" - val SyntacticNew: NameType = "SyntacticNew" - val SyntacticObjectDef: NameType = "SyntacticObjectDef" - val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef" - val SyntacticPartialFunction: NameType = "SyntacticPartialFunction" - val SyntacticPatDef: NameType = "SyntacticPatDef" - val SyntacticSelectType: NameType = "SyntacticSelectType" - val SyntacticSelectTerm: NameType = "SyntacticSelectTerm" - val SyntacticTraitDef: NameType = "SyntacticTraitDef" - val SyntacticTry: NameType = "SyntacticTry" - val SyntacticTuple: NameType = "SyntacticTuple" - val SyntacticTupleType: NameType = "SyntacticTupleType" - val SyntacticTypeApplied: NameType = "SyntacticTypeApplied" - val SyntacticValDef: NameType = "SyntacticValDef" - val SyntacticValEq: NameType = "SyntacticValEq" - val SyntacticValFrom: NameType = "SyntacticValFrom" - val SyntacticVarDef: NameType = "SyntacticVarDef" val This: NameType = "This" val ThisType: NameType = "ThisType" val Tuple2: NameType = "Tuple2" @@ -810,11 +779,50 @@ trait StdNames { val zero: NameType = "zero" // quasiquote interpolators: - val q: NameType = "q" - val tq: NameType = "tq" - val cq: NameType = "cq" - val pq: NameType = "pq" - val fq: NameType = "fq" + val q: NameType = "q" + val tq: NameType = "tq" + val cq: NameType = "cq" + val pq: NameType = "pq" + val fq: NameType = "fq" + + // quasiquote's syntactic combinators + val SyntacticAnnotatedType: NameType = "SyntacticAnnotatedType" + val SyntacticApplied: NameType = "SyntacticApplied" + val SyntacticAppliedType: NameType = "SyntacticAppliedType" + val SyntacticAssign: NameType = "SyntacticAssign" + val SyntacticBlock: NameType = "SyntacticBlock" + val SyntacticClassDef: NameType = "SyntacticClassDef" + val SyntacticCompoundType: NameType = "SyntacticCompoundType" + val SyntacticDefDef: NameType = "SyntacticDefDef" + val SyntacticEmptyTypeTree: NameType = "SyntacticEmptyTypeTree" + val SyntacticExistentialType: NameType = "SyntacticExistentialType" + val SyntacticFilter: NameType = "SyntacticFilter" + val SyntacticFor: NameType = "SyntacticFor" + val SyntacticForYield: NameType = "SyntacticForYield" + val SyntacticFunction: NameType = "SyntacticFunction" + val SyntacticFunctionType: NameType = "SyntacticFunctionType" + val SyntacticImport: NameType = "SyntacticImport" + val SyntacticMatch: NameType = "SyntacticMatch" + val SyntacticNew: NameType = "SyntacticNew" + val SyntacticObjectDef: NameType = "SyntacticObjectDef" + val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef" + val SyntacticPartialFunction: NameType = "SyntacticPartialFunction" + val SyntacticPatDef: NameType = "SyntacticPatDef" + val SyntacticSelectTerm: NameType = "SyntacticSelectTerm" + val SyntacticSelectType: NameType = "SyntacticSelectType" + val SyntacticSingletonType: NameType = "SyntacticSingletonType" + val SyntacticTermIdent: NameType = "SyntacticTermIdent" + val SyntacticTraitDef: NameType = "SyntacticTraitDef" + val SyntacticTry: NameType = "SyntacticTry" + val SyntacticTuple: NameType = "SyntacticTuple" + val SyntacticTupleType: NameType = "SyntacticTupleType" + val SyntacticTypeApplied: NameType = "SyntacticTypeApplied" + val SyntacticTypeIdent: NameType = "SyntacticTypeIdent" + val SyntacticTypeProjection: NameType = "SyntacticTypeProjection" + val SyntacticValDef: NameType = "SyntacticValDef" + val SyntacticValEq: NameType = "SyntacticValEq" + val SyntacticValFrom: NameType = "SyntacticValFrom" + val SyntacticVarDef: NameType = "SyntacticVarDef" // unencoded operators object raw { diff --git a/test/files/scalacheck/quasiquotes/TypecheckedProps.scala b/test/files/scalacheck/quasiquotes/TypecheckedProps.scala index fb2eb69321..a5d526191f 100644 --- a/test/files/scalacheck/quasiquotes/TypecheckedProps.scala +++ b/test/files/scalacheck/quasiquotes/TypecheckedProps.scala @@ -2,32 +2,13 @@ import org.scalacheck._, Prop._, Gen._, Arbitrary._ import scala.reflect.runtime.universe._, Flag._, internal.reificationSupport._ object TypecheckedProps extends QuasiquoteProperties("typechecked") { - def original(tree: Tree) = tree match { - case tt: TypeTree => Some(tt.original) - case _ => None - } - def originals(trees: List[Tree]) = trees.flatMap(original) - val int = ScalaDot(TypeName("Int")) - val intint = List(int, int) + property("tuple term") = test { val q"(..$elements)" = typecheck(q"(1, 2)") assert(elements ≈ List(q"1", q"2")) } - property("tuple type") = test { - val tq"(..$els0)" = typecheckTyp(tq"Unit") - assert(els0.isEmpty) - val tq"(..$els1)" = typecheckTyp(tq"(Int, Int)") - assert(originals(els1) ≈ intint) - } - - property("function type") = test { - val tq"(..$argtpes) => $restpe" = typecheckTyp(tq"(Int, Int) => Int") - assert(originals(argtpes) ≈ intint) - assert(original(restpe).get ≈ int) - } - property("for/for-yield") = test { val enums = fq"x <- xs" :: fq"x1 = x + 1" :: fq"if x1 % 2 == 0" :: Nil val body = q"x1" @@ -158,3 +139,78 @@ object TypecheckedProps extends QuasiquoteProperties("typechecked") { assert(cases ≈ q"{ case 1 => () }".cases) } } + +trait TypecheckedTypes { self: QuasiquoteProperties => + property("type ident") = test { + val q"$_; type $_ = $tpt" = typecheck(q"class C; type T = C") + val tq"C" = tpt + } + + property("type select") = test { + val tq"scala.Int" = typecheckTyp(tq"Int") + } + + property("this type select") = test { + val q"class $_ { $_; type $_ = $tpt }" = typecheck(q"class C { type A = Int; type B = this.A }") + val tq"this.$name" = tpt + val TypeName("A") = name + } + + property("super type select") = test { + val q"$_; class $_ extends $_ { type $_ = $tpt }" = + typecheck(q"class C1 { type A = Int }; class C2 extends C1 { type B = super[C1].A }") + val tq"$empty.super[$c1].$a" = tpt + val TypeName("") = empty + val TypeName("C1") = c1 + val TypeName("A") = a + } + + property("applied type") = test { + val tt = typecheckTyp(q"Map[Int, Int]") + val tq"$tpt[..$tpts]" = tt + val tq"scala.this.Predef.Map" = tpt + val List(tq"scala.Int", tq"scala.Int") = tpts + } + + property("tuple type") = test { + val tq"(..$els0)" = typecheckTyp(tq"Unit") + assert(els0.isEmpty) + val tq"(..$els1)" = typecheckTyp(tq"(Int, Int)") + val List(tq"scala.Int", tq"scala.Int") = els1 + } + + property("function type") = test { + val tq"(..$argtpes) => $restpe" = typecheckTyp(tq"(Int, Int) => Int") + val List(tq"scala.Int", tq"scala.Int") = argtpes + val tq"scala.Int" = restpe + } + + property("compound type") = test { + val tq"..$parents { ..$defns }" = typecheckTyp(tq"Int { def x: Int }") + val List(tq"Int") = parents + val List(q"def x: Int") = defns + } + + property("singleton type") = test { + val tq"$ref.type" = typecheckTyp(tq"scala.Predef.type") + val q"scala.Predef" = ref + } + + property("type projection") = test { + val tq"$tpt#$name" = typecheckTyp(tq"({ type T = Int })#T") + val TypeName("T") = name + val tq"{ type T = Int }" = tpt + } + + property("annotated type") = test { + val tq"$tpt @$annot" = typecheckTyp(tq"Int @unchecked") + val tq"scala.Int" = tpt + val q"new unchecked" = annot + } + + property("existential type") = test { + val tq"$tpt forSome { ..$defns }" = typecheckTyp(tq"T forSome { type T }") + val tq"T" = tpt + val q"type T" :: Nil = defns + } +} |