Skip to content

Commit ca28c25

Browse files
authored
fix subscript in generics, typeof, lent with bracket (#24067)
fixes #15959 Another followup of #22029 and #24005, subscript expressions now recognize when their parameters are generic types, then generating tyFromExpr. `typeof` also now properly sets `tfNonConstExpr` to make it usable in proc signatures. `lent` with brackets like `lent[T]` is also now allowed.
1 parent ebcfd96 commit ca28c25

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

compiler/semmagic.nim

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
5353
let typExpr = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {})
5454
dec c.inTypeofContext
5555
result.add typExpr
56+
if typExpr.typ.kind == tyFromExpr:
57+
typExpr.typ.flags.incl tfNonConstExpr
5658
result.typ = makeTypeDesc(c, typExpr.typ)
5759

5860
type
@@ -68,6 +70,15 @@ proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
6870
if result.isNil:
6971
let x = copyTree(n)
7072
x[0] = newIdentNode(getIdent(c.cache, "[]"), n.info)
73+
if c.inGenericContext > 0:
74+
for i in 0..<n.len:
75+
let a = n[i]
76+
if a.typ != nil and a.typ.kind in {tyGenericParam, tyFromExpr}:
77+
# expression is compiled early in a generic body
78+
result = semGenericStmt(c, x)
79+
result.typ = makeTypeFromExpr(c, copyTree(result))
80+
result.typ.flags.incl tfNonConstExpr
81+
return
7182
bracketNotFoundError(c, x, flags)
7283
#localError(c.config, n.info, "could not resolve: " & $n)
7384
result = errorNode(c, n)

compiler/semtypes.nim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,6 +1864,8 @@ proc semTypeOf(c: PContext; n: PNode; prev: PType): PType =
18641864
closeScope(c)
18651865
fixupTypeOf(c, prev, t)
18661866
result = t.typ
1867+
if result.kind == tyFromExpr:
1868+
result.flags.incl tfNonConstExpr
18671869

18681870
proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
18691871
openScope(c)
@@ -1880,6 +1882,8 @@ proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
18801882
closeScope(c)
18811883
fixupTypeOf(c, prev, t)
18821884
result = t.typ
1885+
if result.kind == tyFromExpr:
1886+
result.flags.incl tfNonConstExpr
18831887

18841888
proc semTypeIdent(c: PContext, n: PNode): PSym =
18851889
if n.kind == nkSym:
@@ -2116,6 +2120,12 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
21162120
of mRef: result = semAnyRef(c, n, tyRef, prev)
21172121
of mPtr: result = semAnyRef(c, n, tyPtr, prev)
21182122
of mTuple: result = semTuple(c, n, prev)
2123+
of mBuiltinType:
2124+
case s.name.s
2125+
of "lent": result = semAnyRef(c, n, tyLent, prev)
2126+
of "sink": result = semAnyRef(c, n, tySink, prev)
2127+
of "owned": result = semAnyRef(c, n, tyOwned, prev)
2128+
else: result = semGeneric(c, n, s, prev)
21192129
else: result = semGeneric(c, n, s, prev)
21202130
of nkDotExpr:
21212131
let typeExpr = semExpr(c, n)

tests/generics/tuninstantiatedgenericcalls.nim

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,26 @@ block: # issue #24044
333333
type MyBuf[I] = ArrayBuf[maxLen(I)]
334334
var v: MyBuf[int]
335335

336+
block: # issue #15959
337+
proc my[T](a: T): typeof(a[0]) = discard
338+
proc my2[T](a: T): array[sizeof(a[0]), T] = discard
339+
proc byLent2[T](a: T): lent type(a[0]) = a[0] # Error: type mismatch: got <T, int literal(0)>
340+
proc byLent3[T](a: T): lent typeof(a[0]) = a[0] # ditto
341+
proc byLent4[T](a: T): lent[type(a[0])] = a[0] # Error: no generic parameters allowed for lent
342+
var x = @[1, 2, 3]
343+
doAssert my(x) is int
344+
doAssert my2(x) is array[sizeof(int), seq[int]]
345+
doAssert byLent2(x) == 1
346+
doAssert byLent2(x) is lent int
347+
doAssert byLent3(x) == 1
348+
doAssert byLent3(x) is lent int
349+
doAssert byLent4(x) == 1
350+
doAssert byLent4(x) is lent int
351+
proc fn[U](a: U): auto = a
352+
proc my3[T](a: T, b: typeof(fn(a))) = discard
353+
my3(x, x)
354+
doAssert not compiles(my3(x, x[0]))
355+
336356
block: # issue #22342, type section version of #22607
337357
type GenAlias[isInt: static bool] = (
338358
when isInt:

0 commit comments

Comments
 (0)