fixes #2252
This commit is contained in:
parent
8ade324b8c
commit
83cab19c62
4 changed files with 55 additions and 45 deletions
|
|
@ -65,8 +65,8 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
|
||||||
echo "passing to safeSemExpr: ", renderTree(n)
|
echo "passing to safeSemExpr: ", renderTree(n)
|
||||||
discard safeSemExpr(c, n)
|
discard safeSemExpr(c, n)
|
||||||
|
|
||||||
proc typeMismatch(n: PNode, formal, actual: PType) =
|
proc typeMismatch(n: PNode, formal, actual: PType) =
|
||||||
if formal.kind != tyError and actual.kind != tyError:
|
if formal.kind != tyError and actual.kind != tyError:
|
||||||
localError(n.info, errGenerated, msgKindToString(errTypeMismatch) &
|
localError(n.info, errGenerated, msgKindToString(errTypeMismatch) &
|
||||||
typeToString(actual) & ") " &
|
typeToString(actual) & ") " &
|
||||||
`%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
|
`%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
|
||||||
|
|
@ -113,7 +113,7 @@ proc commonType*(x, y: PType): PType =
|
||||||
else:
|
else:
|
||||||
result = newType(tyTypeDesc, a.owner)
|
result = newType(tyTypeDesc, a.owner)
|
||||||
rawAddSon(result, newType(tyNone, a.owner))
|
rawAddSon(result, newType(tyNone, a.owner))
|
||||||
elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and
|
elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and
|
||||||
a.kind == b.kind:
|
a.kind == b.kind:
|
||||||
# check for seq[empty] vs. seq[int]
|
# check for seq[empty] vs. seq[int]
|
||||||
let idx = ord(b.kind in {tyArray, tyArrayConstr})
|
let idx = ord(b.kind in {tyArray, tyArrayConstr})
|
||||||
|
|
@ -163,7 +163,7 @@ proc commonType*(x, y: PType): PType =
|
||||||
result = newType(k, r.owner)
|
result = newType(k, r.owner)
|
||||||
result.addSonSkipIntLit(r)
|
result.addSonSkipIntLit(r)
|
||||||
|
|
||||||
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
|
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||||
result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info)
|
result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info)
|
||||||
|
|
||||||
proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||||
|
|
@ -182,7 +182,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||||
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
||||||
allowed: TSymFlags): PSym
|
allowed: TSymFlags): PSym
|
||||||
# identifier with visability
|
# identifier with visability
|
||||||
proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
|
proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
|
||||||
allowed: TSymFlags): PSym
|
allowed: TSymFlags): PSym
|
||||||
proc semStmtScope(c: PContext, n: PNode): PNode
|
proc semStmtScope(c: PContext, n: PNode): PNode
|
||||||
|
|
||||||
|
|
@ -190,7 +190,7 @@ proc typeAllowedCheck(info: TLineInfo; typ: PType; kind: TSymKind) =
|
||||||
let t = typeAllowed(typ, kind)
|
let t = typeAllowed(typ, kind)
|
||||||
if t != nil:
|
if t != nil:
|
||||||
if t == typ: localError(info, "invalid type: '" & typeToString(typ) & "'")
|
if t == typ: localError(info, "invalid type: '" & typeToString(typ) & "'")
|
||||||
else: localError(info, "invalid type: '" & typeToString(t) &
|
else: localError(info, "invalid type: '" & typeToString(t) &
|
||||||
"' in this context: '" & typeToString(typ) & "'")
|
"' in this context: '" & typeToString(typ) & "'")
|
||||||
|
|
||||||
proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
|
proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
|
||||||
|
|
@ -226,7 +226,7 @@ when false:
|
||||||
result = newSymNode(getSysSym"void")
|
result = newSymNode(getSysSym"void")
|
||||||
else:
|
else:
|
||||||
result.typ = makeTypeDesc(c, result.typ)
|
result.typ = makeTypeDesc(c, result.typ)
|
||||||
|
|
||||||
result.handleIsOperator = proc (n: PNode): PNode =
|
result.handleIsOperator = proc (n: PNode): PNode =
|
||||||
result = isOpImpl(c, n)
|
result = isOpImpl(c, n)
|
||||||
|
|
||||||
|
|
@ -248,7 +248,7 @@ proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode =
|
||||||
if result == nil:
|
if result == nil:
|
||||||
result = arg
|
result = arg
|
||||||
# for 'tcnstseq' we support [] to become 'seq'
|
# for 'tcnstseq' we support [] to become 'seq'
|
||||||
if eOrig.typ.skipTypes(abstractInst).kind == tySequence and
|
if eOrig.typ.skipTypes(abstractInst).kind == tySequence and
|
||||||
arg.typ.skipTypes(abstractInst).kind == tyArrayConstr:
|
arg.typ.skipTypes(abstractInst).kind == tyArrayConstr:
|
||||||
arg.typ = eOrig.typ
|
arg.typ = eOrig.typ
|
||||||
|
|
||||||
|
|
@ -320,7 +320,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
|
||||||
else:
|
else:
|
||||||
case s.typ.sons[0].kind
|
case s.typ.sons[0].kind
|
||||||
of tyExpr:
|
of tyExpr:
|
||||||
# BUGFIX: we cannot expect a type here, because module aliases would not
|
# BUGFIX: we cannot expect a type here, because module aliases would not
|
||||||
# work then (see the ``tmodulealias`` test)
|
# work then (see the ``tmodulealias`` test)
|
||||||
# semExprWithType(c, result)
|
# semExprWithType(c, result)
|
||||||
result = semExpr(c, result, flags)
|
result = semExpr(c, result, flags)
|
||||||
|
|
@ -355,18 +355,18 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||||
result = semAfterMacroCall(c, result, sym, flags)
|
result = semAfterMacroCall(c, result, sym, flags)
|
||||||
popInfoContext()
|
popInfoContext()
|
||||||
|
|
||||||
proc forceBool(c: PContext, n: PNode): PNode =
|
proc forceBool(c: PContext, n: PNode): PNode =
|
||||||
result = fitNode(c, getSysType(tyBool), n)
|
result = fitNode(c, getSysType(tyBool), n)
|
||||||
if result == nil: result = n
|
if result == nil: result = n
|
||||||
|
|
||||||
proc semConstBoolExpr(c: PContext, n: PNode): PNode =
|
proc semConstBoolExpr(c: PContext, n: PNode): PNode =
|
||||||
let nn = semExprWithType(c, n)
|
let nn = semExprWithType(c, n)
|
||||||
result = fitNode(c, getSysType(tyBool), nn)
|
result = fitNode(c, getSysType(tyBool), nn)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
localError(n.info, errConstExprExpected)
|
localError(n.info, errConstExprExpected)
|
||||||
return nn
|
return nn
|
||||||
result = getConstExpr(c.module, result)
|
result = getConstExpr(c.module, result)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
localError(n.info, errConstExprExpected)
|
localError(n.info, errConstExprExpected)
|
||||||
result = nn
|
result = nn
|
||||||
|
|
||||||
|
|
@ -403,9 +403,9 @@ proc myOpen(module: PSym): PPassContext =
|
||||||
pushOwner(c.module)
|
pushOwner(c.module)
|
||||||
c.importTable = openScope(c)
|
c.importTable = openScope(c)
|
||||||
c.importTable.addSym(module) # a module knows itself
|
c.importTable.addSym(module) # a module knows itself
|
||||||
if sfSystemModule in module.flags:
|
if sfSystemModule in module.flags:
|
||||||
magicsys.systemModule = module # set global variable!
|
magicsys.systemModule = module # set global variable!
|
||||||
else:
|
else:
|
||||||
c.importTable.addSym magicsys.systemModule # import the "System" identifier
|
c.importTable.addSym magicsys.systemModule # import the "System" identifier
|
||||||
importAllSymbols(c, magicsys.systemModule)
|
importAllSymbols(c, magicsys.systemModule)
|
||||||
c.topLevelScope = openScope(c)
|
c.topLevelScope = openScope(c)
|
||||||
|
|
@ -415,13 +415,13 @@ proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
|
||||||
result = myOpen(module)
|
result = myOpen(module)
|
||||||
for m in items(rd.methods): methodDef(m, true)
|
for m in items(rd.methods): methodDef(m, true)
|
||||||
|
|
||||||
proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
|
proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
|
||||||
result = semStmt(c, n)
|
result = semStmt(c, n)
|
||||||
# BUGFIX: process newly generated generics here, not at the end!
|
# BUGFIX: process newly generated generics here, not at the end!
|
||||||
if c.lastGenericIdx < c.generics.len:
|
if c.lastGenericIdx < c.generics.len:
|
||||||
var a = newNodeI(nkStmtList, n.info)
|
var a = newNodeI(nkStmtList, n.info)
|
||||||
addCodeForGenerics(c, a)
|
addCodeForGenerics(c, a)
|
||||||
if sonsLen(a) > 0:
|
if sonsLen(a) > 0:
|
||||||
# a generic has been added to `a`:
|
# a generic has been added to `a`:
|
||||||
if result.kind != nkEmpty: addSon(a, result)
|
if result.kind != nkEmpty: addSon(a, result)
|
||||||
result = a
|
result = a
|
||||||
|
|
@ -429,17 +429,17 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
|
||||||
if gCmd == cmdInteractive and not isEmptyType(result.typ):
|
if gCmd == cmdInteractive and not isEmptyType(result.typ):
|
||||||
result = buildEchoStmt(c, result)
|
result = buildEchoStmt(c, result)
|
||||||
result = transformStmt(c.module, result)
|
result = transformStmt(c.module, result)
|
||||||
|
|
||||||
proc recoverContext(c: PContext) =
|
proc recoverContext(c: PContext) =
|
||||||
# clean up in case of a semantic error: We clean up the stacks, etc. This is
|
# clean up in case of a semantic error: We clean up the stacks, etc. This is
|
||||||
# faster than wrapping every stack operation in a 'try finally' block and
|
# faster than wrapping every stack operation in a 'try finally' block and
|
||||||
# requires far less code.
|
# requires far less code.
|
||||||
c.currentScope = c.topLevelScope
|
c.currentScope = c.topLevelScope
|
||||||
while getCurrOwner().kind != skModule: popOwner()
|
while getCurrOwner().kind != skModule: popOwner()
|
||||||
while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next
|
while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next
|
||||||
|
|
||||||
proc myProcess(context: PPassContext, n: PNode): PNode =
|
proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||||
var c = PContext(context)
|
var c = PContext(context)
|
||||||
# no need for an expensive 'try' if we stop after the first error anyway:
|
# no need for an expensive 'try' if we stop after the first error anyway:
|
||||||
if msgs.gErrorMax <= 1:
|
if msgs.gErrorMax <= 1:
|
||||||
result = semStmtAndGenerateGenerics(c, n)
|
result = semStmtAndGenerateGenerics(c, n)
|
||||||
|
|
@ -455,8 +455,8 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||||
if getCurrentException() of ESuggestDone: result = nil
|
if getCurrentException() of ESuggestDone: result = nil
|
||||||
else: result = ast.emptyNode
|
else: result = ast.emptyNode
|
||||||
#if gCmd == cmdIdeTools: findSuggest(c, n)
|
#if gCmd == cmdIdeTools: findSuggest(c, n)
|
||||||
|
|
||||||
proc myClose(context: PPassContext, n: PNode): PNode =
|
proc myClose(context: PPassContext, n: PNode): PNode =
|
||||||
var c = PContext(context)
|
var c = PContext(context)
|
||||||
closeScope(c) # close module's scope
|
closeScope(c) # close module's scope
|
||||||
rawCloseScope(c) # imported symbols; don't check for unused ones!
|
rawCloseScope(c) # imported symbols; don't check for unused ones!
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,16 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
## This module implements semantic checking for calls.
|
## This module implements semantic checking for calls.
|
||||||
# included from sem.nim
|
# included from sem.nim
|
||||||
|
|
||||||
proc sameMethodDispatcher(a, b: PSym): bool =
|
proc sameMethodDispatcher(a, b: PSym): bool =
|
||||||
result = false
|
result = false
|
||||||
if a.kind == skMethod and b.kind == skMethod:
|
if a.kind == skMethod and b.kind == skMethod:
|
||||||
var aa = lastSon(a.ast)
|
var aa = lastSon(a.ast)
|
||||||
var bb = lastSon(b.ast)
|
var bb = lastSon(b.ast)
|
||||||
if aa.kind == nkSym and bb.kind == nkSym:
|
if aa.kind == nkSym and bb.kind == nkSym:
|
||||||
if aa.sym == bb.sym:
|
if aa.sym == bb.sym:
|
||||||
result = true
|
result = true
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
@ -31,7 +31,7 @@ proc sameMethodDispatcher(a, b: PSym): bool =
|
||||||
# to avoid subtle problems, the call remains ambiguous and needs to
|
# to avoid subtle problems, the call remains ambiguous and needs to
|
||||||
# be disambiguated by the programmer; this way the right generic is
|
# be disambiguated by the programmer; this way the right generic is
|
||||||
# instantiated.
|
# instantiated.
|
||||||
|
|
||||||
proc determineType(c: PContext, s: PSym)
|
proc determineType(c: PContext, s: PSym)
|
||||||
|
|
||||||
proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
|
|
@ -45,12 +45,12 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
let symScope = o.lastOverloadScope
|
let symScope = o.lastOverloadScope
|
||||||
|
|
||||||
var z: TCandidate
|
var z: TCandidate
|
||||||
|
|
||||||
if sym == nil: return
|
if sym == nil: return
|
||||||
initCandidate(c, best, sym, initialBinding, symScope)
|
initCandidate(c, best, sym, initialBinding, symScope)
|
||||||
initCandidate(c, alt, sym, initialBinding, symScope)
|
initCandidate(c, alt, sym, initialBinding, symScope)
|
||||||
best.state = csNoMatch
|
best.state = csNoMatch
|
||||||
|
|
||||||
while sym != nil:
|
while sym != nil:
|
||||||
if sym.kind in filter:
|
if sym.kind in filter:
|
||||||
determineType(c, sym)
|
determineType(c, sym)
|
||||||
|
|
@ -88,26 +88,26 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||||
# Gives a detailed error message; this is separated from semOverloadedCall,
|
# Gives a detailed error message; this is separated from semOverloadedCall,
|
||||||
# as semOverlodedCall is already pretty slow (and we need this information
|
# as semOverlodedCall is already pretty slow (and we need this information
|
||||||
# only in case of an error).
|
# only in case of an error).
|
||||||
if c.inCompilesContext > 0:
|
if c.inCompilesContext > 0:
|
||||||
# fail fast:
|
# fail fast:
|
||||||
globalError(n.info, errTypeMismatch, "")
|
globalError(n.info, errTypeMismatch, "")
|
||||||
if errors.isNil or errors.len == 0:
|
if errors.isNil or errors.len == 0:
|
||||||
localError(n.info, errExprXCannotBeCalled, n[0].renderTree)
|
localError(n.info, errExprXCannotBeCalled, n[0].renderTree)
|
||||||
return
|
return
|
||||||
|
|
||||||
# to avoid confusing errors like:
|
# to avoid confusing errors like:
|
||||||
# got (SslPtr, SocketHandle)
|
# got (SslPtr, SocketHandle)
|
||||||
# but expected one of:
|
# but expected one of:
|
||||||
# openssl.SSL_set_fd(ssl: SslPtr, fd: SocketHandle): cint
|
# openssl.SSL_set_fd(ssl: SslPtr, fd: SocketHandle): cint
|
||||||
# we do a pre-analysis. If all types produce the same string, we will add
|
# we do a pre-analysis. If all types produce the same string, we will add
|
||||||
# module information.
|
# module information.
|
||||||
let proto = describeArgs(c, n, 1, preferName)
|
let proto = describeArgs(c, n, 1, preferName)
|
||||||
|
|
||||||
var prefer = preferName
|
var prefer = preferName
|
||||||
for err in errors:
|
for err in errors:
|
||||||
var errProto = ""
|
var errProto = ""
|
||||||
let n = err.typ.n
|
let n = err.typ.n
|
||||||
for i in countup(1, n.len - 1):
|
for i in countup(1, n.len - 1):
|
||||||
var p = n.sons[i]
|
var p = n.sons[i]
|
||||||
if p.kind == nkSym:
|
if p.kind == nkSym:
|
||||||
add(errProto, typeToString(p.sym.typ, preferName))
|
add(errProto, typeToString(p.sym.typ, preferName))
|
||||||
|
|
@ -159,9 +159,9 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
|
|
||||||
n.sons.insert(hiddenArg, 1)
|
n.sons.insert(hiddenArg, 1)
|
||||||
orig.sons.insert(hiddenArg, 1)
|
orig.sons.insert(hiddenArg, 1)
|
||||||
|
|
||||||
pickBest(f)
|
pickBest(f)
|
||||||
|
|
||||||
if result.state != csMatch:
|
if result.state != csMatch:
|
||||||
n.sons.delete(1)
|
n.sons.delete(1)
|
||||||
orig.sons.delete(1)
|
orig.sons.delete(1)
|
||||||
|
|
@ -179,7 +179,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
# we are going to try multiple variants
|
# we are going to try multiple variants
|
||||||
n.sons[0..1] = [nil, n[1], calleeName]
|
n.sons[0..1] = [nil, n[1], calleeName]
|
||||||
orig.sons[0..1] = [nil, orig[1], calleeName]
|
orig.sons[0..1] = [nil, orig[1], calleeName]
|
||||||
|
|
||||||
template tryOp(x) =
|
template tryOp(x) =
|
||||||
let op = newIdentNode(getIdent(x), n.info)
|
let op = newIdentNode(getIdent(x), n.info)
|
||||||
n.sons[0] = op
|
n.sons[0] = op
|
||||||
|
|
@ -188,7 +188,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
|
|
||||||
if nfExplicitCall in n.flags:
|
if nfExplicitCall in n.flags:
|
||||||
tryOp ".()"
|
tryOp ".()"
|
||||||
|
|
||||||
if result.state in {csEmpty, csNoMatch}:
|
if result.state in {csEmpty, csNoMatch}:
|
||||||
tryOp "."
|
tryOp "."
|
||||||
|
|
||||||
|
|
@ -199,7 +199,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
n.sons[0..1] = [callOp, n[1], calleeName]
|
n.sons[0..1] = [callOp, n[1], calleeName]
|
||||||
orig.sons[0..1] = [callOp, orig[1], calleeName]
|
orig.sons[0..1] = [callOp, orig[1], calleeName]
|
||||||
pickBest(callOp)
|
pickBest(callOp)
|
||||||
|
|
||||||
if overloadsState == csEmpty and result.state == csEmpty:
|
if overloadsState == csEmpty and result.state == csEmpty:
|
||||||
localError(n.info, errUndeclaredIdentifier, considerQuotedIdent(f).s)
|
localError(n.info, errUndeclaredIdentifier, considerQuotedIdent(f).s)
|
||||||
return
|
return
|
||||||
|
|
@ -224,7 +224,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
internalAssert result.state == csMatch
|
internalAssert result.state == csMatch
|
||||||
#writeMatches(result)
|
#writeMatches(result)
|
||||||
#writeMatches(alt)
|
#writeMatches(alt)
|
||||||
if c.inCompilesContext > 0:
|
if c.inCompilesContext > 0:
|
||||||
# quick error message for performance of 'compiles' built-in:
|
# quick error message for performance of 'compiles' built-in:
|
||||||
globalError(n.info, errGenerated, "ambiguous call")
|
globalError(n.info, errGenerated, "ambiguous call")
|
||||||
elif gErrorCounter == 0:
|
elif gErrorCounter == 0:
|
||||||
|
|
@ -254,7 +254,7 @@ proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) =
|
||||||
for i in 1 .. <n.len:
|
for i in 1 .. <n.len:
|
||||||
instGenericConvertersArg(c, n.sons[i], x)
|
instGenericConvertersArg(c, n.sons[i], x)
|
||||||
|
|
||||||
proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode =
|
proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode =
|
||||||
var m: TCandidate
|
var m: TCandidate
|
||||||
initCandidate(c, m, f)
|
initCandidate(c, m, f)
|
||||||
result = paramTypesMatch(m, f, a, arg, nil)
|
result = paramTypesMatch(m, f, a, arg, nil)
|
||||||
|
|
@ -325,7 +325,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||||
# get rid of the deref again for a better error message:
|
# get rid of the deref again for a better error message:
|
||||||
n.sons[1] = n.sons[1].sons[0]
|
n.sons[1] = n.sons[1].sons[0]
|
||||||
notFoundError(c, n, errors)
|
notFoundError(c, n, errors)
|
||||||
else:
|
else:
|
||||||
notFoundError(c, n, errors)
|
notFoundError(c, n, errors)
|
||||||
# else: result = errorNode(c, n)
|
# else: result = errorNode(c, n)
|
||||||
|
|
||||||
|
|
@ -341,7 +341,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
styleCheckUse(n.info, s)
|
styleCheckUse(n.info, s)
|
||||||
result = newSymNode(newInst, n.info)
|
result = newSymNode(newInst, n.info)
|
||||||
|
|
||||||
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
assert n.kind == nkBracketExpr
|
assert n.kind == nkBracketExpr
|
||||||
for i in 1..sonsLen(n)-1:
|
for i in 1..sonsLen(n)-1:
|
||||||
n.sons[i].typ = semTypeNode(c, n.sons[i], nil)
|
n.sons[i].typ = semTypeNode(c, n.sons[i], nil)
|
||||||
|
|
@ -361,11 +361,11 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
# XXX I think this could be improved by reusing sigmatch.paramTypesMatch.
|
# XXX I think this could be improved by reusing sigmatch.paramTypesMatch.
|
||||||
# It's good enough for now.
|
# It's good enough for now.
|
||||||
result = newNodeI(a.kind, n.info)
|
result = newNodeI(a.kind, n.info)
|
||||||
for i in countup(0, len(a)-1):
|
for i in countup(0, len(a)-1):
|
||||||
var candidate = a.sons[i].sym
|
var candidate = a.sons[i].sym
|
||||||
if candidate.kind in {skProc, skMethod, skConverter,
|
if candidate.kind in {skProc, skMethod, skConverter,
|
||||||
skIterator, skClosureIterator}:
|
skIterator, skClosureIterator}:
|
||||||
# it suffices that the candidate has the proper number of generic
|
# it suffices that the candidate has the proper number of generic
|
||||||
# type parameters:
|
# type parameters:
|
||||||
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
|
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
|
||||||
result.add(explicitGenericSym(c, n, candidate))
|
result.add(explicitGenericSym(c, n, candidate))
|
||||||
|
|
|
||||||
|
|
@ -1435,6 +1435,7 @@ proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
|
||||||
newSeq(tos.slots, c.prc.maxSlots)
|
newSeq(tos.slots, c.prc.maxSlots)
|
||||||
#for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
|
#for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
|
||||||
result = rawExecute(c, start, tos).regToNode
|
result = rawExecute(c, start, tos).regToNode
|
||||||
|
if result.info.line < 0: result.info = n.info
|
||||||
|
|
||||||
proc evalConstExpr*(module: PSym, e: PNode): PNode =
|
proc evalConstExpr*(module: PSym, e: PNode): PNode =
|
||||||
result = evalConstExprAux(module, nil, e, emConst)
|
result = evalConstExprAux(module, nil, e, emConst)
|
||||||
|
|
@ -1496,6 +1497,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
|
||||||
# temporary storage:
|
# temporary storage:
|
||||||
#for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
|
#for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
|
||||||
result = rawExecute(c, start, tos).regToNode
|
result = rawExecute(c, start, tos).regToNode
|
||||||
|
if result.info.line < 0: result.info = n.info
|
||||||
if cyclicTree(result): globalError(n.info, errCyclicTree)
|
if cyclicTree(result): globalError(n.info, errCyclicTree)
|
||||||
dec(evalMacroCounter)
|
dec(evalMacroCounter)
|
||||||
c.callsite = nil
|
c.callsite = nil
|
||||||
|
|
|
||||||
8
tests/clearmsg/tconsttypemismatch.nim
Normal file
8
tests/clearmsg/tconsttypemismatch.nim
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
discard """
|
||||||
|
file: "tconsttypemismatch.nim"
|
||||||
|
line: 7
|
||||||
|
errormsg: "type mismatch"
|
||||||
|
"""
|
||||||
|
# bug #2252
|
||||||
|
const foo: int = 1000 / 30
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue