-
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
Regression in foldables-io/skunk-tables
for match types: with error "selector is uninhabited" but selector is actually inhabited
#21295
Comments
The same commit pointed out by bisect leads to failures in other projects Reproducer//> using options -Ykind-projector:underscores
sealed trait Monomial[A, B, Y]
object Monomial:
case class Interface[A, B, Y](yᵉˣᵖ: A => Y, coeff: B) extends Monomial[A, B, Y]
case class Store[S, Y](yᵉˣᵖ: S => Y, coeff: S) extends Monomial[S, S, Y]
case class StoreF[F[_], S, Y](yᵉˣᵖ: F[S] => Y, coeff: S) extends Monomial[F[S], S, Y]
import Monomial.{Store, Interface, StoreF}
trait Mealy[P[_]]:
def init[Y]: Init[P, Y]
type ~>[P[_], Q[_]] = PolyMap[P, Q, _]
abstract class PolyMap[P[_], Q[_], Y]
type Init[P[_], Y] = P[Y] match
case PolyMap[p, q, Y] => Init[p, Y]
case Store[s, Y] => s
case StoreF[f, s, Y] => s
case Interface[a, b, Y] => b
case Tensor[p, q, Y] => (Init[p, Y], Init[q, Y])
type ⊗[P[_], Q[_]] = Tensor[P, Q, _]
abstract class Tensor[P[_], Q[_], Y]
object tensors:
extension [S1, S2, A1, B1, A2, B2] (m1: Mealy[Store[S1, _] ~> Interface[A1, A1 => B1, _]])
def ⊗(m2: Mealy[Store[S2, _] ~> Interface[A2, A2 => B2, _]]): Mealy[(Store[S1, _] ⊗ Store[S2, _]) ~> (Interface[A1, A1 => B1, _] ⊗ Interface[A2, A2 => B2, _])] =
new Mealy[(Store[S1, _] ⊗ Store[S2, _]) ~> (Interface[A1, A1 => B1, _] ⊗ Interface[A2, A2 => B2, _])]:
def init[Y]: Init[(Store[S1, _] ⊗ Store[S2, _]) ~> (Interface[A1, A1 => B1, _] ⊗ Interface[A2, A2 => B2, _]), Y] =
(m1.init, m2.init) Output[error] ./src/main/scala/usage.scala:31:12
[error] Found: Init[
[error] ([_] =>> Monomial.Store[S1, _]) ~>
[error] ([_²] =>> Monomial.Interface[A1, A1 => B1, _²]),
[error] Y]
[error] Required: S1
[error]
[error] where: Y is a type variable
[error] _ is a type variable
[error] _² is a type variable
[error] (m1.init, m2.init)
[error] ^^^^^^^
[error] ./src/main/scala/usage.scala:31:21
[error] Found: Init[
[error] ([_] =>> Monomial.Store[S2, _]) ~>
[error] ([_²] =>> Monomial.Interface[A2, A2 => B2, _²]),
[error] Y]
[error] Required: S2
[error]
[error] where: Y is a type variable
[error] _ is a type variable
[error] _² is a type variable
[error] (m1.init, m2.init)
[error] |
@sjrd Can you take a look to see whether the breakages are inevitable or whether there is some mitigation? |
I'll have a look on Monday. |
The match type error "failed since selector is uninhabited" fires when the selector is a parameterized trait applied to Nothing, which is wrong since it doesn't preclude it from being inhabited. Here's a minimization: sealed trait Foo[A]
final class Bar extends Foo[Nothing]
object Test:
type Extract[T] = T match
case Foo[_] => Int
val x: Extract[Bar] = 1 8 | val x: Extract[Bar] = 1
| ^
| Found: (1 : Int)
| Required: Test.Extract[Bar]
|
| Note: a match type could not be fully reduced:
|
| trying to reduce Test.Extract[Bar]
| failed since selector Bar
| is uninhabited (there are no values of that type). |
foldables-io/skunk-tables
for match typesfoldables-io/skunk-tables
for match types: with error "selector is uninhabited" but selector is actually inhabited
Looks like we approximate |
This is going to be a problem. It shows that scala3/compiler/src/dotty/tools/dotc/core/TypeComparer.scala Lines 3239 to 3244 in a672e05
However this is bound to destroy other existing use cases. There are existing tests that do not pass anymore if we make that change. We could also be more surgical and still conclude disjointness if we can show that at least one of the sides cannot be instantiated to def invariantDisjoint(tp1: Type, tp2: Type, tparam: TypeParamInfo): Boolean =
provablyDisjoint(tp1, tp2, pending)
&& {
typeparamCorrespondsToField(cls.appliedRef, tparam)
|| cannotBeNothing(tp1) || cannotBeNothing(tp2)
} but It looks like this is a dead end for now. A workaround is not to use |
…iant type params. If `Foo[T]` is invariant in `T`, we previously concluded that `Foo[A] ⋔ Foo[B]` from `A ⋔ B`. That is however wrong if both `A` and `B` can be (instantiated to) `Nothing`. We now rule out these occurrences in two ways: * either we show that `T` corresponds to a field, like we do in the covariant case, or * we show that `A` or `B` cannot possibly be `Nothing`. The second condition is shaky at best. I would have preferred not to include it. However, introducing the former without the fallback on the latter breaks too many existing test cases.
…iant type params. If `Foo[T]` is invariant in `T`, we previously concluded that `Foo[A] ⋔ Foo[B]` from `A ⋔ B`. That is however wrong if both `A` and `B` can be (instantiated to) `Nothing`. We now rule out these occurrences in two ways: * either we show that `T` corresponds to a field, like we do in the covariant case, or * we show that `A` or `B` cannot possibly be `Nothing`. The second condition is shaky at best. I would have preferred not to include it. However, introducing the former without the fallback on the latter breaks too many existing test cases.
…type params. (#21891) If `Foo[T]` is invariant in `T`, we previously concluded that `Foo[A] ⋔ Foo[B]` from `A ⋔ B`. That is however wrong if both `A` and `B` can be (instantiated to) `Nothing`. We now rule out these occurrences in two ways: * either we show that `T` corresponds to a field, like we do in the covariant case, or * we show that `A` or `B` cannot possibly be `Nothing`. The second condition is shaky at best. I would have preferred not to include it. However, introducing the former without the fallback on the latter breaks too many existing test cases.
…type params. If `Foo[T]` is invariant in `T`, we previously concluded that `Foo[A] ⋔ Foo[B]` from `A ⋔ B`. That is however wrong if both `A` and `B` can be (instantiated to) `Nothing`. We now rule out these occurrences in two ways: * either we show that `T` corresponds to a field, like we do in the covariant case, or * we show that `A` or `B` cannot possibly be `Nothing`. The second condition is shaky at best. I would have preferred not to include it. However, introducing the former without the fallback on the latter breaks too many existing test cases. [Cherry-picked 0dceb7f]
…iant type params. If `Foo[T]` is invariant in `T`, we previously concluded that `Foo[A] ⋔ Foo[B]` from `A ⋔ B`. That is however wrong if both `A` and `B` can be (instantiated to) `Nothing`. We now rule out these occurrences in two ways: * either we show that `T` corresponds to a field, like we do in the covariant case, or * we show that `A` or `B` cannot possibly be `Nothing`. The second condition is shaky at best. I would have preferred not to include it. However, introducing the former without the fallback on the latter breaks too many existing test cases.
…iant type params. If `Foo[T]` is invariant in `T`, we previously concluded that `Foo[A] ⋔ Foo[B]` from `A ⋔ B`. That is however wrong if both `A` and `B` can be (instantiated to) `Nothing`. We now rule out these occurrences in two ways: * either we show that `T` corresponds to a field, like we do in the covariant case, or * we show that `A` or `B` cannot possibly be `Nothing`. The second condition is shaky at best. I would have preferred not to include it. However, introducing the former without the fallback on the latter breaks too many existing test cases.
Compiler version
Last good release: 3.6.0-RC1-bin-20240719-af933c4-NIGHTLY
First bad release: 3.6.0-RC1-bin-20240723-46ff151-NIGHTLY
Bisect points to b7846c4
Minimized code
Output
Expectation
Should compile (probably)
The text was updated successfully, but these errors were encountered: