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

fix generics treating symchoice symbols as uninstantiated #23860

Merged
merged 1 commit into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion compiler/semtypinst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,13 @@ proc prepareNode(cl: var TReplTypeVars, n: PNode): PNode =
else:
replaceTypeVarsS(cl, n.sym, replaceTypeVarsT(cl, n.sym.typ))
let isCall = result.kind in nkCallKinds
# don't try to instantiate symchoice symbols, they can be
# generic procs which the compiler will think are uninstantiated
# because their type will contain uninstantiated params
let isSymChoice = result.kind in nkSymChoices
for i in 0..<n.safeLen:
# XXX HACK: ``f(a, b)``, avoid to instantiate `f`
if isCall and i == 0: result.add(n[i])
if isSymChoice or (isCall and i == 0): result.add(n[i])
else: result.add(prepareNode(cl, n[i]))

proc isTypeParam(n: PNode): bool =
Expand Down
91 changes: 91 additions & 0 deletions tests/generics/t23853.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# issue #23853

block simplified:
type QuadraticExt[F] = object
coords: array[2, F]
template Name(E: type QuadraticExt): int = 123
template getBigInt(Name: static int): untyped = int
type Foo[GT] = object
a: getBigInt(GT.Name)
var x: Foo[QuadraticExt[int]]

import std/macros

type
Algebra* = enum
BN254_Snarks
BLS12_381

Fp*[Name: static Algebra] = object
limbs*: array[4, uint64]

QuadraticExt*[F] = object
## Quadratic Extension field
coords*: array[2, F]

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

ExtensionField*[F] = QuadraticExt[F] or CubicExt[F]

Fp2*[Name: static Algebra] =
QuadraticExt[Fp[Name]]

Fp4*[Name: static Algebra] =
QuadraticExt[Fp2[Name]]

Fp6*[Name: static Algebra] =
CubicExt[Fp2[Name]]

Fp12*[Name: static Algebra] =
CubicExt[Fp4[Name]]
# QuadraticExt[Fp6[Name]]

template Name*(E: type ExtensionField): Algebra =
E.F.Name

const BLS12_381_Order = [uint64 0x1, 0x2, 0x3, 0x4]
const BLS12_381_Modulus = [uint64 0x5, 0x6, 0x7, 0x8]


{.experimental: "dynamicBindSym".}

macro baseFieldModulus*(Name: static Algebra): untyped =
result = bindSym($Name & "_Modulus")

macro scalarFieldModulus*(Name: static Algebra): untyped =
result = bindSym($Name & "_Order")

type FieldKind* = enum
kBaseField
kScalarField

template getBigInt*(Name: static Algebra, kind: static FieldKind): untyped =
# Workaround:
# in `ptr UncheckedArray[BigInt[EC.getScalarField().bits()]]
# EC.getScalarField is not accepted by the compiler
#
# and `ptr UncheckedArray[BigInt[Fr[EC.F.Name].bits]]` gets undeclared field: 'Name'
#
# but `ptr UncheckedArray[getBigInt(EC.getName(), kScalarField)]` works fine
when kind == kBaseField:
Name.baseFieldModulus().typeof()
else:
Name.scalarFieldModulus().typeof()

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

type BenchMultiexpContext*[GT] = object
elems: seq[GT]
exponents: seq[getBigInt(GT.Name, kScalarField)]

proc createBenchMultiExpContext*(GT: typedesc, inputSizes: openArray[int]): BenchMultiexpContext[GT] =
discard

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

proc main() =
let ctx = createBenchMultiExpContext(Fp12[BLS12_381], [2, 4, 8, 16])

main()