From 844e5011a592619ee8a3ccef4952d19cf0d174f8 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Fri, 5 Dec 2025 10:07:55 +0100 Subject: [PATCH 1/2] Suggest runtimeChecked in warning/error messages suggest `.runtimeChecked` instead of `: @unchecked` also, change the patch applied under 3.2-migration. --- .../src/dotty/tools/dotc/typer/Checking.scala | 9 +++++---- .../src/dotty/tools/dotc/typer/Typer.scala | 14 +++++++------- tests/neg/i11118.check | 8 ++++---- .../refutable-pattern-binding-messages.check | 18 +++++++++--------- tests/neg/t5702-neg-bad-and-wild.check | 8 ++++---- .../rewrites/refutable-pattern-bindings.check | 14 +++++++------- tests/warn/i16649-refutable.check | 2 +- 7 files changed, 37 insertions(+), 36 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 8573127d6f27..3c05ab42067e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1054,8 +1054,9 @@ trait Checking { } /** Check that pattern `pat` is irrefutable for scrutinee type `sel.tpe`. - * This means `sel` is either marked @unchecked or `sel.tpe` conforms to the - * pattern's type. If pattern is an UnApply, also check that the extractor is + * This means `sel` is either marked `: @RuntimeChecked`, `: @unchecked` (old style), + * or `sel.tpe` conforms to the pattern's type. If pattern is an Unapply, + * also check that the extractor is * irrefutable, and do the check recursively. */ def checkIrrefutable(sel: Tree, pat: Tree, isPatDef: Boolean)(using Context): Boolean = { @@ -1068,7 +1069,7 @@ trait Checking { import Reason.* val message = reason match case NonConforming => - var reportedPt = pt.dropAnnot(defn.UncheckedAnnot) + var reportedPt = pt.dropAnnot(defn.UncheckedAnnot).dropAnnot(defn.RuntimeCheckedAnnot) if !pat.tpe.isSingleton then reportedPt = reportedPt.widen val problem = if pat.tpe <:< reportedPt then "is more specialized than" else "does not match" em"pattern's type ${pat.tpe} $problem the right hand side expression's type $reportedPt" @@ -1084,7 +1085,7 @@ trait Checking { else em"pattern binding uses refutable extractor `$extractor`" val fix = - if isPatDef then "adding `: @unchecked` after the expression" + if isPatDef then "adding `.runtimeChecked` after the expression" else "adding the `case` keyword before the full pattern" val addendum = if isPatDef then "may result in a MatchError at runtime" diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 389cd306fc02..cf29d7cdc8ef 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2213,10 +2213,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer typedMatchFinish(tree, sel1, selType, tree.cases, pt) } - /** Are some form of brackets necessary to annotate the tree `sel` as `@unchecked`? + /** Are some form of brackets necessary to annotate the tree `sel` as `.runtimeChecked`? * If so, return a Some(opening bracket, closing bracket), otherwise None. */ - def uncheckedBrackets(sel: untpd.Tree): Option[(String, String)] = sel match + def runtimeCheckedBrackets(sel: untpd.Tree): Option[(String, String)] = sel match case _: untpd.If | _: untpd.Match | _: untpd.ForYield @@ -2235,20 +2235,20 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer && sourceVersion.isAtLeast(`3.2`) && sourceVersion.isMigrating then - if isPatDef then uncheckedBrackets(tree.selector) match + if isPatDef then runtimeCheckedBrackets(tree.selector) match case None => - patch(Span(tree.selector.span.end), ": @unchecked") + patch(Span(tree.selector.span.end), ".runtimeChecked") case Some(bl, br) => patch(Span(tree.selector.span.start), s"$bl") - patch(Span(tree.selector.span.end), s"$br: @unchecked") + patch(Span(tree.selector.span.end), s"$br.runtimeChecked") else patch(Span(tree.span.start), "case ") // skip exhaustivity check in later phase // TODO: move the check above to patternMatcher phase - val uncheckedTpe = AnnotatedType(sel.tpe.widen, Annotation(defn.UncheckedAnnot, tree.selector.span)) + val runtimeCheckedTpe = AnnotatedType(sel.tpe.widen, Annotation(defn.RuntimeCheckedAnnot, tree.selector.span)) tpd.cpy.Match(result)( - selector = tpd.Typed(sel, tpd.TypeTree(uncheckedTpe, inferred = true)), + selector = tpd.Typed(sel, tpd.TypeTree(runtimeCheckedTpe, inferred = true)), cases = result.cases ) case _ => diff --git a/tests/neg/i11118.check b/tests/neg/i11118.check index 0af98c7f580a..cdd46f48c21a 100644 --- a/tests/neg/i11118.check +++ b/tests/neg/i11118.check @@ -1,11 +1,11 @@ -- Warning: tests/neg/i11118.scala:2:12 -------------------------------------------------------------------------------- 2 |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) + | 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. + | If the narrowing is intentional, this can be communicated by adding `.runtimeChecked` 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 | ^ diff --git a/tests/neg/refutable-pattern-binding-messages.check b/tests/neg/refutable-pattern-binding-messages.check index 4a8f895264a3..f1fe3e4e7e65 100644 --- a/tests/neg/refutable-pattern-binding-messages.check +++ b/tests/neg/refutable-pattern-binding-messages.check @@ -27,22 +27,22 @@ | ^^^^^^^^^^^^^^^ | pattern binding uses refutable extractor `Test.Positive` | - | If this usage is intentional, this can be communicated by adding `: @unchecked` after the expression, + | If this usage is intentional, this can be communicated by adding `.runtimeChecked` after the expression, | which may result in a MatchError at runtime. | This patch can be rewritten automatically under -rewrite -source 3.2-migration. -- Warning: tests/neg/refutable-pattern-binding-messages.scala:10:20 --------------------------------------------------- 10 | val i :: is = List(1, 2, 3) // warn: pattern type more specialized | ^^^^^^^^^^^^^ - | pattern's type ::[Int] is more specialized than the right hand side expression's type List[Int] + | pattern's type ::[Int] is more specialized than the right hand side expression's type List[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. + | If the narrowing is intentional, this can be communicated by adding `.runtimeChecked` after the expression, + | which may result in a MatchError at runtime. + | This patch can be rewritten automatically under -rewrite -source 3.2-migration. -- Warning: tests/neg/refutable-pattern-binding-messages.scala:16:10 --------------------------------------------------- 16 | val 1 = 2 // warn: pattern type does not match | ^ - | pattern's type (1 : Int) does not match the right hand side expression's type (2 : Int) + | pattern's type (1 : Int) does not match the right hand side expression's type (2 : 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. + | If the narrowing is intentional, this can be communicated by adding `.runtimeChecked` after the expression, + | which may result in a MatchError at runtime. + | This patch can be rewritten automatically under -rewrite -source 3.2-migration. diff --git a/tests/neg/t5702-neg-bad-and-wild.check b/tests/neg/t5702-neg-bad-and-wild.check index a70c6db1cef9..77398f4af50a 100644 --- a/tests/neg/t5702-neg-bad-and-wild.check +++ b/tests/neg/t5702-neg-bad-and-wild.check @@ -57,8 +57,8 @@ -- 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 + | 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. + | If the narrowing is intentional, this can be communicated by adding `.runtimeChecked` after the expression, + | which may result in a MatchError at runtime. + | This patch can be rewritten automatically under -rewrite -source 3.2-migration. diff --git a/tests/rewrites/refutable-pattern-bindings.check b/tests/rewrites/refutable-pattern-bindings.check index de61b29ebdf7..7d90d0c4ece6 100644 --- a/tests/rewrites/refutable-pattern-bindings.check +++ b/tests/rewrites/refutable-pattern-bindings.check @@ -2,26 +2,26 @@ val xs: List[Any] = ??? val hd :: tl = (xs match case Nil => null :: xs - case _ => xs): @unchecked + case _ => xs).runtimeChecked -val h :: t = xs: @unchecked +val h :: t = xs.runtimeChecked val a :: b = (if xs.isEmpty then null :: xs - else xs): @unchecked + else xs).runtimeChecked val c :: d = (try xs.head :: xs - catch case _: NoSuchElementException => null :: xs): @unchecked + catch case _: NoSuchElementException => null :: xs).runtimeChecked val e :: f = {val zero = null :: Nil if xs.isEmpty then zero - else xs}: @unchecked + else xs}.runtimeChecked val j :: k = (for case (x: String) <- xs - yield x): @unchecked + yield x).runtimeChecked -val (_: Int | _: AnyRef) = (??? : AnyRef): @unchecked +val (_: Int | _: AnyRef) = (??? : AnyRef).runtimeChecked diff --git a/tests/warn/i16649-refutable.check b/tests/warn/i16649-refutable.check index a6cacfc691ee..749d20662aaa 100644 --- a/tests/warn/i16649-refutable.check +++ b/tests/warn/i16649-refutable.check @@ -3,6 +3,6 @@ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | pattern binding uses refutable extractor `'{...}` | - | If this usage is intentional, this can be communicated by adding `: @unchecked` after the expression, + | If this usage is intentional, this can be communicated by adding `.runtimeChecked` after the expression, | which may result in a MatchError at runtime. | This patch can be rewritten automatically under -rewrite -source 3.2-migration. From e944b5e7992eef2749b04a836848941275dfabc0 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Fri, 5 Dec 2025 11:32:55 +0100 Subject: [PATCH 2/2] Alternative: preserve `: @unchecked` message pre 3.8 patch and warning message text will still suggest/replace `: @unchecked` pre 3.8. from 3.8-migration onwards, the message/patch suggests `.runtimeChecked` This preserves behavior under older source versions. --- .../src/dotty/tools/dotc/typer/Checking.scala | 11 +++-- .../src/dotty/tools/dotc/typer/Typer.scala | 10 ++-- .../dotty/tools/dotc/CompilationTests.scala | 3 +- tests/neg/i11118.check | 2 +- ...futable-pattern-binding-messages-old.check | 48 +++++++++++++++++++ ...futable-pattern-binding-messages-old.scala | 17 +++++++ .../refutable-pattern-binding-messages.check | 6 +-- .../refutable-pattern-binding-messages.scala | 2 +- tests/neg/t5702-neg-bad-and-wild.check | 2 +- .../refutable-pattern-bindings-old.check | 29 +++++++++++ .../refutable-pattern-bindings-old.scala | 29 +++++++++++ .../rewrites/refutable-pattern-bindings.scala | 2 +- tests/warn/i16649-refutable.check | 2 +- 13 files changed, 148 insertions(+), 15 deletions(-) create mode 100644 tests/neg/refutable-pattern-binding-messages-old.check create mode 100644 tests/neg/refutable-pattern-binding-messages-old.scala create mode 100644 tests/rewrites/refutable-pattern-bindings-old.check create mode 100644 tests/rewrites/refutable-pattern-bindings-old.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 3c05ab42067e..b6a3d818ccd4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1085,7 +1085,10 @@ trait Checking { else em"pattern binding uses refutable extractor `$extractor`" val fix = - if isPatDef then "adding `.runtimeChecked` after the expression" + if isPatDef then + val patchText = + if sourceVersion.isAtLeast(`3.8`) then ".runtimeChecked" else ": @unchecked" + s"adding `$patchText` after the expression" else "adding the `case` keyword before the full pattern" val addendum = if isPatDef then "may result in a MatchError at runtime" @@ -1098,7 +1101,9 @@ trait Checking { case NonConforming => sel.srcPos case RefutableExtractor => pat.source.atSpan(pat.span `union` sel.span) else pat.srcPos - def rewriteMsg = Message.rewriteNotice("This patch", `3.2-migration`) + def rewriteMsg = Message.rewriteNotice("This patch", + if isPatDef && sourceVersion.isAtLeast(`3.8`) then `3.8-migration` else `3.2-migration` + ) report.errorOrMigrationWarning( message.append( i"""| @@ -1107,7 +1112,7 @@ trait Checking { |which $addendum.$rewriteMsg"""), pos, // we tighten for-comprehension without `case` to error in 3.4, - // but we keep pat-defs as warnings for now ("@unchecked"), + // but we keep pat-defs as warnings for now (".runtimeChecked"), // until we propose an alternative way to assert exhaustivity to the typechecker. if isPatDef then MigrationVersion.ForComprehensionUncheckedPathDefs else MigrationVersion.ForComprehensionPatternWithoutCase diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index cf29d7cdc8ef..10c1035167ab 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2235,12 +2235,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer && sourceVersion.isAtLeast(`3.2`) && sourceVersion.isMigrating then - if isPatDef then runtimeCheckedBrackets(tree.selector) match + if isPatDef then + val patchText = + if sourceVersion.isAtLeast(`3.8`) then ".runtimeChecked" + else ": @unchecked" + runtimeCheckedBrackets(tree.selector) match case None => - patch(Span(tree.selector.span.end), ".runtimeChecked") + patch(Span(tree.selector.span.end), patchText) case Some(bl, br) => patch(Span(tree.selector.span.start), s"$bl") - patch(Span(tree.selector.span.end), s"$br.runtimeChecked") + patch(Span(tree.selector.span.end), s"$br$patchText") else patch(Span(tree.span.start), "case ") diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 85793e69b9cb..d2f6b8265c6f 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -70,7 +70,8 @@ class CompilationTests { compileFile("tests/rewrites/private-this.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), compileFile("tests/rewrites/alphanumeric-infix-operator.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), compileFile("tests/rewrites/filtering-fors.scala", defaultOptions.and("-rewrite", "-source", "3.2-migration")), - compileFile("tests/rewrites/refutable-pattern-bindings.scala", defaultOptions.and("-rewrite", "-source", "3.2-migration")), + compileFile("tests/rewrites/refutable-pattern-bindings-old.scala", defaultOptions.and("-rewrite", "-source", "3.2-migration")), + compileFile("tests/rewrites/refutable-pattern-bindings.scala", defaultOptions.and("-rewrite", "-source", "3.8-migration")), compileFile("tests/rewrites/i8982.scala", defaultOptions.and("-indent", "-rewrite")), compileFile("tests/rewrites/i9632.scala", defaultOptions.and("-indent", "-rewrite")), compileFile("tests/rewrites/i11895.scala", defaultOptions.and("-indent", "-rewrite")), diff --git a/tests/neg/i11118.check b/tests/neg/i11118.check index cdd46f48c21a..6c89f8420cbf 100644 --- a/tests/neg/i11118.check +++ b/tests/neg/i11118.check @@ -5,7 +5,7 @@ | | If the narrowing is intentional, this can be communicated by adding `.runtimeChecked` after the expression, | which may result in a MatchError at runtime. - | This patch can be rewritten automatically under -rewrite -source 3.2-migration. + | This patch can be rewritten automatically under -rewrite -source 3.8-migration. -- Error: tests/neg/i11118.scala:2:4 ----------------------------------------------------------------------------------- 2 |val (a,b) = (1,2,3) // error // warning | ^ diff --git a/tests/neg/refutable-pattern-binding-messages-old.check b/tests/neg/refutable-pattern-binding-messages-old.check new file mode 100644 index 000000000000..12da938246a9 --- /dev/null +++ b/tests/neg/refutable-pattern-binding-messages-old.check @@ -0,0 +1,48 @@ +-- Error: tests/neg/refutable-pattern-binding-messages-old.scala:6:14 -------------------------------------------------- +6 | for Positive(i) <- List(1, 2, 3) do () // error: refutable extractor + | ^^^^^^^^^^^ + | pattern binding uses refutable extractor `Test.Positive` + | + | If this usage is intentional, this can be communicated by adding the `case` keyword before the full pattern, + | which will result in a filtering for expression (using `withFilter`). + | This patch can be rewritten automatically under -rewrite -source 3.2-migration. +-- Error: tests/neg/refutable-pattern-binding-messages-old.scala:11:11 ------------------------------------------------- +11 | for ((x: String) <- xs) do () // error: pattern type more specialized + | ^^^^^^ + | pattern's type String is more specialized than the right hand side expression's type AnyRef + | + | If the narrowing is intentional, this can be communicated by adding the `case` keyword before the full pattern, + | which will result in a filtering for expression (using `withFilter`). + | This patch can be rewritten automatically under -rewrite -source 3.2-migration. +-- Error: tests/neg/refutable-pattern-binding-messages-old.scala:15:13 ------------------------------------------------- +15 | for none @ None <- ys do () // error: pattern type does not match + | ^^^^ + | pattern's type None.type does not match the right hand side expression's type (x$1 : Option[?]) + | + | If the narrowing is intentional, this can be communicated by adding the `case` keyword before the full pattern, + | which will result in a filtering for expression (using `withFilter`). + | This patch can be rewritten automatically under -rewrite -source 3.2-migration. +-- Warning: tests/neg/refutable-pattern-binding-messages-old.scala:5:14 ------------------------------------------------ +5 | val Positive(p) = 5 // warn: refutable extractor + | ^^^^^^^^^^^^^^^ + | pattern binding uses refutable extractor `Test.Positive` + | + | If this usage 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. +-- Warning: tests/neg/refutable-pattern-binding-messages-old.scala:10:20 ----------------------------------------------- +10 | val i :: is = List(1, 2, 3) // warn: pattern type more specialized + | ^^^^^^^^^^^^^ + | pattern's type ::[Int] is more specialized than the right hand side expression's type List[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. +-- Warning: tests/neg/refutable-pattern-binding-messages-old.scala:16:10 ----------------------------------------------- +16 | val 1 = 2 // warn: pattern type does not match + | ^ + | pattern's type (1 : Int) does not match the right hand side expression's type (2 : 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. diff --git a/tests/neg/refutable-pattern-binding-messages-old.scala b/tests/neg/refutable-pattern-binding-messages-old.scala new file mode 100644 index 000000000000..85a6cce9936d --- /dev/null +++ b/tests/neg/refutable-pattern-binding-messages-old.scala @@ -0,0 +1,17 @@ +//> using options -source 3.7 +object Test { + // refutable extractor + object Positive { def unapply(i: Int): Option[Int] = Some(i).filter(_ > 0) } + val Positive(p) = 5 // warn: refutable extractor + for Positive(i) <- List(1, 2, 3) do () // error: refutable extractor + + // more specialized + val xs: List[AnyRef] = ??? + val i :: is = List(1, 2, 3) // warn: pattern type more specialized + for ((x: String) <- xs) do () // error: pattern type more specialized + + // does not match + val ys: List[Option[?]] = ??? + for none @ None <- ys do () // error: pattern type does not match + val 1 = 2 // warn: pattern type does not match +} diff --git a/tests/neg/refutable-pattern-binding-messages.check b/tests/neg/refutable-pattern-binding-messages.check index f1fe3e4e7e65..6f3c4762fe4f 100644 --- a/tests/neg/refutable-pattern-binding-messages.check +++ b/tests/neg/refutable-pattern-binding-messages.check @@ -29,7 +29,7 @@ | | If this usage is intentional, this can be communicated by adding `.runtimeChecked` after the expression, | which may result in a MatchError at runtime. - | This patch can be rewritten automatically under -rewrite -source 3.2-migration. + | This patch can be rewritten automatically under -rewrite -source 3.8-migration. -- Warning: tests/neg/refutable-pattern-binding-messages.scala:10:20 --------------------------------------------------- 10 | val i :: is = List(1, 2, 3) // warn: pattern type more specialized | ^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ | | If the narrowing is intentional, this can be communicated by adding `.runtimeChecked` after the expression, | which may result in a MatchError at runtime. - | This patch can be rewritten automatically under -rewrite -source 3.2-migration. + | This patch can be rewritten automatically under -rewrite -source 3.8-migration. -- Warning: tests/neg/refutable-pattern-binding-messages.scala:16:10 --------------------------------------------------- 16 | val 1 = 2 // warn: pattern type does not match | ^ @@ -45,4 +45,4 @@ | | If the narrowing is intentional, this can be communicated by adding `.runtimeChecked` after the expression, | which may result in a MatchError at runtime. - | This patch can be rewritten automatically under -rewrite -source 3.2-migration. + | This patch can be rewritten automatically under -rewrite -source 3.8-migration. diff --git a/tests/neg/refutable-pattern-binding-messages.scala b/tests/neg/refutable-pattern-binding-messages.scala index e71371785d15..319d916f882a 100644 --- a/tests/neg/refutable-pattern-binding-messages.scala +++ b/tests/neg/refutable-pattern-binding-messages.scala @@ -1,4 +1,4 @@ - +//> using options -source 3.8 object Test { // refutable extractor object Positive { def unapply(i: Int): Option[Int] = Some(i).filter(_ > 0) } diff --git a/tests/neg/t5702-neg-bad-and-wild.check b/tests/neg/t5702-neg-bad-and-wild.check index 77398f4af50a..96392a9389cd 100644 --- a/tests/neg/t5702-neg-bad-and-wild.check +++ b/tests/neg/t5702-neg-bad-and-wild.check @@ -61,4 +61,4 @@ | | If the narrowing is intentional, this can be communicated by adding `.runtimeChecked` after the expression, | which may result in a MatchError at runtime. - | This patch can be rewritten automatically under -rewrite -source 3.2-migration. + | This patch can be rewritten automatically under -rewrite -source 3.8-migration. diff --git a/tests/rewrites/refutable-pattern-bindings-old.check b/tests/rewrites/refutable-pattern-bindings-old.check new file mode 100644 index 000000000000..21302524d469 --- /dev/null +++ b/tests/rewrites/refutable-pattern-bindings-old.check @@ -0,0 +1,29 @@ +// NOTE: this file is compiled under -source 3.2-migration (i.e. it will rewrite to `: @unchecked`) +// see refutable-pattern-bindings.scala for the version compiled under -source 3.8-migration (which rewrites to `.runtimeChecked`) +val xs: List[Any] = ??? + +val hd :: tl = (xs match + case Nil => null :: xs + case _ => xs): @unchecked + +val h :: t = xs: @unchecked + +val a :: b = + (if xs.isEmpty then null :: xs + else xs): @unchecked + +val c :: d = + (try xs.head :: xs + catch case _: NoSuchElementException => null :: xs): @unchecked + +val e :: f = + {val zero = null :: Nil + if xs.isEmpty then zero + else xs}: @unchecked + +val j :: k = + (for + case (x: String) <- xs + yield x): @unchecked + +val (_: Int | _: AnyRef) = (??? : AnyRef): @unchecked diff --git a/tests/rewrites/refutable-pattern-bindings-old.scala b/tests/rewrites/refutable-pattern-bindings-old.scala new file mode 100644 index 000000000000..c6f7c974fa4c --- /dev/null +++ b/tests/rewrites/refutable-pattern-bindings-old.scala @@ -0,0 +1,29 @@ +// NOTE: this file is compiled under -source 3.2-migration (i.e. it will rewrite to `: @unchecked`) +// see refutable-pattern-bindings.scala for the version compiled under -source 3.8-migration (which rewrites to `.runtimeChecked`) +val xs: List[Any] = ??? + +val hd :: tl = xs match + case Nil => null :: xs + case _ => xs + +val h :: t = xs + +val a :: b = + if xs.isEmpty then null :: xs + else xs + +val c :: d = + try xs.head :: xs + catch case _: NoSuchElementException => null :: xs + +val e :: f = + val zero = null :: Nil + if xs.isEmpty then zero + else xs + +val j :: k = + for + (x: String) <- xs + yield x + +val (_: Int | _: AnyRef) = ??? : AnyRef diff --git a/tests/rewrites/refutable-pattern-bindings.scala b/tests/rewrites/refutable-pattern-bindings.scala index eb796662e207..ce6ad437fc64 100644 --- a/tests/rewrites/refutable-pattern-bindings.scala +++ b/tests/rewrites/refutable-pattern-bindings.scala @@ -21,7 +21,7 @@ val e :: f = val j :: k = for - (x: String) <- xs + case (x: String) <- xs yield x val (_: Int | _: AnyRef) = ??? : AnyRef diff --git a/tests/warn/i16649-refutable.check b/tests/warn/i16649-refutable.check index 749d20662aaa..53bd7f943fb2 100644 --- a/tests/warn/i16649-refutable.check +++ b/tests/warn/i16649-refutable.check @@ -5,4 +5,4 @@ | | If this usage is intentional, this can be communicated by adding `.runtimeChecked` after the expression, | which may result in a MatchError at runtime. - | This patch can be rewritten automatically under -rewrite -source 3.2-migration. + | This patch can be rewritten automatically under -rewrite -source 3.8-migration.