mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
fixes #2252
This commit is contained in:
@@ -65,8 +65,8 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
|
||||
echo "passing to safeSemExpr: ", renderTree(n)
|
||||
discard safeSemExpr(c, n)
|
||||
|
||||
proc typeMismatch(n: PNode, formal, actual: PType) =
|
||||
if formal.kind != tyError and actual.kind != tyError:
|
||||
proc typeMismatch(n: PNode, formal, actual: PType) =
|
||||
if formal.kind != tyError and actual.kind != tyError:
|
||||
localError(n.info, errGenerated, msgKindToString(errTypeMismatch) &
|
||||
typeToString(actual) & ") " &
|
||||
`%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
|
||||
@@ -113,7 +113,7 @@ proc commonType*(x, y: PType): PType =
|
||||
else:
|
||||
result = newType(tyTypeDesc, 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:
|
||||
# check for seq[empty] vs. seq[int]
|
||||
let idx = ord(b.kind in {tyArray, tyArrayConstr})
|
||||
@@ -163,7 +163,7 @@ proc commonType*(x, y: PType): PType =
|
||||
result = newType(k, r.owner)
|
||||
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)
|
||||
|
||||
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,
|
||||
allowed: TSymFlags): PSym
|
||||
# identifier with visability
|
||||
proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
|
||||
proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
|
||||
allowed: TSymFlags): PSym
|
||||
proc semStmtScope(c: PContext, n: PNode): PNode
|
||||
|
||||
@@ -190,7 +190,7 @@ proc typeAllowedCheck(info: TLineInfo; typ: PType; kind: TSymKind) =
|
||||
let t = typeAllowed(typ, kind)
|
||||
if t != nil:
|
||||
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) & "'")
|
||||
|
||||
proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
|
||||
@@ -226,7 +226,7 @@ when false:
|
||||
result = newSymNode(getSysSym"void")
|
||||
else:
|
||||
result.typ = makeTypeDesc(c, result.typ)
|
||||
|
||||
|
||||
result.handleIsOperator = proc (n: PNode): PNode =
|
||||
result = isOpImpl(c, n)
|
||||
|
||||
@@ -248,7 +248,7 @@ proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode =
|
||||
if result == nil:
|
||||
result = arg
|
||||
# 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 = eOrig.typ
|
||||
|
||||
@@ -320,7 +320,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
|
||||
else:
|
||||
case s.typ.sons[0].kind
|
||||
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)
|
||||
# semExprWithType(c, result)
|
||||
result = semExpr(c, result, flags)
|
||||
@@ -355,18 +355,18 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
result = semAfterMacroCall(c, result, sym, flags)
|
||||
popInfoContext()
|
||||
|
||||
proc forceBool(c: PContext, n: PNode): PNode =
|
||||
proc forceBool(c: PContext, n: PNode): PNode =
|
||||
result = fitNode(c, getSysType(tyBool), 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)
|
||||
result = fitNode(c, getSysType(tyBool), nn)
|
||||
if result == nil:
|
||||
localError(n.info, errConstExprExpected)
|
||||
return nn
|
||||
result = getConstExpr(c.module, result)
|
||||
if result == nil:
|
||||
if result == nil:
|
||||
localError(n.info, errConstExprExpected)
|
||||
result = nn
|
||||
|
||||
@@ -403,9 +403,9 @@ proc myOpen(module: PSym): PPassContext =
|
||||
pushOwner(c.module)
|
||||
c.importTable = openScope(c)
|
||||
c.importTable.addSym(module) # a module knows itself
|
||||
if sfSystemModule in module.flags:
|
||||
if sfSystemModule in module.flags:
|
||||
magicsys.systemModule = module # set global variable!
|
||||
else:
|
||||
else:
|
||||
c.importTable.addSym magicsys.systemModule # import the "System" identifier
|
||||
importAllSymbols(c, magicsys.systemModule)
|
||||
c.topLevelScope = openScope(c)
|
||||
@@ -415,13 +415,13 @@ proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
|
||||
result = myOpen(module)
|
||||
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)
|
||||
# BUGFIX: process newly generated generics here, not at the end!
|
||||
if c.lastGenericIdx < c.generics.len:
|
||||
var a = newNodeI(nkStmtList, n.info)
|
||||
addCodeForGenerics(c, a)
|
||||
if sonsLen(a) > 0:
|
||||
if sonsLen(a) > 0:
|
||||
# a generic has been added to `a`:
|
||||
if result.kind != nkEmpty: addSon(a, result)
|
||||
result = a
|
||||
@@ -429,17 +429,17 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
|
||||
if gCmd == cmdInteractive and not isEmptyType(result.typ):
|
||||
result = buildEchoStmt(c, 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
|
||||
# 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.
|
||||
c.currentScope = c.topLevelScope
|
||||
while getCurrOwner().kind != skModule: popOwner()
|
||||
while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next
|
||||
|
||||
proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||
var c = PContext(context)
|
||||
proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||
var c = PContext(context)
|
||||
# no need for an expensive 'try' if we stop after the first error anyway:
|
||||
if msgs.gErrorMax <= 1:
|
||||
result = semStmtAndGenerateGenerics(c, n)
|
||||
@@ -455,8 +455,8 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||
if getCurrentException() of ESuggestDone: result = nil
|
||||
else: result = ast.emptyNode
|
||||
#if gCmd == cmdIdeTools: findSuggest(c, n)
|
||||
|
||||
proc myClose(context: PPassContext, n: PNode): PNode =
|
||||
|
||||
proc myClose(context: PPassContext, n: PNode): PNode =
|
||||
var c = PContext(context)
|
||||
closeScope(c) # close module's scope
|
||||
rawCloseScope(c) # imported symbols; don't check for unused ones!
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements semantic checking for calls.
|
||||
## This module implements semantic checking for calls.
|
||||
# included from sem.nim
|
||||
|
||||
proc sameMethodDispatcher(a, b: PSym): bool =
|
||||
result = false
|
||||
if a.kind == skMethod and b.kind == skMethod:
|
||||
if a.kind == skMethod and b.kind == skMethod:
|
||||
var aa = lastSon(a.ast)
|
||||
var bb = lastSon(b.ast)
|
||||
if aa.kind == nkSym and bb.kind == nkSym:
|
||||
if aa.sym == bb.sym:
|
||||
if aa.sym == bb.sym:
|
||||
result = true
|
||||
else:
|
||||
discard
|
||||
@@ -31,7 +31,7 @@ proc sameMethodDispatcher(a, b: PSym): bool =
|
||||
# to avoid subtle problems, the call remains ambiguous and needs to
|
||||
# be disambiguated by the programmer; this way the right generic is
|
||||
# instantiated.
|
||||
|
||||
|
||||
proc determineType(c: PContext, s: PSym)
|
||||
|
||||
proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||
@@ -45,12 +45,12 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||
let symScope = o.lastOverloadScope
|
||||
|
||||
var z: TCandidate
|
||||
|
||||
|
||||
if sym == nil: return
|
||||
initCandidate(c, best, sym, initialBinding, symScope)
|
||||
initCandidate(c, alt, sym, initialBinding, symScope)
|
||||
best.state = csNoMatch
|
||||
|
||||
|
||||
while sym != nil:
|
||||
if sym.kind in filter:
|
||||
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,
|
||||
# as semOverlodedCall is already pretty slow (and we need this information
|
||||
# only in case of an error).
|
||||
if c.inCompilesContext > 0:
|
||||
if c.inCompilesContext > 0:
|
||||
# fail fast:
|
||||
globalError(n.info, errTypeMismatch, "")
|
||||
if errors.isNil or errors.len == 0:
|
||||
localError(n.info, errExprXCannotBeCalled, n[0].renderTree)
|
||||
return
|
||||
|
||||
# to avoid confusing errors like:
|
||||
# to avoid confusing errors like:
|
||||
# got (SslPtr, SocketHandle)
|
||||
# but expected one of:
|
||||
# but expected one of:
|
||||
# openssl.SSL_set_fd(ssl: SslPtr, fd: SocketHandle): cint
|
||||
# we do a pre-analysis. If all types produce the same string, we will add
|
||||
# module information.
|
||||
let proto = describeArgs(c, n, 1, preferName)
|
||||
|
||||
|
||||
var prefer = preferName
|
||||
for err in errors:
|
||||
var errProto = ""
|
||||
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]
|
||||
if p.kind == nkSym:
|
||||
add(errProto, typeToString(p.sym.typ, preferName))
|
||||
@@ -159,9 +159,9 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
|
||||
n.sons.insert(hiddenArg, 1)
|
||||
orig.sons.insert(hiddenArg, 1)
|
||||
|
||||
|
||||
pickBest(f)
|
||||
|
||||
|
||||
if result.state != csMatch:
|
||||
n.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
|
||||
n.sons[0..1] = [nil, n[1], calleeName]
|
||||
orig.sons[0..1] = [nil, orig[1], calleeName]
|
||||
|
||||
|
||||
template tryOp(x) =
|
||||
let op = newIdentNode(getIdent(x), n.info)
|
||||
n.sons[0] = op
|
||||
@@ -188,7 +188,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
|
||||
if nfExplicitCall in n.flags:
|
||||
tryOp ".()"
|
||||
|
||||
|
||||
if result.state in {csEmpty, csNoMatch}:
|
||||
tryOp "."
|
||||
|
||||
@@ -199,7 +199,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
n.sons[0..1] = [callOp, n[1], calleeName]
|
||||
orig.sons[0..1] = [callOp, orig[1], calleeName]
|
||||
pickBest(callOp)
|
||||
|
||||
|
||||
if overloadsState == csEmpty and result.state == csEmpty:
|
||||
localError(n.info, errUndeclaredIdentifier, considerQuotedIdent(f).s)
|
||||
return
|
||||
@@ -224,7 +224,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
internalAssert result.state == csMatch
|
||||
#writeMatches(result)
|
||||
#writeMatches(alt)
|
||||
if c.inCompilesContext > 0:
|
||||
if c.inCompilesContext > 0:
|
||||
# quick error message for performance of 'compiles' built-in:
|
||||
globalError(n.info, errGenerated, "ambiguous call")
|
||||
elif gErrorCounter == 0:
|
||||
@@ -254,7 +254,7 @@ proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) =
|
||||
for i in 1 .. <n.len:
|
||||
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
|
||||
initCandidate(c, m, f)
|
||||
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:
|
||||
n.sons[1] = n.sons[1].sons[0]
|
||||
notFoundError(c, n, errors)
|
||||
else:
|
||||
else:
|
||||
notFoundError(c, n, errors)
|
||||
# else: result = errorNode(c, n)
|
||||
|
||||
@@ -341,7 +341,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
|
||||
styleCheckUse(n.info, s)
|
||||
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
|
||||
for i in 1..sonsLen(n)-1:
|
||||
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.
|
||||
# It's good enough for now.
|
||||
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
|
||||
if candidate.kind in {skProc, skMethod, skConverter,
|
||||
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:
|
||||
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
|
||||
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)
|
||||
#for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
|
||||
result = rawExecute(c, start, tos).regToNode
|
||||
if result.info.line < 0: result.info = n.info
|
||||
|
||||
proc evalConstExpr*(module: PSym, e: PNode): PNode =
|
||||
result = evalConstExprAux(module, nil, e, emConst)
|
||||
@@ -1496,6 +1497,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
|
||||
# temporary storage:
|
||||
#for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
|
||||
result = rawExecute(c, start, tos).regToNode
|
||||
if result.info.line < 0: result.info = n.info
|
||||
if cyclicTree(result): globalError(n.info, errCyclicTree)
|
||||
dec(evalMacroCounter)
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user