summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2016-07-31 02:13:32 +0300
committerZahary Karadjov <zahary@gmail.com>2017-03-24 16:58:15 +0200
commit0a9a878bd34c9e38eeee36180ce171f54423b45c (patch)
tree53c22dbd42af23fa464ff31fd00dcbaf37fba0ee /compiler
parent33f4e69759820021f6b5089fe3798233b2a1fb13 (diff)
downloadNim-0a9a878bd34c9e38eeee36180ce171f54423b45c.tar.gz
support for matching generic types' procs in generic concepts
Diffstat (limited to 'compiler')
-rw-r--r--compiler/semexprs.nim4
-rw-r--r--compiler/semstmts.nim6
-rw-r--r--compiler/sigmatch.nim42
3 files changed, 42 insertions, 10 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index b3fe83ed8..d81abe20e 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -319,11 +319,11 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
       result = newIntNode(nkIntLit, 0)
   else:
     var rhsOrigType = n[2].typ
-    discard inferTypeClassParam(c, t1, rhsOrigType)
     var t2 = rhsOrigType.skipTypes({tyTypeDesc})
     maybeLiftType(t2, c, n.info)
     var m: TCandidate
     initCandidate(c, m, t2)
+    discard inferTypeClassParam(m, t1, rhsOrigType)
     let match = typeRel(m, t2, t1) >= isSubtype # isNone
     result = newIntNode(nkIntLit, ord(match))
 
@@ -912,8 +912,6 @@ 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
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 9a1850932..33b684e91 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1631,8 +1631,12 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
           of nkPragma, nkCommentStmt, nkNilLit, nkEmpty: discard
           else: localError(n.sons[j].info, errStmtInvalidAfterReturn)
       else: discard
-  if result.len == 1 and result.sons[0].kind != nkDefer:
+  
+  if result.len == 1 and
+     c.inTypeClass == 0 and # concept bodies should be preserved as a stmt list
+     result.sons[0].kind != nkDefer:
     result = result.sons[0]
+
   when defined(nimfix):
     if result.kind == nkCommentStmt and not result.comment.isNil and
         not (result.comment[0] == '#' and result.comment[1] == '#'):
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index f819af13d..3dede8b6f 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -645,7 +645,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
     put(m.bindings, p[1], p[0].typ)
 
   if ff.kind == tyUserTypeClassInst:
-    result = generateTypeInstance(c, m.bindings, m.call.info, ff)
+    result = generateTypeInstance(c, m.bindings, ff.sym.info, ff)
   else:
     result = copyType(ff, ff.owner, true)
 
@@ -1403,13 +1403,34 @@ proc skipToInferrableParam(tt: PType): PType =
 
   return nil
 
-proc inferTypeClassParam*(c: PContext, f, a: PType): bool =
+proc inferTypeClassParam*(m: var TCandidate, f, a: PType): bool =
+  var c = m.c
   if c.inTypeClass == 0: return false
 
   var inferrableType = a.skipToInferrableParam
   if inferrableType == nil: return false
 
-  inferrableType.assignType f
+  var inferAs = f
+  
+  case f.kind
+  of tyGenericParam:
+    var prev  = PType(idTableGet(m.bindings, f))
+    if prev != nil: inferAs = prev
+  
+  of tyFromExpr:
+    let computedType = tryResolvingStaticExpr(m, f.n).typ
+    case computedType.kind
+    of tyTypeDesc:
+      inferAs = computedType.base
+    of tyStatic:
+      inferAs = computedType
+    else:
+      localError(f.n.info, errTypeExpected)
+  
+  else:
+    discard
+    
+  inferrableType.assignType inferAs
   return true
 
 proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
@@ -1420,7 +1441,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
     argType = argType
     c = m.c
 
-  if inferTypeClassParam(c, f, argType):
+  if inferTypeClassParam(m, f, argType):
     return argSemantized
 
   if tfHasStatic in fMaybeStatic.flags:
@@ -1448,9 +1469,18 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
         arg.typ.n = evaluated
         argType = arg.typ
 
-  var a = argType
-  var r = typeRel(m, f, a)
+  var
+    useTypeLoweringRuleInTypeClass = c.inTypeClass > 0 and
+                                     not m.isNoCall and
+                                     f.kind != tyTypeDesc
 
+    a = if useTypeLoweringRuleInTypeClass:
+          argType.skipTypes({tyTypeDesc, tyFieldAccessor})
+        else:
+          argType
+    
+    r = typeRel(m, f, a)
+  
   if r != isNone and m.calleeSym != nil and
      m.calleeSym.kind in {skMacro, skTemplate}:
     # XXX: duplicating this is ugly, but we cannot (!) move this