Description
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 of1 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