scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.88k stars 1.06k forks source link

Confusing suggested import involving inline implicit #9685

Open mpilquist opened 4 years ago

mpilquist commented 4 years ago

Minimized code

import munit.FunSuite

class Example extends FunSuite {
  1.asdf
}

Output

[error] 4 |  1.asdf
[error]   |  ^^^^^^
[error]   |value asdf is not a member of Int, but could be made available as an extension method.
[error]   |
[error]   |The following import might make progress towards fixing the problem:
[error]   |
[error]   |  import munit.Clue.generate
[error]   |
[error] one error found

Expectation

Expected:

[error] 2 |  1.asdf
[error]   |  ^^^^^^
[error]   |  value asdf is not a member of Int

Dotty 0.27.0-RC1 suggests munit.Clue.generate to fix this issue. The clue method and Clue class are defined as:

inline implicit def generate[T](value: T): Clue[T] = ${ clueImpl('value) }

class Clue[+T](
    val source: String,
    val value: T,
    val valueType: String
)
sjrd commented 4 years ago

I've seen this problem before with another inline implicit def. I think the suggestion mechanism believes that inline defs can return anything, this potentially a more precise result that happens to be helpful in the given context. Whereas in fact blackbox inline defs cannot return a more specific type.

nicolasstucki commented 4 years ago

I could not reproduce it, I only get the error. @mpilquist could you write a self-contained code snipped that reproduces the issue?

mpilquist commented 4 years ago

@nicolasstucki I'll work on a standalone reproduction but here's an executable one in the meantime: https://scastie.scala-lang.org/bG9JkRnARomdC2pCPD5eAQ

mpilquist commented 4 years ago

OK this reproduces:

Clue.scala:

package foo

import scala.language.implicitConversions

class Clue[+T](val value: T)

object Clue {
  import scala.quoted._

  inline implicit def generate[T](value: T): Clue[T] = ${ clueImpl('value) }

  def clueImpl[T:Type](value: Expr[T])(using qctx: QuoteContext): Expr[Clue[T]] = '{ new Clue($value) }
}

Main.scala:

package foo

object Main {
  // If this def is removed, there's no suggestion to import Clue.generate
  def toClue[A](a: A): Clue[A] = Clue.generate(a)

  1.asdf
}
olafurpg commented 2 years ago

FWIW, we have been able to reproduce the same issue for regular implicit def without inline

https://github.com/scalameta/munit/blob/8558ab134313c30f94936c5a1ca5596bda4d6c67/tests/shared/src/test/scala/munit/AssertionsSuite.scala#L214

The implicit def implementation

https://github.com/scalameta/munit/blob/8558ab134313c30f94936c5a1ca5596bda4d6c67/tests/shared/src/main/scala/munit/CustomCompare.scala#L15

nicolasstucki commented 2 years ago

@olafurpg the original issue is already fixed. Could you check your use case with the current master to see if that one also got fixed? Otherwise, we should open another issue with that new scenario.

tgodzik commented 1 year ago

Looks like we have a new case that's failing: https://github.com/alessandrocandolini/munit-clue-confusing-suggestion

julienrf commented 1 year ago

Can the fix be backported to 3.3.x? Who should I ask for?

nicolasstucki commented 8 months ago

We had to revert the commit that closed this issue to fix #19415