question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Opaque type weirdness: (self$proxy1 : Any) Required: BigDecimalNewType_this.Type

See original GitHub issue

Opaque types possessing black magic.

It appears that adding 3 or more opaque type numeric causes the code to fail to compile. However here, uncommenting in Line 15 makes the code compile, which is odd, as it is seemingly a random opaque type declaration. Adding 2 Amounts is fine, the issue appears when adding 3 Amounts

Compiler version

3.1.1

Minimized code

trait Newtype[Src]:
  opaque type Type = Src

transparent trait BigDecimalNewType extends Newtype[BigDecimal]:
  override opaque type Type = BigDecimal

  inline def apply(inline dec: BigDecimal): Type = dec

  extension (self: Type)
    inline def value: BigDecimal = self
    inline def +(inline y: Type): Type = self.value + y.value

type Amount = Amount.Type
object Amount extends BigDecimalNewType {
  // opaque type Blahblahblah = BigDecimal
}

case class Fees(
  exchange: Amount,
  slippage: Amount,
  bribe: Amount
):
  def calculateTotalFees: Amount = exchange + slippage + bribe

@main def main(): Unit = 
  val fees: Fees = Fees(Amount(1),Amount(2), Amount(2))
  val totalFees: Amount = fees.calculateTotalFees

  println(s"totalFees: ${totalFees}")

Scastie link: https://scastie.scala-lang.org/MLbciD4bQtysh7mVlYy1ig

Output

Found:    (self$proxy1 : Any)
Required: BigDecimalNewType_this.Type

Expectation

Compile regardless of Line 15 in the code.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
oderskycommented, Mar 11, 2022

Reduced further to:

trait BigDecimalNewType:
  opaque type Type = BigDecimal
  def apply(value: BigDecimal): Type = value
  def value(self: Type): BigDecimal = self
 inline def plus(self: Type, y: Type): Type = apply(value(self) + value(y))

object Amount extends BigDecimalNewType {
  val x = Amount(0)
  val y0 = plus(x, x)
  val y = plus(y0, plus(x, x))
}

Problem goes away if inline is dropped. Problem also exists if inline is replaced with transparent inline. Problem also goes away if BigDecimalNewType is changed to an object, as in:

object BigDecimalNewType:
  opaque type Type = BigDecimal
  def apply(value: BigDecimal): Type = value
  def value(self: Type): BigDecimal = self
  transparent inline def plus(self: Type, y: Type): Type = apply(value(self) + value(y))

object Amount {
  import BigDecimalNewType.*
  val x = BigDecimalNewType(0)
  val y0 = plus(x, x)
  val y = plus(y0, plus(x, x))
}
1reaction
prolativcommented, Mar 10, 2022

I’m wondering if what you’re trying to do here should be possible at all https://github.com/lampepfl/dotty/issues/14659

Read more comments on GitHub >

github_iconTop Results From Across the Web

Some keyword in Swift: Opaque types explained with code ...
The some keyword in Swift allows you to define opaque parameter and return types. Expose only minimum APIs without losing performance.
Read more >
The Problem That Opaque Types Solve
An opaque type lets the function implementation pick the type for the value it returns in a way that's abstracted away from the...
Read more >
Opaque Type Aliases
Opaque type aliases are type aliases that do not allow access to their underlying type outside of the file in which they are...
Read more >
What defines an opaque type in C, and when are they ...
It is the most generally used for library purpose. The main principe behind Opaque type in c is to use data though its...
Read more >
til / opaque types
This works by telling TypeScript that there exists a variable called $uuid that is a unique symbol (the result of calling Symbol() )...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found