Skip to content
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

Just warn on type ascription on a pattern #17454

Merged
merged 2 commits into from May 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 12 additions & 1 deletion compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Expand Up @@ -2878,7 +2878,18 @@ object Parsers {
*/
def pattern1(location: Location = Location.InPattern): Tree =
val p = pattern2()
if (isVarPattern(p) || p.isInstanceOf[Number]) && in.isColon then
if in.isColon then
val isVariableOrNumber = isVarPattern(p) || p.isInstanceOf[Number]
if !isVariableOrNumber then
report.gradualErrorOrMigrationWarning(
em"""Type ascriptions after patterns other than:
| * variable pattern, e.g. `case x: String =>`
| * number literal pattern, e.g. `case 10.5: Double =>`
|are no longer supported. Remove the type ascription or move it to a separate variable pattern.""",
in.sourcePos(),
warnFrom = `3.3`,
errorFrom = future
)
in.nextToken()
ascription(p, location)
else p
Expand Down
1 change: 1 addition & 0 deletions compiler/test/dotty/tools/dotc/CompilationTests.scala
Expand Up @@ -185,6 +185,7 @@ class CompilationTests {
compileFile("tests/neg-custom-args/i13026.scala", defaultOptions.and("-print-lines")),
compileFile("tests/neg-custom-args/i13838.scala", defaultOptions.and("-Ximplicit-search-limit", "1000")),
compileFile("tests/neg-custom-args/jdk-9-app.scala", defaultOptions.and("-release:8")),
compileFile("tests/neg-custom-args/i10994.scala", defaultOptions.and("-source", "future")),
).checkExpectedErrors()
}

Expand Down
4 changes: 2 additions & 2 deletions docs/_docs/internals/syntax.md
Expand Up @@ -315,8 +315,8 @@ TypeCaseClause ::= ‘case’ (InfixType | ‘_’) ‘=>’ Type [semi]

Pattern ::= Pattern1 { ‘|’ Pattern1 } Alternative(pats)
Pattern1 ::= PatVar ‘:’ RefinedType Bind(name, Typed(Ident(wildcard), tpe))
| [‘-’] integerLiteral ‘:’ RefinedType Typed(pat, tpe)
| [‘-’] floatingPointLiteral ‘:’ RefinedType Typed(pat, tpe)
| [‘-’] integerLiteral ‘:’ RefinedType Typed(pat, tpe)
| [‘-’] floatingPointLiteral ‘:’ RefinedType Typed(pat, tpe)
| Pattern2
Pattern2 ::= [id ‘@’] InfixPattern [‘*’] Bind(name, pat)
InfixPattern ::= SimplePattern { id [nl] SimplePattern } InfixOp(pat, op, pat)
Expand Down
4 changes: 2 additions & 2 deletions docs/_docs/reference/syntax.md
Expand Up @@ -313,8 +313,8 @@ TypeCaseClause ::= ‘case’ (InfixType | ‘_’) ‘=>’ Type [semi]

Pattern ::= Pattern1 { ‘|’ Pattern1 }
Pattern1 ::= PatVar ‘:’ RefinedType
| [‘-’] integerLiteral ‘:’ RefinedType
| [‘-’] floatingPointLiteral ‘:’ RefinedType
| [‘-’] integerLiteral ‘:’ RefinedType
| [‘-’] floatingPointLiteral ‘:’ RefinedType
| Pattern2
Pattern2 ::= [id ‘@’] InfixPattern [‘*’]
InfixPattern ::= SimplePattern { id [nl] SimplePattern }
Expand Down
File renamed without changes.
Expand Up @@ -22,7 +22,7 @@ transparent inline def transparentInlineMod2(inline n: NatT): NatT = inline n m
case Succ(Zero()) => Succ(Zero())
case Succ(Succ(predPredN)) => transparentInlineMod2(predPredN)

def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match // exhaustivity warning; unexpected
def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match
case Zero(): Zero => Zero() // error
case Succ(Zero()): Succ[Zero] => Succ(Zero()) // error
case Succ(Succ(predPredN)): Succ[Succ[_]] => dependentlyTypedMod2(predPredN) // error
Expand Down Expand Up @@ -57,5 +57,5 @@ inline def transparentInlineFoo(inline n: NatT): NatT = inline transparentInline
println(transparentInlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
println(transparentInlineFoo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected
println(dependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // runtime error; unexpected
// println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected
// println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected
println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
7 changes: 7 additions & 0 deletions tests/neg-custom-args/i10994.check
@@ -0,0 +1,7 @@
-- Error: tests/neg-custom-args/i10994.scala:2:19 ----------------------------------------------------------------------
2 | case (b: Boolean): Boolean => () // error
| ^
| Type ascriptions after patterns other than:
| * variable pattern, e.g. `case x: String =>`
| * number literal pattern, e.g. `case 10.5: Double =>`
| are no longer supported. Remove the type ascription or move it to a separate variable pattern.
2 changes: 2 additions & 0 deletions tests/neg-custom-args/i10994.scala
@@ -0,0 +1,2 @@
def foo = true match
case (b: Boolean): Boolean => () // error
13 changes: 10 additions & 3 deletions tests/neg/t5702-neg-bad-and-wild.check
Expand Up @@ -10,10 +10,10 @@
| pattern expected
|
| longer explanation available when compiling with `-explain`
-- [E040] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:13:22 ---------------------------------------------------
-- [E040] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:13:23 ---------------------------------------------------
13 | case List(1, _*3:) => // error // error
| ^
| ')' expected, but ':' found
| ^
| an identifier expected, but ')' found
-- [E032] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:15:18 ---------------------------------------------------
15 | case List(x*, 1) => // error: pattern expected
| ^
Expand Down Expand Up @@ -56,6 +56,13 @@
| Recursive value $1$ needs type
|
| longer explanation available when compiling with `-explain`
-- Warning: tests/neg/t5702-neg-bad-and-wild.scala:13:22 ---------------------------------------------------------------
13 | case List(1, _*3:) => // error // error
| ^
| Type ascriptions after patterns other than:
| * variable pattern, e.g. `case x: String =>`
| * number literal pattern, e.g. `case 10.5: Double =>`
| are no longer supported. Remove the type ascription or move it to a separate variable pattern.
-- Warning: tests/neg/t5702-neg-bad-and-wild.scala:22:20 ---------------------------------------------------------------
22 | val K(x @ _*) = k
| ^
Expand Down
6 changes: 3 additions & 3 deletions tests/pending/run/i15893.scala
Expand Up @@ -24,7 +24,7 @@ transparent inline def transparentInlineMod2(inline n: NatT): NatT = inline n m
case Succ(Zero()) => Succ(Zero())
case Succ(Succ(predPredN)) => transparentInlineMod2(predPredN)
*/
def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match // exhaustivity warning; unexpected
def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match
case Zero(): Zero => Zero()
case Succ(Zero()): Succ[Zero] => Succ(Zero())
case Succ(Succ(predPredN)): Succ[Succ[_]] => dependentlyTypedMod2(predPredN)
Expand Down Expand Up @@ -61,5 +61,5 @@ inline def transparentInlineFoo(inline n: NatT): NatT = inline transparentInline
println(transparentInlineFoo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected
*/
println(dependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // runtime error; unexpected
// println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected
// println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // doesn't compile; unexpected
// println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
// println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
2 changes: 2 additions & 0 deletions tests/pos/i10994.scala
@@ -0,0 +1,2 @@
def foo = true match
case (b: Boolean): Boolean => () // warning
61 changes: 61 additions & 0 deletions tests/pos/i15893.scala
@@ -0,0 +1,61 @@
sealed trait NatT
case class Zero() extends NatT
case class Succ[+N <: NatT](n: N) extends NatT

type Mod2[N <: NatT] <: NatT = N match
case Zero => Zero
case Succ[Zero] => Succ[Zero]
case Succ[Succ[predPredN]] => Mod2[predPredN]

def mod2(n: NatT): NatT = n match
case Zero() => Zero()
case Succ(Zero()) => Succ(Zero())
case Succ(Succ(predPredN)) => mod2(predPredN)

inline def inlineMod2(inline n: NatT): NatT = inline n match
case Zero() => Zero()
case Succ(Zero()) => Succ(Zero())
case Succ(Succ(predPredN)) => inlineMod2(predPredN)

transparent inline def transparentInlineMod2(inline n: NatT): NatT = inline n match
case Zero() => Zero()
case Succ(Zero()) => Succ(Zero())
case Succ(Succ(predPredN)) => transparentInlineMod2(predPredN)

def dependentlyTypedMod2[N <: NatT](n: N): Mod2[N] = n match
case Zero(): Zero => Zero() // warning
case Succ(Zero()): Succ[Zero] => Succ(Zero()) // warning
case Succ(Succ(predPredN)): Succ[Succ[_]] => dependentlyTypedMod2(predPredN) // warning

inline def inlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match
case Zero(): Zero => Zero() // warning
case Succ(Zero()): Succ[Zero] => Succ(Zero()) // warning
case Succ(Succ(predPredN)): Succ[Succ[_]] => inlineDependentlyTypedMod2(predPredN) // warning

transparent inline def transparentInlineDependentlyTypedMod2[N <: NatT](inline n: N): Mod2[N] = inline n match
case Zero(): Zero => Zero() // warning
case Succ(Zero()): Succ[Zero] => Succ(Zero()) // warning
case Succ(Succ(predPredN)): Succ[Succ[_]] => transparentInlineDependentlyTypedMod2(predPredN) // warning

def foo(n: NatT): NatT = mod2(n) match
case Succ(Zero()) => Zero()
case _ => n

inline def inlineFoo(inline n: NatT): NatT = inline inlineMod2(n) match
case Succ(Zero()) => Zero()
case _ => n

inline def transparentInlineFoo(inline n: NatT): NatT = inline transparentInlineMod2(n) match
case Succ(Zero()) => Zero()
case _ => n

@main def main(): Unit =
println(mod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
println(foo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected
println(inlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
println(inlineFoo(Succ(Succ(Succ(Zero()))))) // prints Succ(Succ(Succ(Zero()))); unexpected
println(transparentInlineMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
println(transparentInlineFoo(Succ(Succ(Succ(Zero()))))) // prints Zero(), as expected
println(dependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // runtime error; unexpected
println(inlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected
println(transparentInlineDependentlyTypedMod2(Succ(Succ(Succ(Zero()))))) // prints Succ(Zero()), as expected