Skip to content

Use the correct annotation for type pattern definitions #8692

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
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
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -942,14 +942,14 @@ object desugar {
*
* to
*
* @patternBindHole <mods> type $T >: Low <: Hi
* @patternType <mods> 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)
}
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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) =>
Expand Down
9 changes: 8 additions & 1 deletion library/src/scala/internal/quoted/Matcher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
}
Expand Down
3 changes: 3 additions & 0 deletions library/src/scala/tasty/reflect/CompilerInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
28 changes: 14 additions & 14 deletions tests/run-macros/quote-matcher-runtime.check
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]
()
Expand All @@ -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]
()
Expand All @@ -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]
()
Expand All @@ -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]
()
Expand All @@ -789,41 +789,41 @@ 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])
}
Result: Some(List(Type(scala.Int), Type(scala.Double), Type(java.lang.String), Expr(scala.List.apply[scala.Int](1, 2, 3)), Expr(((x: scala.Int) => x.toDouble./(2))), Expr(((y: scala.Double) => y.toString()))))

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])
}
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])
}
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])
}
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])
}
Expand Down
24 changes: 12 additions & 12 deletions tests/run-macros/quote-matcher-runtime/quoted_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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] })

}
}
Expand Down