Closed
Description
See this discussion thread.
Compiler version
3.1.3
Minimized code
sealed trait NatT
case class Zero() extends NatT
case class Succ[+N <: NatT](n: N) extends NatT
type Mod2[N <: NatT] <: NatT = N match
case Zero => Zero
case Succ[Zero] => Succ[Zero]
case Succ[Succ[predPredN]] => Mod2[predPredN]
def mod2(n: NatT): NatT = n match
case Zero() => Zero()
case Succ(Zero()) => Succ(Zero())
case Succ(Succ(predPredN)) => mod2(predPredN)
inline def inlineMod2(inline n: NatT): NatT = inline n match
case Zero() => Zero()
case Succ(Zero()) => Succ(Zero())
case Succ(Succ(predPredN)) => inlineMod2(predPredN)
transparent inline def transparentInlineMod2(inline n: NatT): NatT = inline n match
case Zero() => Zero()
case Succ(Zero()) => Succ(Zero())
case Succ(Succ(predPredN)) => transparentInlineMod2(predPredN)
def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match // exhaustivity warning; unexpected
case Zero(): Zero => Zero()
case Succ(Zero()): Succ[Zero] => Succ(Zero())
case Succ(Succ(predPredN)): Succ[Succ[_]] => dependentlyTypedMod2(predPredN)
inline def inlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match
case Zero(): Zero => Zero()
case Succ(Zero()): Succ[Zero] => Succ(Zero())
case Succ(Succ(predPredN)): Succ[Succ[_]] => inlineDependentlyTypedMod2(predPredN)
transparent inline def transparentInlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match
case Zero(): Zero => Zero()
case Succ(Zero()): Succ[Zero] => Succ(Zero())
case Succ(Succ(predPredN)): Succ[Succ[_]] => transparentInlineDependentlyTypedMod2(predPredN)
def foo(n: NatT): NatT = mod2(n) match
case Succ(Zero()) => Zero()
case _ => n
inline def inlineFoo(inline n: NatT): NatT = inline inlineMod2(n) match
case Succ(Zero()) => Zero()
case _ => n
inline def transparentInlineFoo(inline n: NatT): NatT = inline transparentInlineMod2(n) match
case Succ(Zero()) => Zero()
case _ => n
@main def main(): Unit =
println(mod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
println(foo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected
println(inlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
println(inlineFoo(Succ(Succ(Succ(Zero()))))) // prints Succ(Succ(Succ(Zero()))); unexpected
println(transparentInlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
println(transparentInlineFoo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected
println(dependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // runtime error; unexpected
// println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected
// println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected
Output
Succ(Zero())
Zero()
Succ(Zero())
Succ(Succ(Succ(Zero())))
Succ(Zero())
Zero()
[error] java.lang.ClassCastException: Succ cannot be cast to Zero
[error] at main$package$.dependentlyTypedMod2(main.scala:27)
[error] at main$package$.main(main.scala:59)
[error] at main.main(main.scala:52)
[error] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] at java.lang.reflect.Method.invoke(Method.java:498)
Expectation
inlineFoo(Succ(Succ(Succ(Zero()))))
should not returnSucc(Succ(Succ(Zero())))
;inline
should not change function output.- Compilation should not be negatively affected by more refined types.
- No runtime exception