Skip to content

Type infers widens union of applied abstract covariant types F[A] | F[B] into Any instead of F[A | B] #12264

Closed
@japgolly

Description

@japgolly

Compiler version

3.0.0-RC3

Minimized code

object Html {
  final opaque type Tag[+N] = String
  def apply[N](name: String): Tag[N] = name
}

object HtmlTags {
  final def br: Html.Tag[Int] = Html("br")
  final def p = Html[Long]("p")
}

object Test {
  type Expect = Html.Tag[Any]

  val x = List[Expect](HtmlTags.br, HtmlTags.p) // ok

  val y = List(HtmlTags.br, HtmlTags.p)
  y: List[Expect] // error
}

Output

[error] 17 |  y: List[Expect] // error
[error]    |  ^
[error]    |  Found:    (Test.y : List[Any])
[error]    |  Required: List[Test.Expect]

Expectation

Success.

Without opaque types

If we replace the opaque type with a case class and type alias, everything compiles successfully.

case class Html[+N](name: String)
object Html {
  type Tag[+N] = Html[N]
}

// object Html {
//   final opaque type Tag[+N] = String
//   def apply[N](name: String): Tag[N] = name
// }

// Code below is unchanged

object HtmlTags {
  final def br: Html.Tag[Int] = Html("br")
  final def p = Html[Long]("p")
}

object Test {
  type Expect = Html.Tag[Any]

  val x = List[Expect](HtmlTags.br, HtmlTags.p) // ok

  val y = List(HtmlTags.br, HtmlTags.p)
  y: List[Expect] // ok now
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions