Skip to content

Commit e40dbf2

Browse files
committed
Fix unbound type variables after implicit search
The issue was that an uninstantiated type variable escaped the implicit search and was then affected by the quote pattern match. Fixes #15779 Fixes #16636
1 parent ed5b119 commit e40dbf2

File tree

5 files changed

+79
-1
lines changed

5 files changed

+79
-1
lines changed

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2404,7 +2404,13 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
24042404

24052405
object Implicits extends ImplicitsModule:
24062406
def search(tpe: TypeRepr): ImplicitSearchResult =
2407-
ctx.typer.inferImplicitArg(tpe, Position.ofMacroExpansion.span)
2407+
import tpd.TreeOps
2408+
val implicitTree = ctx.typer.inferImplicitArg(tpe, Position.ofMacroExpansion.span)
2409+
// Make sure that we do not have any uninstantiated type variables.
2410+
// See tests/pos-macros/i16636.
2411+
// See tests/pos-macros/exprSummonWithTypeVar with -Xcheck-macros.
2412+
dotc.typer.Inferencing.fullyDefinedType(implicitTree.tpe, "", implicitTree)
2413+
implicitTree
24082414
end Implicits
24092415

24102416
type ImplicitSearchResult = Tree

tests/pos-macros/i15779/Macro_1.scala

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import scala.quoted._
2+
import scala.deriving.Mirror
3+
4+
trait Encoder[-A]
5+
6+
trait PrimitiveEncoder[A] extends Encoder[A]
7+
8+
given intOpt: PrimitiveEncoder[Option[Int]] with {}
9+
10+
given primitiveNotNull[T](using e: Encoder[Option[T]]): PrimitiveEncoder[T] =
11+
new PrimitiveEncoder[T] {}
12+
13+
transparent inline given fromMirror[A]: Any = ${ fromMirrorImpl[A] }
14+
15+
def fromMirrorImpl[A : Type](using q: Quotes): Expr[Any] =
16+
Expr.summon[Mirror.Of[A]].get match
17+
case '{ ${mirror}: Mirror.ProductOf[A] { type MirroredElemTypes = elementTypes } } =>
18+
val encoder = Type.of[elementTypes] match
19+
case '[tpe *: EmptyTuple] =>
20+
Expr.summon[Encoder[tpe]].get
21+
22+
encoder match
23+
case '{ ${encoder}: Encoder[tpe] } => // ok
24+
case _ => ???
25+
26+
encoder match
27+
case '{ ${encoder}: Encoder[tpe] } => // ok
28+
case _ => ???
29+
30+
encoder

tests/pos-macros/i15779/Test_2.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
case class JustInt(i: Int)
2+
3+
val x = fromMirror[JustInt]

tests/pos-macros/i16636/Macro_1.scala

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import scala.quoted.*
2+
3+
trait ReproTransformer[A, B] {
4+
def transform(from: A): B
5+
}
6+
7+
object ReproTransformer {
8+
final class Identity[A, B >: A] extends ReproTransformer[A, B] {
9+
def transform(from: A): B = from
10+
}
11+
12+
given identity[A, B >: A]: Identity[A, B] = Identity[A, B]
13+
14+
inline def getTransformer[A, B]: ReproTransformer[A, B] = ${ getTransformerMacro[A, B] }
15+
16+
def getTransformerMacro[A, B](using quotes: Quotes, A: Type[A], B: Type[B]) = {
17+
import quotes.reflect.*
18+
19+
val transformer = (A -> B) match {
20+
case '[a] -> '[b] =>
21+
val summoned = Expr.summon[ReproTransformer[a, b]].get
22+
// ----------- INTERESTING STUFF STARTS HERE
23+
summoned match {
24+
case '{ $t: ReproTransformer[src, dest] } => t
25+
}
26+
// ----------- INTERESTING STUFF ENDS HERE
27+
}
28+
transformer.asExprOf[ReproTransformer[A, B]]
29+
}
30+
}

tests/pos-macros/i16636/Test_2.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object A {
2+
case class AnotherCaseClass(name: String)
3+
4+
val errorsOut1 = ReproTransformer.getTransformer[A.AnotherCaseClass, AnotherCaseClass]
5+
val errorsOu2 = ReproTransformer.getTransformer[AnotherCaseClass, A.AnotherCaseClass]
6+
7+
val works1 = ReproTransformer.getTransformer[A.AnotherCaseClass, A.AnotherCaseClass]
8+
val works2 = ReproTransformer.getTransformer[AnotherCaseClass, AnotherCaseClass]
9+
}

0 commit comments

Comments
 (0)