MixinComposition icon indicating copy to clipboard operation
MixinComposition copied to clipboard

Macro Compilation Error with Runtime Types

Open michaelahlers opened this issue 9 years ago • 5 comments

Following the example outlined in the README, this test fails:

package ahlers.michael

import org.scalatest.{Matchers, WordSpec}

class MixinTest
  extends WordSpec
          with Matchers {

  trait Foo {
    def foo: Int
  }

  trait Bear {
    def bear: String
  }

  val f: Foo = new Foo {
    override def foo: Int = 42
  }

  val b: Bear = new Bear {
    override def bear: String = "bear"
  }

  "Foo" must {

    import de.unimarburg.composition._
    import macros._

    "mix Bar with compile-time types" in {
      mix(f, b).foo should be(42)
    }

    "mix Bar with runtime types" in {
      def canCompose[A, B](a: A, b: B)(implicit ev: A With B) = {
        mix(a, b)
      }
      canCompose(f, b).foo should be(42)
    }

  }

}

If I strike the latter, it works as expected. With both, I get this:

> test-only ahlers.michael.MixinTest
[info] Compiling 1 Scala source to /Users/michaelahlers/Projects/MixinComposition/target/scala-2.11/test-classes...
[error] <macro>:1: super may not be used on value <error>
[error] { new A with B { def getClass() = b$macro$4.getClass() } }
[error]       ^
[error] one error found
[error] (test:compileIncremental) Compilation failed

Is this user error? A regression with a newer Scala release (using 2.11.7)?

michaelahlers avatar Feb 12 '16 19:02 michaelahlers

MixinComposition is an interesting project. Has it been abandoned?

mslinn avatar Jun 02 '16 22:06 mslinn

@mslinn, looks that way. It's a powerful concept for shaping domain models, and I have use for this again in the near future. Time permitting, I'd like to fork this project and update it.

michaelahlers avatar Jun 03 '16 14:06 michaelahlers

Hi, sorry -- I don't know how this issue has escaped me. I'll have a look into it (even though this issue is pretty old).

b-studios avatar Jul 12 '17 09:07 b-studios

When looking at the implementation of mix, we see that it will immediately try to materialize A With B. However, since A and B are type parameters, the macro fails.

The easiest workaround is to immediately use the With provided as an argument to canCompose:

def canCompose[A, B](a: A, b: B)(implicit ev: A With B) = {
  ev(a, b)
}

That said, I agree this is brittle and the error message could be way more informative.

b-studios avatar Jul 12 '17 19:07 b-studios

I tried to add a error message that is a bit more expressive. Though not perfect, this should make it easier to discover this bug earlier next time.

b-studios avatar Jul 12 '17 19:07 b-studios