-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Type inference for dependent type class breaks (regression from Scala 2) #10929
Comments
It looks that this exhibits a difference in how we deal with capture conversion. Scala 2 uses existential types for that which are unavailable in Scala 3. This could make up the difference. If that's the case then I am not sure something can be done about this. |
I found a temporary workaround: given [A, Rest <: Tuple, T <: Rest TupleOf A](using tup: T): TupleOf[A *: Rest, A] with
type Mapped[A] = A *: tup.Mapped[A]
def map[B](x: A *: Rest)(f: A => B): Mapped[B] =
(f(x.head) *: tup.map(x.tail)(f)) The problem was that the precise type of I'd say the issue is more pronounced here than in the general case, because dependent I wonder if something could be done about this issue, at least for the special case of |
So in other words the issue is that: given [A, Rest <: Tuple](using tup: Rest TupleOf A): TupleOf[A *: Rest, A] with
type Mapped[+A] = A *: tup.Mapped[A]
def map[B](x: A *: Rest)(f: A => B): Mapped[B] =
(f(x.head) *: tup.map(x.tail)(f)) is desugared into: class given_TupleOf_A_A[A, Rest <: Tuple](using val tup: Rest TupleOf A) extends TupleOf[A *: Rest, A] {
type Mapped[+A] = A *: tup.Mapped[A]
def map[B](x: A *: Rest)(f: A => B): Mapped[B] =
(f(x.head) *: tup.map(x.tail)(f))
}
implicit def given_TupleOf_A_A[A, Rest <: Tuple](using tup: Rest TupleOf A): TupleOf[A *: Rest, A] =
new given_TupleOf_A_A(using tup) which loses any information about implicit def given_TupleOf_A_A[A, Rest <: Tuple](using tup: Rest TupleOf A): TupleOf[A *: Rest, A] { type Mapped[+A] = A *: tup.Mapped[A] } =
new given_TupleOf_A_A(using tup).asInstanceOf where the |
@smarter alternatively, would it make sense to just automatically add type parameters for each class given_TupleOf_A_A[A, Rest <: Tuple, tup <: Rest TupleOf A](using val tup: tup) extends TupleOf[A *: Rest, A] {
type Mapped[+A] = A *: tup.Mapped[A]
def map[B](x: A *: Rest)(f: A => B): Mapped[B] =
(f(x.head) *: tup.map(x.tail)(f))
}
implicit def given_TupleOf_A_A[A, Rest <: Tuple](using tup: Rest TupleOf A): given_TupleOf_A_A[A, Rest, tup.type] =
new given_TupleOf_A_A(using tup) |
Not sure, that would mean the generated given classes could appear in public signatures due to inference whereas now they're mostly hidden. |
@smarter the generated |
Instead of fiddling with the encoding I'd rather like us to take the plunge and work towards a solution of #3964. |
Maybe related, considering: import scala.deriving.Mirror
class Foo(val s: String)
object Foo {
given Mirror.ProductOf[Foo] = new Mirror.Product {
type MirroredType = Foo
type MirroredElemTypes = Tuple1[String]
type MirroredMonoType = Foo
type MirroredLabel = "Foo"
type MirroredElemLabels = Tuple1["s"]
def fromProduct(p: Product): MirroredMonoType =
new Foo(p.productElement(0).asInstanceOf[String])
}
}
def test[T <: *:[_, EmptyTuple]]: Unit = println("ok") Then
Whereas: test[Tuple1["s"]]
// ok If the given instance is defined using non-anonymous class, it's ok. import scala.deriving.Mirror
class Foo(val s: String)
object Foo {
final class FooProduct extends Mirror.Product {
type MirroredType = Foo
type MirroredElemTypes = Tuple1[String]
type MirroredMonoType = Foo
type MirroredLabel = "Foo"
type MirroredElemLabels = Tuple1["s"]
def fromProduct(p: Product): MirroredMonoType =
new Foo(p.productElement(0).asInstanceOf[String])
}
given pof: FooProduct = new FooProduct
}
def test[T <: *:[_, EmptyTuple]]: Unit = println("ok")
test[Foo.pof.MirroredElemLabels]
// ok |
this type will not carry the refinements of the right hand side, you need to give them explicitly: given (Mirror.ProductOf[Foo] {type MirroredElemLabels = Tuple1["s"]}) = new Mirror.Product { |
@mbovel Adding to your pile since it's about dependent classes. Not expecting a fix anytime soon though. |
If a refined type has a parent type watching some other type, the parent should not be mapped to Object. Previously, the parent counted as `isEmpty` which caused this mapping. Fixes scala#10929
If a refined type has a parent type watching some other type, the parent should not be mapped to Object. Previously, the parent counted as `isEmpty` which caused this mapping. Fixes scala#10929
If a refined type has a parent type watching some other type, the parent should not be mapped to Object. Previously, the parent counted as `isEmpty` which caused this mapping. Fixes scala#10929
If a refined type has a parent type watching some other type, the parent should not be mapped to Object. Previously, the parent counted as `isEmpty` which caused this mapping. Fixes scala#10929
If a refined type has a parent type watching some other type, the parent should not be mapped to Object. Previously, the parent counted as `isEmpty` which caused this mapping. Fixes scala#10929
If a refined type has a parent type watching some other type, the parent should not be mapped to Object. Previously, the parent counted as `isEmpty` which caused this mapping. Fixes scala#10929
If a refined type has a parent type watching some other type, the parent should not be mapped to Object. Previously, the parent counted as `isEmpty` which caused this mapping. Fixes scala#10929
If a refined type has a parent type watching some other type, the parent should not be mapped to Object. Previously, the parent counted as `isEmpty` which caused this mapping. Fixes scala#10929
Minimized code
https://scastie.scala-lang.org/TQKBd1mmR6qygyuY0vMSMg
It works in Scala 2 : https://scastie.scala-lang.org/XTg2Thj5QYSyEzSNL5xUpQ
Output
Expectation
Compiles. The
Mapped
type of anyTupleOf.given_TupleOf_A_A[Int, EmptyTuple.type]
value is[A] =>> A *: EmptyTuple
. So?1.Mapped[Int]
should be reduced toInt *: EmptyTuple
.The text was updated successfully, but these errors were encountered: