Skip to content

Instantly share code, notes, and snippets.

@mandubian
Last active August 29, 2015 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mandubian/11373329 to your computer and use it in GitHub Desktop.
Save mandubian/11373329 to your computer and use it in GitHub Desktop.
Trying to re-use custom type def in a macro
//I have a type with 2 types params
class Toto[M[_], T]
// I make a Monad of Future of it using lambda-type
implicit val TotoMonad = Monad[({ type l[T] = Toto[Future, T]})#l]{...}
// then in my macro I want to create a type alias to { type l[T] = Toto[Future, T]})#l] and call the implicit monad
val mType: Type = ...
val sym = newTypeSymbol(api.currentOwner, "FooToto")
val tpeDef = typeDef(sym, tq"({ type l[T] = Toto[$mType, T] })#l")
// ... later
val TypeDef(_, name, _, _) = tpeDef
val tree = q"""
$tpeDef
implicitly[Monad[$name]].bind(...)
"""
//And scalac fails on:
[error] java.lang.AssertionError: assertion failed: FooToto
// Is it just an error in the way I define/use the type or is it again some owner issues?
// Just in case you already tried to do that...
@mandubian
Copy link
Author

// with this code
val tpe = api.typecheck(monadTTpe)

// I obtain
monadT:type Tata = scala.AnyRef {
  type l[T] = _root_.scalaz.OptionT[scala.concurrent.Future, T]
}#l

monadT:TypeDef(Modifiers(), TypeName("Tata"), List(), SelectFromTypeTree(CompoundTypeTree(Template(List(Select(Ident(scala), TypeName("AnyRef"))), noSelfType, List(TypeDef(Modifiers(), TypeName("l"), List(TypeDef(Modifiers(PARAM), TypeName("T"), List(), TypeBoundsTree(EmptyTree, EmptyTree))), AppliedTypeTree(Select(Select(Ident(termNames.ROOTPKG), TermName("scalaz")), TypeName("OptionT")), List(TypeTree(), Ident(TypeName("T")))))))), TypeName("l")))

[error] /Users/pvo/zenexity/workspaces/workspace_mandubian/categoric/src/test/scala/CategoricSpec.scala:32: 
exception during macro expansion:
[error] java.lang.AssertionError: assertion failed: Tata
[error]     at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1410)

@mandubian
Copy link
Author

val rhs = api.typecheck(tq"({ type l[T] = _root_.scalaz.OptionT[$mType, T] })#l")
println("RHS:"+rhs)
(sym, typeDef(sym, rhs))

// result
RHS:<error>

@mandubian
Copy link
Author

// This works so the type is recognized
    val rhs = api.typecheck(q"_root_.scalaz.OptionT[$mType, Int]")

@mandubian
Copy link
Author

It doesn't like:

    val sym = newTypeSymbol(api.currentOwner, "Tata")
    val rhs = api.typecheck(typeDef(sym, tq"({ type l[T] = _root_.scalaz.OptionT[$mType, T] })#l"))

Also tried to use:

    val tpe = typeOf[_root_.scalaz.OptionT[M, _] forSome { type M[_] }]
    val norm = tpe.typeConstructor.normalize
    val PolyType(params, raw) = norm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment