view types: spec changes (#18226)

* view types: spec changes

* Update doc/manual_experimental.rst

Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>

* Update doc/manual_experimental.rst

Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>

Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>
This commit is contained in:
Andreas Rumpf
2021-06-10 16:49:17 +02:00
committed by GitHub
parent 3481ff6172
commit 2ea7287217
3 changed files with 21 additions and 24 deletions

View File

@@ -572,7 +572,7 @@ proc borrowingAsgn(c: var Partitions; dest, src: PNode) =
borrowFrom(c, dest.sym, src)
elif dest.kind in {nkHiddenDeref, nkDerefExpr, nkBracketExpr}:
case directViewType(dest[0].typ)
of mutableView:
of mutableView, immutableView:
# we do not borrow, but we use the view to mutate the borrowed
# location:
let viewOrigin = pathExpr(dest, c.owner)
@@ -580,12 +580,13 @@ proc borrowingAsgn(c: var Partitions; dest, src: PNode) =
let vid = variableId(c, viewOrigin.sym)
if vid >= 0:
c.s[vid].flags.incl viewDoesMutate
of immutableView:
#[of immutableView:
if dest.kind == nkBracketExpr and dest[0].kind == nkHiddenDeref and
mutableParameter(dest[0][0]):
discard "remains a mutable location anyhow"
else:
localError(c.g.config, dest.info, "attempt to mutate a borrowed location from an immutable view")
]#
of noView: discard "nothing to do"
proc containsPointer(t: PType): bool =

View File

@@ -475,8 +475,8 @@ Not nil annotation
**Note:** This is an experimental feature. It can be enabled with
`{.experimental: "notnil"}`.
All types for which `nil` is a valid value can be annotated with the `not
nil` annotation to exclude `nil` as a valid value:
All types for which `nil` is a valid value can be annotated with the
`not nil` annotation to exclude `nil` as a valid value:
.. code-block:: nim
{.experimental: "notnil"}
@@ -1837,8 +1837,7 @@ with `--experimental:strictFuncs`:option:.
A view type is a type that is or contains one of the following types:
- `var T` (mutable view into `T`)
- `lent T` (immutable view into `T`)
- `lent T` (view into `T`)
- `openArray[T]` (pair of (pointer to array of `T`, size))
For example:
@@ -1846,10 +1845,9 @@ For example:
.. code-block:: nim
type
View1 = var int
View2 = openArray[byte]
View3 = lent string
View4 = Table[openArray[char], int]
View1 = openArray[byte]
View2 = lent string
View3 = Table[openArray[char], int]
Exceptions to this rule are types constructed via `ptr` or `proc`.
@@ -1860,11 +1858,11 @@ For example, the following types are **not** view types:
type
NotView1 = proc (x: openArray[int])
NotView2 = ptr openArray[char]
NotView3 = ptr array[4, var int]
NotView3 = ptr array[4, lent int]
A *mutable* view type is a type that is or contains a `var T` type.
An *immutable* view type is a view type that is not a mutable view type.
The mutability aspect of a view type is not part of the type but part
of the locations it's derived from. More on this later.
A *view* is a symbol (a let, var, const, etc.) that has a view type.
@@ -1948,11 +1946,14 @@ details about how this is done for `var T`.
A mutable view can borrow from a mutable location, an immutable view can borrow
from both a mutable or an immutable location.
If a view borrows from a mutable location, the view can be used to update the
location. Otherwise it cannot be used for mutations.
The *duration* of a borrow is the span of commands beginning from the assignment
to the view and ending with the last usage of the view.
For the duration of the borrow operation, no mutations to the borrowed locations
may be performed except via the potentially mutable view that borrowed from the
may be performed except via the view that borrowed from the
location. The borrowed location is said to be *sealed* during the borrow.
.. code-block:: nim
@@ -2064,11 +2065,7 @@ and `b` the location that is borrowed from.
- The lifetime of `v` must not exceed `b`'s lifetime. Note: The lifetime of
a parameter is the complete proc body.
- If `v` is a mutable view and `v` is used to actually mutate the
borrowed location, then `b` has to be a mutable location.
Note: If it is not actually used for mutation, borrowing a mutable view from an
immutable location is allowed! This allows for many important idioms and will be
justified in an upcoming RFC.
- If `v` is used for a mutation, `b` must be a mutable location too.
- During `v`'s lifetime, `G(b)` can only be modified by `v` (and only if
`v` is a mutable view).
- If `v` is `result` then `b` has to be a location derived from the first

View File

@@ -9,8 +9,9 @@ import tables
const
Whitespace = {' ', '\t', '\n', '\r'}
proc split*(s: string, seps: set[char] = Whitespace,
maxsplit: int = -1): Table[int, openArray[char]] =
proc split*(s: string, seps: set[char] = Whitespace, maxsplit: int = -1): Table[int, openArray[char]] #[tt.Error
'result' borrows from the immutable location 's' and attempts to mutate it
]# =
var last = 0
var splits = maxsplit
result = initTable[int, openArray[char]]()
@@ -22,9 +23,7 @@ proc split*(s: string, seps: set[char] = Whitespace,
if splits == 0: last = len(s)
result[first] = toOpenArray(s, first, last-1)
result[first][0] = 'c' #[tt.Error
attempt to mutate a borrowed location from an immutable view
]#
result[first][0] = 'c'
if splits == 0: break
dec(splits)