diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 16d3d6f5b85b..b4eb9f9b47bf 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -487,7 +487,7 @@ proc makeNotType*(c: PContext, t1: PType): PType = result.flags.incl tfHasMeta proc nMinusOne(c: PContext; n: PNode): PNode = - result = newTreeI(nkCall, n.info, newSymNode(getSysMagic(c.graph, n.info, "pred", mPred)), n) + result = newTreeI(nkCall, n.info, newSymNode(getSysMagic(c.graph, n.info, "pred", mPred), n.info), n) # Remember to fix the procs below this one when you make changes! proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType = diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 113946fef256..9e48109e618b 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -385,6 +385,7 @@ proc semArrayIndex(c: PContext, n: PNode): PType = let e = semExprWithType(c, n, {efDetermineType}) if e.typ.kind == tyFromExpr: result = makeRangeWithStaticExpr(c, e.typ.n) + result.flags.incl tfUnresolved elif e.kind in {nkIntLit..nkUInt64Lit}: if e.intVal < 0: localError(c.config, n.info, @@ -411,6 +412,10 @@ proc semArrayIndex(c: PContext, n: PNode): PType = # properly filled-out in semtypinst (see how tyStaticExpr # is handled there). result = makeRangeWithStaticExpr(c, e) + # makeRangeWithStaticExpr doesn't mark range as unresolved unless + # type of e is nil or has nil node, but we know it's unresolved + # even if it has a type because of hasUnresolvedArgs + result.flags.incl tfUnresolved elif e.kind == nkIdent: result = e.typ.skipTypes({tyTypeDesc}) else: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 9643f3765595..41a865f02f37 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -997,7 +997,6 @@ proc maybeSkipDistinct(m: TCandidate; t: PType, callee: PSym): PType = result = t proc tryResolvingStaticExpr(c: var TCandidate, n: PNode, - allowUnresolved = false, allowCalls = false, expectedType: PType = nil): PNode = # Consider this example: @@ -1006,8 +1005,7 @@ proc tryResolvingStaticExpr(c: var TCandidate, n: PNode, # Here, N-1 will be initially nkStaticExpr that can be evaluated only after # N is bound to a concrete value during the matching of the first param. # This proc is used to evaluate such static expressions. - let instantiated = replaceTypesInBody(c.c, c.bindings, n, nil, - allowMetaTypes = allowUnresolved) + let instantiated = replaceTypesInBody(c.c, c.bindings, n, nil) if not allowCalls and instantiated.kind in nkCallKinds: return nil result = c.c.semExpr(c.c, instantiated) @@ -1084,7 +1082,9 @@ proc inferStaticParam*(c: var TCandidate, lhs: PNode, rhs: BiggestInt): bool = (lhs.typ.n == nil or lookup(c.bindings, lhs.typ) == nil): var inferred = newTypeS(tyStatic, c.c, lhs.typ.elementType) inferred.n = newIntNode(nkIntLit, rhs) - put(c, lhs.typ, inferred) + # lhs.typ might be instantiated copy, use original type instead, + # obtained from type sym: + put(c, lhs.typ.sym.typ, inferred) if c.c.matchedConcept != nil: # inside concepts, binding is currently done with # direct mutation of the involved types: @@ -1101,10 +1101,8 @@ proc failureToInferStaticParam(conf: ConfigRef; n: PNode) = proc inferStaticsInRange(c: var TCandidate, inferred, concrete: PType): TTypeRelation = - let lowerBound = tryResolvingStaticExpr(c, inferred.n[0], - allowUnresolved = true) - let upperBound = tryResolvingStaticExpr(c, inferred.n[1], - allowUnresolved = true) + let lowerBound = tryResolvingStaticExpr(c, inferred.n[0], allowCalls = true) + let upperBound = tryResolvingStaticExpr(c, inferred.n[1], allowCalls = true) template doInferStatic(e: PNode, r: Int128) = var exp = e var rhs = r diff --git a/tests/proc/tstaticsignature.nim b/tests/proc/tstaticsignature.nim index 25aa09c5dfe8..d4552243eec9 100644 --- a/tests/proc/tstaticsignature.nim +++ b/tests/proc/tstaticsignature.nim @@ -266,3 +266,24 @@ block: # issue #22276 a = x * 2) doAssert a == 18 foo(B, proc (x: float) = doAssert x == 9) + +block: # issue #19923 + type Test[S: static[Natural]] = object + proc run(self: Test, idx: 0..(self.S * 8)) = discard + # This causes segfault ^^^^^^^^^^^^ + proc run(self: Test, a: array[self.S * 8, int]) = discard + # And this too ^^^^^^^^^^ + var x = Test[3]() + var y: array[24, int] + run(x, y.low) + var z: array[x.S * 8, int] + run(x, z) + +block: + proc foo[I: static int](x: array[I, int]) = discard + foo([1, 2, 3, 4]) + proc bar[I: static int](x: array[I * 2, int]) = discard + bar([1, 2, 3, 4]) + proc double(x: int): int = x * 2 + proc baz[I: static int](x: array[double(I), int]) = discard + doAssert not compiles(baz([1, 2, 3, 4]))