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

fundep materialization doesn't work #7470

Closed
scabug opened this issue May 11, 2013 · 5 comments
Closed

fundep materialization doesn't work #7470

scabug opened this issue May 11, 2013 · 5 comments

Comments

@scabug
Copy link

scabug commented May 11, 2013

import language.experimental.macros
import scala.reflect.macros.Context

trait Iso[T, U] {
  def to(t : T) : U
  // def from(u : U) : T
}

object Iso {
  implicit def materializeIso[T, U]: Iso[T, U] = macro impl[T, U]
  def impl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: Context): c.Expr[Iso[T, U]] = {
    import c.universe._
    import definitions._
    import Flag._

    val sym = c.weakTypeOf[T].typeSymbol
    if (!sym.isClass || !sym.asClass.isCaseClass) c.abort(c.enclosingPosition, s"$sym is not a case class")
    val fields = sym.typeSignature.declarations.toList.collect{ case x: TermSymbol if x.isVal && x.isCaseAccessor => x }

    def mkTpt() = {
      val core = Ident(TupleClass(fields.length) orElse UnitClass)
      if (fields.length == 0) core
      else AppliedTypeTree(core, fields map (f => TypeTree(f.typeSignature)))
    }

    def mkFrom() = {
      if (fields.length == 0) Literal(Constant(Unit))
      else Apply(Ident(newTermName("Tuple" + fields.length)), fields map (f => Select(Ident(newTermName("f")), newTermName(f.name.toString.trim))))
    }

    val evidenceClass = ClassDef(Modifiers(FINAL), newTypeName("$anon"), List(), Template(
      List(AppliedTypeTree(Ident(newTypeName("Iso")), List(Ident(sym), mkTpt()))),
      emptyValDef,
      List(
        DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))),
        DefDef(Modifiers(), newTermName("to"), List(), List(List(ValDef(Modifiers(PARAM), newTermName("f"), Ident(sym), EmptyTree))), TypeTree(), mkFrom()))))
    c.Expr[Iso[T, U]](Block(List(evidenceClass), Apply(Select(New(Ident(newTypeName("$anon"))), nme.CONSTRUCTOR), List())))
  }
}

object Test extends App {
  case class Foo(i: Int, s: String, b: Boolean)
  def foo[C, L](c: C)(implicit iso: Iso[C, L]): L = iso.to(c)

  {
    val equiv = foo(Foo(23, "foo", true))
    def typed[T](t: => T) {}
    typed[(Int, String, Boolean)](equiv)
    println(equiv)
  }
}
21:21 ~/Projects/Kepler_5923/sandbox (ticket/5923)$ ssli
Test.scala:6: Iso.materializeIso is not a valid implicit value for Iso[Test.Foo,L] because:
hasMatchingSymbol reported error: type mismatch;
 found   : Iso[Test.Foo,(Int, String, Boolean)]
 required: Iso[Test.Foo,Nothing]
Note: (Int, String, Boolean) >: Nothing, but trait Iso is invariant in type U.
You may wish to define U as -U instead. (SLS 4.5)
    val equiv = foo(Foo(23, "foo", true))
                   ^
Test.scala:6: error: could not find implicit value for parameter iso: Iso[Test.Foo,L]
    val equiv = foo(Foo(23, "foo", true))
                   ^
one error found
@scabug
Copy link
Author

scabug commented May 11, 2013

Imported From: https://issues.scala-lang.org/browse/SI-7470?orig=1
Reporter: @xeno-by
Affected Versions: 2.10.0

@scabug
Copy link
Author

scabug commented May 11, 2013

@xeno-by said:
scala/scala#2499

@scabug
Copy link
Author

scabug commented Aug 12, 2013

@xeno-by said:
scala/scala#2821

@scabug scabug closed this as completed Aug 16, 2013
@scabug
Copy link
Author

scabug commented Apr 25, 2014

@milessabin said:
Can this be backported to 2.10.5?

@scabug
Copy link
Author

scabug commented Jul 2, 2014

@xeno-by said:
Yes. scala/scala#3859.

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

2 participants