Skip to content

Commit 76ea47c

Browse files
committed
Cover cases where other generics are erased
1 parent dab1cf6 commit 76ea47c

File tree

3 files changed

+33
-7
lines changed

3 files changed

+33
-7
lines changed

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,5 @@ object messages {
12271227
val kind = "Erased Type"
12281228
val msg =
12291229
i"abstract type pattern is unchecked since it is eliminated by erasure"
1230-
val explanation = ""
12311230
}
12321231
}

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

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import dotty.tools.dotc.util.Positions._
55
import TreeTransforms.{MiniPhaseTransform, TransformerInfo}
66
import core._
77
import Contexts.Context, Types._, Constants._, Decorators._, Symbols._
8-
import TypeUtils._, TypeErasure._, Flags._
8+
import TypeUtils._, TypeErasure._, Flags._, TypeApplications._
99
import reporting.diagnostic.messages._
1010

1111
/** Implements partial evaluation of `sc.isInstanceOf[Sel]` according to:
@@ -128,6 +128,25 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
128128

129129
val selClassNonFinal = selClass && !(selector.typeSymbol is Final)
130130
val selFinalClass = selClass && (selector.typeSymbol is Final)
131+
val selTypeParam = tree.args.head.tpe.widen match {
132+
case AppliedType(tycon, args) =>
133+
ctx.uncheckedWarning(
134+
ErasedType(hl"""|Since type parameters are erased, you should not match on them in
135+
|${"match"} expressions."""),
136+
tree.pos
137+
)
138+
true
139+
case x if tree.args.head.symbol is TypeParam =>
140+
ctx.uncheckedWarning(
141+
ErasedType(
142+
hl"""|`${tree.args.head.tpe}` will be erased to `${selector}`. Which means that the specified
143+
|behavior could be different during runtime."""
144+
),
145+
tree.pos
146+
)
147+
true
148+
case _ => false
149+
}
131150

132151
// Cases ---------------------------------
133152
val valueClassesOrAny =
@@ -149,11 +168,8 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
149168

150169
val inMatch = s.qualifier.symbol is Case
151170

152-
if (valueClassesOrAny) {
153-
if ((selector eq defn.ObjectType))
154-
ctx.uncheckedWarning(ErasedType(), tree.pos)
155-
tree
156-
} else if (knownStatically)
171+
if (selTypeParam || valueClassesOrAny) tree
172+
else if (knownStatically)
157173
handleStaticallyKnown(s, scrutinee, selector, inMatch, tree.pos)
158174
else if (falseIfUnrelated && scrutinee <:< selector)
159175
// scrutinee is a subtype of the selector, safe to rewrite

tests/repl/errmsgs.check

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ scala> def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
9797
4 |def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
9898
| ^
9999
| abstract type pattern is unchecked since it is eliminated by erasure
100+
101+
longer explanation available when compiling with `-explain`
100102
def unsafeCast[S](a: Any): [S] => (a: Any)S
101103
scala> unsafeCast[String](1)
102104
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
@@ -107,4 +109,13 @@ java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Stri
107109
at RequestResult$result(<console>)
108110
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
109111
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav...
112+
scala> class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
113+
-- [E034] Erased Type Unchecked Warning: <console> -----------------------------
114+
4 |class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
115+
| ^
116+
| abstract type pattern is unchecked since it is eliminated by erasure
117+
118+
longer explanation available when compiling with `-explain`
119+
defined class A
120+
def unsafeCast2[S <: A](a: Any): [S <: A] => (a: Any)S
110121
scala> :quit

0 commit comments

Comments
 (0)