summary refs log tree commit diff stats
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2023-08-17 19:52:28 +0300
committerGitHub <noreply@github.com>2023-08-17 18:52:28 +0200
commit98c39e8e571b95e7d9351c7115f897ce9af1a218 (patch)
tree69cc5b34456e36fd659d412ef90b1a0488f77748
parentfede75723824e06f59f23b38a9016d3f8cdf71db (diff)
downloadNim-98c39e8e571b95e7d9351c7115f897ce9af1a218.tar.gz
cascade tyFromExpr in type conversions in generic bodies (#22499)
fixes #22490, fixes #22491, adapts #22029 to type conversions
-rw-r--r--compiler/semexprs.nim12
-rw-r--r--tests/statictypes/tgenericcomputedrange.nim8
2 files changed, 15 insertions, 5 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index df65b3371..52d1f0628 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -311,7 +311,7 @@ proc isOwnedSym(c: PContext; n: PNode): bool =
   let s = qualifiedLookUp(c, n, {})
   result = s != nil and sfSystemModule in s.owner.flags and s.name.s == "owned"
 
-proc semConv(c: PContext, n: PNode; expectedType: PType = nil): PNode =
+proc semConv(c: PContext, n: PNode; flags: TExprFlags = {}, expectedType: PType = nil): PNode =
   if n.len != 2:
     localError(c.config, n.info, "a type conversion takes exactly one argument")
     return n
@@ -358,7 +358,7 @@ proc semConv(c: PContext, n: PNode; expectedType: PType = nil): PNode =
   if n[1].kind == nkExprEqExpr and
       targetType.skipTypes(abstractPtrs).kind == tyObject:
     localError(c.config, n.info, "object construction uses ':', not '='")
-  var op = semExprWithType(c, n[1])
+  var op = semExprWithType(c, n[1], flags * {efDetermineType})
   if op.kind == nkClosedSymChoice and op.len > 0 and
       op[0].sym.kind == skEnumField: # resolves overloadedable enums
     op = ambiguousSymChoice(c, n, op)
@@ -373,7 +373,9 @@ proc semConv(c: PContext, n: PNode; expectedType: PType = nil): PNode =
   # here or needs to be overwritten too then.
   result.add op
 
-  if targetType.kind == tyGenericParam:
+  if targetType.kind == tyGenericParam or
+      (op.typ != nil and op.typ.kind == tyFromExpr and c.inGenericContext > 0):
+    # expression is compiled early in a generic body
     result.typ = makeTypeFromExpr(c, copyTree(result))
     return result
 
@@ -1075,7 +1077,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
     t = skipTypes(n[0].typ, abstractInst+{tyOwned}-{tyTypeDesc, tyDistinct})
   if t != nil and t.kind == tyTypeDesc:
     if n.len == 1: return semObjConstr(c, n, flags, expectedType)
-    return semConv(c, n)
+    return semConv(c, n, flags)
 
   let nOrig = n.copyTree
   semOpAux(c, n)
@@ -3123,7 +3125,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
         # XXX think about this more (``set`` procs)
         let ambig = c.isAmbiguous
         if not (n[0].kind in {nkClosedSymChoice, nkOpenSymChoice, nkIdent} and ambig) and n.len == 2:
-          result = semConv(c, n, expectedType)
+          result = semConv(c, n, flags, expectedType)
         elif ambig and n.len == 1:
           errorUseQualifier(c, n.info, s)
         elif n.len == 1:
diff --git a/tests/statictypes/tgenericcomputedrange.nim b/tests/statictypes/tgenericcomputedrange.nim
index 82abe2677..9e3a49ae0 100644
--- a/tests/statictypes/tgenericcomputedrange.nim
+++ b/tests/statictypes/tgenericcomputedrange.nim
@@ -115,3 +115,11 @@ block: # issue #22187
     k: array[p(m(T, s)), int64]
   var x: F[int, 3]
   doAssert x.k is array[3, int64]
+
+block: # issue #22490
+  proc log2trunc(x: uint64): int =
+    if x == 0: int(0) else: int(0)
+  template maxChunkIdx(T: typedesc): int64 = 0'i64
+  template layer(vIdx: int64): int = log2trunc(0'u64)
+  type HashList[T] = object
+    indices: array[int(layer(maxChunkIdx(T))), int]