Skip to content

Compiler crash with AssertionError "mixed in lazy value .. from class .. is not param?!" #10223

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

Open
scabug opened this issue Mar 9, 2017 · 10 comments
Labels
compiler crash fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) mixin
Milestone

Comments

@scabug
Copy link

scabug commented Mar 9, 2017

The code:

object Broken {
  trait Parent
  class Child extends Parent

  trait Test { lazy val x: Child = new Child }
  abstract class Test2 extends Test { override def x: Parent }
}

Causes the compiler to assertion fail:

java.lang.AssertionError: assertion failed:
  mixed in lazy value x from class Broken$Test2 is not param?!?
     while compiling: C:\Users\anixon\source\myproject\src\test\scala\myproject\Broken.scala
        during phase: globalPhase=mixin, enteringPhase=cleanup
     library version: version 2.12.1
    compiler version: version 2.12.1
@scabug
Copy link
Author

scabug commented Mar 9, 2017

Imported From: https://issues.scala-lang.org/browse/SI-10223?orig=1
Reporter: Alex Nixon (alexnixon)
Affected Versions: 2.12.0, 2.12.1

@scabug
Copy link
Author

scabug commented Mar 9, 2017

@adriaanm said:
Thanks! This shouldn't crash (it should compile). However, you can't make the def x concrete, as a lazy val cannot be overridden by a method.

What's the purpose of the abstract method x?

@scabug
Copy link
Author

scabug commented Mar 20, 2017

@adriaanm said:
Dotty cross-ref: scala/scala3#2072 --> scala/scala3#2085

@adriaanm adriaanm self-assigned this Apr 10, 2017
@adriaanm adriaanm added this to the 2.12.3 milestone Apr 10, 2017
@retronym retronym modified the milestones: 2.12.3, 2.12.4 Jul 8, 2017
@adriaanm adriaanm modified the milestones: 2.12.4, 2.12.5 Oct 10, 2017
@SethTisue SethTisue modified the milestones: 2.12.5, Backlog Mar 1, 2018
@diesalbla
Copy link

The fragment of code (current 2.13.x HEAD) where the failing assertion arises:

      for (sym <- clazz.info.decls ; if sym hasFlag MIXEDIN) {
        // if current class is a trait, add an abstract method for accessor `sym`
        // ditto for a super accessor (will get an RHS in completeSuperAccessor)
        if (clazz.isTrait || sym.isSuperAccessor) addDefDef(sym)
        // implement methods mixed in from a supertrait (the symbols were created by mixinTraitMembers)
        else if (sym.hasFlag(ACCESSOR) && !sym.hasFlag(DEFERRED)) {
          assert(sym hasFlag (PARAMACCESSOR), s"mixed in $sym from $clazz is not param?!?")
          // add accessor definitions
          addDefDef(sym, accessorBody(sym))
        }

@diesalbla
Copy link

diesalbla commented Mar 10, 2019

A slightly reduced example, using existing types from the base library:

object BrokenLit {
  trait Test { lazy val x: String = ""}
  abstract class Test2 extends Test { override def x: Any }
}

@adriaanm said:
Thanks! This shouldn't crash (it should compile). However, you can't make the def x concrete, as a lazy val cannot be overridden by a method.

Could you clarify why this should compile? The two key aspects of this example are:

  • A concrete lazy val definition is being overridden by an abstract def one.
  • A member with return type String is being overridden by one with return type Any, i.e., the subtype is overridden by the supertype, which seems to be wrong.

@melezov
Copy link

melezov commented Aug 30, 2020

I've stumbled across this via a different route:

trait Foo { lazy val bar = 1L }
class Baz extends Foo { private[this] lazy val bar = 2L }

It is given that the code shouldn't compile, but it slays the compiler instead of producing a nice error with

java.lang.AssertionError: assertion failed:
  mixed in lazy value bar from class iw$Baz is not param?!?

@SethTisue SethTisue added the fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) label Aug 21, 2023
@SethTisue
Copy link
Member

still reproduces in 2.13.11.

Scala 3.3.1-RC5:

-- [E164] Declaration Error: ---------------------------------------------------
6 |  abstract class Test2 extends Test { override def x: Parent }
  |                                                   ^
  | error overriding lazy value x in trait Test of type Broken.Child;
  |   method x of type => Broken.Parent needs to be a stable, immutable value

@som-snytt
Copy link

Welcome to Scala 2.13.11 (OpenJDK 64-Bit Server VM, Java 20.0.1).
Type in expressions for evaluation. Or try :help.

scala> trait Foo { lazy val bar = 1L }
trait Foo

scala> class Baz extends Foo { private[this] lazy val bar = 2L }
                                                      ^
       error: weaker access privileges in overriding
       lazy val bar: Long (defined in trait Foo)
         override should not be private

@SethTisue
Copy link
Member

to summarize: @melezov's version is okay now, but the original report and Diego's version both still crash

@som-snytt
Copy link

som-snytt commented Aug 23, 2023

I was taking a look. Scala 3 benefits from treating the abstract member overriding the concrete member, so it errors correctly in refchecks.

In Scala 2, concrete member has precedence over abstract member, but Refchecks has a supplementary rule that still requires a concrete implementation in a subclass. So that clarifies why it should compile; Jasper's comment on the open dotty ticket is an example of the second rule.

The wider method is bridged in erasure. But a concrete subclass is required to supply an implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler crash fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) mixin
Projects
None yet
7 participants