Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@
errors for ambiguous type symbols, and macros operating on generic proc AST
may encounter symchoice nodes instead of the arbitrarily resolved type symbol nodes.

- With `-d:nimPreviewStrictVarRange`, variables of range types do not match
`var` parameters of their base type. This is to prevent implicit operations
that can cause values to escape their range, i.e.:

```nim
type Foo = range[0..5]
var foo: Foo = 5
proc double(x: var int) =
x = x * 2
double(foo)
echo foo # 10
```

will give a type mismatch error.

## Standard library additions and changes

[//]: # "Changes:"
Expand Down
17 changes: 15 additions & 2 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1017,9 +1017,22 @@ proc inferStaticsInRange(c: var TCandidate,
doInferStatic(lowerBound, getInt(upperBound) + 1 - lengthOrd(c.c.config, concrete))

template subtypeCheck() =
if result <= isSubrange and f.last.skipTypes(abstractInst).kind in {
tyRef, tyPtr, tyVar, tyLent, tyOwned}:
case result
of isIntConv:
result = isNone
of isSubrange:
if c.c.config.isDefined("nimPreviewStrictVarRange"):
result = isNone
of isConvertible:
if f.last.skipTypes(abstractInst).kind != tyOpenArray:
# exclude var openarray which compiler supports
result = isNone
of isSubtype:
if f.last.skipTypes(abstractInst).kind in {
tyRef, tyPtr, tyVar, tyLent, tyOwned}:
# compiler can't handle subtype conversions with pointer indirection
result = isNone
else: discard

proc isCovariantPtr(c: var TCandidate, f, a: PType): bool =
# this proc is always called for a pair of matching types
Expand Down
20 changes: 20 additions & 0 deletions lib/pure/json.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,8 @@ proc initFromJson[T](dst: var OrderedTable[string, T]; jsonNode: JsonNode; jsonP
proc initFromJson[T](dst: var ref T; jsonNode: JsonNode; jsonPath: var string)
proc initFromJson[T](dst: var Option[T]; jsonNode: JsonNode; jsonPath: var string)
proc initFromJson[T: distinct](dst: var T; jsonNode: JsonNode; jsonPath: var string)
when defined(nimPreviewStrictVarRange):
proc initFromJson[T: range](dst: var T; jsonNode: JsonNode; jsonPath: var string)
proc initFromJson[T: object|tuple](dst: var T; jsonNode: JsonNode; jsonPath: var string)

# initFromJson definitions
Expand Down Expand Up @@ -1224,6 +1226,24 @@ macro assignDistinctImpl[T: distinct](dst: var T;jsonNode: JsonNode; jsonPath: v
proc initFromJson[T: distinct](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
assignDistinctImpl(dst, jsonNode, jsonPath)

when defined(nimPreviewStrictVarRange):
# doesn't work without #24037
macro assignRangeImpl[T: range](dst: var T;jsonNode: JsonNode; jsonPath: var string) =
let typImpl = getTypeImpl(dst)
assert typImpl.kind == nnkBracketExpr and typImpl[0].eqIdent"range"
let lowNode =
if typImpl[^1].kind == nnkInfix:
typImpl[^1][1]
else:
typImpl[1]
let baseTyp = getType(lowNode)

result = quote do:
initFromJson(`baseTyp`(`dst`), `jsonNode`, `jsonPath`)

proc initFromJson[T: range](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
assignRangeImpl(dst, jsonNode, jsonPath)

proc detectIncompatibleType(typeExpr, lineinfoNode: NimNode) =
if typeExpr.kind == nnkTupleConstr:
error("Use a named tuple instead of: " & typeExpr.repr, lineinfoNode)
Expand Down
2 changes: 1 addition & 1 deletion lib/pure/unicode.nim
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ proc runeOffset*(s: openArray[char], pos: Natural, start: Natural = 0): int =
i = 0
o = start
while i < pos:
o += runeLenAt(s, o)
inc o, runeLenAt(s, o)
if o >= s.len:
return -1
inc i
Expand Down
4 changes: 2 additions & 2 deletions tests/errmsgs/t22097.nim
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
discard """
errormsg: "for a 'var' type a variable needs to be passed; but 'uint16(x)' is immutable"
errormsg: "type mismatch: got <uint8>"
"""

proc toUInt16(x: var uint16) =
discard

var x = uint8(1)
toUInt16 x
toUInt16 x
16 changes: 16 additions & 0 deletions tests/int/twrongexplicitvarconv.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
discard """
action: reject
nimout: '''
but expression 'int(a)' is immutable, not 'var'
'''
"""

proc `++`(n: var int) =
n += 1

var a: int32 = 15

++int(a) #[tt.Error
^ type mismatch: got <int>]#

echo a
9 changes: 9 additions & 0 deletions tests/int/twrongvarconv.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
proc `++`(n: var int) =
n += 1

var a: int32 = 15

++a #[tt.Error
^ type mismatch: got <int32>]#

echo a
2 changes: 1 addition & 1 deletion tests/iter/titer12.nim
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ proc filter[T](it: (iterator : T), f: proc(x: T): bool): (iterator : T) =

proc len[T](it : iterator : T) : Natural =
for i in it():
result += 1
result.inc 1

proc simpleSeqIterator(s :seq[int]) : iterator : int =
iterator it: int {.closure.} =
Expand Down
4 changes: 2 additions & 2 deletions tests/overflow/trangechecks.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ var expected: int
var x: range[1..10] = 10

try:
x += 1
inc x, 1
echo x
except OverflowDefect, RangeDefect:
expected += 1
Expand All @@ -27,7 +27,7 @@ except OverflowDefect, RangeDefect:

x = 1
try:
x -= 1
dec x, 1
echo x
except OverflowDefect, RangeDefect:
expected += 1
Expand Down
18 changes: 18 additions & 0 deletions tests/range/twrongvarconv.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
discard """
matrix: "-d:nimPreviewStrictVarRange"
"""

# issue #24032

proc `++`(n: var int) =
n += 1

type
r = range[ 0..15 ]

var a: r = 15

++a #[tt.Error
^ type mismatch: got <r>]#

echo a
Loading