Skip to content

Commit e27232a

Browse files
committed
Cover cases where other generics are erased
1 parent dc6bc20 commit e27232a

File tree

3 files changed

+34
-8
lines changed

3 files changed

+34
-8
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -902,11 +902,10 @@ object messages {
902902
val explanation = ""
903903
}
904904

905-
case class ErasedType()(implicit ctx: Context)
905+
case class ErasedType(val explanation: String = "")(implicit ctx: Context)
906906
extends Message(34) {
907907
val kind = "Erased Type"
908908
val msg =
909909
i"abstract type pattern is unchecked since it is eliminated by erasure"
910-
val explanation = ""
911910
}
912911
}

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

@@ -127,6 +127,25 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
127127

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

131150
// Cases ---------------------------------
132151
val valueClassesOrAny =
@@ -148,11 +167,8 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
148167

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

151-
if (valueClassesOrAny) {
152-
if ((selector eq defn.ObjectType))
153-
ctx.uncheckedWarning(ErasedType(), tree.pos)
154-
tree
155-
} else if (knownStatically)
170+
if (selTypeParam || valueClassesOrAny) tree
171+
else if (knownStatically)
156172
handleStaticallyKnown(s, scrutinee, selector, inMatch, tree.pos)
157173
else if (falseIfUnrelated && scrutinee <:< selector)
158174
// 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
@@ -83,6 +83,8 @@ scala> def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
8383
4 |def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
8484
| ^
8585
| abstract type pattern is unchecked since it is eliminated by erasure
86+
87+
longer explanation available when compiling with `-explain`
8688
def unsafeCast[S](a: Any): [S] => (a: Any)S
8789
scala> unsafeCast[String](1)
8890
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
@@ -93,4 +95,13 @@ java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Stri
9395
at RequestResult$result(<console>)
9496
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
9597
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav...
98+
scala> class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
99+
-- [E034] Erased Type Unchecked Warning: <console> -----------------------------
100+
4 |class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
101+
| ^
102+
| abstract type pattern is unchecked since it is eliminated by erasure
103+
104+
longer explanation available when compiling with `-explain`
105+
defined class A
106+
def unsafeCast2[S <: A](a: Any): [S <: A] => (a: Any)S
96107
scala> :quit

0 commit comments

Comments
 (0)