Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Commit fdcc262

Browse files
committed
SI-8029 Avoid multi-run cyclic error with companions, package object
The bug report suggests this problem only became visible in the IDE *after* 2.10.3, but I tested an IDE with exactly 2.10.3 and saw the same problem. In fact, my test case fails as far back as 2.10.0. I suspect the problem showed up after 816cecf, which checks that pairs of companion symbols are codefined eagerly in Namers. This commit modifies the check of `rawInfo ne NoType` in `isCoDefinedWith` to avoid triggering adaptation of types from the previous run. I'm not sure of the precise intent of that check. I looked at c9861cd (genesis of isCoDefinedWith). Before that we get back to 3761cb4 (the dawn of Subversion.)
1 parent 7c1d114 commit fdcc262

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

bincompat-forward.whitelist.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,6 +1431,10 @@ filter {
14311431
{
14321432
matchName="scala.reflect.internal.Trees#Modifiers.isDeferredNotDefault"
14331433
problemName=MissingMethodProblem
1434+
},
1435+
{
1436+
matchName="scala.reflect.internal.Symbols#Symbol.rawInfoIsNoType"
1437+
problemName=MissingMethodProblem
14341438
}
14351439
]
14361440
}

src/reflect/scala/reflect/internal/Symbols.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,13 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
12821282
def hasRawInfo: Boolean = infos ne null
12831283
def hasCompleteInfo = hasRawInfo && rawInfo.isComplete
12841284

1285+
// does not run adaptToNewRun, which is prone to trigger cycles (SI-8029)
1286+
// TODO: give this a better name if you understand the intent of the caller.
1287+
// Is it something to do with `reallyExists` or `isStale`?
1288+
final def rawInfoIsNoType: Boolean = {
1289+
hasRawInfo && (infos.info eq NoType)
1290+
}
1291+
12851292
/** Return info without checking for initialization or completing */
12861293
def rawInfo: Type = {
12871294
var infos = this.infos
@@ -1928,7 +1935,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
19281935

19291936
/** Is this symbol defined in the same scope and compilation unit as `that` symbol? */
19301937
def isCoDefinedWith(that: Symbol) = (
1931-
(this.rawInfo ne NoType)
1938+
!rawInfoIsNoType
19321939
&& (this.effectiveOwner == that.effectiveOwner)
19331940
&& ( !this.effectiveOwner.isPackageClass
19341941
|| (this.sourceFile eq null)

test/files/run/t8029.scala

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import scala.tools.partest._
2+
import scala.tools.nsc._
3+
4+
object Test extends DirectTest {
5+
6+
override def extraSettings: String = "-usejavacp -nowarn -Ystop-after:typer"
7+
8+
override def code = "" // not used
9+
10+
def code1 = """
11+
package object p1 {
12+
trait A
13+
object A
14+
}
15+
"""
16+
17+
def code2 = """
18+
package object p2 {
19+
class A
20+
object A
21+
}
22+
"""
23+
24+
def code3 = """
25+
package object p3 {
26+
object A
27+
trait A
28+
}
29+
"""
30+
31+
def code4 = """
32+
package object p4 {
33+
object A
34+
trait A
35+
}
36+
"""
37+
38+
def show() {
39+
val global = newCompiler()
40+
import global._
41+
def typecheck(code: String): Unit = {
42+
val r = new Run
43+
val sourceFile = newSources(code).head
44+
global.reporter.reset()
45+
r.compileSources(sourceFile :: Nil)
46+
assert(!global.reporter.hasErrors)
47+
}
48+
49+
def typecheckTwice(code: String): Unit = {
50+
typecheck(code)
51+
typecheck(code)
52+
}
53+
54+
// was: illegal cyclic reference involving package ...
55+
Seq(code1, code2, code3, code4) foreach typecheckTwice
56+
}
57+
}

0 commit comments

Comments
 (0)