Skip to content

Commit 0baa6dc

Browse files
authored
Merge pull request #3070 from dotty-staging/fix-2.12-lazy-vals
Fix access of lazy vals in traits compiled by 2.12
2 parents 60d14c3 + 195840a commit 0baa6dc

File tree

5 files changed

+43
-11
lines changed

5 files changed

+43
-11
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ object NameOps {
132132

133133
def implClassName: N = likeSpaced(name ++ tpnme.IMPL_CLASS_SUFFIX)
134134

135+
def traitOfImplClassName: N = {
136+
val suffix = tpnme.IMPL_CLASS_SUFFIX.toString
137+
assert(name.endsWith(suffix), name)
138+
likeSpaced(name.mapLast(_.dropRight(suffix.length)))
139+
}
140+
135141
def errorName: N = likeSpaced(name ++ nme.ERROR)
136142

137143
/** Map variance value -1, +1 to 0, 1 */

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransform
5555
val implClass = ctx.newCompleteClassSymbol(
5656
owner = mixin.owner,
5757
name = mixin.name.implClassName,
58-
flags = Abstract | Scala2x,
58+
flags = Abstract | Scala2x | ImplClass,
5959
parents = defn.ObjectType :: Nil,
6060
assocFile = mixin.assocFile).enteredAfter(thisTransform)
6161

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

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,23 +85,29 @@ class LinkScala2Impls extends MiniPhase with IdentityDenotTransformer { thisTran
8585
val impl = implMethod(sel.symbol)
8686
if (impl.exists) Apply(ref(impl), This(currentClass) :: args).withPos(app.pos)
8787
else app // could have been an abstract method in a trait linked to from a super constructor
88+
case Apply(sel, args)
89+
if sel.symbol.maybeOwner.is(ImplClass) && sel.symbol.owner.traitOfImplClass.is(Scala_2_12_Trait) =>
90+
val impl = implMethod(sel.symbol)
91+
cpy.Apply(app)(ref(impl), args)
8892
case _ =>
8993
app
9094
}
9195
}
9296

97+
/** The 2.12 implementation method of a super call or implementation class target */
9398
private def implMethod(meth: Symbol)(implicit ctx: Context): Symbol = {
94-
val (implInfo, implName) =
95-
if (meth.owner.is(Scala_2_12_Trait))
96-
(meth.owner.info, ImplMethName(meth.name.asTermName))
99+
val implName = ImplMethName(meth.name.asTermName)
100+
val cls = meth.owner
101+
if (cls.is(ImplClass))
102+
cls.traitOfImplClass.info.decl(implName).atSignature(meth.signature).symbol
103+
else if (cls.is(Scala_2_12_Trait))
104+
if (meth.isConstructor)
105+
cls.info.decl(nme.TRAIT_CONSTRUCTOR).symbol
97106
else
98-
(meth.owner.implClass.info, meth.name)
99-
if (meth.isConstructor)
100-
implInfo.decl(nme.TRAIT_CONSTRUCTOR).symbol
101-
else
102-
implInfo.decl(implName)
103-
.suchThat(c => FullParameterization.memberSignature(c.info) == meth.signature)
104-
.symbol
107+
cls.info.decl(implName)
108+
.suchThat(c => FullParameterization.memberSignature(c.info) == meth.signature)
109+
.symbol
110+
else throw new AssertionError(i"no impl method for $meth")
105111
}
106112
}
107113

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ class SymUtils(val self: Symbol) extends AnyVal {
115115
def implClass(implicit ctx: Context): Symbol =
116116
self.owner.info.decl(self.name.implClassName).symbol
117117

118+
def traitOfImplClass(implicit ctx: Context): Symbol =
119+
self.owner.info.decl(self.name.traitOfImplClassName).symbol
120+
118121
def annotationsCarrying(meta: ClassSymbol)(implicit ctx: Context): List[Annotation] =
119122
self.annotations.filter(_.symbol.hasAnnotation(meta))
120123

tests/run/scala2trait-lazyval.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class Foo extends scala.collection.SeqView[Int, List[Int]] {
2+
def iterator: Iterator[Int] = null
3+
def apply(idx: Int): Int = idx
4+
def length: Int = 0
5+
protected def underlying = null
6+
}
7+
8+
object Test {
9+
def main(args: Array[String]): Unit = {
10+
val f: scala.collection.TraversableViewLike[Int, List[Int], _] = new Foo
11+
new f.Transformed[Int] {
12+
def foreach[U](f: Int => U): Unit = ()
13+
// underlying is a lazy val
14+
assert(underlying == null)
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)