mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
* fixes #22613; Default value does not work with object's discriminator fixes #22613 * merge branches * add a test case * fixes status * remove outdated comments * move collectBranchFields into the global scope
723 lines
14 KiB
Nim
723 lines
14 KiB
Nim
discard """
|
|
matrix: "-d:nimPreviewRangeDefault --mm:refc; -d:nimPreviewRangeDefault --warningAsError:ProveInit --mm:orc"
|
|
targets: "c cpp js"
|
|
"""
|
|
|
|
import std/[times, macros, tables]
|
|
|
|
type
|
|
Guess = object
|
|
poi: DateTime
|
|
|
|
GuessDistinct = distinct Guess
|
|
|
|
block:
|
|
var x: Guess
|
|
discard Guess()
|
|
|
|
var y: GuessDistinct
|
|
|
|
discard y
|
|
|
|
discard GuessDistinct(x)
|
|
|
|
|
|
import mobject_default_value
|
|
|
|
block:
|
|
let x = Default()
|
|
doAssert x.se == 0'i32
|
|
|
|
block:
|
|
let x = default(Default)
|
|
doAssert x.se == 0'i32
|
|
# echo Default(poi: 12)
|
|
# echo Default(poi: 17)
|
|
|
|
# echo NonDefault(poi: 77)
|
|
|
|
block:
|
|
var x: Default
|
|
doAssert x.se == 0'i32
|
|
|
|
type
|
|
ObjectBase = object of RootObj
|
|
value = 12
|
|
|
|
ObjectBaseDistinct = distinct ObjectBase
|
|
|
|
DinstinctInObject = object
|
|
data: ObjectBaseDistinct
|
|
|
|
Object = object of ObjectBase
|
|
time: float = 1.2
|
|
date: int
|
|
scale: range[1..10]
|
|
|
|
Object2 = object
|
|
name: Object
|
|
|
|
Object3 = object
|
|
obj: Object2
|
|
|
|
ObjectTuple = tuple
|
|
base: ObjectBase
|
|
typ: int
|
|
obj: Object
|
|
|
|
TupleInObject = object
|
|
size = 777
|
|
data: ObjectTuple
|
|
|
|
Ref = ref object of ObjectBase
|
|
|
|
RefInt = ref object of Ref
|
|
data = 73
|
|
|
|
Ref2 = ref object of ObjectBase
|
|
|
|
RefInt2 = ref object of Ref
|
|
data = 73
|
|
|
|
var t {.threadvar.}: Default
|
|
# var m1, m2 {.threadvar.}: Default
|
|
|
|
block:
|
|
doAssert t.se == 0'i32
|
|
|
|
block: # ARC/ORC cannot bind destructors twice, so it cannot
|
|
# be moved into main
|
|
block:
|
|
var x: Ref
|
|
new(x)
|
|
doAssert x.value == 12, "Ref.value = " & $x.value
|
|
|
|
var y: RefInt
|
|
new(y)
|
|
doAssert y.value == 12
|
|
doAssert y.data == 73
|
|
|
|
block:
|
|
var x: Ref2
|
|
new(x, proc (x: Ref2) {.nimcall.} = discard "call Ref")
|
|
doAssert x.value == 12, "Ref.value = " & $x.value
|
|
|
|
proc call(x: RefInt2) =
|
|
discard "call RefInt"
|
|
|
|
var y: RefInt2
|
|
new(y, call)
|
|
doAssert y.value == 12
|
|
doAssert y.data == 73
|
|
|
|
template main {.dirty.} =
|
|
block: # bug #16744
|
|
type
|
|
R = range[1..10]
|
|
Obj = object
|
|
r: R
|
|
|
|
var
|
|
rVal: R = default(R) # Works fine
|
|
objVal = default(Obj)
|
|
|
|
doAssert rVal == 0 # it should be 1
|
|
doAssert objVal.r == 1
|
|
|
|
block: # bug #16744
|
|
type
|
|
R = range[1..10]
|
|
Obj = object
|
|
r: R
|
|
|
|
var
|
|
rVal: R = default(R) # Works fine
|
|
objVal = Obj()
|
|
|
|
doAssert rVal == 0 # it should be 1
|
|
doAssert objVal.r == 1
|
|
|
|
block: # bug #3608
|
|
type
|
|
abc = ref object
|
|
w: range[2..100]
|
|
|
|
proc createABC(): abc =
|
|
new(result)
|
|
result.w = 20
|
|
|
|
doAssert createABC().w == 20
|
|
|
|
block:
|
|
var x = new ObjectBase
|
|
doAssert x.value == 12
|
|
|
|
proc hello(): ref ObjectBase =
|
|
new result
|
|
|
|
let z = hello()
|
|
doAssert z.value == 12
|
|
|
|
block:
|
|
var base = ObjectBase()
|
|
var x: ObjectBaseDistinct = ObjectBaseDistinct(base)
|
|
doAssert ObjectBase(x).value == 12
|
|
let y = ObjectBaseDistinct(default(ObjectBase))
|
|
doAssert ObjectBase(y).value == 12
|
|
|
|
let m = ObjectBaseDistinct(ObjectBase())
|
|
doAssert ObjectBase(m).value == 12
|
|
|
|
proc hello(): ObjectBaseDistinct =
|
|
result = ObjectBaseDistinct(default(ObjectBase))
|
|
|
|
let z = hello()
|
|
doAssert ObjectBase(z).value == 12
|
|
|
|
block:
|
|
var x: DinstinctInObject
|
|
x.data = ObjectBaseDistinct(default(ObjectBase))
|
|
|
|
doAssert ObjectBase(x.data).value == 12
|
|
|
|
block:
|
|
var x = Object()
|
|
doAssert x.value == 12
|
|
doAssert x.time == 1.2
|
|
doAssert x.scale == 1
|
|
|
|
let y = default(Object)
|
|
doAssert y.value == 12
|
|
doAssert y.time == 1.2
|
|
doAssert y.scale == 1
|
|
|
|
var x1, x2, x3 = default(Object)
|
|
doAssert x1.value == 12
|
|
doAssert x1.time == 1.2
|
|
doAssert x1.scale == 1
|
|
doAssert x2.value == 12
|
|
doAssert x2.time == 1.2
|
|
doAssert x2.scale == 1
|
|
doAssert x3.value == 12
|
|
doAssert x3.time == 1.2
|
|
doAssert x3.scale == 1
|
|
|
|
block:
|
|
var x = new Object
|
|
doAssert x[] == default(Object)
|
|
|
|
block:
|
|
var x = default(Object2)
|
|
doAssert x.name.value == 12
|
|
doAssert x.name.time == 1.2
|
|
doAssert x.name.scale == 1
|
|
|
|
block:
|
|
let x = Object2()
|
|
doAssert x.name.value == 12
|
|
doAssert x.name.time == 1.2
|
|
doAssert x.name.scale == 1
|
|
|
|
block:
|
|
var x: ref Object2
|
|
new x
|
|
doAssert x[] == default(Object2)
|
|
|
|
block:
|
|
var x = default(Object3)
|
|
doAssert x.obj.name.value == 12
|
|
doAssert x.obj.name.time == 1.2
|
|
doAssert x.obj.name.scale == 1
|
|
|
|
block:
|
|
var x = Object3()
|
|
doAssert x.obj.name.value == 12
|
|
doAssert x.obj.name.time == 1.2
|
|
doAssert x.obj.name.scale == 1
|
|
|
|
when nimvm:
|
|
# todo
|
|
discard "fixme"
|
|
else:
|
|
when defined(gcArc) or defined(gcOrc):
|
|
block: #seq
|
|
var x = newSeq[Object](10)
|
|
let y = x[0]
|
|
doAssert y.value == 12
|
|
doAssert y.time == 1.2
|
|
doAssert y.scale == 1
|
|
|
|
block:
|
|
var x: seq[Object]
|
|
setLen(x, 5)
|
|
let y = x[^1]
|
|
doAssert y.value == 12
|
|
doAssert y.time == 1.2
|
|
doAssert y.scale == 1
|
|
|
|
block:
|
|
var my = @[1, 2, 3, 4, 5]
|
|
my.setLen(0)
|
|
my.setLen(5)
|
|
doAssert my == @[0, 0, 0, 0, 0]
|
|
|
|
block:
|
|
var my = "hello"
|
|
my.setLen(0)
|
|
my.setLen(5)
|
|
doAssert $(@my) == """@['\x00', '\x00', '\x00', '\x00', '\x00']"""
|
|
|
|
block: # array
|
|
var x: array[10, Object] = default(array[10, Object])
|
|
let y = x[0]
|
|
doAssert y.value == 12
|
|
doAssert y.time == 1.2
|
|
doAssert y.scale == 1
|
|
|
|
block: # array
|
|
var x {.noinit.}: array[10, Object]
|
|
discard x
|
|
|
|
block: # tuple
|
|
var x = default(ObjectTuple)
|
|
doAssert x.base.value == 12
|
|
doAssert x.typ == 0
|
|
doAssert x.obj.time == 1.2
|
|
doAssert x.obj.date == 0
|
|
doAssert x.obj.scale == 1
|
|
doAssert x.obj.value == 12
|
|
|
|
block: # tuple in object
|
|
var x = default(TupleInObject)
|
|
doAssert x.data.base.value == 12
|
|
doAssert x.data.typ == 0
|
|
doAssert x.data.obj.time == 1.2
|
|
doAssert x.data.obj.date == 0
|
|
doAssert x.data.obj.scale == 1
|
|
doAssert x.data.obj.value == 12
|
|
doAssert x.size == 777
|
|
|
|
type
|
|
ObjectArray = object
|
|
data: array[10, Object]
|
|
|
|
block:
|
|
var x = default(ObjectArray)
|
|
let y = x.data[0]
|
|
doAssert y.value == 12
|
|
doAssert y.time == 1.2
|
|
doAssert y.scale == 1
|
|
|
|
block:
|
|
var x: PrellDeque[int]
|
|
doAssert x.pendingTasks == 0
|
|
|
|
type
|
|
Color = enum
|
|
Red, Blue, Yellow
|
|
|
|
ObjectVarint = object
|
|
case kind: Color
|
|
of Red:
|
|
data: int = 10
|
|
of Blue:
|
|
fill = "123"
|
|
of Yellow:
|
|
time = 1.8'f32
|
|
|
|
ObjectVarint1 = object
|
|
case kind: Color = Blue
|
|
of Red:
|
|
data1: int = 10
|
|
of Blue:
|
|
fill2 = "123"
|
|
cry: float
|
|
of Yellow:
|
|
time3 = 1.8'f32
|
|
him: int
|
|
|
|
block:
|
|
var x = ObjectVarint(kind: Red)
|
|
doAssert x.kind == Red
|
|
doAssert x.data == 10
|
|
|
|
block:
|
|
var x = ObjectVarint(kind: Blue)
|
|
doAssert x.kind == Blue
|
|
doAssert x.fill == "123"
|
|
|
|
block:
|
|
var x = ObjectVarint(kind: Yellow)
|
|
doAssert x.kind == Yellow
|
|
doAssert typeof(x.time) is float32
|
|
|
|
block:
|
|
var x = default(ObjectVarint1)
|
|
doAssert x.kind == Blue
|
|
doAssert x.fill2 == "123"
|
|
x.cry = 326
|
|
|
|
type
|
|
ObjectVarint2 = object
|
|
case kind: Color
|
|
of Red:
|
|
data: int = 10
|
|
of Blue:
|
|
fill = "123"
|
|
of Yellow:
|
|
time = 1.8'f32
|
|
|
|
block:
|
|
var x = ObjectVarint2(kind: Blue)
|
|
doAssert x.fill == "123"
|
|
|
|
block:
|
|
type
|
|
Color = enum
|
|
Red, Blue, Yellow
|
|
|
|
type
|
|
ObjectVarint3 = object
|
|
case kind: Color = Blue
|
|
of Red:
|
|
data1: int = 10
|
|
of Blue:
|
|
case name: Color = Blue
|
|
of Blue:
|
|
go = 12
|
|
else:
|
|
temp = 66
|
|
fill2 = "123"
|
|
cry: float
|
|
of Yellow:
|
|
time3 = 1.8'f32
|
|
him: int
|
|
|
|
block:
|
|
var x = default(ObjectVarint3)
|
|
doAssert x.kind == Blue
|
|
doAssert x.name == Blue
|
|
doAssert x.go == 12
|
|
|
|
block:
|
|
var x = ObjectVarint3(kind: Blue, name: Red, temp: 99)
|
|
doAssert x.kind == Blue
|
|
doAssert x.name == Red
|
|
doAssert x.temp == 99
|
|
|
|
block:
|
|
type
|
|
Default = tuple
|
|
id: int = 1
|
|
obj: ObjectBase
|
|
name: string
|
|
|
|
Class = object
|
|
def: Default
|
|
|
|
Member = object
|
|
def: Default = (id: 777, obj: ObjectBase(), name: "fine")
|
|
|
|
block:
|
|
var x = default(Default)
|
|
doAssert x.id == 1
|
|
doAssert x.obj == default(ObjectBase)
|
|
doAssert x.name == ""
|
|
|
|
block:
|
|
var x = default(Class)
|
|
doAssert x.def == default(Default)
|
|
doAssert x.def.id == 1
|
|
doAssert x.def.obj == default(ObjectBase)
|
|
doAssert x.def.name == ""
|
|
|
|
block:
|
|
var x = default(Member)
|
|
doAssert x.def.id == 777
|
|
doAssert x.def.obj == default(ObjectBase)
|
|
doAssert x.def.name == "fine"
|
|
|
|
block:
|
|
var x {.noinit.} = 12
|
|
doAssert x == 12
|
|
|
|
type
|
|
Pure = object
|
|
id: int = 12
|
|
|
|
var y {.noinit.}: Pure
|
|
doAssert y.id == 0
|
|
|
|
var z {.noinit.}: Pure = Pure(id: 77)
|
|
doAssert z.id == 77
|
|
|
|
block: # bug #20681
|
|
type A = object
|
|
d: DateTime = DateTime()
|
|
|
|
let x = default(A)
|
|
doAssert $x == "(d: Uninitialized DateTime)"
|
|
|
|
block: # bug #20715
|
|
block:
|
|
type
|
|
Foo = enum
|
|
A
|
|
B
|
|
|
|
Bar = object
|
|
case foo: Foo
|
|
of A:
|
|
t: range[-1..2]
|
|
else: discard
|
|
|
|
var d = default(Bar)
|
|
doAssert d.t == -1
|
|
|
|
block:
|
|
type
|
|
Foo = enum
|
|
A
|
|
B
|
|
|
|
Bar = object
|
|
case foo: Foo
|
|
of A:
|
|
t: range[0..2]
|
|
else: discard
|
|
|
|
var d = default(Bar)
|
|
doAssert d.t == 0
|
|
|
|
block: # bug #20740
|
|
block:
|
|
proc foo(x: static DateTime = Datetime()) =
|
|
discard
|
|
|
|
foo()
|
|
|
|
block:
|
|
macro foo(x: static DateTime) =
|
|
discard x
|
|
|
|
macro foo2: untyped =
|
|
var x = DateTime()
|
|
|
|
result = quote do:
|
|
foo(`x`)
|
|
|
|
foo2()
|
|
|
|
|
|
block: # issue #20699
|
|
type
|
|
Either[A,B] = object
|
|
case kind:bool
|
|
of false:
|
|
b: B
|
|
of true:
|
|
a: A
|
|
O = object of RootRef
|
|
|
|
proc oToEither(o:O):Either[O,void] =
|
|
Either[O,void](kind:true,a: o)
|
|
|
|
discard oToEither(O())
|
|
|
|
block: # bug #20695
|
|
type
|
|
Default = object
|
|
tabs: Table[string, int] = initTable[string, int]()
|
|
|
|
let d = default(Default)
|
|
doAssert d.tabs.len == 0
|
|
|
|
block:
|
|
type
|
|
Default = object
|
|
tabs: Table[string, int] = Table[string, int]()
|
|
|
|
let d = default(Default)
|
|
doAssert d.tabs.len == 0
|
|
|
|
|
|
block:
|
|
type DjangoDateTime = distinct DateTime
|
|
|
|
type Default = object
|
|
data: DjangoDateTime = DjangoDateTime(DateTime())
|
|
|
|
let x = default(Default)
|
|
doAssert x.data is DjangoDateTime
|
|
|
|
block:
|
|
type DjangoDateTime = distinct DateTime
|
|
|
|
type Default = object
|
|
data = DjangoDateTime(DateTime())
|
|
|
|
let x = default(Default)
|
|
doAssert x.data is DjangoDateTime
|
|
|
|
block:
|
|
type
|
|
Result2 = object
|
|
case o: bool
|
|
of false:
|
|
e: float
|
|
of true:
|
|
v {.requiresInit.} : int = 1
|
|
|
|
proc startSessionSync(): Result2 =
|
|
return Result2(o: true)
|
|
|
|
proc mainSync =
|
|
let ff = startSessionSync()
|
|
doAssert ff.v == 1
|
|
|
|
mainSync()
|
|
|
|
block:
|
|
type
|
|
Result2 = object
|
|
v {.requiresInit.} : int = 1
|
|
|
|
proc startSessionSync(): Result2 =
|
|
return Result2()
|
|
|
|
proc mainSync =
|
|
let ff = startSessionSync()
|
|
doAssert ff.v == 1
|
|
|
|
mainSync()
|
|
|
|
block: # bug #21801
|
|
func evaluate(i: int): float =
|
|
0.0
|
|
|
|
func evaluate(): float =
|
|
0.0
|
|
|
|
type SearchOptions = object
|
|
evaluation: proc(): float = evaluate
|
|
|
|
block:
|
|
func evaluate(): float =
|
|
0.0
|
|
|
|
type SearchOptions = object
|
|
evaluation: proc(): float = evaluate
|
|
|
|
block:
|
|
func evaluate(i: int): float =
|
|
0.0
|
|
|
|
type SearchOptions = object
|
|
evaluation = evaluate
|
|
block:
|
|
type
|
|
Result[T, E] = object
|
|
when T is void:
|
|
when E is void:
|
|
oResultPrivate: bool
|
|
else:
|
|
case oResultPrivate: bool
|
|
of false:
|
|
eResultPrivate: E
|
|
of true:
|
|
discard
|
|
else:
|
|
when E is void:
|
|
case oResultPrivate: bool
|
|
of false:
|
|
discard
|
|
of true:
|
|
vResultPrivate: T
|
|
else:
|
|
case oResultPrivate: bool
|
|
of false:
|
|
eResultPrivate: E
|
|
of true:
|
|
vResultPrivate: T
|
|
|
|
|
|
template `?`[T, E](self: Result[T, E]): auto =
|
|
let v = (self)
|
|
if not v.oResultPrivate:
|
|
when compiles(`assignResult?`(default(typeof(result)))):
|
|
when typeof(result) is typeof(v):
|
|
`assignResult?`(v)
|
|
elif E is void:
|
|
`assignResult?`(err(typeof(result)))
|
|
else:
|
|
`assignResult?`(err(typeof(result), v.eResultPrivate))
|
|
return
|
|
else:
|
|
return
|
|
when typeof(result) is typeof(v):
|
|
v
|
|
elif E is void:
|
|
err(typeof(result))
|
|
else:
|
|
err(typeof(result), v.eResultPrivate)
|
|
|
|
when not(T is void):
|
|
v.vResultPrivate
|
|
|
|
type R = Result[int, string]
|
|
|
|
proc testAssignResult() =
|
|
var assigned: bool
|
|
template `assignResult?`(v: Result) =
|
|
assigned = true
|
|
result = v
|
|
|
|
proc failed(): Result[int, string] =
|
|
discard
|
|
|
|
proc calling(): Result[int, string] =
|
|
let _ = ? failed()
|
|
doAssert false
|
|
|
|
let r = calling()
|
|
doAssert assigned
|
|
|
|
when nimvm:
|
|
when not defined(js):
|
|
testAssignResult()
|
|
else:
|
|
testAssignResult()
|
|
|
|
block: # bug #22123
|
|
type Thing = object
|
|
x: float32 = 1
|
|
|
|
type ThingWithArray = object
|
|
arr: array[256, float32]
|
|
n: float32 = 1
|
|
|
|
type Container = ref object
|
|
thing: array[5, Thing]
|
|
thing_with_array: array[5, ThingWithArray]
|
|
|
|
var foo = new Container
|
|
doAssert int(foo.thing[0].x) == 1
|
|
|
|
block: # bug #22613
|
|
type
|
|
K = enum
|
|
A = "a"
|
|
B = "b"
|
|
T = object
|
|
case kind: K = B
|
|
of A:
|
|
a: int
|
|
of B:
|
|
b: float
|
|
|
|
doAssert T().kind == B
|
|
|
|
|
|
static: main()
|
|
main()
|