Skip to content

make refutable patterns an error in 3.4 #16665

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

Closed
wants to merge 13 commits into from
2 changes: 1 addition & 1 deletion community-build/community-projects/utest
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2771,7 +2771,7 @@ object Parsers {
atSpan(startOffset(pat), accept(LARROW)) {
val checkMode =
if casePat then GenCheckMode.FilterAlways
else if sourceVersion.isAtLeast(`future`) then GenCheckMode.Check
else if sourceVersion.isAtLeast(`3.4`) then GenCheckMode.Check
else if sourceVersion.isAtLeast(`3.2`) then GenCheckMode.CheckAndFilter
else GenCheckMode.FilterNow // filter on source version < 3.2, for backward compat
GenFrom(pat, subExpr(), checkMode)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@ trait Checking {
|
|If $usage is intentional, this can be communicated by $fix,
|which $addendum.$rewriteMsg"""),
pos, warnFrom = `3.2`, errorFrom = `future`)
pos, warnFrom = `3.2`, errorFrom = `3.4`)
false
}

Expand Down
4 changes: 4 additions & 0 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1490,6 +1490,8 @@ object Build {
(
(dir / "shared/src/test/scala" ** (("*.scala": FileFilter)
-- "ReflectiveCallTest.scala" // uses many forms of structural calls that are not allowed in Scala 3 anymore
-- "ArrayTest.scala" // refutable pattern match
-- "UTF16Test.scala" // refutable pattern match
)).get

++ (dir / "shared/src/test/require-sam" ** "*.scala").get
Expand All @@ -1499,6 +1501,8 @@ object Build {
++ (dir / "js/src/test/scala" ** (("*.scala": FileFilter)
-- "StackTraceTest.scala" // would require `npm install source-map-support`
-- "UnionTypeTest.scala" // requires the Scala 2 macro defined in Typechecking*.scala
-- "ObjectTest.scala" // refutable pattern match
-- "TupleTest.scala" // refutable pattern match
)).get

++ (dir / "js/src/test/require-2.12" ** "*.scala").get
Expand Down
12 changes: 12 additions & 0 deletions tests/neg/i11118-pre3-4.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- Warning: tests/neg/i11118-pre3-4.scala:4:12 -------------------------------------------------------------------------
4 |val (a,b) = (1,2,3) // error // warning
| ^^^^^^^
| pattern's type (Any, Any) does not match the right hand side expression's type (Int, Int, Int)
|
| If the narrowing is intentional, this can be communicated by adding `: @unchecked` after the expression,
| which may result in a MatchError at runtime.
| This patch can be rewritten automatically under -rewrite -source 3.2-migration.
-- Error: tests/neg/i11118-pre3-4.scala:4:4 ----------------------------------------------------------------------------
4 |val (a,b) = (1,2,3) // error // warning
| ^
| this case is unreachable since type (Int, Int, Int) is not a subclass of class Tuple2
4 changes: 4 additions & 0 deletions tests/neg/i11118-pre3-4.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import scala.language.`3.3`

// https://github.com/lampepfl/dotty/issues/11118
val (a,b) = (1,2,3) // error // warning
8 changes: 2 additions & 6 deletions tests/neg/i11118.check
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
-- Warning: tests/neg/i11118.scala:2:12 --------------------------------------------------------------------------------
2 |val (a,b) = (1,2,3) // error // warning
-- Error: tests/neg/i11118.scala:2:12 ----------------------------------------------------------------------------------
2 |val (a,b) = (1,2,3) // error
| ^^^^^^^
| pattern's type (Any, Any) does not match the right hand side expression's type (Int, Int, Int)
|
| If the narrowing is intentional, this can be communicated by adding `: @unchecked` after the expression,
| which may result in a MatchError at runtime.
| This patch can be rewritten automatically under -rewrite -source 3.2-migration.
-- Error: tests/neg/i11118.scala:2:4 -----------------------------------------------------------------------------------
2 |val (a,b) = (1,2,3) // error // warning
| ^
| this case is unreachable since type (Int, Int, Int) is not a subclass of class Tuple2
2 changes: 1 addition & 1 deletion tests/neg/i11118.scala
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// https://github.com/lampepfl/dotty/issues/11118
val (a,b) = (1,2,3) // error // warning
val (a,b) = (1,2,3) // error
2 changes: 1 addition & 1 deletion tests/neg/i4935.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
object Foo {
val (A, B) = () // error // error
val (A, B) = (): @unchecked // error // error
}
4 changes: 2 additions & 2 deletions tests/neg/i7879.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
object Test {
val head1 +: _ = List(1).view
val head1 +: _ = List(1).view: @unchecked
val _: Int = head1 // error
}
}
4 changes: 2 additions & 2 deletions tests/neg/i9310.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//AE-d101cfe6d25117a51897609e673f6c8e74d31e6e
val foo @ this = 0
val foo @ this = 0: @unchecked
class Foo {
foo { } // error
}
}
16 changes: 4 additions & 12 deletions tests/neg/t5702-neg-bad-and-wild.check
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@
|
| longer explanation available when compiling with `-explain`
-- Error: tests/neg/t5702-neg-bad-and-wild.scala:23:16 -----------------------------------------------------------------
23 | val K(ns @ _*, xx) = k // error: pattern expected
23 | val K(ns @ _*, xx) = k: @unchecked // error: pattern expected
| ^
| spread operator `*` not allowed here; must come last in a parameter list
-- Error: tests/neg/t5702-neg-bad-and-wild.scala:25:14 -----------------------------------------------------------------
25 | val (b, _ * ) = (5,6) // error: bad use of `*`
25 | val (b, _ * ) = (5,6): @unchecked // error: bad use of `*`
| ^
| bad use of `*` - sequence pattern not allowed here
-- [E161] Naming Error: tests/neg/t5702-neg-bad-and-wild.scala:24:10 ---------------------------------------------------
24 | val K(x) = k // error: x is already defined as value x
| ^^^^^^^^^^^^
24 | val K(x) = k: @unchecked // error: x is already defined as value x
| ^^^^^^^^^^^^^^^^^^^^^^^^
| x is already defined as value x
|
| Note that overloaded methods must all be defined in the same group of toplevel definitions
Expand All @@ -61,11 +61,3 @@
| * 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
| ^
| pattern's type Int* does not match the right hand side expression's type Int
|
| If the narrowing is intentional, this can be communicated by adding `: @unchecked` after the expression,
| which may result in a MatchError at runtime.
| This patch can be rewritten automatically under -rewrite -source 3.2-migration.
9 changes: 4 additions & 5 deletions tests/neg/t5702-neg-bad-and-wild.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@ object Test {

// good syntax, bad semantics, detected by typer
//gowild.scala:14: error: star patterns must correspond with varargs parameters
val K(x @ _*) = k
val K(ns @ _*, xx) = k // error: pattern expected
val K(x) = k // error: x is already defined as value x
val (b, _ * ) = (5,6) // error: bad use of `*`
val K(x @ _*) = k: @unchecked
val K(ns @ _*, xx) = k: @unchecked // error: pattern expected
val K(x) = k: @unchecked // error: x is already defined as value x
val (b, _ * ) = (5,6): @unchecked // error: bad use of `*`
// no longer complains
//bad-and-wild.scala:15: error: ')' expected but '}' found.
}
}

4 changes: 2 additions & 2 deletions tests/neg/trailingCommas.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ trait FunTypeParamClause { def f[A, B, ] } // error // error
trait SimpleType { def f: (Int, String, ) } // error
trait FunctionArgTypes { def f: (Int, String, ) => Boolean } // error

trait SimplePattern { val (foo, bar, ) = null: Any } // error
trait SimplePattern { val (foo, bar, ) = null: Any @unchecked } // error

trait ImportSelectors { import foo.{ Ev0, Ev1, } } // error

Expand Down Expand Up @@ -79,4 +79,4 @@ val a,
b,
c,
= (1, 2, 3) // error
val x, y, z, = (1, 2, 3) // error
val x, y, z, = (1, 2, 3) // error
2 changes: 1 addition & 1 deletion tests/pos-deep-subtype/i7580.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

def foo =
val List(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, _:_*) = List.fill(25)(0)
val List(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, _:_*) = List.fill(25)(0): @unchecked

()
2 changes: 1 addition & 1 deletion tests/pos-macros/i12188b/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ object MatchTest {
def testImpl[T](objExpr: Expr[T])(using Quotes): Expr[Unit] = {
import quotes.reflect.*
// test that the extractors work
val Inlined(None, Nil, Block(Nil, Match(param @ Ident("a"), List(CaseDef(Literal(IntConstant(1)), None, Block(Nil, Literal(UnitConstant()))), CaseDef(Wildcard(), None, Block(Nil, Literal(UnitConstant()))))))) = objExpr.asTerm
val Inlined(None, Nil, Block(Nil, Match(param @ Ident("a"), List(CaseDef(Literal(IntConstant(1)), None, Block(Nil, Literal(UnitConstant()))), CaseDef(Wildcard(), None, Block(Nil, Literal(UnitConstant()))))))) = objExpr.asTerm: @unchecked
// test that the constructors work
Block(Nil, Match(param, List(CaseDef(Literal(IntConstant(1)), None, Block(Nil, Literal(UnitConstant()))), CaseDef(Wildcard(), None, Block(Nil, Literal(UnitConstant())))))).asExprOf[Unit]
}
Expand Down
4 changes: 2 additions & 2 deletions tests/pos-macros/i15650.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ object meta:
def unapply(using Quotes)(using TC)(tr: quotes.reflect.TypeRepr): Option[Rational] = ???

def foo(using Quotes)(p: quotes.reflect.TypeRepr): Unit =
val rationalTE(e) = p // warn: pattern binding uses refutable extractor `meta.rationalTE`
val rationalTE(e) = p: @unchecked

def bar(using Quotes)(using TC)(p: quotes.reflect.TypeRepr): Unit =
val rationalTC(c) = p // warn: pattern binding uses refutable extractor `meta.rationalTC`
val rationalTC(c) = p: @unchecked
6 changes: 3 additions & 3 deletions tests/pos-macros/i6435.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ class Foo {

def f(sc: quoted.Expr[StringContext])(using Quotes): Unit = {

val '{ StringContext(${parts}*) } = sc
val '{ StringContext(${parts}*) } = sc: @unchecked
val ps0: Expr[Seq[String]] = parts

val '{ StringContext(${Varargs(parts2)}*) } = sc
val '{ StringContext(${Varargs(parts2)}*) } = sc: @unchecked
val ps: Seq[Expr[String]] = parts2
}
}
}
2 changes: 1 addition & 1 deletion tests/pos-macros/i6998.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import scala.quoted.*

def foo(using Quotes) : Unit = {
val '{ $f : (Int => Double) } = ??? : Expr[Any]
val '{ $f : (Int => Double) } = ??? : Expr[Any] @unchecked
}
2 changes: 1 addition & 1 deletion tests/pos-macros/i7204.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import scala.quoted.*
object Foo {
def impl(using Quotes) : Unit = {
import quotes.reflect.*
val Select(_, _) = (??? : Term)
val Select(_, _) = (??? : Term): @unchecked
}
}
2 changes: 1 addition & 1 deletion tests/pos-macros/i8577a/Main_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ def main: Unit =
extension (inline ctx: Macro.StrCtx) inline def unapplySeq(inline input: Int): Option[Seq[Int]] =
${ implUnapply('ctx, 'input) }

val mac"$x" = 1
val mac"$x" = 1: @unchecked
assert(x == 1)
2 changes: 1 addition & 1 deletion tests/pos-macros/i8577b/Main_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ def main: Unit =
extension (inline ctx: Macro.StrCtx) inline def unapplySeq[U](inline input: U): Option[Seq[U]] =
${ implUnapply('ctx, 'input) }

val mac"$x" = 1
val mac"$x" = 1: @unchecked
assert(x == 1)
2 changes: 1 addition & 1 deletion tests/pos-macros/i8577c/Main_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ def main: Unit =
extension [T] (inline ctx: Macro.StrCtx) inline def unapplySeq(inline input: T): Option[Seq[T]] =
${ implUnapply('ctx, 'input) }

val mac"$x" = 1
val mac"$x" = 1: @unchecked
assert(x == 1)
2 changes: 1 addition & 1 deletion tests/pos-macros/i8577d/Main_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ def main: Unit =
extension [T] (inline ctx: Macro.StrCtx) inline def unapplySeq[U](inline input: T): Option[Seq[T]] =
${ implUnapply('ctx, 'input) }

val mac"$x" = 1
val mac"$x" = 1: @unchecked
assert(x == 1)
2 changes: 1 addition & 1 deletion tests/pos-macros/i8577e/Main_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ def main: Unit =
extension [T] (inline ctx: Macro.StrCtx) inline def unapplySeq[U](inline input: U): Option[Seq[U]] =
${ implUnapply('ctx, 'input) }

val mac"$x" = 1
val mac"$x" = 1: @unchecked
assert(x == 1)
4 changes: 2 additions & 2 deletions tests/pos-macros/i8577f/Main_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ def main: Unit =
extension [T] (inline ctx: Macro.StrCtx) inline def unapplySeq[U](inline input: (T, U)): Option[Seq[(T, U)]] =
${ implUnapply('ctx, 'input) }

val mac"$x" = (1, 2)
val mac"$x" = (1, 2): @unchecked
assert(x == (1, 2))

val mac"$y" = (1, "a")
val mac"$y" = (1, "a"): @unchecked
assert(y == (1, "a"))
2 changes: 1 addition & 1 deletion tests/pos-macros/i8577g/Main_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ def main: Unit =
extension [T] (inline ctx: Macro.StrCtx) inline def unapplySeq[U](inline input: T | U): Option[Seq[T | U]] =
${ implUnapply('ctx, 'input) }

val mac"$x" = 1
val mac"$x" = 1: @unchecked
assert(x == 1)
2 changes: 1 addition & 1 deletion tests/pos-macros/i8577h/Main_2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ def main: Unit =
extension [T] (inline ctx: Macro.StrCtx) inline def unapplySeq[U](inline input: U | T): Option[Seq[T | U]] =
${ implUnapply('ctx, 'input) }

val mac"$x" = 1
val mac"$x" = 1: @unchecked
assert(x == 1)
4 changes: 2 additions & 2 deletions tests/pos-macros/tasty-constant-type/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ object Macro {
def impl[A <: Int : Type, B <: Int : Type](using Quotes) : Expr[AddInt[A, B]] = {
import quotes.reflect.*

val ConstantType(IntConstant(v1)) = TypeRepr.of[A]
val ConstantType(IntConstant(v2)) = TypeRepr.of[B]
val ConstantType(IntConstant(v1)) = TypeRepr.of[A]: @unchecked
val ConstantType(IntConstant(v2)) = TypeRepr.of[B]: @unchecked

Literal(IntConstant(v1 + v2)).tpe.asType match
case '[t] => '{ null: AddInt[A, B] { type Out = t } }
Expand Down
4 changes: 2 additions & 2 deletions tests/pos/endmarkers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package p1.p2:
this()
if x > 0 then
val a :: b =
x :: Nil
(x :: Nil): @unchecked
end val
var y =
x
Expand Down Expand Up @@ -55,4 +55,4 @@ package p1.p2:
def ff: String = x.f
end extension

end p2
end p2
4 changes: 2 additions & 2 deletions tests/pos/extractor-types.scala
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package p1 {
object Ex { def unapply(p: Any): Option[_ <: Int] = null }
object Foo { val Ex(_) = null }
object Foo { val Ex(_) = null: @unchecked }
}
// a.scala:2: error: error during expansion of this match (this is a scalac bug).
// The underlying error was: type mismatch;
// found : Some[_$1(in value x$1)] where type _$1(in value x$1)
// required: Some[_$1(in method unapply)]
// object Foo { val Ex(_) = null }
// object Foo { val Ex(_) = null: @unchecked }
// ^
// one error found

Expand Down
2 changes: 1 addition & 1 deletion tests/pos/i15188.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ extension [T] (ctx: O.type) inline def unapplySeq(input: T): Option[Seq[T]] = So

@main
def Main = {
val O(x) = 3
val O(x) = 3: @unchecked
println(s"x: $x")
}
2 changes: 1 addition & 1 deletion tests/pos/i15188b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ extension (ctx: C) inline def unapply(input: String): Option[String] = Some("hi"

@main def run = {
val O = new C
val O(x) = "3"
val O(x) = "3": @unchecked
}
2 changes: 1 addition & 1 deletion tests/pos/i1540.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ object Casey1 { def unapply(a: Casey1) = a }

object Test {
def main(args: Array[String]): Unit = {
val c @ Casey1(x) = new Casey1(0)
val c @ Casey1(x) = new Casey1(0): @unchecked
assert(x == c.get)
}
}
2 changes: 1 addition & 1 deletion tests/pos/i1540b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ object Casey1 { def unapply[T](a: Casey1[T]) = a }

object Test {
def main(args: Array[String]): Unit = {
val c @ Casey1(x) = new Casey1(0)
val c @ Casey1(x) = new Casey1(0): @unchecked
assert(x == c.get)
}
}
4 changes: 2 additions & 2 deletions tests/pos/i7532.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ class Tasty {
object Foo {
def impl(using tasty: Tasty) : Unit = {
import tasty.{_, given}
val Select() = (??? : Term)
val Select() = (??? : Term): @unchecked
}
}
}
2 changes: 1 addition & 1 deletion tests/pos/inline-i1773.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ object Test {
}

def main(args: Array[String]): Unit = {
val q"class $name extends $parent" = new Object
val q"class $name extends $parent" = new Object: @unchecked
println(name)
println(parent)
}
Expand Down
Loading