See here for the current (draft) proposal. It is still incomplete, but I think it is in a fleshed-out enough state to start the pre-sip discussion.
There are several outstanding questions namely about mirror support which I’m still unclear on:
Should productArity and productElement be promoted onto the Mirror trait?
Should a new anonymous class be created each time at the callsite; does the reasoning which went into including the TupleMirror apply here?
Is it a problem to include a class which only compiles with JDK16+ in the compilation process of the runtime library?
What happens if I refer to a method on the companion object for the Java class at runtime? Do we still go through the same desugar steps in the compiler with a compiled jar?
I have also left the specification until some of the questions are (hopefully) answered by the Pre-SIP discussion.
It should be noted, that the current eco-system implicitly assumes that a Mirror.Product returns a class which extends Product even though there are no type bounds on the actual trait itself. This is implied by the example in the official documentation and can be seen in the source code of well-used libraries in the wild.
[…]
Releasing the changes proposed would mean that a codec would be able to be derived for a record, but the program would fail at runtime — which is not ideal behaviour.
This is pretty unfortunate indeed. One way to work around this would be to create new types that would generalize the existing Mirror types. This might be worth it if we’d like to support other non-Product things, for example, classes with multiple parameter lists. It could also let us replace fromProduct by something that takes into account apply methods: Case class deserialization doesn't go through `apply` in Scala 3 · Issue #552 · com-lihaoyi/upickle · GitHub
One other relevant suggestion is here from @lihaoyi. If we introduced a new mirror type which was something like,
trait Mirror.NamedProduct:
// type aliases same as `Mirror.Product`
type MirrorElemLabels <: Tuple
type MirroredLabel <: String
type MirrorMonoType
// These allow a user of the mirror to abstract over named products at runtime
def productArity: Int
def productElementAt(i: Int): Any
def fromProduct(p: Product): MirroredMonoType
And make it derivable for both T <: NamedTuple and records.
Perhaps we could even use it to address @odersky point from below:
But the problem is we can’t abstract over it. If we want to have a generic type that reflects names and types, we are back to NamedTuple.
Since you can use the methods on the mirror to abstract over the T <: NamedProduct.