Open arnetheduck opened 1 week ago
Just
echo v.toOpenArray(0, -1)
The parameter type of first
, last
in toOpenArray[I, T](a: array[I, T], first, last: I)
is I
, not T
.
e.g. in your code var v: array[1, byte]
, the generic type I
is 0..0
(a slice of int
), so the type of first
, last
shall be of 0..0
instead of int8
.
Converting -1'i8
to 0..0
raises the error as shown above.
I wish the API had it so that the second argument was the length of the openarray, not the end index, that would probably make more sense for the construction of the openarray too since it stores the length. For the start/end index version we could have overloaded it for HSlice
instead.
It's not really needed to fix this issue but we could still add an overload like toOpenArrayLen[I, T](a: array[I, T], start: I, len: int)
, so we could instead do:
v.toOpenArrayLen(0'i8, 0)
the sanity ship of slice indexing in nim sailed, so we must do with what we have unfortunately.
an empty array is toOpenArray(0, -1)
because the second argument is inclusive and must therefore be -1
to point to the same location as the 0
- in particular, 0..0
is a slice of length 1.
int8
should promote to int
in all relevant aspects - this is a conversion bug.
it's a lot more dangerous at runtime:
var v: int
var v8: int8
var a: array[1, byte]
echo a.toOpenArray(v, v-1)
echo a.toOpenArray(v8, v8-1) # crashes here - obviously you should be able to use int8 like this.
@arnetheduck toOpenArray
works for this case because proc toOpenArray*[T](x: openArray[T]; first, last: int): openArray[T]
takes precedence when both ends are integer.
var v: int
var a: array[1, byte]
echo a.toOpenArray(v, v-1)
So when implementing a toOpenarray
function
proc toOpenArray2*[I, T](x: array[I, T]; first, last: I) =
echo x
proc foo =
var v: array[1, byte]
toOpenArray2(v, 0, -1)
foo()
It gives Error: conversion from int literal(-1) to range 0..0(int) is invalid
as expected
It gives Error: conversion from int literal(-1) to range 0..0(int) is invalid as expected
I'm not sure I understand your comment.
toOpenArray(0, -1)
is a valid slice over array[1, byte]
- in particular, it's the empty openarray.
toOpenArray(0'i8, -1'i8)
is also a valid slice range over array[1, byte]
- the same one. Both should work without compile-time error and/or crashes at runtime.
See https://play.nim-lang.org/#pasty=dAQERzuy
[]
/usercode/in.nim(6) in
/playground/nim/lib/system/fatal.nim(53) sysFatal
Error: unhandled exception: value out of range: -1 notin 0 .. 0 [RangeDefect]
we can see the empty openArray being printed, then the crash happening - it should have the same behavior regardless of int type.
I explained why this happens. I'm not saying the API is reasonable.
proc toOpenArray*[I, T](x: array[I, T]; first, last: I): openArray[T] {.
magic: "Slice".}
Isn't array[1, byte]
actually array[0..0, byte]
? So the type of first
and last
is range[0..0]
. It cannot accept -1
which is out of range. so toOpenArray(0'i8, -1'i8)
doesn't work since it can only match this one.
It is consistent with var x: range[0..0] = -1
.
toOpenArray(0, -1)
works because it matches proc toOpenArray*[T](x: openArray[T]; first, last: int): openArray[T]
instead of proc toOpenArray*[I, T](x: array[I, T]; first, last: I): openArray[T]
.
I think there is no type resolution bug here but the code generation for some variant of magic: "Slice"
is overly picky.
Description
at runtime, this crashes with a Defect (!)
Nim Version
2.0.6
Current Output
Expected Output
No response
Possible Solution
No response
Additional Information
No response