summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semmagic.nim11
-rw-r--r--compiler/semtypes.nim10
-rw-r--r--tests/generics/tuninstantiatedgenericcalls.nim20
3 files changed, 41 insertions, 0 deletions
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 524c9a0ab..360d23477 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -53,6 +53,8 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
   let typExpr = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {})
   dec c.inTypeofContext
   result.add typExpr
+  if typExpr.typ.kind == tyFromExpr:
+    typExpr.typ.flags.incl tfNonConstExpr
   result.typ = makeTypeDesc(c, typExpr.typ)
 
 type
@@ -68,6 +70,15 @@ proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
   if result.isNil:
     let x = copyTree(n)
     x[0] = newIdentNode(getIdent(c.cache, "[]"), n.info)
+    if c.inGenericContext > 0:
+      for i in 0..<n.len:
+        let a = n[i]
+        if a.typ != nil and a.typ.kind in {tyGenericParam, tyFromExpr}:
+          # expression is compiled early in a generic body
+          result = semGenericStmt(c, x)
+          result.typ = makeTypeFromExpr(c, copyTree(result))
+          result.typ.flags.incl tfNonConstExpr
+          return
     bracketNotFoundError(c, x, flags)
     #localError(c.config, n.info, "could not resolve: " & $n)
     result = errorNode(c, n)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index d51cafe0c..5faefc9aa 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1864,6 +1864,8 @@ proc semTypeOf(c: PContext; n: PNode; prev: PType): PType =
   closeScope(c)
   fixupTypeOf(c, prev, t)
   result = t.typ
+  if result.kind == tyFromExpr:
+    result.flags.incl tfNonConstExpr
 
 proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
   openScope(c)
@@ -1880,6 +1882,8 @@ proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
   closeScope(c)
   fixupTypeOf(c, prev, t)
   result = t.typ
+  if result.kind == tyFromExpr:
+    result.flags.incl tfNonConstExpr
 
 proc semTypeIdent(c: PContext, n: PNode): PSym =
   if n.kind == nkSym:
@@ -2116,6 +2120,12 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     of mRef: result = semAnyRef(c, n, tyRef, prev)
     of mPtr: result = semAnyRef(c, n, tyPtr, prev)
     of mTuple: result = semTuple(c, n, prev)
+    of mBuiltinType:
+      case s.name.s
+      of "lent": result = semAnyRef(c, n, tyLent, prev)
+      of "sink": result = semAnyRef(c, n, tySink, prev)
+      of "owned": result = semAnyRef(c, n, tyOwned, prev)
+      else: result = semGeneric(c, n, s, prev)
     else: result = semGeneric(c, n, s, prev)
   of nkDotExpr:
     let typeExpr = semExpr(c, n)
diff --git a/tests/generics/tuninstantiatedgenericcalls.nim b/tests/generics/tuninstantiatedgenericcalls.nim
index edce48aef..9b43d18d9 100644
--- a/tests/generics/tuninstantiatedgenericcalls.nim
+++ b/tests/generics/tuninstantiatedgenericcalls.nim
@@ -333,6 +333,26 @@ block: # issue #24044
   type MyBuf[I] = ArrayBuf[maxLen(I)]
   var v: MyBuf[int]
 
+block: # issue #15959
+  proc my[T](a: T): typeof(a[0]) = discard
+  proc my2[T](a: T): array[sizeof(a[0]), T] = discard
+  proc byLent2[T](a: T): lent type(a[0]) = a[0] # Error: type mismatch: got <T, int literal(0)>
+  proc byLent3[T](a: T): lent typeof(a[0]) = a[0] # ditto
+  proc byLent4[T](a: T): lent[type(a[0])] = a[0] # Error: no generic parameters allowed for lent
+  var x = @[1, 2, 3]
+  doAssert my(x) is int
+  doAssert my2(x) is array[sizeof(int), seq[int]]
+  doAssert byLent2(x) == 1
+  doAssert byLent2(x) is lent int
+  doAssert byLent3(x) == 1
+  doAssert byLent3(x) is lent int
+  doAssert byLent4(x) == 1
+  doAssert byLent4(x) is lent int
+  proc fn[U](a: U): auto = a
+  proc my3[T](a: T, b: typeof(fn(a))) = discard
+  my3(x, x)
+  doAssert not compiles(my3(x, x[0]))
+
 block: # issue #22342, type section version of #22607
   type GenAlias[isInt: static bool] = (
     when isInt: