bug icon indicating copy to clipboard operation
bug copied to clipboard

[toolbox] IndexOutOfBoundsException from StandardImporter.recreateOrRelink

Open scabug opened this issue 10 years ago • 6 comments

Unfortunately no minimal right now, as this appears only when I run a whole test suite - on single test it works ok.

Failing test is in expression evaluator PR for Scala IDE (https://github.com/scala-ide/scala-ide/pull/906/files#diff-2dbb5006e81b31769258a37f8cc7016eR50)

Stack trace:

java.lang.IndexOutOfBoundsException: 0
	at scala.collection.LinearSeqOptimized$class.apply(LinearSeqOptimized.scala:65)
	at scala.collection.immutable.List.apply(List.scala:84)
	at scala.reflect.internal.Importers$StandardImporter.recreateOrRelink$1(Importers.scala:170)
	at scala.reflect.internal.Importers$StandardImporter.importSymbol(Importers.scala:210)
	at scala.reflect.internal.Importers$StandardImporter$$anonfun$recreateType$3.apply(Importers.scala:232)
	at scala.reflect.internal.Importers$StandardImporter$$anonfun$recreateType$3.apply(Importers.scala:232)
	at scala.collection.immutable.List.map(List.scala:273)
	at scala.reflect.internal.Importers$StandardImporter.recreateType(Importers.scala:232)
	at scala.reflect.internal.Importers$StandardImporter.importType(Importers.scala:284)
	at scala.reflect.internal.Importers$StandardImporter.recreatedTreeCompleter(Importers.scala:304)
	at scala.reflect.internal.Importers$StandardImporter$$anonfun$importTree$1.apply$mcV$sp(Importers.scala:417)
	at scala.reflect.internal.Importers$StandardImporter.tryFixup(Importers.scala:49)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:418)
	at scala.reflect.internal.Importers$StandardImporter.recreateTree(Importers.scala:367)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:415)
	at scala.reflect.internal.Importers$StandardImporter.recreateTree(Importers.scala:374)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:415)
	at scala.reflect.internal.Importers$StandardImporter.recreateTree(Importers.scala:333)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:415)
	at scala.reflect.internal.Importers$StandardImporter.recreateTree(Importers.scala:333)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:415)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:29)
	at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$$anonfun$typecheck$2.apply(ToolBoxFactory.scala:376)
	at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$$anonfun$typecheck$2.apply(ToolBoxFactory.scala:367)
	at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.liftedTree2$1(ToolBoxFactory.scala:355)
	at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.apply(ToolBoxFactory.scala:355)
	at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.typecheck(ToolBoxFactory.scala:367)
	at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.typecheck(ToolBoxFactory.scala:27)
	at org.scalaide.debug.internal.expression.proxies.phases.TypeCheck.doTypeCheck$1(TypeCheck.scala:44)
	at org.scalaide.debug.internal.expression.proxies.phases.TypeCheck.transform(TypeCheck.scala:46)
	at org.scalaide.debug.internal.expression.ExpressionEvaluator$$anonfun$1.apply(ExpressionEvaluator.scala:152)
	at org.scalaide.debug.internal.expression.ExpressionEvaluator$$anonfun$1.apply(ExpressionEvaluator.scala:146)
	at scala.collection.LinearSeqOptimized$class.foldLeft(LinearSeqOptimized.scala:124)
	at scala.collection.immutable.List.foldLeft(List.scala:84)
	at org.scalaide.debug.internal.expression.ExpressionEvaluator.org$scalaide$debug$internal$expression$ExpressionEvaluator$$transform(ExpressionEvaluator.scala:146)
	at org.scalaide.debug.internal.expression.ExpressionEvaluator$$anonfun$compileExpression$1.apply(ExpressionEvaluator.scala:80)
	at org.scalaide.debug.internal.expression.ExpressionEvaluator$$anonfun$compileExpression$1.apply(ExpressionEvaluator.scala:73)
	at scala.util.Try$.apply(Try.scala:191)
	at org.scalaide.debug.internal.expression.ExpressionEvaluator.compileExpression(ExpressionEvaluator.scala:73)
	at org.scalaide.debug.internal.expression.JdiExpressionEvaluator.apply(JdiExpressionEvaluator.scala:61)
	... 53 more

scabug avatar Mar 12 '15 15:03 scabug

Imported From: https://issues.scala-lang.org/browse/SI-9218?orig=1 Reporter: Jerzy Muller (keros) Affected Versions: 2.11.5

scabug avatar Mar 12 '15 15:03 scabug

@retronym said: Is the error intermittent or deterministic?

I would recommend to add a better diagnostic message in that part of Importers when the number of type parameters of the recreated symbol doesn't match the number of type args in the imported type. This might be a symbol initialization bug; try calling symbol.initialize to force this (Symbol#typeParams does not force it IIRC)

scabug avatar Mar 12 '15 21:03 scabug

Jerzy Muller (keros) said: It is deterministic - every time I run a full test suite one test fail on this.The test itself compiles some code using toolbox, in this case call to generic Java method:

public <T> T genericMethod(T x) {
  return x;
}

I'll try to debug the cause of this later, it have to be some corrupted state in Toolbox, as running this test alone works fine.

scabug avatar Mar 12 '15 22:03 scabug

Here's a standalone reproduction of a bug with the same symptom.

==> test/files/run/macro-eval-importer-crash/A_1.scala <==
package com.acme

class Predicate[A, B] {
  self => // self type needed to trigger the bug
}

object Predicate {
  def FALSE: Predicate[Any, Boolean] = new Predicate
}

==> test/files/run/macro-eval-importer-crash/Macro_2.scala <==
import scala.reflect.macros.blackbox.Context

object M {
  def apply(a: Any): Unit = macro impl
  def impl(c: Context)(a: c.Tree): c.Tree = {
    c.eval(c.Expr(c.untypecheck(a)))
    import c.universe._
    Literal(Constant(()))
  }
}

==> test/files/run/macro-eval-importer-crash/Client_3.scala <==
object Test {
  def main(args: Array[String]): Unit = {
    com.acme.M.apply(com.acme.Predicate.FALSE)
  }
}
~/scala/2.11.8/bin/scalac -cp /tmp -d /tmp test/files/run/macro-eval-importer-crash/Client_3.scala
test/files/run/macro-eval-importer-crash/Client_3.scala:3: error: exception during macro expansion:
java.lang.IndexOutOfBoundsException: 0
	at scala.collection.LinearSeqOptimized$class.apply(LinearSeqOptimized.scala:65)
	at scala.collection.immutable.List.apply(List.scala:84)
	at scala.reflect.internal.Importers$StandardImporter.recreateOrRelink$1(Importers.scala:170)
	at scala.reflect.internal.Importers$StandardImporter.importSymbol(Importers.scala:210)
	at scala.reflect.internal.Importers$StandardImporter.recreateType(Importers.scala:224)
	at scala.reflect.internal.Importers$StandardImporter.importType(Importers.scala:284)
	at scala.reflect.internal.Importers$StandardImporter$$anonfun$recreateType$1.apply(Importers.scala:224)
	at scala.reflect.internal.Importers$StandardImporter$$anonfun$recreateType$1.apply(Importers.scala:224)
	at scala.collection.immutable.List.map(List.scala:273)
	at scala.reflect.internal.Importers$StandardImporter.recreateType(Importers.scala:224)
	at scala.reflect.internal.Importers$StandardImporter.importType(Importers.scala:284)
	at scala.reflect.internal.Importers$StandardImporter.recreateSymbol(Importers.scala:128)
	at scala.reflect.internal.Importers$StandardImporter.scala$reflect$internal$Importers$StandardImporter$$cachedRecreateSymbol$1(Importers.scala:145)
	at scala.reflect.internal.Importers$StandardImporter.recreateOrRelink$1(Importers.scala:193)
	at scala.reflect.internal.Importers$StandardImporter.importSymbol(Importers.scala:210)
	at scala.reflect.internal.Importers$StandardImporter$$anonfun$recreateType$4.apply(Importers.scala:248)
	at scala.reflect.internal.Importers$StandardImporter$$anonfun$recreateType$4.apply(Importers.scala:248)
	at scala.reflect.internal.Scopes$Scope.foreach(Scopes.scala:373)
	at scala.reflect.internal.Importers$StandardImporter.recreateType(Importers.scala:248)
	at scala.reflect.internal.Importers$StandardImporter.importType(Importers.scala:284)
	at scala.reflect.internal.Importers$StandardImporter$$anon$1.complete(Importers.scala:75)
	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1514)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$1.scala$reflect$runtime$SynchronizedSymbols$SynchronizedSymbol$$super$info(SynchronizedSymbols.scala:174)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anonfun$info$1.apply(SynchronizedSymbols.scala:127)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anonfun$info$1.apply(SynchronizedSymbols.scala:127)
	at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19)
	at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$class.gilSynchronizedIfNotThreadsafe(SynchronizedSymbols.scala:123)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$1.gilSynchronizedIfNotThreadsafe(SynchronizedSymbols.scala:174)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$class.info(SynchronizedSymbols.scala:127)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$1.info(SynchronizedSymbols.scala:174)
	at scala.reflect.internal.Importers$StandardImporter.recreateOrRelink$1(Importers.scala:167)
	at scala.reflect.internal.Importers$StandardImporter.importSymbol(Importers.scala:210)
	at scala.reflect.internal.Importers$StandardImporter.recreatedTreeCompleter(Importers.scala:298)
	at scala.reflect.internal.Importers$StandardImporter$$anonfun$importTree$1.apply$mcV$sp(Importers.scala:417)
	at scala.reflect.internal.Importers$StandardImporter.tryFixup(Importers.scala:49)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:418)
	at scala.reflect.internal.Importers$StandardImporter.recreateTree(Importers.scala:383)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:415)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:29)
	at scala.reflect.macros.contexts.Evals$class.eval(Evals.scala:19)
	at scala.reflect.macros.contexts.Context.eval(Context.scala:6)
	at com.acme.M$.impl(Macro_2.scala:9)

    com.acme.M.apply(com.acme.Predicate.FALSE)
                    ^
one error found

The code creates the new class symbol for Predicate in the to symbol table of the importer, but only later assigns its info. It first tries to import the self type and assign this to typeOfThis_=. The self type import recursively needs to import the type parameters of from::Predicate which call to::Predicate.info.typeParams to find the corresponding parameter. This returns Nil because of the info eq null check in isMonorphicType.

This is minimized from https://github.com/fthomas/refined/issues/3

import eu.timepit.refined._
import eu.timepit.refined.numeric._
import shapeless.nat._

object Test {
  refineLit[Greater[_10]](15)
}
~/scala/2.11.8/bin/scalac -cp /Users/jz/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.11/bundles/scala-parser-combinators_2.11-1.0.3.jar:/Users/jz/.ivy2/cache/com.chuusai/shapeless_2.11/bundles/shapeless_2.11-2.2.0.jar:/Users/jz/code/refined/target/scala-2.11/refined_2.11-0.0.3-SNAPSHOT.jar /tmp/test.scala

.. a bug which still has a workaround in refined. https://github.com/fthomas/refined/issues/260 describes a different bug in the same area.

The error goes away sometime between Scala 2.12.0-M3 and 2.12.0-M4. The biggest change to land in that time is the new trait encoding. I don't see relevant changes to Importers itself.

retronym avatar Dec 13 '19 03:12 retronym

Something like:

diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala
index 494f62af06..b2b0ebe551 100644
--- a/src/reflect/scala/reflect/internal/Importers.scala
+++ b/src/reflect/scala/reflect/internal/Importers.scala
@@ -78,6 +78,13 @@ trait Importers { to: SymbolTable =>
             }
             my setInfo GenPolyType(mytypeParams, importType(theirCore))
             my setAnnotations (their.annotations map importAnnotationInfo)
+            their match {
+              case _: ClassSymbol =>
+                if (their.thisSym != their) {
+                  my.typeOfThis = importType(their.typeOfThis)
+                  my.thisSym setName importName(their.thisSym.name)
+                }
+            }
             markAllCompleted(my)
           }
         }
@@ -124,10 +131,6 @@ trait Importers { to: SymbolTable =>
         case their: from.ClassSymbol =>
           val my = myowner.newClassSymbol(myname.toTypeName, mypos, myflags)
           symMap.weakUpdate(their, my)
-          if (their.thisSym != their) {
-            my.typeOfThis = importType(their.typeOfThis)
-            my.thisSym setName importName(their.thisSym.name)
-          }
           my.associatedFile = their.associatedFile
           my
         case their: from.TypeSymbol =>

seems better to me.

retronym avatar Dec 13 '19 05:12 retronym

I encounter something similar in a macro expansion:

exception during macro expansion: 
java.lang.IndexOutOfBoundsException: 0
	at scala.collection.LinearSeqOps.apply(LinearSeq.scala:117)
	at scala.collection.LinearSeqOps.apply$(LinearSeq.scala:114)
	at scala.reflect.internal.Importers$StandardImporter.recreateOrRelink$1(Importers.scala:183)
	at scala.reflect.internal.Importers$StandardImporter.importSymbol(Importers.scala:223)
	at scala.reflect.internal.Importers$StandardImporter.recreateType(Importers.scala:237)
	at scala.reflect.internal.Importers$StandardImporter.importType(Importers.scala:298)
	at scala.reflect.internal.Importers$StandardImporter.recreateType(Importers.scala:237)
	at scala.reflect.internal.Importers$StandardImporter.importType(Importers.scala:298)
	at scala.reflect.internal.Importers$StandardImporter.recreateSymbol(Importers.scala:141)
	at scala.reflect.internal.Importers$StandardImporter.cachedRecreateSymbol$1(Importers.scala:158)
	at scala.reflect.internal.Importers$StandardImporter.$anonfun$importSymbol$6(Importers.scala:207)
	at scala.reflect.internal.Symbols$Symbol.orElse(Symbols.scala:2644)
	at scala.reflect.internal.Importers$StandardImporter.recreateOrRelink$1(Importers.scala:206)
	at scala.reflect.internal.Importers$StandardImporter.importSymbol(Importers.scala:223)
	at scala.reflect.internal.Importers$StandardImporter.$anonfun$recreateType$5(Importers.scala:261)
	at scala.reflect.internal.Scopes$Scope.foreach(Scopes.scala:455)
	at scala.reflect.internal.Importers$StandardImporter.recreateType(Importers.scala:261)
	at scala.reflect.internal.Importers$StandardImporter.importType(Importers.scala:298)
	at scala.reflect.internal.Importers$StandardImporter$$anon$3.complete(Importers.scala:91)
	at scala.reflect.internal.Symbols$Symbol.completeInfo(Symbols.scala:1568)
	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1531)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$9.scala$reflect$runtime$SynchronizedSymbols$SynchronizedSymbol$$super$info(SynchronizedSymbols.scala:209)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol.info(SynchronizedSymbols.scala:158)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol.info$(SynchronizedSymbols.scala:158)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$9.info(SynchronizedSymbols.scala:209)
	at scala.reflect.internal.Importers$StandardImporter.recreateOrRelink$1(Importers.scala:180)
	at scala.reflect.internal.Importers$StandardImporter.importSymbol(Importers.scala:223)
	at scala.reflect.internal.Importers$StandardImporter.recreatedTreeCompleter(Importers.scala:312)
	at scala.reflect.internal.Importers$StandardImporter.$anonfun$importTree$1(Importers.scala:432)
	at scala.reflect.internal.Importers$StandardImporter.tryFixup(Importers.scala:61)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:433)
	at scala.reflect.internal.Importers$StandardImporter.recreateTree(Importers.scala:397)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:430)
	at scala.reflect.internal.Importers$StandardImporter.recreateTree(Importers.scala:381)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:430)
	at scala.reflect.internal.Importers$StandardImporter.recreateTree(Importers.scala:388)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:430)
	at scala.reflect.internal.Importers$StandardImporter.recreateTree(Importers.scala:379)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:430)
	at scala.reflect.internal.Importers$StandardImporter.recreateTree(Importers.scala:397)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:430)
	at scala.reflect.internal.Importers$StandardImporter.importTree(Importers.scala:41)
	at scala.reflect.macros.contexts.Evals.eval(Evals.scala:31)
	at scala.reflect.macros.contexts.Evals.eval$(Evals.scala:26)
	at scala.reflect.macros.contexts.Context.eval(Context.scala:18)

But if compiled with bloop & metals this problem disappeared. Have you tried the same?

tribbloid avatar Apr 04 '21 03:04 tribbloid