diff --git a/compiler/src/dotty/tools/dotc/CompilationUnit.scala b/compiler/src/dotty/tools/dotc/CompilationUnit.scala index 13ae18141c67..2ffb201609b1 100644 --- a/compiler/src/dotty/tools/dotc/CompilationUnit.scala +++ b/compiler/src/dotty/tools/dotc/CompilationUnit.scala @@ -23,6 +23,7 @@ class CompilationUnit protected (val source: SourceFile) { var tpdTree: tpd.Tree = tpd.EmptyTree + /** Is this the compilation unit of a Java file */ def isJava: Boolean = source.file.name.endsWith(".java") /** The source version for this unit, as determined by a language import */ @@ -47,7 +48,14 @@ class CompilationUnit protected (val source: SourceFile) { var suspended: Boolean = false + /** Can this compilation unit be suspended */ + def isSuspendable: Boolean = true + + /** Suspends the compilation unit by thowing a SuspendException + * and recoring the suspended compilation unit + */ def suspend()(using Context): Nothing = + assert(isSuspendable) if !suspended then if (ctx.settings.XprintSuspension.value) ctx.echo(i"suspended: $this") diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index 62fe2d8fe79f..386c63a08a1c 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -393,7 +393,7 @@ object Splicer { ex.getTargetException match { case ex: scala.quoted.Reporting.StopQuotedContext => throw ex - case MissingClassDefinedInCurrentRun(sym) => + case MissingClassDefinedInCurrentRun(sym) if ctx.compilationUnit.isSuspendable => if (ctx.settings.XprintSuspension.value) ctx.echo(i"suspension triggered by a dependency on $sym", pos) ctx.compilationUnit.suspend() // this throws a SuspendException diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index e9e9d9420041..6355bd53d34d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -1407,14 +1407,15 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { assert(level == 0) val inlinedFrom = enclosingInlineds.last val dependencies = macroDependencies(body) - + val suspendable = ctx.compilationUnit.isSuspendable if dependencies.nonEmpty && !ctx.reporter.errorsReported then for sym <- dependencies do if ctx.compilationUnit.source.file == sym.associatedFile then ctx.error(em"Cannot call macro $sym defined in the same source file", call.sourcePos) - if (ctx.settings.XprintSuspension.value) + if (suspendable && ctx.settings.XprintSuspension.value) ctx.echo(i"suspension triggered by macro call to ${sym.showLocated} in ${sym.associatedFile}", call.sourcePos) - ctx.compilationUnit.suspend() // this throws a SuspendException + if suspendable then + ctx.compilationUnit.suspend() // this throws a SuspendException val evaluatedSplice = inContext(tastyreflect.MacroExpansion.context(inlinedFrom)) { Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext) diff --git a/compiler/src/dotty/tools/repl/ReplCompiler.scala b/compiler/src/dotty/tools/repl/ReplCompiler.scala index 96eb187b2eac..7947022444aa 100644 --- a/compiler/src/dotty/tools/repl/ReplCompiler.scala +++ b/compiler/src/dotty/tools/repl/ReplCompiler.scala @@ -146,7 +146,7 @@ class ReplCompiler extends Compiler { val objectTermName = ctx.source.file.toString.toTermName objectNames.update(defs.state.objectIndex, objectTermName) - val unit = CompilationUnit(ctx.source) + val unit = new ReplCompilationUnit(ctx.source) unit.untpdTree = wrapped(defs, objectTermName, span) unit } diff --git a/compiler/src/dotty/tools/repl/ReplCompillationUnit.scala b/compiler/src/dotty/tools/repl/ReplCompillationUnit.scala new file mode 100644 index 000000000000..d3f2cee7e207 --- /dev/null +++ b/compiler/src/dotty/tools/repl/ReplCompillationUnit.scala @@ -0,0 +1,8 @@ +package dotty.tools.repl + +import dotty.tools.dotc.CompilationUnit +import dotty.tools.dotc.util.SourceFile + + +class ReplCompilationUnit(source: SourceFile) extends CompilationUnit(source): + override def isSuspendable: Boolean = false diff --git a/compiler/test-resources/repl/i9227 b/compiler/test-resources/repl/i9227 new file mode 100644 index 000000000000..97f9caab6bca --- /dev/null +++ b/compiler/test-resources/repl/i9227 @@ -0,0 +1,5 @@ +scala> import scala.quoted._; inline def myMacro[T]: Unit = ${ myMacroImpl[T] }; def myMacroImpl[T](using qctx: QuoteContext): Expr[Unit] = '{}; println(myMacro[Int]) +1 | import scala.quoted._; inline def myMacro[T]: Unit = ${ myMacroImpl[T] }; def myMacroImpl[T](using qctx: QuoteContext): Expr[Unit] = '{}; println(myMacro[Int]) + | ^^^^^^^^^^^^ + | Cannot call macro method myMacroImpl defined in the same source file + | This location contains code that was inlined from rs$line$1:1