Skip to content

Commit aeda72b

Browse files
author
Aleksandar Pokopec
committed
Fixes #4351.
Added an "Abstract" method info to the specialized phase, which denotes that no implementation should be generated. Previously: trait A[@specialized(Boolean) T] { def foo: T } used to generate: trait A$mcZ$sp extends A[Boolean] { def foo$mcZ$sp = this.foo } which caused cyclic calls because of linearization rules when several traits are mixed together. Now, the following is generated: trait A$mcZ$sp extends A[Boolean] { def foo$mcZ$sp: Boolean } Review by dragos.
1 parent 567e9f2 commit aeda72b

File tree

3 files changed

+43
-11
lines changed

3 files changed

+43
-11
lines changed

src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
6767
emptyEnv ++ (sym.info.typeParams zip args filter (kv => isSpecialized(kv._1)))
6868
}
6969

70-
/** Is typeenv `t1` included in `t2`? All type variables in `t1`
70+
/** Does typeenv `t1` include `t2`? All type variables in `t1`
7171
* are defined in `t2` and:
7272
* - are bound to the same type, or
7373
* - are an AnyRef specialization and `t2` is bound to a subtype of AnyRef
@@ -150,6 +150,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
150150
def target = t
151151
}
152152

153+
/** Symbol is a specialized abstract method, either specialized or original. The original `t` is abstract. */
154+
case class Abstract(t: Symbol) extends SpecializedInfo {
155+
def target = t
156+
}
157+
153158
/** Symbol is a specialized accessor for the `target` field. */
154159
case class SpecializedAccessor(target: Symbol) extends SpecializedInfo {
155160
override def isAccessor = true
@@ -301,7 +306,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
301306
loop(keys map concreteTypes) map (keys zip _ toMap)
302307
}
303308

304-
/** Does the given tpe need to be specialized in the environment 'env'?
309+
/** Does the given 'sym' need to be specialized in the environment 'env'?
305310
* Specialization is needed for
306311
* - members with specialized type parameters found in the given environment
307312
* - constructors of specialized classes
@@ -587,13 +592,13 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
587592
log("conflicting env for " + m + " env: " + env)
588593
}
589594
else if (m.isDeferred) { // abstract methods
590-
val specMember = enterMember(m.cloneSymbol(cls)).setFlag(SPECIALIZED).resetFlag(DEFERRED)
591-
debuglog("deferred " + specMember.fullName + " is forwarded")
592-
593-
info(specMember) = new Forward(specMember) {
594-
override def target = m.owner.info.member(specializedName(m, env))
595-
}
595+
val specMember = enterMember(m.cloneSymbol(cls)).setFlag(SPECIALIZED).setFlag(DEFERRED)
596+
debuglog("deferred " + specMember.fullName + " remains abstract")
596597

598+
info(specMember) = new Abstract(specMember)
599+
// was: new Forward(specMember) {
600+
// override def target = m.owner.info.member(specializedName(m, env))
601+
// }
597602
} else if (m.isMethod && !m.hasAccessorFlag) { // other concrete methods
598603
// log("other concrete " + m)
599604
forwardToOverload(m)
@@ -812,15 +817,15 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
812817
)
813818
}
814819

815-
/** For each method m that overrides inherited method m', add a special
820+
/** For each method m that overrides an inherited method m', add a special
816821
* overload method `om` that overrides the corresponding overload in the
817822
* superclass. For the following example:
818823
*
819824
* class IntFun extends Function1[Int, Int] {
820-
* def apply(x: Int): Int = ..
825+
* def apply(x: Int): Int = ..
821826
* }
822827
*
823-
* this method will return List('apply$spec$II')
828+
* this method will return List('apply$mcII$sp')
824829
*/
825830
private def specialOverrides(clazz: Symbol): List[Symbol] = {
826831
/** Return the overridden symbol in syms that needs a specialized overriding symbol,
@@ -1431,6 +1436,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
14311436
Assign(gen.mkAttributedRef(target), Ident(vparamss.head.head.symbol))
14321437
log("specialized accessor: " + target + " -> " + rhs1)
14331438
localTyper.typed(treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs1))
1439+
1440+
case Abstract(targ) =>
1441+
log("abstract: " + targ)
1442+
val DefDef(mods, name, tparams, vparamss, tpt, rhs) = tree
1443+
val t = treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs)
1444+
localTyper.typed(t)
14341445
}
14351446

14361447
case ValDef(mods, name, tpt, rhs) if symbol.hasFlag(SPECIALIZED) && !symbol.isParamAccessor =>

test/files/pos/t4351.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
runtime exception

test/files/pos/t4351.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
try new BooleanPropImpl() value
4+
catch {
5+
case e: RuntimeException => println("runtime exception")
6+
}
7+
}
8+
}
9+
10+
trait Prop[@specialized(Boolean) +T] {
11+
def value: T
12+
}
13+
14+
class PropImpl[+T] extends Prop[T] {
15+
def value: T = scala.sys.error("")
16+
}
17+
18+
trait BooleanProp extends Prop[Boolean]
19+
20+
class BooleanPropImpl() extends PropImpl[Boolean] with BooleanProp

0 commit comments

Comments
 (0)