implement the 'bind' statement for generics, it was an oversight that this was never implemented (#14584)

This commit is contained in:
Andreas Rumpf
2020-06-07 09:55:56 +02:00
committed by GitHub
parent 51b71e35f2
commit 66c50c2ffc
2 changed files with 28 additions and 4 deletions

View File

@@ -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)

View File

@@ -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))