Skip to content

Commit 22803e5

Browse files
committed
Make sure IsInstanceOfEvaluator respects @unchecked
1 parent 0456326 commit 22803e5

File tree

2 files changed

+27
-19
lines changed

2 files changed

+27
-19
lines changed

compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -135,30 +135,32 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
135135
val selFinalClass = selClass && (selector.typeSymbol is Final)
136136

137137
/** Check if the selector's potential type parameters will be erased, and if so warn */
138-
val selTypeParam = tree.args.head.tpe.widen match {
139-
case tp @ AppliedType(tycon, args) =>
140-
// If the type is Array[X] where x extends AnyVal, this shouldn't yield a warning:
141-
val illegalComparison = !(tp.isRef(defn.ArrayClass) && {
142-
args.head.derivesFrom(defn.AnyValClass) ||
143-
args.head.isRef(defn.AnyClass)
144-
})
145-
146-
if (illegalComparison) ctx.uncheckedWarning(
138+
val selTypeParam = tree.args.head.tpe.widen match {
139+
case tp @ AppliedType(_, arg :: _) =>
140+
// If the type is `Array[X]` where `X` extends AnyVal or `X =:=
141+
// Any`, this shouldn't yield a warning:
142+
val isArray = tp.isRef(defn.ArrayClass)
143+
val unerased = arg.derivesFrom(defn.AnyValClass) || arg.isRef(defn.AnyClass)
144+
val hasAnnot = arg.hasAnnotation(defn.UncheckedAnnot)
145+
146+
if (!hasAnnot && !(isArray && unerased)) ctx.uncheckedWarning(
147147
ErasedType(hl"""|Since type parameters are erased, you should not match on them in
148148
|${"match"} expressions."""),
149149
tree.pos
150150
)
151151
true
152-
case x if tree.args.head.symbol is TypeParam =>
153-
ctx.uncheckedWarning(
154-
ErasedType(
155-
hl"""|`${tree.args.head.tpe}` will be erased to `${selector}`. Which means that the specified
156-
|behavior could be different during runtime."""
157-
),
158-
tree.pos
159-
)
160-
true
161-
case _ => false
152+
case _ =>
153+
if (tree.args.head.symbol.is(TypeParam)) {
154+
ctx.uncheckedWarning(
155+
ErasedType(
156+
hl"""|`${tree.args.head.tpe}` will be erased to `${selector}`. Which means that the specified
157+
|behavior could be different during runtime."""
158+
),
159+
tree.pos
160+
)
161+
true
162+
}
163+
else false
162164
}
163165

164166
// Cases ---------------------------------

tests/repl/erasure.check

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,10 @@ scala> def matchArray4(xs: Array[Any]) = xs match { case xs: Array[Int] => xs; c
5050

5151
longer explanation available when compiling with `-explain`
5252
def matchArray4(xs: Array[Any]): Array[Int]
53+
scala> def matchArray5[A](xs: Array[Any]) = xs match { case xs: Array[Int] => xs; case xs: Array[A @unchecked] => ??? }
54+
def matchArray5[A](xs: Array[Any]): [A] => (xs: Array[Any])Array[Int]
55+
scala> def matchList1(xs: List[Any]) = xs match { case xs: List[Int @unchecked] => ??? }
56+
def matchList1(xs: List[Any]): Nothing
57+
scala> def matchList2(xs: List[Any]) = xs match { case List() => ???; case _ => ??? }
58+
def matchList2(xs: List[Any]): Nothing
5359
scala> :quit

0 commit comments

Comments
 (0)