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

illegal cyclic reference involving class #3809

Closed
scabug opened this issue Aug 29, 2010 · 37 comments
Closed

illegal cyclic reference involving class #3809

scabug opened this issue Aug 29, 2010 · 37 comments

Comments

@scabug
Copy link

scabug commented Aug 29, 2010

The original title of this ticket referred specifically to JSoup. It's since been observed in other libraries.

test.scala:

object Test {
  def main(args : Array[String]) {
    val url = new java.net.URL("http://www.google.com/");
    org.jsoup.Jsoup.parse(url, 3000).select("img");
  }
}

Jsoup 1.3.1 is available here: http://jsoup.org/download

scalac -Ydebug -classpath jsoup-1.3.1.jar test.scala 2>err 1>out

@scabug
Copy link
Author

scabug commented Aug 29, 2010

Imported From: https://issues.scala-lang.org/browse/SI-3809?orig=1
Reporter: Ricky Clarkson (ricky_clarkson)
See #7481
Attachments:

@scabug
Copy link
Author

scabug commented Aug 29, 2010

Ricky Clarkson (ricky_clarkson) said:

class package; annotations = List()
constructor String; annotations = List(lang.this.Deprecated, scala.this.deprecated("see corresponding Javadoc for more information."))
constructor String; annotations = List(lang.this.Deprecated, scala.this.deprecated("see corresponding Javadoc for more information."))
method getBytes; annotations = List(lang.this.Deprecated, scala.this.deprecated("see corresponding Javadoc for more information."))
class package; annotations = List()
[running phase parser on test.scala]
[running phase namer on test.scala]
class Predef; annotations = List()
[running phase packageobjects on test.scala]
[running phase typer on test.scala]
trait ScalaObject; annotations = List()
trait ClassfileAnnotation; annotations = List()
class Annotation; annotations = List()
trait StaticAnnotation; annotations = List()
class List; annotations = List()
class package; annotations = List()
class SeqFactory; annotations = List()
class TraversableFactory; annotations = List()
class GenericCompanion; annotations = List()
class Array; annotations = List()
class LowPriorityImplicits; annotations = List()
method setURL; annotations = List(lang.this.Deprecated, scala.this.deprecated("see corresponding Javadoc for more information."))
method toURL; annotations = List(lang.this.Deprecated, scala.this.deprecated("see corresponding Javadoc for more information."), scala.this.throws(classOf[java.net.MalformedURLException]))
class Tuple2; annotations = List(scala.this.serializable)
trait Product2; annotations = List()
trait Product; annotations = List()
trait Equals; annotations = List()
trait IndexedSeq; annotations = List()
trait Seq; annotations = List()
trait GenericTraversableTemplate; annotations = List()
trait IndexedSeqLike; annotations = List()
trait PartialFunction; annotations = List()
trait Iterable; annotations = List()
trait SeqLike; annotations = List()
trait Function1; annotations = List()
trait Traversable; annotations = List()
trait IterableLike; annotations = List()
trait TraversableLike; annotations = List()
trait HasNewBuilder; annotations = List()
trait FilterMonadic; annotations = List()
trait TraversableOnce; annotations = List()
class uncheckedVariance; annotations = List()
trait TypeConstraint; annotations = List()
trait CanBuildFrom; annotations = List()
class StringOps; annotations = List()
trait StringLike; annotations = List()
trait IndexedSeqOptimized; annotations = List()
class package; annotations = List()
class MathCommon; annotations = List()
trait Ordered; annotations = List()
class StringAdd; annotations = List()
class ArrayOps; annotations = List()
trait IndexedSeq; annotations = List()
class WrappedString; annotations = List()
trait Seq; annotations = List()
trait Iterable; annotations = List()
trait Traversable; annotations = List()
trait Immutable; annotations = List()
trait Proxy; annotations = List()
class WrappedArray; annotations = List()
scala.tools.nsc.symtab.Types$$TypeError: illegal cyclic reference involving class Document
	at scala.tools.nsc.symtab.Types$$CompoundType.baseClasses(Types.scala:1271)
	at scala.tools.nsc.symtab.Types$$Type.findMember(Types.scala:820)
	at scala.tools.nsc.symtab.Types$$Type.member(Types.scala:471)
	at scala.tools.nsc.symtab.classfile.ClassfileParser$$innerClasses$$.getMember$$1(ClassfileParser.scala:1170)
	at scala.tools.nsc.symtab.classfile.ClassfileParser$$innerClasses$$$$anonfun$$14.apply(ClassfileParser.scala:1182)
	at scala.tools.nsc.symtab.classfile.ClassfileParser$$innerClasses$$$$anonfun$$14.apply(ClassfileParser.scala:1182)
	at scala.tools.nsc.symtab.SymbolTable.atPhase(SymbolTable.scala:103)
	at scala.tools.nsc.symtab.classfile.ClassfileParser$$innerClasses$$.innerSymbol$$1(ClassfileParser.scala:1182)
	at scala.tools.nsc.symtab.classfile.ClassfileParser$$innerClasses$$.classSymbol(ClassfileParser.scala:1197)
	at scala.tools.nsc.symtab.classfile.ClassfileParser.classNameToSymbol(ClassfileParser.scala:442)
	at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$$1(ClassfileParser.scala:720)
	at scala.tools.nsc.symtab.classfile.ClassfileParser.sig2type$$1(ClassfileParser.scala:745)
	at scala.tools.nsc.symtab.classfile.ClassfileParser.scala$$tools$$nsc$$symtab$$classfile$$ClassfileParser$$$$sigToType(ClassfileParser.scala:798)
	at scala.tools.nsc.symtab.classfile.ClassfileParser$$ConstantPool.getType(ClassfileParser.scala:328)
	at scala.tools.nsc.symtab.classfile.ClassfileParser.parseMethod(ClassfileParser.scala:596)
	at scala.tools.nsc.symtab.classfile.ClassfileParser$$$$anonfun$$1$$$$anonfun$$apply$$mcV$$sp$$2.apply$$mcVI$$sp(ClassfileParser.scala:525)
	at scala.collection.immutable.Range$$ByOne$$class.foreach$$mVc$$sp(Range.scala:282)
	at scala.collection.immutable.Range$$$$anon$$2.foreach$$mVc$$sp(Range.scala:265)
	at scala.tools.nsc.symtab.classfile.ClassfileParser$$$$anonfun$$1.apply$$mcV$$sp(ClassfileParser.scala:525)
	at scala.tools.nsc.symtab.classfile.ClassfileParser.parseClass(ClassfileParser.scala:542)
	at scala.tools.nsc.symtab.classfile.ClassfileParser.parse(ClassfileParser.scala:98)
	at scala.tools.nsc.symtab.SymbolLoaders$$ClassfileLoader.doComplete(SymbolLoaders.scala:247)
	at scala.tools.nsc.symtab.SymbolLoaders$$SymbolLoader.complete(SymbolLoaders.scala:61)
	at scala.tools.nsc.symtab.SymbolLoaders$$SymbolLoader.complete(SymbolLoaders.scala:35)
	at scala.tools.nsc.symtab.Symbols$$Symbol.info(Symbols.scala:743)
	at scala.tools.nsc.symtab.Types$$TypeRef.thisInfo(Types.scala:1630)
	at scala.tools.nsc.symtab.Types$$TypeRef.baseClasses(Types.scala:1818)
	at scala.tools.nsc.symtab.Types$$CompoundType.computeBaseClasses$$1(Types.scala:1243)
	at scala.tools.nsc.symtab.Types$$CompoundType$$$$anonfun$$baseClasses$$1.apply(Types.scala:1267)
	at scala.tools.nsc.symtab.Types$$CompoundType$$$$anonfun$$baseClasses$$1.apply(Types.scala:1267)
	at scala.tools.nsc.symtab.Types$$CompoundType.memo(Types.scala:1280)
	at scala.tools.nsc.symtab.Types$$CompoundType.baseClasses(Types.scala:1267)
	at scala.tools.nsc.symtab.Types$$TypeRef.baseClasses(Types.scala:1818)
	at scala.tools.nsc.symtab.Types$$Type.findMember(Types.scala:820)
	at scala.tools.nsc.symtab.Types$$Type.nonLocalMember(Types.scala:489)
	at scala.tools.nsc.typechecker.Typers$$Typer.member(Typers.scala:684)
	at scala.tools.nsc.typechecker.Typers$$Typer.typedSelect$$1(Typers.scala:3473)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3985)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:4078)
	at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$typedApply$$1$$1.apply(Typers.scala:3284)
	at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$typedApply$$1$$1.apply(Typers.scala:3284)
	at scala.tools.nsc.typechecker.Typers$$Typer.silent(Typers.scala:699)
	at scala.tools.nsc.typechecker.Typers$$Typer.typedApply$$1(Typers.scala:3284)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3924)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:4078)
	at scala.tools.nsc.typechecker.Typers$$Typer.typedBlock(Typers.scala:1890)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3769)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:4078)
	at scala.tools.nsc.typechecker.Typers$$Typer.transformedOrTyped(Typers.scala:4222)
	at scala.tools.nsc.typechecker.Typers$$Typer.typedDefDef(Typers.scala:1747)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3742)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:4078)
	at scala.tools.nsc.typechecker.Typers$$Typer.typedStat$$1(Typers.scala:2067)
	at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$20.apply(Typers.scala:2135)
	at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$20.apply(Typers.scala:2135)
	at scala.collection.immutable.List.loop$$1(List.scala:115)
	at scala.collection.immutable.List.mapConserve(List.scala:132)
	at scala.tools.nsc.typechecker.Typers$$Typer.typedStats(Typers.scala:2135)
	at scala.tools.nsc.typechecker.Typers$$Typer.typedTemplate(Typers.scala:1507)
	at scala.tools.nsc.typechecker.Typers$$Typer.typedModuleDef(Typers.scala:1312)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3736)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:4078)
	at scala.tools.nsc.typechecker.Typers$$Typer.typedStat$$1(Typers.scala:2067)
	at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$20.apply(Typers.scala:2135)
	at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$20.apply(Typers.scala:2135)
	at scala.collection.immutable.List.loop$$1(List.scala:115)
	at scala.collection.immutable.List.mapConserve(List.scala:132)
	at scala.tools.nsc.typechecker.Typers$$Typer.typedStats(Typers.scala:2135)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3729)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:4078)
	at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:4126)
	at scala.tools.nsc.typechecker.Analyzer$$typerFactory$$$$anon$$3.apply(Analyzer.scala:85)
	at scala.tools.nsc.Global$$GlobalPhase$$$$anonfun$$applyPhase$$1.apply(Global.scala:276)
	at scala.tools.nsc.Global$$GlobalPhase$$$$anonfun$$applyPhase$$1.apply(Global.scala:276)
	at scala.tools.nsc.reporters.Reporter.withSource(Reporter.scala:48)
	at scala.tools.nsc.Global$$GlobalPhase.applyPhase(Global.scala:276)
	at scala.tools.nsc.typechecker.Analyzer$$typerFactory$$$$anon$$3$$$$anonfun$$run$$1.apply(Analyzer.scala:80)
	at scala.tools.nsc.typechecker.Analyzer$$typerFactory$$$$anon$$3$$$$anonfun$$run$$1.apply(Analyzer.scala:80)
	at scala.collection.Iterator$$class.foreach(Iterator.scala:631)
	at scala.collection.mutable.ListBuffer$$$$anon$$1.foreach(ListBuffer.scala:304)
	at scala.tools.nsc.typechecker.Analyzer$$typerFactory$$$$anon$$3.run(Analyzer.scala:80)
	at scala.tools.nsc.Global$$Run.compileSources(Global.scala:733)
	at scala.tools.nsc.Global$$Run.compile(Global.scala:813)
	at scala.tools.nsc.Main$$.process(Main.scala:108)
	at scala.tools.nsc.Main$$.main(Main.scala:122)
	at scala.tools.nsc.Main.main(Main.scala)
test.scala:4: error: illegal cyclic reference involving class Document
    org.jsoup.Jsoup.parse(url, 3000).select("img");
                                     ^
one error found

@scabug
Copy link
Author

scabug commented Aug 29, 2010

Ricky Clarkson (ricky_clarkson) said:
Scala 2.8.0-final

@scabug
Copy link
Author

scabug commented Aug 31, 2010

@lrytz said:
problem while parsing inner classes

@scabug
Copy link
Author

scabug commented Sep 1, 2010

Sam Stainsby (stainsby) said:
Stranglely in REPL it works on the third attempt :-/

scala> object Test {
| def main(args : Array[String]) {
| val url = new java.net.URL("http://www.google.com/");
| org.jsoup.Jsoup.parse(url, 3000).select("img");
| }
| }
:8: error: illegal cyclic reference involving class Document
org.jsoup.Jsoup.parse(url, 3000).select("img");
^

scala> object Test {
| def main(args : Array[String]) {
| val url = new java.net.URL("http://www.google.com/");
| org.jsoup.Jsoup.parse(url, 3000).select("img");
| }
| }
:8: error: illegal cyclic reference involving class Document
org.jsoup.Jsoup.parse(url, 3000).select("img");
^

scala> object Test {
| def main(args : Array[String]) {
| val url = new java.net.URL("http://www.google.com/");
| org.jsoup.Jsoup.parse(url, 3000).select("img");
| }
| }
defined module Test

This is 2.8.0.final with Jsoup 1.3.2

@scabug
Copy link
Author

scabug commented Nov 19, 2010

tommy chheng (tommy.chheng) said:
I"m running into this problem too with jsoup 1.3.3 and scala 2.8.1.final. I invoke a mvn test and get this error:

error: illegal cyclic reference involving class Document
[INFO] val title = document.select("title").text

Any ideas what's causing this problem or workaround?

@scabug
Copy link
Author

scabug commented Nov 22, 2010

@paulp said:
I have beaten up on this long enough to minimize the cause.

package bar;

// both f and g must be present
class A {
  void f(C.D arg) { }
}
class B extends A { 
  void g(C.D arg) { }
}
class C extends B {
  public class D { }
}
// the above wouldn't work anyway, but the cyclic reference hits
// before the package access check so it'll do.
scala> import bar.B._
<console>:5: error: illegal cyclic reference involving class C
       import bar.B._
                  ^

@scabug
Copy link
Author

scabug commented Jan 27, 2011

Atsuhiko Yamanaka (ymnk) said:
FYI, it seems the author of jsoup has changed the code, and
the reported problem will not appear on the latest jsoup version, anymore.

https://github.com/jhy/jsoup/issues/closed#issue/54

@scabug
Copy link
Author

scabug commented Jan 27, 2011

@paulp said:
Replying to [comment:9 ymnk]:

FYI, it seems the author of jsoup has changed the code, and
the reported problem will not appear on the latest jsoup version, anymore.

https://github.com/jhy/jsoup/issues/closed#issue/54

That is good for jsoup users, but please nobody close this ticket: this isn't fixed.

@scabug
Copy link
Author

scabug commented Sep 20, 2011

Oleg Poleshuk (relgames) said:
Same issue for me when using Google Tasks API:

error: illegal cyclic reference involving class Tasks:
val tasksService:Tasks = new Tasks(TRANSPORT, access, JSON_FACTORY)

@scabug
Copy link
Author

scabug commented Oct 24, 2011

Jerzy Muller (keros) said (edited on Oct 24, 2011 2:17:39 PM UTC):
Same one with Google Plus API:
error: illegal cyclic reference involving class Plus
val plus: Plus = new Plus(transport, factory)

Any chance of fix for this one soon?

@scabug
Copy link
Author

scabug commented Sep 29, 2012

@paulp said:
scala/scala#1422

@scabug
Copy link
Author

scabug commented Nov 8, 2012

@paulp said:
Nightly builds of scala 2.11 have a "-Ybreak-cycles" option. If any of the commenters or anyone else experiencing these issues can try that and tell me if it helps, it would be much appreciated. The references to the google tasks and google plus api leave a fairly enormous amount to do to see a reproduction.

@scabug
Copy link
Author

scabug commented Feb 1, 2013

Rice Yeh (riceyeh) said:
Release 2.11 will be released at least 1 year later. Couldn't this bug be fixed on more recent releases 2.10.* because many java libraries have this problem.

@scabug
Copy link
Author

scabug commented Feb 1, 2013

@paulp said:
If many java libraries have this problem, it would help a lot if people could post actual reproductions and not single-line decontextualized snippets. I once tried to reproduce based on the google tasks / plus API comments above and it was a ludicrous rabbit hole of unrelated complexity. I don't have time to master the google APIs for the thrill of reproducing this bug. But with more reproductions than the one from jsoup ( which no longer reproduces) I'd have a chance.

@scabug
Copy link
Author

scabug commented Feb 2, 2013

Rice Yeh (riceyeh) said:
My company has accumulated a bunch of java libraries for more than a decade. Now, we are trying to switch to scala and this bug seems becoming a setback for this try. Yes, we can modify our libraries but it is not convincible to many java developers to say their libraries (some have been used for more than a decade) has problems because their libraries cause my scala program cannot pass scala's compiler.

Rice

@scabug
Copy link
Author

scabug commented Feb 2, 2013

@retronym said:
@rice: if you can post sample code that hits the problem, with clear instructions about which third party library is used, we have a chance to fix the problem (or to verify that the new option -Ybreak-cycles already has fixed it.)

Once that is done, we can consider a backport, most likely to 2.10.2 as development for 2.10.1 will finish in a week or two.

@scabug
Copy link
Author

scabug commented Feb 2, 2013

@gkossakowski said (edited on Feb 2, 2013 9:02:33 AM UTC):
@jason, I found my own post about this from a while ago: http://article.gmane.org/gmane.comp.lang.scala.user/30615

Here are the updated instructions:

$ curl http://pastie.org/pastes/1124288/download -o test.scala
$ curl http://jsoup.org/packages/jsoup-1.3.2.jar -o jsoup-1.3.2.jar
$ scalac -version
Scala compiler version 2.10.0 -- Copyright 2002-2012, LAMP/EPFL
$ scalac -classpath jsoup-1.3.2.jar test.scala
test.scala:5: error: illegal cyclic reference involving class Document
    val links = doc.select("img");
                    ^
one error found

My comment from that post my be relevant:

I looked at class hierarchy to figure out what might be the cause and it looks like scalac is confused by following situation. Document from Element class and this class has a select method which returns class called Elements. Elements implements List<Element> and here we get cyclic reference. Although I find this design weird I guess it's a bug in scalac because it should handle any kind of weird java we throw at it. Am I right?

Apart from that it was reported that newer version of jsoup fixed that problem, see: http://article.gmane.org/gmane.comp.lang.scala.user/37122
The diff is here: jhy/jsoup@9a2e19e
That might help understanding the problem.

@scabug
Copy link
Author

scabug commented Feb 2, 2013

@paulp said:

% scalac3 -Ybreak-cycles -cp jsoup-1.3.2.jar  test.scala 
warning: Breaking cycle in base class computation of class Element in org.jsoup.nodes (List(class Element, class Node, class Object, class Any))
warning: Breaking cycle in base class computation of class Document in org.jsoup.nodes (List(class Document, class Element, class Node, class Object, class Any))
warning: Breaking cycle in base class computation of class Document in org.jsoup.nodes (List(class Document, class Element, class Node, class Object, class Any))
three warnings found
%

@scabug
Copy link
Author

scabug commented Feb 2, 2013

@retronym said:
Paul added a workaround and test for the JSoup problem in master: https://github.com/scala/scala/pull/1422/files

We need additional test cases from the other commenters of this ticket to evaluate if that workaround helps in other cases. If so we might be able to backport to 2.10.2.

@scabug
Copy link
Author

scabug commented Feb 2, 2013

Rice Yeh (riceyeh) said:
I tried the new compiler on my company's jars and it works. The following is its output:

D:\tmp>\coffee\scala-2.11.0-20130119-233428-42f34f61ce\bin\scalac -Ybreak-cycles -cp c:\users\user.m2\repository\xs\binding\xs-binding\1.5.0-SNAPSHOT\xs-binding-1.5.0-SNAPSHOT.jar;c:\users\user.m2\repository\xs\binding\xs-binding-json\1.5.0-SNAPSHOT\xs-binding-json-1.5.0-SNAPSHOT.jar MarshallingContextTest.scala

warning: Breaking cycle in base class computation of class AbstractMarshallerFinder in xs.binding (List(class AbstractMarshallerFinder, trait MarshallerFinder, class Object, class Any))
warning: Breaking cycle in base class computation of class MarshallingContext in xs.binding (List(class MarshallingContext, class AbstractMarshallerFinder, trait MarshallerFinder, class Object, class Any))
warning: Breaking cycle in base class computation of class MarshallingContext in xs.binding (List(class MarshallingContext, class AbstractMarshallerFinder, trait MarshallerFinder, class Object, class Any))
three warnings found

@scabug
Copy link
Author

scabug commented Feb 2, 2013

@paulp said:
Neat-o, that's good to hear. I trust that running the program works too? One of my concerns is that I might be allowing something to compile, but to miscompile.

The code is behind a -Y option because it's pretty sketchy. Jason I know you've already looked at it, but if we want to let it out from its -Y cage it probably needs even more looks.

@scabug
Copy link
Author

scabug commented Feb 2, 2013

@retronym said:
Adding it to the 2.11.x series, initially behind -Y, might be a good way to get that feedback. It's hard for people to test against master without dependencies.

@scabug
Copy link
Author

scabug commented Feb 5, 2013

Rice Yeh (riceyeh) said (edited on Feb 5, 2013 4:23:48 PM UTC):
Attached is an already-simplified version of the framework used in my previous post. I use it to figure out what causing the compiler error. This framework is about marshalling and unmarshalling. The attached file contains 2 packges 'binding' and 'json':

binding:
F.java (interface, stands for Marhsaller Finder)
Af.java (an abstract implmentation of F)
M.java (marshaller)
Mc.java (marshalling context)
Mc.Sc (inner class within Mc, stands for Sub-context)

json:
M.java (marshaller specific for json marshalling)
Mc.java (marshalling context specific for json marshalling)

With the following code in scala, scala compiler gives me the illegal cyclic reference error:

import json._
val mc = new Mc

However, if I change the inner class Mc.Sc to be static nested class, the error is gone.

Rice

@scabug
Copy link
Author

scabug commented May 7, 2013

René Vangsgaard (rvange) said:
I get a similar error when using the indextank-java API. I am running Play! framework 2.10, using this dependency:

"com.indextank" % "indextank-java" % "1.0.9",
[info] Compiling 64 Scala sources and 3 Java sources to /-/target/scala-2.10/classes...
[error] /home/-/TextSearchEngine.scala:26: illegal cyclic reference involving class IndexTankClient
[error]     val client = new com.flaptor.indextank.apiclient.IndexTankClient("<YOUR API URL HERE>")
[error]                  ^
[error] one error found

@scabug
Copy link
Author

scabug commented May 15, 2013

@Sciss said (edited on May 15, 2013 7:13:19 AM UTC):
I'm having this problem now with a project, too (Scala 2.10.1). It doesn't seem to have to do anything with the actual code where it crashes. For example I can reduce the file to

package bar

object Foo {
  new Array[Byte](33)
}

Leading to

exception when typing new Array[Byte]/class scala.reflect.internal.Trees$New
illegal cyclic reference involving class Array in file /Users/hhrutz/Documents/devel/Mellite/src/main/scala/de/sciss/mellite/gui/impl/InterpreterFrameImpl.scala
scala.reflect.internal.Symbols$CyclicReference: illegal cyclic reference involving class Array
	at scala.reflect.internal.Symbols$TypeSymbol.tpe(Symbols.scala:2759)
...
[error] 
[error]   last tree to typer: Literal(Constant(33))
[error]               symbol: null
[error]    symbol definition: null
[error]        symbol owners: 
[error]       context owners: value <local Foo> -> object Foo -> package bar
[error] 
[error] == Enclosing template or block ==
[error] 
[error] Template( // val <local Foo>: <notype> in object Foo
[error]   "java.lang.Object" // parents
[error]   ValDef(
[error]     private
[error]     "_"
[error]     <tpt>
[error]     <empty>
[error]   )
[error]   // 2 statements
[error]   DefDef( // def <init>(): bar.Foo.type in object Foo
[error]     <method>
[error]     "<init>"
[error]     []
[error]     List(Nil)
[error]     <tpt> // tree.tpe=bar.Foo.type
[error]     Block( // tree.tpe=Unit
[error]       Apply( // def <init>(): Object in class Object, tree.tpe=Object
[error]         Foo.super."<init>" // def <init>(): Object in class Object, tree.tpe=()Object
[error]         Nil
[error]       )
[error]       ()
[error]     )
[error]   )
[error]   Apply( // sym= <error> illegal cyclic inheritance involving class Array
[error]     "<init>" // sym= <error> illegal cyclic inheritance involving class Array
[error]     33
[error]   )
[error] )
[error] 
[error] unrecoverable error
[error] Total time: 1 s, completed May 15, 2013 9:01:51 AM

Then of course, if I compile that above example alone, there is no problem, only in the context of my project (even if this is the only file being compiled) :-/

It seems to have to do with compilation order, because once I made that crash disappear by changing things (factoring out a method for example), it re-appeared soon after even though I didn't touch that file anymore.

@scabug
Copy link
Author

scabug commented May 15, 2013

@retronym said (edited on May 15, 2013 7:31:12 AM UTC):
@rene: Your problem is also fixed by Pauls experimental -Ybreak-cycles option.

  ~/code/scratch1 tail build.sbt test.scala
==> build.sbt <==
libraryDependencies += "com.indextank" % "indextank-java" % "1.0.9"

scalaVersion := "2.10.1"

==> test.scala <==
import com.flaptor.indextank.apiclient.IndexTankClient
object Test {
  new IndexTankClient("")
}
  ~/code/scratch1 scala-hash origin/master -nc -classpath /Users/jason/.ivy2/cache/com.indextank/indextank-java/jars/indextank-java-1.0.9.jar:/Users/jason/.ivy2/cache/com.googlecode.json-simple/json-simple/jars/json-simple-1.1.jar -Ybreak-cycles test.scala
[info] origin/mas => /Users/jason/usr/scala-v2.11.0-M2-411-g9a2f6c7
warning: Breaking cycle in base class computation of class IndexTankClient in com.flaptor.indextank.apiclient (List(class IndexTankClient, trait ApiClient, class Object, class Any))

Unfortunately that option is not available in 2.10.x.

Another way to break the cycle appears to be:

import com.flaptor.indextank.apiclient.IndexTankClient
object Test {
  def dummy[A]: Any = dummy[IndexTankClient];

  new IndexTankClient("")
}

@scabug
Copy link
Author

scabug commented May 15, 2013

@retronym said:
@Sciss: Please provide the full stack trace, not the truncated SBT error report. You can get that with the 'last' command in SBT after the crash. It is possible that the crash happens later on in the compiler, and the "last file to the typer" diagnostic is misleading.

@scabug
Copy link
Author

scabug commented May 15, 2013

@Sciss said:
Here is the full output of 'last'

@scabug
Copy link
Author

scabug commented May 15, 2013

@Sciss said (edited on May 15, 2013 8:52:55 AM UTC):
Steps to reproduce:

$ git clone -b si3809 git@github.com:Sciss/Mellite.git
...
$ cd Mellite/
$ sbt compile
...  // this should go through with 93 files
$ vi src/main/scala/de/sciss/mellite/gui/impl/InterpreterFrameImpl.scala

Now comment out line 13, so {code}val boom = ...{code} becomes {code}// val boom = ...{code}

Then:

$ sbt
> compile
... // crashes
> last
... // see attachment

@scabug
Copy link
Author

scabug commented May 15, 2013

René Vangsgaard (rvange) said:
@jason thank you very much for the work around regarding IndexTankClient - it solved my problem. I can now get rid of the previous workaround: a Java class.

@scabug
Copy link
Author

scabug commented Jul 10, 2013

@adriaanm said:
Unassigning and rescheduling to M6 as previous deadline was missed.

@scabug
Copy link
Author

scabug commented Oct 26, 2013

@retronym said:
Raising to critical; we should try to elevate this cycle-buster to the default before 2.11.0

@scabug
Copy link
Author

scabug commented Jul 26, 2016

Kevin Wright (kev.lee.wright) said:
This has resurfaced again... this time with DSE graph and Scala 2.11.8, as in the following snippet:

val c = DseCluster.builder
   .addContactPoint(System.getProperty("cassandra.host", "127.0.0.1"))
   .withGraphOptions(new GraphOptions().setGraphName("mygraph"))
   .build

yielding the error:

Error:(22, 33) illegal cyclic reference involving class Cluster
 val cbuilder = new DseCluster.Builder()

The -Ybreak-cycles fix is confirmed to work

@scabug
Copy link
Author

scabug commented Jul 28, 2016

@retronym said (edited on Jul 28, 2016 10:26:14 AM UTC):
The snippet above can be reproduced with:

scalaVersion := "2.11.8"
libraryDependencies += "com.datastax.cassandra" % "dse-driver" % "1.0.0"
class Test {
  new com.datastax.driver.dse.DseCluster.Builder()
}

@scabug
Copy link
Author

scabug commented Jul 28, 2016

@retronym said (edited on Jul 28, 2016 10:41:31 AM UTC):
Seems like using the existing cycle avoidance facility in the compiler's classfile parser when looking up inner class symbols might be a better fix that the delicate approach in -Ybreak-cycles.

I'm trying this out here:

scala/scala#5308

@scabug scabug added this to the Backlog milestone Apr 7, 2017
retronym added a commit to retronym/scala that referenced this issue May 16, 2018
Manually tested with:

```
$ scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala
test.scala:2: error: illegal cyclic reference involving class Cluster
	new com.datastax.driver.dse.DseCluster.Builder()
                                               ^
one error found

$ /code/scala/build/quick/bin/scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala

$ cat test.scala
class Test {
	new com.datastax.driver.dse.DseCluster.Builder()
}
```

```
class Test {
  new com.datastax.driver.dse.DseCluster.Builder()
}
```

I was also able to compile `pos/cycle{-jsoup,}` without the experimental
`-Ybreak-cycles`. I've removed the entire `-Ybreak-cycles` option and
supporting code in favour of the approach in this patch.

What's changed? I've used lazy types for methods infos, which is analagous
to what we do in `Unpickler` for scala originated types.

Fixes scala/bug#3809
retronym added a commit to retronym/scala that referenced this issue May 16, 2018
Manually tested with:

```
$ scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala
test.scala:2: error: illegal cyclic reference involving class Cluster
	new com.datastax.driver.dse.DseCluster.Builder()
                                               ^
one error found

$ /code/scala/build/quick/bin/scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala

$ cat test.scala
class Test {
	new com.datastax.driver.dse.DseCluster.Builder()
}
```

```
class Test {
  new com.datastax.driver.dse.DseCluster.Builder()
}
```

I was also able to compile `pos/cycle{-jsoup,}` without the experimental
`-Ybreak-cycles`. I've removed the entire `-Ybreak-cycles` option and
supporting code in favour of the approach in this patch.

What's changed? I've used lazy types for methods infos, which is analagous
to what we do in `Unpickler` for scala originated types.

Fixes scala/bug#3809
retronym added a commit to retronym/scala that referenced this issue May 16, 2018
Manually tested with:

```
$ scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala
test.scala:2: error: illegal cyclic reference involving class Cluster
	new com.datastax.driver.dse.DseCluster.Builder()
                                               ^
one error found

$ /code/scala/build/quick/bin/scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala

$ cat test.scala
class Test {
	new com.datastax.driver.dse.DseCluster.Builder()
}
```

```
class Test {
  new com.datastax.driver.dse.DseCluster.Builder()
}
```

I was also able to compile `pos/cycle{-jsoup,}` without the experimental
`-Ybreak-cycles`. I've removed the entire `-Ybreak-cycles` option and
supporting code in favour of the approach in this patch.

What's changed? I've used lazy types for methods infos, which is analagous
to what we do in `Unpickler` for scala originated types.

Fixes scala/bug#3809
retronym added a commit to retronym/scala that referenced this issue May 30, 2018
Manually tested with:

```
$ scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala
test.scala:2: error: illegal cyclic reference involving class Cluster
	new com.datastax.driver.dse.DseCluster.Builder()
                                               ^
one error found

$ /code/scala/build/quick/bin/scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala

$ cat test.scala
class Test {
	new com.datastax.driver.dse.DseCluster.Builder()
}
```

```
class Test {
  new com.datastax.driver.dse.DseCluster.Builder()
}
```

I was also able to compile `pos/cycle{-jsoup,}` without the experimental
`-Ybreak-cycles`. I've removed the entire `-Ybreak-cycles` option and
supporting code in favour of the approach in this patch.

What's changed? I've used lazy types for methods infos, which is analagous
to what we do in `Unpickler` for scala originated types.

Fixes scala/bug#3809
retronym added a commit to retronym/scala that referenced this issue Feb 12, 2019
Manually tested with:

```
$ scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala
test.scala:2: error: illegal cyclic reference involving class Cluster
	new com.datastax.driver.dse.DseCluster.Builder()
                                               ^
one error found

$ /code/scala/build/quick/bin/scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala

$ cat test.scala
class Test {
	new com.datastax.driver.dse.DseCluster.Builder()
}
```

```
class Test {
  new com.datastax.driver.dse.DseCluster.Builder()
}
```

I was also able to compile `pos/cycle{-jsoup,}` without the experimental
`-Ybreak-cycles`. I've removed the entire `-Ybreak-cycles` option and
supporting code in favour of the approach in this patch.

What's changed? I've used lazy types for methods infos, which is analagous
to what we do in `Unpickler` for scala originated types.

Fixes scala/bug#3809
retronym added a commit to retronym/scala that referenced this issue Feb 27, 2019
Manually tested with:

```
$ scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala
test.scala:2: error: illegal cyclic reference involving class Cluster
	new com.datastax.driver.dse.DseCluster.Builder()
                                               ^
one error found

$ /code/scala/build/quick/bin/scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala

$ cat test.scala
class Test {
	new com.datastax.driver.dse.DseCluster.Builder()
}
```

```
class Test {
  new com.datastax.driver.dse.DseCluster.Builder()
}
```

I was also able to compile `pos/cycle{-jsoup,}` without the experimental
`-Ybreak-cycles`. I've removed the entire `-Ybreak-cycles` option and
supporting code in favour of the approach in this patch.

What's changed? I've used lazy types for methods infos, which is analagous
to what we do in `Unpickler` for scala originated types.

Fixes scala/bug#3809
retronym added a commit to retronym/scala that referenced this issue Feb 28, 2019
…ass/method

I've used lazy types for field/method/class infos, which is analagous to what we
do in `Unpickler` for scala originated types.  We read all data needed by the
inner class table and the type completers from the pool eagerly, but still be
lazy about interning strings to Names and completion of the field/method
types themselves.

This fixes some long standing spurious cyclic errors:

Manually tested with:

```
$ scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala
test.scala:2: error: illegal cyclic reference involving class Cluster
	new com.datastax.driver.dse.DseCluster.Builder()
                                               ^
one error found

$ /code/scala/build/quick/bin/scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala

$ cat test.scala
class Test {
	new com.datastax.driver.dse.DseCluster.Builder()
}
```

```
class Test {
  new com.datastax.driver.dse.DseCluster.Builder()
}
```

It subsumes `-Ybreak-cycles`. I was to compile `pos/cycle{-jsoup,}` without the experimental
`-Ybreak-cycles`. I've removed the entire `-Ybreak-cycles` option and supporting code.

It also subsumes the existing implementation related to cycle avoidance
(`queueLoad` / `raiseLoaderLevel`.)

Descriptor, signature, constant, and param names are made available to the field/method lazy
completer which can use them if and when the symbol is completed.

After classfile parsing the constant pool is discarded (some entries are of course captured by
the lazy type completers.)

Fixes scala/bug#3809
retronym added a commit to retronym/scala that referenced this issue Feb 28, 2019
…ass/method

I've used lazy types for field/method/class infos, which is analagous to what we
do in `Unpickler` for scala originated types.  We read all data needed by the
inner class table and the type completers from the pool eagerly, but still be
lazy about interning strings to Names and completion of the field/method
types themselves.

This fixes some long standing spurious cyclic errors:

Manually tested with:

```
$ scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala
test.scala:2: error: illegal cyclic reference involving class Cluster
	new com.datastax.driver.dse.DseCluster.Builder()
                                               ^
one error found

$ /code/scala/build/quick/bin/scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala

$ cat test.scala
class Test {
	new com.datastax.driver.dse.DseCluster.Builder()
}
```

```
class Test {
  new com.datastax.driver.dse.DseCluster.Builder()
}
```

It subsumes `-Ybreak-cycles`. I was to compile `pos/cycle{-jsoup,}` without the experimental
`-Ybreak-cycles`. I've removed the entire `-Ybreak-cycles` option and supporting code.

It also subsumes the existing implementation related to cycle avoidance
(`queueLoad` / `raiseLoaderLevel`.)

Descriptor, signature, constant, and param names are made available to the field/method lazy
completer which can use them if and when the symbol is completed.

After classfile parsing the constant pool is discarded (some entries are of course captured by
the lazy type completers.)

Fixes scala/bug#3809
retronym added a commit to retronym/scala that referenced this issue Mar 4, 2019
…ass/method

I've used lazy types for field/method/class infos, which is analagous to what we
do in `Unpickler` for scala originated types.  We read all data needed by the
inner class table and the type completers from the pool eagerly, but still be
lazy about interning strings to Names and completion of the field/method
types themselves.

This fixes some long standing spurious cyclic errors:

Manually tested with:

```
$ scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala
test.scala:2: error: illegal cyclic reference involving class Cluster
	new com.datastax.driver.dse.DseCluster.Builder()
                                               ^
one error found

$ /code/scala/build/quick/bin/scalac -cp $(coursier fetch -q -p com.datastax.cassandra:dse-driver:1.0.0) test.scala

$ cat test.scala
class Test {
	new com.datastax.driver.dse.DseCluster.Builder()
}
```

```
class Test {
  new com.datastax.driver.dse.DseCluster.Builder()
}
```

It subsumes `-Ybreak-cycles`. I was to compile `pos/cycle{-jsoup,}` without the experimental
`-Ybreak-cycles`. I've removed the entire `-Ybreak-cycles` option and supporting code.

It also subsumes the existing implementation related to cycle avoidance
(`queueLoad` / `raiseLoaderLevel`.)

Descriptor, signature, constant, and param names are made available to the field/method lazy
completer which can use them if and when the symbol is completed.

After classfile parsing the constant pool is discarded (some entries are of course captured by
the lazy type completers.)

Fixes scala/bug#3809

(cherry picked from commit 4554e02)
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

3 participants