Skip to content

Commit 53a2dc5

Browse files
authored
Merge pull request #11410 from dotty-staging/fix-11344
Fix trait parameter passing algorithm
2 parents 7f48c4c + fc4fd2d commit 53a2dc5

File tree

5 files changed

+17
-15
lines changed

5 files changed

+17
-15
lines changed

compiler/src/dotty/tools/dotc/transform/Mixin.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
258258
&& !wasOneOf(getter, Deferred)
259259
&& !getter.isConstExprFinalVal
260260
yield
261-
if (isCurrent(getter) || getter.name.is(ExpandedName)) {
261+
if (isInImplementingClass(getter) || getter.name.is(ExpandedName)) {
262262
val rhs =
263263
if (wasOneOf(getter, ParamAccessor))
264264
nextArgument()
@@ -271,6 +271,9 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
271271
// transformFollowing call is needed to make memoize & lazy vals run
272272
transformFollowing(DefDef(mkForwarderSym(getter.asTerm), rhs))
273273
}
274+
else if wasOneOf(getter, ParamAccessor) then
275+
// mixin parameter field is defined by an override; evaluate the argument and throw it away
276+
nextArgument()
274277
else EmptyTree
275278
}
276279

compiler/src/dotty/tools/dotc/transform/MixinOps.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(using Context) {
4242
/** Is `sym` a member of implementing class `cls`?
4343
* The test is performed at phase `thisPhase`.
4444
*/
45-
def isCurrent(sym: Symbol): Boolean =
45+
def isInImplementingClass(sym: Symbol): Boolean =
4646
atPhase(thisPhase) {
4747
cls.info.nonPrivateMember(sym.name).hasAltWith(_.symbol == sym)
4848
}
@@ -71,7 +71,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(using Context) {
7171
meth.is(Method, butNot = PrivateOrAccessorOrDeferred) &&
7272
(ctx.settings.mixinForwarderChoices.isTruthy || meth.owner.is(Scala2x) || needsDisambiguation || hasNonInterfaceDefinition ||
7373
generateJUnitForwarder || generateSerializationForwarder) &&
74-
isCurrent(meth)
74+
isInImplementingClass(meth)
7575
}
7676

7777
final val PrivateOrAccessor: FlagSet = Private | Accessor

docs/docs/reference/other-new-features/trait-parameters.md

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,12 @@ class D extends C, Greeting("Bill") // error: parameter passed twice
2626
Should this print "Bob" or "Bill"? In fact this program is illegal,
2727
because it violates the second rule of the following for trait parameters:
2828

29-
1. If a class `C` directly extends a parameterized trait `T`, and its superclass does not, `C` _must_ pass arguments to `T`.
29+
1. If a class `C` extends a parameterized trait `T`, and its superclass does not, `C` _must_ pass arguments to `T`.
3030

31-
2. If a class `C` directly or indirectly extends a parameterized trait `T`, and its superclass does as well, `C` _must not_ pass arguments to `T`.
31+
2. If a class `C` extends a parameterized trait `T`, and its superclass does as well, `C` _must not_ pass arguments to `T`.
3232

3333
3. Traits must never pass arguments to parent traits.
3434

35-
4. If a class `C` extends a parameterized trait `T` only indirectly, and its superclass does not extend `T`, then all parameters of `T` must be defined via overrides.
36-
3735
Here's a trait extending the parameterized trait `Greeting`.
3836

3937
```scala
@@ -53,13 +51,6 @@ The correct way to write `E` is to extend both `Greeting` and
5351
```scala
5452
class E extends Greeting("Bob"), FormalGreeting
5553
```
56-
Alternatively, a class could also define the `name` parameter of `Greeting` using
57-
an override, using rule (4) above:
58-
59-
```scala
60-
class E2 extends FormalGreeting:
61-
override val name: String = "Bob"
62-
```
6354

6455
## Reference
6556

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
trait Pet(val name: String)
22
trait FeatheredPet extends Pet
33

4-
class Bird(override val name: String) extends FeatheredPet:
4+
class Bird(override val name: String) extends FeatheredPet: // error
55
override def toString = s"bird name: $name"

tests/run/i11344.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
trait Pet(val name: String, rest: Int):
2+
def f(suffix: String) = s"$name$suffix$rest"
3+
4+
class Birdie(override val name: String) extends Pet("huh", 1)
5+
6+
@main def Test =
7+
assert(Birdie("Polly").f("more") == "Pollymore1")
8+

0 commit comments

Comments
 (0)