Skip to content

Commit

Permalink
Don't use member type name for deferred givens
Browse files Browse the repository at this point in the history
When expanding a context bound of a member type, don't use the member name
as the name of the generated deferred given. The same member type might have
different single context bounds in different traits. A class inheriting
several of these traits would then get double definitions in its given clauses.

Partial revert of "Changes to default names for context bound witnesses"
  • Loading branch information
odersky committed Feb 29, 2024
1 parent 3857796 commit ad1ebad
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 22 deletions.
8 changes: 6 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,16 @@ object desugar {
flags: FlagSet,
freshName: => TermName)(using Context): Tree = rhs match
case ContextBounds(tbounds, cxbounds) =>
val isMember = flags.isAllOf(DeferredGivenFlags)
for bound <- cxbounds do
val evidenceName = bound match
case ContextBoundTypeTree(_, _, ownName) if !ownName.isEmpty =>
ownName
case _ if Feature.enabled(Feature.modularity) && cxbounds.tail.isEmpty =>
case _ if !isMember && cxbounds.tail.isEmpty && Feature.enabled(Feature.modularity) =>
tname.toTermName
case _ =>
freshName
if isMember then inventGivenOrExtensionName(bound)
else freshName
val evidenceParam = ValDef(evidenceName, bound, EmptyTree).withFlags(flags)
evidenceParam.pushAttachment(ContextBoundParam, ())
evidenceBuf += evidenceParam
Expand Down Expand Up @@ -1202,6 +1204,8 @@ object desugar {
case tree: TypeDef => tree.name.toString
case tree: AppliedTypeTree if followArgs && tree.args.nonEmpty =>
s"${apply(x, tree.tpt)}_${extractArgs(tree.args)}"
case ContextBoundTypeTree(tycon, paramName, _) =>
s"${apply(x, tycon)}_$paramName"
case InfixOp(left, op, right) =>
if followArgs then s"${op.name}_${extractArgs(List(left, right))}"
else op.name.toString
Expand Down
11 changes: 2 additions & 9 deletions docs/_docs/reference/experimental/typeclasses-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,22 +185,15 @@ The compiler expands this to the following implementation:
```scala
trait Sorted:
type Element
given Ord[Element] as Element = compiletime.deferred
given Ord[Element] = compiletime.deferred

class SortedSet[A](using A: Ord[A]) extends Sorted:
type Element = A
override given Ord[Element] as Element = A // i.e. the A defined by the using clause
override given Ord[Element] = A // i.e. the A defined by the using clause
```

The using clause in class `SortedSet` provides an implementation for the deferred given in trait `Sorted`.

If there is a single context bound, as in
```scala
type T : C
```
the synthesized deferred given will get the (term-)name of the constrained type `T`. If there are multiple bounds,
the standard convention for naming anonymous givens applies.

**Benefits:**

- Better orthogonality, type parameters and abstract type members now accept the same kinds of bounds.
Expand Down
11 changes: 2 additions & 9 deletions docs/_docs/reference/experimental/typeclasses.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,22 +306,15 @@ The compiler expands this to the following implementation:
```scala
trait Sorted:
type Element
given Ord[Element] as Element = compiletime.deferred
given Ord[Element] = compiletime.deferred

class SortedSet[A](using A: Ord[A]) extends Sorted:
type Element = A
override given Ord[Element] as Element = A // i.e. the A defined by the using clause
override given Ord[Element] = A // i.e. the A defined by the using clause
```

The using clause in class `SortedSet` provides an implementation for the deferred given in trait `Sorted`.

If there is a single context bound, as in
```scala
type T : C
```
the synthesized deferred given will get the (term-)name of the constrained type `T`. If there are multiple bounds,
the standard convention for naming anonymous givens applies.

**Benefits:**

- Better orthogonality, type parameters and abstract type members now accept the same kinds of bounds.
Expand Down
3 changes: 1 addition & 2 deletions tests/pos/deferred-givens.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ trait A:

class AC extends A:
type Elem = Double
override given Ord[Elem] as Elem = ???
override given Ord[Elem] = ???

class AD extends A:
type Elem = Double
Expand All @@ -34,4 +34,3 @@ class E(using x: Ord[String]) extends B:

class F[X: Ord] extends B:
type Elem = X

0 comments on commit ad1ebad

Please sign in to comment.