From 64d151a0466522e8b5e0a887938d374dec2882fa Mon Sep 17 00:00:00 2001 From: Dale Wijnand <dale.wijnand@gmail.com> Date: Wed, 14 Jun 2023 18:20:26 +0100 Subject: [PATCH 1/2] Fix hasMatchingMember handling NoDenotation --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 2 +- tests/neg/i17581.check | 7 +++++++ tests/neg/i17581.scala | 9 +++++++++ tests/neg/i7812.scala | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 tests/neg/i17581.check create mode 100644 tests/neg/i17581.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index a0922c1f0574..264ff52d0af9 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -2021,7 +2021,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling || (tp1.isStable && isSubType(TermRef(tp1, m.symbol), tp2.refinedInfo)) tp1.member(name) match // inlined hasAltWith for performance - case mbr: SingleDenotation => qualifies(mbr) + case mbr: SingleDenotation => mbr.exists && qualifies(mbr) case mbr => mbr hasAltWith qualifies } diff --git a/tests/neg/i17581.check b/tests/neg/i17581.check new file mode 100644 index 000000000000..e21e9fd32019 --- /dev/null +++ b/tests/neg/i17581.check @@ -0,0 +1,7 @@ +-- [E007] Type Mismatch Error: tests/neg/i17581.scala:9:6 -------------------------------------------------------------- +9 | foo(test) // error // was NoSuchMethodException + | ^^^^ + | Found: (test : Test) + | Required: Object{def bar: Any} + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i17581.scala b/tests/neg/i17581.scala new file mode 100644 index 000000000000..1cd86a9d39cd --- /dev/null +++ b/tests/neg/i17581.scala @@ -0,0 +1,9 @@ +import scala.reflect.Selectable.reflectiveSelectable + +class Test + +def foo[A <: { def bar: Any }](ob: A) = ob.bar + +@main def main = + val test = new Test + foo(test) // error // was NoSuchMethodException diff --git a/tests/neg/i7812.scala b/tests/neg/i7812.scala index 264258fa4db3..9cbd58071bc8 100644 --- a/tests/neg/i7812.scala +++ b/tests/neg/i7812.scala @@ -1,3 +1,3 @@ def f(): Any = ??? var f: (UndefinedA & UndefinedB) { val x: Int } = ??? // error // error -val a = f // error \ No newline at end of file +val a = f From 4373d48d20c872a2a45514aa5e6878572fc5e179 Mon Sep 17 00:00:00 2001 From: Dale Wijnand <dale.wijnand@gmail.com> Date: Sat, 17 Jun 2023 11:36:55 +0100 Subject: [PATCH 2/2] Introduce hasAltWithInline, to fix all usages --- compiler/src/dotty/tools/dotc/core/Denotations.scala | 4 ++++ compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 4 +--- compiler/src/dotty/tools/dotc/typer/Applications.scala | 5 +---- compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala | 4 +--- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 82368fd4dbf5..a535048d2e73 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -261,6 +261,10 @@ object Denotations { /** Does this denotation have an alternative that satisfies the predicate `p`? */ def hasAltWith(p: SingleDenotation => Boolean): Boolean + inline final def hasAltWithInline(inline p: SingleDenotation => Boolean): Boolean = inline this match + case mbr: SingleDenotation => mbr.exists && p(mbr) + case mbr => mbr.hasAltWith(p) + /** The denotation made up from the alternatives of this denotation that * are accessible from prefix `pre`, or NoDenotation if no accessible alternative exists. */ diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 264ff52d0af9..6c7af839f008 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -2020,9 +2020,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling || matchAbstractTypeMember(m.info) || (tp1.isStable && isSubType(TermRef(tp1, m.symbol), tp2.refinedInfo)) - tp1.member(name) match // inlined hasAltWith for performance - case mbr: SingleDenotation => mbr.exists && qualifies(mbr) - case mbr => mbr hasAltWith qualifies + tp1.member(name).hasAltWithInline(qualifies) } final def ensureStableSingleton(tp: Type): SingletonType = tp.stripTypeVar match { diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 17b79ab0f801..08437a529a88 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1517,10 +1517,7 @@ trait Applications extends Compatibility { && isApplicableType( normalize(tp.select(xname, mbr), WildcardType), argType :: Nil, resultType) - tp.memberBasedOnFlags(xname, required = ExtensionMethod) match { - case mbr: SingleDenotation => qualifies(mbr) - case mbr => mbr.hasAltWith(qualifies(_)) - } + tp.memberBasedOnFlags(xname, required = ExtensionMethod).hasAltWithInline(qualifies) } /** Drop any leading type or implicit parameter sections */ diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 8b04ca8dd75b..ad07b0ebd7a5 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -212,9 +212,7 @@ object ProtoTypes { || tp1.isValueType && compat.normalizedCompatible(NamedType(tp1, name, m), memberProto, keepConstraint)) // Note: can't use `m.info` here because if `m` is a method, `m.info` // loses knowledge about `m`'s default arguments. - mbr match // hasAltWith inlined for performance - case mbr: SingleDenotation => mbr.exists && qualifies(mbr) - case _ => mbr hasAltWith qualifies + mbr.hasAltWithInline(qualifies) catch case ex: TypeError => // A scenario where this can happen is in pos/15673.scala: // We have a type `CC[A]#C` where `CC`'s upper bound is `[X] => Any`, but