From 66bdfb80a94e11a4d26ad2fb99a60f3ddb673f9f Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 3 Sep 2022 22:05:40 +0200 Subject: [PATCH] Fix isSubType for static objects filling in type projections Fixes #15931 --- .../dotty/tools/dotc/core/TypeComparer.scala | 3 +-- .../src/dotty/tools/dotc/core/Types.scala | 6 +++-- .../tools/dotc/transform/TreeChecker.scala | 2 +- tests/pos/i15931.scala | 24 +++++++++++++++++++ tests/{neg => pos}/i8338.scala | 0 5 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 tests/pos/i15931.scala rename tests/{neg => pos}/i8338.scala (100%) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 78fbea352bf3..2454133dc05a 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -311,8 +311,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling thirdTryNamed(tp2) else ( (tp1.name eq tp2.name) - && tp1.isMemberRef - && tp2.isMemberRef + && tp2.isPrefixDependentMemberRef && isSubPrefix(tp1.prefix, tp2.prefix) && tp1.signature == tp2.signature && !(sym1.isClass && sym2.isClass) // class types don't subtype each other diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 0df3fa368d5a..92408ed28e76 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2496,8 +2496,10 @@ object Types { symd.maybeOwner.membersNeedAsSeenFrom(prefix) && !symd.is(NonMember) || prefix.isInstanceOf[Types.ThisType] && symd.is(Opaque) // see pos/i11277.scala for a test where this matters - /** Is this a reference to a class or object member? */ - def isMemberRef(using Context): Boolean = designator match { + /** Is this a reference to a class or object member with an info that might depend + * on the prefix? + */ + def isPrefixDependentMemberRef(using Context): Boolean = designator match { case sym: Symbol => infoDependsOnPrefix(sym, prefix) case _ => true } diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index 5791d0c7d119..d1cd4e8729a2 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -385,7 +385,7 @@ class TreeChecker extends Phase with SymTransformer { val sym = tree.symbol val symIsFixed = tpe match { - case tpe: TermRef => ctx.erasedTypes || !tpe.isMemberRef + case tpe: TermRef => ctx.erasedTypes || !tpe.isPrefixDependentMemberRef case _ => false } if (sym.exists && !sym.is(Private) && diff --git a/tests/pos/i15931.scala b/tests/pos/i15931.scala new file mode 100644 index 000000000000..cd57094576eb --- /dev/null +++ b/tests/pos/i15931.scala @@ -0,0 +1,24 @@ +sealed trait TP: + type C + type P + +final class Foo extends TP: + class C + enum P: + case A, B + +object Bar extends TP: + class C + enum P: + case A, B, C + +// Works +def test = + summon[Foo#P <:< TP#P] + val a: TP#P = Foo().P.A + + // These fail + val b: TP#P = Bar.P.A: Bar.P + summon[Bar.type#P <:< TP#P] + summon[Bar.P <:< TP#P] + val c: TP#C = ??? : Bar.C diff --git a/tests/neg/i8338.scala b/tests/pos/i8338.scala similarity index 100% rename from tests/neg/i8338.scala rename to tests/pos/i8338.scala