Skip to content
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

Opaque type with type parameter slot is never matched #21889

Open
prolativ opened this issue Nov 5, 2024 · 0 comments
Open

Opaque type with type parameter slot is never matched #21889

prolativ opened this issue Nov 5, 2024 · 0 comments

Comments

@prolativ
Copy link
Contributor

prolativ commented Nov 5, 2024

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

@prolativ prolativ added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label area:typer area:opaque-types and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Nov 5, 2024
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

2 participants