scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.87k stars 1.06k forks source link

Infer refinement types for val members of traits and abstract classes #3964

Open liufengyun opened 6 years ago

liufengyun commented 6 years ago

Currently abstract member of trait or class will get a refinement type:

trait Animal
class Dog extends Animal
class Cat extends Animal

abstract class Bar { val x: Animal }
val bar: Bar { val x: Cat } = new Bar { val x = new Cat }

trait Foo { val x: Animal }
val foo: Foo { val x: Cat } = new Foo { val x = new Cat }

As argued by @julienrf , there should be a symmetry if the members are in the constructor positions:

abstract class Bar(val x: Animal)
val bar: Bar { val x: Cat } = new Bar(new Cat)

trait Foo(val x: Animal)
val foo: Foo { val x: Cat } = new Foo(new Cat)

Hopefully, this feature should also make the following work:

trait Vec(val size: Int)
class Vec8 extends Vec(8)

abstract class Lst(val size: Int)
class Lst8 extends Lst(8)

class Test {
  val v8a: Vec { val size: 8 } = new Vec8        // ok
  val v8b: Vec { val size: 8 } = new Vec(8)      // ok

  val l8a: Lst { val size: 8 } = new Lst8        // ok
  val l8b: Lst { val size: 8 } = new Lst(8)      // ok
}

Related #3920 .

Blaisorblade commented 6 years ago

Wait, so you want Vec8 to not have a refinement? Can I add one by hand if I want to? How? This syntax looks odd:

class Vec8 extends Vec(8) { val size: 8 }

Also, it looks like I can write new Vec(8) but I can’t abstract it as a class... it’s good I can abstract it as a method, but how do you explain why one works and the other doesn’t to a user?

liufengyun commented 6 years ago

@Blaisorblade Thanks for pointing out. That's a miscommunication, I think both should work.