summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semexprs.nim27
-rw-r--r--compiler/sigmatch.nim35
-rw-r--r--tests/concepts/tstackconcept.nim19
3 files changed, 65 insertions, 16 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index a14bc6c79..b3fe83ed8 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -912,11 +912,14 @@ const
   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 in {tyGenericInst, tyUserTypeClassInst}: typ.skipGenericAlias
            else: (internalAssert(typ.kind == tyCompositeTypeClass);
                   typ.sons[1].skipGenericAlias)
+
   let tbody = ty.sons[0]
   for s in countup(0, tbody.len-2):
     let tParam = tbody.sons[s]
@@ -927,7 +930,29 @@ proc readTypeParameter(c: PContext, typ: PType,
       else:
         let foundTyp = makeTypeDesc(c, rawTyp)
         return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
-  #echo "came here: returned nil"
+
+  if ty.n != nil:
+    for statement in ty.n:
+      case statement.kind
+      of nkTypeSection:
+        for def in statement:
+          if def[0].sym.name.id == paramName.id:
+            # XXX: Instead of lifting the section type to a typedesc
+            # here, we could try doing it earlier in semTypeSection.
+            # This seems semantically correct and then we'll be able
+            # to return the section symbol directly here
+            let foundType = makeTypeDesc(c, def[2].typ)
+            return newSymNode(copySym(def[2].sym).linkTo(foundType), info)
+
+      of nkConstSection:
+        for def in statement:
+          if def[0].sym.name.id == paramName.id:
+            return def[2]
+
+      else:
+        discard
+
+  return nil
 
 proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
   let s = getGenSym(c, sym)
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index f8004fa21..f819af13d 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -572,11 +572,11 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
     result = isNone
 
 proc matchUserTypeClass*(c: PContext, m: var TCandidate,
-                         ff, a: PType): TTypeRelation =
+                         ff, a: PType): PType =
   var body = ff.skipTypes({tyUserTypeClassInst})
   if c.inTypeClass > 4:
     localError(body.n[3].info, $body.n[3] & " too nested for type matching")
-    return isNone
+    return nil
 
   openScope(c)
   inc c.inTypeClass
@@ -636,7 +636,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
     #echo "B ", dummyName.ident.s, " ", typeToString(dummyType), " ", dummyparam.kind
 
   var checkedBody = c.semTryExpr(c, body.n[3].copyTree)
-  if checkedBody == nil: return isNone
+  if checkedBody == nil: return nil
 
   # The inferrable type params have been identified during the semTryExpr above.
   # We need to put them in the current sigmatch's binding table in order for them
@@ -644,7 +644,12 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
   for p in typeParams:
     put(m.bindings, p[1], p[0].typ)
 
-  return isGeneric
+  if ff.kind == tyUserTypeClassInst:
+    result = generateTypeInstance(c, m.bindings, m.call.info, ff)
+  else:
+    result = copyType(ff, ff.owner, true)
+
+  result.n = checkedBody
 
 proc shouldSkipDistinct(rules: PNode, callIdent: PIdent): bool =
   if rules.kind == nkWith:
@@ -1130,17 +1135,23 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
 
   of tyUserTypeClass:
     considerPreviousT:
-      result = matchUserTypeClass(c.c, c, f, aOrig)
-      if result == isGeneric:
+      var matched = matchUserTypeClass(c.c, c, f, aOrig)
+      if matched != nil:
+        # TODO, make user type classes skipable too
         put(c, f, a)
+        result = isGeneric
+      else:
+        result = isNone
 
   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)
+      var matched = matchUserTypeClass(c.c, c, f, aOrig)
+      if matched != nil:
+        matched.sons.add a
+        put(c.bindings, f, matched)
+        result = isGeneric
+      else:
+        result = isNone
 
   of tyCompositeTypeClass:
     considerPreviousT:
@@ -1408,7 +1419,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/tests/concepts/tstackconcept.nim b/tests/concepts/tstackconcept.nim
index dc75df5ff..11d6505cf 100644
--- a/tests/concepts/tstackconcept.nim
+++ b/tests/concepts/tstackconcept.nim
@@ -2,11 +2,15 @@ discard """
 output: "20\n10"
 msg: '''
 INFERRED int
+VALUE TYPE int
+VALUE TYPE NAME INT
 IMPLICIT INFERRED int int
+IMPLICIT VALUE TYPE int int
+IMPLICIT VALUE TYPE NAME INT INT
 '''
 """
 
-import typetraits
+import typetraits, strutils
 
 template reject(e: expr) =
   static: assert(not compiles(e))
@@ -26,14 +30,23 @@ type
     s.push(T)
     s.pop() is T
 
+    type ValueType = T
+    const ValueTypeName = T.name.toUpper
+
 proc genericAlgorithm[T](s: var Stack[T], y: T) =
-  static: echo "INFERRED ", T.name
+  static:
+    echo "INFERRED ", T.name
+    echo "VALUE TYPE ", s.ValueType.name
+    echo "VALUE TYPE NAME ", s.ValueTypeName
 
   s.push(y)
   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
+    echo "IMPLICIT VALUE TYPE ", s.ValueType.name, " ", Stack.ValueType.name
+    echo "IMPLICIT VALUE TYPE NAME ", s.ValueTypeName, " ", s.ValueTypeName
 
   return s.pop()