Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/transform/Mixin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
&& !wasOneOf(getter, Deferred)
&& !getter.isConstExprFinalVal
yield
if (isCurrent(getter) || getter.name.is(ExpandedName)) {
if (isInImplementingClass(getter) || getter.name.is(ExpandedName)) {
val rhs =
if (wasOneOf(getter, ParamAccessor))
nextArgument()
Expand All @@ -271,6 +271,9 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
// transformFollowing call is needed to make memoize & lazy vals run
transformFollowing(DefDef(mkForwarderSym(getter.asTerm), rhs))
}
else if wasOneOf(getter, ParamAccessor) then
// mixin parameter field is defined by an override; evaluate the argument and throw it away
nextArgument()
else EmptyTree
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/MixinOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(using Context) {
/** Is `sym` a member of implementing class `cls`?
* The test is performed at phase `thisPhase`.
*/
def isCurrent(sym: Symbol): Boolean =
def isInImplementingClass(sym: Symbol): Boolean =
atPhase(thisPhase) {
cls.info.nonPrivateMember(sym.name).hasAltWith(_.symbol == sym)
}
Expand Down Expand Up @@ -71,7 +71,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(using Context) {
meth.is(Method, butNot = PrivateOrAccessorOrDeferred) &&
(ctx.settings.mixinForwarderChoices.isTruthy || meth.owner.is(Scala2x) || needsDisambiguation || hasNonInterfaceDefinition ||
generateJUnitForwarder || generateSerializationForwarder) &&
isCurrent(meth)
isInImplementingClass(meth)
}

final val PrivateOrAccessor: FlagSet = Private | Accessor
Expand Down
13 changes: 2 additions & 11 deletions docs/docs/reference/other-new-features/trait-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ class D extends C, Greeting("Bill") // error: parameter passed twice
Should this print "Bob" or "Bill"? In fact this program is illegal,
because it violates the second rule of the following for trait parameters:

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

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`.
2. If a class `C` extends a parameterized trait `T`, and its superclass does as well, `C` _must not_ pass arguments to `T`.

3. Traits must never pass arguments to parent traits.

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.

Here's a trait extending the parameterized trait `Greeting`.

```scala
Expand All @@ -53,13 +51,6 @@ The correct way to write `E` is to extend both `Greeting` and
```scala
class E extends Greeting("Bob"), FormalGreeting
```
Alternatively, a class could also define the `name` parameter of `Greeting` using
an override, using rule (4) above:

```scala
class E2 extends FormalGreeting:
override val name: String = "Bob"
```

## Reference

Expand Down
2 changes: 1 addition & 1 deletion tests/pos/i11214.scala → tests/neg/i11214.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
trait Pet(val name: String)
trait FeatheredPet extends Pet

class Bird(override val name: String) extends FeatheredPet:
class Bird(override val name: String) extends FeatheredPet: // error
override def toString = s"bird name: $name"
8 changes: 8 additions & 0 deletions tests/pos/i11344.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
trait Pet(val name: String, rest: Int):
def f(suffix: String) = s"$name$suffix$rest"

class Birdie(override val name: String) extends Pet("huh", 1)

@main def Test =
assert(Birdie("Polly").f("more") == "Pollymore1")