-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Indirectly extending a trait with parameters works (unexpectedly) #11214
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
Comments
I put the "needs spec" label but I think the spec is fine (SIP-25 says "If a class C implements a parameterized trait T, and its superclass does not, then T must appear as a parent trait of C with arguments.") and it's the implementation which is missing a check, /cc @odersky. |
TIL I don't know how trait parameters are supposed to work. [success] Total time: 170 s (02:50), completed Jan 25, 2021, 6:39:32 PM
Starting scala3 REPL...
scala> trait Pet(val name: String, rest: String):
| def f(suffix: String) = s"$name$suffix$rest"
|
// defined trait Pet
scala> class Birdie(override val name: String) extends Pet("huh", "more")
// defined class Birdie
scala> Birdie("Polly").f("Cracker")
val res0: String = PollyCrackerhuh // expected s/huh/more Without the trait val and override, it's correctly scala> Birdie("Polly").f("Cracker")
val res1: String = huhCrackermore The unspecified behavior of not requiring args when val params are overridden (and params aren't used in initialization) seems OK to me: scala> trait Pet(val name: String, val rest: String):
| def f(suffix: String) = s"$name$suffix$rest"
|
// defined trait Pet
scala> trait X extends Pet
// defined trait X
scala> class Birdie(override val name: String) extends X
1 |class Birdie(override val name: String) extends X
| ^
| parameterized trait Pet is indirectly implemented,
| needs to be implemented directly so that arguments can be passed
scala> class Birdie(override val name: String, override val rest: String) extends X
// defined class Birdie
scala> Birdie("Polly", "Parrot").f("Cracker")
val res2: String = PollyCrackerParrot |
I would naively expect the same behavior: scala> class C(val s: String) { def f = s * 2 ; println(s) }
// defined class C
scala> class D(override val s: String) extends C("bye")
// defined class D
scala> D("hello").f
bye
val res10: String = hellohello
scala> trait C(val s: String) { def f = s * 2 ; println(s) }
// defined trait C
scala> class D(override val s: String) extends C("bye")
// defined class D
scala> D("hello").f
hello
val res11: String = hellohello I have to re-read what the docs say about initialization. I think the original "One-Question FAQ" from Scala 2, which had one question about initialization, will still have only question, but now it will have multiple answers. |
Actually #9460 |
This legalizes the behavior exhibited in scala#11214. Fixes scala#11214
As part of the fix, we now also detect missing trait constructors. Fixes scala#11214 Fixes scala#11344
Compiler version
Scala 3.0-M3
Minimized code
In a Gitter discussion that starts here, I noted that in following this documentation page I created this example, which works as desired:
Then out of curiosity I also tried this, and saw that it works as well:
On Gitter, @smarter noted that this second behavior might be an issue, so I’m reporting it here.
The text was updated successfully, but these errors were encountered: