Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SI-7242 Fix crash when inner object mixes in its companion
Given: class C { trait T { C.this } // C$T$$$outer$ : C object T extends T { C.this } // C$T$$$outer$ : C.this.type } object T ended up with a definitions for both of the accessors. These cannot co-exist, as they have the same erased type. A crash ensued almost immediately in explitouter. Fortunately, the solution is straightforward: we can just omit the mixin outer accessor altogether, the objects own outer accessor is compatible with it. scala> :javap C.T Compiled from "<console>" public interface C$T{ public abstract C C$T$$$outer(); } scala> :javap C.T$ Compiled from "<console>" public class C$T$ extends java.lang.Object implements C$T{ public C C$T$$$outer(); public C$T$(C); } I also added an assertion to give a better error message in case we find ourselves here again. Also includes tests from SI-3994, which I'll mark as a duplicate.
- Loading branch information
Showing
3 changed files
with
124 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
trait T { | ||
trait Default { def foo = this } | ||
object Default extends Default | ||
} | ||
|
||
class Crash { // if you change this to a `trait` it keeps failing, though if it is an `object` it compiles just fine! | ||
class Element | ||
|
||
/* declare this as a class, and the crash goes away */ | ||
trait ElementOrdering extends Ordering[Element] { | ||
def compare(a: Element, b: Element): Int = 0 | ||
} | ||
|
||
implicit object ElementOrdering extends ElementOrdering | ||
} | ||
|
||
object Test extends App { | ||
(new T {}).Default | ||
(new Crash).ElementOrdering | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
class CrashTest { | ||
def foo = () | ||
trait CrashTestTable { | ||
def cols = foo | ||
} | ||
// This was leading to a class between the mixed in | ||
// outer accessor and the outer accessor of this object. | ||
object CrashTestTable extends CrashTestTable { | ||
foo | ||
cols | ||
} | ||
} | ||
|
||
class CrashTest1 { | ||
def foo = () | ||
class CrashTestTable { | ||
def cols = foo | ||
} | ||
object CrashTestTable extends CrashTestTable { | ||
foo | ||
cols | ||
} | ||
} | ||
|
||
class CrashTest2 { | ||
def foo = () | ||
trait CrashTestTable { | ||
def cols = foo | ||
} | ||
object Obj extends CrashTestTable { | ||
foo | ||
cols | ||
} | ||
} | ||
|
||
class CrashTest3 { | ||
def foo = () | ||
|
||
def meth() { | ||
trait CrashTestTable { | ||
def cols = foo | ||
} | ||
object Obj extends CrashTestTable { | ||
foo | ||
cols | ||
} | ||
Obj | ||
} | ||
} | ||
|
||
object Test extends App { | ||
{ | ||
val c = new CrashTest | ||
c.CrashTestTable | ||
} | ||
|
||
{ | ||
val c = new CrashTest1 | ||
c.CrashTestTable | ||
} | ||
|
||
{ | ||
val c = new CrashTest2 | ||
c.Obj | ||
} | ||
|
||
{ | ||
val c = new CrashTest3 | ||
c.meth() | ||
} | ||
} |