Skip to content

distinct borrow of generics + template in type section + macro type inference issue #23971

Open
@mratsim

Description

@mratsim

A similar starting point to #23784

The following confuses the type inference with the error

[...]/nim-2.0.8/lib/system.nim(700, 10) Error: invalid type: 'typeof(matchingBigInt(C))' in this context: 'proc (x: array[0..2, Fp[Fp3prj.C]]): int{.noSideEffect, gcsafe.}' for proc

Line 700 of system.nim in 2.0.8 corresponds to len of array

image

It seems like the signature func len*(x: (type array)|array): int is buggy with distinct type indirection.

import std/macros
import std/bitops

proc replaceNodes(ast: NimNode, what: NimNode, by: NimNode): NimNode =
  # Replace "what" ident node by "by"
  proc inspect(node: NimNode): NimNode =
    case node.kind:
    of {nnkIdent, nnkSym}:
      if node.eqIdent(what):
        return by
      return node
    of nnkEmpty:
      return node
    of nnkLiterals:
      return node
    else:
      var rTree = node.kind.newTree()
      for child in node:
        rTree.add inspect(child)
      return rTree
  result = inspect(ast)

macro staticFor*(idx: untyped{nkIdent}, start, stopEx: static int, body: untyped): untyped =
  result = newStmtList()
  for i in start ..< stopEx:
    result.add nnkBlockStmt.newTree(
      ident("unrolledIter_" & $idx & $i),
      body.replaceNodes(idx, newLit i))

# --------------------------------------------------------------

type Curve = enum
  BLS12_381

const WordBitWidth* = sizeof(uint64) * 8

func wordsRequired*(bits: int): int {.inline.} =
  const divShiftor = fastLog2(WordBitWidth)
  result = (bits + WordBitWidth - 1) shr divShiftor

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

# --------------------------------------------------------------

const CurveBitWidth = [
  BLS12_381: 381
]

template matchingBigInt*(Name: static Curve): untyped =
  ## BigInt type necessary to store the prime field Fp
  BigInt[CurveBitWidth[Name]]

type
  Fp[C: static Curve] = object
    residue: matchingBigInt(C)

type
  CubicExt*[F] = object
    ## Cubic Extension field
    coords*: array[3, F]

  Fp3[C: static Curve] = CubicExt[Fp[C]]

type
  Fp3prj[C: static Curve] {.borrow: `.`.} = distinct Fp3[C]

func `+=`*(a: var Fp, b: Fp) =
  for i in 0 ..< a.residue.limbs.len:
    a.residue.limbs[i] += b.limbs[i]

func `+=`*(a: var CubicExt, b: CubicExt) =
  ## Addition in the extension field
  staticFor i, 0, a.coords.len:
    a.coords[i] += b.coords[i]

# --------------------------------------------------------------

var a: Fp3prj[BLS12_381]
echo a.coords.len
echo a.coords[0].residue.limbs.len
# Up until there everything works

func `+=`*(a: var Fp3prj, b: Fp3prj) {.borrow.}
  # Comment this out and code compiles
  # Error is:
  #   Error: invalid type: 'typeof(matchingBigInt(C))'
  #   in this context: 'proc (x: array[0..2, Fp[Fp3prj.C]]): int{.noSideEffect, gcsafe.}' for proc
  #
  # The proc name isn't specified but it's `len` in system.nim which does type(array)|array

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions