-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
codifies the state of the art wrt SI-8104
As it was discovered in SI-8104, whiteboxity doesn’t apply equally to type parameters and type members of materialized type classes. During implicit search and subsequent type inference, whitebox type parameters are consistently erased to wildcards, whereas whitebox type members sometimes remain as is and get in the way of signature conformance checks.
- Loading branch information
Showing
6 changed files
with
64 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Test_2.scala:20: error: could not find implicit value for parameter e: Generic.Aux[Test.C,(Int, Int)] | ||
implicitly[Generic.Aux[C, (Int, Int)]] | ||
^ | ||
one error found |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import scala.reflect.macros.WhiteboxContext | ||
|
||
object Macros { | ||
def impl[T](c: WhiteboxContext)(implicit T: c.WeakTypeTag[T]) = { | ||
import c.universe._ | ||
import definitions._ | ||
val fields = T.tpe.declarations.toList.collect{ case x: TermSymbol if x.isVal && x.isCaseAccessor => x } | ||
val Repr = appliedType(TupleClass(fields.length).asType.toType, fields.map(_.typeSignature)) | ||
q"new Generic[$T]{ type Repr = $Repr }" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
trait Generic[T] { type Repr } | ||
object Generic { | ||
type Aux[T, Repr0] = Generic[T] { type Repr = Repr0 } | ||
import scala.language.experimental.macros | ||
implicit def materializeGeneric[T]: Generic[T] = macro Macros.impl[T] | ||
} | ||
|
||
object Test extends App { | ||
case class C(x: Int, y: Int) | ||
|
||
import scala.reflect.runtime.universe._ | ||
def reprify[T, Repr](x: T)(implicit generic: Generic.Aux[T, Repr], tag: TypeTag[Repr]) = println(tag) | ||
reprify(C(40, 2)) | ||
|
||
// this is a compilation error at the moment as explained in SI-8104 | ||
// because matchesPt in implicit search says that depoly(<type of materializeGeneric>) isn't a subtype of Generic.Aux[C, (Int, Int)] | ||
// which is rightfully so, because depoly only replaces type parameters, not type members with wildcard types | ||
// however in the future we might want to relax the matchesPt check, so this might start compiling | ||
// therefore, if you've broken this test, then you should be happy, because most likely you've just enabled an interesting use case! | ||
implicitly[Generic.Aux[C, (Int, Int)]] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
TypeTag[(Int, Int)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import scala.reflect.macros.WhiteboxContext | ||
|
||
object Macros { | ||
def impl[T](c: WhiteboxContext)(implicit T: c.WeakTypeTag[T]) = { | ||
import c.universe._ | ||
import definitions._ | ||
val fields = T.tpe.declarations.toList.collect{ case x: TermSymbol if x.isVal && x.isCaseAccessor => x } | ||
val Repr = appliedType(TupleClass(fields.length).asType.toType, fields.map(_.typeSignature)) | ||
q"new Generic[$T]{ type Repr = $Repr }" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
trait Generic[T] { type Repr } | ||
object Generic { | ||
type Aux[T, Repr0] = Generic[T] { type Repr = Repr0 } | ||
import scala.language.experimental.macros | ||
implicit def materializeGeneric[T, Repr]: Generic.Aux[T, Repr] = macro Macros.impl[T] | ||
} | ||
|
||
object Test extends App { | ||
case class C(x: Int, y: Int) | ||
|
||
import scala.reflect.runtime.universe._ | ||
def reprify[T, Repr](x: T)(implicit generic: Generic.Aux[T, Repr], tag: TypeTag[Repr]) = println(tag) | ||
reprify(C(40, 2)) | ||
|
||
implicitly[Generic.Aux[C, (Int, Int)]] | ||
} |