Skip to content

Commit 4daf543

Browse files
authored
Merge pull request #1768 from dotty-staging/fix-#1765
Fix #1765: Context bounds and denotation handling
2 parents 4830901 + a7003bb commit 4daf543

File tree

5 files changed

+56
-12
lines changed

5 files changed

+56
-12
lines changed

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,16 +142,21 @@ object desugar {
142142
val DefDef(name, tparams, vparamss, tpt, rhs) = meth
143143
val mods = meth.mods
144144
val epbuf = new ListBuffer[ValDef]
145-
val tparams1 = tparams mapConserve {
146-
case tparam @ TypeDef(_, ContextBounds(tbounds, cxbounds)) =>
145+
def desugarContextBounds(rhs: Tree): Tree = rhs match {
146+
case ContextBounds(tbounds, cxbounds) =>
147147
for (cxbound <- cxbounds) {
148148
val paramFlags: FlagSet = if (isPrimaryConstructor) PrivateLocalParamAccessor else Param
149149
val epname = ctx.freshName(nme.EVIDENCE_PARAM_PREFIX).toTermName
150150
epbuf += ValDef(epname, cxbound, EmptyTree).withFlags(paramFlags | Implicit)
151151
}
152-
cpy.TypeDef(tparam)(rhs = tbounds)
153-
case tparam =>
154-
tparam
152+
tbounds
153+
case PolyTypeTree(tparams, body) =>
154+
cpy.PolyTypeTree(rhs)(tparams, desugarContextBounds(body))
155+
case _ =>
156+
rhs
157+
}
158+
val tparams1 = tparams mapConserve { tdef =>
159+
cpy.TypeDef(tdef)(rhs = desugarContextBounds(tdef.rhs))
155160
}
156161

157162
val meth1 = addEvidenceParams(cpy.DefDef(meth)(tparams = tparams1), epbuf.toList)

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ object Denotations {
132132
def atSignature(sig: Signature, site: Type = NoPrefix, relaxed: Boolean = false)(implicit ctx: Context): Denotation
133133

134134
/** The variant of this denotation that's current in the given context.
135-
* If no such denotation exists, returns the denotation with each alternative
135+
* If no such denotation exists, returns the denotation with each alternative
136136
* at its first point of definition.
137137
*/
138138
def current(implicit ctx: Context): Denotation
@@ -744,6 +744,20 @@ object Denotations {
744744
else NoDenotation
745745
}
746746

747+
/** The next defined denotation (following `nextInRun`) or an arbitrary
748+
* undefined denotation, if all denotations in a `nextinRun` cycle are
749+
* undefined.
750+
*/
751+
private def nextDefined: SingleDenotation = {
752+
var p1 = this
753+
var p2 = nextInRun
754+
while (p1.validFor == Nowhere && (p1 ne p2)) {
755+
p1 = p1.nextInRun
756+
p2 = p2.nextInRun.nextInRun
757+
}
758+
p1
759+
}
760+
747761
/** Produce a denotation that is valid for the given context.
748762
* Usually called when !(validFor contains ctx.period)
749763
* (even though this is not a precondition).
@@ -763,8 +777,9 @@ object Denotations {
763777
// can happen if we sit on a stale denotation which has been replaced
764778
// wholesale by an installAfter; in this case, proceed to the next
765779
// denotation and try again.
766-
if (validFor == Nowhere && nextInRun.validFor != Nowhere) return nextInRun.current
767-
assert(false)
780+
val nxt = nextDefined
781+
if (nxt.validFor != Nowhere) return nxt
782+
assert(false, this)
768783
}
769784

770785
if (valid.runId != currentPeriod.runId)
@@ -905,6 +920,7 @@ object Denotations {
905920
prev.nextInRun = this
906921
this.nextInRun = old.nextInRun
907922
old.validFor = Nowhere
923+
old.nextInRun = this
908924
}
909925

910926
def staleSymbolError(implicit ctx: Context) = {

compiler/src/dotty/tools/dotc/core/Periods.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ object Periods {
153153
final val FirstPhaseId = 1
154154

155155
/** The number of bits needed to encode a phase identifier. */
156-
final val PhaseWidth = 6
156+
final val PhaseWidth = 7
157157
final val PhaseMask = (1 << PhaseWidth) - 1
158158
final val MaxPossiblePhaseId = PhaseMask
159159
}

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ import Decorators._
4747
}
4848
tree match {
4949
case ddef: DefDef
50-
if !ddef.symbol.is(Deferred) && ddef.rhs == EmptyTree =>
50+
if !ddef.symbol.is(Deferred) &&
51+
!ddef.symbol.isConstructor && // constructors bodies are added later at phase Constructors
52+
ddef.rhs == EmptyTree =>
5153
errorLackImplementation(ddef)
5254
case tdef: TypeDef
5355
if tdef.symbol.isClass && !tdef.symbol.is(Deferred) && tdef.rhs == EmptyTree =>
@@ -89,10 +91,10 @@ import Decorators._
8991
}
9092

9193
lazy val field = sym.field.orElse(newField).asTerm
92-
94+
9395
def adaptToField(tree: Tree) =
9496
if (tree.isEmpty) tree else tree.ensureConforms(field.info.widen)
95-
97+
9698
if (sym.is(Accessor, butNot = NoFieldNeeded))
9799
if (sym.isGetter) {
98100
def skipBlocks(t: Tree): Tree = t match {

tests/pos/i1765.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
trait T[X]
2+
3+
trait U[X]
4+
5+
trait TC[M[_]] {
6+
def foo[M[_]: TC, A](ma: U[A]) = ()
7+
implicit val TCofT: TC[T] = new TC[T] {}
8+
implicit def any2T[A](a: A): T[A] = new T[A] {}
9+
implicit def any2U[A](a: A): U[A] = new U[A] {}
10+
val x = foo[T, Int](1)
11+
val y = ()
12+
}
13+
14+
// Minimized version exhibiting an assertion violation in Denotation#current at phase lambdalift:
15+
trait TC2 {
16+
// implicit val TCofT: TC2[T] = new TC2[T] {}
17+
val TCofT: Object = {
18+
class C extends TC2
19+
new Object
20+
}
21+
}

0 commit comments

Comments
 (0)