Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't create empty openArray with int8 #23752

Open
arnetheduck opened this issue Jun 21, 2024 · 8 comments
Open

Can't create empty openArray with int8 #23752

arnetheduck opened this issue Jun 21, 2024 · 8 comments

Comments

@arnetheduck
Copy link
Contributor

Description

var v: array[1, byte]

echo v.toOpenArray(0'i8, -1'i8)

at runtime, this crashes with a Defect (!)

Nim Version

2.0.6

Current Output

Error: conversion from int8 to range 0..0(int) is invalid

Expected Output

No response

Possible Solution

No response

Additional Information

No response

@litlighilit
Copy link
Contributor

litlighilit commented Jun 22, 2024

Just

echo v.toOpenArray(0, -1)

@litlighilit
Copy link
Contributor

litlighilit commented Jun 22, 2024

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.

@metagn
Copy link
Collaborator

metagn commented Jun 22, 2024

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)

@arnetheduck
Copy link
Contributor Author

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.

@ringabout ringabout assigned ringabout and unassigned ringabout Jun 25, 2024
@ringabout
Copy link
Member

ringabout commented Jun 25, 2024

@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

@arnetheduck
Copy link
Contributor Author

arnetheduck commented Jun 25, 2024

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.

@ringabout
Copy link
Member

ringabout commented Jun 25, 2024

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].

@Araq
Copy link
Member

Araq commented Jun 25, 2024

I think there is no type resolution bug here but the code generation for some variant of magic: "Slice" is overly picky.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants