Skip to content

Commit

Permalink
fix: Only implement a deferred given in a class if its parent won't i…
Browse files Browse the repository at this point in the history
…mplement it (#21206)

It should be possible to extend a class that inherits a deferred given,
so a generated given implementation should not be final.

closes #21189
  • Loading branch information
odersky authored Aug 1, 2024
2 parents e261fa2 + 532c287 commit 6c4eace
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 1 deletion.
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3044,7 +3044,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
body

/** Implement givens that were declared with a `deferred` rhs.
* The a given value matching the declared type is searched in a
* The given value matching the declared type is searched in a
* context directly enclosing the current class, in which all given
* parameters of the current class are also defined.
*/
Expand All @@ -3061,6 +3061,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
false
else true

def willBeimplementedInParentClass(m: TermRef) =
val superCls = cls.superClass
superCls.exists && superCls.asClass.baseClasses.contains(m.symbol.owner)

def givenImpl(mbr: TermRef): ValDef =
val dcl = mbr.symbol
val target = dcl.info.asSeenFrom(cls.thisType, dcl.owner)
Expand Down Expand Up @@ -3090,6 +3094,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
cls.thisType.implicitMembers
//.showing(i"impl def givens for $cls/$result")
.filter(_.symbol.isAllOf(DeferredGivenFlags, butNot = Param))
.filter(!willBeimplementedInParentClass(_)) // only implement the given in the topmost class
//.showing(i"impl def filtered givens for $cls/$result")
.filter(isGivenValue)
.map(givenImpl)
Expand Down
12 changes: 12 additions & 0 deletions tests/pos/i21189-alt.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//> using options -source:future -language:experimental.modularity

class MySortedSet[T : Ord] extends SortedSet[T]

trait Ord[T]

trait Sorted[T] extends ParentOfSorted[T]

trait ParentOfSorted[T]:
given Ord[T] as ord = compiletime.deferred

class SortedSet[T : Ord] extends Sorted[T]
10 changes: 10 additions & 0 deletions tests/pos/i21189.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//> using options -source:future -language:experimental.modularity

class MySortedSet[T : Ord] extends SortedSet[T]

trait Ord[T]

trait Sorted[T]:
given Ord[T] as ord = compiletime.deferred

class SortedSet[T : Ord] extends Sorted[T]

0 comments on commit 6c4eace

Please sign in to comment.