diff options
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 41 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 16 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/OverridingPairs.scala | 4 | ||||
-rw-r--r-- | test/dotc/tests.scala | 2 | ||||
-rw-r--r-- | tests/neg/over.scala | 8 |
5 files changed, 36 insertions, 35 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index b40baafdf..1687d6159 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -648,45 +648,34 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi // Tests around `matches` /** A function implementing `tp1` matches `tp2`. */ - final def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = tp1 match { + final def matchesType(tp1: Type, tp2: Type, relaxed: Boolean): Boolean = tp1.widen match { case tp1: MethodType => - tp2 match { + tp2.widen match { case tp2: MethodType => tp1.isImplicit == tp2.isImplicit && matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) && - matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), alwaysMatchSimple) - case tp2: ExprType => - tp1.paramNames.isEmpty && - matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple) - case _ => - false - } - case tp1: ExprType => - tp2 match { - case tp2: MethodType => - tp2.paramNames.isEmpty && - matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple) - case tp2: ExprType => - matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple) - case _ => - false // was: matchesType(tp1.resultType, tp2, alwaysMatchSimple) + matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed) + case tp2 => + relaxed && tp1.paramNames.isEmpty && + matchesType(tp1.resultType, tp2, relaxed) } case tp1: PolyType => - tp2 match { + tp2.widen match { case tp2: PolyType => sameLength(tp1.paramNames, tp2.paramNames) && - matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), alwaysMatchSimple) + matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed) case _ => false } case _ => - tp2 match { - case _: MethodType | _: PolyType => + tp2.widen match { + case _: PolyType => false - case tp2: ExprType => - false // was: matchesType(tp1, tp2.resultType, alwaysMatchSimple) - case _ => - alwaysMatchSimple || isSameType(tp1, tp2) + case tp2: MethodType => + relaxed && tp2.paramNames.isEmpty && + matchesType(tp1, tp2.resultType, relaxed) + case tp2 => + relaxed || isSameType(tp1, tp2) } } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 6c87d44e6..e759c3ad3 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -598,17 +598,21 @@ object Types { * - Either both types are polytypes with the same number of * type parameters and their result types match after renaming * corresponding type parameters - * - Or both types are (possibly nullary) method types with equivalent parameter types - * and matching result types - * - Or both types are equivalent - * - Or phase.erasedTypes is false and both types are neither method nor - * poly types. + * - Or both types are method types with =:=-equivalent(*) parameter types + * and matching result types after renaming corresponding parameter types + * if the method types are dependent. + * - Or both types are =:=-equivalent + * - Or phase.erasedTypes is false, and neither type takes + * term or type parameters. + * + * (*) when matching with a Java method, we also regard Any and Object as equivalent + * parameter types. */ def matches(that: Type)(implicit ctx: Context): Boolean = if (Config.newMatch) this.signature matches that.signature else track("matches") { ctx.typeComparer.matchesType( - this, that, alwaysMatchSimple = !ctx.phase.erasedTypes) + this, that, relaxed = !ctx.phase.erasedTypes) } /** This is the same as `matches` except that it also matches => T with T and diff --git a/src/dotty/tools/dotc/transform/OverridingPairs.scala b/src/dotty/tools/dotc/transform/OverridingPairs.scala index 4026749b2..bad763f41 100644 --- a/src/dotty/tools/dotc/transform/OverridingPairs.scala +++ b/src/dotty/tools/dotc/transform/OverridingPairs.scala @@ -42,8 +42,8 @@ object OverridingPairs { sym1.isType || { val info1 = self.memberInfo(sym1) val info2 = self.memberInfo(sym2) - // info1.signature == info2.signature && // TODO enable for speed - info1.widenExpr matches info2.widenExpr + info1.signature.sameParams(info2.signature) && + info1.matches(info2) } /** The symbols that can take part in an overriding pair */ diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 27c4c6cd0..4c617c035 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -82,7 +82,7 @@ class tests extends CompilerTest { @Test def neg_autoTupling = compileFile(posDir, "autoTuplingTest", "-language:noAutoTupling" :: Nil, xerrors = 4) @Test def neg_autoTupling2 = compileFile(negDir, "autoTuplingTest", xerrors = 4) @Test def neg_companions = compileFile(negDir, "companions", xerrors = 1) - @Test def neg_over = compileFile(negDir, "over", xerrors = 2) + @Test def neg_over = compileFile(negDir, "over", xerrors = 3) @Test def neg_overrides = compileFile(negDir, "overrides", xerrors = 9) @Test def neg_projections = compileFile(negDir, "projections", xerrors = 1) @Test def neg_i39 = compileFile(negDir, "i39", xerrors = 1) diff --git a/tests/neg/over.scala b/tests/neg/over.scala index 488d71614..80ce7d09f 100644 --- a/tests/neg/over.scala +++ b/tests/neg/over.scala @@ -8,3 +8,11 @@ class C extends T { override val y = 2 } + +class D extends T { + + def x(): String = "" + +} + + |