Skip to content

Commit

Permalink
Cover cases where other generics are erased
Browse files Browse the repository at this point in the history
  • Loading branch information
felixmulder committed Dec 19, 2016
1 parent dc6bc20 commit e27232a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -902,11 +902,10 @@ object messages {
val explanation = ""
}

case class ErasedType()(implicit ctx: Context)
case class ErasedType(val explanation: String = "")(implicit ctx: Context)
extends Message(34) {
val kind = "Erased Type"
val msg =
i"abstract type pattern is unchecked since it is eliminated by erasure"
val explanation = ""
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import dotty.tools.dotc.util.Positions._
import TreeTransforms.{MiniPhaseTransform, TransformerInfo}
import core._
import Contexts.Context, Types._, Constants._, Decorators._, Symbols._
import TypeUtils._, TypeErasure._, Flags._
import TypeUtils._, TypeErasure._, Flags._, TypeApplications._
import reporting.diagnostic.messages._


Expand Down Expand Up @@ -127,6 +127,25 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>

val selClassNonFinal = selClass && !(selector.typeSymbol is Final)
val selFinalClass = selClass && (selector.typeSymbol is Final)
val selTypeParam = tree.args.head.tpe.widen match {
case AppliedType(tycon, args) =>
ctx.uncheckedWarning(
ErasedType(hl"""|Since type parameters are erased, you cannot match on them in
|${"match"} expressions."""),
tree.pos
)
true
case x if tree.args.head.symbol is TypeParam =>
ctx.uncheckedWarning(
ErasedType(
hl"""|`${tree.args.head.tpe}` will be erased to `${selector}`. Which means that the specified
|behavior could be different during runtime."""
),
tree.pos
)
true
case _ => false
}

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

val inMatch = s.qualifier.symbol is Case

if (valueClassesOrAny) {
if ((selector eq defn.ObjectType))
ctx.uncheckedWarning(ErasedType(), tree.pos)
tree
} else if (knownStatically)
if (selTypeParam || valueClassesOrAny) tree
else if (knownStatically)
handleStaticallyKnown(s, scrutinee, selector, inMatch, tree.pos)
else if (falseIfUnrelated && scrutinee <:< selector)
// scrutinee is a subtype of the selector, safe to rewrite
Expand Down
11 changes: 11 additions & 0 deletions tests/repl/errmsgs.check
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ scala> def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
4 |def unsafeCast[S](a: Any) = a match { case s: S => s; case _ => ??? }
| ^
| abstract type pattern is unchecked since it is eliminated by erasure

longer explanation available when compiling with `-explain`
def unsafeCast[S](a: Any): [S] => (a: Any)S
scala> unsafeCast[String](1)
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
Expand All @@ -93,4 +95,13 @@ java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Stri
at RequestResult$result(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav...
scala> class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
-- [E034] Erased Type Unchecked Warning: <console> -----------------------------
4 |class A; def unsafeCast2[S <: A](a: Any) = a match { case s: S => s; case _ => ??? }
| ^
| abstract type pattern is unchecked since it is eliminated by erasure

longer explanation available when compiling with `-explain`
defined class A
def unsafeCast2[S <: A](a: Any): [S <: A] => (a: Any)S
scala> :quit

0 comments on commit e27232a

Please sign in to comment.