From 8f7fd96fb343ba41a77cc13114e04beef41724ba Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 27 May 2021 10:52:55 +0200 Subject: [PATCH] Fix hole in scan for outer references Type tests of singletons need to be considered as well. --- .../src/dotty/tools/dotc/transform/ExplicitOuter.scala | 7 +++++++ .../src/dotty/tools/dotc/transform/TypeTestsCasts.scala | 2 +- tests/pos/i12616.scala | 9 +++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i12616.scala diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index 8b13633e6125..7a211631a481 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -282,6 +282,10 @@ object ExplicitOuter { case TypeRef(prefix, _) => isOuterRef(prefix) case _ => false } + def containsOuterRefs(tp: Type): Boolean = tp match + case tp: SingletonType => isOuterRef(tp) + case tp: AndOrType => containsOuterRefs(tp.tp1) || containsOuterRefs(tp.tp2) + case _ => false tree match { case _: This | _: Ident => isOuterRef(tree.tpe) case nw: New => @@ -292,6 +296,9 @@ object ExplicitOuter { // newCls might get proxies for free variables. If current class is // properly contained in newCls, it needs an outer path to newCls access the // proxies and forward them to the new instance. + case app: TypeApply if app.symbol.isTypeTest => + // Type tests of singletons translate to `eq` tests with references, which might require outer pointers + containsOuterRefs(app.args.head.tpe) case _ => false } diff --git a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 2679fbeaf94d..894bbc433dca 100644 --- a/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -295,7 +295,7 @@ object TypeTestsCasts { derivedTree(expr, defn.Any_asInstanceOf, testType) } - /** Transform isInstanceOf OrType + /** Transform isInstanceOf * * expr.isInstanceOf[A | B] ~~> expr.isInstanceOf[A] | expr.isInstanceOf[B] * expr.isInstanceOf[A & B] ~~> expr.isInstanceOf[A] & expr.isInstanceOf[B] diff --git a/tests/pos/i12616.scala b/tests/pos/i12616.scala new file mode 100644 index 000000000000..ff5a6bf204fd --- /dev/null +++ b/tests/pos/i12616.scala @@ -0,0 +1,9 @@ +class Foo: + + //object Bar + val Bar = 22 + + object Baz: + def f(x: Any): Unit = + x match + case s: (Bar.type & x.type) => \ No newline at end of file