Why inline methods of opaque types can be called from concrete classes but not from traits?
The following code
opaque type ConstrainedBigDecimal = BigDecimal
extension (n: ConstrainedBigDecimal)
inline def isWhole = n.isWhole
opaque type PositiveBigDecimal <: ConstrainedBigDecimal = BigDecimal
opaque type NegativeBigDecimal <: ConstrainedBigDecimal = BigDecimal
sealed trait Quantity:
protected type QuantityType <: ConstrainedBigDecimal
def quantity: QuantityType
def formatQuantity: String =
if quantity.isWhole then quantity.toString() else f"$quantity%.2f"
produces
-- Error: test.scala:15:20 --------------------------------------------------------------------------------------------------------------------------
15 | if quantity.isWhole then quantity.toString() else f"$quantity%.2f"
| ^^^^^^^^^^^^^^^^
| isWhole cannot be accessed as a member of (n$proxy1 : Quantity.this.QuantityType) from trait Quantity.
|-------------------------------------------------------------------------------------------------------------------------------------------------
|Inline stack trace
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|This location contains code that was inlined from test.scala:4
4 | inline def isWhole = n.isWhole
| ^^^^^^^^^
-------------------------------------------------------------------------------------------------------------------------------------------------
However, a concrete class with an identical implementation
case class PositiveQuantity(
quantity: PositiveBigDecimal
):
def formatQuantity: String =
if quantity.isWhole then quantity.toString() else f"$quantity%.2f"
compiles just fine.