summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2022-11-23 03:07:00 +0800
committerGitHub <noreply@github.com>2022-11-22 20:07:00 +0100
commit0448f30fd9c2e53084ee8b284f6fa24684661bc3 (patch)
tree04ce8580c319f10684ee390edd2aea85c13624ab
parent354eb2a86c75335c34cab8074b8b3532f09ecccf (diff)
downloadNim-0448f30fd9c2e53084ee8b284f6fa24684661bc3.tar.gz
fixes #20026; marks system procs which can raise defects (#20864)
* marks system procs which can raise defects

* add tests

* add more systemRaisesDefect

* add comment
-rw-r--r--compiler/ast.nim1
-rw-r--r--compiler/ccgcalls.nim3
-rw-r--r--compiler/condsyms.nim1
-rw-r--r--compiler/pragmas.nim4
-rw-r--r--compiler/wordrecg.nim2
-rw-r--r--lib/system/indices.nim33
-rw-r--r--tests/stdlib/tstring.nim1
7 files changed, 26 insertions, 19 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 22ad1aa27..9679c10c1 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -299,6 +299,7 @@ type
     sfInjectDestructors # whether the proc needs the 'injectdestructors' transformation
     sfNeverRaises     # proc can never raise an exception, not even OverflowDefect
                       # or out-of-memory
+    sfSystemRaisesDefect # proc in the system can raise defects
     sfUsedInFinallyOrExcept  # symbol is used inside an 'except' or 'finally'
     sfSingleUsedTemp  # For temporaries that we know will only be used once
     sfNoalias         # 'noalias' annotation, means C's 'restrict'
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index a58f59c51..9993322fb 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -14,7 +14,8 @@ proc canRaiseDisp(p: BProc; n: PNode): bool =
   if n.kind == nkSym and {sfNeverRaises, sfImportc, sfCompilerProc} * n.sym.flags != {}:
     result = false
   elif optPanics in p.config.globalOptions or
-      (n.kind == nkSym and sfSystemModule in getModule(n.sym).flags):
+      (n.kind == nkSym and sfSystemModule in getModule(n.sym).flags and
+       sfSystemRaisesDefect notin n.sym.flags):
     # we know we can be strict:
     result = canRaise(n)
   else:
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index bab8ff5e3..557ea7ca6 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -147,3 +147,4 @@ proc initDefines*(symbols: StringTableRef) =
   defineSymbol("nimHasAmbiguousEnumHint")
 
   defineSymbol("nimHasOutParams")
+  defineSymbol("nimHasSystemRaisesDefect")
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index bcc786703..b60331b29 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -34,7 +34,7 @@ const
     wAsmNoStackFrame, wDiscardable, wNoInit, wCodegenDecl,
     wGensym, wInject, wRaises, wEffectsOf, wTags, wForbids, wLocks, wDelegator, wGcSafe,
     wConstructor, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy,
-    wRequires, wEnsures, wEnforceNoRaises}
+    wRequires, wEnsures, wEnforceNoRaises, wSystemRaisesDefect}
   converterPragmas* = procPragmas
   methodPragmas* = procPragmas+{wBase}-{wImportCpp}
   templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
@@ -1229,6 +1229,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
         pragmaEnsures(c, it)
       of wEnforceNoRaises:
         sym.flags.incl sfNeverRaises
+      of wSystemRaisesDefect:
+        sym.flags.incl sfSystemRaisesDefect
       else: invalidPragma(c, it)
     elif comesFromPush and whichKeyword(ident) != wInvalid:
       discard "ignore the .push pragma; it doesn't apply"
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index c21eda1f9..a9ef31dc2 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -86,7 +86,7 @@ type
     wAsmNoStackFrame = "asmNoStackFrame", wImplicitStatic = "implicitStatic",
     wGlobal = "global", wCodegenDecl = "codegenDecl", wUnchecked = "unchecked",
     wGuard = "guard", wLocks = "locks", wPartial = "partial", wExplain = "explain",
-    wLiftLocals = "liftlocals", wEnforceNoRaises = "enforceNoRaises",
+    wLiftLocals = "liftlocals", wEnforceNoRaises = "enforceNoRaises", wSystemRaisesDefect = "systemRaisesDefect",
     wRedefine = "redefine", wCallsite = "callsite",
 
     wAuto = "auto", wBool = "bool", wCatch = "catch", wChar = "char",
diff --git a/lib/system/indices.nim b/lib/system/indices.nim
index 3f90d4399..fd6770e23 100644
--- a/lib/system/indices.nim
+++ b/lib/system/indices.nim
@@ -1,3 +1,6 @@
+when not defined(nimHasSystemRaisesDefect):
+  {.pragma: systemRaisesDefect.}
+
 type
   BackwardsIndex* = distinct int ## Type that is constructed by `^` for
                                  ## reversed array accesses.
@@ -16,24 +19,24 @@ template `^`*(x: int): BackwardsIndex = BackwardsIndex(x)
   ##   echo b[^2] # => g
   ##   ```
 
-proc `[]`*[T](s: openArray[T]; i: BackwardsIndex): T {.inline.} =
+proc `[]`*[T](s: openArray[T]; i: BackwardsIndex): T {.inline, systemRaisesDefect.} =
   system.`[]`(s, s.len - int(i))
 
-proc `[]`*[Idx, T](a: array[Idx, T]; i: BackwardsIndex): T {.inline.} =
+proc `[]`*[Idx, T](a: array[Idx, T]; i: BackwardsIndex): T {.inline, systemRaisesDefect.} =
   a[Idx(a.len - int(i) + int low(a))]
-proc `[]`*(s: string; i: BackwardsIndex): char {.inline.} = s[s.len - int(i)]
+proc `[]`*(s: string; i: BackwardsIndex): char {.inline, systemRaisesDefect.} = s[s.len - int(i)]
 
-proc `[]`*[T](s: var openArray[T]; i: BackwardsIndex): var T {.inline.} =
+proc `[]`*[T](s: var openArray[T]; i: BackwardsIndex): var T {.inline, systemRaisesDefect.} =
   system.`[]`(s, s.len - int(i))
-proc `[]`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex): var T {.inline.} =
+proc `[]`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex): var T {.inline, systemRaisesDefect.} =
   a[Idx(a.len - int(i) + int low(a))]
-proc `[]`*(s: var string; i: BackwardsIndex): var char {.inline.} = s[s.len - int(i)]
+proc `[]`*(s: var string; i: BackwardsIndex): var char {.inline, systemRaisesDefect.} = s[s.len - int(i)]
 
-proc `[]=`*[T](s: var openArray[T]; i: BackwardsIndex; x: T) {.inline.} =
+proc `[]=`*[T](s: var openArray[T]; i: BackwardsIndex; x: T) {.inline, systemRaisesDefect.} =
   system.`[]=`(s, s.len - int(i), x)
-proc `[]=`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex; x: T) {.inline.} =
+proc `[]=`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex; x: T) {.inline, systemRaisesDefect.} =
   a[Idx(a.len - int(i) + int low(a))] = x
-proc `[]=`*(s: var string; i: BackwardsIndex; x: char) {.inline.} =
+proc `[]=`*(s: var string; i: BackwardsIndex; x: char) {.inline, systemRaisesDefect.} =
   s[s.len - int(i)] = x
 
 template `..^`*(a, b: untyped): untyped =
@@ -70,7 +73,7 @@ template spliceImpl(s, a, L, b: typed): untyped =
   # fill the hole:
   for i in 0 ..< b.len: s[a+i] = b[i]
 
-proc `[]`*[T, U: Ordinal](s: string, x: HSlice[T, U]): string {.inline.} =
+proc `[]`*[T, U: Ordinal](s: string, x: HSlice[T, U]): string {.inline, systemRaisesDefect.} =
   ## Slice operation for strings.
   ## Returns the inclusive range `[s[x.a], s[x.b]]`:
   ##   ```
@@ -82,7 +85,7 @@ proc `[]`*[T, U: Ordinal](s: string, x: HSlice[T, U]): string {.inline.} =
   result = newString(L)
   for i in 0 ..< L: result[i] = s[i + a]
 
-proc `[]=`*[T, U: Ordinal](s: var string, x: HSlice[T, U], b: string) =
+proc `[]=`*[T, U: Ordinal](s: var string, x: HSlice[T, U], b: string) {.systemRaisesDefect.} =
   ## Slice assignment for strings.
   ##
   ## If `b.len` is not exactly the number of elements that are referred to
@@ -100,7 +103,7 @@ proc `[]=`*[T, U: Ordinal](s: var string, x: HSlice[T, U], b: string) =
   else:
     spliceImpl(s, a, L, b)
 
-proc `[]`*[Idx, T; U, V: Ordinal](a: array[Idx, T], x: HSlice[U, V]): seq[T] =
+proc `[]`*[Idx, T; U, V: Ordinal](a: array[Idx, T], x: HSlice[U, V]): seq[T] {.systemRaisesDefect.} =
   ## Slice operation for arrays.
   ## Returns the inclusive range `[a[x.a], a[x.b]]`:
   ##   ```
@@ -112,7 +115,7 @@ proc `[]`*[Idx, T; U, V: Ordinal](a: array[Idx, T], x: HSlice[U, V]): seq[T] =
   result = newSeq[T](L)
   for i in 0..<L: result[i] = a[Idx(i + xa)]
 
-proc `[]=`*[Idx, T; U, V: Ordinal](a: var array[Idx, T], x: HSlice[U, V], b: openArray[T]) =
+proc `[]=`*[Idx, T; U, V: Ordinal](a: var array[Idx, T], x: HSlice[U, V], b: openArray[T]) {.systemRaisesDefect.} =
   ## Slice assignment for arrays.
   ##   ```
   ##   var a = [10, 20, 30, 40, 50]
@@ -126,7 +129,7 @@ proc `[]=`*[Idx, T; U, V: Ordinal](a: var array[Idx, T], x: HSlice[U, V], b: ope
   else:
     sysFatal(RangeDefect, "different lengths for slice assignment")
 
-proc `[]`*[T; U, V: Ordinal](s: openArray[T], x: HSlice[U, V]): seq[T] =
+proc `[]`*[T; U, V: Ordinal](s: openArray[T], x: HSlice[U, V]): seq[T] {.systemRaisesDefect.} =
   ## Slice operation for sequences.
   ## Returns the inclusive range `[s[x.a], s[x.b]]`:
   ##   ```
@@ -138,7 +141,7 @@ proc `[]`*[T; U, V: Ordinal](s: openArray[T], x: HSlice[U, V]): seq[T] =
   newSeq(result, L)
   for i in 0 ..< L: result[i] = s[i + a]
 
-proc `[]=`*[T; U, V: Ordinal](s: var seq[T], x: HSlice[U, V], b: openArray[T]) =
+proc `[]=`*[T; U, V: Ordinal](s: var seq[T], x: HSlice[U, V], b: openArray[T]) {.systemRaisesDefect.} =
   ## Slice assignment for sequences.
   ##
   ## If `b.len` is not exactly the number of elements that are referred to
diff --git a/tests/stdlib/tstring.nim b/tests/stdlib/tstring.nim
index 232211471..2e8fe09e1 100644
--- a/tests/stdlib/tstring.nim
+++ b/tests/stdlib/tstring.nim
@@ -1,5 +1,4 @@
 discard """
-  matrix: "--mm:refc"
   targets: "c cpp js"
 """