Skip to content

Different treatment of the Aux pattern between Dotty/scalac #3590

Closed
@OlivierBlanvillain

Description

@OlivierBlanvillain

Here is a minimized example showing a small difference between Dotty and scalac handling of the "Aux pattern". The issue is that when asking for an implicit Tagged.Aux[T, _] instead of Tagged[T], Dotty won't consider the companion object of T as part of the its implicit scopes.

trait Tagged[T]

object Tagged {
  type Aux[T, UNUSED] = Tagged[T]
}

trait Fun[R] {
  type Out
}

object Fun extends Fun0 {
  // In Dotty there is a difference between asking for Tagged.Aux[T, Int]
  // and asking for Tagged[T]. In the former case the companion of T is
  // not considered as a valid scope during implicit search. In scalac
  // both cases are treated equally.
  implicit def tagged[T](implicit t: Tagged.Aux[T, Int]): Fun[T] { type Out = Int } = ???
}

trait Fun0 {
  implicit def default[T]: Fun[T] { type Out = String } = ???
}

object FunDemo extends App {
  case class A(x: Int, y: String)
  object A {
    implicit val tag: Tagged[A] = ???
  }

  // Precise version of implicitly that keeps type members
  def the[T <: AnyRef](implicit ev: T): ev.type = ev

  val adhl = the[Fun[A]]

  // Compiles in scalac: the tagged case wins the implicit search using A.tag
  // Does not compile in Dotty: because of Tagged.Aux[T, _] the companion
  //                            object of T is not explored during the search,
  //                            it fallbacks to default (type Out = String)
  identity[Fun[A] { type Out = Int }](adhl)
}

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