Skip to content

Inconsistent summonInline behavior #15788

@yurikpanic

Description

@yurikpanic

We define an inline given type class instance, which may end up with calling scala.compiletime.error at some point.
Things work as expected if the error is not called when:

  • we use it via using argument to an inline method (fff1 in the example below)
  • if we call summonInline for the instance from the object for a distinct case class
  • if we call summonInline from within an inline method (fff2 in the example below)

But if the compiletime.error is called the behavior is different in these cases

  • we use it via using argument to an inline method - the custom error message is returned at the compile time - OK
  • if we call summonInline for the instance from the object for a distinct case class - the custom error message is returned at the compile time - OK
  • if we call summonInline from within an inline method - no given instance of type Test[Test2] was found. error is returned. - does not look as correct (or at least expected) behavior to me.

Compiler version

Checked on 3.1.3 and 3.2.1-RC1-bin-SNAPSHOT-git-f157978

Minimized code

import scala.deriving.Mirror
import scala.compiletime.*

trait Test[A] {
  def test: String
}

object Test {

  inline def findA[T <: Tuple]: Unit =
    inline erasedValue[T] match {
      case _: EmptyTuple  => error("Field 'a' not found")
      case _: ("a" *: tl) => ()
      case _: (_ *: tl)   => findA[tl]
    }

  inline given [A <: Product](using mm: Mirror.ProductOf[A]): Test[A] = new {
    override def test: String = {
      findA[mm.MirroredElemLabels]
      "test"
    }
  }
}

final case class Test1(a: String, b: Int)
final case class Test2(q: String, w: Int)

object Main {
  inline def fff1[P <: Product](using ggg: Test[P]): String = {
    ggg.test
  }

  inline def fff2[P <: Product]: String = {
    summonInline[Test[P]].test
  }

  fff1[Test1]
  fff1[Test2]

  summonInline[Test[Test1]].test
  summonInline[Test[Test2]].test

  fff2[Test1]
  fff2[Test2]
}

Output

-- Error: xxx.scala:38:13 ------------------------------------------------------
38 |  fff1[Test2]
   |             ^
   |             Field 'a' not found
-- Error: xxx.scala:41:15 ------------------------------------------------------
41 |  summonInline[Test[Test2]].test
   |               ^
   |               Field 'a' not found
-- Error: xxx.scala:44:6 -------------------------------------------------------
44 |  fff2[Test2]
   |  ^^^^^^^^^^^
   |no given instance of type Test[Test2] was found.
   |I found:
   |
   |    Test.given_Test_A[Test2](
   |      Test2.$asInstanceOf[
   |
   |          (
   |            deriving.Mirror.Product{
   |              MirroredType = Test2; MirroredMonoType = Test2;
   |                MirroredElemTypes <: Tuple
   |            }
   |           &
   |            scala.deriving.Mirror.Product{
   |              MirroredMonoType = Test2; MirroredType = Test2;
   |                MirroredLabel = ("Test2" : String)
   |            }
   |          ){
   |            MirroredElemTypes = (String, Int);
   |              MirroredElemLabels = (("q" : String), ("w" : String))
   |          }
   |
   |      ]
   |    )
   |
   |But given instance given_Test_A in object Test does not match type Test[Test2].
   |----------------------------------------------------------------------------
   |Inline stack trace
   |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   |This location contains code that was inlined from xxx.scala:34
34 |    summonInline[Test[P]].test
   |    ^^^^^^^^^^^^^^^^^^^^^
    ----------------------------------------------------------------------------

Expectation

All three errors should be Field 'a' not found

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions