mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 21:40:32 +00:00
bugfix: type converter that converts to bool in 'if' context
This commit is contained in:
@@ -87,6 +87,11 @@ proc new*[T](a: var ref T, finalizer: proc (x: ref T)) {.
|
||||
## freeing the object. Note: The `finalizer` refers to the type `T`, not to
|
||||
## the object! This means that for each object of type `T` the finalizer
|
||||
## will be called!
|
||||
|
||||
proc reset*(obj: var T) {.magic: "Reset", noSideEffect.}
|
||||
proc reset*(obj: ref T) {.noSideEffect.} = reset(obj^)
|
||||
## resets an object `obj` to its initial (binary zero) value. This needs to
|
||||
## be called before any possible `object branch transition`:idx:.
|
||||
|
||||
# for low and high the return type T may not be correct, but
|
||||
# we handle that with compiler magic in SemLowHigh()
|
||||
|
||||
@@ -361,6 +361,7 @@ proc evalAsgn(c: PEvalContext, n: PNode): PNode =
|
||||
var x = result
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
when defined(system.reset): reset(x)
|
||||
x.kind = result.kind
|
||||
x.typ = result.typ
|
||||
case x.kind
|
||||
|
||||
30
rod/sem.nim
30
rod/sem.nim
@@ -114,17 +114,37 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
|
||||
dec(evalTemplateCounter)
|
||||
|
||||
include seminst, semcall
|
||||
|
||||
proc CheckBool(t: PNode) =
|
||||
if (t.Typ == nil) or
|
||||
(skipTypes(t.Typ, {tyGenericInst, tyVar, tyOrdinal}).kind != tyBool):
|
||||
LocalError(t.Info, errExprMustBeBool)
|
||||
|
||||
proc typeMismatch(n: PNode, formal, actual: PType) =
|
||||
GlobalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
|
||||
typeToString(actual) & ") " &
|
||||
`%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
|
||||
|
||||
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
|
||||
result = IndexTypesMatch(c, formal, arg.typ, arg)
|
||||
if result == nil:
|
||||
#debug(arg)
|
||||
typeMismatch(arg, formal, arg.typ)
|
||||
|
||||
proc forceBool(c: PContext, n: PNode): PNode =
|
||||
result = fitNode(c, getSysType(tyBool), n)
|
||||
if result == nil: result = n
|
||||
when false:
|
||||
result = t
|
||||
if (t.Typ == nil) or
|
||||
(skipTypes(t.Typ, {tyGenericInst, tyVar, tyOrdinal}).kind != tyBool):
|
||||
var a = ConvertTo(c, getSysType(tyBool), t)
|
||||
if a != nil: result = a
|
||||
else: LocalError(t.Info, errExprMustBeBool)
|
||||
|
||||
proc semConstBoolExpr(c: PContext, n: PNode): PNode =
|
||||
result = fitNode(c, getSysType(tyBool), semExprWithType(c, n))
|
||||
if result == nil:
|
||||
GlobalError(n.info, errConstExprExpected)
|
||||
return
|
||||
result = getConstExpr(c.module, result)
|
||||
if result == nil: GlobalError(n.info, errConstExprExpected)
|
||||
|
||||
include semtypes, semexprs, semgnrc, semstmts
|
||||
|
||||
proc addCodeForGenerics(c: PContext, n: PNode) =
|
||||
|
||||
@@ -792,8 +792,7 @@ proc semIfExpr(c: PContext, n: PNode): PNode =
|
||||
case it.kind
|
||||
of nkElifExpr:
|
||||
checkSonsLen(it, 2)
|
||||
it.sons[0] = semExprWithType(c, it.sons[0])
|
||||
checkBool(it.sons[0])
|
||||
it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
|
||||
it.sons[1] = semExprWithType(c, it.sons[1])
|
||||
if typ == nil: typ = it.sons[1].typ
|
||||
else: it.sons[1] = fitNode(c, typ, it.sons[1])
|
||||
|
||||
@@ -38,8 +38,7 @@ proc semWhen(c: PContext, n: PNode): PNode =
|
||||
case it.kind
|
||||
of nkElifBranch:
|
||||
checkSonsLen(it, 2)
|
||||
var e = semConstExpr(c, it.sons[0])
|
||||
checkBool(e)
|
||||
var e = semConstBoolExpr(c, it.sons[0])
|
||||
if (e.kind != nkIntLit): InternalError(n.info, "semWhen")
|
||||
if (e.intVal != 0) and (result == nil):
|
||||
result = semStmt(c, it.sons[1]) # do not open a new scope!
|
||||
@@ -63,8 +62,7 @@ proc semIf(c: PContext, n: PNode): PNode =
|
||||
of nkElifBranch:
|
||||
checkSonsLen(it, 2)
|
||||
openScope(c.tab)
|
||||
it.sons[0] = semExprWithType(c, it.sons[0])
|
||||
checkBool(it.sons[0])
|
||||
it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
|
||||
it.sons[1] = semStmt(c, it.sons[1])
|
||||
closeScope(c.tab)
|
||||
of nkElse:
|
||||
@@ -121,8 +119,7 @@ proc semWhile(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
checkSonsLen(n, 2)
|
||||
openScope(c.tab)
|
||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||
CheckBool(n.sons[0])
|
||||
n.sons[0] = forceBool(c, semExprWithType(c, n.sons[0]))
|
||||
inc(c.p.nestedLoopCounter)
|
||||
n.sons[1] = semStmt(c, n.sons[1])
|
||||
dec(c.p.nestedLoopCounter)
|
||||
@@ -162,8 +159,7 @@ proc semCase(c: PContext, n: PNode): PNode =
|
||||
of nkElifBranch:
|
||||
chckCovered = false
|
||||
checkSonsLen(x, 2)
|
||||
x.sons[0] = semExprWithType(c, x.sons[0])
|
||||
checkBool(x.sons[0])
|
||||
x.sons[0] = forceBool(c, semExprWithType(c, x.sons[0]))
|
||||
x.sons[1] = semStmtScope(c, x.sons[1])
|
||||
of nkElse:
|
||||
chckCovered = false
|
||||
|
||||
@@ -9,12 +9,6 @@
|
||||
|
||||
# this module does the semantic checking of type declarations
|
||||
|
||||
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
|
||||
result = IndexTypesMatch(c, formal, arg.typ, arg)
|
||||
if result == nil:
|
||||
#debug(arg)
|
||||
typeMismatch(arg, formal, arg.typ)
|
||||
|
||||
proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
|
||||
if prev == nil:
|
||||
result = newTypeS(kind, c)
|
||||
@@ -355,8 +349,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
case it.kind
|
||||
of nkElifBranch:
|
||||
checkSonsLen(it, 2)
|
||||
e = semConstExpr(c, it.sons[0])
|
||||
checkBool(e)
|
||||
e = semConstBoolExpr(c, it.sons[0])
|
||||
if (e.kind != nkIntLit): InternalError(e.info, "semRecordNodeAux")
|
||||
if (e.intVal != 0) and (branch == nil): branch = it.sons[1]
|
||||
of nkElse:
|
||||
|
||||
@@ -461,6 +461,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
var dest = c.converters[i].typ.sons[0]
|
||||
if (typeRel(m.bindings, f, dest) == isEqual) and
|
||||
(typeRel(m.bindings, src, a) == isEqual):
|
||||
markUsed(arg, c.converters[i])
|
||||
var s = newSymNode(c.converters[i])
|
||||
s.typ = c.converters[i].typ
|
||||
s.info = arg.info
|
||||
@@ -564,6 +565,11 @@ proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode =
|
||||
initCandidate(m, f)
|
||||
result = paramTypesMatch(c, m, f, a, arg)
|
||||
|
||||
proc ConvertTo*(c: PContext, f: PType, n: PNode): PNode =
|
||||
var m: TCandidate
|
||||
initCandidate(m, f)
|
||||
result = paramTypesMatch(c, m, f, n.typ, n)
|
||||
|
||||
proc argtypeMatches*(c: PContext, f, a: PType): bool =
|
||||
var m: TCandidate
|
||||
initCandidate(m, f)
|
||||
|
||||
11
tests/accept/compile/tcan_alias_generic.nim
Normal file
11
tests/accept/compile/tcan_alias_generic.nim
Normal file
@@ -0,0 +1,11 @@
|
||||
##
|
||||
## can_alias_generic Nimrod Module
|
||||
##
|
||||
## Created by Eric Doughty-Papassideris on 2011-02-16.
|
||||
## Copyright (c) 2011 FWA. All rights reserved.
|
||||
|
||||
type
|
||||
TGen[T] = object
|
||||
TGen2[T] = TGen[T]
|
||||
|
||||
|
||||
11
tests/accept/compile/tcan_alias_specialised_generic.nim
Normal file
11
tests/accept/compile/tcan_alias_specialised_generic.nim
Normal file
@@ -0,0 +1,11 @@
|
||||
##
|
||||
## can_alias_specialised_generic Nimrod Module
|
||||
##
|
||||
## Created by Eric Doughty-Papassideris on 2011-02-16.
|
||||
## Copyright (c) 2011 FWA. All rights reserved.
|
||||
|
||||
type
|
||||
TGen[T] = object
|
||||
TSpef = TGen[string]
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
converter p(i: int): bool = return i != 0
|
||||
|
||||
if 0:
|
||||
echo "foo"
|
||||
if 1:
|
||||
echo if 4: "foo" else: "barr"
|
||||
while 0:
|
||||
echo "bar"
|
||||
|
||||
|
||||
8
tests/reject/tno_int_in_bool_context.nim
Normal file
8
tests/reject/tno_int_in_bool_context.nim
Normal file
@@ -0,0 +1,8 @@
|
||||
discard """
|
||||
line: 6
|
||||
errormsg: "Error: type mismatch: got (int) but expected 'bool'"
|
||||
"""
|
||||
|
||||
if 1:
|
||||
echo "wtf?"
|
||||
|
||||
Reference in New Issue
Block a user