Skip to content

Commit 2c2a279

Browse files
committed
Disallow macro expansion in compilation depending on BE files, add tests
Also includes some minor fixes to shown errors and to the test framework.
1 parent 1d42ed6 commit 2c2a279

File tree

13 files changed

+64
-8
lines changed

13 files changed

+64
-8
lines changed

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ object Denotations {
714714
|| ctx.settings.YtestPickler.value // mixing test pickler with debug printing can travel back in time
715715
|| ctx.mode.is(Mode.Printing) // no use to be picky when printing error messages
716716
|| symbol.isOneOf(ValidForeverFlags)
717-
|| ctx.isBestEffort,
717+
|| ctx.isBestEffort || ctx.usesBestEffortTasty,
718718
s"denotation $this invalid in run ${ctx.runId}. ValidFor: $validFor")
719719
var d: SingleDenotation = this
720720
while ({

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@ class TreePickler(pickler: TastyPickler) {
6262
fillRef(lengthAddr, currentAddr, relative = true)
6363
}
6464

65-
/* There are certain expectations with code naturally being able to reach typer vs
66-
* one that uses best-effort-compilation.
65+
/* There are certain expectations with code naturally being able to reach typer
66+
* as opposed to one that uses best-effort-compilation. For betasty files, we try
67+
* to avoid calling any assertions which can be unfullfilled.
6768
*/
6869
private inline def assertForBestEffort(assertion: Boolean)(using ctx: Context) =
6970
!ctx.isBestEffort || assertion
@@ -302,7 +303,7 @@ class TreePickler(pickler: TastyPickler) {
302303
pickleType(tpe.ref)
303304
case tpe: ErrorType if ctx.isBestEffort =>
304305
pickleError()
305-
case tree if ctx.isBestEffort =>
306+
case _ if ctx.isBestEffort =>
306307
pickleError()
307308
}
308309

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,7 @@ class Inliner(val call: tpd.Tree)(using Context):
835835

836836
override def typedSplice(tree: untpd.Splice, pt: Type)(using Context): Tree =
837837
super.typedSplice(tree, pt) match
838-
case tree1 @ Splice(expr) if level == 0 && !hasInliningErrors =>
838+
case tree1 @ Splice(expr) if level == 0 && !hasInliningErrors && !ctx.usesBestEffortTasty =>
839839
val expanded = expandMacro(expr, tree1.srcPos)
840840
transform.TreeChecker.checkMacroGeneratedTree(tree1, expanded)
841841
typedExpr(expanded) // Inline calls and constant fold code generated by the macro

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4214,6 +4214,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
42144214
* tree that went unreported. A scenario where this happens is i1802.scala.
42154215
*/
42164216
def ensureReported(tp: Type) = tp match {
4217+
case err: PreviousErrorType if ctx.usesBestEffortTasty => // do nothing if error was already reported in previous compilation
42174218
case err: ErrorType if !ctx.reporter.errorsReported => report.error(err.msg, tree.srcPos)
42184219
case _ =>
42194220
}

compiler/test/dotty/tools/dotc/BestEffortCompilationTests.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ class BestEffortCompilationTests {
2121
@Test def negTestFromBestEffortTasty: Unit = {
2222
// Can be reproduced with
2323
// > sbt
24-
// > scalac --Ybest-effort-dir best-effort-dir <source>
25-
// > scalac --from-tasty -Ywith-best-effort-tasty best-effort-dir/<tasty>
24+
// > scalac --Ybest-effort <source>
25+
// > scalac --from-tasty -Ywith-best-effort-tasty META_INF/best-effort/<tasty>
2626

2727
implicit val testGroup: TestGroup = TestGroup("negTestFromBestEffortTasty")
2828
compileBestEffortTastyInDir(s"tests${JFile.separator}neg", bestEffortBaselineOptions,
@@ -34,7 +34,7 @@ class BestEffortCompilationTests {
3434
// Tests an actual use case of this compilation mode, where symbol definitions of the downstream
3535
// projects depend on the best effort tasty files generated with the Best Effort dir option
3636
@Test def bestEffortIntergrationTest: Unit = {
37-
implicit val testGroup: TestGroup = TestGroup("BestEffortIntegrationTest")
37+
implicit val testGroup: TestGroup = TestGroup("bestEffortIntegrationTests")
3838
compileBestEffortIntegration(s"tests${JFile.separator}best-effort", bestEffortBaselineOptions)
3939
.noCrashWithCompilingDependencies()
4040
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
object ExecutedMacro:
2+
val failingMacro = FailingTransparent.execute()
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
object FailingTransparentInline:
2+
sealed trait Foo
3+
case class FooA() extends Foo
4+
case class FooB() extends Foo
5+
6+
transparent inline def execute(): Foo = ${ executeImpl() }
7+
def executeImpl(using Quotes)() = {
8+
val a = 0
9+
a.asInstanceOf[String]
10+
FooB()
11+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
object Main:
2+
ExecutedMacro.failingMacro
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.quoted._
2+
object BrokenMacros:
3+
transparent inline def macro1() = ${macroImpl()}
4+
def macroImpl(using Quotes)(): Expr[String] =
5+
val a: Int = "str" // source of the error
6+
'{a}
7+
8+
sealed trait Foo
9+
case class FooA() extends Foo
10+
case class FooB()
11+
transparent inline def macro2(): Foo = ${macro2Impl()}
12+
def macro2Impl(using Quotes)(): Expr[Foo] =
13+
'{FooB()}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object Main
2+
val a = BrokenMacros.macro1()
3+
val b = BrokenMacros.macro2()
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.quoted._
2+
object BrokenMacros:
3+
transparent inline def macro1() = ${macroImpl()}
4+
def macroImpl(using Quotes)(): Expr[String] =
5+
val a: Int = "str" // source of the error
6+
'{a}
7+
8+
sealed trait Foo
9+
case class FooA() extends Foo
10+
case class FooB()
11+
transparent inline def macro2(): Foo = ${macro2Impl()}
12+
def macro2Impl(using Quotes)(): Expr[Foo] =
13+
'{FooB()}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
object MirrorTypes:
2+
case class BrokenType(a: NonExistent, b: Int)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import scala.deriving.Mirror
2+
3+
object MirrorExec:
4+
transparent inline def getNames[T](using m: Mirror.Of[T]): m.MirroredElemTypes = // ???
5+
scala.compiletime.erasedValue[m.MirroredElemTypes]
6+
7+
val ab = getNames[MirrorTypes.BrokenType]
8+

0 commit comments

Comments
 (0)