Nim: [TODO] should `proc foo[N](dims: array[N, int])` be illegal? it causes issues

Created on 22 Dec 2018  路  9Comments  路  Source: nim-lang/Nim

not 100% sure but I'm guessing proc foo[N](dims: array[N, int]) should be illegal since N isn't a type, instead should be:

when true:
  block:
    proc foo[N: static int](dims: array[N, int])= # should that be legal?
      ...

accepting it leads to further issues:

Example

when true:
  block:
    proc foo[N](dims: array[N, int])= # should that be legal?
      const N1 = N
      # let temp = N # Error: 'typedesc' metatype is not valid here; typed '=' instead of ':'?
      let temp2 = (a:N) # Error: internal error: expr(skType); unknown symbol

    foo([1, 2])

Current Output

See above

proposal

  • give CT error for proc foo[N](dims: array[N, int]) (if it should be considered legal, then please explain https://github.com/nim-lang/Nim/issues/10074#issuecomment-449624687)
  • update this section in spec /cc @araq :
    https://nim-lang.github.io/Nim/manual.html#generics-generic-inference-restrictions
Generics Static[T]

Most helpful comment

Besides the discussions, there are indeed some issues listed here. As far as I know, they are not duplicates of other issues, so we can keep this open.

All 9 comments

Then how could it accept foo[1..10](array), which is a totally valid array index type? How about enums also?

if it were legal, it'd be inconsistent with behavior in following code:

  type Foo[D] = object # Error: cannot instantiate Foo
  # type Foo[D: static int] = object # works
    arr: array[D, float]
  type Foo2 = Foo[2]
  echo Foo2()

Then how could it accept foo1..10, which is a totally valid array index type? How about enums also?

  • for enum:
when defined(case5d):
  type Bar = enum
    a1, a2, a3
  type Foo[D: enum] = object
    arr: array[D, float]
  var t: array[Bar, float]=[1.0,2.0,3.0]
  type Foo2 = Foo[Bar]
  • for foo1..10:
    I have no idea, maybe @Araq knows?
when defined(case5c):
  import typetraits
  type Foo[D: Slice[int]] = object
    arr: array[D, float]
  var t: array[10..11, float]=[1.0,2.0]
  static: echo type(t) #array[10..11, float]
  type Foo2 = Foo[10..11] # Error: cannot instantiate Foo

Note that we have iterators such as this:

https://github.com/nim-lang/Nim/blob/d407af565f164a2182e9d72fa69d1263cd7b3f9f/lib/system.nim#L2370

and proc like this:

https://github.com/nim-lang/Nim/blob/d407af565f164a2182e9d72fa69d1263cd7b3f9f/lib/system.nim#L3636

all of which depend on the feature you'd like to make illegal.

if it were legal, it'd be inconsistent with behavior in following code:

  type Foo[D] = object # Error: cannot instantiate Foo
  # type Foo[D: static int] = object # works
    arr: array[D, float]
  type Foo2 = Foo[2]
  echo Foo2()

Then shouldn't that be fixed, or am I missing something here? Because AFAICT generics instantiation is more or less similar to a template instantiation

I'm not necessarily saying we should make it illegal, but there's clearly inconsistencies, as shown above:

When you don't specify the kind of the generic parameter, the compiler will try to infer it from the rest of the signature. In the compiler internals, this is represented by the tfWildcard flag. Something like this should work:

proc foo[N](dims: SomeGenericTypeWithStaticParam[N])

The array type is a bit more complicated, because internally it has a canonical representation using a range type that determines the size of the array (e.g. array[10, int] is equivalent to array[range[0..9], int]). This "duality" of the array type has been a source of many bugs in the past and it does complicate the picture for the user a bit as demonstrated here.

This is not really an issue it is more a question and therefore it belongs in the forum or the chat. Not the issue tracker. proc foo[N](dims: array[N, int]) is clearly legal Nim. All arrays have a type argument for the size (usually a range from 0 to N), not a integer. It is just that you can use integer litersal as well, but they are treated as syntactic sugar, not the other way around.

/cc @krux02 @zah

This is not really an issue

it is, and it's fixable: see top-post that gives:
Error: internal error: expr(skType); unknown symbol

if proc foo[N](dims: array[N, int]) is staying legal in Nim, compiler should give a helpful error when accessing N, eg instead of:

# let temp = N # Error: 'typedesc' metatype is not valid here; typed '=' instead of ':'?
# let temp2 = (a:N) # Error: internal error: expr(skType); unknown symbol

it could give:

# let temp = N # Error: use `const` when accessing a static param
# let temp2 = (a:N) # Error: use `const` when accessing a static param

Besides the discussions, there are indeed some issues listed here. As far as I know, they are not duplicates of other issues, so we can keep this open.

@zah yes there are issues listed here in the discussion. But this issue is not the right place to discuss them. This issue is "should proc foo[N](dims: array[N, int]) be illegal?" and the answer is "No". And I also explained why Foo[2] doesn't compile. 2 is not a type, it is just allowed in array types, here it is an alias to the 0..1 type. So when there are issues left they should be addrassed in their own issue. For example like I did here: https://github.com/nim-lang/Nim/issues/10185

Was this page helpful?
0 / 5 - 0 ratings