diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 634e00b595020..dfb17c5c59b80 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -704,10 +704,6 @@ proc semResolvedCall(c: PContext, x: var TCandidate, else: # For macros and templates, the resolved generic params # are added as normal params. - # This is not done with unresolved static arguments, as typed macros - # cannot be instantiated yet and semMacroExpr/semTemplateExpr will - # reject them and delay their instantiation, when fully resolved types - # will be added instead. c.inheritBindings(x, expectedType) for s in instantiateGenericParamList(c, gp, x.bindings): case s.kind diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 6b70f7fd026a3..a22764817f0b4 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1500,7 +1500,7 @@ proc tryReadingGenericParam(c: PContext, n: PNode, i: PIdent, t: PType): PNode = result.typ = makeTypeFromExpr(c, copyTree(result)) else: result = nil - of tyGenericParam, tyAnything: + of tyFromExpr, tyGenericParam, tyAnything: if true or c.inGenericContext > 0: result = semGenericStmt(c, n) result.typ = makeTypeFromExpr(c, copyTree(result)) diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 3da32c6394194..d294aa391e9f4 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -105,6 +105,8 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, if s.typ.n != nil: result = s.typ.n elif c.inGenericContext > 0 and withinConcept notin flags: + # fine to give a symbol node a generic type here since + # we are in a generic context and `prepareNode` will be called result = newSymNodeTypeDesc(s, c.idgen, n.info) if canOpenSym(result.sym): if genericsOpenSym in c.features: @@ -137,6 +139,8 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, result.flags.incl nfDisabledOpenSym result.typ = nil elif c.inGenericContext > 0 and withinConcept notin flags: + # fine to give a symbol node a generic type here since + # we are in a generic context and `prepareNode` will be called result = newSymNodeTypeDesc(s, c.idgen, n.info) if canOpenSym(result.sym): if genericsOpenSym in c.features: diff --git a/tests/generics/t23854.nim b/tests/generics/t23854.nim new file mode 100644 index 0000000000000..08a08927f644b --- /dev/null +++ b/tests/generics/t23854.nim @@ -0,0 +1,65 @@ +# issue #23854 + +import std/bitops + +const WordBitWidth = sizeof(pointer) * 8 + +func wordsRequired*(bits: int): int {.inline.} = + const divShiftor = fastLog2(uint32(WordBitWidth)) + result = (bits + WordBitWidth - 1) shr divShiftor + +type + Algebra* = enum + BLS12_381 + + BigInt*[bits: static int] = object + limbs*: array[wordsRequired(bits), uint] + + Fr*[Name: static Algebra] = object + residue_form*: BigInt[255] + + Fp*[Name: static Algebra] = object + residue_form*: BigInt[381] + + FF*[Name: static Algebra] = Fp[Name] or Fr[Name] + +type + EC_ShortW_Aff*[F] = object + ## Elliptic curve point for a curve in Short Weierstrass form + ## y² = x³ + a x + b + ## + ## over a field F + x*, y*: F + +type FieldKind* = enum + kBaseField + kScalarField + +template getBigInt*[Name: static Algebra](T: type FF[Name]): untyped = + ## Get the underlying BigInt type. + BigInt[123] + +func bits*[Name: static Algebra](T: type FF[Name]): static int = + T.getBigInt().bits + +template getScalarField*(EC: type EC_ShortW_Aff): untyped = + Fr[EC.F.Name] + +# ------------------------------------------------------------------------------ + +type + ECFFT_Descriptor*[EC] = object + ## Metadata for FFT on Elliptic Curve + order*: int + rootsOfUnity1*: ptr UncheckedArray[BigInt[EC.getScalarField().bits()]] # Error: in expression 'EC.getScalarField()': identifier expected, but found 'EC.getScalarField' + rootsOfUnity2*: ptr UncheckedArray[BigInt[getScalarField(EC).bits()]] # Compiler SIGSEGV: Illegal Storage Access + +func new*(T: type ECFFT_Descriptor): T = + discard + +# ------------------------------------------------------------------------------ + +proc main() = + let ctx = ECFFT_Descriptor[EC_ShortW_Aff[Fp[BLS12_381]]].new() + +main() diff --git a/tests/generics/t23855.nim b/tests/generics/t23855.nim new file mode 100644 index 0000000000000..66c6454a1ad2b --- /dev/null +++ b/tests/generics/t23855.nim @@ -0,0 +1,57 @@ +# issue #23855 + +import std/bitops + +const WordBitWidth = sizeof(pointer) * 8 + +func wordsRequired*(bits: int): int {.inline.} = + const divShiftor = fastLog2(uint32(WordBitWidth)) + result = (bits + WordBitWidth - 1) shr divShiftor + +type + Algebra* = enum + BLS12_381 + + BigInt*[bits: static int] = object + limbs*: array[wordsRequired(bits), uint] + + Fr*[Name: static Algebra] = object + residue_form*: BigInt[255] + + Fp*[Name: static Algebra] = object + residue_form*: BigInt[381] + + FF*[Name: static Algebra] = Fp[Name] or Fr[Name] + +template getBigInt*[Name: static Algebra](T: type FF[Name]): untyped = + ## Get the underlying BigInt type. + BigInt[123] + +type + EC_ShortW_Aff*[F] = object + ## Elliptic curve point for a curve in Short Weierstrass form + ## y² = x³ + a x + b + ## + ## over a field F + x*, y*: F + +func bits*[Name: static Algebra](T: type FF[Name]): static int = + T.getBigInt().bits + +# ------------------------------------------------------------------------------ + +type + ECFFT_Descriptor*[EC] = object + ## Metadata for FFT on Elliptic Curve + order*: int + rootsOfUnity*: ptr UncheckedArray[BigInt[Fr[EC.F.Name].bits()]] # Undeclared identifier `Name` + +func new*(T: type ECFFT_Descriptor): T = + discard + +# ------------------------------------------------------------------------------ + +proc main() = + let ctx = ECFFT_Descriptor[EC_ShortW_Aff[Fp[BLS12_381]]].new() + +main()