Skip to content

Commit

Permalink
deprecate unsafeAddr; extend addr
Browse files Browse the repository at this point in the history
addr is now available for all addressable locations, unsafeAddr is deprecated and become an alias for addr
  • Loading branch information
ringabout committed Jan 12, 2022
1 parent c7d5b8c commit ea7f5c9
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 23 deletions.
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
- `std/sharedstrings` module is removed.
- Constants `colors.colPaleVioletRed` and `colors.colMediumPurple` changed to match the CSS color standard.

- `addr` is now available for all addressable locations, `unsafeAddr` is deprecated and
become an alias for `addr`.

## Standard library additions and changes

- `macros.parseExpr` and `macros.parseStmt` now accept an optional
Expand Down
2 changes: 1 addition & 1 deletion compiler/isolation_check.nim
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ proc isValueOnlyType(t: PType): bool =

proc canAlias*(arg, ret: PType): bool =
if isValueOnlyType(arg):
# can alias only with unsafeAddr(arg.x) and we don't care if it is not safe
# can alias only with addr(arg.x) and we don't care if it is not safe
result = false
else:
var marker = initIntSet()
Expand Down
9 changes: 2 additions & 7 deletions compiler/semmagic.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,8 @@ proc semAddrArg(c: PContext; n: PNode; isUnsafeAddr = false): PNode =
let x = semExprWithType(c, n)
if x.kind == nkSym:
x.sym.flags.incl(sfAddrTaken)
if isAssignable(c, x, isUnsafeAddr) notin {arLValue, arLocalLValue}:
# Do not suggest the use of unsafeAddr if this expression already is a
# unsafeAddr
if isUnsafeAddr:
localError(c.config, n.info, errExprHasNoAddress)
else:
localError(c.config, n.info, errExprHasNoAddress & "; maybe use 'unsafeAddr'")
if isAssignable(c, x, true) notin {arLValue, arLocalLValue}:
localError(c.config, n.info, errExprHasNoAddress)
result = x

proc semTypeOf(c: PContext; n: PNode): PNode =
Expand Down
15 changes: 5 additions & 10 deletions doc/manual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3502,8 +3502,9 @@ location is `T`, the `addr` operator result is of the type `ptr T`. An
address is always an untraced reference. Taking the address of an object that
resides on the stack is **unsafe**, as the pointer may live longer than the
object on the stack and can thus reference a non-existing object. One can get
the address of variables, but one can't use it on variables declared through
`let` statements:
the address of variables. For easier interoperability with other compiled languages
such as C, retrieving the address of a `let` variable, a parameter,
or a `for` loop variable can be accomplished too:

.. code-block:: nim
Expand All @@ -3515,24 +3516,18 @@ the address of variables, but one can't use it on variables declared through
# --> ref 0x7fff6b71b670 --> 0x10bb81050"Hello"
echo cast[ptr string](t3)[]
# --> Hello
# The following line doesn't compile:
# The following line also works
echo repr(addr(t1))
# Error: expression has no address
The unsafeAddr operator
-----------------------

For easier interoperability with other compiled languages such as C, retrieving
the address of a `let` variable, a parameter, or a `for` loop variable can
be accomplished by using the `unsafeAddr` operation:
The unsafeAddr operator is an alias for the addr operator and is deprecated:

.. code-block:: nim
let myArray = [1, 2, 3]
foreignProcThatTakesAnAddr(unsafeAddr myArray)
Procedures
==========

Expand Down
2 changes: 1 addition & 1 deletion doc/manual_experimental.rst
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ has `source` as the owner. A path expression `e` is defined recursively:
- Object field access `e.field` is a path expression.
- `system.toOpenArray(e, ...)` is a path expression.
- Pointer dereference `e[]` is a path expression.
- An address `addr e`, `unsafeAddr e` is a path expression.
- An address `addr e` is a path expression.
- A type conversion `T(e)` is a path expression.
- A cast expression `cast[T](e)` is a path expression.
- `f(e, ...)` is a path expression if `f`'s return type is a view type.
Expand Down
15 changes: 11 additions & 4 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,13 @@ else:

proc `addr`*[T](x: var T): ptr T {.magic: "Addr", noSideEffect.} =
## Builtin `addr` operator for taking the address of a memory location.
## This works even for `let` variables or parameters
## for better interop with C.
##
## .. note:: When you use it to write a wrapper for a C library, you should
## always check that the original library does never write to data behind the
## pointer that is returned from this procedure.
##
## Cannot be overloaded.
##
## See also:
Expand All @@ -205,13 +212,13 @@ proc `addr`*[T](x: var T): ptr T {.magic: "Addr", noSideEffect.} =
## echo p[] # b
discard

proc unsafeAddr*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} =
proc unsafeAddr*[T](x: T): ptr T {.magic: "Addr", noSideEffect,
deprecated: "'unsafeAddr' is a deprecated alias for 'addr'".} =
## Builtin `addr` operator for taking the address of a memory
## location. This works even for `let` variables or parameters
## for better interop with C and so it is considered even more
## unsafe than the ordinary `addr <#addr,T>`_.
## for better interop with C.
##
## **Note**: When you use it to write a wrapper for a C library, you should
## .. note:: When you use it to write a wrapper for a C library, you should
## always check that the original library does never write to data behind the
## pointer that is returned from this procedure.
##
Expand Down

0 comments on commit ea7f5c9

Please sign in to comment.