From aeeb14be243f21edfb4906ee3112594f3deb9175 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 27 Apr 2020 12:04:15 +0200 Subject: [PATCH 01/19] Fix #5494: Spurious unchecked warning when type testing an alias --- .../dotty/tools/dotc/transform/TypeTestsCasts.scala | 2 +- tests/pos-special/fatal-warnings/i5495.scala | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 tests/pos-special/fatal-warnings/i5495.scala diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 722867215adc..3e10266f0510 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -117,7 +117,7 @@ object TypeTestsCasts { res } - def recur(X: Type, P: Type): Boolean = (X <:< P) || (P match { + def recur(X: Type, P: Type): Boolean = (X <:< P) || (P.dealias match { case _: SingletonType => true case _: TypeProxy if isAbstract(P) => false diff --git a/tests/pos-special/fatal-warnings/i5495.scala b/tests/pos-special/fatal-warnings/i5495.scala new file mode 100644 index 000000000000..f41a4692fa11 --- /dev/null +++ b/tests/pos-special/fatal-warnings/i5495.scala @@ -0,0 +1,10 @@ +class A +class B + +type AorB = A | B + +def foo(any: Any) = any match { + case aorb: AorB => + case _ => +} + From 39911983f08ef52cd5d3ee6241480743457533d3 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 27 Apr 2020 12:32:42 +0200 Subject: [PATCH 02/19] Fix type test warning involving applied types Previously, the check relied used `maximizeType`, which means that depending on which bound got picked by type inference, the check might fail. Instead, we only need to check if there is a possible constraint solution by making sure both subtype tests return true. I'm not sure if this is always a safe type test, but it at least avoids spurious warnings. This is necessary to bootstrap dotty after the previous commit which added a `dealias` to `recur`, this probably means that there are other situations where `recur` is missing checks. --- .../dotty/tools/dotc/transform/TypeTestsCasts.scala | 11 +++-------- tests/pos-special/fatal-warnings/patmat-applied.scala | 9 +++++++++ 2 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 tests/pos-special/fatal-warnings/patmat-applied.scala diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 3e10266f0510..4dc5a337efc0 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -47,8 +47,8 @@ object TypeTestsCasts { * 4. if `P = Array[T]`, checkable(E, T) where `E` is the element type of `X`, defaults to `Any`. * 5. if `P` is `pre.F[Ts]` and `pre.F` refers to a class which is not `Array`: * (a) replace `Ts` with fresh type variables `Xs` - * (b) constrain `Xs` with `pre.F[Xs] <:< X` - * (c) instantiate Xs and check `pre.F[Xs] <:< P` + * (b) check that we can constrain `Xs` such that `pre.F[Xs] <:< X` and `pre.F[Xs] <:< P` + * can both be true at the same time. * 6. if `P = T1 | T2` or `P = T1 & T2`, checkable(X, T1) && checkable(X, T2). * 7. if `P` is a refinement type, FALSE * 8. otherwise, TRUE @@ -105,12 +105,7 @@ object TypeTestsCasts { debug.println("P1 : " + P1.show) debug.println("X : " + X.show) - P1 <:< X // constraint P1 - - // use fromScala2x to avoid generating pattern bound symbols - maximizeType(P1, span, fromScala2x = true) - - val res = P1 <:< P + val res = (P1 <:< X) && (P1 <:< P) debug.println("P1 : " + P1.show) debug.println("P1 <:< P = " + res) diff --git a/tests/pos-special/fatal-warnings/patmat-applied.scala b/tests/pos-special/fatal-warnings/patmat-applied.scala new file mode 100644 index 000000000000..c48ae23b8975 --- /dev/null +++ b/tests/pos-special/fatal-warnings/patmat-applied.scala @@ -0,0 +1,9 @@ +class A[-T] +class B[T] extends A[T] + +object Test { + def foo(x: A[Null]) = x match { + case x: B[Null] => + case _ => + } +} From b1a9fd78bc4efdb4e925000b6b4e8e3ccc42e516 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 27 Apr 2020 13:15:36 +0200 Subject: [PATCH 03/19] Add unchecked marks for technically unsafe type tests `Tree` here is `tpd.Tree` and we're checking against `tpd.Tree | (Context => tpd.Tree)`. Because `Function1` is a trait, we cannot rule out that there exists some subclass of `Tree` which extends it and is not a `tpd.Tree`. The unchecked warning started appearing after the first commit in this PR. --- compiler/src/dotty/tools/dotc/core/Annotations.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala index af0f209ee4b0..5621215af942 100644 --- a/compiler/src/dotty/tools/dotc/core/Annotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala @@ -86,7 +86,7 @@ object Annotations { myTree.asInstanceOf[Tree] override def isEvaluating: Boolean = myTree == null - override def isEvaluated: Boolean = myTree.isInstanceOf[Tree] + override def isEvaluated: Boolean = myTree.isInstanceOf[Tree @unchecked] } /** An annotation indicating the body of a right-hand side, @@ -119,7 +119,7 @@ object Annotations { myTree.asInstanceOf[Tree] override def isEvaluating: Boolean = myTree == null - override def isEvaluated: Boolean = myTree.isInstanceOf[Tree] + override def isEvaluated: Boolean = myTree.isInstanceOf[Tree @unchecked] } object LazyBodyAnnotation { From 7e30d84af9dacc5b262b3395e6be41bfbc97cb7d Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 12:43:37 +0200 Subject: [PATCH 04/19] Move tests --- .../isInstanceOf}/patmat-applied.scala | 0 tests/pos-special/fatal-warnings/i5495.scala | 10 ---------- 2 files changed, 10 deletions(-) rename tests/{pos-special/fatal-warnings => neg-custom-args/isInstanceOf}/patmat-applied.scala (100%) delete mode 100644 tests/pos-special/fatal-warnings/i5495.scala diff --git a/tests/pos-special/fatal-warnings/patmat-applied.scala b/tests/neg-custom-args/isInstanceOf/patmat-applied.scala similarity index 100% rename from tests/pos-special/fatal-warnings/patmat-applied.scala rename to tests/neg-custom-args/isInstanceOf/patmat-applied.scala diff --git a/tests/pos-special/fatal-warnings/i5495.scala b/tests/pos-special/fatal-warnings/i5495.scala deleted file mode 100644 index f41a4692fa11..000000000000 --- a/tests/pos-special/fatal-warnings/i5495.scala +++ /dev/null @@ -1,10 +0,0 @@ -class A -class B - -type AorB = A | B - -def foo(any: Any) = any match { - case aorb: AorB => - case _ => -} - From d61eb85e6aff12e2530ff7a7314d14747cd7111d Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 13:06:45 +0200 Subject: [PATCH 05/19] Handle GADT bounds in isInstanceOf type test --- .../dotty/tools/dotc/transform/TypeTestsCasts.scala | 10 +++++++--- tests/neg-custom-args/isInstanceOf/3324g.scala | 2 +- tests/neg-custom-args/isInstanceOf/i5495.scala | 12 ++++++++++++ .../isInstanceOf/patmat-applied.scala | 2 ++ 4 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 tests/neg-custom-args/isInstanceOf/i5495.scala diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 4dc5a337efc0..e3a22c3f3e4c 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -105,7 +105,11 @@ object TypeTestsCasts { debug.println("P1 : " + P1.show) debug.println("X : " + X.show) - val res = (P1 <:< X) && (P1 <:< P) + P1 <:< X + + maximizeType(P1, span, fromScala2x = false) + + val res = P1 <:< P debug.println("P1 : " + P1.show) debug.println("P1 <:< P = " + res) @@ -133,8 +137,8 @@ object TypeTestsCasts { case _ => // first try withou striping type parameters for performance X.classSymbol.exists && P.classSymbol.exists && !X.classSymbol.asClass.mayHaveCommonChild(P.classSymbol.asClass) || - isClassDetermined(X, tpe)(ctx.fresh.setNewTyperState()) || - isClassDetermined(stripTypeParam(X), tpe)(ctx.fresh.setNewTyperState()) + isClassDetermined(X, tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) || + isClassDetermined(stripTypeParam(X), tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) } case AndType(tp1, tp2) => recur(X, tp1) && recur(X, tp2) case OrType(tp1, tp2) => recur(X, tp1) && recur(X, tp2) diff --git a/tests/neg-custom-args/isInstanceOf/3324g.scala b/tests/neg-custom-args/isInstanceOf/3324g.scala index 423e56eee4b7..5c37929eb464 100644 --- a/tests/neg-custom-args/isInstanceOf/3324g.scala +++ b/tests/neg-custom-args/isInstanceOf/3324g.scala @@ -12,7 +12,7 @@ class Test { } def quux[T](a: A[T]): Unit = a match { - case _: B[T] => // should be an error!! + case _: B[T] => // error!! } quux(new C[Int]) diff --git a/tests/neg-custom-args/isInstanceOf/i5495.scala b/tests/neg-custom-args/isInstanceOf/i5495.scala new file mode 100644 index 000000000000..ad396f1ff6c8 --- /dev/null +++ b/tests/neg-custom-args/isInstanceOf/i5495.scala @@ -0,0 +1,12 @@ +class A +class B + +type AorB = A | B + +def foo(any: Any) = any match { + case aorb: AorB => + case _ => +} + +def bar[T](x: List[T]) = x.isInstanceof[List[Int]] // error + diff --git a/tests/neg-custom-args/isInstanceOf/patmat-applied.scala b/tests/neg-custom-args/isInstanceOf/patmat-applied.scala index c48ae23b8975..eaf3c240aaa1 100644 --- a/tests/neg-custom-args/isInstanceOf/patmat-applied.scala +++ b/tests/neg-custom-args/isInstanceOf/patmat-applied.scala @@ -7,3 +7,5 @@ object Test { case _ => } } + +def bar[T](x: List[T]) = x.isInstanceof[List[Int]] // error From 77bd0cc937ffc2f17c48d3af098cf32e1470338c Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 13:07:05 +0200 Subject: [PATCH 06/19] Add test --- tests/neg-custom-args/isInstanceOf/gadt.scala | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/neg-custom-args/isInstanceOf/gadt.scala diff --git a/tests/neg-custom-args/isInstanceOf/gadt.scala b/tests/neg-custom-args/isInstanceOf/gadt.scala new file mode 100644 index 000000000000..940555e160e7 --- /dev/null +++ b/tests/neg-custom-args/isInstanceOf/gadt.scala @@ -0,0 +1,13 @@ +class Test { + trait A[+T] + class B[T] extends A[T] + + class C + class D extends C + + def quux(a: A[C]): Unit = a match { + case _: B[C] => // error!! + } + + quux(new B[D]) +} \ No newline at end of file From 891db3ca1b7eea49d2e93beb0a6e08fe942f796e Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 13:10:49 +0200 Subject: [PATCH 07/19] Restore original spec --- compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index e3a22c3f3e4c..9df0d0cd4a96 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -47,8 +47,8 @@ object TypeTestsCasts { * 4. if `P = Array[T]`, checkable(E, T) where `E` is the element type of `X`, defaults to `Any`. * 5. if `P` is `pre.F[Ts]` and `pre.F` refers to a class which is not `Array`: * (a) replace `Ts` with fresh type variables `Xs` - * (b) check that we can constrain `Xs` such that `pre.F[Xs] <:< X` and `pre.F[Xs] <:< P` - * can both be true at the same time. + * (b) constrain `Xs` with `pre.F[Xs] <:< X` + * (c) instantiate Xs and check `pre.F[Xs] <:< P` * 6. if `P = T1 | T2` or `P = T1 & T2`, checkable(X, T1) && checkable(X, T2). * 7. if `P` is a refinement type, FALSE * 8. otherwise, TRUE From 2531e1894614be27f86744a267c9757d533bccc0 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 13:48:47 +0200 Subject: [PATCH 08/19] Add test for Tree | Context => Tree --- .../src/dotty/tools/dotc/core/Annotations.scala | 4 ++-- .../isInstanceOf/or-type-trees.scala | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 tests/neg-custom-args/isInstanceOf/or-type-trees.scala diff --git a/compiler/src/dotty/tools/dotc/core/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala index 5621215af942..af0f209ee4b0 100644 --- a/compiler/src/dotty/tools/dotc/core/Annotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala @@ -86,7 +86,7 @@ object Annotations { myTree.asInstanceOf[Tree] override def isEvaluating: Boolean = myTree == null - override def isEvaluated: Boolean = myTree.isInstanceOf[Tree @unchecked] + override def isEvaluated: Boolean = myTree.isInstanceOf[Tree] } /** An annotation indicating the body of a right-hand side, @@ -119,7 +119,7 @@ object Annotations { myTree.asInstanceOf[Tree] override def isEvaluating: Boolean = myTree == null - override def isEvaluated: Boolean = myTree.isInstanceOf[Tree @unchecked] + override def isEvaluated: Boolean = myTree.isInstanceOf[Tree] } object LazyBodyAnnotation { diff --git a/tests/neg-custom-args/isInstanceOf/or-type-trees.scala b/tests/neg-custom-args/isInstanceOf/or-type-trees.scala new file mode 100644 index 000000000000..ddd54f37776d --- /dev/null +++ b/tests/neg-custom-args/isInstanceOf/or-type-trees.scala @@ -0,0 +1,13 @@ +trait Tree +trait Context + +def foo(myTree: Tree | (Context => Tree)) = + println(myTree.isInstanceOf[Tree]) + myTree match + case treeFn: (Context => Tree) => // error + case _ => + +def bar(myTree: Tree | (Context => Tree)) = + myTree match + case treeFn: (_ => _) => // ok + case _ => From 58f506ba7d51e2c659f5553ece4dc3d5d62c1c11 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 13:54:50 +0200 Subject: [PATCH 09/19] Add missing variance annotation --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 59a439e4bb21..631168948121 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -503,7 +503,7 @@ object Trees { type ThisTree[-T >: Untyped] = If[T] def isInline = false } - class InlineIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @constructorOnly src: SourceFile) + class InlineIf[-T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit @constructorOnly src: SourceFile) extends If(cond, thenp, elsep) { override def isInline = true override def toString = s"InlineIf($cond, $thenp, $elsep)" @@ -529,7 +529,7 @@ object Trees { type ThisTree[-T >: Untyped] = Match[T] def isInline = false } - class InlineMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @constructorOnly src: SourceFile) + class InlineMatch[-T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])(implicit @constructorOnly src: SourceFile) extends Match(selector, cases) { override def isInline = true override def toString = s"InlineMatch($selector, $cases)" @@ -579,7 +579,7 @@ object Trees { } /** Array(elems) */ - class JavaSeqLiteral[T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @constructorOnly src: SourceFile) + class JavaSeqLiteral[-T >: Untyped] private[ast] (elems: List[Tree[T]], elemtpt: Tree[T])(implicit @constructorOnly src: SourceFile) extends SeqLiteral(elems, elemtpt) { override def toString: String = s"JavaSeqLiteral($elems, $elemtpt)" } From 10169b1e24c0ce21843000de3acb51e3922fc0f4 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 14:13:06 +0200 Subject: [PATCH 10/19] Add test for Tree | (Context => Tree) --- .../dotty/tools/dotc/core/Annotations.scala | 4 +- .../isInstanceOf/or-type-trees.scala | 51 ++++++++++++++----- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala index af0f209ee4b0..5621215af942 100644 --- a/compiler/src/dotty/tools/dotc/core/Annotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala @@ -86,7 +86,7 @@ object Annotations { myTree.asInstanceOf[Tree] override def isEvaluating: Boolean = myTree == null - override def isEvaluated: Boolean = myTree.isInstanceOf[Tree] + override def isEvaluated: Boolean = myTree.isInstanceOf[Tree @unchecked] } /** An annotation indicating the body of a right-hand side, @@ -119,7 +119,7 @@ object Annotations { myTree.asInstanceOf[Tree] override def isEvaluating: Boolean = myTree == null - override def isEvaluated: Boolean = myTree.isInstanceOf[Tree] + override def isEvaluated: Boolean = myTree.isInstanceOf[Tree @unchecked] } object LazyBodyAnnotation { diff --git a/tests/neg-custom-args/isInstanceOf/or-type-trees.scala b/tests/neg-custom-args/isInstanceOf/or-type-trees.scala index ddd54f37776d..b393578acdc7 100644 --- a/tests/neg-custom-args/isInstanceOf/or-type-trees.scala +++ b/tests/neg-custom-args/isInstanceOf/or-type-trees.scala @@ -1,13 +1,38 @@ -trait Tree -trait Context - -def foo(myTree: Tree | (Context => Tree)) = - println(myTree.isInstanceOf[Tree]) - myTree match - case treeFn: (Context => Tree) => // error - case _ => - -def bar(myTree: Tree | (Context => Tree)) = - myTree match - case treeFn: (_ => _) => // ok - case _ => +object Test1 { + trait Tree + trait Context + + def foo1(myTree: Tree | (Context => Tree)) = + println(myTree.isInstanceOf[Tree]) + + def foo2(myTree: Tree | (Context => Tree)) = + myTree match + case treeFn: (Context => Tree) => // error + case _ => + + def foo3(myTree: Tree | (Context => Tree)) = + myTree match + case treeFn: (_ => _) => // ok + case _ => +} + +object Test2 { + trait Tree[-T] + trait Context + + trait Type + + def foo1(myTree: Tree[Type] | (Context => Tree[Type])) = + println(myTree.isInstanceOf[Tree[Type]]) // error + /* class DummyTree extends Tree[Nothing] with (Context => Tree[Type]) */ + + def foo2(myTree: Tree[Type] | (Context => Tree[Type])) = + myTree match + case treeFn: (Context => Tree[Type]) => // error + case _ => + + def foo3(myTree: Tree[Type] | (Context => Tree[Type])) = + myTree match + case treeFn: (_ => _) => // ok + case _ => +} \ No newline at end of file From 31c751f36a9c486047ec02ea93d84944c0bdac65 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 14:28:59 +0200 Subject: [PATCH 11/19] Fix unchecked warnings in compiler --- .../tools/dotc/interactive/Completion.scala | 2 +- .../ReflectionCompilerInterface.scala | 134 +++++++++--------- .../dotty/tools/dotc/transform/Erasure.scala | 4 +- .../tools/dotc/transform/TreeChecker.scala | 2 +- .../dotty/tools/dotc/typer/Applications.scala | 4 +- .../dotty/tools/dotc/typer/Nullables.scala | 4 +- .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- 7 files changed, 76 insertions(+), 76 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index 1785164eff8f..668dd8f078ec 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -89,7 +89,7 @@ object Completion { completionPrefix(selector :: Nil, pos) }.getOrElse("") - case (ref: RefTree) :: _ => + case (ref: untpd.RefTree) :: _ => if (ref.name == nme.ERROR) "" else ref.name.toString.take(pos.span.point - ref.span.point) diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index 1e9eab79b66f..c2bb1173aced 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -117,7 +117,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfPackageClause(using ctx: Context): IsInstanceOf[PackageClause] = new { def runtimeClass: Class[?] = classOf[PackageClause] override def unapply(x: Any): Option[PackageClause] = x match - case x: tpd.PackageDef => Some(x) + case x: tpd.PackageDef @unchecked => Some(x) case _ => None } @@ -135,9 +135,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfStatement(using ctx: Context): IsInstanceOf[Statement] = new { def runtimeClass: Class[?] = classOf[Statement] override def unapply(x: Any): Option[Statement] = x match - case _: PatternTree => None - case tree: Tree if tree.isTerm => isInstanceOfTerm.unapply(tree) - case tree: Tree => isInstanceOfDefinition.unapply(tree) + case _: PatternTree @unchecked => None + case tree: Tree @unchecked if tree.isTerm => isInstanceOfTerm.unapply(tree) + case tree: Tree @unchecked => isInstanceOfDefinition.unapply(tree) case _ => None } @@ -146,7 +146,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfImport(using ctx: Context): IsInstanceOf[Import] = new { def runtimeClass: Class[?] = classOf[Import] override def unapply(x: Any): Option[Import] = x match - case tree: tpd.Import => Some(tree) + case tree: tpd.Import @unchecked => Some(tree) case _ => None } @@ -165,8 +165,8 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfDefinition(using ctx: Context): IsInstanceOf[Definition] = new { def runtimeClass: Class[?] = classOf[Definition] override def unapply(x: Any): Option[Definition] = x match - case x: tpd.MemberDef => Some(x) - case x: PackageDefinition => Some(x) + case x: tpd.MemberDef @unchecked => Some(x) + case x: PackageDefinition @unchecked => Some(x) case _ => None } @@ -180,7 +180,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfPackageDef(using ctx: Context): IsInstanceOf[PackageDef] = new { def runtimeClass: Class[?] = classOf[PackageDef] override def unapply(x: Any): Option[PackageDef] = x match - case x: PackageDefinition => Some(x) + case x: PackageDefinition @unchecked => Some(x) case _ => None } @@ -195,7 +195,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfClassDef(using ctx: Context): IsInstanceOf[ClassDef] = new { def runtimeClass: Class[?] = classOf[ClassDef] override def unapply(x: Any): Option[ClassDef] = x match - case x: tpd.TypeDef if x.isClassDef => Some(x) + case x: tpd.TypeDef @unchecked if x.isClassDef => Some(x) case _ => None } @@ -216,7 +216,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfTypeDef(using ctx: Context): IsInstanceOf[TypeDef] = new { def runtimeClass: Class[?] = classOf[TypeDef] override def unapply(x: Any): Option[TypeDef] = x match - case x: tpd.TypeDef if !x.isClassDef => Some(x) + case x: tpd.TypeDef @unchecked if !x.isClassDef => Some(x) case _ => None } @@ -231,7 +231,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfDefDef(using ctx: Context): IsInstanceOf[DefDef] = new { def runtimeClass: Class[?] = classOf[DefDef] override def unapply(x: Any): Option[DefDef] = x match - case x: tpd.DefDef => Some(x) + case x: tpd.DefDef @unchecked => Some(x) case _ => None } @@ -251,7 +251,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfValDef(using ctx: Context): IsInstanceOf[ValDef] = new { def runtimeClass: Class[?] = classOf[ValDef] override def unapply(x: Any): Option[ValDef] = x match - case x: tpd.ValDef => Some(x) + case x: tpd.ValDef @unchecked => Some(x) case _ => None } @@ -270,9 +270,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def runtimeClass: Class[?] = classOf[Term] override def unapply(x: Any): Option[Term] = x match case _ if isInstanceOfUnapply.unapply(x).isDefined => None - case _: tpd.PatternTree => None - case x: tpd.SeqLiteral => Some(x) - case x: tpd.Tree if x.isTerm => Some(x) + case _: tpd.PatternTree @unchecked => None + case x: tpd.SeqLiteral @unchecked => Some(x) + case x: tpd.Tree @unchecked if x.isTerm => Some(x) case _ => None } @@ -283,7 +283,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def Term_etaExpand(term: Term)(using ctx: Context): Term = term.tpe.widen match { case mtpe: Types.MethodType if !mtpe.isParamDependent => val closureResType = mtpe.resType match { - case t: Types.MethodType => t.toFunctionType() + case t: Types.MethodType @unchecked => t.toFunctionType() case t => t } val closureTpe = Types.MethodType(mtpe.paramNames, mtpe.paramInfos, closureResType) @@ -302,7 +302,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfRef(using ctx: Context): IsInstanceOf[Ref] = new { def runtimeClass: Class[?] = classOf[Ref] override def unapply(x: Any): Option[Ref] = x match - case x: tpd.RefTree if x.isTerm => Some(x) + case x: tpd.RefTree @unchecked if x.isTerm => Some(x) case _ => None } @@ -319,7 +319,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfIdent(using ctx: Context): IsInstanceOf[Ident] = new { def runtimeClass: Class[?] = classOf[Ident] override def unapply(x: Any): Option[Ident] = x match - case x: tpd.Ident if x.isTerm => Some(x) + case x: tpd.Ident @unchecked if x.isTerm => Some(x) case _ => None } @@ -336,7 +336,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfSelect(using ctx: Context): IsInstanceOf[Select] = new { def runtimeClass: Class[?] = classOf[Select] override def unapply(x: Any): Option[Select] = x match - case x: tpd.Select if x.isTerm => Some(x) + case x: tpd.Select @unchecked if x.isTerm => Some(x) case _ => None } @@ -367,7 +367,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfLiteral(using ctx: Context): IsInstanceOf[Literal] = new { def runtimeClass: Class[?] = classOf[Literal] override def unapply(x: Any): Option[Literal] = x match - case x: tpd.Literal => Some(x) + case x: tpd.Literal @unchecked => Some(x) case _ => None } @@ -384,7 +384,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfThis(using ctx: Context): IsInstanceOf[This] = new { def runtimeClass: Class[?] = classOf[This] override def unapply(x: Any): Option[This] = x match - case x: tpd.This => Some(x) + case x: tpd.This @unchecked => Some(x) case _ => None } @@ -401,7 +401,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfNew(using ctx: Context): IsInstanceOf[New] = new { def runtimeClass: Class[?] = classOf[New] override def unapply(x: Any): Option[New] = x match - case x: tpd.New => Some(x) + case x: tpd.New @unchecked => Some(x) case _ => None } @@ -417,7 +417,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfNamedArg(using ctx: Context): IsInstanceOf[NamedArg] = new { def runtimeClass: Class[?] = classOf[NamedArg] override def unapply(x: Any): Option[NamedArg] = x match - case x: tpd.NamedArg if x.name.isInstanceOf[core.Names.TermName] => Some(x) // TODO: Now, the name should alwas be a term name + case x: tpd.NamedArg @unchecked if x.name.isInstanceOf[core.Names.TermName] => Some(x) // TODO: Now, the name should alwas be a term name case _ => None } @@ -435,7 +435,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfApply(using ctx: Context): IsInstanceOf[Apply] = new { def runtimeClass: Class[?] = classOf[Apply] override def unapply(x: Any): Option[Apply] = x match - case x: tpd.Apply => Some(x) + case x: tpd.Apply @unchecked => Some(x) case _ => None } @@ -454,7 +454,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfTypeApply(using ctx: Context): IsInstanceOf[TypeApply] = new { def runtimeClass: Class[?] = classOf[TypeApply] override def unapply(x: Any): Option[TypeApply] = x match - case x: tpd.TypeApply => Some(x) + case x: tpd.TypeApply @unchecked => Some(x) case _ => None } @@ -472,7 +472,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfSuper(using ctx: Context): IsInstanceOf[Super] = new { def runtimeClass: Class[?] = classOf[Super] override def unapply(x: Any): Option[Super] = x match - case x: tpd.Super => Some(x) + case x: tpd.Super @unchecked => Some(x) case _ => None } @@ -490,7 +490,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfTyped(using ctx: Context): IsInstanceOf[Typed] = new { def runtimeClass: Class[?] = classOf[Typed] override def unapply(x: Any): Option[Typed] = x match - case x: tpd.Typed => Some(x) + case x: tpd.Typed @unchecked => Some(x) case _ => None } @@ -508,7 +508,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfAssign(using ctx: Context): IsInstanceOf[Assign] = new { def runtimeClass: Class[?] = classOf[Assign] override def unapply(x: Any): Option[Assign] = x match - case x: tpd.Assign => Some(x) + case x: tpd.Assign @unchecked => Some(x) case _ => None } @@ -527,7 +527,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def runtimeClass: Class[?] = classOf[Block] override def unapply(x: Any): Option[Block] = x match - case x: tpd.Tree => + case x: tpd.Tree @unchecked => normalizedLoops(x) match case y: tpd.Block => Some(y) case _ => None @@ -578,7 +578,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfInlined(using ctx: Context): IsInstanceOf[Inlined] = new { def runtimeClass: Class[?] = classOf[Inlined] override def unapply(x: Any): Option[Inlined] = x match - case x: tpd.Inlined => Some(x) + case x: tpd.Inlined @unchecked => Some(x) case _ => None } @@ -597,7 +597,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfClosure(using ctx: Context): IsInstanceOf[Closure] = new { def runtimeClass: Class[?] = classOf[Closure] override def unapply(x: Any): Option[Closure] = x match - case x: tpd.Closure => Some(x) + case x: tpd.Closure @unchecked => Some(x) case _ => None } @@ -618,7 +618,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfIf(using ctx: Context): IsInstanceOf[If] = new { def runtimeClass: Class[?] = classOf[If] override def unapply(x: Any): Option[If] = x match - case x: tpd.If => Some(x) + case x: tpd.If @unchecked => Some(x) case _ => None } @@ -637,7 +637,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfMatch(using ctx: Context): IsInstanceOf[Match] = new { def runtimeClass: Class[?] = classOf[Match] override def unapply(x: Any): Option[Match] = x match - case x: tpd.Match if !x.selector.isEmpty => Some(x) + case x: tpd.Match @unchecked if !x.selector.isEmpty => Some(x) case _ => None } @@ -655,7 +655,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfGivenMatch(using ctx: Context): IsInstanceOf[GivenMatch] = new { def runtimeClass: Class[?] = classOf[GivenMatch] override def unapply(x: Any): Option[GivenMatch] = x match - case x: tpd.Match if x.selector.isEmpty => Some(x) + case x: tpd.Match @unchecked if x.selector.isEmpty => Some(x) case _ => None } @@ -672,7 +672,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfTry(using ctx: Context): IsInstanceOf[Try] = new { def runtimeClass: Class[?] = classOf[Try] override def unapply(x: Any): Option[Try] = x match - case x: tpd.Try => Some(x) + case x: tpd.Try @unchecked => Some(x) case _ => None } @@ -691,7 +691,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfReturn(using ctx: Context): IsInstanceOf[Return] = new { def runtimeClass: Class[?] = classOf[Return] override def unapply(x: Any): Option[Return] = x match - case x: tpd.Return => Some(x) + case x: tpd.Return @unchecked => Some(x) case _ => None } @@ -708,7 +708,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfRepeated(using ctx: Context): IsInstanceOf[Repeated] = new { def runtimeClass: Class[?] = classOf[Repeated] override def unapply(x: Any): Option[Repeated] = x match - case x: tpd.SeqLiteral => Some(x) + case x: tpd.SeqLiteral @unchecked => Some(x) case _ => None } @@ -726,7 +726,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfSelectOuter(using ctx: Context): IsInstanceOf[SelectOuter] = new { def runtimeClass: Class[?] = classOf[SelectOuter] override def unapply(x: Any): Option[SelectOuter] = x match - case x: tpd.Select => + case x: tpd.Select @unchecked => x.name match case NameKinds.OuterSelectName(_, _) => Some(x) case _ => None @@ -750,7 +750,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfWhile(using ctx: Context): IsInstanceOf[While] = new { def runtimeClass: Class[?] = classOf[While] override def unapply(x: Any): Option[While] = x match - case x: tpd.WhileDo => Some(x) + case x: tpd.WhileDo @unchecked => Some(x) case _ => None } @@ -768,8 +768,8 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfTypeTree(using ctx: Context): IsInstanceOf[TypeTree] = new { def runtimeClass: Class[?] = classOf[TypeTree] override def unapply(x: Any): Option[TypeTree] = x match - case x: tpd.TypeBoundsTree => None - case x: tpd.Tree if x.isType => Some(x) + case x: tpd.TypeBoundsTree @unchecked => None + case x: tpd.Tree @unchecked if x.isType => Some(x) case _ => None } @@ -780,7 +780,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfInferred(using ctx: Context): IsInstanceOf[Inferred] = new { def runtimeClass: Class[?] = classOf[Inferred] override def unapply(x: Any): Option[Inferred] = x match - case tpt: tpd.TypeTree if !tpt.tpe.isInstanceOf[Types.TypeBounds] => Some(tpt) + case tpt: tpd.TypeTree @unchecked if !tpt.tpe.isInstanceOf[Types.TypeBounds] => Some(tpt) case _ => None } @@ -791,7 +791,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfTypeIdent(using ctx: Context): IsInstanceOf[TypeIdent] = new { def runtimeClass: Class[?] = classOf[TypeIdent] override def unapply(x: Any): Option[TypeIdent] = x match - case tpt: tpd.Ident if tpt.isType => Some(tpt) + case tpt: tpd.Ident @unchecked if tpt.isType => Some(tpt) case _ => None } @@ -805,7 +805,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfTypeSelect(using ctx: Context): IsInstanceOf[TypeSelect] = new { def runtimeClass: Class[?] = classOf[TypeSelect] override def unapply(x: Any): Option[TypeSelect] = x match - case tpt: tpd.Select if tpt.isType && tpt.qualifier.isTerm => Some(tpt) + case tpt: tpd.Select @unchecked if tpt.isType && tpt.qualifier.isTerm => Some(tpt) case _ => None } @@ -824,7 +824,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfProjection(using ctx: Context): IsInstanceOf[Projection] = new { def runtimeClass: Class[?] = classOf[Projection] override def unapply(x: Any): Option[Projection] = x match - case tpt: tpd.Select if tpt.isType && tpt.qualifier.isType => Some(tpt) + case tpt: tpd.Select @unchecked if tpt.isType && tpt.qualifier.isType => Some(tpt) case _ => None } @@ -839,7 +839,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfSingleton(using ctx: Context): IsInstanceOf[Singleton] = new { def runtimeClass: Class[?] = classOf[Singleton] override def unapply(x: Any): Option[Singleton] = x match - case tpt: tpd.SingletonTypeTree => Some(tpt) + case tpt: tpd.SingletonTypeTree @unchecked => Some(tpt) case _ => None } @@ -856,7 +856,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfRefined(using ctx: Context): IsInstanceOf[Refined] = new { def runtimeClass: Class[?] = classOf[Refined] override def unapply(x: Any): Option[Refined] = x match - case tpt: tpd.RefinedTypeTree => Some(tpt) + case tpt: tpd.RefinedTypeTree @unchecked => Some(tpt) case _ => None } @@ -871,7 +871,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfApplied(using ctx: Context): IsInstanceOf[Applied] = new { def runtimeClass: Class[?] = classOf[Applied] override def unapply(x: Any): Option[Applied] = x match - case tpt: tpd.AppliedTypeTree => Some(tpt) + case tpt: tpd.AppliedTypeTree @unchecked => Some(tpt) case _ => None } @@ -889,7 +889,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfAnnotated(using ctx: Context): IsInstanceOf[Annotated] = new { def runtimeClass: Class[?] = classOf[Annotated] override def unapply(x: Any): Option[Annotated] = x match - case tpt: tpd.Annotated => Some(tpt) + case tpt: tpd.Annotated @unchecked => Some(tpt) case _ => None } @@ -907,7 +907,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfMatchTypeTree(using ctx: Context): IsInstanceOf[MatchTypeTree] = new { def runtimeClass: Class[?] = classOf[MatchTypeTree] override def unapply(x: Any): Option[MatchTypeTree] = x match - case tpt: tpd.MatchTypeTree => Some(tpt) + case tpt: tpd.MatchTypeTree @unchecked => Some(tpt) case _ => None } @@ -926,7 +926,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfByName(using ctx: Context): IsInstanceOf[ByName] = new { def runtimeClass: Class[?] = classOf[ByName] override def unapply(x: Any): Option[ByName] = x match - case tpt: tpd.ByNameTypeTree => Some(tpt) + case tpt: tpd.ByNameTypeTree @unchecked => Some(tpt) case _ => None } @@ -943,7 +943,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfLambdaTypeTree(using ctx: Context): IsInstanceOf[LambdaTypeTree] = new { def runtimeClass: Class[?] = classOf[LambdaTypeTree] override def unapply(x: Any): Option[LambdaTypeTree] = x match - case tpt: tpd.LambdaTypeTree => Some(tpt) + case tpt: tpd.LambdaTypeTree @unchecked => Some(tpt) case _ => None } @@ -961,7 +961,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfTypeBind(using ctx: Context): IsInstanceOf[TypeBind] = new { def runtimeClass: Class[?] = classOf[TypeBind] override def unapply(x: Any): Option[TypeBind] = x match - case tpt: tpd.Bind if tpt.name.isTypeName => Some(tpt) + case tpt: tpd.Bind @unchecked if tpt.name.isTypeName => Some(tpt) case _ => None } @@ -976,7 +976,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfTypeBlock(using ctx: Context): IsInstanceOf[TypeBlock] = new { def runtimeClass: Class[?] = classOf[TypeBlock] override def unapply(x: Any): Option[TypeBlock] = x match - case tpt: tpd.Block => Some(tpt) + case tpt: tpd.Block @unchecked => Some(tpt) case _ => None } @@ -994,7 +994,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfTypeBoundsTree(using ctx: Context): IsInstanceOf[TypeBoundsTree] = new { def runtimeClass: Class[?] = classOf[TypeBoundsTree] override def unapply(x: Any): Option[TypeBoundsTree] = x match - case x: tpd.TypeBoundsTree => Some(x) + case x: tpd.TypeBoundsTree @unchecked => Some(x) case x @ tpd.TypeTree() => // TODO only enums generate this kind of type bounds. Is this possible without enums? If not generate tpd.TypeBoundsTree for enums instead (x.tpe: Any) match { @@ -1014,7 +1014,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfWildcardTypeTree(using ctx: Context): IsInstanceOf[WildcardTypeTree] = new { def runtimeClass: Class[?] = classOf[WildcardTypeTree] override def unapply(x: Any): Option[WildcardTypeTree] = x match - case x: tpd.Ident if x.name == nme.WILDCARD => Some(x) + case x: tpd.Ident @unchecked if x.name == nme.WILDCARD => Some(x) case _ => None } @@ -1025,7 +1025,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfCaseDef(using ctx: Context): IsInstanceOf[CaseDef] = new { def runtimeClass: Class[?] = classOf[CaseDef] override def unapply(x: Any): Option[CaseDef] = x match - case tree: tpd.CaseDef if tree.body.isTerm => Some(tree) + case tree: tpd.CaseDef @unchecked if tree.body.isTerm => Some(tree) case _ => None } @@ -1044,7 +1044,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfTypeCaseDef(using ctx: Context): IsInstanceOf[TypeCaseDef] = new { def runtimeClass: Class[?] = classOf[TypeCaseDef] override def unapply(x: Any): Option[TypeCaseDef] = x match - case tree: tpd.CaseDef if tree.body.isType => Some(tree) + case tree: tpd.CaseDef @unchecked if tree.body.isType => Some(tree) case _ => None } @@ -1062,7 +1062,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfBind(using ctx: Context): IsInstanceOf[Bind] = new { def runtimeClass: Class[?] = classOf[Bind] override def unapply(x: Any): Option[Bind] = x match - case x: tpd.Bind if x.name.isTermName => Some(x) + case x: tpd.Bind @unchecked if x.name.isTermName => Some(x) case _ => None } @@ -1078,8 +1078,8 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfUnapply(using ctx: Context): IsInstanceOf[Unapply] = new { def runtimeClass: Class[?] = classOf[Unapply] override def unapply(x: Any): Option[Unapply] = x match - case pattern: tpd.UnApply => Some(pattern) - case Trees.Typed(pattern: tpd.UnApply, _) => Some(pattern) + case pattern: tpd.UnApply @unchecked => Some(pattern) + case Trees.Typed(pattern: tpd.UnApply @unchecked, _) => Some(pattern) case _ => None } @@ -1100,7 +1100,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfAlternatives(using ctx: Context): IsInstanceOf[Alternatives] = new { def runtimeClass: Class[?] = classOf[Alternatives] override def unapply(x: Any): Option[Alternatives] = x match - case x: tpd.Alternative => Some(x) + case x: tpd.Alternative @unchecked => Some(x) case _ => None } @@ -2002,7 +2002,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfImplicitSearchSuccess(using ctx: Context): IsInstanceOf[ImplicitSearchSuccess] = new { def runtimeClass: Class[?] = classOf[ImplicitSearchSuccess] override def unapply(x: Any): Option[ImplicitSearchSuccess] = x match - case x: Tree => + case x: Tree @unchecked => x.tpe match case _: SearchFailureType => None case _ => Some(x) @@ -2014,7 +2014,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfImplicitSearchFailure(using ctx: Context): IsInstanceOf[ImplicitSearchFailure] = new { def runtimeClass: Class[?] = classOf[ImplicitSearchFailure] override def unapply(x: Any): Option[ImplicitSearchFailure] = x match - case x: Tree => + case x: Tree @unchecked => x.tpe match case _: SearchFailureType => Some(x) case _ => None @@ -2027,7 +2027,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfDivergingImplicit(using ctx: Context): IsInstanceOf[DivergingImplicit] = new { def runtimeClass: Class[?] = classOf[DivergingImplicit] override def unapply(x: Any): Option[DivergingImplicit] = x match - case x: Tree => + case x: Tree @unchecked => x.tpe match case _: Implicits.DivergingImplicit => Some(x) case _ => None @@ -2038,7 +2038,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfNoMatchingImplicits(using ctx: Context): IsInstanceOf[NoMatchingImplicits] = new { def runtimeClass: Class[?] = classOf[NoMatchingImplicits] override def unapply(x: Any): Option[NoMatchingImplicits] = x match - case x: Tree => + case x: Tree @unchecked => x.tpe match case _: Implicits.NoMatchingImplicits => Some(x) case _ => None @@ -2049,7 +2049,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def isInstanceOfAmbiguousImplicits(using ctx: Context): IsInstanceOf[AmbiguousImplicits] = new { def runtimeClass: Class[?] = classOf[AmbiguousImplicits] override def unapply(x: Any): Option[AmbiguousImplicits] = x match - case x: Tree => + case x: Tree @unchecked => x.tpe match case _: Implicits.AmbiguousImplicits => Some(x) case _ => None diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index d8eb393e91d0..24ab78f4df7a 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -907,7 +907,7 @@ object Erasure { */ private def addRetainedInlineBodies(stats: List[untpd.Tree])(using Context): List[untpd.Tree] = lazy val retainerDef: Map[Symbol, DefDef] = stats.collect { - case stat: DefDef if stat.symbol.name.is(BodyRetainerName) => + case stat: DefDef @unchecked if stat.symbol.name.is(BodyRetainerName) => val retainer = stat.symbol val origName = retainer.name.asTermName.exclude(BodyRetainerName) val inlineMeth = ctx.atPhase(ctx.typerPhase) { @@ -918,7 +918,7 @@ object Erasure { (inlineMeth, stat) }.toMap stats.mapConserve { - case stat: DefDef if stat.symbol.isRetainedInlineMethod => + case stat: DefDef @unchecked if stat.symbol.isRetainedInlineMethod => val rdef = retainerDef(stat.symbol) val fromParams = untpd.allParamSyms(rdef) val toParams = untpd.allParamSyms(stat) diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index e0831e32124c..d1cd9f870d37 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -455,7 +455,7 @@ class TreeChecker extends Phase with SymTransformer { override def typedClosure(tree: untpd.Closure, pt: Type)(using Context): Tree = { if (!ctx.phase.lambdaLifted) nestingBlock match { - case block @ Block((meth : DefDef) :: Nil, closure: Closure) => + case block @ Block((meth : untpd.DefDef) :: Nil, closure: untpd.Closure) => assert(meth.symbol == closure.meth.symbol, "closure.meth symbol not equal to method symbol. Block: " + block.show) case block: untpd.Block => diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 464a14d51cec..a98c232cc8cc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -910,8 +910,8 @@ trait Applications extends Compatibility { tree.args match { case (arg @ Match(EmptyTree, cases)) :: Nil => cases.foreach { - case CaseDef(Typed(_: Ident, _), _, _) => // OK - case CaseDef(Bind(_, Typed(_: Ident, _)), _, _) => // OK + case CaseDef(Typed(_: untpd.Ident, _), _, _) => // OK + case CaseDef(Bind(_, Typed(_: untpd.Ident, _)), _, _) => // OK case CaseDef(Ident(name), _, _) if name == nme.WILDCARD => // Ok case CaseDef(pat, _, _) => ctx.error(UnexpectedPatternForSummonFrom(pat), pat.sourcePos) diff --git a/compiler/src/dotty/tools/dotc/typer/Nullables.scala b/compiler/src/dotty/tools/dotc/typer/Nullables.scala index ad64a8f41f89..4834f3aa016d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Nullables.scala +++ b/compiler/src/dotty/tools/dotc/typer/Nullables.scala @@ -489,8 +489,8 @@ object Nullables: object retyper extends ReTyper: override def typedUnadapted(t: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = t match - case t: ValDef if !t.symbol.is(Lazy) => super.typedUnadapted(t, pt, locked) - case t: MemberDef => promote(t) + case t: untpd.ValDef if !t.symbol.is(Lazy) => super.typedUnadapted(t, pt, locked) + case t: untpd.MemberDef => promote(t) case _ => super.typedUnadapted(t, pt, locked) def postProcess(formal: Type, arg: Tree): Tree = diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index d5fc2cb29caf..8cd906f5cb47 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1264,7 +1264,7 @@ class Typer extends Namer .map(cas => untpd.unbind(untpd.unsplice(cas.pat))) .zip(mt.cases) .forall { - case (pat: Typed, pt) => + case (pat: untpd.Typed, pt) => // To check that pattern types correspond we need to type // check `pat` here and throw away the result. val gadtCtx: Context = ctx.fresh.setFreshGADTBounds From 77e96cda07dfd7f243ffff200deb495e983c0a5a Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 14:53:14 +0200 Subject: [PATCH 12/19] Fix typo in comment --- compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 9df0d0cd4a96..7af553bd2c29 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -135,7 +135,7 @@ object TypeTestsCasts { // See TypeComparer#either recur(tp1, P) && recur(tp2, P) case _ => - // first try withou striping type parameters for performance + // first try without striping type parameters for performance X.classSymbol.exists && P.classSymbol.exists && !X.classSymbol.asClass.mayHaveCommonChild(P.classSymbol.asClass) || isClassDetermined(X, tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) || isClassDetermined(stripTypeParam(X), tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) From b5ae277e0a6aa5f15b96512674220c81ff1b96c4 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 15:28:15 +0200 Subject: [PATCH 13/19] Fix unchecked warning in language server --- .../src/dotty/tools/languageserver/DottyLanguageServer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala b/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala index c6314d7a3cd6..1cd39fac92ab 100644 --- a/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala +++ b/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala @@ -392,7 +392,7 @@ class DottyLanguageServer extends LanguageServer val refs = path match { // Selected a renaming in an import node - case untpd.ImportSelector(_, rename: Ident, _) :: (_: Import) :: rest if rename.span.contains(pos.span) => + case untpd.ImportSelector(_, rename: untpd.Ident, _) :: (_: Import) :: rest if rename.span.contains(pos.span) => findRenamedReferences(uriTrees, syms, rename.name) // Selected a reference that has been renamed From 1cb965af7a78e800b331a89e374ae417e9f026ba Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 18:19:36 +0200 Subject: [PATCH 14/19] Add more test case --- .../isInstanceOf/JavaSeqLiteral.scala | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/neg-custom-args/isInstanceOf/JavaSeqLiteral.scala diff --git a/tests/neg-custom-args/isInstanceOf/JavaSeqLiteral.scala b/tests/neg-custom-args/isInstanceOf/JavaSeqLiteral.scala new file mode 100644 index 000000000000..19f15dc0957a --- /dev/null +++ b/tests/neg-custom-args/isInstanceOf/JavaSeqLiteral.scala @@ -0,0 +1,29 @@ +object Test1 { + trait Tree[-T] + + class JavaSeqLiteral[T] extends Tree[T] + + trait Type + + class DummyTree extends JavaSeqLiteral[Any] + + def foo1(tree: Tree[Type]) = + tree.isInstanceOf[JavaSeqLiteral[Type]] // error + + foo1(new DummyTree) +} + +object Test2 { + trait Tree[-T] + + class JavaSeqLiteral[-T] extends Tree[T] + + trait Type + + class DummyTree extends JavaSeqLiteral[Any] + + def foo1(tree: Tree[Type]) = + tree.isInstanceOf[JavaSeqLiteral[Type]] + + foo1(new DummyTree) +} \ No newline at end of file From 2e028af0f47456bc66b8f702c33ce6f640eb52dd Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Tue, 28 Apr 2020 20:07:10 +0200 Subject: [PATCH 15/19] Add documentation for code --- .../dotty/tools/dotc/transform/TypeTestsCasts.scala | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 7af553bd2c29..e5ca49f180c4 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -48,7 +48,7 @@ object TypeTestsCasts { * 5. if `P` is `pre.F[Ts]` and `pre.F` refers to a class which is not `Array`: * (a) replace `Ts` with fresh type variables `Xs` * (b) constrain `Xs` with `pre.F[Xs] <:< X` - * (c) instantiate Xs and check `pre.F[Xs] <:< P` + * (c) maximize `pre.F[Xs]` and check `pre.F[Xs] <:< P` * 6. if `P = T1 | T2` or `P = T1 & T2`, checkable(X, T1) && checkable(X, T2). * 7. if `P` is a refinement type, FALSE * 8. otherwise, TRUE @@ -105,8 +105,17 @@ object TypeTestsCasts { debug.println("P1 : " + P1.show) debug.println("X : " + X.show) + // It does not matter if P1 is not a subtype of X. + // It just tries to infer type arguments of P1 from X if the value x + // conforms to the type skeleton pre.F[_]. Then it goes on to check + // if P1 <: P, which means the type arguments in P are trivial, + // thus no runtime checks are needed for them. P1 <:< X + // Maximization of the type means we try to cover all possible values + // which conform to the skeleton pre.F[_] and X. Then we have to make + // sure all of them are actually of the type P, which implies that the + // type arguments in P are trivial (no runtime check needed). maximizeType(P1, span, fromScala2x = false) val res = P1 <:< P From 33094bfcdd5b667a30fd55cb8a3a2729d633f141 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Wed, 29 Apr 2020 13:42:02 +0200 Subject: [PATCH 16/19] Address review: add comment --- compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index e5ca49f180c4..455670218583 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -144,8 +144,9 @@ object TypeTestsCasts { // See TypeComparer#either recur(tp1, P) && recur(tp2, P) case _ => - // first try without striping type parameters for performance + // always false test warnings are emitted elsewhere X.classSymbol.exists && P.classSymbol.exists && !X.classSymbol.asClass.mayHaveCommonChild(P.classSymbol.asClass) || + // first try without striping type parameters for performance isClassDetermined(X, tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) || isClassDetermined(stripTypeParam(X), tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) } From fb672e59f7dd5bcd9853a88e7bf47643c7db96f8 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Wed, 29 Apr 2020 13:57:14 +0200 Subject: [PATCH 17/19] Address review: rename isClassDetermined to typeArgsTrivial --- .../src/dotty/tools/dotc/transform/TypeTestsCasts.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 455670218583..fb49baf673e8 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -90,7 +90,8 @@ object TypeTestsCasts { } }.apply(tp) - def isClassDetermined(X: Type, P: AppliedType)(implicit ctx: Context) = { + /** Returns true if the type arguments of `P` can be determined from `X` */ + def typeArgsTrivial(X: Type, P: AppliedType)(implicit ctx: Context) = { val AppliedType(tycon, _) = P def underlyingLambda(tp: Type): TypeLambda = tp.ensureLambdaSub match { @@ -147,8 +148,8 @@ object TypeTestsCasts { // always false test warnings are emitted elsewhere X.classSymbol.exists && P.classSymbol.exists && !X.classSymbol.asClass.mayHaveCommonChild(P.classSymbol.asClass) || // first try without striping type parameters for performance - isClassDetermined(X, tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) || - isClassDetermined(stripTypeParam(X), tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) + typeArgsTrivial(X, tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) || + typeArgsTrivial(stripTypeParam(X), tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) } case AndType(tp1, tp2) => recur(X, tp1) && recur(X, tp2) case OrType(tp1, tp2) => recur(X, tp1) && recur(X, tp2) From 4a5ab5ac50ef8b8c2f77cd1eb385f5c2bd3b1b87 Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Wed, 29 Apr 2020 14:00:16 +0200 Subject: [PATCH 18/19] Address review: code refactoring --- .../src/dotty/tools/dotc/transform/TypeTestsCasts.scala | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index fb49baf673e8..c0f9f976d3ee 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -91,7 +91,7 @@ object TypeTestsCasts { }.apply(tp) /** Returns true if the type arguments of `P` can be determined from `X` */ - def typeArgsTrivial(X: Type, P: AppliedType)(implicit ctx: Context) = { + def typeArgsTrivial(X: Type, P: AppliedType)(using Context) = inContext(ctx.fresh.setExploreTyperState().setFreshGADTBounds) { val AppliedType(tycon, _) = P def underlyingLambda(tp: Type): TypeLambda = tp.ensureLambdaSub match { @@ -146,10 +146,11 @@ object TypeTestsCasts { recur(tp1, P) && recur(tp2, P) case _ => // always false test warnings are emitted elsewhere - X.classSymbol.exists && P.classSymbol.exists && !X.classSymbol.asClass.mayHaveCommonChild(P.classSymbol.asClass) || + X.classSymbol.exists && P.classSymbol.exists && + !X.classSymbol.asClass.mayHaveCommonChild(P.classSymbol.asClass) || // first try without striping type parameters for performance - typeArgsTrivial(X, tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) || - typeArgsTrivial(stripTypeParam(X), tpe)(ctx.fresh.setNewTyperState().setFreshGADTBounds) + typeArgsTrivial(X, tpe) || + typeArgsTrivial(stripTypeParam(X), tpe) } case AndType(tp1, tp2) => recur(X, tp1) && recur(X, tp2) case OrType(tp1, tp2) => recur(X, tp1) && recur(X, tp2) From 841d19176f3fdc7da45e800634e9f3f6971c9add Mon Sep 17 00:00:00 2001 From: Liu Fengyun Date: Wed, 29 Apr 2020 14:04:15 +0200 Subject: [PATCH 19/19] Add test case for type lambda --- .../neg-custom-args/isInstanceOf/type-lambda.scala | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/neg-custom-args/isInstanceOf/type-lambda.scala diff --git a/tests/neg-custom-args/isInstanceOf/type-lambda.scala b/tests/neg-custom-args/isInstanceOf/type-lambda.scala new file mode 100644 index 000000000000..d17b3a026f4c --- /dev/null +++ b/tests/neg-custom-args/isInstanceOf/type-lambda.scala @@ -0,0 +1,14 @@ +trait A[T] +trait B[T] extends A[T] + +object Test { + def foo(x: ([X] =>> A[X])[Any]) = x match { + case x: ([X] =>> B[X])[Any] => + case _ => + } + + def bar(x: ([X] =>> A[X])[Any]) = x match { + case x: ([X] =>> B[Nothing])[Any] => // error + case _ => + } +}