diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 1e6741fee79d..8cb7903ad06f 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -942,14 +942,14 @@ object desugar { * * to * - * @patternBindHole type $T >: Low <: Hi + * @patternType type $T >: Low <: Hi * * if the type is a type splice. */ def quotedPatternTypeDef(tree: TypeDef)(implicit ctx: Context): TypeDef = { assert(ctx.mode.is(Mode.QuotedPattern)) if (tree.name.startsWith("$") && !tree.isBackquoted) { - val patternBindHoleAnnot = New(ref(defn.InternalQuoted_patternBindHoleAnnot.typeRef)).withSpan(tree.span) + val patternBindHoleAnnot = New(ref(defn.InternalQuoted_patternTypeAnnot.typeRef)).withSpan(tree.span) val mods = tree.mods.withAddedAnnotation(patternBindHoleAnnot) tree.withMods(mods) } diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index e0adf73fd1c2..d8806c093acc 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -696,6 +696,7 @@ class Definitions { @tu lazy val InternalQuoted_typeQuote : Symbol = InternalQuotedModule.requiredMethod("typeQuote") @tu lazy val InternalQuoted_patternHole: Symbol = InternalQuotedModule.requiredMethod("patternHole") @tu lazy val InternalQuoted_patternBindHoleAnnot: ClassSymbol = InternalQuotedModule.requiredClass("patternBindHole") + @tu lazy val InternalQuoted_patternTypeAnnot: ClassSymbol = InternalQuotedModule.requiredClass("patternType") @tu lazy val InternalQuoted_QuoteTypeTagAnnot: ClassSymbol = InternalQuotedModule.requiredClass("quoteTypeTag") @tu lazy val InternalQuoted_fromAboveAnnot: ClassSymbol = InternalQuotedModule.requiredClass("fromAbove") diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index e1f10a8c6b53..c2a207aff44b 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -1964,6 +1964,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def Definitions_InternalQuoted_patternHole: Symbol = defn.InternalQuoted_patternHole def Definitions_InternalQuoted_patternBindHoleAnnot: Symbol = defn.InternalQuoted_patternBindHoleAnnot + def Definitions_InternalQuoted_patternTypeAnnot: Symbol = defn.InternalQuoted_patternTypeAnnot def Definitions_InternalQuoted_fromAboveAnnot: Symbol = defn.InternalQuoted_fromAboveAnnot // Types diff --git a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala index 91e18cb2791e..70a0a53b4c73 100644 --- a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala +++ b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala @@ -147,7 +147,7 @@ trait QuotesAndSplices { case pt: TypeBounds => pt case _ => TypeBounds.empty val typeSym = ctx.newSymbol(spliceOwner(ctx), name, EmptyFlags, typeSymInfo, NoSymbol, tree.expr.span) - typeSym.addAnnotation(Annotation(New(ref(defn.InternalQuoted_patternBindHoleAnnot.typeRef)).withSpan(tree.expr.span))) + typeSym.addAnnotation(Annotation(New(ref(defn.InternalQuoted_patternTypeAnnot.typeRef)).withSpan(tree.expr.span))) val pat = typedPattern(tree.expr, defn.QuotedTypeClass.typeRef.appliedTo(typeSym.typeRef))( using spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx))) pat.select(tpnme.splice) @@ -250,7 +250,7 @@ trait QuotesAndSplices { patBuf += Bind(sym, untpd.Ident(nme.WILDCARD).withType(defn.StringType)).withSpan(ddef.span) } super.transform(tree) - case tdef: TypeDef if tdef.symbol.hasAnnotation(defn.InternalQuoted_patternBindHoleAnnot) => + case tdef: TypeDef if tdef.symbol.hasAnnotation(defn.InternalQuoted_patternTypeAnnot) => transformTypeBindingTypeDef(tdef, typePatBuf) case tree @ AppliedTypeTree(tpt, args) => val args1: List[Tree] = args.zipWithConserve(tpt.tpe.typeParams.map(_.paramVarianceSign)) { (arg, v) => diff --git a/library/src/scala/internal/quoted/Matcher.scala b/library/src/scala/internal/quoted/Matcher.scala index ea16027cae93..b2a639989c17 100644 --- a/library/src/scala/internal/quoted/Matcher.scala +++ b/library/src/scala/internal/quoted/Matcher.scala @@ -74,10 +74,17 @@ private[quoted] object Matcher { case _ => false } + private def hasPatternTypeAnnotation(sym: Symbol) = sym.annots.exists(isPatternTypeAnnotation) + private def hasBindAnnotation(sym: Symbol) = sym.annots.exists(isBindAnnotation) private def hasFromAboveAnnotation(sym: Symbol) = sym.annots.exists(isFromAboveAnnotation) + private def isPatternTypeAnnotation(tree: Tree): Boolean = tree match { + case New(tpt) => tpt.symbol == internal.Definitions_InternalQuoted_patternTypeAnnot + case annot => annot.symbol.owner == internal.Definitions_InternalQuoted_patternTypeAnnot + } + private def isBindAnnotation(tree: Tree): Boolean = tree match { case New(tpt) => tpt.symbol == internal.Definitions_InternalQuoted_patternBindHoleAnnot case annot => annot.symbol.owner == internal.Definitions_InternalQuoted_patternBindHoleAnnot @@ -423,7 +430,7 @@ private[quoted] object Matcher { } private def isTypeBinding(tree: Tree): Boolean = tree match { - case tree: TypeDef => hasBindAnnotation(tree.symbol) + case tree: TypeDef => hasPatternTypeAnnotation(tree.symbol) case _ => false } } diff --git a/library/src/scala/tasty/reflect/CompilerInterface.scala b/library/src/scala/tasty/reflect/CompilerInterface.scala index 46c7399ddbe7..84a553867b0c 100644 --- a/library/src/scala/tasty/reflect/CompilerInterface.scala +++ b/library/src/scala/tasty/reflect/CompilerInterface.scala @@ -1500,6 +1500,9 @@ trait CompilerInterface { /** Symbol of scala.internal.Quoted.patternBindHole */ def Definitions_InternalQuoted_patternBindHoleAnnot: Symbol + /** Symbol of scala.internal.Quoted.patternType */ + def Definitions_InternalQuoted_patternTypeAnnot: Symbol + /** Symbol of scala.internal.Quoted.fromAbove */ def Definitions_InternalQuoted_fromAboveAnnot: Symbol diff --git a/tests/run-macros/quote-matcher-runtime.check b/tests/run-macros/quote-matcher-runtime.check index 2cab7037b4b6..59ed107db039 100644 --- a/tests/run-macros/quote-matcher-runtime.check +++ b/tests/run-macros/quote-matcher-runtime.check @@ -716,21 +716,21 @@ Result: Some(List(Expr(1), Expr(2))) Scrutinee: scala.List.apply[scala.Int](1, 2, 3).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T + @scala.internal.quoted.CompileTime.patternType type T scala.internal.quoted.CompileTime.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.quoted.CompileTime.patternHole[scala.Function1[scala.Int, T]]) } Result: Some(List(Type(scala.Unit), Expr(scala.List.apply[scala.Int](1, 2, 3)), Expr(((x: scala.Int) => scala.Predef.println(x))))) Scrutinee: scala.List.apply[scala.Int](1, 2, 3).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T = scala.Unit + @scala.internal.quoted.CompileTime.patternType type T = scala.Unit scala.internal.quoted.CompileTime.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.quoted.CompileTime.patternHole[scala.Function1[scala.Int, T]]) } Result: Some(List(Type(scala.Unit), Expr(scala.List.apply[scala.Int](1, 2, 3)), Expr(((x: scala.Int) => scala.Predef.println(x))))) Scrutinee: scala.List.apply[scala.Int](1, 2, 3).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T <: scala.Predef.String + @scala.internal.quoted.CompileTime.patternType type T <: scala.Predef.String scala.internal.quoted.CompileTime.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.quoted.CompileTime.patternHole[scala.Function1[scala.Int, T]]) } Result: None @@ -741,7 +741,7 @@ Scrutinee: { () } Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T + @scala.internal.quoted.CompileTime.patternType type T val a: T = scala.internal.quoted.CompileTime.patternHole[T] val b: T = scala.internal.quoted.CompileTime.patternHole[T] () @@ -754,7 +754,7 @@ Scrutinee: { () } Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T + @scala.internal.quoted.CompileTime.patternType type T val a: T = scala.internal.quoted.CompileTime.patternHole[T] val b: T = scala.internal.quoted.CompileTime.patternHole[T] () @@ -767,7 +767,7 @@ Scrutinee: { () } Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T + @scala.internal.quoted.CompileTime.patternType type T val a: T = scala.internal.quoted.CompileTime.patternHole[T] val b: T = scala.internal.quoted.CompileTime.patternHole[T] () @@ -780,7 +780,7 @@ Scrutinee: { () } Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T <: scala.Int + @scala.internal.quoted.CompileTime.patternType type T <: scala.Int val a: T = scala.internal.quoted.CompileTime.patternHole[T] val b: T = scala.internal.quoted.CompileTime.patternHole[T] () @@ -789,9 +789,9 @@ Result: None Scrutinee: scala.List.apply[scala.Int](1, 2, 3).map[scala.Double](((x: scala.Int) => x.toDouble./(2))).map[java.lang.String](((y: scala.Double) => y.toString())) Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T - @scala.internal.quoted.CompileTime.patternBindHole type U - @scala.internal.quoted.CompileTime.patternBindHole type V + @scala.internal.quoted.CompileTime.patternType type T + @scala.internal.quoted.CompileTime.patternType type U + @scala.internal.quoted.CompileTime.patternType type V (scala.internal.quoted.CompileTime.patternHole[scala.List[T]].map[U](scala.internal.quoted.CompileTime.patternHole[scala.Function1[T, U]]).map[V](scala.internal.quoted.CompileTime.patternHole[scala.Function1[U, V]]): scala.collection.immutable.List[scala.Any]) } @@ -799,7 +799,7 @@ Result: Some(List(Type(scala.Int), Type(scala.Double), Type(java.lang.String), E Scrutinee: ((x: scala.Int) => x) Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T + @scala.internal.quoted.CompileTime.patternType type T (scala.internal.quoted.CompileTime.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) } @@ -807,7 +807,7 @@ Result: Some(List(Type(scala.Int), Expr(((x: scala.Int) => x)))) Scrutinee: ((x: scala.Int) => x.toString()) Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T + @scala.internal.quoted.CompileTime.patternType type T (scala.internal.quoted.CompileTime.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) } @@ -815,7 +815,7 @@ Result: None Scrutinee: ((x: scala.Any) => scala.Predef.???) Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T + @scala.internal.quoted.CompileTime.patternType type T (scala.internal.quoted.CompileTime.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) } @@ -823,7 +823,7 @@ Result: Some(List(Type(scala.Nothing), Expr(((x: scala.Any) => scala.Predef.???) Scrutinee: ((x: scala.Nothing) => (1: scala.Any)) Pattern: { - @scala.internal.quoted.CompileTime.patternBindHole type T + @scala.internal.quoted.CompileTime.patternType type T (scala.internal.quoted.CompileTime.patternHole[scala.Function1[T, T]]: scala.Function1[scala.Nothing, scala.Any]) } diff --git a/tests/run-macros/quote-matcher-runtime/quoted_2.scala b/tests/run-macros/quote-matcher-runtime/quoted_2.scala index b26810fcb9ae..e83318e55d5d 100644 --- a/tests/run-macros/quote-matcher-runtime/quoted_2.scala +++ b/tests/run-macros/quote-matcher-runtime/quoted_2.scala @@ -134,18 +134,18 @@ object Test { matches(try 1 finally 2, try 1 finally 2) matches(try 1 catch { case _ => 2 }, try patternHole[Int] catch { case _ => patternHole[Int] }) matches(try 1 finally 2, try patternHole[Int] finally patternHole[Int]) - matches(List(1, 2, 3).foreach(x => println(x)), { @patternBindHole type T; patternHole[List[Int]].foreach[T](patternHole[Int => T]) }) - matches(List(1, 2, 3).foreach(x => println(x)), { @patternBindHole type T = Unit; patternHole[List[Int]].foreach[T](patternHole[Int => T]) }) - matches(List(1, 2, 3).foreach(x => println(x)), { @patternBindHole type T <: String; patternHole[List[Int]].foreach[T](patternHole[Int => T]) }) - matches({ val a: Int = 4; val b: Int = 4 }, { @patternBindHole type T; { val a: T = patternHole[T]; val b: T = patternHole[T] } }) - matches({ val a: Int = 4; val b: Int = 5 }, { @patternBindHole type T; { val a: T = patternHole[T]; val b: T = patternHole[T] } }) - matches({ val a: Int = 4; val b: String = "x" }, { @patternBindHole type T; { val a: T = patternHole[T]; val b: T = patternHole[T] } }) - matches({ val a: Int = 4; val b: String = "x" }, { @patternBindHole type T <: Int; { val a: T = patternHole[T]; val b: T = patternHole[T] } }) - matches(List(1, 2, 3).map(x => x.toDouble / 2).map(y => y.toString), { @patternBindHole type T; @patternBindHole type U; @patternBindHole type V; patternHole[List[T]].map(patternHole[T => U]).map(patternHole[U => V]) }) - matches((x: Int) => x, { @patternBindHole type T; patternHole[T => T] }) - matches((x: Int) => x.toString, { @patternBindHole type T; patternHole[T => T] }) - matches((x: Any) => ???, { @patternBindHole type T; patternHole[T => T] }) - matches((x: Nothing) => (1 : Any), { @patternBindHole type T; patternHole[T => T] }) + matches(List(1, 2, 3).foreach(x => println(x)), { @patternType type T; patternHole[List[Int]].foreach[T](patternHole[Int => T]) }) + matches(List(1, 2, 3).foreach(x => println(x)), { @patternType type T = Unit; patternHole[List[Int]].foreach[T](patternHole[Int => T]) }) + matches(List(1, 2, 3).foreach(x => println(x)), { @patternType type T <: String; patternHole[List[Int]].foreach[T](patternHole[Int => T]) }) + matches({ val a: Int = 4; val b: Int = 4 }, { @patternType type T; { val a: T = patternHole[T]; val b: T = patternHole[T] } }) + matches({ val a: Int = 4; val b: Int = 5 }, { @patternType type T; { val a: T = patternHole[T]; val b: T = patternHole[T] } }) + matches({ val a: Int = 4; val b: String = "x" }, { @patternType type T; { val a: T = patternHole[T]; val b: T = patternHole[T] } }) + matches({ val a: Int = 4; val b: String = "x" }, { @patternType type T <: Int; { val a: T = patternHole[T]; val b: T = patternHole[T] } }) + matches(List(1, 2, 3).map(x => x.toDouble / 2).map(y => y.toString), { @patternType type T; @patternType type U; @patternType type V; patternHole[List[T]].map(patternHole[T => U]).map(patternHole[U => V]) }) + matches((x: Int) => x, { @patternType type T; patternHole[T => T] }) + matches((x: Int) => x.toString, { @patternType type T; patternHole[T => T] }) + matches((x: Any) => ???, { @patternType type T; patternHole[T => T] }) + matches((x: Nothing) => (1 : Any), { @patternType type T; patternHole[T => T] }) } }