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

Macro returning static int in type section: intVal is not accessible for TFullReg #16774

Open
mratsim opened this issue Jan 20, 2021 · 3 comments

Comments

@mratsim
Copy link
Collaborator

mratsim commented Jan 20, 2021

When using a macro to compute the static int that parametrize a static type in a type section, we get

.....fatal.nim(53)            sysFatal
Error: unhandled exception: 'intVal' is not accessible using discriminant 'kind' of type 'TFullReg' [FieldDefect]

Test case

import macros

type SecretWord = distinct uint64
const WordBitWidth = 8 * sizeof(uint64)

func wordsRequired*(bits: int): int {.compileTime.} =
  ## Compute the number of limbs required
  # from the **announced** bit length
  (bits + WordBitWidth - 1) div WordBitWidth

type
  Curve = enum
    BLS12_381

  BigInt*[bits: static int] = object
    limbs*: array[bits.wordsRequired, SecretWord]

const BLS12_381_Modulus = default(BigInt[381])

{.experimental: "dynamicBindSym".}
macro Mod*(C: static Curve): untyped =
  ## Get the Modulus associated to a curve
  result = bindSym($C & "_Modulus")

macro getCurveBitwidth*(C: static Curve): untyped =
  result = nnkDotExpr.newTree(
    getAST(Mod(C)),
    ident"bits"
  )

type
  Fp*[C: static Curve] = object
    ## Finite Fields / Modular arithmetic
    ## modulo the curve modulus
    mres*: BigInt[getCurveBitwidth(C)]

var x: Fp[BLS12_381]
mratsim added a commit to mratsim/constantine that referenced this issue Jan 21, 2021
* Introduce Fr type: finite field over curve order. Need workaround for nim-lang/Nim#16774

* Split curve properties into core and derived

* Attach field properties to an instantiated field instead of the curve enum

* Workaround nim-lang/Nim#14021, yet another "working with types in macros" is difficult nim-lang/RFCs#44

* Implement finite field over prime order of a curve subgroup

* skip OpenSSL tests on windows
@timotheecour
Copy link
Member

@mratsim please minimize; note that #17590 fixes #14585 but not this issue, however it could very well be that a similar fix as #17590 would fix this too

@mratsim
Copy link
Collaborator Author

mratsim commented Apr 2, 2021

Come on, it's a single file with 37 lines. It's also the minimum translation of my data structure and what I attempted to do.

Given how distinct, static, symbol resolution/bindsym, generics, {.compileTime.} and types interact with each other and the useless error message, I think that's reasonable minimal reproducing example.

@can-lehmann
Copy link
Contributor

I tried to minimize this a bit more and obtained the following code:

import macros

macro makeIntLit(c: static int): untyped =
  result = newLit(c)

type Test*[T: static int] = object
  myArray: array[makeIntLit(T), int]

It turns out, that the compiler passes the NimNode "T" to makeIntLit, instead of an int. Therefore its register is of kind rkNode and the call to newLit fails. In the original example, the same thing happens: Instead of passing the enum value BLS12_381, the node "C" is passed to the Mod macro.

I see two ways to solve this:

  1. defer the macro expansion of macros with typed arguments until after generic instantiation (might break existing code, not sure how feasible this is)
  2. report an error that T is not a static value

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

3 participants