Skip to content

Potential Issue with Opaque Types #5455

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

Closed
adamgfraser opened this issue Nov 16, 2018 · 1 comment
Closed

Potential Issue with Opaque Types #5455

adamgfraser opened this issue Nov 16, 2018 · 1 comment
Assignees

Comments

@adamgfraser
Copy link
Contributor

I was playing a bit with opaque types and encountered what at least to me seems like some strange behavior. If I define an opaque type Nat and then want to refer to that type in a function definition at use site I need to use Nat.Nat. Nat seems to only refer to the companion object versus the opaque type itself. This is inconsistent with the treatment of other types. For example, if I defined Nat as a case class with a companion object then I could use Nat to refer to the type itself in a function definition. This seems less than ideal since I think one of the goals of opaque types was for them to be treated like any other type at use site. Is this intended behavior or a bug? Example below:

object Library {

  opaque type Nat = Int

  object Nat {
    def apply(n: Int): Nat = {
      require(n >= 0)
      n
    }
    def times(x: Nat, y: Nat): Nat = x * y
    def toInt(n: Nat): Int = n

    implicit class NatOps(val self: Nat) extends AnyVal {
      def *(other: Nat): Nat = self * other
      def toInt: Int = self
    }
  }
}

object User extends App {
  import Library._

  val x = Nat(3)
  val y = Nat(4)

  val a = x * y               // inferred type is Library.Nat.Nat
  val b = double1(x)          // inferred type is Library.Nat
  val c = double2(x)          // inferred type is Library.Nat.Nat

  assert(a.toInt == 12)       // works
  //assert(b.toInt == 6)      // error: toInt is not a member of Library.Nat
  assert(c.toInt == 6)        // works

  //def double0(n: Nat): Nat = n * Nat(2)       // error

  def double1(n: Nat.Nat): Nat = n * Nat(2)     // output type is incorrect

  def double2(n: Nat.Nat): Nat.Nat =n * Nat(2)  // works
}
@odersky odersky self-assigned this Nov 20, 2018
@odersky
Copy link
Contributor

odersky commented Nov 20, 2018

Thanks for the report! I could find a fix, and also one for #5481.

liufengyun added a commit that referenced this issue Nov 21, 2018
Fix #5455: Fix computation of companion object of opaque type
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants