Scala3: making macro implementation polymorphic - scala

I want to implement a polymorphic macro execution that delegates to context specific type class instances:
trait Compile[C, S] {
type T
def compile(e: Expr[S])(using Quotes): Expr[T]
}
object Memory {
given memoryCompile[A]: Compile[Memory.type, A] with
final type T = A
def compile(a: Expr[A])(using Quotes): Expr[A] = a
}
transparent inline def compile[C, S](ctx: C)(inline query: S) = ${
compileImpl('ctx)('query)
}
def compileImpl[C, S](
ctx: Expr[C]
)(query: Expr[S])(using q: Quotes, tc: Type[C], ts: Type[S]): Expr[Any] =
Expr.summon[Compile[C, S]] match {
case Some(c) =>
staging
.run(c)(using staging.Compiler.make(getClass.getClassLoader))
.compile(query)
case None => throw Exception(
s"No Compiler found for expression of type ${Type.show[S]} in the context of ${Type.show[C]}"
)
}
My own attempt, as shown, tries evaluating the expression using staging.run, but that is subject to scala.quoted.runtime.impl.ScopeException: Cannot use Expr oustide of the macro splice `${...}` or the scala.quoted.staging.run(...)` where it was defined

Turns out macros can call other macros. There was no need for multi-stage compilation. The Compile[C,S] givens could have their own macro expansions:
trait Compile[C, S] {
type T
def compile(e: S): T
}
given m[S]: Compile[Memory.type, S] with
type T = S
transparent inline def compile(e: S): S = ${Macros.compile('e)}
// In another file
object Macros {
def compile[S](e: Expr[S])(using Quotes): Expr[S] = e
}
Then, this:
staging
.run(c)(using staging.Compiler.make(getClass.getClassLoader))
.compile(query)
Becomse this:
'{$c.compile($query)}

Related

How can I dynamically construct a Scala class without knowing types in advance?

I want to build a simple library in which a developer can define a Scala class that represents command line arguments (to keep it simple, just a single set of required arguments -- no flags or optional arguments). I'd like the library to parse the command line arguments and return an instance of the class. The user of the library would just do something like this:
case class FooArgs(fluxType: String, capacitorCount: Int)
def main(args: Array[String]) {
val argsObject: FooArgs = ArgParser.parse(args).as[FooArgs]
// do real stuff
}
The parser should throw runtime errors if the provided arguments do not match the expected types (e.g. if someone passes the string "bar" at a position where an Int is expected).
How can I dynamically build a FooArgs without knowing its shape in advance? Since FooArgs can have any arity or types, I don't know how to iterate over the command line arguments, cast or convert them to the expected types, and then use the result to construct a FooArgs. Basically, I want to do something along these lines:
// ** notional code - does not compile **
def parse[T](args: Seq[String], klass: Class[T]): T = {
val expectedTypes = klass.getDeclaredFields.map(_.getGenericType)
val typedArgs = args.zip(expectedTypes).map({
case (arg, String) => arg
case (arg, Int) => arg.toInt
case (arg, unknownType) =>
throw new RuntimeException(s"Unsupported type $unknownType")
})
(klass.getConstructor(typedArgs).newInstance _).tupled(typedArgs)
}
Any suggestions on how I can achieve something like this?
When you want to abstract over case class (or Tuple) shape, the standard approach is to get the HList representation of the case class with the help of shapeless library. HList keeps track in its type signature of the types of its elements and their amount. Then you can implement the algorithm you want recursively on the HList. Shapeless also provides a number of helpful transformations of HLists in shapeless.ops.hlist.
For this problem, first we need to define an auxiliary typeclass to parse an argument of some type from String:
trait Read[T] {
def apply(str: String): T
}
object Read {
def make[T](f: String => T): Read[T] = new Read[T] {
def apply(str: String) = f(str)
}
implicit val string: Read[String] = make(identity)
implicit val int: Read[Int] = make(_.toInt)
}
You can define more instances of this typeclass, if you need to support other argument types than String or Int.
Then we can define the actual typeclass that parses a sequence of arguments into some type:
// This is needed, because there seems to be a conflict between
// HList's :: and the standard Scala's ::
import shapeless.{:: => :::, _}
trait ParseArgs[T] {
def apply(args: List[String]): T
}
object ParseArgs {
// Base of the recursion on HList
implicit val hnil: ParseArgs[HNil] = new ParseArgs[HNil] {
def apply(args: List[String]) =
if (args.nonEmpty) sys.error("too many args")
else HNil
}
// A single recursion step on HList
implicit def hlist[T, H <: HList](
implicit read: Read[T], parseRest: ParseArgs[H]
): ParseArgs[T ::: H] = new ParseArgs[T ::: H] {
def apply(args: List[String]) = args match {
case first :: rest => read(first) :: parseRest(rest)
case Nil => sys.error("too few args")
}
}
// The implementation for any case class, based on its HList representation
implicit def caseClass[C, H <: HList](
implicit gen: Generic.Aux[C, H], parse: ParseArgs[H]
): ParseArgs[C] = new ParseArgs[C] {
def apply(args: List[String]) = gen.from(parse(args))
}
}
And lastly we can define some API, that uses this typeclass. For example:
case class ArgParser(args: List[String]) {
def to[C](implicit parseArgs: ParseArgs[C]): C = parseArgs(args)
}
object ArgParser {
def parse(args: Array[String]): ArgParser = ArgParser(args.toList)
}
And a simple test:
scala> ArgParser.parse(Array("flux", "10")).to[FooArgs]
res0: FooArgs = FooArgs(flux,10)
There is a great guide on using shapeless for solving similar problems, which you may find helpful: The Type Astronaut’s Guide to Shapeless

Shapeless: Iterate over the types in a Coproduct

I want to do something really simple, but I'm struggling to craft the correct search or just understanding some of the solutions I've seen.
Given a method that takes a generic type parameter which is a Coproduct;
def apply[T <: Coproduct] = {
...
}
How can I iterate over the types that form the coproduct? Specifically, for each type that is a case class, I'd like to recursively examine each field and build up a map with all the information.
Currently I'm working around this using a builder pattern, which I'll post here in case it's useful to others;
class ThingMaker[Entities <: Coproduct] private {
def doThings(item: Entities): Set[Fact] = {
...
}
def register[A <: Product with Serializable]: ThingMaker[A :+: Entities] = {
// useful work can be done here on a per type basis
new ThingMaker[A :+: Entities]
}
}
object ThingMaker {
def register[A <: Product with Serializable]: ThingMaker[A :+: CNil] = {
// useful work can be done here on a per type basis
new ThingMaker[A :+: CNil]
}
}
If you just want to inspect values, you can simply pattern match on a coproduct like on any other value...
def apply[T <: Coproduct](co: T): Any = co match {
case Inl(MyCaseClass(a, b, c)) => ???
...
}
...but if you want to be more precise than that, for instance to have a return type that depends on the input, or to inspect the types inside this coproduct to summon implicits, then you can write the exact same pattern matching expression using a type class and several implicit definition:
trait MyFunction[T <: Coproduct] {
type Out
def apply(co: T): Out
}
object MyFunction {
// case Inl(MyCaseClass(a, b, c)) =>
implicit val case1 = new MyFunction[Inl[MyCaseClass]] {
type Out = Nothing
def apply(co: Inl[MyCaseClass]): Out = ???
}
// ...
}
In general, when you want iterate over all types of a coproduct, you will always follow the same tail recursive structure. As a function:
def iterate[T <: Coproduct](co: T): Any = co match {
case Inr(head: Any) => println(v)
case Inl(tail: Coproduct) => iterate(tail)
case CNil => ???
}
Or as a "dependently typed function":
trait Iterate[T <: Coproduct]
object Iterate {
implicit def caseCNil = new Iterate[CNil] {...}
implicit def caseCCons[H, T <: Coproduct](implicit rec: Iterate[T]) =
new Iterate[H :+: T] {...}
}
You can for instance ontain the name of each type in a coproduct using an addition ClassTag implicit:
trait Iterate[T <: Coproduct] { def types: List[String] }
object Iterate {
implicit def caseCNil = new Iterate[CNil] {
def types: List[String] = Nil
}
implicit def caseCCons[H, T <: Coproduct]
(implicit
rec: Iterate[T],
ct: reflect.ClassTag[H]
) =
new Iterate[H :+: T] {
def types: List[String] = ct.runtimeClass.getName :: rec.types
}
}
implicitly[Iterate[Int :+: String :+: CNil]].types // List(int, java.lang.String)
Because of the way Scala lets you influence implicit priority, it's actually possible to translate any recursive function with pattern matching into this "dependently typed function" pattern. This is unlike Haskell where such function can only be written if call cases of the match expression are provably non-overlapping.

Can we elegantly match an erased type in scala?

Is there any elegant way, to arrive from:
def foo[T: TypeTag](a: A[T]) {
// can we match on the type of T here?
}
at a match expression on the type of T?
Obviously this below does not overcome erasure for T, so must we inspect the TypeTag by hand?
a match {
case _:A[SomeSpecificType] => ...
Or does scala afford some elegance to that end?
Sadly no, as the compiler does not take type tags into account if you add type checks to a pattern. I'm not sure why and whether this is planned. You can however compare type tags for equality:
typeOf[T] =:= typeOf[List[String]]
You can use that in an if or match condition and then cast to the target type.
After thinking a bit more about it, I recognized that it would be quite easy to write my own pattern extractor, that hides the check and cast:
import scala.reflect.runtime.universe._
class TypeTest[A: TypeTag]() {
def unapply[B: TypeTag](v: B): Option[A] =
if(typeOf[B] <:< typeOf[A])
Some(v.asInstanceOf[A])
else
None
}
object TypeTest {
def apply[A: TypeTag] = new TypeTest()
}
Now, we can do stuff like this:
def printIfStrings[T: TypeTag](v: T) {
val string = TypeTest[List[String]]
v match {
case string(s) => printString(s)
case _ =>
}
}
def printString(s: List[String]) {
println(s)
}
printIfStrings(List(123))
printIfStrings(List("asd"))
This is already quite neat, but as Scala does not support passing an argument directly to an extractor in a pattern, we have to define all extractors as val string before the match expression.
Macros
Macros can transform code, so it should be easy enough to transform any unchecked typechecks in a match expression into an appropriate pattern or add explicit checks using the type tags directly.
This however requires that we have a macro invocation wrapped around every critical match expression, which would be quite ugly. An alternative is to replace match expressions by some method call that takes a partial function as an argument. This method can be provide for an arbitrary type using an implicit conversion.
The only remaining problem then is that the compiler typechecks the code before any macros are invoked, so it will generate a warning for the unchecked cast even though it is now checked. We can still us #unchecked to suppress these warnings.
I chose to replace type checks in patterns by the extractor described above instead of adding a condition to the case and explicit type casts. The reason for that is that this transformation is local (I just have to replace a subexpression with another).
So here is the macro:
import scala.language.experimental.macros
import scala.language.implicitConversions
import scala.reflect.macros.blackbox.Context
object Switch {
implicit class Conversion[A](val value: A) {
def switch[B](f: PartialFunction[A, B]): B = macro switchImpl
}
def switchImpl(c: Context)(f: c.Tree): c.Tree = {
import c.universe._
val types = collection.mutable.Map[Tree,String]()
val t1 = new Transformer {
override def transformCaseDefs(trees: List[CaseDef]) = {
val t2 = new Transformer {
override def transform(tree: Tree) = {
def pattern(v: String, t: Tree) = {
val check = types.getOrElseUpdate(t, c.freshName())
pq"${TermName(check)}(${TermName(v)})"
}
tree match {
case Bind(TermName(v),Typed(Ident(termNames.WILDCARD),
Annotated(Apply(
Select(New(Ident(TypeName("unchecked"))),
termNames.CONSTRUCTOR), List()
), t)))
=> pattern(v,t)
case Bind(TermName(v),Typed(Ident(termNames.WILDCARD),t))
=> pattern(v,t)
case _ => super.transform(tree)
}
}
}
t2.transformCaseDefs(trees)
}
}
val tree = t1.transform(c.untypecheck(f))
val checks =
for ((t,n) <- types.toList) yield
q"val ${TermName(n)} = Switch.TypeTest[$t]"
q"""
..$checks
$tree(${c.prefix}.value)
"""
}
import scala.reflect.runtime.universe._
class TypeTest[A: TypeTag]() {
def unapply[B: TypeTag](v: B): Option[A] =
if(typeOf[B] <:< typeOf[A]) Some(v.asInstanceOf[A])
else None
}
object TypeTest {
def apply[A: TypeTag] = new TypeTest()
}
}
And now magically type checks in patterns work:
import Switch.Conversion
val l = List("qwe")
def printIfStrings2[T: scala.reflect.runtime.universe.TypeTag](v: T) {
v switch {
case s: Int => println("int")
case s: List[String] #unchecked => printString(s)
case _ => println("none")
}
}
printIfStrings2(l)
printIfStrings2(List(1, 2, 3))
printIfStrings2(1)
I'm not sure whether I handle all possible cases correctly, but every thing I tried worked fine. A type with multiple annotations is possibly not handled correctly if it is also annotated by #unchecked, but I couldn't find an example in the standard library to test this.
If you leave out the #unchecked the result is exactly the same, but as mentioned above you will get a compiler warning. I don't see a way to get rid of that warning with normal macros. Maybe annotation macros can do it but they are not in the standard branch of Scala.

How to enforce non-generic type at compile time

consider a generic function:
def genericFn[T](fn: T => Boolean): Unit = {
// do something involves T
}
is it possibile to restrict T (at compile time) to be a simple type, not a type like List[Int]?
the underling problem I want to solve is something like this:
var actorReceive: Receive = PartialFunction.empty
def addCase[T](handler: T => Boolean): Unit = {
actorReceive = actorReceive orElse ({
case msg: T => // call handle at some point, plus some other logic
handler(msg)
})
}
the addCase function would result in type erasure warning, which could be solved by requiring ClassTag like: def addCase[T: ClassTag](..., but ClassTag still can't guard against calls like:
addCase[List[Int]](_ => {println("Int"); true})
addCase[List[String]](_ => {println("String"); false})
actorReceive(List("str")) // will print "Int"
the above code will print "Int" while not issuing any warning or error at all, is there any way out?
There is no way to enforce this in the type system as-is, without reflection.
The nicest way to do this would be to have a type-class such as NonEraseable[A], that provides evidence that a type has no type parameters that would be erased at runtime. An implicit NonEraseable[A] in scope should mean that A has no type parameters. Seeing as these would be tedious to manually create, an implicit macro can do the job:
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
trait NonEraseable[A]
object NonEraseable {
implicit def ev[A]: NonEraseable[A] = macro evImpl[A]
def evImpl[A](c: Context)(implicit tt: c.WeakTypeTag[A]): c.Expr[NonEraseable[A]] = {
import c.universe._
val tpe = weakTypeOf[A]
if(tpe.dealias.typeArgs.isEmpty)
c.Expr[NonEraseable[A]](q"new NonEraseable[$tpe] {}")
else
c.abort(c.enclosingPosition, s"$tpe contains parameters that will be erased at runtime.")
}
}
Use case:
def onlySimple[A : NonEraseable](value: A): Unit = println(value)
scala> onlySimple(1)
1
scala> onlySimple(List(1, 2, 3))
<console>:13: error: List[Int] contains parameters that will be erased at runtime.
onlySimple(List(1, 2, 3))
^
Using this, you can enforce at compile time that a type parameter A with a context bound NonEraseable is the kind of type you want. (Assuming you don't cheat and manually create instance of the type class)
You can at least get it to fail at run-time as follows:
def addCase[T: ClassTag](handler: T => Boolean): Unit =
if (classTag[T].runtimeClass.getTypeParameters.nonEmpty) {
// throw an exception
} else {
// the main code
}
Compile-time failure can be achieved using a macro instead of a function (approximate, untested):
def addCase[T](handler: T => Boolean): Unit = macro addCaseImpl
def addCaseImpl[T: c.WeakTypeTag](c: Context)(handler: c.Expr[T => Boolean]): c.Expr[Unit] =
if (c.weakTypeOf[T].typeParams.nonEmpty) {
c.abort(c.enclosingPosition, "Generic types not allowed in addCase")
} else {
// generate code for main line
}

What are the limitations on inference of higher-kinded types in Scala?

In the following simplified sample code:
case class One[A](a: A) // An identity functor
case class Twice[F[_], A](a: F[A], b: F[A]) // A functor transformer
type Twice1[F[_]] = ({type L[α] = Twice[F, α]}) // We'll use Twice1[F]#L when we'd like to write Twice[F]
trait Applicative[F[_]] // Members omitted
val applicativeOne: Applicative[One] = null // Implementation omitted
def applicativeTwice[F[_]](implicit inner: Applicative[F]): Applicative[({type L[α] = Twice[F, α]})#L] = null
I can call applicativeTwice on applicativeOne, and type inference works, as soon as I try to call it on applicativeTwice(applicativeOne), inference fails:
val aOK = applicativeTwice(applicativeOne)
val bOK = applicativeTwice[Twice1[One]#L](applicativeTwice(applicativeOne))
val cFAILS = applicativeTwice(applicativeTwice(applicativeOne))
The errors in scala 2.10.0 are
- type mismatch;
found : tools.Two.Applicative[[α]tools.Two.Twice[tools.Two.One,α]]
required: tools.Two.Applicative[F]
- no type parameters for method applicativeTwice:
(implicit inner: tools.Two.Applicative[F])tools.Two.Applicative[[α]tools.Two.Twice[F,α]]
exist so that it can be applied to arguments
(tools.Two.Applicative[[α]tools.Two.Twice[tools.Two.One,α]])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : tools.Two.Applicative[[α]tools.Two.Twice[tools.Two.One,α]]
required: tools.Two.Applicative[?F]
Why wouldn't "?F" match with anything (of the right kind) ?
Ultimately I'd like applicativeTwice to be an implicit function, but I'd have to get the type inference working first.
I have seen similar questions, and the answers pointed to limitations in the type inference algorithms. But this case seems pretty limitative, and must be quite an annoyance in monad transformers, so I suspect I'm missing some trick to work around this.
You've hit a common annoyance: SI-2712. For clarity, I'm going to minimize your code a bit:
import language.higherKinds
object Test {
case class Base[A](a: A)
case class Recursive[F[_], A](fa: F[A])
def main(args: Array[String]): Unit = {
val one = Base(1)
val two = Recursive(one)
val three = Recursive(two) // doesn't compile
println(three)
}
}
This demonstrates the same type error as yours:
argument expression's type is not compatible with formal parameter type;
found : Test.Recursive[Test.Base,Int]
required: ?F
val three = Recursive(two) // doesn't compile
^
First a bit of syntax and terminology you probably already know:
In Scala we say that a plain, unparameterized data type (such as Int) has kind _. It's monomorphic.
Base, on the other hand, is parameterized. we can't use it as the type of a value without providing the type it contains, so we say has kind _[_]. It's rank-1 polymorphic: a type constructor that takes a type.
Recursive goes further still: it has two parameters, F[_] and A. The number of type parameters don't matter here, but their kinds do. F[_] is rank-1 polymorphic, so Recursive is rank-2 polymorphic: it's a type constructor that takes a type constructor.
We call anything rank two or above higher-kinded, and this is where the fun starts.
Scala in general doesn't have trouble with higher-kinded types. This is one of several key features that distinguishes its type system from, say, Java's. But it does have trouble with partial application of type parameters when dealing with higher-kinded types.
Here's the problem: Recursive[F[_], A] has two type parameters. In your sample code, you did the "type lambda" trick to partially apply the first parameter, something like:
val one = Base(1)
val two = Recursive(one)
val three = {
type λ[α] = Recursive[Base, α]
Recursive(two : λ[Int])
}
This convinces the compiler that you're providing something of the correct kind (_[_]) to the Recursive constructor. If Scala had curried type parameter lists, I'd definitely have used that here:
case class Base[A](a: A)
case class Recursive[F[_]][A](fa: F[A]) // curried!
def main(args: Array[String]): Unit = {
val one = Base(1) // Base[Int]
val two = Recursive(one) // Recursive[Base][Int]
val three = Recursive(two) // Recursive[Recursive[Base]][Int]
println(three)
}
Alas, it does not (see SI-4719). So, to the best of my knowledge, the most common way of dealing with this problem is the "unapply trick," due to Miles Sabin. Here is a greatly simplified version of what appears in scalaz:
import language.higherKinds
trait Unapply[FA] {
type F[_]
type A
def apply(fa: FA): F[A]
}
object Unapply {
implicit def unapply[F0[_[_], _], G0[_], A0] = new Unapply[F0[G0, A0]] {
type F[α] = F0[G0, α]
type A = A0
def apply(fa: F0[G0, A0]): F[A] = fa
}
}
In somewhat hand-wavey terms, this Unapply construct is like a "first-class type lambda." We define a trait representing the assertion that some type FA can be decomposed into a type constructor F[_] and a type A. Then in its companion object, we can define implicits to provide specific decompositions for types of various kinds. I've only defined here the specific one that we need to make Recursive fit, but you could write others.
With this extra bit of plumbing, we can now do what we need:
import language.higherKinds
object Test {
case class Base[A](a: A)
case class Recursive[F[_], A](fa: F[A])
object Recursive {
def apply[FA](fa: FA)(implicit u: Unapply[FA]) = new Recursive(u(fa))
}
def main(args: Array[String]): Unit = {
val one = Base(1)
val two = Recursive(one)
val three = Recursive(two)
println(three)
}
}
Ta-da! Now type inference works, and this compiles. As an exercise, I'd suggest you create an additional class:
case class RecursiveFlipped[A, F[_]](fa: F[A])
... which isn't really different from Recursive in any meaningful way, of course, but will again break type inference. Then define the additional plumbing needed to fix it. Good luck!
Edit
You asked for a less simplified version, something aware of type-classes. Some modification is required, but hopefully you can see the similarity. First, here's our upgraded Unapply:
import language.higherKinds
trait Unapply[TC[_[_]], FA] {
type F[_]
type A
def TC: TC[F]
def apply(fa: FA): F[A]
}
object Unapply {
implicit def unapply[TC[_[_]], F0[_[_], _], G0[_], A0](implicit TC0: TC[({ type λ[α] = F0[G0, α] })#λ]) =
new Unapply[TC, F0[G0, A0]] {
type F[α] = F0[G0, α]
type A = A0
def TC = TC0
def apply(fa: F0[G0, A0]): F[A] = fa
}
}
Again, this is completely ripped off from scalaz. Now some sample code using it:
import language.{ implicitConversions, higherKinds }
object Test {
// functor type class
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
// functor extension methods
object Functor {
implicit class FunctorOps[F[_], A](fa: F[A])(implicit F: Functor[F]) {
def map[B](f: A => B) = F.map(fa)(f)
}
implicit def unapply[FA](fa: FA)(implicit u: Unapply[Functor, FA]) =
new FunctorOps(u(fa))(u.TC)
}
// identity functor
case class Id[A](value: A)
object Id {
implicit val idFunctor = new Functor[Id] {
def map[A, B](fa: Id[A])(f: A => B) = Id(f(fa.value))
}
}
// pair functor
case class Pair[F[_], A](lhs: F[A], rhs: F[A])
object Pair {
implicit def pairFunctor[F[_]](implicit F: Functor[F]) = new Functor[({ type λ[α] = Pair[F, α] })#λ] {
def map[A, B](fa: Pair[F, A])(f: A => B) = Pair(F.map(fa.lhs)(f), F.map(fa.rhs)(f))
}
}
def main(args: Array[String]): Unit = {
import Functor._
val one = Id(1)
val two = Pair(one, one) map { _ + 1 }
val three = Pair(two, two) map { _ + 1 }
println(three)
}
}
Note (3 years later, July 2016), scala v2.12.0-M5 is starting to implement SI-2172 (support for higher order unification)
See commit 892a6d6 from Miles Sabin
-Xexperimental mode now only includes -Ypartial-unification
It follows Paul Chiusano's simple algorithm:
// Treat the type constructor as curried and partially applied, we treat a prefix
// as constants and solve for the suffix. For the example in the ticket, unifying
// M[A] with Int => Int this unifies as,
//
// M[t] = [t][Int => t] --> abstract on the right to match the expected arity
// A = Int --> capture the remainder on the left
The test/files/neg/t2712-1.scala includes:
package test
trait Two[A, B]
object Test {
def foo[M[_], A](m: M[A]) = ()
def test(ma: Two[Int, String]) = foo(ma) // should fail with -Ypartial-unification *disabled*
}
And (test/files/neg/t2712-2.scala):
package test
class X1
class X2
class X3
trait One[A]
trait Two[A, B]
class Foo extends Two[X1, X2] with One[X3]
object Test {
def test1[M[_], A](x: M[A]): M[A] = x
val foo = new Foo
test1(foo): One[X3] // fails with -Ypartial-unification enabled
test1(foo): Two[X1, X2] // fails without -Ypartial-unification
}