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
warn on refutable patterns in pattern valdef #5898
Comments
Imported From: https://issues.scala-lang.org/browse/SI-5898?orig=1 |
Aaron Novstrup (anovstrup) said: |
Aaron Novstrup (anovstrup) said: Some alternative solutions:
|
@LilyLambda said: |
Aaron Novstrup (anovstrup) said (edited on Jun 20, 2011 3:24:44 AM UTC): Semantics aside (I'm more concerned with the issue than with the title), the problem with these constructs is that there is no clue in the syntax that unchecked matching is going on and that a runtime error may arise. Furthermore, there is no reason that unchecked matching should be going on (in the very common, specific cases considered here, such as tuples and case classes). Having a match error occur in what appears to be a perfectly safe assignment is similar to having something like a MissingMethodError occur on a method call when it is known at compile time that the method is not a member of the target object's type. |
@SethTisue said: "val (a,b) = 1: Any" is pretty strange code. The ": Any" tells the compiler, "forget Why I would be using practically useless, vague types like Any and Product anyway...? I'm not critiquing your overall goals here, I'm just saying you need more compelling |
Aaron Novstrup (anovstrup) said (edited on Jun 20, 2011 9:27:18 PM UTC): https://groups.google.com/d/topic/scala-user/21IbHRhgxQU/discussion "The real danger, of course, is that the right-hand side need not be The complaint is not that the compiler does not use its knowledge of what "1" is, but rather that it doesn't use its knowledge of what Tuple2 is. Any unintended widening of the static type on the right-hand side could lead to runtime failure. Here's a more realistic example (although it fails the simplicity test): class Character(name: String)
case class Player(name: String, age: Int, gender: Gender) extends Character(name)
case class NPC(name: String, species: Species, language: Lang) extends Character(name)
// Originally, getCharacter returns a Player. Later, it's modified
// to return a Character. After the change, the following line of
// code will still compile but may fail at runtime.
val Player(_, a, g) = getCharacter("Dingus") The original developer intended his code as shorthand for val c = getCharacter("Dingus")
val a = c.age
val g = c.gender which would fail to compile after the change in |
Aaron Novstrup (anovstrup) said (edited on Jun 20, 2011 9:31:50 PM UTC): // original
List(1 -> "a", 2 -> "b") map { p => val (a,b) = p; a + " -> " + b }
// changed: oops!
List(1 -> "a", 2 -> "b", 3) map { p => val (a,b) = p; a + " -> " + b } |
@som-snytt is scala/scala#7526 something you plan to pick up again, or is this up for grabs? |
@SethTisue that one was resubmitted and merged. I don't remember, but I don't think it's enough to close the ticket. |
oh, scala/scala#7687 |
@SethTisue sorry to make work for you. Unless you need work? Probably you don't need work. |
it beats watching TV |
Value/variable definitions with patterns expand into unsafe matches in cases where a safe alternative is feasible. For example, all of the following definitions compile without even a warning, but inevitably fail with MatchErrors at runtime:
Desired behavior:
The definitions above should not compile. In cases where unsafe pattern matching cannot be avoided (e.g.
val x :: xs = list
), the compiler should issue a warning. Additional syntax could be used to eliminate the warning (e.g.val case x :: xs = list
) or to indicate the desire for an unsafe pattern match (e.g.val case (a,b) = x: Any
). The existing behavior is per spec, but given the violation of type safety it seems appropriate to consider this issue a "Bug" rather than an "Improvement".Proposed solution:
To facilitate the desired behavior, unapply methods should declare Some as their return type whenever possible. In particular, the generated unapply methods for case classes should guarantee a Some return value. For example, Tuple2.unapply could be written
Then, when an appropriate unapply method is available (i.e. one that is guaranteed to return a Some), the expansions of value/variable definitions would call these methods directly rather than resorting to pattern matching. Thus
would expand to
When an appropriate unapply method is not available (i.e. unapply returns an Option), the compiler would expand the definition into a pattern match but issue a warning.
The text was updated successfully, but these errors were encountered: