Skip to content

summonInline still fails #12415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
soronpo opened this issue May 11, 2021 · 2 comments
Closed

summonInline still fails #12415

soronpo opened this issue May 11, 2021 · 2 comments

Comments

@soronpo
Copy link
Contributor

soronpo commented May 11, 2021

Possibly related to #12379
@michelou
There are still differences between summonInline and a using argument.

Compiler version

3.0 master branch

Minimized code

import scala.language.implicitConversions
import scala.compiletime.*

object Good:
  trait ~[Of]:
    type To <: Of
    val value : To
  object ~ :
    trait Conversion[Of, From]:
      type To <: Of
      def apply(from : From) : To
    transparent inline implicit def conv[Of, From](inline from : From)(using c : Conversion[Of, from.type]) : ~[Of] =
      new ~[Of]:
        type To = c.To
        val value : To = c(from)

  class Foo[T](value : T)
  transparent inline given [F <: Int] : ~.Conversion[Foo[_], F] = new ~.Conversion[Foo[_], F] {
    type To = Foo[F]
    def apply(from: F): Foo[F] = new Foo(from)
  }
  def foo(x : ~[Foo[_]]) = x.value

  val f1 = foo(1)
  val f1_ : Foo[1] = f1
  val one = 1
  val fOne = foo(one)
  val fOne_ : Foo[one.type] = fOne


object Bad:
  trait ~[Of]:
    type To <: Of
    val value : To
  object ~ :
    trait Conversion[Of, From]:
      type To <: Of
      def apply(from : From) : To
    transparent inline implicit def conv[Of, From](inline from : From) : ~[Of] =
      val c = summonInline[Conversion[Of, from.type]]
      new ~[Of]:
        type To = c.To
        val value : To = c(from)

  class Foo[T](value : T)
  transparent inline given [F <: Int] : ~.Conversion[Foo[_], F] = new ~.Conversion[Foo[_], F] {
    type To = Foo[F]
    def apply(from: F): Foo[F] = new Foo(from)
  }
  def foo(x : ~[Foo[_]]) = x.value

  val f1 = foo(1)
  val f1_ : Foo[1] = f1
  val one = 1
  val fOne = foo(one)
  val fOne_ : Foo[one.type] = fOne

Output

54 |  val f1 = foo(1)
   |               ^
   |               Found:    (1 : Int)
   |               Required: Bad.~[Bad.Foo[?]]

longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: sandbox\Main.scala:57:17 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

57 |  val fOne = foo(one)
   |                 ^^^
   |                 Found:    (Bad.one : Int)
   |                 Required: Bad.~[Bad.Foo[?]]

Expectation

summonInline use should be equivalent to a using clause.

@soronpo
Copy link
Contributor Author

soronpo commented May 11, 2021

I also included the PR #12409 to verify it's not related to that issue.

@nicolasstucki
Copy link
Contributor

summonInline use should be equivalent to a using clause.

That is not the case. When an argument is inferred for a using clause it can/must be part of type inference of the type parameters of the method. On the other hand with an inline method, the type parameters are inferred first and then the code is inlined and then the summonInline looks for the implicit based on the type that has already been determined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants