Skip to content

Opaque type with type parameter slot is never matched #21889

Open
@prolativ

Description

@prolativ

Compiler version

3.3.4, 3.5.2, 3.6.2-RC1-bin-20241104-8ab7ebe-NIGHTLY and older

Minimized code

Foo.scala:

class Foo

object Opaques:
  opaque type Bar[T] <: Foo = Foo
  object Bar:
    def apply[T]: Bar[T] = Foo()

export Opaques.Bar

class Baz[T] extends Foo

TypeValue1.scala:

inline def typeValue(inline foo: Foo): Int =
  inline foo match
    case bar: Bar[Int] =>
      1
    case bar: Bar[t] =>
      2
    case baz: Baz[Int] =>
      3
    case baz: Baz[t] =>
      4
    case _ =>
      5

TypeValue2.scala:

import scala.quoted.*

inline def typeValue(inline foo: Foo): Int = ${ typeValueImpl('foo) }

def typeValueImpl(foo: Expr[Foo])(using Quotes) =
  foo match
    case '{ $bar: Bar[Int] } =>
      '{ 1 }
    case '{ $bar: Bar[t] } =>
      '{ 2 }
    case '{ $baz: Baz[Int] } =>
      '{ 3 }
    case '{ $baz: Baz[t] } =>
      '{ 4 }
    case _ =>
      '{ 5 }

TypeValue3.scala:

import scala.quoted.*

inline def typeValue(inline foo: Foo): Int = ${ typeValueImpl('foo) }

def typeValueImpl(foo: Expr[Foo])(using Quotes) =
  import quotes.reflect.*

  foo.asTerm.tpe.asType match
    case '[Bar[Int]] =>
      '{ 1 }
    case '[Bar[t]] =>
      '{ 2 }
    case '[Baz[Int]] =>
      '{ 3 }
    case '[Baz[t]] =>
      '{ 4 }
    case _ =>
      '{ 5 }

Test.scala:

@main def test() =
  println(typeValue(Bar[Int]))
  println(typeValue(Bar[String]))
  println(typeValue(Baz[Int]))
  println(typeValue(Baz[String]))

Output

When running Foo.scala, Test.scala and one of {TypeValue1.scala, TypeValue2.scala, TypeValue3.scala} at a time the stdout is

1
5
3
4

Expectation

This should print

1
2
3
4

instead.

Further investigation

If we replace Bar[t] and Baz[t] with Bar[?] and Baz[?] respectively in TypeValue{1,2,3}.scala then:

  • in cases 2 and 3 the compiler reports an error:
unreducible application of higher-kinded type [T] =>> Opaques.Bar[T] to wildcard arguments
    case '[Bar[?]] =>
  • in case 1 no error is reported and the program runs, but still prints 1 5 3 4 instead of 1 2 3 4.

The error messages are not very informative, giving no hint what should be changed to make this work and why there's a difference in behaviour between a class and an opaque type.
I would expect the code to always compile and print 1 2 3 4.
However, if the unreducible application it indeed a limitation that we cannot overcome (at all or at least for now), we should improve the error and report it in all the situations when this limitation might lead to letting the code compile and give wrong/unexpected results

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