summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgutils.nim2
-rw-r--r--compiler/semexprs.nim4
-rw-r--r--compiler/semtypinst.nim2
-rw-r--r--compiler/sigmatch.nim17
-rw-r--r--compiler/types.nim3
-rw-r--r--tests/concepts/tstackconcept.nim3
6 files changed, 24 insertions, 7 deletions
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index ff8f768bd..afcf24167 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -101,6 +101,8 @@ proc getUniqueType*(key: PType): PType =
         gCanonicalTypes[k] = key
         result = key
     of tyTypeDesc, tyTypeClasses, tyGenericParam, tyFromExpr, tyFieldAccessor:
+      if key.isResolvedUserTypeClass:
+        return getUniqueType(lastSon(key))
       if key.sym != nil:
         internalError(key.sym.info, "metatype not eliminated")
       else:
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index cb16bf406..a14bc6c79 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -909,12 +909,12 @@ proc makeDeref(n: PNode): PNode =
     t = skipTypes(baseTyp, {tyGenericInst, tyAlias})
 
 const
-  tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass}
+  tyTypeParamsHolders = {tyGenericInst, tyUserTypeClassInst, tyCompositeTypeClass}
   tyDotOpTransparent = {tyVar, tyPtr, tyRef, tyAlias}
 
 proc readTypeParameter(c: PContext, typ: PType,
                        paramName: PIdent, info: TLineInfo): PNode =
-  let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias
+  let ty = if typ.kind in {tyGenericInst, tyUserTypeClassInst}: typ.skipGenericAlias
            else: (internalAssert(typ.kind == tyCompositeTypeClass);
                   typ.sons[1].skipGenericAlias)
   let tbody = ty.sons[0]
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 75dffb67f..9a1ace42e 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -447,7 +447,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
   of tyUserTypeClass:
     result = t
 
-  of tyGenericInst:
+  of tyGenericInst, tyUserTypeClassInst:
     bailout()
     result = instCopyType(cl, t)
     idTablePut(cl.localCache, t, result)
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index b279e7d2d..f8004fa21 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -642,7 +642,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
   # We need to put them in the current sigmatch's binding table in order for them
   # to be resolvable while matching the rest of the parameters
   for p in typeParams:
-    put(m.bindings, p[0].typ, p[1])
+    put(m.bindings, p[1], p[0].typ)
 
   return isGeneric
 
@@ -716,6 +716,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         tyGenericInst, tyGenericParam} + tyTypeClasses:
     return typeRel(c, f, lastSon(a))
 
+  if a.isResolvedUserTypeClass:
+    return typeRel(c, f, a.lastSon)
+
   template bindingRet(res) =
     if doBind:
       let bound = aOrig.skipTypes({tyRange}).skipIntLit
@@ -1125,12 +1128,20 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       else:
         return isNone
 
-  of tyUserTypeClass, tyUserTypeClassInst:
+  of tyUserTypeClass:
     considerPreviousT:
       result = matchUserTypeClass(c.c, c, f, aOrig)
       if result == isGeneric:
         put(c, f, a)
 
+  of tyUserTypeClassInst:
+    considerPreviousT:
+      result = matchUserTypeClass(c.c, c, f, aOrig)
+      if result == isGeneric:
+        var fWithResolvedParams = generateTypeInstance(c.c, c.bindings, c.call.info, f)
+        fWithResolvedParams.sons.add a
+        put(c.bindings, f, fWithResolvedParams)
+
   of tyCompositeTypeClass:
     considerPreviousT:
       let roota = a.skipGenericAlias
@@ -1397,7 +1408,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
     arg = argSemantized
     argType = argType
     c = m.c
-
+ 
   if inferTypeClassParam(c, f, argType):
     return argSemantized
 
diff --git a/compiler/types.nim b/compiler/types.nim
index f4ef75094..285854aa0 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1485,6 +1485,9 @@ proc isEmptyContainer*(t: PType): bool =
   of tyGenericInst, tyAlias: result = isEmptyContainer(t.lastSon)
   else: result = false
 
+proc isResolvedUserTypeClass*(t: PType): bool =
+  t.kind in {tyUserTypeClassInst} and t.base.sonsLen == t.sonsLen - 2
+
 proc takeType*(formal, arg: PType): PType =
   # param: openArray[string] = []
   # [] is an array constructor of length 0 of type string!
diff --git a/tests/concepts/tstackconcept.nim b/tests/concepts/tstackconcept.nim
index 3993ca534..dc75df5ff 100644
--- a/tests/concepts/tstackconcept.nim
+++ b/tests/concepts/tstackconcept.nim
@@ -2,6 +2,7 @@ discard """
 output: "20\n10"
 msg: '''
 INFERRED int
+IMPLICIT INFERRED int int
 '''
 """
 
@@ -32,7 +33,7 @@ proc genericAlgorithm[T](s: var Stack[T], y: T) =
   echo s.pop
 
 proc implicitGeneric(s: var Stack): auto =
-  # static: echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name
+  static: echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name
 
   return s.pop()