nim-works / nimskull

An in development statically typed systems programming language; with sustainability at its core. We, the community of users, maintain it.
https://nim-works.github.io/nimskull/index.html
Other
272 stars 38 forks source link

Static hint in Generic Type declaration failing to compile depending on order of type decls #1413

Open shayanhabibi opened 1 month ago

shayanhabibi commented 1 month ago

Example

type
  # INVALID                                                  v INVALID
  HyalosTracker*[T; N: static int] = ref HyalosTrackerObj[T, N] #<- type expected, but expression has no type
  HyalosTrackerObj*[T; N: static int] = object
# ...
# Valid if 'typeof N' used
  HyalosTracker*[T; N: static int] = ref HyalosTrackerObj[T, typeof N] # Valid
  HyalosTrackerObj*[T; N: static int] = object
# ...
# Valid if remove static hint/requirement
  HyalosTracker*[T; N: int] = ref HyalosTrackerObj[T, N] # Valid
  HyalosTrackerObj*[T; N: static int] = object
# ...
# Valid by reordering Obj decl before ref
  HyalosTrackerObj*[T; N: static int] = object # Valid
  HyalosTracker*[T; N: static int] = ref HyalosTrackerObj[T, N]

Additional Information

What is the accepted outcome in this situation?

Under previous main line versions, I am used to the first 'mostly' functioning. However, I don't understand why this would be valid:

type
# Valid if 'typeof N' used
  HyalosTracker*[T; N: static int] = ref HyalosTrackerObj[T, typeof N] # Valid
  HyalosTrackerObj*[T; N: static int] = object

If N is a compiletime literal I'm passing through the generic type to predetermine fields such as array sizes, then I would expect this of all to fail. As a disclaimer, this is what I would expect to happen from my shallow understanding. I will do some investigation to determine possible sources for this behaviour in the compiler but would like to understand what we view as being valid and what is invalid from the get go.

This can even be sidelined until static and generics are visited in depth in the compiler.

zerbina commented 1 month ago

What is the accepted outcome in this situation?

All cases except for the ref HyalosTrackerObj[T, typeof N] one should work. Whether typeof N itself should be allowed is not certain at this time, since whether tyStatic is a type or a value (or both) is still fuzzy, but using using typedesc[static int] as the argument to a generic parameter which is constrained to a static int is always wrong.

Under previous main line versions, I am used to the first 'mostly' functioning.

The code responsible for reporting an error has not changed since the fork happened. Using a recent-ish version of Nim, I also get the "type expected" error.


The fundamental reason why case 1 fails and case 2 (erroneously) succeeds is that when the ref HyalosTrackerObj type construction is analyzed, the compiler only knows that HylaosTrackerObj is a generic type, but not what its generic parameters are.

For forwarded generic types, the compiler makes the assumption that all generic parameters want types (see semtypes.nim:1729 for the code that handles this case), even if that turns out to be wrong, hence typeof N being accepted but not N (a static-constrained generic parameter cannot be used in a type/typedesc context).

If you were to swap the definitions in the typeof N case, the compiler would correctly report an error.