From 79491f184b291718b9f16b0239e6ebf93e070b2c Mon Sep 17 00:00:00 2001 From: Jan Chyb Date: Mon, 7 Apr 2025 15:41:52 +0200 Subject: [PATCH 1/2] Fail not inlined inline methods calls early All of them would be achieved with implicit resolution, during which the global state (ctx.base) would have stopInlining set to true, but the corresponding error might not have been shown as part of the implicit resolution - now we reset that value after failing the implicit, if it was not set before typing the implicit. --- .../dotty/tools/dotc/typer/Implicits.scala | 4 + tests/neg/i13044.check | 134 ++---------------- tests/neg/i13044.scala | 2 +- tests/neg/i22423.check | 24 ++++ tests/neg/i22423.scala | 35 +++++ 5 files changed, 72 insertions(+), 127 deletions(-) create mode 100644 tests/neg/i22423.check create mode 100644 tests/neg/i22423.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index a1a01823e2f3..063513f1c295 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -1250,11 +1250,15 @@ trait Implicits: val history = ctx.searchHistory.nest(cand, pt) val typingCtx = nestedContext().setNewTyperState().setFreshGADTBounds.setSearchHistory(history) + val alreadyStoppedInlining = ctx.base.stopInlining val result = typedImplicit(cand, pt, argument, span)(using typingCtx) result match case res: SearchSuccess => ctx.searchHistory.defineBynameImplicit(wideProto, res) case _ => + if !alreadyStoppedInlining && ctx.base.stopInlining then + // a call overflowed as part of the expansion when typing the implicit + ctx.base.stopInlining = false // Since the search failed, the local typerstate will be discarded // without being committed, but type variables local to that state // might still appear in an error message, so we run `gc()` here to diff --git a/tests/neg/i13044.check b/tests/neg/i13044.check index 69c61b06c353..6d6b2a349eb7 100644 --- a/tests/neg/i13044.check +++ b/tests/neg/i13044.check @@ -1,63 +1,18 @@ --- Error: tests/neg/i13044.scala:46:40 --------------------------------------------------------------------------------- -46 | implicit def typeSchema: Schema[A] = Schema.gen // error // error +-- [E172] Type Error: tests/neg/i13044.scala:46:40 --------------------------------------------------------------------- +61 | implicit def typeSchema: Schema[A] = Schema.gen // error | ^^^^^^^^^^ - | given instance gen is declared as `inline`, but was not inlined + | No given instance of type Schema[B] was found. + | I found: | - | Try increasing `-Xmax-inlines` above 32 + | Schema.gen[B] + | + | But given instance gen in trait SchemaDerivation does not match type Schema[B]. |-------------------------------------------------------------------------------------------------------------------- |Inline stack trace |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 17 | val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]] - | ^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -29 | lazy val fields = recurse[m.MirroredElemTypes] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -33 | inline given gen[A]: Schema[A] = derived - | ^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -17 | val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]] - | ^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -29 | lazy val fields = recurse[m.MirroredElemTypes] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -33 | inline given gen[A]: Schema[A] = derived - | ^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -17 | val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]] - | ^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -29 | lazy val fields = recurse[m.MirroredElemTypes] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -33 | inline given gen[A]: Schema[A] = derived - | ^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -17 | val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]] - | ^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -29 | lazy val fields = recurse[m.MirroredElemTypes] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -33 | inline given gen[A]: Schema[A] = derived - | ^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 -17 | val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]] - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^ |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:17 18 | builder :: recurse[ts] @@ -71,76 +26,3 @@ 33 | inline given gen[A]: Schema[A] = derived | ^^^^^^^ -------------------------------------------------------------------------------------------------------------------- --- Error: tests/neg/i13044.scala:46:40 --------------------------------------------------------------------------------- -46 | 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 - |-------------------------------------------------------------------------------------------------------------------- - |Inline stack trace - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -18 | builder :: recurse[ts] - | ^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -29 | lazy val fields = recurse[m.MirroredElemTypes] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -33 | inline given gen[A]: Schema[A] = derived - | ^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -17 | val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]] - | ^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -29 | lazy val fields = recurse[m.MirroredElemTypes] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -33 | inline given gen[A]: Schema[A] = derived - | ^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -17 | val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]] - | ^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -29 | lazy val fields = recurse[m.MirroredElemTypes] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -33 | inline given gen[A]: Schema[A] = derived - | ^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -17 | val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]] - | ^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -29 | lazy val fields = recurse[m.MirroredElemTypes] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -33 | inline given gen[A]: Schema[A] = derived - | ^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -17 | val builder = summonInline[Schema[t]].asInstanceOf[Schema[Any]] - | ^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -18 | builder :: recurse[ts] - | ^^^^^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -29 | lazy val fields = recurse[m.MirroredElemTypes] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from i13044.scala:18 -33 | inline given gen[A]: Schema[A] = derived - | ^^^^^^^ - -------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg/i13044.scala b/tests/neg/i13044.scala index ad7687bbf2b8..525a52376abf 100644 --- a/tests/neg/i13044.scala +++ b/tests/neg/i13044.scala @@ -43,5 +43,5 @@ case class B(c: C) case class A(a: A, b: B) object TestApp { - implicit def typeSchema: Schema[A] = Schema.gen // error // error + implicit def typeSchema: Schema[A] = Schema.gen // error } diff --git a/tests/neg/i22423.check b/tests/neg/i22423.check new file mode 100644 index 000000000000..ec189d99524a --- /dev/null +++ b/tests/neg/i22423.check @@ -0,0 +1,24 @@ +-- Error: tests/neg/i22423.scala:35:14 --------------------------------------------------------------------------------- +35 | exportReader[Settings] // error + | ^^^^^^^^^^^^^^^^^^^^^^ + | cannot reduce summonFrom with + | patterns : case given reader @ _:ConfigReader[List[String]] + |-------------------------------------------------------------------------------------------------------------------- + |Inline stack trace + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |This location contains code that was inlined from i22423.scala:12 +12 | summonFrom { case reader: ConfigReader[A] => reader } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |This location contains code that was inlined from i22423.scala:12 +15 | summonConfigReader[List[String]] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |This location contains code that was inlined from i22423.scala:12 + 8 | readCaseClass() + | ^^^^^^^^^^^^^^^ + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |This location contains code that was inlined from i22423.scala:12 +30 |inline given exportReader[A]: Exported[ConfigReader[A]] = Exported(HintsAwareConfigReaderDerivation.deriveReader[A]) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + -------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg/i22423.scala b/tests/neg/i22423.scala new file mode 100644 index 000000000000..4204f8f93216 --- /dev/null +++ b/tests/neg/i22423.scala @@ -0,0 +1,35 @@ +//> using options -Xmax-inlines:7 +import scala.deriving.Mirror +import scala.compiletime._ +import scala.compiletime.ops.int._ + +object HintsAwareConfigReaderDerivation { + inline def deriveReader[A]: ConfigReader[A] = + readCaseClass() + ??? + + private inline def summonConfigReader[A]: ConfigReader[A] = + summonFrom { case reader: ConfigReader[A] => reader } + + private inline def readCaseClass(): Unit = + summonConfigReader[List[String]] + val a1: Int = ??? + val a2: EmptyTuple = ??? + a1 *: a2 + ??? +} + +trait ConfigReader[A] +object ConfigReader { + implicit def traversableReader[A, F[A] <: TraversableOnce[A]](implicit configConvert: ConfigReader[A]): ConfigReader[F[A]] = ??? + implicit def exportedReader[A](implicit exported: Exported[ConfigReader[A]]): ConfigReader[A] = exported.instance + case class Exported[A](instance: A) +} + +import ConfigReader._ +inline given exportReader[A]: Exported[ConfigReader[A]] = Exported(HintsAwareConfigReaderDerivation.deriveReader[A]) + +case class Settings(rules: List[String]) + +val settings = + exportReader[Settings] // error From 563653c5bf2ff80395c98fc25e8e43667d468814 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Tue, 8 Jul 2025 15:06:51 +0200 Subject: [PATCH 2/2] Fail not inlined inline methods calls early All of them would be achieved with implicit resolution, during which the global state (ctx.base) would have stopInlining set to true, but the corresponding error might not have been shown as part of the implicit resolution - now we reset that value after failing the implicit, if it was not set before typing the implicit. [Cherry-picked 0396584f18bf6adb12d0bf5ecbe1b1f6901c32b9][modified]