summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/types.nim2
-rw-r--r--compiler/varpartitions.nim26
-rw-r--r--lib/impure/nre.nim6
-rw-r--r--lib/pure/mimetypes.nim3
-rw-r--r--lib/pure/strtabs.nim13
5 files changed, 36 insertions, 14 deletions
diff --git a/compiler/types.nim b/compiler/types.nim
index 3545b0703..b8452c3ea 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -543,7 +543,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
       else:
         result = "<invalid tyUserTypeClass>"
     of tyBuiltInTypeClass:
-      result = case t.base.kind:
+      result = case t.base.kind
         of tyVar: "var"
         of tyRef: "ref"
         of tyPtr: "ptr"
diff --git a/compiler/varpartitions.nim b/compiler/varpartitions.nim
index 6857e1b57..fd6751cdf 100644
--- a/compiler/varpartitions.nim
+++ b/compiler/varpartitions.nim
@@ -14,7 +14,8 @@
 ## The used data structure is "union find" with path compression.
 
 import ast, types, lineinfos, options, msgs, renderer
-from trees import getMagic
+from trees import getMagic, whichPragma
+from wordrecg import wNoSideEffect
 from isolation_check import canAlias
 
 type
@@ -48,7 +49,7 @@ type
     s: seq[VarIndex]
     graphs: seq[MutationInfo]
     unanalysableMutation, performCursorInference: bool
-    inAsgnSource, inConstructor: int
+    inAsgnSource, inConstructor, inNoSideEffectSection: int
 
 proc `$`*(config: ConfigRef; g: MutationInfo): string =
   result = ""
@@ -336,12 +337,15 @@ proc deps(c: var Partitions; dest, src: PNode) =
   var targets, sources: seq[PSym]
   allRoots(dest, targets)
   allRoots(src, sources)
+
+  proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr}
+  let destIsComplex = types.searchTypeFor(dest.typ, wrap)
+
   for t in targets:
     if dest.kind != nkSym:
       potentialMutation(c, t, dest.info)
 
-    proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr}
-    if types.searchTypeFor(t.typ, wrap):
+    if destIsComplex:
       for s in sources:
         connect(c, t, s, dest.info)
 
@@ -399,7 +403,8 @@ proc traverse(c: var Partitions; n: PNode) =
           var roots: seq[PSym]
           allRoots(it, roots)
           if paramType.kind == tyVar:
-            for r in roots: potentialMutation(c, r, it.info)
+            if c.inNoSideEffectSection == 0:
+              for r in roots: potentialMutation(c, r, it.info)
           else:
             for r in roots: noCursor(c, r)
 
@@ -434,6 +439,17 @@ proc traverse(c: var Partitions; n: PNode) =
           # test arc/topt_no_cursor.nim
           noCursor(c, it.sym)
 
+  of nkPragmaBlock:
+    let pragmaList = n[0]
+    var enforceNoSideEffects = 0
+    for i in 0..<pragmaList.len:
+      if whichPragma(pragmaList[i]) == wNoSideEffect:
+        enforceNoSideEffects = 1
+        break
+
+    inc c.inNoSideEffectSection, enforceNoSideEffects
+    traverse(c, n.lastSon)
+    dec c.inNoSideEffectSection, enforceNoSideEffects
   else:
     for child in n: traverse(c, child)
 
diff --git a/lib/impure/nre.nim b/lib/impure/nre.nim
index 0817ca4ec..88fa0b323 100644
--- a/lib/impure/nre.nim
+++ b/lib/impure/nre.nim
@@ -374,12 +374,14 @@ func checkNamedCaptured(pattern: RegexMatch, name: string): void =
 func `[]`*(pattern: CaptureBounds, name: string): HSlice[int, int] =
   let pattern = RegexMatch(pattern)
   checkNamedCaptured(pattern, name)
-  pattern.captureBounds[pattern.pattern.captureNameToId[name]]
+  {.noSideEffect.}:
+    result = pattern.captureBounds[pattern.pattern.captureNameToId[name]]
 
 func `[]`*(pattern: Captures, name: string): string =
   let pattern = RegexMatch(pattern)
   checkNamedCaptured(pattern, name)
-  return pattern.captures[pattern.pattern.captureNameToId[name]]
+  {.noSideEffect.}:
+    result = pattern.captures[pattern.pattern.captureNameToId[name]]
 
 template toTableImpl() {.dirty.} =
   for key in RegexMatch(pattern).pattern.captureNameId.keys:
diff --git a/lib/pure/mimetypes.nim b/lib/pure/mimetypes.nim
index 3bbd0d243..206783929 100644
--- a/lib/pure/mimetypes.nim
+++ b/lib/pure/mimetypes.nim
@@ -1914,7 +1914,8 @@ func register*(mimedb: var MimeDB, ext: string, mimetype: string) =
   ## ``mimetype`` and ``ext`` are lowercased before registering on ``mimedb``.
   assert ext.strip.len > 0, "ext argument can not be empty string"
   assert mimetype.strip.len > 0, "mimetype argument can not be empty string"
-  mimedb.mimes[ext.toLowerAscii()] = mimetype.toLowerAscii()
+  {.noSideEffect.}:
+    mimedb.mimes[ext.toLowerAscii()] = mimetype.toLowerAscii()
 
 runnableExamples:
   static:
diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim
index 676e8eb1d..4c2dd1451 100644
--- a/lib/pure/strtabs.nim
+++ b/lib/pure/strtabs.nim
@@ -252,7 +252,7 @@ proc `[]=`*(t: StringTableRef, key, val: string) {.
     inc(t.counter)
 
 proc newStringTable*(mode: StringTableMode): owned(StringTableRef) {.
-  rtlFunc, extern: "nst$1".} =
+  rtlFunc, extern: "nst$1", noSideEffect.} =
   ## Creates a new empty string table.
   ##
   ## See also:
@@ -265,7 +265,7 @@ proc newStringTable*(mode: StringTableMode): owned(StringTableRef) {.
 
 proc newStringTable*(keyValuePairs: varargs[string],
                      mode: StringTableMode): owned(StringTableRef) {.
-  rtlFunc, extern: "nst$1WithPairs".} =
+  rtlFunc, extern: "nst$1WithPairs", noSideEffect.} =
   ## Creates a new string table with given `key, value` string pairs.
   ##
   ## `StringTableMode` must be specified.
@@ -276,12 +276,13 @@ proc newStringTable*(keyValuePairs: varargs[string],
   result = newStringTable(mode)
   var i = 0
   while i < high(keyValuePairs):
-    result[keyValuePairs[i]] = keyValuePairs[i + 1]
+    {.noSideEffect.}:
+      result[keyValuePairs[i]] = keyValuePairs[i + 1]
     inc(i, 2)
 
 proc newStringTable*(keyValuePairs: varargs[tuple[key, val: string]],
     mode: StringTableMode = modeCaseSensitive): owned(StringTableRef) {.
-    rtlFunc, extern: "nst$1WithTableConstr".} =
+    rtlFunc, extern: "nst$1WithTableConstr", noSideEffect.} =
   ## Creates a new string table with given `(key, value)` tuple pairs.
   ##
   ## The default mode is case sensitive.
@@ -291,7 +292,9 @@ proc newStringTable*(keyValuePairs: varargs[tuple[key, val: string]],
       mytab2 = newStringTable([("key3", "val3"), ("key4", "val4")])
 
   result = newStringTable(mode)
-  for key, val in items(keyValuePairs): result[key] = val
+  for key, val in items(keyValuePairs):
+    {.noSideEffect.}:
+      result[key] = val
 
 proc raiseFormatException(s: string) =
   raise newException(ValueError, "format string: key not found: " & s)