Skip to content

Match type failure on opaque types prevents zero-cost abstractions in arbitrary tuples #23084

Closed
@Ichoran

Description

@Ichoran

Compiler version

3.6.4 (or 3.7-RC4)

Minimized example

Runnable example

object OpaqueScope:
  opaque type Opaque[A, B] = Unit
  trait Trait[A, B] {}

object OtherScope:
  import OpaqueScope.*

  type OpaqueLeft[Tp <: Tuple] = Tp match
    case EmptyTuple => Nothing
    case Opaque[l, _] *: _ => l
    case _ *: rest => OpaqueLeft[rest]

  type TraitLeft[Tp <: Tuple] = Tp match
    case EmptyTuple => Nothing
    case Trait[l, _] *: _ => l
    case _ *: rest => TraitLeft[rest]

  def leftO[Tp <: Tuple](x: OpaqueLeft[Tp]): Int = x.##
  def leftT[Tp <: Tuple](x: TraitLeft[Tp]): Int = x.##

  val traited = leftT[(Int, Trait[Char, Boolean], String)]('e')
  val opaqued = leftO[(Int, Opaque[Char, Boolean], String)]('e')

Output

Found:    ('e' : Char)
Required: Playground.OtherScope.OpaqueLeft[(Int,
  Playground.OpaqueScope.Opaque[Char, Boolean], String)]

Note: a match type could not be fully reduced:

  trying to reduce  Playground.OtherScope.OpaqueLeft[(Int,
  Playground.OpaqueScope.Opaque[Char, Boolean], String)]
  failed since selector (Int, Playground.OpaqueScope.Opaque[Char, Boolean], String)
  does not match  case Playground.OpaqueScope.Opaque[l, _] *: _ => l
  and cannot be shown to be disjoint from it either.
  Therefore, reduction cannot advance to the remaining case

    case _ *: rest => Playground.OtherScope.OpaqueLeft[rest]

Expectation

The compiler will treat type-level computations on types the same way, regardless of type, so it is irrelevant whether the type is opaque or not when doing a match type computation.

Alternatively, case Opaque[l, _] *: _ => ... will fail to compile. If it is intrinsically unmatchable, it should complain when you try to match on it and not leave you wondering why two things of the same shape behave differently.

Because opaque types are the primary mechanism for zero-cost abstraction in Scala, the former is strongly preferred.

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