Skip to content

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

Closed
alvinj opened this issue Jan 25, 2021 · 4 comments · Fixed by #11338
Closed

Indirectly extending a trait with parameters works (unexpectedly) #11214

alvinj opened this issue Jan 25, 2021 · 4 comments · Fixed by #11338

Comments

@alvinj
Copy link

alvinj commented Jan 25, 2021

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:

trait Pet(val name: String)
trait FeatheredPet extends Pet

// the docs say to do this
class Bird(override val name: String) extends Pet(name), FeatheredPet:
   override def toString = s"bird name: $name"

Then out of curiosity I also tried this, and saw that it works as well:

// this also works
class Bird(override val name: String) extends FeatheredPet:
   override def toString = s"bird name: $name"

On Gitter, @smarter noted that this second behavior might be an issue, so I’m reporting it here.

@smarter
Copy link
Member

smarter commented Jan 25, 2021

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.

@som-snytt
Copy link
Contributor

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

@som-snytt
Copy link
Contributor

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.

@som-snytt
Copy link
Contributor

Actually #9460

odersky added a commit to dotty-staging/dotty that referenced this issue Feb 7, 2021
This legalizes the behavior exhibited in scala#11214.

Fixes scala#11214
@odersky odersky self-assigned this Feb 8, 2021
odersky added a commit to dotty-staging/dotty that referenced this issue Feb 13, 2021
As part of the fix, we now also detect missing trait constructors.

Fixes scala#11214
Fixes scala#11344
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants