diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeGen.scala | 6 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 36 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Definitions.scala | 1 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Types.scala | 5 | ||||
-rw-r--r-- | test/files/neg/t5761.check | 2 | ||||
-rw-r--r-- | test/files/run/delambdafy_uncurry_byname_inline.check | 2 | ||||
-rw-r--r-- | test/files/run/delambdafy_uncurry_inline.check | 2 | ||||
-rw-r--r-- | test/files/run/sammy_restrictions_LMF.scala | 9 | ||||
-rw-r--r-- | test/files/run/t6028.check | 6 | ||||
-rw-r--r-- | test/files/run/t6555.check | 2 |
10 files changed, 48 insertions, 23 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) diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 8074b448fe..e9baa47d82 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -581,7 +581,6 @@ trait Definitions extends api.StandardDefinitions { /** Creators for TupleN, ProductN, FunctionN. */ def tupleType(elems: List[Type]) = TupleClass.specificType(elems) def functionType(formals: List[Type], restpe: Type) = FunctionClass.specificType(formals, restpe) - def abstractFunctionType(formals: List[Type], restpe: Type) = AbstractFunctionClass.specificType(formals, restpe) def wrapArrayMethodName(elemtp: Type): TermName = elemtp.typeSymbol match { case ByteClass => nme.wrapByteArray diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 00df55f044..f385ca08c9 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -4553,11 +4553,6 @@ trait Types else (ps :+ SerializableTpe).toList ) - def addObjectParent(tps: List[Type]) = tps match { - case hd :: _ if hd.typeSymbol.isTrait => ObjectTpe :: tps - case _ => tps - } - /** Adds the @uncheckedBound annotation if the given `tp` has type arguments */ final def uncheckedBounds(tp: Type): Type = { if (tp.typeArgs.isEmpty || UncheckedBoundsClass == NoSymbol) tp // second condition for backwards compatibility with older scala-reflect.jar diff --git a/test/files/neg/t5761.check b/test/files/neg/t5761.check index 2d66af26f6..15c0bc7634 100644 --- a/test/files/neg/t5761.check +++ b/test/files/neg/t5761.check @@ -13,7 +13,7 @@ Unspecified value parameter x. t5761.scala:13: error: not found: type Tread new Tread("sth") { }.run() ^ -t5761.scala:13: error: value run is not a member of AnyRef +t5761.scala:13: error: value run is not a member of <error> new Tread("sth") { }.run() ^ 5 errors found diff --git a/test/files/run/delambdafy_uncurry_byname_inline.check b/test/files/run/delambdafy_uncurry_byname_inline.check index d96a995f44..e1ee4c29e2 100644 --- a/test/files/run/delambdafy_uncurry_byname_inline.check +++ b/test/files/run/delambdafy_uncurry_byname_inline.check @@ -7,7 +7,7 @@ package <empty> { }; def bar(x: () => Int): Int = x.apply(); def foo(): Int = Foo.this.bar({ - @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractFunction0[Int] with Serializable { + @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends Object with () => Int with Serializable { def <init>(): <$anon: () => Int> = { $anonfun.super.<init>(); () diff --git a/test/files/run/delambdafy_uncurry_inline.check b/test/files/run/delambdafy_uncurry_inline.check index 5521cc4a2c..479e9409fa 100644 --- a/test/files/run/delambdafy_uncurry_inline.check +++ b/test/files/run/delambdafy_uncurry_inline.check @@ -7,7 +7,7 @@ package <empty> { }; def bar(): Unit = { val f: Int => Int = { - @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractFunction1[Int,Int] with Serializable { + @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends Object with Int => Int with Serializable { def <init>(): <$anon: Int => Int> = { $anonfun.super.<init>(); () diff --git a/test/files/run/sammy_restrictions_LMF.scala b/test/files/run/sammy_restrictions_LMF.scala index 27a3d21dad..aa49e14113 100644 --- a/test/files/run/sammy_restrictions_LMF.scala +++ b/test/files/run/sammy_restrictions_LMF.scala @@ -8,6 +8,11 @@ trait TImpure { def apply(x: Int): String ; println(1) } trait Println { println(1) } trait TImpureSuper extends Println { def apply(x: Int): String } +class C +trait A extends C +trait B extends A +trait TClassParent extends B { def apply(x: Int): String } + object Test extends App { final val AnonFunClass = "$anonfun$" final val LMFClass = "$$Lambda$" // LambdaMetaFactory names classes like this @@ -45,4 +50,8 @@ object Test extends App { notLMF((x => "a"): TImpure) notLMF((x => "a"): TImpureSuper) + + val fClassParent: TClassParent = x => "a" + notLMF(fClassParent) + assert(fClassParent(1) == "a") } diff --git a/test/files/run/t6028.check b/test/files/run/t6028.check index 532d177300..f21b77fdc7 100644 --- a/test/files/run/t6028.check +++ b/test/files/run/t6028.check @@ -24,9 +24,10 @@ package <empty> { (new <$anon: Function0>(T.this, tryyParam, tryyLocal): Function0) } }; - @SerialVersionUID(value = 0) final <synthetic> class $anonfun$foo$1 extends scala.runtime.AbstractFunction0$mcI$sp with Serializable { + @SerialVersionUID(value = 0) final <synthetic> class $anonfun$foo$1 extends Object with Function0$mcI$sp with Serializable { def <init>($outer: T, methodParam$1: Int, methodLocal$1: Int): <$anon: Function0> = { $anonfun$foo$1.super.<init>(); + $anonfun$foo$1.super./*Function0*/$init$(); () }; final def apply(): Int = $anonfun$foo$1.this.apply$mcI$sp(); @@ -66,9 +67,10 @@ package <empty> { T.this.MethodLocalObject$lzycompute$1(barParam$1, MethodLocalObject$module$1) else MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type](); - @SerialVersionUID(value = 0) final <synthetic> class $anonfun$tryy$1 extends scala.runtime.AbstractFunction0$mcV$sp with Serializable { + @SerialVersionUID(value = 0) final <synthetic> class $anonfun$tryy$1 extends Object with Function0$mcV$sp with Serializable { def <init>($outer: T, tryyParam$1: Int, tryyLocal$1: runtime.IntRef): <$anon: Function0> = { $anonfun$tryy$1.super.<init>(); + $anonfun$tryy$1.super./*Function0*/$init$(); () }; final def apply(): Unit = $anonfun$tryy$1.this.apply$mcV$sp(); diff --git a/test/files/run/t6555.check b/test/files/run/t6555.check index e3b467ce7c..fef689a80d 100644 --- a/test/files/run/t6555.check +++ b/test/files/run/t6555.check @@ -6,7 +6,7 @@ package <empty> { () }; private[this] val f: Int => Int = { - @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractFunction1$mcII$sp with Serializable { + @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends Object with Int => Int with Serializable { def <init>(): <$anon: Int => Int> = { $anonfun.super.<init>(); () |