Skip to content

Commit

Permalink
out parameters: enforce that 'out' is only used as a parameter (#20510)
Browse files Browse the repository at this point in the history
* out parameters: enforce that 'out' is only used as a parameter

* make tables.nim use 'out' parameters

* better backwards compat
  • Loading branch information
Araq authored Oct 7, 2022
1 parent a132f55 commit e83f27e
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 3 deletions.
2 changes: 2 additions & 0 deletions compiler/typeallowed.nim
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
elif t.kind == tyLent and ((kind != skResult and views notin c.features) or
kind == skParam): # lent can't be used as parameters.
result = t
elif isOutParam(t) and kind != skParam:
result = t
else:
var t2 = skipTypes(t[0], abstractInst-{tyTypeDesc, tySink})
case t2.kind
Expand Down
5 changes: 4 additions & 1 deletion lib/core/macros.nim
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ type
nnkTupleTy, nnkTupleClassTy, nnkTypeClassTy, nnkStaticTy,
nnkRecList, nnkRecCase, nnkRecWhen,
nnkRefTy, nnkPtrTy, nnkVarTy,
nnkConstTy, nnkMutableTy,
nnkConstTy, nnkOutTy,
nnkDistinctTy,
nnkProcTy,
nnkIteratorTy, # iterator type
Expand Down Expand Up @@ -125,6 +125,9 @@ type

TNimSymKinds* {.deprecated.} = set[NimSymKind]

const
nnkMutableTy* {.deprecated.} = nnkOutTy

type
NimIdent* {.deprecated.} = object of RootObj
## Represents a Nim identifier in the AST. **Note**: This is only
Expand Down
3 changes: 2 additions & 1 deletion lib/pure/collections/hashcommon.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
when defined(nimPreviewSlimSystem):
import std/assertions

import std / outparams

const
growthFactor = 2
Expand Down Expand Up @@ -78,5 +79,5 @@ template rawGetImpl() {.dirty.} =
genHashImpl(key, hc)
rawGetKnownHCImpl()

proc rawGet[X, A](t: X, key: A, hc: var Hash): int {.inline.} =
proc rawGet[X, A](t: X, key: A, hc: var Hash): int {.inline, outParamsAt: [3].} =
rawGetImpl()
2 changes: 1 addition & 1 deletion lib/pure/collections/tableimpl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ template rawInsertImpl() {.dirty.} =
data[h].val = val
data[h].hcode = hc

proc rawGetDeep[X, A](t: X, key: A, hc: var Hash): int {.inline.} =
proc rawGetDeep[X, A](t: X, key: A, hc: var Hash): int {.inline, outParamsAt: [3].} =
rawGetDeepImpl()

proc rawInsert[X, A, B](t: var X, data: var KeyValuePairSeq[A, B],
Expand Down
38 changes: 38 additions & 0 deletions lib/std/outparams.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2022 Nim contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#

## `outParamsAt` macro for easy writing code that works with both 2.0 and 1.x.

import macros

macro outParamsAt*(positions: static openArray[int]; n: untyped): untyped =
## Use this macro to annotate `out` parameters in a portable way.
runnableExamples:
proc p(x: var int) {.outParamsAt: [1].} =
discard "x is really an 'out int' if the Nim compiler supports 'out' parameters"

result = n
when defined(nimHasOutParams):
var p = n.params
for po in positions:
p[po][^2].expectKind nnkVarTy
p[po][^2] = newTree(nnkOutTy, p[po][^2][0])

when isMainModule:
{.experimental: "strictDefs".}

proc main(x: var int) {.outParamsAt: [1].} =
x = 3

proc us =
var x: int
main x
echo x

us()

0 comments on commit e83f27e

Please sign in to comment.