Skip to content

Commit e2f9fb0

Browse files
committed
New spec and implementation for matching.
Reformulated matchign spec and implemented accordingly. Previous fix for #329 would have missed third new error case in over.scala.
1 parent 79d782d commit e2f9fb0

File tree

5 files changed

+37
-36
lines changed

5 files changed

+37
-36
lines changed

src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -644,45 +644,34 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
644644
// Tests around `matches`
645645

646646
/** A function implementing `tp1` matches `tp2`. */
647-
final def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = tp1 match {
647+
final def matchesType(tp1: Type, tp2: Type, relaxed: Boolean): Boolean = tp1.widen match {
648648
case tp1: MethodType =>
649-
tp2 match {
649+
tp2.widen match {
650650
case tp2: MethodType =>
651651
tp1.isImplicit == tp2.isImplicit &&
652652
matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
653-
matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), alwaysMatchSimple)
654-
case tp2: ExprType =>
655-
tp1.paramNames.isEmpty &&
656-
matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple)
657-
case _ =>
658-
false
659-
}
660-
case tp1: ExprType =>
661-
tp2 match {
662-
case tp2: MethodType =>
663-
tp2.paramNames.isEmpty &&
664-
matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple)
665-
case tp2: ExprType =>
666-
matchesType(tp1.resultType, tp2.resultType, alwaysMatchSimple)
667-
case _ =>
668-
false // was: matchesType(tp1.resultType, tp2, alwaysMatchSimple)
653+
matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed)
654+
case tp2 =>
655+
relaxed && tp1.paramNames.isEmpty &&
656+
matchesType(tp1.resultType, tp2, relaxed)
669657
}
670658
case tp1: PolyType =>
671-
tp2 match {
659+
tp2.widen match {
672660
case tp2: PolyType =>
673661
sameLength(tp1.paramNames, tp2.paramNames) &&
674-
matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), alwaysMatchSimple)
662+
matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed)
675663
case _ =>
676664
false
677665
}
678666
case _ =>
679-
tp2 match {
680-
case _: MethodType | _: PolyType =>
667+
tp2.widen match {
668+
case _: PolyType =>
681669
false
682-
case tp2: ExprType =>
683-
false // was: matchesType(tp1, tp2.resultType, alwaysMatchSimple)
684-
case _ =>
685-
alwaysMatchSimple || isSameType(tp1, tp2)
670+
case tp2: MethodType =>
671+
relaxed && tp2.paramNames.isEmpty &&
672+
matchesType(tp1, tp2.resultType, relaxed)
673+
case tp2 =>
674+
relaxed || isSameType(tp1, tp2)
686675
}
687676
}
688677

src/dotty/tools/dotc/core/Types.scala

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -593,22 +593,26 @@ object Types {
593593
}
594594

595595
/** Is this type close enough to that type so that members
596-
* with the two type would override each other?d
596+
* with the two type would override each other?
597597
* This means:
598598
* - Either both types are polytypes with the same number of
599599
* type parameters and their result types match after renaming
600600
* corresponding type parameters
601-
* - Or both types are (possibly nullary) method types with equivalent parameter types
602-
* and matching result types
603-
* - Or both types are equivalent
604-
* - Or phase.erasedTypes is false and both types are neither method nor
605-
* poly types.
601+
* - Or both types are method types with =:=-equivalent(*) parameter types
602+
* and matching result types after renaming corresponding parameter types
603+
* if the method types are dependent.
604+
* - Or both types are =:=-equivalent
605+
* - Or phase.erasedTypes is false, and neither type takes
606+
* term or type parameters.
607+
*
608+
* (*) when matching with a Java method, we also regard Any and Object as equivalent
609+
* parameter types.
606610
*/
607611
def matches(that: Type)(implicit ctx: Context): Boolean =
608612
if (Config.newMatch) this.signature matches that.signature
609613
else track("matches") {
610614
ctx.typeComparer.matchesType(
611-
this, that, alwaysMatchSimple = !ctx.phase.erasedTypes)
615+
this, that, relaxed = !ctx.phase.erasedTypes)
612616
}
613617

614618
/** This is the same as `matches` except that it also matches => T with T and

src/dotty/tools/dotc/transform/OverridingPairs.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ object OverridingPairs {
4242
sym1.isType || {
4343
val info1 = self.memberInfo(sym1)
4444
val info2 = self.memberInfo(sym2)
45-
// info1.signature == info2.signature && // TODO enable for speed
46-
info1.widenExpr matches info2.widenExpr
45+
info1.signature.sameParams(info2.signature) &&
46+
info1.matches(info2)
4747
}
4848

4949
/** The symbols that can take part in an overriding pair */

test/dotc/tests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class tests extends CompilerTest {
8282
@Test def neg_autoTupling = compileFile(posDir, "autoTuplingTest", "-language:noAutoTupling" :: Nil, xerrors = 4)
8383
@Test def neg_autoTupling2 = compileFile(negDir, "autoTuplingTest", xerrors = 4)
8484
@Test def neg_companions = compileFile(negDir, "companions", xerrors = 1)
85-
@Test def neg_over = compileFile(negDir, "over", xerrors = 2)
85+
@Test def neg_over = compileFile(negDir, "over", xerrors = 3)
8686
@Test def neg_overrides = compileFile(negDir, "overrides", xerrors = 9)
8787
@Test def neg_projections = compileFile(negDir, "projections", xerrors = 1)
8888
@Test def neg_i39 = compileFile(negDir, "i39", xerrors = 1)

tests/neg/over.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,11 @@ class C extends T {
88
override val y = 2
99

1010
}
11+
12+
class D extends T {
13+
14+
def x(): String = ""
15+
16+
}
17+
18+

0 commit comments

Comments
 (0)