From fe6574ce384449aa21add25f387e3a71cffe726b Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 7 Feb 2022 11:04:25 +0000 Subject: [PATCH] Fix invariant quote type holes --- .../src/scala/quoted/runtime/impl/QuotesImpl.scala | 5 +++-- tests/pos-macros/i12343/Macro.scala | 13 +++++++++++++ tests/pos-macros/i12343/Test.scala | 7 +++++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/pos-macros/i12343/Macro.scala create mode 100644 tests/pos-macros/i12343/Test.scala diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index ae3067a894d7..000f84199c27 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -3056,8 +3056,9 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler // that we have found, seal them in a quoted.Type and add them to the result def typeHoleApproximation(sym: Symbol) = val fromAboveAnnot = sym.hasAnnotation(dotc.core.Symbols.defn.QuotedRuntimePatterns_fromAboveAnnot) - val approx = ctx1.gadt.approximation(sym, !fromAboveAnnot) - reflect.TypeReprMethods.asType(approx) + val fullBounds = ctx1.gadt.fullBounds(sym) + val tp = if fromAboveAnnot then fullBounds.hi else fullBounds.lo + reflect.TypeReprMethods.asType(tp) matchings.map { tup => Tuple.fromIArray(typeHoles.map(typeHoleApproximation).toArray.asInstanceOf[IArray[Object]]) ++ tup } diff --git a/tests/pos-macros/i12343/Macro.scala b/tests/pos-macros/i12343/Macro.scala new file mode 100644 index 000000000000..03642dd1f4af --- /dev/null +++ b/tests/pos-macros/i12343/Macro.scala @@ -0,0 +1,13 @@ +package test + +import scala.quoted.* + +object Macro: + def covImpl(arg: Expr[Any])(using Quotes): Expr[Any] = arg match // Covariant (List) + case '{ $h : List[h] } => '{ $h : List[h] } + + def invImpl(arg: Expr[Any])(using Quotes): Expr[Any] = arg match // Invariant (Set) + case '{ $h : Set[h] } => '{ $h : Set[h] } + + transparent inline def cov(inline arg: Any): Any = ${ covImpl('arg) } + transparent inline def inv(inline arg: Any): Any = ${ invImpl('arg) } diff --git a/tests/pos-macros/i12343/Test.scala b/tests/pos-macros/i12343/Test.scala new file mode 100644 index 000000000000..ef23a9c16725 --- /dev/null +++ b/tests/pos-macros/i12343/Test.scala @@ -0,0 +1,7 @@ +package test + +object Test: + val cov1: List[Boolean] = Macro.cov(List(true)) + val inv1: Set[Boolean] = Macro.inv(Set(true)) + def cov2[X](a: List[X]): List[X] = Macro.cov(a) + def inv2[X](a: Set[X]): Set[X] = Macro.inv(a) // doesn't compile; Set[Nothing] is inferred