Skip to content

Commit 2909603

Browse files
committed
Make sure IsInstanceOfEvaluator respects @unchecked
1 parent 7e3de65 commit 2909603

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
@@ -134,30 +134,32 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
134134
val selFinalClass = selClass && (selector.typeSymbol is Final)
135135

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

163165
// 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)