diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2020-06-07 09:55:56 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-07 09:55:56 +0200 |
commit | 66c50c2ffcfdd31f9f1eecfaf23b1b58b22d3a36 (patch) | |
tree | 6b20a4fea12283ae5ec7f08004f7dc4bca3ba6e8 | |
parent | 51b71e35f2c0000def4f35d65ceb28ecdeb7ee10 (diff) | |
download | Nim-66c50c2ffcfdd31f9f1eecfaf23b1b58b22d3a36.tar.gz |
implement the 'bind' statement for generics, it was an oversight that this was never implemented (#14584)
-rw-r--r-- | compiler/semgnrc.nim | 15 | ||||
-rw-r--r-- | tests/lookups/tbind_for_generics.nim | 17 |
2 files changed, 28 insertions, 4 deletions
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 6fefc2233..23b6e9b9d 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -28,7 +28,7 @@ proc getIdentNode(c: PContext; n: PNode): PNode = type GenericCtx = object - toMixin: IntSet + toMixin, toBind: IntSet cursorInBody: bool # only for nimsuggest bracketExpr: PNode @@ -124,7 +124,7 @@ proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags, if ident.id notin ctx.toMixin and withinMixin notin flags: errorUndeclaredIdentifier(c, n.info, ident.s) else: - if withinBind in flags: + if withinBind in flags or s.id in ctx.toBind: result = symChoice(c, n, s, scClosed) elif s.isMixedIn: result = symChoice(c, n, s, scForceOpen) @@ -155,7 +155,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags, var s = searchInScopes(c, ident, routineKinds).skipAlias(n, c.config) if s != nil: isMacro = s.kind in {skTemplate, skMacro} - if withinBind in flags: + if withinBind in flags or s.id in ctx.toBind: result = newDot(result, symChoice(c, n, s, scClosed)) elif s.isMixedIn: result = newDot(result, symChoice(c, n, s, scForceOpen)) @@ -211,6 +211,8 @@ proc semGenericStmt(c: PContext, n: PNode, result = semGenericStmt(c, n[0], flags+{withinBind}, ctx) of nkMixinStmt: result = semMixinStmt(c, n, ctx.toMixin) + of nkBindStmt: + result = semBindStmt(c, n, ctx.toBind) of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit: # check if it is an expression macro: checkMinSonsLen(n, 1, c.config) @@ -227,7 +229,10 @@ proc semGenericStmt(c: PContext, n: PNode, if s != nil: incl(s.flags, sfUsed) mixinContext = s.magic in {mDefined, mDefinedInScope, mCompiles, mAstToStr} - let sc = symChoice(c, fn, s, if s.isMixedIn: scForceOpen else: scOpen) + let whichChoice = if s.id in ctx.toBind: scClosed + elif s.isMixedIn: scForceOpen + else: scOpen + let sc = symChoice(c, fn, s, whichChoice) case s.kind of skMacro: if macroToExpand(s) and sc.safeLen <= 1: @@ -492,12 +497,14 @@ proc semGenericStmt(c: PContext, n: PNode, proc semGenericStmt(c: PContext, n: PNode): PNode = var ctx: GenericCtx ctx.toMixin = initIntSet() + ctx.toBind = initIntSet() result = semGenericStmt(c, n, {}, ctx) semIdeForTemplateOrGeneric(c, result, ctx.cursorInBody) proc semConceptBody(c: PContext, n: PNode): PNode = var ctx: GenericCtx ctx.toMixin = initIntSet() + ctx.toBind = initIntSet() result = semGenericStmt(c, n, {withinConcept}, ctx) semIdeForTemplateOrGeneric(c, result, ctx.cursorInBody) diff --git a/tests/lookups/tbind_for_generics.nim b/tests/lookups/tbind_for_generics.nim new file mode 100644 index 000000000..db5fbebbc --- /dev/null +++ b/tests/lookups/tbind_for_generics.nim @@ -0,0 +1,17 @@ +discard """ + errormsg: "type mismatch: got <Foo, Foo>" + line: 8 +""" +proc g[T](x: T) = + bind `+` + # because we bind `+` here, we must not find the `+` for 'Foo' below: + echo x + x + +type + Foo = object + a: int + +proc `+`(a, b: Foo): Foo = Foo(a: a.a+b.a) + +g(3) +g(Foo(a: 8)) |