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

Throw an error message when Scala 2.12.4 is used #1010

Open
lefou opened this issue Dec 12, 2021 · 10 comments
Open

Throw an error message when Scala 2.12.4 is used #1010

lefou opened this issue Dec 12, 2021 · 10 comments
Assignees

Comments

@lefou
Copy link
Contributor

lefou commented Dec 12, 2021

We have various test cases in Mill, which fail when we update zinc version from 1.5.7 to 1.5.8.

steps

On example reproducer is:

  • checkout mill repository and bump zinc to 1.5.8
diff --git a/build.sc b/build.sc
index c415e742..a9b29871 100755
--- a/build.sc
+++ b/build.sc
@@ -121,7 +121,7 @@ object Deps {
   val upickle = ivy"com.lihaoyi::upickle:1.4.2"
   val utest = ivy"com.lihaoyi::utest:0.7.10"
   val windowsAnsi = ivy"io.github.alexarchambault.windows-ansi:windows-ansi:0.0.3"
-  val zinc = ivy"org.scala-sbt::zinc:1.5.7"
+  val zinc = ivy"org.scala-sbt::zinc:1.5.8"
   val bsp = ivy"ch.epfl.scala:bsp4j:2.0.0"
   val fansi = ivy"com.lihaoyi::fansi:0.2.14"
   val jarjarabrams = ivy"com.eed3si9n.jarjarabrams::jarjar-abrams-core:1.8.0"
mill contrib.buildinfo.test

problem

Compilation with zinc aborts with an java.lang.StackOverflowError.

  java.lang.StackOverflowError
    xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.handleClassicTreeNode(ExtractUsedNames.scala:251)
    xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.traverse(ExtractUsedNames.scala:170)
    xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3(ExtractUsedNames.scala:294)
    xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3$adapted(ExtractUsedNames.scala:294)
    xsbt.Compat$OriginalTreeTraverser$Reflective$.traverseOriginal(Compat.scala:49)
    xsbt.Compat.processOriginalTreeAttachment(Compat.scala:25)
    xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.handleClassicTreeNode(ExtractUsedNames.scala:294)
    xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.traverse(ExtractUsedNames.scala:170)
    xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3(ExtractUsedNames.scala:294)
    xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3$adapted(ExtractUsedNames.scala:294)
    xsbt.Compat$OriginalTreeTraverser$Reflective$.traverseOriginal(Compat.scala:49)
    xsbt.Compat.processOriginalTreeAttachment(Compat.scala:25)
...

expectation

Compilation succeedes as it did with older zinc versions.

notes

I choosen this test as it is fairly minimal. The effective mill build simulated in this test case would basically look like this:

  object BuildInfo extends BuildInfoModule {
    override def scalaVersion = "2.12.4"
    override def buildInfoMembers = T {
      Map(
        "scalaVersion" -> scalaVersion()
      )
    }
  }

It seems, this failure is sensitive to the target scala version. e.g. it fails for: 2.12.4

But from some quick experiments, it seems to succeed for many other scala versions, e.g.: 2.12.3, 2.12.5, 2.12.7, 2.13.7

The code probably causing the StackOverflowError, xsbt.Compat.OriginalTreeTraverser, was newly added in zinc 1.5.8 (v1.5.7...v1.5.8). My wild guess is, that it was never tested with Scala 2.12.4 and the issue is only present for this exact Scala version.

This is a (soft) blocker for updating zinc in Mill. See PR com-lihaoyi/mill#1613

@eed3si9n
Copy link
Member

Thanks for the report.

@dwijnand Looks like Zinc 1.5.8 shipped #997, and caught some infinite loop of walking the "original tree". I am guessing that there's some node where the original tree points to itself or something.

Also stack trace shows macros related:

	at scala.reflect.macros.Attachments.matchesTag(Attachments.scala:38)
	at scala.reflect.macros.Attachments.$anonfun$get$1(Attachments.scala:42)
	at scala.reflect.macros.Attachments.$anonfun$get$1$adapted(Attachments.scala:42)
	at scala.collection.immutable.Set$Set1.find(Set.scala:104)
	at scala.reflect.macros.Attachments.get(Attachments.scala:42)
	at xsbt.Compat$OriginalTreeTraverser$Reflective$.traverseOriginal(Compat.scala:48)
	at xsbt.Compat.processOriginalTreeAttachment(Compat.scala:25)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.handleClassicTreeNode(ExtractUsedNames.scala:294)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.traverse(ExtractUsedNames.scala:170)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3(ExtractUsedNames.scala:294)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3$adapted(ExtractUsedNames.scala:294)
	at xsbt.Compat$OriginalTreeTraverser$Reflective$.traverseOriginal(Compat.scala:49)
	at xsbt.Compat.processOriginalTreeAttachment(Compat.scala:25)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.handleClassicTreeNode(ExtractUsedNames.scala:294)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.traverse(ExtractUsedNames.scala:170)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3(ExtractUsedNames.scala:294)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3$adapted(ExtractUsedNames.scala:294)
	at xsbt.Compat$OriginalTreeTraverser$Reflective$.traverseOriginal(Compat.scala:49)
	at xsbt.Compat.processOriginalTreeAttachment(Compat.scala:25)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.handleClassicTreeNode(ExtractUsedNames.scala:294)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.traverse(ExtractUsedNames.scala:170)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3(ExtractUsedNames.scala:294)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3$adapted(ExtractUsedNames.scala:294)
	at xsbt.Compat$OriginalTreeTraverser$Reflective$.traverseOriginal(Compat.scala:49)
	at xsbt.Compat.processOriginalTreeAttachment(Compat.scala:25)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.handleClassicTreeNode(ExtractUsedNames.scala:294)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.traverse(ExtractUsedNames.scala:170)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3(ExtractUsedNames.scala:294)
	at xsbt.ExtractUsedNames$ExtractUsedNamesTraverser.$anonfun$handleClassicTreeNode$3$adapted(ExtractUsedNames.scala:294)
	at xsbt.Compat$OriginalTreeTraverser$Reflective$.traverseOriginal(Compat.scala:49)
	at xsbt.Compat.processOriginalTreeAttachment(Compat.scala:25)

This could mean that original tree might be used for multiple purposes (constant folding, macros etc) and testing with one scenario might work but doesn't for the other? Also if previous version of Zinc didn't have this issue, maybe it's a problem specific to 2.12?

@dwijnand
Copy link
Member

Here's my hypothesis: OriginalTreeAttachment was added in 2.12.3, something was changed in 2.12.4 which introduced some cycle, which was either removed or guarded against in 2.12.5+ as well as 2.13+. 2.12.4 is Oct 2017 and 2.12.5 is Mar 2018, so this seems pretty low priority to me. But apologies for introducing the bug!

@lefou
Copy link
Contributor Author

lefou commented Dec 14, 2021

Sound reasonable. How about guarding that Scala version with a better error message, indicating that simply selecting some other version might fix the issue? I don't need this fix for me; but want to provide a nice experience for the users of Mill and zinc. If we claim to compile Scala 2.12 code but we know that certain versions may not work, we could at least communicate that to the user and avoid lots of frustrations.

@eed3si9n
Copy link
Member

@dwijnand
Copy link
Member

Why?

@eed3si9n
Copy link
Member

I didn't want to create a Trolley problem of log4shell and unpredictable (works only on some 2.12.x?) stackoverflow in 1.5.x branch.

If sbt 1.6.0 eventually finalizes this would still be part of 1.6.x.

@dwijnand
Copy link
Member

You still have a trolley problem because you just introduced under-compilation involving constants for all versions of scala 2.12.x just because it (sometimes?) stackoverflows for scala 2.12.4. Which is the wrong choice IMO.

sjrd added a commit to sjrd/scala-js that referenced this issue Jun 5, 2023
It simply has not been supported by the Zinc used since sbt 1.6.0.
See sbt/sbt#6838 and
sbt/zinc#1010 .

Attempting to compile *any* project using Scala 2.12.4 and sbt
1.6.0+, including a Hello World, results in a StackOverflow.
Therefore, no one must be using Scala 2.12.4 at this point.
sjrd added a commit to sjrd/scala-js that referenced this issue Jun 12, 2023
It simply has not been supported by the Zinc used since sbt 1.6.0.
See sbt/sbt#6838 and
sbt/zinc#1010 .

Attempting to compile *any* project using Scala 2.12.4 and sbt
1.6.0+, including a Hello World, results in a StackOverflow.
Therefore, no one must be using Scala 2.12.4 at this point.
@Friendseeker
Copy link
Member

Referring to sjrd's comment

Attempting to compile any project using Scala 2.12.4 and sbt
1.6.0+, including a Hello World, results in a StackOverflow.
Therefore, no one must be using Scala 2.12.4 at this point.

@Friendseeker Friendseeker closed this as not planned Won't fix, can't repro, duplicate, stale Dec 24, 2023
@eed3si9n
Copy link
Member

eed3si9n commented Oct 7, 2024

We should probably throw an error message from Zinc saying the version not supported.

@eed3si9n eed3si9n reopened this Oct 7, 2024
@eed3si9n eed3si9n changed the title Stackoverflow in ExtractUsedNamesTraverser introduced in zinc-1.5.8 Throw an error message when Scala 2.12.4 is used Oct 7, 2024
@Friendseeker Friendseeker self-assigned this Oct 7, 2024
@Friendseeker
Copy link
Member

Friendseeker commented Oct 7, 2024

Note to myself: Probably want to add new type of exception specifically for unsupported compile setup.

Can throw same exception for #1352

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