Skip to content

Commit 508dba4

Browse files
committed
Expr#show: Don't crash when the expression contains an unsupported type (like a SkolemType)
When the SkolemType appears as the prefix of a TypeRef, we avoid it by going using `qualifier` which is defined in QuotesImpl to widen skolem, but skolems can appear in any position, and so before this change we would get a compiler crash in the added test case where the skolem appears as the prefix of a TermRef. We fix this by adding fallback cases in the quotes pretty-printer, now for the test case we get: Test.f.ho(((arg: <<SkolemType(693709097) does not have a corresponding extractor> does not have a source representation>.x.type) => arg)) Which isn't great, but better than a crash. Maybe we should run `Type#deskolemized` on a type before trying to print it in SourceCode/Extractors, but currently these files are intentionally defined to not depend on compiler internals and do not have a `Context` so we cannot even call `deskolemized` on them. Alternatively, maybe SkolemType should be a tasty-reflect constructor but that would also be a pretty big change.
1 parent 6e852d2 commit 508dba4

File tree

4 files changed

+28
-3
lines changed

4 files changed

+28
-3
lines changed

compiler/src/scala/quoted/runtime/impl/printers/Extractors.scala

+4
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ object Extractors {
177177
this += "Alternatives(" ++= patterns += ")"
178178
case TypedOrTest(tree, tpt) =>
179179
this += "TypedOrTest(" += tree += ", " += tpt += ")"
180+
case tree =>
181+
this += s"<Internal compiler AST $tree does not have a corresponding reflect extractor>"
180182
}
181183

182184
def visitConstant(x: Constant): this.type = x match {
@@ -241,6 +243,8 @@ object Extractors {
241243
this += "MatchCase(" += pat += ", " += rhs += ")"
242244
case FlexibleType(tp) =>
243245
this += "FlexibleType(" += tp += ")"
246+
case tp =>
247+
this += s"<Internal compiler type $tp does not have a corresponding reflect extractor>"
244248
}
245249

246250
def visitSignature(sig: Signature): this.type = {

compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala

+5-3
Original file line numberDiff line numberDiff line change
@@ -1292,7 +1292,9 @@ object SourceCode {
12921292
val sym = annot.tpe.typeSymbol
12931293
sym != Symbol.requiredClass("scala.forceInline") &&
12941294
sym.maybeOwner != Symbol.requiredPackage("scala.annotation.internal")
1295-
case x => cannotBeShownAsSource(x.show(using Printer.TreeStructure))
1295+
case x =>
1296+
cannotBeShownAsSource(x.show(using Printer.TreeStructure))
1297+
false
12961298
}
12971299
printAnnotations(annots)
12981300
if (annots.nonEmpty) this += " "
@@ -1463,8 +1465,8 @@ object SourceCode {
14631465
}
14641466
}
14651467

1466-
private def cannotBeShownAsSource(x: String): Nothing =
1467-
throw new Exception(s"$x does not have a source representation")
1468+
private def cannotBeShownAsSource(x: String): this.type =
1469+
this += s"<$x does not have a source representation>"
14681470

14691471
private object SpecialOp {
14701472
def unapply(arg: Tree): Option[(String, List[Term])] = arg match {

tests/pos-macros/skolem/Macro_1.scala

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import scala.quoted.*
2+
3+
object Macro {
4+
5+
def impl(expr: Expr[Any])(using Quotes): Expr[Unit] =
6+
println(expr.show)
7+
'{ () }
8+
9+
inline def macr(inline x: Any): Unit = ${impl('x)}
10+
}

tests/pos-macros/skolem/Test_2.scala

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
trait Foo:
2+
val x: Int
3+
def ho(p: x.type => x.type): Unit = ()
4+
5+
object Test {
6+
var f: Foo = ???
7+
Macro.macr:
8+
f.ho(arg => arg)
9+
}

0 commit comments

Comments
 (0)