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
Missing type parameter inference for stable identifier patterns. #785
Comments
Imported From: https://issues.scala-lang.org/browse/SI-785?orig=1 |
Lauri Alanko (lealanko) said: The specification states (8.1.4) that v matches a stable identifier class C(name : String) {
override def equals(o : Any) = {
Console.println(name + " == ...")
super.equals(o)
}
}
object O extends C("O")
val V = new C("V")
scala> val ov = O match { case V => true; case _ => false }
O == ...
ov: Boolean = false Either the specification or implementation is in error. When matching against an object, even though it is a stable identifier scala> val ov = V match { case O => true; case _ => false }
ov: Boolean = false Presumably direct reference equality is used, and this is indeed Thus, an object pattern as currently implemented is not a stable An object pattern provides stronger type refinement than a singleton type pattern. object O
scala> def f[X] : X => X = { case O => O }
f: [X](X) => X
scala> def g[X] : X => X = { case _:O.type => O }
<console>:5: error: type mismatch;
found : O.type (with underlying type object O)
required: X
def g[X] : X => X = { case _:O.type => O } Presumably matching to O gives us constraints X <: O.type <: X on the However, for an explicit type pattern, we only get the constraint X <: Singleton type patterns should be given special treatment to make them Summary: Object patterns currently behave differently both from other stable Here's a sketch of the situation and my view of how it should be: pattern matched with type refinement
spec impl ideal spec impl ideal
object == eq eq none? strong strong
other stable id == ==(rev) eq none? none strong
singleton type eq eq eq weak weak weak or strong The point of stable identifiers is that they have these wonderful Yet, on the other hand, it would also be at times useful to have def f[X] : Class[X] => X = { case { classOf[int] } => 42 } provide the proper type refinements, which of course requires that the def f[X] : Class[X] => X = {
val IC = classOf[int]
{ case _ : IC.type => 42 }
} As a general rule in programming language design, I think that if a So, both eq-compared type-refinable matches and ==-compared |
Lauri Alanko (lealanko) said: object T3 {
class A { type T }
case class B[X]
object C extends B[Int]
def f[X](b : B[X]) : A { type T = X } = b match {
case C => new A { type T = Int }
}
}
T3.scala:6: error: type mismatch;
found : T3.A{ ... }
required: T3.A{type T = X}
case C => new A { type T = Int } However, this can be worked around by using a simple wrapper class around the refined type. With the following change it works: def f[X](b : B[X]) : A { type T = X } = {
case class W[Y](a : A { type T = Y })
val w : W[X] = b match {
case C => W[Int](new A { type T = Int })
}
w.a
} |
@odersky said: |
@paulp said:
Can you clarify what is no longer working? I can't tell what you are referring to. I find about the same behavior for everything I tried. scala> trait T[X]
defined trait T
scala> object O extends T[Int]
defined module O
scala> def f[X] : T[X] => X = { case O => 42 }
f: [X](T[X]) => X
scala> val V = new T[Int] { }
V: java.lang.Object with T[Int] = $$anon$$1@50ec2522
scala> def g[X] : T[X] => X = { case V => 42 }
<console>:7: error: type mismatch;
found : Int(42)
required: X
def g[X] : T[X] => X = { case V => 42 }
^
scala> def g[X] : T[X] => X = { case _ : V.type => 42 }
g: [X](T[X]) => X
scala> g(V)
res0: Int = 42 |
@harrah said: |
@paulp said: |
This is both a report of a defect in the specification and a
minor enhancement request for the implementation.
GADT-style dependent case analysis works for objects:
O is syntactically a stable identifier pattern (8.1.4), but
dependent case analysis isn't defined for them in section 8.3 of
the specification. Their treatment seems straightforwardly
analogous to the treatment of constructor patterns, though: {
case O => 42 } just gets translated to { case _ : O.type => 42 }.
This description is currently missing from the specification.
Moreover, it seems that with the current implementation, the
above rule only works for objects, not for other stable
identifiers.
Still, manual translation to a type pattern works all right:
This seems inconsistent. I very much think all stable identifiers
should be treated uniformly. My immediate motivation for this is
that it makes writing a typecase somewhat neater. Given:
Currently one has to write:
Instead of the prettier:
The text was updated successfully, but these errors were encountered: