From d53a89e4539a33d9f7cf8416155d7cb700628872 Mon Sep 17 00:00:00 2001 From: Bung Date: Wed, 9 Aug 2023 18:45:43 +0800 Subject: [PATCH] fix #12938 index type of array in type section without static (#20529) * fix #12938 nim compiler assertion fail when literal integer is passed as template argument for array size * use new flag tfImplicitStatic * fix * fix #14193 * correct tfUnresolved add condition * clean test --- compiler/ast.nim | 1 + compiler/semtypes.nim | 57 ++++++++++++++++++++++++--------------- tests/generics/t12938.nim | 9 +++++++ tests/generics/t14193.nim | 6 +++++ 4 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 tests/generics/t12938.nim create mode 100644 tests/generics/t14193.nim diff --git a/compiler/ast.nim b/compiler/ast.nim index fc3f523787..d62b563682 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -591,6 +591,7 @@ type tfEffectSystemWorkaround tfIsOutParam tfSendable + tfImplicitStatic TTypeFlags* = set[TTypeFlag] diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 06be954e6d..5e72996ac1 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -335,6 +335,14 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType = localError(c.config, n.info, errXExpectsOneTypeParam % "range") result = newOrPrevType(tyError, prev, c) +proc semArrayIndexConst(c: PContext, e: PNode, info: TLineInfo): PType = + let x = semConstExpr(c, e) + if x.kind in {nkIntLit..nkUInt64Lit}: + result = makeRangeType(c, 0, x.intVal-1, info, + x.typ.skipTypes({tyTypeDesc})) + else: + result = x.typ.skipTypes({tyTypeDesc}) + proc semArrayIndex(c: PContext, n: PNode): PType = if isRange(n): result = semRangeAux(c, n, nil) @@ -351,14 +359,18 @@ proc semArrayIndex(c: PContext, n: PNode): PType = localError(c.config, n.info, "Array length can't be negative, but was " & $e.intVal) result = makeRangeType(c, 0, e.intVal-1, n.info, e.typ) - elif e.kind == nkSym and e.typ.kind == tyStatic: - if e.sym.ast != nil: - return semArrayIndex(c, e.sym.ast) - if e.typ.lastSon.kind != tyGenericParam and not isOrdinalType(e.typ.lastSon): - let info = if n.safeLen > 1: n[1].info else: n.info - localError(c.config, info, errOrdinalTypeExpected % typeToString(e.typ, preferDesc)) - result = makeRangeWithStaticExpr(c, e) - if c.inGenericContext > 0: result.flags.incl tfUnresolved + elif e.kind == nkSym and (e.typ.kind == tyStatic or e.typ.kind == tyTypeDesc) : + if e.typ.kind == tyStatic: + if e.sym.ast != nil: + return semArrayIndex(c, e.sym.ast) + if e.typ.lastSon.kind != tyGenericParam and not isOrdinalType(e.typ.lastSon): + let info = if n.safeLen > 1: n[1].info else: n.info + localError(c.config, info, errOrdinalTypeExpected % typeToString(e.typ, preferDesc)) + result = makeRangeWithStaticExpr(c, e) + if c.inGenericContext > 0: result.flags.incl tfUnresolved + else: + result = e.typ.skipTypes({tyTypeDesc}) + result.flags.incl tfImplicitStatic elif e.kind in (nkCallKinds + {nkBracketExpr}) and hasUnresolvedArgs(c, e): if not isOrdinalType(e.typ.skipTypes({tyStatic, tyAlias, tyGenericInst, tySink})): localError(c.config, n[1].info, errOrdinalTypeExpected % typeToString(e.typ, preferDesc)) @@ -371,12 +383,7 @@ proc semArrayIndex(c: PContext, n: PNode): PType = elif e.kind == nkIdent: result = e.typ.skipTypes({tyTypeDesc}) else: - let x = semConstExpr(c, e) - if x.kind in {nkIntLit..nkUInt64Lit}: - result = makeRangeType(c, 0, x.intVal-1, n.info, - x.typ.skipTypes({tyTypeDesc})) - else: - result = x.typ.skipTypes({tyTypeDesc}) + result = semArrayIndexConst(c, e, n.info) #localError(c.config, n[1].info, errConstExprExpected) proc semArray(c: PContext, n: PNode, prev: PType): PType = @@ -1504,20 +1511,24 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = var t = s.typ.skipTypes({tyAlias}) if t.kind == tyCompositeTypeClass and t.base.kind == tyGenericBody: t = t.base - result = newOrPrevType(tyGenericInvocation, prev, c) addSonSkipIntLit(result, t, c.idgen) - template addToResult(typ) = + template addToResult(typ, skip) = + if typ.isNil: internalAssert c.config, false rawAddSon(result, typ) - else: addSonSkipIntLit(result, typ, c.idgen) + else: + if skip: + addSonSkipIntLit(result, typ, c.idgen) + else: + rawAddSon(result, makeRangeWithStaticExpr(c, typ.n)) if t.kind == tyForward: for i in 1..= i - 1 and tfImplicitStatic in rType[i - 1].flags and isIntLit(typ): + skip = false + addToResult(typ, skip) if isConcrete: if s.ast == nil and s.typ.kind != tyCompositeTypeClass: diff --git a/tests/generics/t12938.nim b/tests/generics/t12938.nim new file mode 100644 index 0000000000..e09d65c7ae --- /dev/null +++ b/tests/generics/t12938.nim @@ -0,0 +1,9 @@ +type + ExampleArray[Size, T] = array[Size, T] + +var integerArray: ExampleArray[32, int] # Compiler crash! +doAssert integerArray.len == 32 + +const Size = 2 +var integerArray2: ExampleArray[Size, int] +doAssert integerArray2.len == 2 diff --git a/tests/generics/t14193.nim b/tests/generics/t14193.nim new file mode 100644 index 0000000000..213b1a8e6e --- /dev/null +++ b/tests/generics/t14193.nim @@ -0,0 +1,6 @@ +type + Task*[N: int] = object + env*: array[N, byte] + +var task14193: Task[20] +doAssert task14193.env.len == 20