diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2016-03-29 18:18:09 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2016-03-29 23:19:26 -0700 |
commit | 3904c3216c741b387d81754e55aa079ce4218d06 (patch) | |
tree | 9d53968a9542a5b2791afac33d6f8fa2152b66dd /src/compiler | |
parent | 62d97d7f110894a0c2f36b1ed9dd7ad59c0115fa (diff) | |
download | scala-3904c3216c741b387d81754e55aa079ce4218d06.tar.gz scala-3904c3216c741b387d81754e55aa079ce4218d06.tar.bz2 scala-3904c3216c741b387d81754e55aa079ce4218d06.zip |
LMF cannot instantiate SAM of trait with non-trait superclass
Also, drop AbstractFunction for parent of anonymous subclass of
function type that must have its class spun up at compile time
(rather than at linkage time by LambdaMetaFactory).
This revealed an old problem with typedTemplate, in which
parent types may be normalized at the level of trees,
while this change does not get propagated to the class's info
in time for the constructor to be located when we type check
the primary constructor.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeGen.scala | 6 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 36 |
2 files changed, 31 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 27e366e725..227d395036 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -310,13 +310,9 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { newDefDef(methSym, moveToMethod(useMethodParams(fun.body)))(tpt = TypeTree(resTp)) } - // TODO: the rewrite to AbstractFunction is superfluous once we compile FunctionN to a SAM type (aka functional interface) - def functionClassType(fun: Function): Type = - if (isFunctionType(fun.tpe)) abstractFunctionType(fun.vparams.map(_.symbol.tpe), fun.body.tpe.deconst) - else fun.tpe def expandFunction(localTyper: analyzer.Typer)(fun: Function, inConstructorFlag: Long): Tree = { - val parents = addObjectParent(addSerializable(functionClassType(fun))) + val parents = addSerializable(fun.tpe) val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation SerialVersionUIDAnnotation // The original owner is used in the backend for the EnclosingMethod attribute. If fun is diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 35cfc644ab..ff0513156b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1747,17 +1747,21 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper classinfo.parents map (_.instantiateTypeParams(List(tparam), List(AnyRefTpe))), classinfo.decls, clazz) - clazz.setInfo { - clazz.info match { - case PolyType(tparams, _) => PolyType(tparams, newinfo) - case _ => newinfo - } - } + updatePolyClassInfo(clazz, newinfo) FinitaryError(tparam) } } } + private def updatePolyClassInfo(clazz: Symbol, newinfo: ClassInfoType): clazz.type = { + clazz.setInfo { + clazz.info match { + case PolyType(tparams, _) => PolyType(tparams, newinfo) + case _ => newinfo + } + } + } + def typedClassDef(cdef: ClassDef): Tree = { val clazz = cdef.symbol val typedMods = typedModifiers(cdef.mods) @@ -1866,6 +1870,26 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // please FIXME: uncommenting this line breaks everything // val templ = treeCopy.Template(templ0, templ0.body, templ0.self, templ0.parents) val clazz = context.owner + + val parentTypes = parents1.map(_.tpe) + + // The parents may have been normalized by typedParentTypes. + // We must update the info as well, or we won't find the super constructor for our now-first parent class + // Consider `class C ; trait T extends C ; trait U extends T` + // `U`'s info will start with parent `T`, but `typedParentTypes` will return `List(C, T)` (`== parents1`) + // now, the super call in the primary ctor will fail to find `C`'s ctor, since it bases its search on + // `U`'s info, not the trees. + // + // For correctness and performance, we restrict this rewrite to anonymous classes, + // as others have their parents in order already (it seems!), and we certainly + // don't want to accidentally rewire superclasses for e.g. the primitive value classes. + // + // TODO: Find an example of a named class needing this rewrite, I tried but couldn't find one. + if (clazz.isAnonymousClass && clazz.info.parents != parentTypes) { +// println(s"updating parents of $clazz from ${clazz.info.parents} to $parentTypes") + updatePolyClassInfo(clazz, ClassInfoType(parentTypes, clazz.info.decls, clazz)) + } + clazz.annotations.map(_.completeInfo()) if (templ.symbol == NoSymbol) templ setSymbol clazz.newLocalDummy(templ.pos) |