Skip to content
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

abstract var can only be overridden when the override modifier is not used #21149

Closed
symingz opened this issue Jul 10, 2024 · 10 comments
Closed

Comments

@symingz
Copy link

symingz commented Jul 10, 2024

Compiler version

3.4.2

Minimized code

File1:

trait C:
  var x: Int

class D extends C:
  var x: Int = 10

File2:

trait C:
  var x: Int

class D extends C:
  override var x: Int = 10

Output

File1 compiles, File2 fails with

-- [E164] Declaration Error: Main.scala:5:15 -----------------------------------
5 |  override var x: Int = 10
  |               ^
  |               error overriding variable x in trait C of type Int;
  |                 variable x of type Int cannot override a mutable variable
1 error found

Expectation

Both File1 and File2 should compile.

@symingz symingz added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Jul 10, 2024
@Gedochao Gedochao added area:overloading stat:wontfix and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Jul 10, 2024
@Gedochao
Copy link
Contributor

Gedochao commented Jul 12, 2024

Hey, so this is actually the intended behaviour, we do not allow to override vars.
There used to be a flag for allowing this in Scala 2 (-Yoverride-vars), but not in Scala 3.

What we maybe could consider is adjusting the spec, since we actually don't mention it there, I think. (cc @sjrd)
https://www.scala-lang.org/files/archive/spec/3.4/05-classes-and-objects.html#overriding

Either way, closing this.

@Gedochao Gedochao closed this as not planned Won't fix, can't repro, duplicate, stale Jul 12, 2024
@symingz
Copy link
Author

symingz commented Jul 12, 2024

I see. In this case should File 1 (without the override modifier) be rejected by the compiler as well? Right now the compiler accepts it.

@bishabosha
Copy link
Member

bishabosha commented Jul 12, 2024

overriding is not the same thing as implementing, overriding changes signature, implementing is fine because the types stay the same

@symingz
Copy link
Author

symingz commented Jul 12, 2024

I find this confusing. For val and def, one can simply add the override modifier without thinking about if it is implement or override. But then var requires such fine distinction. Furthermore, I have read in multiple places (such as Programming in Scala, 5th Ed) that var is equivalent to two methods (one getter and one setter). From this one would reasonably assume that var can be overridden, but apparently that's not the case. These all seem unnecessary complications. I would rather the language simply ban abstract var, and specify that all var are implicitly final.

@bishabosha
Copy link
Member

you actually can not override a function to have a more precise argument, meaning you can not override a setter, so it makes no sense to override a var, which would override the setter:

scala> trait Foo:
     |   def setFoo(newFoo: Any): Unit
     | trait Bar extends Foo:
     |   override def setFoo(newFoo: String): Unit
     |
-- [E038] Declaration Error: ---------------------------------------------------
4 |  override def setFoo(newFoo: String): Unit
  |               ^
  |   method setFoo has a different signature than the overridden declaration
  |
  | longer explanation available when compiling with `-explain`
1 error found
@symingz
Copy link
Author

symingz commented Jul 12, 2024

I don't think that applies to my examples, in

trait C:
  var x: Int

class D extends C:
  override var x: Int = 10

The type for x is always Int.

@symingz
Copy link
Author

symingz commented Jul 12, 2024

I am no longer convinced that this is the expected behavior. There are two open issues (#18692, #13019) raising similar questions, and in neither of them was there consensus that this is the expected behavior. If anything, the consensus is that this is an issue that needs to be fixed.

@bishabosha
Copy link
Member

ok, comparing to scala 2 behavior it would seem attempt the override as long as the type does not change:

scala> trait Foo {
     |   var x: Any}
trait Foo

scala> class Bar extends Foo {
     |   override var x: Any = 23
     | }
class Bar

scala> class Bar extends Foo {
     |   override var x = 23
     | }
             ^
       error: class Bar needs to be abstract.
       Missing implementation for member of trait Foo:
         def x_=(x$1: Any): Unit = ??? // an abstract var requires a setter in addition to the getter
         override var x = 23
                      ^
On line 2: error: variable x overrides nothing.
       Note: the super classes of class Bar contain the following, non final members named x_$eq:
       def x_=(x$1: Any): Unit
@bishabosha bishabosha reopened this Jul 14, 2024
@bishabosha
Copy link
Member

saying this is duplicicate of #18692 because the error message is the same

@bishabosha bishabosha closed this as not planned Won't fix, can't repro, duplicate, stale Jul 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
3 participants