New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AnyRef specialization crashes when compiling against source Function1 #5545
Comments
Imported From: https://issues.scala-lang.org/browse/SI-5545?orig=1 |
@paulp said: |
@paulp said: |
@paulp said:
|
@paulp said: trait F[@specialized(AnyRef) R] {
def f(): R
def g() = () => f()
}
|
@paulp said:
So the surviving type parameter after anyref specialization (TR$sp) is referenced from a closure. The other difference of note is that these two lines appear only in the crashing version:
|
@VladUreche said: $ git log --oneline -n 5
3525296 Oops, all the preceding meant SI-5541.
777dbd7 Revert attempt to limit private types in lubs.
f708b87 Overcame trait/protected/java limitation.
fb87f2d Test case closes SI-4777.
61d34ed An old patch on pattern matcher exhaustivity.
$ ant quick.clean; ant
[...]
$ cat a.scala
trait F[@specialized(AnyRef) R] {
def f(): R
def g() = () => f()
}
$ rm -rf out && mkdir out && scalac -cp out -d out ./a.scala && scalac -cp out -d out ./a.scala
$ # it ran fine |
@paulp said: trait F[@specialized(Int, AnyRef) T1, @specialized(AnyRef) R] {
def apply(v1: T1): R
def compose[A](g: A => T1): A => R = { x => apply(g(x)) }
} |
@VladUreche said: $ cat a.scala
trait F[@specialized(Int) T1, R] {
def f(v1: T1): R
def g = v1 => f(v1)
}
$ rm -rf out; mkdir out; scalac -d out a.scala; scalac -d out -cp out a.scala
error: R in trait F$mcI$sp cannot be instantiated from F$mcI$sp
error:
while compiling: a.scala
current phase: jvm
library version: version 2.10.0-M2-0097-g35252961db-2012-03-05
compiler version: version 2.10.0-M2-0097-g35252961db-2012-03-05
reconstructed args: -d out -classpath out
uncaught exception during compilation: scala.reflect.internal.FatalError
error: scala.reflect.internal.FatalError:
while compiling: a.scala
current phase: erasure
library version: version 2.10.0-M2-0097-g35252961db-2012-03-05
compiler version: version 2.10.0-M2-0097-g35252961db-2012-03-05
reconstructed args: -d out -classpath out
R in trait F$mcI$sp cannot be instantiated from F$mcI$sp
at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:38)
at scala.tools.nsc.Global.abort(Global.scala:189)
at scala.reflect.internal.Types$AsSeenFromMap.throwError$1(Types.scala:4085)
[...]
at scala.tools.nsc.Driver.main(Driver.scala:65)
at scala.tools.nsc.Main.main(Main.scala)
error: fatal error:
while compiling: a.scala
current phase: erasure
library version: version 2.10.0-M2-0097-g35252961db-2012-03-05
compiler version: version 2.10.0-M2-0097-g35252961db-2012-03-05
reconstructed args: -d out -classpath out
R in trait F$mcI$sp cannot be instantiated from F$mcI$sp |
@paulp said: |
@paulp said:
|
@VladUreche said (edited on Mar 5, 2012 3:29:43 PM UTC): $ cd out
$ scalap -cp . 'F$mcI$sp'
package F$mcI$sp;
abstract trait F$mcI$sp with F {
def g$mcI$sp(): scala.Function1;
def g(): scala.Function1;
def f(scala.Int): scala.Any;
} |
@paulp said:
Except, why are there two signatures attached to f and g, is that normal?
|
@non said: |
@VladUreche said: Before you dive into the details, I need someone to explain how the signatures work. If I understood well, only the main class F should have a Scala signature pickled into it, and when loading the class and the signature, it will undergo the specialization type transform and infer there must be other specialized classes lying around (from the @specialized on the type params) - thus F$mcI$sp should not pickle a Scala signature, right? Now, comparing the two logs (compile with and without existing bytecode) one can spot a bytecode loading taking place just before generating the class in GenJVM -- and this seems to change (break) the existing signature generated by specialization: [log jvm] sig(g$mcI$sp, method g$mcI$sp#10450, trait F$mcI$sp#10444) ()Lscala/Function1<Ljava/lang/Object;TR;>;
<omitted output>
[log jvm] sig(F$mcI$sp, trait F$mcI$sp#10444, package class <empty>#4) <R:Ljava/lang/Object;>Ljava/lang/Object;LF<Ljava/lang/Object;TR;>;
[log jvm(->lazyvals)] [class] >> F$mcI$sp
This is trait F$mcI$sp#10444: I got my info changed!
new info: lang#2520.this.Object#2592
with <empty>#4.this.F#8[T1#7693,R#7694] {
}
phase: parser
stack:
at java.lang.Thread.getStackTrace(Thread.java:1479)
at scala.reflect.internal.Symbols$Symbol.info_$eq(Symbols.scala:1023)
at scala.reflect.internal.Symbols$TypeSymbol.info_$eq(Symbols.scala:2434)
at scala.reflect.internal.Symbols$Symbol.setInfo(Symbols.scala:1031)
at scala.tools.nsc.symtab.classfile.ClassfileParser.parseClass(ClassfileParser.scala:559)
at scala.tools.nsc.symtab.classfile.ClassfileParser.parse(ClassfileParser.scala:100)
at scala.tools.nsc.symtab.SymbolLoaders$ClassfileLoader.doComplete(SymbolLoaders.scala:234)
at scala.tools.nsc.symtab.SymbolLoaders$SymbolLoader.complete(SymbolLoaders.scala:136)
at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:996)
at scala.reflect.internal.Symbols$Symbol.initialize(Symbols.scala:1136)
at scala.tools.nsc.symtab.SymbolLoaders$moduleClassLoader$.doComplete(SymbolLoaders.scala:259)
at scala.tools.nsc.symtab.SymbolLoaders$SymbolLoader.complete(SymbolLoaders.scala:136)
at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:996)
at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator$$anonfun$addInnerClasses$1$$anonfun$apply$mcV$sp$1.apply(GenJVM.scala:803)
at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator$$anonfun$addInnerClasses$1$$anonfun$apply$mcV$sp$1.apply(GenJVM.scala:803)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
at scala.collection.immutable.List.foreach(List.scala:77)
at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator$$anonfun$addInnerClasses$1.apply$mcV$sp(GenJVM.scala:803)
at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator$$anonfun$addInnerClasses$1.apply(GenJVM.scala:803)
at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator$$anonfun$addInnerClasses$1.apply(GenJVM.scala:803)
at scala.reflect.internal.SymbolTable.atPhase(SymbolTable.scala:134)
at scala.reflect.internal.SymbolTable.afterPhase(SymbolTable.scala:143)
at scala.tools.nsc.Global.afterErasure(Global.scala:872)
at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator.addInnerClasses(GenJVM.scala:802)
at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator.emitClass(GenJVM.scala:295)
at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator.genClass(GenJVM.scala:426)
at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase$$anonfun$run$3.apply(GenJVM.scala:165)
at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase$$anonfun$run$3.apply(GenJVM.scala:164)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
at scala.collection.immutable.List.foreach(List.scala:77)
at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase.run(GenJVM.scala:164)
at scala.tools.nsc.Global$Run.compileUnitsInternal(Global.scala:1288)
at scala.tools.nsc.Global$Run.compileUnits(Global.scala:1261)
at scala.tools.nsc.Global$Run.compileSources(Global.scala:1255)
at scala.tools.nsc.Global$Run.compile(Global.scala:1385)
at scala.tools.nsc.Driver.doCompile(Driver.scala:31)
at scala.tools.nsc.Main$.doCompile(Main.scala:81)
at scala.tools.nsc.Driver.process(Driver.scala:52)
at scala.tools.nsc.Driver.main(Driver.scala:65)
at scala.tools.nsc.Main.main(Main.scala)
This is module class F$mcI$sp#7: I got my info changed!
new info: {
}
phase: parser
stack:
at java.lang.Thread.getStackTrace(Thread.java:1479)
at scala.reflect.internal.Symbols$Symbol.info_$eq(Symbols.scala:1023)
at scala.reflect.internal.Symbols$TypeSymbol.info_$eq(Symbols.scala:2434)
at scala.reflect.internal.Symbols$Symbol.setInfo(Symbols.scala:1031)
at scala.tools.nsc.symtab.classfile.ClassfileParser.parseClass(ClassfileParser.scala:561)
at scala.tools.nsc.symtab.classfile.ClassfileParser.parse(ClassfileParser.scala:100)
[ ... same as before ...]
This is module F$mcI$sp#6: I got my info changed!
new info: object <empty>#4.this.F$mcI$sp#7
phase: parser
stack:
at java.lang.Thread.getStackTrace(Thread.java:1479)
at scala.reflect.internal.Symbols$Symbol.info_$eq(Symbols.scala:1023)
at scala.reflect.internal.Symbols$Symbol.setInfo(Symbols.scala:1031)
at scala.tools.nsc.symtab.classfile.ClassfileParser.parseClass(ClassfileParser.scala:562)
at scala.tools.nsc.symtab.classfile.ClassfileParser.parse(ClassfileParser.scala:100)
[ ... same as before ...]
[log jvm] F$mcI$sp contains 1 inner classes.
[log jvm] //class F$mcI$sp$$anonfun$g$mcI$sp$1
[log jvm] Adding field: F$mcI$sp$$anonfun$g$mcI$sp$1.$outer
[log jvm] Generating method F$mcI$sp$$anonfun$g$mcI$sp$1.apply
[log jvm] Index value for value v1#19172{880484842}: 1
[log jvm] Linearizer adding block 1
[log jvm] Making labels for: F$mcI$sp$$anonfun$g$mcI$sp$1.apply
[log jvm] Generating code for block: 1 at pc: 0
[log jvm] LOAD_FIELD with owner: F$mcI$sp$$anonfun$g$mcI$sp$1 flags: final <synthetic> <lifted>
[log jvm] invokeinterface F$mcI$sp.f:(int)java/lang/Object
/// starting debugging output added by me
parent = anonymous class F$mcI$sp$$anonfun$g$mcI$sp$1#19167
signature after erasure: <root>#2#<empty>#4#F$mcI$sp$$anonfun$g$mcI$sp$1#19167
signature before erasure: F$mcI$sp$$anonfun$g$mcI$sp$1#19167.this.type
we want child info: method apply#19170
signature after erasure: (<param> <triedcooking> v1#19237: <root>#2#scala#30#Int#453)<root>#2#java#26#lang#2520#Object#2592
now computing it before erasure
/// In the first test, without bytecode, the next line is:
/// instantiating type R#10434 from trait F$mcI$sp#10433 with List(type R#10434) and List(R#10434), pre = F$mcI$sp#10433.this.type, symclazz = trait F$mcI$sp#10433
/// but now it's missing the type parameter R in the signature:
instantiating type R#10445 from trait F$mcI$sp#10444 with List() and List(), pre = F$mcI$sp#10444.this.type, symclazz = trait F$mcI$sp#10444
error: R#10445 in trait F$mcI$sp#10444 cannot be instantiated from <empty>#4.this.F$mcI$sp#10444
/// end of debugging output
error:
while compiling: a.scala
current phase: jvm
library version: version 2.10.0-M2-0097-g35252961db-2012-03-05
compiler version: version 2.10.0-M2-0097-g35252961db-2012-03-06
reconstructed args: -Ydebug -d out -classpath out -uniqid -Ylog:all
Current unit body:
<empty>
uncaught exception during compilation: scala.reflect.internal.FatalError
error: scala.reflect.internal.FatalError:
while compiling: a.scala
current phase: erasure
library version: version 2.10.0-M2-0097-g35252961db-2012-03-05
compiler version: version 2.10.0-M2-0097-g35252961db-2012-03-06
reconstructed args: -Ydebug -d out -classpath out -uniqid -Ylog:all
Current unit body:
<empty>
R#10445 in trait F$mcI$sp#10444 cannot be instantiated from <empty>#4.this.F$mcI$sp#10444 |
@VladUreche said: Short explanation:
phase before parser (Definition.<init> specialization genJVM
source ---------------------------------------- trait F -----------------------------------------------------
code \
/ class sym (lazy type) ---- ----- synthetic F$mcI$sp ------- force .info - signature messed up --- crash
existing ---<- module sym (lazy type) -------------------------------------- force .info - eliminated
bytecode \ mclass sym (lazy type) ---------------------------------------------------- eliminated
A localized solution is to force .info on all members with the same name before creating a specialized version of a class - and this fixes the particular problem - but shouldn't this be done everytime we create a synthetic class? |
@VladUreche said: |
Since 8ae0fda, the specializion phase eagerly info transforms all of FunctionN and TupleN. This was done to let us turn off needless specialization info transforms (which incurs classfile parsing up the base classes looking for @specialized annotations) of types after the specialization tree transform is done. However, in combination with an old fix for scala/bug#5545, we end up parsing all of the class files of all the variants, just to unlink them in favour of the info-transformed types. I note that the test for scala/bug#5545 no longer crashes if the fix is removed. I have have not investigated the reason. This commit reworks the scala/bug#5545 to just unlink the stale symbols directly, rather than calling `.info` to parse them and do the same after noticing the ScalaRaw attribute.
Since 8ae0fda, the specializion phase eagerly info transforms all of FunctionN and TupleN. This was done to let us turn off needless specialization info transforms (which incurs classfile parsing up the base classes looking for @specialized annotations) of types after the specialization tree transform is done. However, in combination with an old fix for scala/bug#5545, we end up parsing all of the class files of all the variants, just to unlink them in favour of the info-transformed types. I note that the test for scala/bug#5545 no longer crashes if the fix is removed. I have have not investigated the reason. This commit reworks the scala/bug#5545 to just unlink the stale symbols directly, rather than calling `.info` to parse them and do the same after noticing the ScalaRaw attribute.
This looks like something tied up in AnyRef specialization and generic signatures. It's not clear to me what it is yet though. I'd appreciate any assistance.
[Removed red herring, compiling Function1.scala is enough.]
scala> classOf[scala.Function1[,]].getTypeParameters.toList
res3: List[java.lang.reflect.TypeVariable[Class[Function1[_, _]]]] = List(T1, R)
scala> classOf[scala.Function1$mcDL$sp[]].getTypeParameters.toList
res4: List[java.lang.reflect.TypeVariable[Class[Function1$mcDL$sp[]]]] = List(T1$sp)
{noformat}
The text was updated successfully, but these errors were encountered: