Skip to content

Commit 6f87f90

Browse files
mbovelclaude
andcommitted
Use wildcard type instead of whitebox cast in IsoFields
Replace the `whitebox` cast (`asInstanceOf[Expr[Iso[S, Tuple]]]`) with a proper wildcard return type using `PIso[S, S, ? <: Tuple, ? <: Tuple]`. Since `IsoFields.apply` is a `transparent inline` method, the compiler still infers the precise tuple type at call sites. This avoids the unsafe cast and prepares for potential stricter macro type checking in future Scala versions. The motivation is to prepare for future stricter checks in the Scala 3 compiler. The current implementation exploits a missing check to generate an unsound cast. Note: we use `PIso` (a trait) directly instead of the `Iso` type alias (defined as `type Iso[S, A] = PIso[S, S, A, A]`) because Scala 3 cannot reduce higher-kinded type aliases applied to wildcard arguments. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5f9f17b commit 6f87f90

2 files changed

Lines changed: 6 additions & 11 deletions

File tree

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
11
package monocle.internal
22

3-
import monocle.Iso
3+
import monocle.{Iso, PIso}
44
import scala.quoted.{quotes, Expr, Quotes, Type}
55
import scala.deriving.Mirror
66

77
object IsoFields {
8-
transparent inline def apply[S <: Product](using mirror: Mirror.ProductOf[S]): Iso[S, Tuple] =
8+
transparent inline def apply[S <: Product](using mirror: Mirror.ProductOf[S]): PIso[S, S, ? <: Tuple, ? <: Tuple] =
99
${ IsoFieldsImpl.apply[S]('mirror) }
1010
}
1111

1212
private[monocle] object IsoFieldsImpl {
1313

14-
def apply[S <: Product](mirror: Expr[Mirror.ProductOf[S]])(using Quotes, Type[S]): Expr[Iso[S, Tuple]] = {
15-
16-
def whitebox[A <: Tuple](e: Expr[Iso[S, A]]): Expr[Iso[S, Tuple]] =
17-
e.asInstanceOf[Expr[Iso[S, Tuple]]]
18-
14+
def apply[S <: Product](mirror: Expr[Mirror.ProductOf[S]])(using Quotes, Type[S]): Expr[PIso[S, S, ? <: Tuple, ? <: Tuple]] =
1915
mirror match {
2016
case '{ type a <: Tuple; $m: Mirror.ProductOf[S] { type MirroredElemTypes = `a` } } =>
21-
whitebox('{
17+
'{
2218
val f: S => a = Tuple.fromProductTyped(_)(using $m)
2319
val g: a => S = $m.fromProduct(_)
2420
Iso[S, a](f)(g)
25-
})
21+
}
2622
}
27-
}
2823
}

core/shared/src/main/scala-3/monocle/syntax/MacroSyntax.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ trait MacroSyntax {
1313
* Case classes with 0 fields will correspond with `EmptyTuple`, 1 with `Tuple1[field type]`, 2 or more with a
1414
* tuple of all field types in the same order as the fields themselves.
1515
*/
16-
transparent inline def fields[S <: Product: Mirror.ProductOf]: Iso[S, Tuple] =
16+
transparent inline def fields[S <: Product: Mirror.ProductOf]: PIso[S, S, ? <: Tuple, ? <: Tuple] =
1717
IsoFields[S]
1818
}
1919

0 commit comments

Comments
 (0)