summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semtypes.nim2
-rw-r--r--compiler/sigmatch.nim9
-rw-r--r--compiler/types.nim9
-rw-r--r--tests/errmsgs/tconceptconstraint.nim21
-rw-r--r--tests/errmsgs/tgenericconstraint.nim15
5 files changed, 51 insertions, 5 deletions
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index c0974022a..4c7786f61 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1131,7 +1131,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     m.isNoCall = true
     matches(c, n, copyTree(n), m)
 
-    if m.state != csMatch and not m.typedescMatched:
+    if m.state != csMatch:
       let err = "cannot instantiate " & typeToString(t) & "\n" &
                 "got: (" & describeArgs(c, n) & ")\n" &
                 "but expected: (" & describeArgs(c, t.n, 0) & ")"
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 7a603a2d4..59add90a2 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -307,12 +307,13 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
 proc typeRelImpl*(c: var TCandidate, f, aOrig: PType,
                   flags: TTypeRelFlags = {}): TTypeRelation
 
-var nextTypeRel = 0
+const traceTypeRel = false
+
+when traceTypeRel:
+  var nextTypeRel = 0
 
 template typeRel*(c: var TCandidate, f, aOrig: PType,
                  flags: TTypeRelFlags = {}): TTypeRelation =
-  const traceTypeRel = false
-
   when traceTypeRel:
     var enteringAt = nextTypeRel
     if mdbg:
@@ -320,6 +321,7 @@ template typeRel*(c: var TCandidate, f, aOrig: PType,
       echo "----- TYPE REL ", enteringAt
       debug f
       debug aOrig
+      # writeStackTrace()
 
   let r = typeRelImpl(c, f, aOrig, flags)
 
@@ -1487,6 +1489,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
       result = typeRel(c, f.lastSon, a)
     else:
       considerPreviousT:
+        if aOrig == f: return isEqual
         var matched = matchUserTypeClass(c.c, c, f, aOrig)
         if matched != nil:
           bindConcreteTypeToUserTypeClass(matched, a)
diff --git a/compiler/types.nim b/compiler/types.nim
index 13b24ccf8..2b4ba12d1 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -440,6 +440,13 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
       result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
     elif prefer == preferName or t.sym.owner.isNil:
       result = t.sym.name.s
+      if t.kind == tyGenericParam and t.sons != nil and t.sonsLen > 0:
+        result.add ": "
+        var first = true
+        for son in t.sons:
+          if not first: result.add " or "
+          result.add son.typeToString
+          first = false
     else:
       result = t.sym.owner.name.s & '.' & t.sym.name.s
     result.addTypeFlags(t)
@@ -461,7 +468,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     add(result, ']')
   of tyTypeDesc:
     if t.sons[0].kind == tyNone: result = "typedesc"
-    else: result = "typedesc[" & typeToString(t.sons[0]) & "]"
+    else: result = "type " & typeToString(t.sons[0])
   of tyStatic:
     internalAssert t.len > 0
     if prefer == preferGenericArg and t.n != nil:
diff --git a/tests/errmsgs/tconceptconstraint.nim b/tests/errmsgs/tconceptconstraint.nim
new file mode 100644
index 000000000..c1f0b94eb
--- /dev/null
+++ b/tests/errmsgs/tconceptconstraint.nim
@@ -0,0 +1,21 @@
+discard """
+  errormsg: "cannot instantiate B"
+  line: 20
+  nimout: '''
+got: (type string)
+but expected: (T: A)
+'''
+"""
+
+type
+  A = concept c
+    advance(c)
+  
+  B[T: A] = object
+    child: ref B[T]
+
+proc advance(x: int): int = x + 1
+
+var a: B[int]
+var b: B[string]
+
diff --git a/tests/errmsgs/tgenericconstraint.nim b/tests/errmsgs/tgenericconstraint.nim
new file mode 100644
index 000000000..9129d257b
--- /dev/null
+++ b/tests/errmsgs/tgenericconstraint.nim
@@ -0,0 +1,15 @@
+discard """
+  errormsg: "cannot instantiate B"
+  line: 14
+  nimout: '''
+got: (type int)
+but expected: (T: string or float)
+'''
+"""
+
+type
+  B[T: string|float] = object
+    child: ref B[T]
+
+var b: B[int]
+