Skip to content
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

[toolbox] IndexOutOfBoundsException from StandardImporter.recreateOrRelink #9218

Open
scabug opened this issue Mar 12, 2015 · 6 comments
Open
Milestone

Comments

@scabug
Copy link

scabug commented Mar 12, 2015

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
Copy link
Author

scabug commented Mar 12, 2015

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

@scabug
Copy link
Author

scabug commented Mar 12, 2015

@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
Copy link
Author

scabug commented Mar 12, 2015

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.

@retronym
Copy link
Member

retronym commented Dec 13, 2019

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 fthomas/refined#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. fthomas/refined#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
Copy link
Member

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.

@tribbloid
Copy link

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants