conversions to unsigned numbers are not checked anymore; implements /… (#12688) [backport]
* conversions to unsigned numbers are not checked anymore; implements / fixes https://github.com/nim-lang/RFCs/issues/175 * change the spec yet again to be less consistent but to make more sense; updated the changelog
This commit is contained in:
parent
85ffcd80c0
commit
c98e0e22ad
6 changed files with 29 additions and 6 deletions
|
|
@ -64,6 +64,9 @@
|
||||||
## Language changes
|
## Language changes
|
||||||
|
|
||||||
- Unsigned integer operators have been fixed to allow promotion of the first operand.
|
- Unsigned integer operators have been fixed to allow promotion of the first operand.
|
||||||
|
- Conversions to unsigned integers are unchecked at runtime, imitating earlier Nim
|
||||||
|
versions. The documentation was improved to acknowledge this special case.
|
||||||
|
See https://github.com/nim-lang/RFCs/issues/175 for more details.
|
||||||
|
|
||||||
|
|
||||||
### Tool changes
|
### Tool changes
|
||||||
|
|
|
||||||
|
|
@ -1929,7 +1929,8 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
|
||||||
proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
|
proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
var dest = skipTypes(n.typ, abstractVar)
|
var dest = skipTypes(n.typ, abstractVar)
|
||||||
if optRangeCheck notin p.options:
|
if optRangeCheck notin p.options or (dest.kind in {tyUInt..tyUInt64} and
|
||||||
|
checkUnsignedConversions notin p.config.legacyFeatures):
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
putIntoDest(p, d, n, "(($1) ($2))" %
|
putIntoDest(p, d, n, "(($1) ($2))" %
|
||||||
[getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage)
|
[getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage)
|
||||||
|
|
|
||||||
|
|
@ -2155,7 +2155,10 @@ proc upConv(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
proc genRangeChck(p: PProc, n: PNode, r: var TCompRes, magic: string) =
|
proc genRangeChck(p: PProc, n: PNode, r: var TCompRes, magic: string) =
|
||||||
var a, b: TCompRes
|
var a, b: TCompRes
|
||||||
gen(p, n.sons[0], r)
|
gen(p, n.sons[0], r)
|
||||||
if optRangeCheck in p.options:
|
if optRangeCheck notin p.options or (skipTypes(n.typ, abstractVar).kind in {tyUInt..tyUInt64} and
|
||||||
|
checkUnsignedConversions notin p.config.legacyFeatures):
|
||||||
|
discard "XXX maybe emit masking instructions here"
|
||||||
|
else:
|
||||||
gen(p, n.sons[1], a)
|
gen(p, n.sons[1], a)
|
||||||
gen(p, n.sons[2], b)
|
gen(p, n.sons[2], b)
|
||||||
useMagic(p, "chckRange")
|
useMagic(p, "chckRange")
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,10 @@ type
|
||||||
## Allows to modify a NimNode where the type has already been
|
## Allows to modify a NimNode where the type has already been
|
||||||
## flagged with nfSem. If you actually do this, it will cause
|
## flagged with nfSem. If you actually do this, it will cause
|
||||||
## bugs.
|
## bugs.
|
||||||
|
checkUnsignedConversions
|
||||||
|
## Historically and especially in version 1.0.0 of the language
|
||||||
|
## conversions to unsigned numbers were checked. In 1.0.4 they
|
||||||
|
## are not anymore.
|
||||||
|
|
||||||
SymbolFilesOption* = enum
|
SymbolFilesOption* = enum
|
||||||
disabledSf, writeOnlySf, readOnlySf, v2Sf
|
disabledSf, writeOnlySf, readOnlySf, v2Sf
|
||||||
|
|
|
||||||
|
|
@ -434,15 +434,12 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
|
||||||
let dstTyp = skipTypes(n.typ, abstractRange - {tyTypeDesc})
|
let dstTyp = skipTypes(n.typ, abstractRange - {tyTypeDesc})
|
||||||
let srcTyp = skipTypes(a.typ, abstractRange - {tyTypeDesc})
|
let srcTyp = skipTypes(a.typ, abstractRange - {tyTypeDesc})
|
||||||
|
|
||||||
|
|
||||||
# if srcTyp.kind == tyUInt64 and "FFFFFF" in $n:
|
# if srcTyp.kind == tyUInt64 and "FFFFFF" in $n:
|
||||||
# echo "n: ", n, " a: ", a
|
# echo "n: ", n, " a: ", a
|
||||||
# echo "from: ", srcTyp, " to: ", dstTyp, " check: ", check
|
# echo "from: ", srcTyp, " to: ", dstTyp, " check: ", check
|
||||||
# echo getInt(a)
|
# echo getInt(a)
|
||||||
# echo high(int64)
|
# echo high(int64)
|
||||||
# writeStackTrace()
|
# writeStackTrace()
|
||||||
|
|
||||||
# XXX range checks?
|
|
||||||
case dstTyp.kind
|
case dstTyp.kind
|
||||||
of tyInt..tyInt64, tyUInt..tyUInt64:
|
of tyInt..tyInt64, tyUInt..tyUInt64:
|
||||||
case srcTyp.kind
|
case srcTyp.kind
|
||||||
|
|
@ -450,6 +447,7 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
|
||||||
result = newIntNodeT(toInt128(getFloat(a)), n, g)
|
result = newIntNodeT(toInt128(getFloat(a)), n, g)
|
||||||
of tyChar, tyUInt..tyUInt64, tyInt..tyInt64:
|
of tyChar, tyUInt..tyUInt64, tyInt..tyInt64:
|
||||||
var val = a.getOrdValue
|
var val = a.getOrdValue
|
||||||
|
|
||||||
if check: rangeCheck(n, val, g)
|
if check: rangeCheck(n, val, g)
|
||||||
result = newIntNodeT(val, n, g)
|
result = newIntNodeT(val, n, g)
|
||||||
if dstTyp.kind in {tyUInt..tyUInt64}:
|
if dstTyp.kind in {tyUInt..tyUInt64}:
|
||||||
|
|
|
||||||
|
|
@ -3188,6 +3188,7 @@ has lots of advantages:
|
||||||
|
|
||||||
Type conversions
|
Type conversions
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Syntactically a `type conversion` is like a procedure call, but a
|
Syntactically a `type conversion` is like a procedure call, but a
|
||||||
type name replaces the procedure name. A type conversion is always
|
type name replaces the procedure name. A type conversion is always
|
||||||
safe in the sense that a failure to convert a type to another
|
safe in the sense that a failure to convert a type to another
|
||||||
|
|
@ -3207,6 +3208,19 @@ A type conversion can also be used to disambiguate overloaded routines:
|
||||||
let procVar = (proc(x: string))(p)
|
let procVar = (proc(x: string))(p)
|
||||||
procVar("a")
|
procVar("a")
|
||||||
|
|
||||||
|
Since operations on unsigned numbers wrap around and are unchecked so are
|
||||||
|
type conversion to unsigned integers and between unsigned integers. The
|
||||||
|
rationale for this is mostly better interoperability with the C Programming
|
||||||
|
language when algorithms are ported from C to Nim.
|
||||||
|
|
||||||
|
Exception: Values that are converted to an unsigned type at compile time
|
||||||
|
are checked so that code like ``byte(-1)`` does not compile.
|
||||||
|
|
||||||
|
**Note**: Historically the operations
|
||||||
|
were unchecked and the conversions were sometimes checked but starting with
|
||||||
|
the revision 1.0.4 of this document and the language implementation the
|
||||||
|
conversions too are now *always unchecked*.
|
||||||
|
|
||||||
|
|
||||||
Type casts
|
Type casts
|
||||||
----------
|
----------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue