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

Static + when: Cannot generate code #7378

Open
mratsim opened this issue Mar 20, 2018 · 5 comments
Open

Static + when: Cannot generate code #7378

mratsim opened this issue Mar 20, 2018 · 5 comments

Comments

@mratsim
Copy link
Collaborator

mratsim commented Mar 20, 2018

This is an alternative approach due to the problem in #7230.
This might be solved by PR #7333.

The proc fails_always will trigger "Cannot generate code for: bits" as soon as it is uncommented.
The proc fails_if_called triggers the same error if called.

type
  MpUint*[bits: static[int]] = object
    when system.cpuEndian == littleEndian:
      when bits == 128: lo*, hi*: uint64
      elif bits ==  64: lo*, hi*: uint32
      elif bits ==  32: lo*, hi*: uint16
      elif bits ==  16: lo*, hi*: uint8
      else:
        lo*, hi*: MpUint[bits div 2]
    else:
      when bits == 128: hi*, lo*: uint64
      elif bits ==  64: hi*, lo*: uint32
      elif bits ==  32: hi*, lo*: uint16
      elif bits ==  16: hi*, lo*: uint8
      else:
        hi*, lo*: MpUint[bits div 2]


proc toMpUint*(n: uint16): MpUint[16] =
  cast[type result](n)

let a = 10'u16
var b = a.toMpUint()


## uncomment the following for failure
# proc fails_always(x: MpUint, y: MpUint) =
#   echo x
# Error: cannot generate code for: bits

proc fails_if_called*[bits: static[int]](x: MpUint[bits], y: MpUint[bits]) =
  echo x

## uncomment the following for failure
# fails_if_called(b, b) # Error: cannot generate code for: bits

Edit: calling like this works:

fails_if_called[16](b, b) # This works but we shouldn't have to tell the size each time
@mratsim
Copy link
Collaborator Author

mratsim commented Mar 20, 2018

Further investigation shows that the issue is actually with when + static and that macros are not related:

type
  BaseUint* = SomeUnsignedInt or MpUintBase

  MpUintBase*[BaseUint] = object
      lo*, hi*: BaseUint

type
  # works
  Foo*[bits: static[int]] = (
    when true:
      MpUintBase[uint64]
    )

type
  # Cannot generate bits
  Bar*[bits: static[int]] = (
    when bits == 128: # Error points to the bits here
       MpUintBase[uint64]
    )

@mratsim mratsim changed the title Macro + Static + when: Cannot generate code Static + when: Cannot generate code Mar 20, 2018
@ghost ghost added the Static[T] label Mar 20, 2018
@LemonBoy
Copy link
Contributor

This is not much of an issue with static[T] but rather with how the compiler works: the when is evaluated when the whole TypeSection goes trough the semantic pass and at that time the bits parameter is still not bound.
I guess the snippet above isn't supposed to work.

@zah
Copy link
Member

zah commented Jun 25, 2018

The snippet should work. In general, the semTypeNode processing in typeSectionRightSidePass is just a preliminary pass when it comes to generic types. There is a second pass that will resolve all unknowns in semtypinst.nim.

@cheatfate
Copy link
Member

cheatfate commented Jul 4, 2018

The snippet should work but it is not working, here one more sample which are not working:

type
  Blake2Context*[bits: static[int]] = object
    when bits == 384 or bits == 512:
      b: array[128, byte]
      h: array[8, uint64]
      t: array[2, uint64]
      c: int
    elif bits == 224 or bits == 256:
      b: array[64, byte]
      h: array[8, uint32]
      t: array[2, uint32]
      c: int

  blake2_224* = Blake2Context[224]
  blake2_256* = Blake2Context[256]
  blake2_384* = Blake2Context[384]
  blake2_512* = Blake2Context[512]

proc init*[bits: static[int]](ctx: var Blake2Context[bits],
                              key: openarray[char]) {.inline.} =
  discard

when isMainModule:
  var c0: blake2_512
  c0.init("abc")
  var c1: blake2_224
  c1.init("abc")

@LemonBoy
Copy link
Contributor

LemonBoy commented Sep 2, 2018

The problem in @cheatfate snippet is harder to solve since c0.init("abc") tries to initialize the formal type Blake2Context[bits] but without the bits parameter bound yet. We may solve the problem by stealing the argument template parameters in prepareMetatypeForSigmatch or something else, I couldn't come up with a valid plan yet.

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

No branches or pull requests

4 participants