summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgexprs.nim4
-rw-r--r--compiler/lowerings.nim2
-rw-r--r--compiler/modules.nim2
-rw-r--r--compiler/semmagic.nim8
-rw-r--r--compiler/sempass2.nim2
-rw-r--r--compiler/semstmts.nim3
-rw-r--r--compiler/sigmatch.nim12
-rw-r--r--compiler/types.nim10
-rw-r--r--lib/pure/os.nim4
-rw-r--r--tests/ccgbugs/tcapture_static.nim13
-rw-r--r--tests/generics/ttable_alias.nim7
11 files changed, 51 insertions, 16 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index f4068b2a2..f9fa1a0f6 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1980,6 +1980,10 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
     fillLoc(d, locData, t, tmp, OnStatic)
   else:
     putDataIntoDest(p, d, t, tmp)
+    # This fixes bug #4551, but we really need better dataflow
+    # analysis to make this 100% safe.
+    if t.kind notin {tySequence, tyString}:
+      d.s = OnStatic
 
 proc expr(p: BProc, n: PNode, d: var TLoc) =
   case n.kind
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index cdea2a4ff..36eb24653 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -578,6 +578,8 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
   var fn = n.sons[0]
   # templates and macros are in fact valid here due to the nature of
   # the transformation:
+  if fn.kind == nkClosure:
+    localError(n.info, "closure in spawn environment is not allowed")
   if not (fn.kind == nkSym and fn.sym.kind in {skProc, skTemplate, skMacro,
                                                skMethod, skConverter}):
     # for indirect calls we pass the function pointer in the scratchObj
diff --git a/compiler/modules.nim b/compiler/modules.nim
index 1b4746484..9120bd1b6 100644
--- a/compiler/modules.nim
+++ b/compiler/modules.nim
@@ -49,7 +49,7 @@ proc hashChanged(fileIdx: int32): bool =
                                        else: hashNotChanged
     # echo "TESTING Hash: ", fileIdx.toFilename, " ", result
 
-  case gMemCacheData[fileIdx].hashStatus:
+  case gMemCacheData[fileIdx].hashStatus
   of hashHasChanged:
     result = true
   of hashNotChanged:
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index d9fec6275..cbe9bc176 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -114,8 +114,12 @@ proc semTypeTraits(c: PContext, n: PNode): PNode =
 
 proc semOrd(c: PContext, n: PNode): PNode =
   result = n
-  result.typ = makeRangeType(c, firstOrd(n.sons[1].typ),
-                                lastOrd(n.sons[1].typ), n.info)
+  let parType = n.sons[1].typ
+  if isOrdinalType(parType) or parType.kind == tySet:
+    result.typ = makeRangeType(c, firstOrd(parType), lastOrd(parType), n.info)
+  else:
+    localError(n.info, errOrdinalTypeExpected)
+    result.typ = errorType(c)
 
 proc semBindSym(c: PContext, n: PNode): PNode =
   result = copyNode(n)
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 120c4c774..b12ab5e96 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -532,7 +532,7 @@ proc isOwnedProcVar(n: PNode; owner: PSym): bool =
 proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
   let a = skipConvAndClosure(n)
   let op = a.typ
-  if op != nil and op.kind == tyProc and n.kind != nkNilLit:
+  if op != nil and op.kind == tyProc and n.skipConv.kind != nkNilLit:
     internalAssert op.n.sons[0].kind == nkEffectList
     var effectList = op.n.sons[0]
     let s = n.skipConv
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index ab9ecd1a6..5d1770a32 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1309,6 +1309,7 @@ proc determineType(c: PContext, s: PSym) =
 
 proc semIterator(c: PContext, n: PNode): PNode =
   # gensym'ed iterator?
+  let isAnon = n[namePos].kind == nkEmpty
   if n[namePos].kind == nkSym:
     # gensym'ed iterators might need to become closure iterators:
     n[namePos].sym.owner = getCurrOwner()
@@ -1318,6 +1319,8 @@ proc semIterator(c: PContext, n: PNode): PNode =
   var t = s.typ
   if t.sons[0] == nil and s.typ.callConv != ccClosure:
     localError(n.info, errXNeedsReturnType, "iterator")
+  if isAnon and s.typ.callConv == ccInline:
+    localError(n.info, "inline iterators are not first-class / cannot be assigned to variables")
   # iterators are either 'inline' or 'closure'; for backwards compatibility,
   # we require first class iterators to be marked with 'closure' explicitly
   # -- at least for 0.9.2.
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 3918bb74b..ce4f893ea 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -985,11 +985,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
 
   of tyGenericBody:
     considerPreviousT:
-      let ff = lastSon(f)
-      var depth = 0
-      if a.kind == tyGenericInst and (a.sons[0] == f): #or (ff != nil and ff.kind == tyObject and isGenericSubtype(a.sons[0], ff, depth))):
-        c.inheritancePenalty += depth
+      if a.kind == tyGenericInst and a.sons[0] == f:
         bindingRet isGeneric
+      let ff = lastSon(f)
       if ff != nil:
         result = typeRel(c, ff, a)
 
@@ -1006,7 +1004,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       for i in countup(1, sonsLen(f) - 1):
         if x.sons[i].kind == tyGenericParam:
           internalError("wrong instantiated type!")
-        elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype: return
+        elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype:
+          # Workaround for regression #4589
+          if f.sons[i].kind != tyTypeDesc: return
       c.inheritancePenalty += depth
       result = isGeneric
     else:
@@ -1024,7 +1024,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         #
         # we steal the generic parameters from the tyGenericBody:
         for i in countup(1, sonsLen(f) - 1):
-          var x = PType(idTableGet(c.bindings, genericBody.sons[i-1]))
+          let x = PType(idTableGet(c.bindings, genericBody.sons[i-1]))
           if x == nil:
             discard "maybe fine (for eg. a==tyNil)"
           elif x.kind in {tyGenericInvocation, tyGenericParam}:
diff --git a/compiler/types.nim b/compiler/types.nim
index c56382b89..ff60730f0 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -148,10 +148,12 @@ proc skipGeneric(t: PType): PType =
 
 proc isOrdinalType(t: PType): bool =
   assert(t != nil)
-  # caution: uint, uint64 are no ordinal types!
-  result = t.kind in {tyChar,tyInt..tyInt64,tyUInt8..tyUInt32,tyBool,tyEnum} or
-      (t.kind in {tyRange, tyOrdinal, tyConst, tyMutable, tyGenericInst}) and
-       isOrdinalType(t.sons[0])
+  const
+    # caution: uint, uint64 are no ordinal types!
+    baseKinds = {tyChar,tyInt..tyInt64,tyUInt8..tyUInt32,tyBool,tyEnum}
+    parentKinds = {tyRange, tyOrdinal, tyConst, tyMutable, tyGenericInst,
+                   tyDistinct}
+  t.kind in baseKinds or (t.kind in parentKinds and isOrdinalType(t.sons[0]))
 
 proc enumHasHoles(t: PType): bool =
   var b = t
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index e6ecb184e..1e474f4d4 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -1507,8 +1507,8 @@ template rawToFormalFileInfo(rawInfo, formalInfo): untyped =
   ## 'rawInfo' is either a 'TBY_HANDLE_FILE_INFORMATION' structure on Windows,
   ## or a 'Stat' structure on posix
   when defined(Windows):
-    template toTime(e: FILETIME): expr {.gensym.} = winTimeToUnixTime(rdFileTime(e)) # local templates default to bind semantics
-    template merge(a, b): expr = a or (b shl 32)
+    template toTime(e: FILETIME): untyped {.gensym.} = winTimeToUnixTime(rdFileTime(e)) # local templates default to bind semantics
+    template merge(a, b): untyped = a or (b shl 32)
     formalInfo.id.device = rawInfo.dwVolumeSerialNumber
     formalInfo.id.file = merge(rawInfo.nFileIndexLow, rawInfo.nFileIndexHigh)
     formalInfo.size = merge(rawInfo.nFileSizeLow, rawInfo.nFileSizeHigh)
diff --git a/tests/ccgbugs/tcapture_static.nim b/tests/ccgbugs/tcapture_static.nim
new file mode 100644
index 000000000..2afb8de47
--- /dev/null
+++ b/tests/ccgbugs/tcapture_static.nim
@@ -0,0 +1,13 @@
+discard """
+  output: '''hi'''
+"""
+
+# bug #4551
+
+proc foo() =
+    let arr = ["hi"]
+    for i, v in arr:
+        let bar = proc =
+            echo v
+        bar()
+foo()
diff --git a/tests/generics/ttable_alias.nim b/tests/generics/ttable_alias.nim
new file mode 100644
index 000000000..992ca85e0
--- /dev/null
+++ b/tests/generics/ttable_alias.nim
@@ -0,0 +1,7 @@
+# bug #4589
+
+import tables
+type SimpleTable*[TKey, TVal] = TableRef[TKey, TVal]
+template newSimpleTable*(TKey, TVal: typedesc): SimpleTable[TKey, TVal] = newTable[TKey, TVal]()
+var fontCache : SimpleTable[string, SimpleTable[int32, int]]
+fontCache = newSimpleTable(string, SimpleTable[int32, int])