diff options
-rw-r--r-- | compiler/semtypes.nim | 5 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 18 | ||||
-rw-r--r-- | tests/concepts/tmisc_issues.nim | 2 | ||||
-rw-r--r-- | tests/generics/tbindoncevsbindmany.nim | 68 |
4 files changed, 82 insertions, 11 deletions
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 8efd2f943..16066da91 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -904,8 +904,9 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, allowMetaTypes = true) result = liftingWalk(expanded, true) - of tyUserTypeClasses, tyBuiltInTypeClass, tyAnd, tyOr, tyNot: - result = addImplicitGeneric(copyType(paramType, getCurrOwner(c), true)) + of tyUserTypeClasses, tyBuiltInTypeClass, tyCompositeTypeClass, + tyAnd, tyOr, tyNot: + result = addImplicitGeneric(copyType(paramType, getCurrOwner(c), false)) of tyGenericParam: markUsed(info, paramType.sym, c.graph.usageSym) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 43a939007..49478f5a7 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1383,13 +1383,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = if f.isResolvedUserTypeClass: result = typeRel(c, f.lastSon, a) else: - var matched = matchUserTypeClass(c.c, c, f, aOrig) - if matched != nil: - bindConcreteTypeToUserTypeClass(matched, a) - put(c, f, matched) - result = isGeneric - else: - result = isNone + considerPreviousT: + var matched = matchUserTypeClass(c.c, c, f, aOrig) + if matched != nil: + bindConcreteTypeToUserTypeClass(matched, a) + if doBind: put(c, f, matched) + result = isGeneric + else: + result = isNone of tyCompositeTypeClass: considerPreviousT: @@ -1407,6 +1408,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = if result != isNone: put(c, f, a) result = isGeneric + of tyGenericParam: var x = PType(idTableGet(c.bindings, f)) if x == nil: @@ -1436,7 +1438,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = result = isNone else: if f.sonsLen > 0 and f.sons[0].kind != tyNone: - result = typeRel(c, f.lastSon, a) + result = typeRel(c, f.lastSon, a, false) if doBind and result notin {isNone, isGeneric}: let concrete = concreteType(c, a) if concrete == nil: return isNone diff --git a/tests/concepts/tmisc_issues.nim b/tests/concepts/tmisc_issues.nim index 10e072521..d9bb84a2f 100644 --- a/tests/concepts/tmisc_issues.nim +++ b/tests/concepts/tmisc_issues.nim @@ -42,7 +42,7 @@ echo p2 is AbstractPointOfFloat # true echo p2.x is float and p2.y is float # true # https://github.com/nim-lang/Nim/issues/2018 -type ProtocolFollower = generic +type ProtocolFollower = concept true # not a particularly involved protocol type ImplementorA = object diff --git a/tests/generics/tbindoncevsbindmany.nim b/tests/generics/tbindoncevsbindmany.nim new file mode 100644 index 000000000..01e801f0e --- /dev/null +++ b/tests/generics/tbindoncevsbindmany.nim @@ -0,0 +1,68 @@ +template accept(x) = + static: assert(compiles(x)) + +template reject(x) = + static: assert(not compiles(x)) + +type + ObjectWithNumber = concept obj + obj.number is int + + Foo[T] = object + x: T + +type A = object + anumber: int + +type B = object + bnumber: int + +proc number(a: A): int = a.anumber +proc number(b: B): int = b.bnumber + +proc notDistincConcept1(a: ObjectWithNumber, b: ObjectWithNumber) = discard +proc notDistincConcept2(a, b: ObjectWithNumber) = discard +proc distinctConcept1(a, b: distinct ObjectWithNumber) = discard +proc distinctConcept2(a: ObjectWithNumber, b: distinct ObjectWithNumber) = discard +proc distinctConcept3(a: distinct ObjectWithNumber, b: ObjectWithNumber) = discard +proc distinctConcept4(a: distinct ObjectWithNumber, b: distinct ObjectWithNumber) = discard + +var a = A(anumber: 5) +var b = B(bnumber: 6) + +accept notDistincConcept1(a, a) +accept notDistincConcept1(b, b) +reject notDistincConcept2(a, b) + +accept notDistincConcept2(a, a) +accept notDistincConcept2(b, b) +reject notDistincConcept2(a, b) + +accept distinctConcept1(a, b) +accept distinctConcept2(a, b) +accept distinctConcept3(a, b) +accept distinctConcept4(a, b) + +proc nonDistincGeneric1(a: Foo, b: Foo) = discard +proc nonDistincGeneric2(a, b: Foo) = discard +proc distinctGeneric1(a, b: distinct Foo) = discard +proc distinctGeneric2(a: distinct Foo, b: Foo) = discard +proc distinctGeneric3(a: Foo, b: distinct Foo) = discard +proc distinctGeneric4(a: distinct Foo, b: distinct Foo) = discard + +var f1 = Foo[int](x: 10) +var f2 = Foo[string](x: "x") + +accept nonDistincGeneric1(f1, f1) +accept nonDistincGeneric1(f2, f2) +reject nonDistincGeneric1(f1, f2) + +accept nonDistincGeneric2(f1, f1) +accept nonDistincGeneric2(f2, f2) +reject nonDistincGeneric2(f1, f2) + +accept distinctGeneric1(f1, f1) +accept distinctGeneric2(f1, f1) +accept distinctGeneric3(f1, f1) +accept distinctGeneric4(f1, f1) + |