From 7ed0041e9eb2afc57936670007f46ac33c803cf2 Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 9 Apr 2022 18:11:03 +0200 Subject: [PATCH 1/4] Avoid redundant type test for irrefutable @unchecked patterns Fixes #14896 --- compiler/src/dotty/tools/dotc/typer/Applications.scala | 2 +- tests/pos/i14896.scala | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i14896.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index a43d32e591ee..d80d4f366636 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1378,7 +1378,7 @@ trait Applications extends Compatibility { val unapplyPatterns = bunchedArgs.lazyZip(argTypes) map (typed(_, _)) val result = assignType(cpy.UnApply(tree)(unapplyFn, unapplyImplicits(unapplyApp), unapplyPatterns), ownType) unapp.println(s"unapply patterns = $unapplyPatterns") - if ((ownType eq selType) || ownType.isError) result + if (ownType.stripped eq selType.stripped) || ownType.isError then result else tryWithTypeTest(Typed(result, TypeTree(ownType)), selType) case tp => val unapplyErr = if (tp.isError) unapplyFn else notAnExtractor(unapplyFn) diff --git a/tests/pos/i14896.scala b/tests/pos/i14896.scala new file mode 100644 index 000000000000..2ef595fbcaa4 --- /dev/null +++ b/tests/pos/i14896.scala @@ -0,0 +1,2 @@ +object Ex { def unapply(p: Any): Option[_ <: Int] = null } +object Foo { val Ex(_) = null: @unchecked } \ No newline at end of file From f70b899d26109abd92a2a456875b88d475f06473 Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 9 Apr 2022 18:42:25 +0200 Subject: [PATCH 2/4] Avoid double @unchecked annotation Avoid double @unchecked annotation if selector is marked checkIrrefutable. --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index ac8d6152812e..380fcd7a5eeb 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1599,7 +1599,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer result match { case result @ Match(sel, CaseDef(pat, _, _) :: _) => tree.selector.removeAttachment(desugar.CheckIrrefutable) match { - case Some(checkMode) => + case Some(checkMode) if !sel.tpe.hasAnnotation(defn.UncheckedAnnot) => val isPatDef = checkMode == desugar.MatchCheck.IrrefutablePatDef if (!checkIrrefutable(sel, pat, isPatDef) && sourceVersion == `future-migration`) if (isPatDef) patch(Span(tree.selector.span.end), ": @unchecked") From b8df54405058b7c4133bd7becdbdce42e81bd809 Mon Sep 17 00:00:00 2001 From: Tom Grigg Date: Sat, 9 Apr 2022 22:04:58 -0700 Subject: [PATCH 3/4] Add regression test for Scala.js `js.Tuple2` example Since support for `isInstanceOf[Null]` is subject to change. --- .../testsuite/compiler/RegressionTestScala3.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala b/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala index 08aa26726dc7..9561c0866e7e 100644 --- a/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala +++ b/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala @@ -119,6 +119,16 @@ object RegressionTestScala3 { def bar(x: Long = 0): Foo = new Foo(x) } } + + object Issue14896 { + val obj = new js.Object { + val a = 42 + val b = "foo" + } + + val entries = js.Object.entries(obj) + val js.Tuple2(k, v) = entries(0): @unchecked + } } // This class needs to be at the top-level, not in an object, to reproduce the issue From 05f5a6f4deffb385c33225c540eef691a1df0d4a Mon Sep 17 00:00:00 2001 From: Tom Grigg Date: Sat, 9 Apr 2022 22:36:25 -0700 Subject: [PATCH 4/4] Add regression test for #14821 --- tests/pos/i14821.scala | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/pos/i14821.scala diff --git a/tests/pos/i14821.scala b/tests/pos/i14821.scala new file mode 100644 index 000000000000..9c007de53322 --- /dev/null +++ b/tests/pos/i14821.scala @@ -0,0 +1,29 @@ +trait Statement +trait Definition extends Statement + +trait ClassDef extends Definition: + def constructor: DefDef + +object ClassDef: + def copy(constr: DefDef): ClassDef = ??? + +// >>> This abstract implementation of DefDef causes a compilation error in transform... +type DefDef <: Definition +val DefDef: DefDefModule = ??? +trait DefDefModule: + def unapply(ddef: DefDef): (String, List[AnyRef]) +// ...unless this given TypeTest is commented out, in which case we get only a type test warning +given scala.reflect.TypeTest[Statement, DefDef] = ??? + +// >>> This alternative works +// trait DefDef extends Definition +// object DefDef: +// def unapply(ddef: DefDef): (String, List[AnyRef]) = ??? + +// >>> This alternative also works +// case class DefDef(name: String, paramss: List[AnyRef]) extends Definition + +def transform(tree: Statement): Statement = tree match + case tree: ClassDef => + val constructor @ DefDef(_, _) = transform(tree.constructor): @unchecked + ClassDef.copy(constructor)