Skip to content

Commit 9a1e7cb

Browse files
prolativKordyjan
authored andcommitted
Raise a warning instead of an error for a type ascription on a pattern other than a variable or a number literal.
This partially reverts the changes from #16150. This change is motivated by not breaking source compatibility for a number of projects in the Open Community Build.
1 parent 752ad2f commit 9a1e7cb

File tree

9 files changed

+83
-22
lines changed

9 files changed

+83
-22
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

+5-5
Original file line numberDiff line numberDiff line change
@@ -2821,14 +2821,14 @@ object Parsers {
28212821
if (isIdent(nme.raw.BAR)) { in.nextToken(); pattern1(location) :: patternAlts(location) }
28222822
else Nil
28232823

2824-
/** Pattern1 ::= PatVar Ascription
2825-
* | [‘-’] integerLiteral Ascription
2826-
* | [‘-’] floatingPointLiteral Ascription
2827-
* | Pattern2
2824+
/** Pattern1 ::= Pattern2 [Ascription]
28282825
*/
28292826
def pattern1(location: Location = Location.InPattern): Tree =
28302827
val p = pattern2()
2831-
if (isVarPattern(p) || p.isInstanceOf[Number]) && in.isColon then
2828+
if in.isColon then
2829+
val isVariableOrNumber = isVarPattern(p) || p.isInstanceOf[Number]
2830+
if !isVariableOrNumber then
2831+
warning(em"Only variable and number literal patterns can have type ascriptions")
28322832
in.nextToken()
28332833
ascription(p, location)
28342834
else p

docs/_docs/internals/syntax.md

+1-4
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,7 @@ TypeCaseClauses ::= TypeCaseClause { TypeCaseClause }
319319
TypeCaseClause ::= ‘case’ (InfixType | ‘_’) ‘=>’ Type [semi]
320320
321321
Pattern ::= Pattern1 { ‘|’ Pattern1 } Alternative(pats)
322-
Pattern1 ::= PatVar ‘:’ RefinedType Bind(name, Typed(Ident(wildcard), tpe))
323-
| [‘-’] integerLiteral ‘:’ RefinedType Typed(pat, tpe)
324-
| [‘-’] floatingPointLiteral ‘:’ RefinedType Typed(pat, tpe)
325-
| Pattern2
322+
Pattern1 ::= Pattern2 [‘:’ RefinedType] Bind(name, Typed(Ident(wildcard), tpe))
326323
Pattern2 ::= [id ‘@’] InfixPattern [‘*’] Bind(name, pat)
327324
InfixPattern ::= SimplePattern { id [nl] SimplePattern } InfixOp(pat, op, pat)
328325
SimplePattern ::= PatVar Ident(wildcard)

docs/_docs/reference/syntax.md

+1-4
Original file line numberDiff line numberDiff line change
@@ -312,10 +312,7 @@ TypeCaseClauses ::= TypeCaseClause { TypeCaseClause }
312312
TypeCaseClause ::= ‘case’ (InfixType | ‘_’) ‘=>’ Type [semi]
313313
314314
Pattern ::= Pattern1 { ‘|’ Pattern1 }
315-
Pattern1 ::= PatVar ‘:’ RefinedType
316-
| [‘-’] integerLiteral ‘:’ RefinedType
317-
| [‘-’] floatingPointLiteral ‘:’ RefinedType
318-
| Pattern2
315+
Pattern1 ::= Pattern2 [‘:’ RefinedType]
319316
Pattern2 ::= [id ‘@’] InfixPattern [‘*’]
320317
InfixPattern ::= SimplePattern { id [nl] SimplePattern }
321318
SimplePattern ::= PatVar

tests/neg/i15893.scala renamed to tests/neg-custom-args/fatal-warnings/i15893.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ transparent inline def transparentInlineMod2(inline n: NatT): NatT = inline n m
2222
case Succ(Zero()) => Succ(Zero())
2323
case Succ(Succ(predPredN)) => transparentInlineMod2(predPredN)
2424

25-
def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match // exhaustivity warning; unexpected
25+
def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match
2626
case Zero(): Zero => Zero() // error
2727
case Succ(Zero()): Succ[Zero] => Succ(Zero()) // error
2828
case Succ(Succ(predPredN)): Succ[Succ[_]] => dependentlyTypedMod2(predPredN) // error
@@ -57,5 +57,5 @@ inline def transparentInlineFoo(inline n: NatT): NatT = inline transparentInline
5757
println(transparentInlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
5858
println(transparentInlineFoo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected
5959
println(dependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // runtime error; unexpected
60-
// println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected
61-
// println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected
60+
println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
61+
println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected

tests/neg/t5702-neg-bad-and-wild.check

+7-3
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
| pattern expected
1111
|
1212
| longer explanation available when compiling with `-explain`
13-
-- [E040] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:13:22 ---------------------------------------------------
13+
-- [E040] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:13:23 ---------------------------------------------------
1414
13 | case List(1, _*3:) => // error // error
15-
| ^
16-
| ')' expected, but ':' found
15+
| ^
16+
| an identifier expected, but ')' found
1717
-- [E032] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:15:18 ---------------------------------------------------
1818
15 | case List(x*, 1) => // error: pattern expected
1919
| ^
@@ -56,6 +56,10 @@
5656
| Recursive value $1$ needs type
5757
|
5858
| longer explanation available when compiling with `-explain`
59+
-- Warning: tests/neg/t5702-neg-bad-and-wild.scala:13:22 ---------------------------------------------------------------
60+
13 | case List(1, _*3:) => // error // error
61+
| ^
62+
| Only variable and number literal patterns can have type ascriptions
5963
-- Warning: tests/neg/t5702-neg-bad-and-wild.scala:22:20 ---------------------------------------------------------------
6064
22 | val K(x @ _*) = k
6165
| ^

tests/pending/run/i15893.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ transparent inline def transparentInlineMod2(inline n: NatT): NatT = inline n m
2424
case Succ(Zero()) => Succ(Zero())
2525
case Succ(Succ(predPredN)) => transparentInlineMod2(predPredN)
2626
*/
27-
def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match // exhaustivity warning; unexpected
27+
def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match
2828
case Zero(): Zero => Zero()
2929
case Succ(Zero()): Succ[Zero] => Succ(Zero())
3030
case Succ(Succ(predPredN)): Succ[Succ[_]] => dependentlyTypedMod2(predPredN)
@@ -61,5 +61,5 @@ inline def transparentInlineFoo(inline n: NatT): NatT = inline transparentInline
6161
println(transparentInlineFoo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected
6262
*/
6363
println(dependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // runtime error; unexpected
64-
// println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected
65-
// println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected
64+
// println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
65+
// println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected

tests/pos/i10994.scala

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def foo = true match
2+
case (b: Boolean): Boolean => ()

tests/pos/i15893.scala

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
sealed trait NatT
2+
case class Zero() extends NatT
3+
case class Succ[+N <: NatT](n: N) extends NatT
4+
5+
type Mod2[N <: NatT] <: NatT = N match
6+
case Zero => Zero
7+
case Succ[Zero] => Succ[Zero]
8+
case Succ[Succ[predPredN]] => Mod2[predPredN]
9+
10+
def mod2(n: NatT): NatT = n match
11+
case Zero() => Zero()
12+
case Succ(Zero()) => Succ(Zero())
13+
case Succ(Succ(predPredN)) => mod2(predPredN)
14+
15+
inline def inlineMod2(inline n: NatT): NatT = inline n match
16+
case Zero() => Zero()
17+
case Succ(Zero()) => Succ(Zero())
18+
case Succ(Succ(predPredN)) => inlineMod2(predPredN)
19+
20+
transparent inline def transparentInlineMod2(inline n: NatT): NatT = inline n match
21+
case Zero() => Zero()
22+
case Succ(Zero()) => Succ(Zero())
23+
case Succ(Succ(predPredN)) => transparentInlineMod2(predPredN)
24+
25+
def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match
26+
case Zero(): Zero => Zero() // warning
27+
case Succ(Zero()): Succ[Zero] => Succ(Zero()) // warning
28+
case Succ(Succ(predPredN)): Succ[Succ[_]] => dependentlyTypedMod2(predPredN) // warning
29+
30+
inline def inlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match
31+
case Zero(): Zero => Zero() // warning
32+
case Succ(Zero()): Succ[Zero] => Succ(Zero()) // warning
33+
case Succ(Succ(predPredN)): Succ[Succ[_]] => inlineDependentlyTypedMod2(predPredN) // warning
34+
35+
transparent inline def transparentInlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match
36+
case Zero(): Zero => Zero() // warning
37+
case Succ(Zero()): Succ[Zero] => Succ(Zero()) // warning
38+
case Succ(Succ(predPredN)): Succ[Succ[_]] => transparentInlineDependentlyTypedMod2(predPredN) // warning
39+
40+
def foo(n: NatT): NatT = mod2(n) match
41+
case Succ(Zero()) => Zero()
42+
case _ => n
43+
44+
inline def inlineFoo(inline n: NatT): NatT = inline inlineMod2(n) match
45+
case Succ(Zero()) => Zero()
46+
case _ => n
47+
48+
inline def transparentInlineFoo(inline n: NatT): NatT = inline transparentInlineMod2(n) match
49+
case Succ(Zero()) => Zero()
50+
case _ => n
51+
52+
@main def main(): Unit =
53+
println(mod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
54+
println(foo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected
55+
println(inlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
56+
println(inlineFoo(Succ(Succ(Succ(Zero()))))) // prints Succ(Succ(Succ(Zero()))); unexpected
57+
println(transparentInlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
58+
println(transparentInlineFoo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected
59+
println(dependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // runtime error; unexpected
60+
println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
61+
println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected

0 commit comments

Comments
 (0)