strict effects (#18777)

* fixes #17369
* megatest is green for --cpu:arm64
* docgen output includes more tags/raises
* implemented 'effectsOf' 
* algorithm.nim: uses new effectsOf annotation
* closes #18376
* closes #17475
* closes #13905
* allow effectsOf: [a, b]
* added a test case
* parameters that are not ours cannot be declared as .effectsOf
* documentation
* manual: added the 'sort' example
* bootstrap with the new better options
This commit is contained in:
Andreas Rumpf 2021-09-02 12:10:14 +02:00 • committed by GitHub
commit e0ef859130
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 482 additions and 203 deletions

View file

@ -147,8 +147,13 @@ proc reversed*[T](a: openArray[T], first: Natural, last: int): seq[T]
{.inline, deprecated: "use: `reversed(toOpenArray(a, first, last))`".} =
reversed(toOpenArray(a, first, last))
when defined(nimHasEffectsOf):
{.experimental: "strictEffects".}
else:
{.pragma: effectsOf.}
proc binarySearch*[T, K](a: openArray[T], key: K,
cmp: proc (x: T, y: K): int {.closure.}): int =
cmp: proc (x: T, y: K): int {.closure.}): int {.effectsOf: cmp.} =
## Binary search for `key` in `a`. Return the index of `key` or -1 if not found.
## Assumes that `a` is sorted according to `cmp`.
##
@ -210,7 +215,7 @@ const
onlySafeCode = true
proc lowerBound*[T, K](a: openArray[T], key: K,
cmp: proc(x: T, k: K): int {.closure.}): int =
cmp: proc(x: T, k: K): int {.closure.}): int {.effectsOf: cmp.} =
## Returns the index of the first element in `a` that is not less than
## (i.e. greater or equal to) `key`, or last if no such element is found.
## In other words if you have a sorted sequence and you call
@ -260,7 +265,7 @@ proc lowerBound*[T](a: openArray[T], key: T): int = lowerBound(a, key, cmp[T])
## * `upperBound proc<#upperBound,openArray[T],T>`_
proc upperBound*[T, K](a: openArray[T], key: K,
cmp: proc(x: T, k: K): int {.closure.}): int =
cmp: proc(x: T, k: K): int {.closure.}): int {.effectsOf: cmp.} =
## Returns the index of the first element in `a` that is greater than
## `key`, or last if no such element is found.
## In other words if you have a sorted sequence and you call
@ -318,7 +323,7 @@ template `<-`(a, b) =
copyMem(addr(a), addr(b), sizeof(T))
proc mergeAlt[T](a, b: var openArray[T], lo, m, hi: int,
cmp: proc (x, y: T): int {.closure.}, order: SortOrder) =
cmp: proc (x, y: T): int {.closure.}, order: SortOrder) {.effectsOf: cmp.} =
# Optimization: If max(left) <= min(right) there is nothing to do!
# 1 2 3 4 ## 5 6 7 8
# -> O(n) for sorted arrays.
@ -358,7 +363,7 @@ proc mergeAlt[T](a, b: var openArray[T], lo, m, hi: int,
func sort*[T](a: var openArray[T],
cmp: proc (x, y: T): int {.closure.},
order = SortOrder.Ascending) =
order = SortOrder.Ascending) {.effectsOf: cmp.} =
## Default Nim sort (an implementation of merge sort). The sorting
## is guaranteed to be stable (that is, equal elements stay in the same order)
## and the worst case is guaranteed to be O(n log n).
@ -420,7 +425,7 @@ proc sort*[T](a: var openArray[T], order = SortOrder.Ascending) = sort[T](a,
## * `sortedByIt template<#sortedByIt.t,untyped,untyped>`_
proc sorted*[T](a: openArray[T], cmp: proc(x, y: T): int {.closure.},
order = SortOrder.Ascending): seq[T] =
order = SortOrder.Ascending): seq[T] {.effectsOf: cmp.} =
## Returns `a` sorted by `cmp` in the specified `order`.
##
## **See also:**
@ -497,7 +502,7 @@ template sortedByIt*(seq1, op: untyped): untyped =
func isSorted*[T](a: openArray[T],
cmp: proc(x, y: T): int {.closure.},
order = SortOrder.Ascending): bool =
order = SortOrder.Ascending): bool {.effectsOf: cmp.} =
## Checks to see whether `a` is already sorted in `order`
## using `cmp` for the comparison. The parameters are identical
## to `sort`. Requires O(n) time.
@ -545,7 +550,7 @@ proc isSorted*[T](a: openArray[T], order = SortOrder.Ascending): bool =
proc merge*[T](
result: var seq[T],
x, y: openArray[T], cmp: proc(x, y: T): int {.closure.}
) {.since: (1, 5, 1).} =
) {.since: (1, 5, 1), effectsOf: cmp.} =
## Merges two sorted `openArray`. `x` and `y` are assumed to be sorted.
## If you do not wish to provide your own `cmp`,
## you may use `system.cmp` or instead call the overloaded
@ -638,7 +643,7 @@ proc product*[T](x: openArray[seq[T]]): seq[seq[T]] =
## Produces the Cartesian product of the array.
## Every element of the result is a combination of one element from each seq in `x`,
## with the ith element coming from `x[i]`.
##
##
## .. warning:: complexity may explode.
runnableExamples:
assert product(@[@[1], @[2]]) == @[@[1, 2]]