Skip to content

Implicit not found in clean compilation, but found in incremental compilation #13121

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

Open
soronpo opened this issue Jul 21, 2021 · 5 comments
Open

Comments

@soronpo
Copy link
Contributor

soronpo commented Jul 21, 2021

This was extremely difficult to minimize, and this is as short as I could make it.
In clean compilation we get an implicit not found error, but if we comment out dfVal.as(DFBool) in DFBool.scala the code compiles successfully, and afterwords we can uncomment it and still get a successful compilation.
The compilation order is affected from very little things and there is a special order that causes the implicit not to be found. To get this order various features take place and include export, inline macro, extension methods, and opaque types.

Compiler version

3.0.3-RC1-bin-20210716-cc47c56-NIGHTLY

Minimized code

Minimized project at: https://github.com/soronpo/dottybug/tree/inc_implicit_err

DFBool.scala

opaque type DFBool <: DFType with HasToken =
  DFType with HasToken

trait HasToken

extension (dfVal: DFVal[DFBool]) def bar: Unit = dfVal.as(DFBool)

final val DFBool: DFBool = ???

DFType.scala

opaque type DFType = Int
object DFType:
  extension (dfType: Int) def asFE[T <: DFType]: T = dfType.asInstanceOf[T]

  trait TC[T]:
    type Type <: DFType
    def apply(t: T): Type
  object TC:
    given ofDFType[T <: DFType]: TC[T] with
      type Type = T
      def apply(t: T): Type = t
  end TC

export DFType.asFE

DFVal.scala

opaque type DFVal[T <: DFType] = Int

extension [T <: DFType](dfVal: DFVal[T])
  def as[A](aliasType: A)(using
      tc: DFType.TC[A],
      w1: Width[?]
  ): DFVal[tc.Type] = ???

Width.scala

import scala.quoted.*

trait Width[T]:
  type Out <: Int
object Width:
  transparent inline given [T]: Width[T] = ${ getWidthMacro[T] }
  def getWidthMacro[T](using Quotes, Type[T]): Expr[Width[T]] =
    import quotes.reflect.*
    '{
      new Width[T] {
        type Out = 1
      }
    }

Output

[error] -- Error: C:\IdeaProjects\dottybug\src\main\scala\DFBool.scala:6:65 ---------------------------------------
[error] 6 |extension (dfVal: DFVal[DFBool]) def bar: Unit = dfVal.as(DFBool)
[error]   |                                                                 ^
[error]   |              no implicit argument of type DFType.TC[DFBool] was found for parameter tc of method as.
[error]   |              I found:
[error]   |
[error]   |                  DFType.TC.ofDFType[T]
[error]   |
[error]   |              But given instance ofDFType in object TC does not match type DFType.TC[DFBool].
[error] one error found

Expectation

No error.

@griggt
Copy link
Contributor

griggt commented Jul 21, 2021

Slightly smaller:

DFBool.scala

trait HasToken

opaque type DFBool <: DFType with HasToken = DFType with HasToken

def bar(v: DFVal): Unit = v.as[DFBool]

DFType.scala

opaque type DFType = Int

object DFType:
  def foo: Unit = ???

  trait TC[T]
  object TC:
    given [T <: DFType]: TC[T] = ???

export DFType.foo

trait DFVal:
  def as[A](using tc: DFType.TC[A], w: Width): Unit = ()

Width.scala

import scala.quoted.*

trait Width
object Width:
  inline given Width = ${ getWidthMacro }
  def getWidthMacro(using Quotes): Expr[Width] = '{ new Width {} }

@soronpo
Copy link
Contributor Author

soronpo commented Jul 21, 2021

Slightly smaller:
....

Thanks. I updated the branch with your smaller example.

@mpilquist
Copy link
Contributor

Is the following another example or something different? With 3.0.1

  cs launch scala3-repl
scala> object Foo:
     |   opaque type Bar = Int
     |   object Bar:
     |     extension (b: Bar) def flip: Bar = -b
     |     def apply(x: Int): Bar = x
     |
// defined object Foo

scala> val a = Foo.Bar(42)
val a: Foo.Bar = 42

scala> val b = a.flip
val b: Foo.Bar = -42

scala> val c = b.flip
val c: Foo.Bar = 42

scala> val d = c.flip
1 |val d = c.flip
  |        ^^^^^^
  |value flip is not a member of Foo.Bar, but could be made available as an extension method.
  |
  |The following import might fix the problem:
  |
  |  import Foo.Bar.flip
  |

scala>

@soronpo
Copy link
Contributor Author

soronpo commented Aug 30, 2021

Is the following another example or something different? With 3.0.1

To me it looks like a separate issue

@mpilquist
Copy link
Contributor

Whoops, I meant to link to #10044

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

5 participants