Skip to content

Commit 393c620

Browse files
committed
Refine way eqInstance is generated
It turns out that simply renaming type parameters is not enough to generate a correct eqInstance definition such as def eqInstance[S$1, S$1, S$2, T$2]eqInstance ... This failed when a parameter `S` or `T` contained the other in its bound. i2663.scala now contains a test for that. The infix involes keeping track of renaming suffices when inter-parameter references are resolved.
1 parent aa2da96 commit 393c620

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

+22-13
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@ object desugar {
4040
def derivedType(sym: Symbol)(implicit ctx: Context) = sym.typeRef
4141
}
4242

43-
class DerivedFromParamTree extends DerivedTypeTree {
43+
/** A type tree that computes its type from an existing parameter.
44+
* @param suffix String difference between existing parameter (call it `P`) and parameter owning the
45+
* DerivedTypeTree (call it `O`). We have: `O.name == P.name + suffix`.
46+
*/
47+
class DerivedFromParamTree(suffix: String) extends DerivedTypeTree {
4448

4549
/** Make sure that for all enclosing module classes their companion lasses
4650
* are completed. Reason: We need the constructor of such companion classes to
@@ -58,24 +62,28 @@ object desugar {
5862

5963
/** Return info of original symbol, where all references to siblings of the
6064
* original symbol (i.e. sibling and original symbol have the same owner)
61-
* are rewired to same-named parameters or accessors in the scope enclosing
65+
* are rewired to like-named* parameters or accessors in the scope enclosing
6266
* the current scope. The current scope is the scope owned by the defined symbol
6367
* itself, that's why we have to look one scope further out. If the resulting
6468
* type is an alias type, dealias it. This is necessary because the
6569
* accessor of a type parameter is a private type alias that cannot be accessed
6670
* from subclasses.
71+
*
72+
* (*) like-named means:
73+
*
74+
* parameter name == reference name ++ suffix
6775
*/
6876
def derivedType(sym: Symbol)(implicit ctx: Context) = {
6977
val relocate = new TypeMap {
7078
val originalOwner = sym.owner
7179
def apply(tp: Type) = tp match {
7280
case tp: NamedType if tp.symbol.exists && (tp.symbol.owner eq originalOwner) =>
7381
val defctx = ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next()
74-
var local = defctx.denotNamed(tp.name).suchThat(_.isParamOrAccessor).symbol
82+
var local = defctx.denotNamed(tp.name ++ suffix).suchThat(_.isParamOrAccessor).symbol
7583
if (local.exists) (defctx.owner.thisType select local).dealias
7684
else {
7785
def msg =
78-
s"no matching symbol for ${tp.symbol.showLocated} in ${defctx.owner} / ${defctx.effectiveScope}"
86+
s"no matching symbol for ${tp.symbol.showLocated} in ${defctx.owner} / ${defctx.effectiveScope.toList}"
7987
if (ctx.reporter.errorsReported) ErrorType(msg)
8088
else throw new java.lang.Error(msg)
8189
}
@@ -88,18 +96,20 @@ object desugar {
8896
}
8997

9098
/** A type definition copied from `tdef` with a rhs typetree derived from it */
91-
def derivedTypeParam(tdef: TypeDef) =
99+
def derivedTypeParam(tdef: TypeDef, suffix: String = ""): TypeDef =
92100
cpy.TypeDef(tdef)(
93-
rhs = new DerivedFromParamTree() withPos tdef.rhs.pos watching tdef)
101+
name = tdef.name ++ suffix,
102+
rhs = new DerivedFromParamTree(suffix).withPos(tdef.rhs.pos).watching(tdef)
103+
)
94104

95105
/** A derived type definition watching `sym` */
96106
def derivedTypeParam(sym: TypeSymbol)(implicit ctx: Context): TypeDef =
97-
TypeDef(sym.name, new DerivedFromParamTree().watching(sym)).withFlags(TypeParam)
107+
TypeDef(sym.name, new DerivedFromParamTree("").watching(sym)).withFlags(TypeParam)
98108

99109
/** A value definition copied from `vdef` with a tpt typetree derived from it */
100110
def derivedTermParam(vdef: ValDef) =
101111
cpy.ValDef(vdef)(
102-
tpt = new DerivedFromParamTree() withPos vdef.tpt.pos watching vdef)
112+
tpt = new DerivedFromParamTree("") withPos vdef.tpt.pos watching vdef)
103113

104114
// ----- Desugar methods -------------------------------------------------
105115

@@ -321,8 +331,8 @@ object desugar {
321331
}
322332
def anyRef = ref(defn.AnyRefAlias.typeRef)
323333

324-
val derivedTparams = constrTparams map derivedTypeParam
325-
val derivedVparamss = constrVparamss nestedMap derivedTermParam
334+
val derivedTparams = constrTparams.map(derivedTypeParam(_))
335+
val derivedVparamss = constrVparamss.nestedMap(derivedTermParam(_))
326336
val arity = constrVparamss.head.length
327337

328338
val classTycon: Tree = new TypeRefTree // watching is set at end of method
@@ -423,9 +433,8 @@ object desugar {
423433
// ev1: Eq[T1$1, T1$2], ..., evn: Eq[Tn$1, Tn$2]])
424434
// : Eq[C[T1$1, ..., Tn$1], C[T1$2, ..., Tn$2]] = Eq
425435
def eqInstance = {
426-
def append(tdef: TypeDef, str: String) = cpy.TypeDef(tdef)(name = tdef.name ++ str)
427-
val leftParams = derivedTparams.map(append(_, "$1"))
428-
val rightParams = derivedTparams.map(append(_, "$2"))
436+
val leftParams = constrTparams.map(derivedTypeParam(_, "$1"))
437+
val rightParams = constrTparams.map(derivedTypeParam(_, "$2"))
429438
val subInstances = (leftParams, rightParams).zipped.map((param1, param2) =>
430439
appliedRef(ref(defn.EqType), List(param1, param2)))
431440
DefDef(

tests/pos/i2663.scala

+14
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,18 @@ object Test {
1313
val baz: Foo[String] & Tr = Baz("")
1414
}
1515

16+
enum Foo2[S <: T, T](x1: S, x2: T) {
17+
case Bar[T](y: T) extends Foo2(y, y)
18+
case Bas[T](y: Int) extends Foo2(y, y)
19+
case Bam[T](y: String) extends Foo2(y, y) with Tr
20+
case Baz[S, T](y: String) extends Foo2(y, y) with Tr
21+
}
22+
object Test2 {
23+
import Foo2._
24+
val bar: Foo2[Boolean, Boolean] = Bar(true)
25+
val bas: Foo2[Int, Int] = Bas(1)
26+
val bam: Foo2[String, String] & Tr = Bam("")
27+
val baz: Foo2[String, String] & Tr = Baz("")
28+
}
29+
1630

0 commit comments

Comments
 (0)