Skip to content

Commit 769b645

Browse files
Merge pull request #14827 from dotty-staging/fix-14772
Handle situation where an inline info cannot be computed
2 parents 95bae7d + aa2d3c5 commit 769b645

File tree

4 files changed

+42
-1
lines changed

4 files changed

+42
-1
lines changed

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ object Inliner {
4040

4141
private type DefBuffer = mutable.ListBuffer[ValOrDefDef]
4242

43+
/** An exception signalling that an inline info cannot be computed due to a
44+
* cyclic reference. i14772.scala shows a case where this happens.
45+
*/
46+
private[typer] class MissingInlineInfo extends Exception
47+
4348
/** `sym` is an inline method with a known body to inline.
4449
*/
4550
def hasBodyToInline(sym: SymDenotation)(using Context): Boolean =
@@ -154,7 +159,10 @@ object Inliner {
154159
if bindings.nonEmpty then
155160
cpy.Block(tree)(bindings.toList, inlineCall(tree1))
156161
else if enclosingInlineds.length < ctx.settings.XmaxInlines.value && !reachedInlinedTreesLimit then
157-
val body = bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
162+
val body =
163+
try bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
164+
catch case _: MissingInlineInfo =>
165+
throw CyclicReference(ctx.owner)
158166
new Inliner(tree, body).inlined(tree.srcPos)
159167
else
160168
ctx.base.stopInlining = true

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ class Namer { typer: Typer =>
103103
}
104104
}
105105

106+
def hasDefinedSymbol(tree: Tree)(using Context): Boolean =
107+
val xtree = expanded(tree)
108+
xtree.hasAttachment(TypedAhead) || xtree.hasAttachment(SymOfTree)
109+
106110
/** The enclosing class with given name; error if none exists */
107111
def enclosingClassNamed(name: TypeName, span: Span)(using Context): Symbol =
108112
if (name.isEmpty) NoSymbol
@@ -837,6 +841,10 @@ class Namer { typer: Typer =>
837841
private def addInlineInfo(sym: Symbol) = original match {
838842
case original: untpd.DefDef if sym.isInlineMethod =>
839843
def rhsToInline(using Context): tpd.Tree =
844+
if !original.symbol.exists && !hasDefinedSymbol(original) then
845+
throw
846+
if sym.isCompleted then Inliner.MissingInlineInfo()
847+
else CyclicReference(sym)
840848
val mdef = typedAheadExpr(original).asInstanceOf[tpd.DefDef]
841849
PrepareInlineable.wrapRHS(original, mdef.tpt, mdef.rhs)
842850
PrepareInlineable.registerInlineInfo(sym, rhsToInline)(using localContext(sym))

tests/neg/i14772.check

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-- [E044] Cyclic Error: tests/neg/i14772.scala:7:7 ---------------------------------------------------------------------
2+
7 | foo(a) // error
3+
| ^
4+
| Overloaded or recursive method impl needs return type
5+
|
6+
| longer explanation available when compiling with `-explain`
7+
-- Error: tests/neg/i14772.scala:8:12 ----------------------------------------------------------------------------------
8+
8 | Expr(()) // error
9+
| ^
10+
| no given instance of type quoted.ToExpr[Unit] was found for parameter x$2 of method apply in object Expr.
11+
| I found:
12+
|
13+
| quoted.ToExpr.ClassToExpr[T]
14+
|
15+
| But given instance ClassToExpr in object ToExpr does not match type quoted.ToExpr[Unit].

tests/neg/i14772.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import scala.quoted.*
2+
3+
object A {
4+
transparent inline def foo(a: Any): Any = ${ impl('a) }
5+
6+
def impl(a: Expr[Any])(using Quotes)/*: Expr[Any]*/ = {
7+
foo(a) // error
8+
Expr(()) // error
9+
}
10+
}

0 commit comments

Comments
 (0)