diff options
-rw-r--r-- | changelog.md | 2 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 24 | ||||
-rw-r--r-- | tests/overload/tprefer_tygenericinst.nim | 25 |
3 files changed, 36 insertions, 15 deletions
diff --git a/changelog.md b/changelog.md index 758bc6a4e..640cb98c5 100644 --- a/changelog.md +++ b/changelog.md @@ -14,3 +14,5 @@ `getBool`, `getFloat`, `getBiggestInt`. Also `getInt` procedure was added. - `reExtended` is no longer default for the `re` constructor in the `re` module. +- The overloading rules changed slightly so that constrained generics are + preferred over unconstrained generics. (Bug #6526) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index b4e79e7e9..09d8ea292 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1452,8 +1452,13 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, of tyOr: considerPreviousT: result = isNone + let oldInheritancePenalty = c.inheritancePenalty + var maxInheritance = 0 for branch in f.sons: + c.inheritancePenalty = 0 let x = typeRel(c, branch, aOrig) + maxInheritance = max(maxInheritance, c.inheritancePenalty) + # 'or' implies maximum matching result: if x > result: result = x if result >= isSubtype: @@ -1461,6 +1466,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, bindingRet result else: result = isNone + c.inheritancePenalty = oldInheritancePenalty + maxInheritance of tyNot: considerPreviousT: @@ -1551,21 +1557,19 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, result = isNone else: if f.sonsLen > 0 and f.sons[0].kind != tyNone: - when false: - let oldInheritancePenalty = c.inheritancePenalty + let oldInheritancePenalty = c.inheritancePenalty result = typeRel(c, f.lastSon, a, flags + {trDontBind}) if doBind and result notin {isNone, isGeneric}: let concrete = concreteType(c, a) if concrete == nil: return isNone put(c, f, concrete) - when false: - # bug #6526 - if result in {isEqual, isSubtype}: - # 'T: Class' is a *better* match than just 'T' - # but 'T: Subclass' is even better: - c.inheritancePenalty = oldInheritancePenalty - c.inheritancePenalty - - 100 * ord(result == isEqual) - result = isGeneric + # bug #6526 + if result in {isEqual, isSubtype}: + # 'T: Class' is a *better* match than just 'T' + # but 'T: Subclass' is even better: + c.inheritancePenalty = oldInheritancePenalty - c.inheritancePenalty - + 100 * ord(result == isEqual) + result = isGeneric else: result = isGeneric diff --git a/tests/overload/tprefer_tygenericinst.nim b/tests/overload/tprefer_tygenericinst.nim index 56541c7e8..72f5a94fd 100644 --- a/tests/overload/tprefer_tygenericinst.nim +++ b/tests/overload/tprefer_tygenericinst.nim @@ -2,7 +2,9 @@ discard """ output: '''Version 2 was called. This has the highest precedence. This has the second-highest precedence. -This has the lowest precedence.''' +This has the lowest precedence. +baseobj == +true''' """ # bug #2220 @@ -26,13 +28,13 @@ template testPred(a: untyped) = type SomeA = A|A # A hack to make "A" a typeclass. when a >= 3: - proc p[X](x: X) = - echo "This has the highest precedence." - when a >= 2: proc p[X: A](x: X) = + echo "This has the highest precedence." + when a == 2: + proc p[X: SomeA](x: X) = echo "This has the second-highest precedence." when a >= 1: - proc p[X: SomeA](x: X) = + proc p[X](x: X) = echo "This has the lowest precedence." p(B()) @@ -40,3 +42,16 @@ template testPred(a: untyped) = testPred(3) testPred(2) testPred(1) + +# bug #6526 +type + BaseObj = ref object of RootObj + DerivedObj = ref object of BaseObj + +proc `==`*[T1, T2: BaseObj](a: T1, b: T2): bool = + echo "baseobj ==" + return true + +let a = DerivedObj() +let b = DerivedObj() +echo a == b |