summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semtypes.nim5
-rw-r--r--compiler/sigmatch.nim18
-rw-r--r--tests/concepts/tmisc_issues.nim2
-rw-r--r--tests/generics/tbindoncevsbindmany.nim68
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)
+