diff options
author | Zahary Karadjov <zahary@gmail.com> | 2016-07-31 02:13:32 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2017-03-24 16:58:15 +0200 |
commit | 0a9a878bd34c9e38eeee36180ce171f54423b45c (patch) | |
tree | 53c22dbd42af23fa464ff31fd00dcbaf37fba0ee /compiler | |
parent | 33f4e69759820021f6b5089fe3798233b2a1fb13 (diff) | |
download | Nim-0a9a878bd34c9e38eeee36180ce171f54423b45c.tar.gz |
support for matching generic types' procs in generic concepts
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/semexprs.nim | 4 | ||||
-rw-r--r-- | compiler/semstmts.nim | 6 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 42 |
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 |