Skip to content

Commit 4c2436b

Browse files
committed
fix runtime check warning for canEqual & equals of case class
1 parent 0b9f8a8 commit 4c2436b

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ object Checkable {
4545
*
4646
* 1. if `P` is a singleton type, TRUE
4747
* 2. if `P` is WildcardType, TRUE
48+
* 3. if `P = T @unchecked`, TRUE
4849
* 3. if `P` refers to an abstract type member, FALSE
4950
* 4. if `P = Array[T]`, checkable(E, T) where `E` is the element type of `X`, defaults to `Any`.
5051
* 5. if `P` is `pre.F[Ts]` and `pre.F` refers to a class which is not `Array`:
@@ -73,16 +74,15 @@ object Checkable {
7374
val tvars = tycon.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
7475
val P1 = tycon.appliedTo(tvars)
7576

76-
debug.println("P1 : " + P1)
77+
debug.println("P1 : " + P1.show)
7778
debug.println("X : " + X.widen)
7879

7980
!(P1 <:< X.widen) || {
8081
// val syms = maximizeType(P1, Psym.pos, fromScala2x = false)
8182
isFullyDefined(P1, ForceDegree.noBottom)
8283
val P2 = replaceBinderMap.apply(P)
8384
val res = P1 <:< P2
84-
debug.println("P1: " + P1)
85-
debug.println("P2: " + P2)
85+
debug.println("P2: " + P2.show)
8686
debug.println("P1 <:< P2 = " + res)
8787
res
8888
}
@@ -99,7 +99,8 @@ object Checkable {
9999
case tpe: AppliedType => !isAbstract && isClassDetermined(tpe)(ctx.fresh.setFreshGADTBounds)
100100
case AndType(tp1, tp2) => checkable(X, tp1) && checkable(X, tp2)
101101
case OrType(tp1, tp2) => checkable(X, tp1) && checkable(X, tp2)
102-
case AnnotatedType(tp, _) => checkable(X, tp)
102+
case AnnotatedType(t, an) => an.symbol == defn.UncheckedAnnot || checkable(X, t)
103+
case _: RefinedType => false
103104
case _ => replaceBinderMap.apply(P) == WildcardType || !isAbstract
104105
}
105106

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import ast.Trees._
1111
import ast.untpd
1212
import Decorators._
1313
import NameOps._
14+
import Annotations.Annotation
1415
import ValueClasses.isDerivedValueClass
1516
import scala.collection.mutable.ListBuffer
1617
import scala.language.postfixOps
@@ -152,7 +153,7 @@ class SyntheticMethods(thisPhase: DenotTransformer) {
152153
* def equals(that: Any): Boolean =
153154
* (this eq that) || {
154155
* that match {
155-
* case x$0 @ (_: C) => this.x == this$0.x && this.y == x$0.y
156+
* case x$0 @ (_: C @unchecked) => this.x == this$0.x && this.y == x$0.y
156157
* case _ => false
157158
* }
158159
* ```
@@ -162,7 +163,7 @@ class SyntheticMethods(thisPhase: DenotTransformer) {
162163
def equalsBody(that: Tree)(implicit ctx: Context): Tree = {
163164
val thatAsClazz = ctx.newSymbol(ctx.owner, nme.x_0, Synthetic, clazzType, coord = ctx.owner.pos) // x$0
164165
def wildcardAscription(tp: Type) = Typed(Underscore(tp), TypeTree(tp))
165-
val pattern = Bind(thatAsClazz, wildcardAscription(clazzType)) // x$0 @ (_: C)
166+
val pattern = Bind(thatAsClazz, wildcardAscription(AnnotatedType(clazzType, Annotation(defn.UncheckedAnnot)))) // x$0 @ (_: C @unchecked)
166167
val comparisons = accessors map { accessor =>
167168
This(clazz).select(accessor).equal(ref(thatAsClazz).select(accessor)) }
168169
val rhs = // this.x == this$0.x && this.y == x$0.y
@@ -250,10 +251,10 @@ class SyntheticMethods(thisPhase: DenotTransformer) {
250251
* gets the `canEqual` method
251252
*
252253
* ```
253-
* def canEqual(that: Any) = that.isInstanceOf[C]
254+
* def canEqual(that: Any) = that.isInstanceOf[C @unchecked]
254255
* ```
255256
*/
256-
def canEqualBody(that: Tree): Tree = that.isInstance(clazzType)
257+
def canEqualBody(that: Tree): Tree = that.isInstance(AnnotatedType(clazzType, Annotation(defn.UncheckedAnnot)))
257258

258259
symbolsToSynthesize flatMap syntheticDefIfMissing
259260
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import scala.util.control.NonFatal
2+
object p {
3+
4+
enum Result[+T, +E] {
5+
case OK [T](x: T) extends Result[T, Nothing]
6+
case Err[E](e: E) extends Result[Nothing, E]
7+
}
8+
9+
type Try[T] = Result[T, Throwable]
10+
object Try {
11+
def apply[T](x: => T): Try[T] =
12+
try Result.OK(x)
13+
catch {
14+
case NonFatal(ex) => Result.Err(ex)
15+
}
16+
}
17+
18+
def foo(x: Any): Boolean =
19+
x.isInstanceOf[List[String]] // error
20+
}

0 commit comments

Comments
 (0)