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

Intermittent assertion failure in genLoadIdent: temporary value created by patmat disappearing from scope #9264

Closed
scabug opened this issue Apr 7, 2015 · 35 comments
Assignees

Comments

@scabug
Copy link

scabug commented Apr 7, 2015

From PR validation (scala/scala#4376 (comment)):

That assertion error is the same one that @gkossakowski's encountered while working on the SBT build. When we also saw it during PR validation, I added (https://github.com/scala/scala/pull/4397) an extended diagnostic error to the assertion in the hope we would see it again.

Now, to make sense of this:
[quick.compiler] error: symbol value x2#803320 does not exist in scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen.AdaptTypeError, which contains locals value x1#803317,value foundType#508052,value req#508050,value found#508049,value tree#508048
[quick.compiler] error: scala.reflect.internal.FatalError: symbol value x2#803320 does not exist in scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen.AdaptTypeError, which contains locals value x1#803317,value foundType#508052,value req#508050,value found#508049,value tree#508048
@scabug
Copy link
Author

scabug commented Apr 7, 2015

Imported From: https://issues.scala-lang.org/browse/SI-9264?orig=1
Reporter: @retronym
Affected Versions: 2.11.2
See #8283, #3971

@scabug
Copy link
Author

scabug commented Apr 7, 2015

@retronym said (edited on Apr 7, 2015 1:50:39 AM UTC):
Here's what I see from that method:

      def AdaptTypeError(tree: Tree, found: Type, req: Type) = {
        // SI-3971 unwrapping to the outermost Apply helps prevent confusion with the
        // error message point.
        def callee = {
          def unwrap(t: Tree): Tree = t match {
            case Apply(app: Apply, _) => unwrap(app)
            case _                    => t
          }
          unwrap(tree)
        }

        // If the expected type is a refinement type, and the found type is a refinement or an anon
        // class, we can greatly improve the error message by retyping the tree to recover the actual
        // members present, then display along with the expected members. This is done here because
        // this is the last point where we still have access to the original tree, rather than just
        // the found/req types.
        val foundType: Type = req.dealiasWiden match {
          case RefinedType(parents, decls) if !decls.isEmpty && found.typeSymbol.isAnonOrRefinementClass =>
            val retyped    = typed (tree.duplicate.clearType())
            val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic)
            if (foundDecls.isEmpty || (found.typeSymbol eq NoSymbol)) found
            else {
              // The members arrive marked private, presumably because there was no
              // expected type and so they're considered members of an anon class.
              foundDecls foreach (_.makePublic)
              // TODO: if any of the found parents match up with required parents after normalization,
              // print the error so that they match. The major beneficiary there would be
              // java.lang.Object vs. AnyRef.
              refinedType(found.parents, found.typeSymbol.owner, foundDecls, tree.pos)
            }
          case _ =>
            found
        }
        assert(!foundType.isErroneous && !req.isErroneous, (foundType, req))

        issueNormalTypeError(callee, withAddendum(callee.pos)(typeErrorMsg(foundType, req)))
        infer.explainTypes(foundType, req)
      }
% qscalac -Xprint:jvm /Users/jason/code/scala3/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala | grep --context=100 'def AdaptTypeError'
...
      def AdaptTypeError(tree: reflect.internal.Trees$Tree, found: reflect.internal.Types$Type, req: reflect.internal.Types$Type): Unit = {
        val foundType: reflect.internal.Types$Type = {
          case <synthetic> val x1: reflect.internal.Types$Type = req.dealiasWiden();
          case5(){
            if (x1.$isInstanceOf[reflect.internal.Types$RefinedType]())
              {
                <synthetic> val x2: reflect.internal.Types$RefinedType = (x1.$asInstanceOf[reflect.internal.Types$RefinedType](): reflect.internal.Types$RefinedType);
                {
                  val decls: reflect.internal.Scopes$Scope = x2.decls();
                  if (decls.isEmpty().unary_!().&&(found.typeSymbol().isAnonOrRefinementClass()))
                    matchEnd4({
                      val retyped: reflect.internal.Trees$Tree = ContextErrors$TyperContextErrors$TyperErrorGen.this.$outer.typed(tree.duplicate().clearType());
                      val foundDecls: reflect.internal.Scopes$Scope = retyped.tpe().decls().filter({
                        (new <$anon: Function1>(ContextErrors$TyperContextErrors$TyperErrorGen.this): Function1)
                      });
                      if (foundDecls.isEmpty().||(found.typeSymbol().eq(ContextErrors$TyperContextErrors$TyperErrorGen.this.$outer.$outer().$asInstanceOf[tools.nsc.typechecker.Analyzer]().global().NoSymbol())))
                        found
                      else
                        {
                          foundDecls.foreach({
                            (new <$anon: Function1>(ContextErrors$TyperContextErrors$TyperErrorGen.this): Function1)
                          });
                          ContextErrors$TyperContextErrors$TyperErrorGen.this.$outer.$outer().$asInstanceOf[tools.nsc.typechecker.Analyzer]().global().refinedType(found.parents(), found.typeSymbol().owner(), foundDecls, tree.pos())
                        }
                    })
                  else
                    case6()
                }
              }
            else
              case6()
          };
          case6(){
            matchEnd4(found)
          };
          matchEnd4(x: reflect.internal.Types$Type){
            x
          }
        };
        ContextErrors$TyperContextErrors$TyperErrorGen.this.$outer.$outer().$asInstanceOf[tools.nsc.typechecker.Analyzer]().global().assert(foundType.isErroneous().unary_!().&&(req.isErroneous().unary_!()), {
          (new <$anon: Function0>(ContextErrors$TyperContextErrors$TyperErrorGen.this, req, foundType): Function0)
        });
        ContextErrors$TyperContextErrors$TyperErrorGen.this.$outer.$outer().ErrorUtils().issueNormalTypeError(ContextErrors$TyperContextErrors$TyperErrorGen.this.callee$1(tree), ContextErrors$TyperContextErrors$TyperErrorGen.this.$outer.$outer().$asInstanceOf[tools.nsc.typechecker.TypeDiagnostics]().withAddendum(ContextErrors$TyperContextErrors$TyperErrorGen.this.callee$1(tree).pos()).apply(ContextErrors$TyperContextErrors$TyperErrorGen.this.$outer.$outer().ErrorUtils().typeErrorMsg(foundType, req)).$asInstanceOf[String](), ContextErrors$TyperContextErrors$TyperErrorGen.this.contextTyperErrorGen());
        ContextErrors$TyperContextErrors$TyperErrorGen.this.$outer.infer().explainTypes(foundType, req)
      };

@scabug
Copy link
Author

scabug commented Apr 7, 2015

@retronym said:
One hypothesis is that the pattern matcher intermittently fails to emit the ValDef for the temporary in the first place.

By introducing such a fault, we can exhibit the same failure mode:

git diff head -- src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala
index 06b39b0..a470c4f 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala
@@ -216,7 +216,7 @@ trait MatchCodeGen extends Interface {
         def flatMapCond(cond: Tree, res: Tree, nextBinder: Symbol, next: Tree): Tree = {
           val rest = (
             // only emit a local val for `nextBinder` if it's actually referenced in `next`
-            if (next.exists(_.symbol eq nextBinder))
+            if (next.exists(_.symbol eq nextBinder) && math.random > .01)
               BLOCK(ValDef(nextBinder, res), next)
             else next
           )
% qscalac -d /tmp -optimize $(find src/scalap/ -name '*.scala')
error: symbol value x2#77162 does not exist in scala.tools.scalap.scalax.rules.scalasig.ScalaSigPrinter.printModifiers, which contains locals value x1#77152,value x#77164,value x1#77161,value symbol#71698
error: scala.reflect.internal.FatalError: symbol value x2#77162 does not exist in scala.tools.scalap.scalax.rules.scalasig.ScalaSigPrinter.printModifiers, which contains locals value x1#77152,value x#77164,value x1#77161,value symbol#71698
	at scala.reflect.internal.Reporting$class.abort(Reporting.scala:59)

@scabug
Copy link
Author

scabug commented Apr 7, 2015

@retronym said:
Both times I've seen this in PR validation have been in the validate-test job. This uses the compiler built by publish-core as STARR.

This suggests that the bug might have been introduced between v2.11.6..2.11.x.

@scabug
Copy link
Author

scabug commented Apr 7, 2015

@retronym said:
/cc @adriaanm for brainstorming...

@scabug
Copy link
Author

scabug commented Apr 7, 2015

@gkossakowski said:
More diagnostics added by scala/scala#4432

@scabug
Copy link
Author

scabug commented Apr 9, 2015

@adriaanm said:
One thing we could do to narrow it down is to use different prefixes for freshSym, instead of "x". I suspected patmat's CSE, but it introduces "rc" variables and none were spotted around the crime scene.

@scabug
Copy link
Author

scabug commented Apr 9, 2015

@retronym said (edited on Apr 9, 2015 12:38:45 AM UTC):
I wonder if it is in the logic that avoids emitting a binder if it doesn't find a reference to it in the case body (that's what I tweaked in my intentional failure above in flatMapCond.)

Maybe scala/scala#4274 is involved?

@scabug
Copy link
Author

scabug commented Apr 9, 2015

@retronym said:
Adriaan notes that the extended diagnostics fired into action in https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/596/console

error: scala.reflect.internal.FatalError: symbol value x2#820443 does not exist in scala.tools.nsc.typechecker.Implicits$ImplicitSearch.ypechecker$Implicits$ImplicitSearch$$implicitsOfExpectedType, which contains locals value x#820447,value x1#820442.
Method code: private def implicitsOfExpectedType(): Implicits.this.Infoss = {
  if (scala.reflect.internal.util.Statistics.canEnable())
    scala.reflect.internal.util.Statistics.incCounter(ImplicitsStats.implicitCacheAccs())
  else
    ();
  {
    case val x1: Option#860 = ImplicitSearch.this.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$$outer().implicitsCache().get(is.pt);
    case7(){
      if (x1.$isInstanceOf[Some#2435]())
        matchEnd6({
          if (scala.reflect.internal.util.Statistics.canEnable())
            scala.reflect.internal.util.Statistics.incCounter(ImplicitsStats.implicitCacheHits())
          else
            ();
          x2.x().$asInstanceOf[List#39836]()
        })
      else
        case8()
    };

Note that the tree case val x2 = x1.asInstanceOf[Some] is missing.

@scabug
Copy link
Author

scabug commented Apr 14, 2015

@adriaanm said:
It looks like this goes all the way back to 2.11.0, based on https://groups.google.com/forum/#!topic/scala-internals/trzjEv-D53U

The log is no longer available, but from the thread I infer it was using af7cf11:

From af7cf11f07581bf92628c82b7bf2cf3cca3e32c9 Mon Sep 17 00:00:00 2001
From: Adriaan Moors <adriaan.moors@typesafe.com>
Date: Fri, 14 Feb 2014 14:08:01 -0800
Subject: [PATCH] Merge pull request #3533 from adriaanm/t8283

SI-8283 mutation-free bound inference for existentials

The oldest actual log I could find is at https://scala-webapps.epfl.ch/jenkins/job/scala-nightly-main-2.11.x/81/, for 50167e3f1d (2.11.2-ish).

I grepped the jenkins logs on scala-ci (the new CI). It occurs in the core build job as well as the test suite, both in quick and locker. Scrolling will reveal URLs etc:

symbol value x2 does not exist in scala.tools.nsc.typechecker.Contexts$Context.implicitss                                                                                                                                                                                                     https://scala-ci.typesafe.com/job/scala-2.11.x-validate-publish-core/789/consoleText  [locker.compiler]
symbol value x2 does not exist in scala.tools.nsc.typechecker.Contexts$Context.implicitss                                                                                                                                                                                                     https://scala-ci.typesafe.com/job/scala-2.11.x-validate-publish-core/789/consoleText  [locker.compiler]
symbol value x2 does not exist in scala.tools.nsc.typechecker.Implicits$ImplicitSearch.isImpossibleSubType                                                                                                                                                                                    https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/435/consoleText          [quick.compiler] 
symbol value x2 does not exist in scala.tools.nsc.typechecker.Implicits$ImplicitSearch.isImpossibleSubType                                                                                                                                                                                    https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/435/consoleText          [quick.compiler] 
symbol value x2#803320 does not exist in scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen.AdaptTypeError, which contains locals value x1#803317,value foundType#508052,value req#508050,value found#508049,value tree#508048                                        https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/568/consoleText          [quick.compiler] 
symbol value x2#803320 does not exist in scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen.AdaptTypeError, which contains locals value x1#803317,value foundType#508052,value req#508050,value found#508049,value tree#508048                                        https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/568/consoleText          [quick.compiler] 
symbol value x2#807114 does not exist in scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen.AdaptTypeError, which contains locals value x1#807111,value foundType#511891,value req#511889,value found#511888,value tree#511887                                        https://scala-ci.typesafe.com/job/scala-2.11.x-validate-publish-core/815/consoleText  [quick.compiler] 
symbol value x2#807114 does not exist in scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen.AdaptTypeError, which contains locals value x1#807111,value foundType#511891,value req#511889,value found#511888,value tree#511887                                        https://scala-ci.typesafe.com/job/scala-2.11.x-validate-publish-core/815/consoleText  [quick.compiler] 
symbol value x2#807259 does not exist in scala.tools.nsc.transform.patmat.Solving$Solver$class.findTseitinModelFor, which contains locals value unitLit#507616,value x#807262,value x1#807258,value satisfiableWithModel#507095,value start#507094,value clauses#1148776,value $this#1250982. https://scala-ci.typesafe.com/job/scala-2.11.x-validate-publish-core/917/consoleText  [quick.compiler] 
symbol value x2#807259 does not exist in scala.tools.nsc.transform.patmat.Solving$Solver$class.findTseitinModelFor, which contains locals value unitLit#507616,value x#807262,value x1#807258,value satisfiableWithModel#507095,value start#507094,value clauses#1148776,value $this#1250982. https://scala-ci.typesafe.com/job/scala-2.11.x-validate-publish-core/917/consoleText  [quick.compiler] 
symbol value x2#811892 does not exist in scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$implicitsOfExpectedType, which contains locals value x#811896,value x1#811891                                                             https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/508/consoleText          [quick.compiler] 
symbol value x2#811892 does not exist in scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$implicitsOfExpectedType, which contains locals value x#811896,value x1#811891                                                             https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/508/consoleText          [quick.compiler] 
symbol value x2#820443 does not exist in scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$implicitsOfExpectedType, which contains locals value x#820447,value x1#820442.                                                            https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/596/consoleText          [quick.compiler] 
symbol value x2#820443 does not exist in scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$implicitsOfExpectedType, which contains locals value x#820447,value x1#820442.                                                            https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/596/consoleText          [quick.compiler] 
symbol value x4 does not exist in scala.tools.nsc.transform.patmat.MatchOptimization$SwitchEmission$SwitchMaker.scala$tools$nsc$transform$patmat$MatchOptimization$SwitchEmission$SwitchMaker$$patternImplies                                                                                 https://scala-ci.typesafe.com/job/scala-2.11.x-validate-publish-core/820/consoleText  [locker.compiler]
symbol value x4 does not exist in scala.tools.nsc.transform.patmat.MatchOptimization$SwitchEmission$SwitchMaker.scala$tools$nsc$transform$patmat$MatchOptimization$SwitchEmission$SwitchMaker$$patternImplies                                                                                 https://scala-ci.typesafe.com/job/scala-2.11.x-validate-publish-core/820/consoleText  [locker.compiler]
symbol value x5 does not exist in scala.tools.nsc.typechecker.DestructureTypes$DestructureType$$anonfun$apply$1.apply                                                                                                                                                                         https://scala-ci.typesafe.com/job/scala-2.11.x-validate-publish-core/760/consoleText  [quick.compiler] 
symbol value x5 does not exist in scala.tools.nsc.typechecker.DestructureTypes$DestructureType$$anonfun$apply$1.apply                                                                                                                                                                         https://scala-ci.typesafe.com/job/scala-2.11.x-validate-publish-core/760/consoleText  [quick.compiler] 
symbol value x5#781214 does not exist in scala.tools.nsc.transform.patmat.MatchTranslation$MatchTranslator$PatternBoundToUnderscore.unapply, which contains locals variable eqEqTemp$4#1279646,value x#781237,variable eqEqTemp$3#1279642,value x2#781208,value x1#781206,value pat#484460    https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/588/consoleText          [quick.compiler] 
symbol value x5#781214 does not exist in scala.tools.nsc.transform.patmat.MatchTranslation$MatchTranslator$PatternBoundToUnderscore.unapply, which contains locals variable eqEqTemp$4#1279646,value x#781237,variable eqEqTemp$3#1279642,value x2#781208,value x1#781206,value pat#484460    https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/588/consoleText          [quick.compiler] 

2.11.6: https://scala-ci.typesafe.com/job/scala-2.11.x-validate-publish-core/789/consoleText

It occurs on EPFL's CI as well, so not some freaky VM thing only seen on EC2: https://scala-webapps.epfl.ch/jenkins/job/scala-checkin/9771/consoleFull d7835d62cf, 2.11.3ish

I checked all scala-checkin builds older than 9771 and could find no mention of "symbol value .* does not exist in", so it must have been introduced in that period.*

/data/tomcat/.hudson/jobs/scala-checkin/builds$ grep "symbol value .* does not exist in" 10???/log
10239/log:[locker.compiler] error: symbol value x3 does not exist in scala.tools.nsc.typechecker.Infer$Inferencer.isAsSpecific
10239/log:[locker.compiler] error: scala.reflect.internal.FatalError: symbol value x3 does not exist in scala.tools.nsc.typechecker.Infer$Inferencer.isAsSpecific
10252/log:[quick.compiler] error: symbol value x5#790503 does not exist in scala.tools.nsc.transform.patmat.MatchOptimization$SwitchEmission$RegularSwitchMaker.isDefault, which contains locals variable eqEqTemp$16#1288588,value x1#790497,value x#494859.
10252/log:[quick.compiler] error: scala.reflect.internal.FatalError: symbol value x5#790503 does not exist in scala.tools.nsc.transform.patmat.MatchOptimization$SwitchEmission$RegularSwitchMaker.isDefault, which contains locals variable eqEqTemp$16#1288588,value x1#790497,value x#494859.
10269/log:[quick.compiler] error: symbol value x2#803110 does not exist in scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen.AdaptTypeError, which contains locals value x1#803107,value foundType#509247,value req#509245,value found#509244,value tree#509243
10269/log:[quick.compiler] error: scala.reflect.internal.FatalError: symbol value x2#803110 does not exist in scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen.AdaptTypeError, which contains locals value x1#803107,value foundType#509247,value req#509245,value found#509244,value tree#509243
10275/log:[quick.compiler] error: symbol value x2#804218 does not exist in scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen.MissingParameterTypeError, which contains locals value x1#804215,value withTupleAddendum#510505,value pt#510504,value vparam#510503,value fun#510502.
10275/log:[quick.compiler] error: scala.reflect.internal.FatalError: symbol value x2#804218 does not exist in scala.tools.nsc.typechecker.ContextErrors$TyperContextErrors$TyperErrorGen.MissingParameterTypeError, which contains locals value x1#804215,value withTupleAddendum#510505,value pt#510504,value vparam#510503,value fun#510502.
10333/log:[quick.compiler] error: symbol value x2#802590 does not exist in scala.tools.nsc.typechecker.EtaExpansion$class.liftoutPrefix$1, which contains locals value x#802614,value x1#802587,value tree1#516629,value typer$1#1192802,value unit$1#1192801,value defs$1#1192800,value cnt$1#1192799,value tree#516627,value $this#1242702
10333/log:[quick.compiler] error: scala.reflect.internal.FatalError: symbol value x2#802590 does not exist in scala.tools.nsc.typechecker.EtaExpansion$class.liftoutPrefix$1, which contains locals value x#802614,value x1#802587,value tree1#516629,value typer$1#1192802,value unit$1#1192801,value defs$1#1192800,value cnt$1#1192799,value tree#516627,value $this#1242702
10394/log:[locker.compiler] error: symbol value x5 does not exist in scala.tools.nsc.typechecker.DestructureTypes$DestructureType$$anonfun$apply$1.apply
10394/log:[locker.compiler] error: scala.reflect.internal.FatalError: symbol value x5 does not exist in scala.tools.nsc.typechecker.DestructureTypes$DestructureType$$anonfun$apply$1.apply

Here are some older builds of other jobs

/data/tomcat/.hudson/jobs/scala-nightly-main-2.11.x/builds$ grep "symbol value .* does not exist in" */log
296/log:[strap.compiler] error: symbol value x2 does not exist in scala.tools.nsc.transform.patmat.Solving$Solver$class.findTseitinModelFor
296/log:[strap.compiler] error: scala.reflect.internal.FatalError: symbol value x2 does not exist in scala.tools.nsc.transform.patmat.Solving$Solver$class.findTseitinModelFor
81/log:[strap.compiler] error: symbol value x4 does not exist in scala.tools.nsc.transform.patmat.MatchOptimization$SwitchEmission$SwitchMaker.scala$tools$nsc$transform$patmat$MatchOptimization$SwitchEmission$SwitchMaker$$patternImplies
81/log:[strap.compiler] error: scala.reflect.internal.FatalError: symbol value x4 does not exist in scala.tools.nsc.transform.patmat.MatchOptimization$SwitchEmission$SwitchMaker.scala$tools$nsc$transform$patmat$MatchOptimization$SwitchEmission$SwitchMaker$$patternImplies

@scabug
Copy link
Author

scabug commented Apr 14, 2015

@adriaanm said (edited on Apr 14, 2015 8:12:41 PM UTC):
Below are all hits on EPFL's CI, newest first.

With relevant snippets: https://gist.github.com/adriaanm/6b2acc9c37b13e0f9731

64K Apr 14 14:29 https://scala-webapps.epfl.ch/jenkins/job/scala-checkin/10394/consoleFull
384K Apr 14 04:09 https://scala-webapps.epfl.ch/jenkins/job/scala-nightly-checkinit-2.11.x/347/consoleFull
70K Apr 13 18:46 https://scala-webapps.epfl.ch/jenkins/job/scala-checkin/10333/consoleFull
70K Apr 10 15:36 https://scala-webapps.epfl.ch/jenkins/job/scala-checkin/10269/consoleFull
72K Apr 10 15:35 https://scala-webapps.epfl.ch/jenkins/job/scala-checkin/10275/consoleFull
71K Apr 10 12:52 https://scala-webapps.epfl.ch/jenkins/job/scala-checkin/10252/consoleFull
408K Mar 14 06:00 https://scala-webapps.epfl.ch/jenkins/job/scala-nightly-main-2.11.x/296/consoleFull
67K Feb 19 21:17 https://scala-webapps.epfl.ch/jenkins/job/scala-checkin/10239/consoleFull
52K Feb 2 23:52 https://scala-webapps.epfl.ch/jenkins/job/pr-scala-publish-core/5211/consoleFull
102K Jan 22 03:20 https://scala-webapps.epfl.ch/jenkins/job/scala-nightly-checkinit-2.12.x/262/consoleFull
52K Jan 20 10:24 https://scala-webapps.epfl.ch/jenkins/job/scala-release-2.11.x/323/consoleFull
54K Jan 14 22:47 https://scala-webapps.epfl.ch/jenkins/job/pr-scala-publish-core/5096/consoleFull
24K Dec 26 04:25 https://scala-webapps.epfl.ch/jenkins/job/scala-release-2.11.x/298/consoleFull
352K Nov 12 06:02 https://scala-webapps.epfl.ch/jenkins/job/pr-scala-test-tmp/17/consoleFull
109K Nov 5 17:23 https://scala-webapps.epfl.ch/jenkins/job/scala-checkin/9771/consoleFull
105K Oct 26 02:50 https://scala-webapps.epfl.ch/jenkins/job/scala-nightly-rangepos-2.12.x/176/consoleFull
61K Oct 1 2014 https://scala-webapps.epfl.ch/jenkins/job/pr-scala-rangepos/7930/consoleFull
747K Aug 11 2014 https://scala-webapps.epfl.ch/jenkins/job/scala-nightly-main-2.11.x/81/consoleFull

@scabug
Copy link
Author

scabug commented Apr 14, 2015

@adriaanm said:
Out of 40K runs, this happened 18 times or less... Stupid question: could it be a sort of caching blip on trees/symbols?

@scabug
Copy link
Author

scabug commented Sep 16, 2015

Konrad Malawski (konrad.malawski) said:
FYI, this seems to happening rather often when trying to release Akka (2.3.x) using 2.11.7.

We are seeing a lot of errors like:

[error] (akka-remote/compile:compile) scala.reflect.internal.FatalError: symbol value x2#84606 does not exist in akka.remote.DefaultFailureDetectorRegistry.isAvailable, which contains locals value r#33196,value x1#84605,value resource#33158.
[error] Method code: final override def isAvailable(resource: A): scala.Boolean = {
[error]   case val x1: Option#1804 = DefaultFailureDetectorRegistry.this.resourceToFailureDetector().get().$asInstanceOf[collection#2621.MapLike#5620]().get(resource);
[error]   case6(){
[error]     if (x1.$isInstanceOf[Some#1306]())
[error]       {
[error]         val r: akka#23.remote#7146.FailureDetector#7694 = x2.x().$asInstanceOf[akka#23.remote#7146.FailureDetector#7694]();
[error]         matchEnd5(r.isAvailable())
[error]       }
[error]     else
[error]       case7()
[error]   };
[error]   case7(){
[error]     matchEnd5(true)
[error]   };
[error]   matchEnd5(x#84609: Boolean#2392){
[error]     x
[error]   }
[error] }

It happens repeatedly, most of the time actually, and makes releasing Akka 2.3.x quite troublesome.

To see more instances of this failure you can check out akka/akka@02898f3 and ;++2.11.7; compile.

@scabug
Copy link
Author

scabug commented Sep 16, 2015

Konrad Malawski (konrad.malawski) said:
I made an interesting observation, maybe helpful for you when investigating:
It failed almost each time on 2.11.7, however on 2.11.5 it fails very rarely (just managed to roll the release on .5).

@scabug
Copy link
Author

scabug commented Sep 18, 2015

@retronym said:
Thanks, [~konrad.malawski]. We struggled to reproduce this locally, it only seemed to show up on the CI servers (or on Greg's laptop!).

What JDK version where you using?

@scabug
Copy link
Author

scabug commented Sep 18, 2015

@retronym said:
Another recent occurence in Scala PR validation: https://scala-ci.typesafe.com/job/scala-2.11.x-validate-test/1246/console

@scabug
Copy link
Author

scabug commented Sep 25, 2015

@retronym said:
Ping [~konrad.malawski],

@scabug
Copy link
Author

scabug commented Sep 25, 2015

Konrad Malawski (konrad.malawski) said:
Whoops, sorry Jason - I thought I had replied.
I'm pretty sure this was on Java(TM) SE Runtime Environment (build 1.6.0_65-b14-466.1-11M4716) since we release that version of Akka on 1.6.

@scabug
Copy link
Author

scabug commented Sep 29, 2015

@retronym said (edited on Sep 29, 2015 6:45:58 AM UTC):
[~konrad.malawski] I haven't had any luck in doing so on my system, even by running the build over and over in a loop, or trying different JDK versions.

Just before you crammed onto that RyanAir flight, you were hoping to be able to reproduce the error on your laptop. Could you see if the problem still happens there? Does it happen on any of your CI machines?

Thanks for your help!

@scabug
Copy link
Author

scabug commented Sep 29, 2015

Konrad Malawski (konrad.malawski) said:
I'll hunt for a reproducer today, sorry for the delays Jason!

@scabug
Copy link
Author

scabug commented Sep 30, 2015

Konrad Malawski (konrad.malawski) said:
Been attempting to reproduce a few times, now running a release built (dry-run) in which I had this problem. Maybe it's related to "running the entire akka build", no idea, it's running now - will let you know if it fails.

@scabug
Copy link
Author

scabug commented Sep 30, 2015

@retronym said:
Perhaps you need to turn away from the screen as the build is running, inspired by https://www.youtube.com/watch?v=bHQ9eeDCbW8

@scabug
Copy link
Author

scabug commented Sep 30, 2015

Konrad Malawski (konrad.malawski) said:
Hell yeah, Super Mario 64 - had all stars on the N64 version :D
Hah, makes sense that you unlock him in the scary mansion :-)

// Yep, waiting...

@scabug
Copy link
Author

scabug commented Sep 30, 2015

Konrad Malawski (konrad.malawski) said:
Was unable to make it fail using diff scala versions over 10 runs or so... Will try again later,

@scabug
Copy link
Author

scabug commented Jan 27, 2016

@SethTisue said:
recently sighted in a Jenkins run on Windows, running strap.compiler: https://scala-ci.typesafe.com/job/scala-2.11.x-integrate-windows/142/console

@scabug
Copy link
Author

scabug commented Mar 29, 2016

@SethTisue said:
another one https://scala-ci.typesafe.com/job/scala-2.11.x-integrate-windows/199/consoleFull (but I'll stop here — the two-month interval gives some idea of the approximate frequency)

@scabug
Copy link
Author

scabug commented Nov 14, 2016

@SethTisue said (edited on Nov 14, 2016 3:57:04 PM UTC):
recently this started happening a great deal more often on Jenkins, during pull request validation. see scala/scala-dev#251

@scabug
Copy link
Author

scabug commented Dec 1, 2016

@retronym said:
I've run a build on Jenkins with -Xprint:patmat enabled to confirm that the missing ValDef tree is really missing from that juncture.

My working theory is that the problem is in the code guarded by if (!debugInfoEmitVars).

This is defined as:

protected val debugInfoEmitVars = !settings.optimise.value

Oops. That's false when in 2.12.0 after we've heeded the deprecation warning of -optimize and switched over to -opt:l:classpath.

Still not sure where the non-determinism stems from. The code in PreserveSubPatBinders uses hash sets, mutable collections.

Next steps:

  • Can we repro this on 2.12.x and/or Java 8 by setting debugInfoEmitVars=false ?
  • review/refactor PreserveSubPatBinders
  • add some assertions to the code, try to find the problem sooner.

@scabug
Copy link
Author

scabug commented Dec 7, 2016

@retronym said:
I've captured the pattern matcher debug log from translation of a pattern that ends up with a missing ValDef in the tree for a binder that is referenced.

https://gist.github.com/retronym/23b7ad0f8826b1883a15387b77891fb8

@scabug
Copy link
Author

scabug commented Dec 7, 2016

@retronym said:
That log output leads by to believe that we've got a codegen problem for method local lazy vals, and that we're getting multiple evaluation of lazy val typeTest in

      // example check: List[Int] <:< ::[Int]
      private def extractorStep(): TranslationStep = {
        def paramType = extractor.aligner.wholeType
        import extractor.treeMaker
        // chain a type-testing extractor before the actual extractor call
        // it tests the type, checks the outer pointer and casts to the expected type
        // TODO: the outer check is mandated by the spec for case classes, but we do it for user-defined unapplies as well [SPEC]
        // (the prefix of the argument passed to the unapply must equal the prefix of the type of the binder)
        lazy val typeTest = new TypeTestTreeMaker(binder, binder, paramType, paramType)(pos, extractorArgTypeTest = true)
        // check whether typetest implies binder is not null,
        // even though the eventual null check will be on typeTest.nextBinder
        // it'll be equal to binder casted to paramType anyway (and the type test is on binder)
        def extraction: TreeMaker = treeMaker(typeTest.nextBinder, typeTest impliesBinderNonNull binder, pos)

        // paramType = the type expected by the unapply
        // TODO: paramType may contain unbound type params (run/t2800, run/t3530)
        val makers = (
          // Statically conforms to paramType
          if (this ensureConformsTo paramType) treeMaker(binder, false, pos) :: Nil
          else typeTest :: extraction :: Nil
        )
        val subBound = extractor.subBoundTrees
        TranslationStep(makers, subBound)
      }

Changing the lazy val to a def exhibits the same failure mode (crash in genLoadIdent) 100% of the time.

Decompiling the lazy compute method suggests unbalanced monitors.

    private final MatchTreeMaking.TreeMakers.TypeTestTreeMaker typeTest$lzycompute$1(ObjectRef typeTest$lzy$1, VolatileByteRef bitmap$0$1) {
        MatchTranslation.MatchTranslator.BoundTree boundTree = this;
        synchronized (boundTree) {
            if ((byte)(bitmap$0$1.elem & 1) == 0) {
                typeTest$lzy$1.elem = new MatchTreeMaking.TreeMakers.TypeTestTreeMaker(this.$outer, this.binder(), this.binder(), this.paramType$1(), this.paramType$1(), this.pos(), true);
                bitmap$0$1.elem = (byte)(bitmap$0$1.elem | 1);
            }
            // ** MonitorExit[this] (shouldn't be in output)
            return (MatchTreeMaking.TreeMakers.TypeTestTreeMaker)typeTest$lzy$1.elem;
        }
    }
  private final scala.tools.nsc.transform.patmat.MatchTreeMaking$TreeMakers$TypeTestTreeMaker typeTest$lzycompute$1(scala.runtime.ObjectRef, scala.runtime.VolatileByteRef);
    Code:
       0: aload_0
       1: dup
       2: astore_3
       3: monitorenter
       4: aload_2
       5: getfield      #658                // Field scala/runtime/VolatileByteRef.elem:B
       8: iconst_1
       9: iand
      10: i2b
      11: iconst_0
      12: if_icmpne     62
      15: aload_1
      16: new           #253                // class scala/tools/nsc/transform/patmat/MatchTreeMaking$TreeMakers$TypeTestTreeMaker
      19: dup
      20: aload_0
      21: getfield      #29                 // Field $outer:Lscala/tools/nsc/transform/patmat/MatchTranslation$MatchTranslator;
      24: aload_0
      25: invokevirtual #92                 // Method binder:()Lscala/reflect/internal/Symbols$Symbol;
      28: aload_0
      29: invokevirtual #92                 // Method binder:()Lscala/reflect/internal/Symbols$Symbol;
      32: aload_0
      33: invokespecial #351                // Method paramType$1:()Lscala/reflect/internal/Types$Type;
      36: aload_0
      37: invokespecial #351                // Method paramType$1:()Lscala/reflect/internal/Types$Type;
      40: aload_0
      41: invokevirtual #236                // Method pos:()Lscala/reflect/internal/util/Position;
      44: iconst_1
      45: invokespecial #256                // Method scala/tools/nsc/transform/patmat/MatchTreeMaking$TreeMakers$TypeTestTreeMaker."<init>":(Lscala/tools/nsc/transform/patmat/MatchTreeMaking$TreeMakers;Lscala/reflect/internal/Symbols$Symbol;Lscala/reflect/internal/Symbols$Symbol;Lscala/reflect/internal/Types$Type;Lscala/reflect/internal/Types$Type;Lscala/reflect/internal/util/Position;Z)V
      48: putfield      #660                // Field scala/runtime/ObjectRef.elem:Ljava/lang/Object;
      51: aload_2
      52: aload_2
      53: getfield      #658                // Field scala/runtime/VolatileByteRef.elem:B
      56: iconst_1
      57: ior
      58: i2b
      59: putfield      #658                // Field scala/runtime/VolatileByteRef.elem:B
      62: getstatic     #52                 // Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
      65: pop
      66: aload_0
      67: monitorexit
      68: aload_1
      69: getfield      #660                // Field scala/runtime/ObjectRef.elem:Ljava/lang/Object;
      72: checkcast     #253                // class scala/tools/nsc/transform/patmat/MatchTreeMaking$TreeMakers$TypeTestTreeMaker
      75: areturn
      76: aload_3
      77: monitorexit
      78: athrow
    Exception table:
       from    to  target type
           4    68    76   any

@scabug
Copy link
Author

scabug commented Dec 7, 2016

@retronym said:
Standalone reproduction: https://gist.github.com/415c9109a37cd10a1657451281a9e129

Reproducible with only -Yclosure-elim.

Appears to be reproducible back to at least 2.10.1 and also on the current tip of 2.11.x

@scabug
Copy link
Author

scabug commented Dec 7, 2016

@retronym said:
This patch https://github.com/retronym/scala/tree/ticket/9264-monitor-copy-propagation

disables copy propagation in closelim when the consuming instruction is a monitorenter/exit.

But looking at this some more, the bytecode actually appears technically okay, AFAIK it is legal to lock and unlock aliases of the same object. So this might be a red herring.

@scabug
Copy link
Author

scabug commented Dec 7, 2016

@retronym said:
Next step is to add some more logging/assertions to test the theory that the lazy val is being double executed when things end up crashing.

@scabug
Copy link
Author

scabug commented Jan 9, 2017

@adriaanm said:
I removed the fix versions because it's not clear what the issue is in 2.11, but we've worked around it in scala/scala#5612, and it was never reported on 2.12 as far as I know.

@dwijnand
Copy link
Member

we've worked around it in scala/scala#5612, and it was never reported on 2.12 as far as I know.

🤞

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

No branches or pull requests

4 participants