@@ -48,6 +48,36 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
4848 case _ => EmptyTree
4949 end synthesizedClassTag
5050
51+ lazy val synthesizedTypeTest : SpecialHandler =
52+ (formal, span) => formal.argInfos match {
53+ case arg1 :: arg2 :: Nil if ! defn.isBottomClass(arg2.typeSymbol) =>
54+ val tp1 = fullyDefinedType(arg1, " TypeTest argument" , span)
55+ val tp2 = fullyDefinedType(arg2, " TypeTest argument" , span)
56+ val sym2 = tp2.typeSymbol
57+ if tp1 <:< tp2 then
58+ ref(defn.TypeTestModule_identity ).appliedToType(tp2).withSpan(span)
59+ else if sym2 == defn.AnyValClass || sym2 == defn.AnyRefAlias || sym2 == defn.ObjectClass then
60+ EmptyTree
61+ else
62+ // Generate SAM: (s: <tp1>) => if s.isInstanceOf[s.type & <tp2>] then Some(s.asInstanceOf[s.type & <tp2>]) else None
63+ def body (args : List [Tree ]): Tree = {
64+ val arg :: Nil = args
65+ val t = arg.tpe & tp2
66+ If (
67+ arg.select(defn.Any_isInstanceOf ).appliedToType(t),
68+ ref(defn.SomeClass .companionModule.termRef).select(nme.apply)
69+ .appliedToType(t)
70+ .appliedTo(arg.select(nme.asInstanceOf_).appliedToType(t)),
71+ ref(defn.NoneModule ))
72+ }
73+ val tpe = MethodType (List (nme.s))(_ => List (tp1), mth => defn.OptionClass .typeRef.appliedTo(mth.newParamRef(0 ) & tp2))
74+ val meth = ctx.newSymbol(ctx.owner, nme.ANON_FUN , Synthetic | Method , tpe, coord = span)
75+ val typeTestType = defn.TypeTestClass .typeRef.appliedTo(List (tp1, tp2))
76+ Closure (meth, tss => body(tss.head).changeOwner(ctx.owner, meth), targetType = typeTestType).withSpan(span)
77+ case _ =>
78+ EmptyTree
79+ }
80+
5181 /** Synthesize the tree for `'[T]` for an implicit `scala.quoted.Type[T]`.
5282 * `T` is deeply dealiased to avoid references to local type aliases.
5383 */
@@ -389,6 +419,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
389419
390420 val specialHandlers = List (
391421 defn.ClassTagClass -> synthesizedClassTag,
422+ defn.TypeTestClass -> synthesizedTypeTest,
392423 defn.QuotedTypeClass -> synthesizedTypeTag,
393424 defn.EqlClass -> synthesizedEql,
394425 defn.TupledFunctionClass -> synthesizedTupleFunction,
0 commit comments