Skip to content

Commit 3156d50

Browse files
authored
Merge pull request #14898 from dotty-staging/fix-14896-v2
Avoid redundant type test for irrefutable @unchecked patterns
2 parents 8037f3b + 05f5a6f commit 3156d50

File tree

5 files changed

+43
-2
lines changed

5 files changed

+43
-2
lines changed

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,7 @@ trait Applications extends Compatibility {
13781378
val unapplyPatterns = bunchedArgs.lazyZip(argTypes) map (typed(_, _))
13791379
val result = assignType(cpy.UnApply(tree)(unapplyFn, unapplyImplicits(unapplyApp), unapplyPatterns), ownType)
13801380
unapp.println(s"unapply patterns = $unapplyPatterns")
1381-
if ((ownType eq selType) || ownType.isError) result
1381+
if (ownType.stripped eq selType.stripped) || ownType.isError then result
13821382
else tryWithTypeTest(Typed(result, TypeTree(ownType)), selType)
13831383
case tp =>
13841384
val unapplyErr = if (tp.isError) unapplyFn else notAnExtractor(unapplyFn)

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
15991599
result match {
16001600
case result @ Match(sel, CaseDef(pat, _, _) :: _) =>
16011601
tree.selector.removeAttachment(desugar.CheckIrrefutable) match {
1602-
case Some(checkMode) =>
1602+
case Some(checkMode) if !sel.tpe.hasAnnotation(defn.UncheckedAnnot) =>
16031603
val isPatDef = checkMode == desugar.MatchCheck.IrrefutablePatDef
16041604
if (!checkIrrefutable(sel, pat, isPatDef) && sourceVersion == `future-migration`)
16051605
if (isPatDef) patch(Span(tree.selector.span.end), ": @unchecked")

tests/pos/i14821.scala

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
trait Statement
2+
trait Definition extends Statement
3+
4+
trait ClassDef extends Definition:
5+
def constructor: DefDef
6+
7+
object ClassDef:
8+
def copy(constr: DefDef): ClassDef = ???
9+
10+
// >>> This abstract implementation of DefDef causes a compilation error in transform...
11+
type DefDef <: Definition
12+
val DefDef: DefDefModule = ???
13+
trait DefDefModule:
14+
def unapply(ddef: DefDef): (String, List[AnyRef])
15+
// ...unless this given TypeTest is commented out, in which case we get only a type test warning
16+
given scala.reflect.TypeTest[Statement, DefDef] = ???
17+
18+
// >>> This alternative works
19+
// trait DefDef extends Definition
20+
// object DefDef:
21+
// def unapply(ddef: DefDef): (String, List[AnyRef]) = ???
22+
23+
// >>> This alternative also works
24+
// case class DefDef(name: String, paramss: List[AnyRef]) extends Definition
25+
26+
def transform(tree: Statement): Statement = tree match
27+
case tree: ClassDef =>
28+
val constructor @ DefDef(_, _) = transform(tree.constructor): @unchecked
29+
ClassDef.copy(constructor)

tests/pos/i14896.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
object Ex { def unapply(p: Any): Option[_ <: Int] = null }
2+
object Foo { val Ex(_) = null: @unchecked }

tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ object RegressionTestScala3 {
119119
def bar(x: Long = 0): Foo = new Foo(x)
120120
}
121121
}
122+
123+
object Issue14896 {
124+
val obj = new js.Object {
125+
val a = 42
126+
val b = "foo"
127+
}
128+
129+
val entries = js.Object.entries(obj)
130+
val js.Tuple2(k, v) = entries(0): @unchecked
131+
}
122132
}
123133

124134
// This class needs to be at the top-level, not in an object, to reproduce the issue

0 commit comments

Comments
 (0)