From 443b03666b039fbcbb67acd24080d04a48c0b5ed Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 21 Oct 2021 10:33:06 +0200 Subject: [PATCH] Improve message when -Xmax-inlines limit reached Fixes #13044 --- .../dotty/tools/dotc/transform/Erasure.scala | 10 +++- .../dotty/tools/dotc/CompilationTests.scala | 1 + tests/neg/i13044.check | 44 ++++++++++++++++ tests/neg/i13044.scala | 51 +++++++++++++++++++ tests/pos-custom-args/i13044.scala | 51 +++++++++++++++++++ 5 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 tests/neg/i13044.check create mode 100644 tests/neg/i13044.scala create mode 100644 tests/pos-custom-args/i13044.scala diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 2875e2e2d865..ae2eac2c20fd 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -593,8 +593,14 @@ object Erasure { */ private def checkNotErased(tree: Tree)(using Context): tree.type = { if (!ctx.mode.is(Mode.Type)) { - if (isErased(tree)) - report.error(em"${tree.symbol} is declared as erased, but is in fact used", tree.srcPos) + if isErased(tree) then + val msg = + if tree.symbol.is(Flags.Inline) then + em"""${tree.symbol} is declared as `inline`, but was not inlined + | + |Try increasing `-Xmax-inlines` above ${ctx.settings.XmaxInlines.value}""".stripMargin + else em"${tree.symbol} is declared as `erased`, but is in fact used" + report.error(msg, tree.srcPos) tree.symbol.getAnnotation(defn.CompileTimeOnlyAnnot) match { case Some(annot) => def defaultMsg = diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index c94ebe563f72..a9e679eb6e95 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -63,6 +63,7 @@ class CompilationTests { compileFile("tests/pos-special/extend-java-enum.scala", defaultOptions.and("-source", "3.0-migration")), compileFile("tests/pos-custom-args/help.scala", defaultOptions.and("-help", "-V", "-W", "-X", "-Y")), compileFile("tests/pos-custom-args/i10383.scala", defaultOptions.and("-source", "future", "-deprecation", "-Xfatal-warnings")), + compileFile("tests/pos-custom-args/i13044.scala", defaultOptions.and("-Xmax-inlines:33")), ).checkCompile() } diff --git a/tests/neg/i13044.check b/tests/neg/i13044.check new file mode 100644 index 000000000000..87b8a1fe9ae2 --- /dev/null +++ b/tests/neg/i13044.check @@ -0,0 +1,44 @@ +-- Error: tests/neg/i13044.scala:50:40 --------------------------------------------------------------------------------- +50 | implicit def typeSchema: Schema[A] = Schema.gen // error // error + | ^^^^^^^^^^ + | given instance gen is declared as `inline`, but was not inlined + | + | Try increasing `-Xmax-inlines` above 32 + | This location contains code that was inlined from i13044.scala:17 + | This location contains code that was inlined from i13044.scala:31 + | This location contains code that was inlined from i13044.scala:37 + | This location contains code that was inlined from i13044.scala:17 + | This location contains code that was inlined from i13044.scala:31 + | This location contains code that was inlined from i13044.scala:37 + | This location contains code that was inlined from i13044.scala:17 + | This location contains code that was inlined from i13044.scala:31 + | This location contains code that was inlined from i13044.scala:37 + | This location contains code that was inlined from i13044.scala:17 + | This location contains code that was inlined from i13044.scala:31 + | This location contains code that was inlined from i13044.scala:37 + | This location contains code that was inlined from i13044.scala:17 + | This location contains code that was inlined from i13044.scala:18 + | This location contains code that was inlined from i13044.scala:31 + | This location contains code that was inlined from i13044.scala:37 +-- Error: tests/neg/i13044.scala:50:40 --------------------------------------------------------------------------------- +50 | implicit def typeSchema: Schema[A] = Schema.gen // error // error + | ^^^^^^^^^^ + | method recurse is declared as `inline`, but was not inlined + | + | Try increasing `-Xmax-inlines` above 32 + | This location contains code that was inlined from i13044.scala:18 + | This location contains code that was inlined from i13044.scala:31 + | This location contains code that was inlined from i13044.scala:37 + | This location contains code that was inlined from i13044.scala:17 + | This location contains code that was inlined from i13044.scala:31 + | This location contains code that was inlined from i13044.scala:37 + | This location contains code that was inlined from i13044.scala:17 + | This location contains code that was inlined from i13044.scala:31 + | This location contains code that was inlined from i13044.scala:37 + | This location contains code that was inlined from i13044.scala:17 + | This location contains code that was inlined from i13044.scala:31 + | This location contains code that was inlined from i13044.scala:37 + | This location contains code that was inlined from i13044.scala:17 + | This location contains code that was inlined from i13044.scala:18 + | This location contains code that was inlined from i13044.scala:31 + | This location contains code that was inlined from i13044.scala:37 diff --git a/tests/neg/i13044.scala b/tests/neg/i13044.scala new file mode 100644 index 000000000000..081b642c604c --- /dev/null +++ b/tests/neg/i13044.scala @@ -0,0 +1,51 @@ +import scala.deriving.Mirror +import scala.compiletime._ + +trait Schema[T] { + def build: T +} + +object Schema extends SchemaDerivation { + implicit lazy val int: Schema[Int] = ??? + implicit def option[A](implicit ev: Schema[A]): Schema[Option[A]] = ??? +} + +trait SchemaDerivation { + inline def recurse[A <: Tuple]: List[Schema[Any]] = + inline erasedValue[A] match { + case _: (t *: ts) => + val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]] + builder :: recurse[ts] + case _: EmptyTuple => Nil + } + + inline def derived[A]: Schema[A] = + inline summonInline[Mirror.Of[A]] match { + case m: Mirror.SumOf[A] => + lazy val subTypes = recurse[m.MirroredElemTypes] + new Schema[A] { + def build: A = ??? + } + + case m: Mirror.ProductOf[A] => + lazy val fields = recurse[m.MirroredElemTypes] + new Schema[A] { + def build: A = ??? + } + } + + inline given gen[A]: Schema[A] = derived +} + +case class H(i: Int) +case class G(h: H) +case class F(g: G) +case class E(f: Option[F]) +case class D(e: E) +case class C(d: D) +case class B(c: C) +case class A(a: A, b: B) + +object TestApp { + implicit def typeSchema: Schema[A] = Schema.gen // error // error +} diff --git a/tests/pos-custom-args/i13044.scala b/tests/pos-custom-args/i13044.scala new file mode 100644 index 000000000000..33a20b5800c8 --- /dev/null +++ b/tests/pos-custom-args/i13044.scala @@ -0,0 +1,51 @@ +import scala.deriving.Mirror +import scala.compiletime._ + +trait Schema[T] { + def build: T +} + +object Schema extends SchemaDerivation { + implicit lazy val int: Schema[Int] = ??? + implicit def option[A](implicit ev: Schema[A]): Schema[Option[A]] = ??? +} + +trait SchemaDerivation { + inline def recurse[A <: Tuple]: List[Schema[Any]] = + inline erasedValue[A] match { + case _: (t *: ts) => + val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]] + builder :: recurse[ts] + case _: EmptyTuple => Nil + } + + inline def derived[A]: Schema[A] = + inline summonInline[Mirror.Of[A]] match { + case m: Mirror.SumOf[A] => + lazy val subTypes = recurse[m.MirroredElemTypes] + new Schema[A] { + def build: A = ??? + } + + case m: Mirror.ProductOf[A] => + lazy val fields = recurse[m.MirroredElemTypes] + new Schema[A] { + def build: A = ??? + } + } + + inline given gen[A]: Schema[A] = derived +} + +case class H(i: Int) +case class G(h: H) +case class F(g: G) +case class E(f: Option[F]) +case class D(e: E) +case class C(d: D) +case class B(c: C) +case class A(a: A, b: B) + +object TestApp { + implicit def typeSchema: Schema[A] = Schema.gen +}