mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-11 22:08:54 +00:00
implement the 'bind' statement for generics, it was an oversight that this was never implemented (#14584)
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
17
tests/lookups/tbind_for_generics.nim
Normal file
17
tests/lookups/tbind_for_generics.nim
Normal 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))
|
||||
Reference in New Issue
Block a user