1
- ======================================================
2
1
Index Invalidation Rules in the Swift Standard Library
3
2
======================================================
4
3
@@ -28,7 +27,7 @@ In C++, validity of an iterator is a property of the iterator itself, since
28
27
iterators can be dereferenced to access collection elements.
29
28
30
29
In Swift, in order to access a collection element designated by an index,
31
- subscript operator is applied to the collection, `` C[I] ` `. Thus, index is
30
+ subscript operator is applied to the collection, ` C[I] ` . Thus, index is
32
31
valid or not only in context of a certain collection instance at a certain
33
32
point of program execution. A given index can be valid for zero, one or more
34
33
than one collection instance at the same time.
@@ -51,32 +50,32 @@ An arbitrary index instance is not valid for an arbitrary collection instance.
51
50
The following points apply to all collections, defined in the library or by the
52
51
user:
53
52
54
- (1) Indices obtained from a collection `` C `` via `` C.startIndex ` `,
55
- `` C.endIndex ` ` and other collection-specific APIs returning indices, are
56
- valid for `` C ` `.
53
+ (1) Indices obtained from a collection ` C ` via ` C.startIndex ` ,
54
+ ` C.endIndex ` and other collection-specific APIs returning indices, are
55
+ valid for ` C ` .
57
56
58
- (2) If an index `` I `` is valid for a collection `` C `` , a copy of `` I ` ` is valid
59
- for `` C ` `.
57
+ (2) If an index ` I ` is valid for a collection ` C ` , a copy of ` I ` is valid
58
+ for ` C ` .
60
59
61
- (3) If an index `` I `` is valid for a collection `` C ` `, indices obtained from
62
- `` I `` via `` I.successor() `` , `` I.predecessor() ` `, and other index-specific
63
- APIs, are valid for `` C ` `.
60
+ (3) If an index ` I ` is valid for a collection ` C ` , indices obtained from
61
+ ` I ` via ` I.successor() ` , ` I.predecessor() ` , and other index-specific
62
+ APIs, are valid for ` C ` .
64
63
FIXME: disallow startIndex.predecessor(), endIndex.successor()
65
64
66
65
(4) ** Indices of collections and slices freely interoperate.**
67
66
68
- If an index `` I `` is valid for a collection `` C ` `, it is also valid for
69
- slices of `` C `` , provided that `` I ` ` was in the bounds that were passed to
67
+ If an index `I` is valid for a collection `C `, it is also valid for
68
+ slices of `C` , provided that `I ` was in the bounds that were passed to
70
69
the slicing subscript.
71
70
72
- If an index `` I `` is valid for a slice obtained from a collection `` C ` `, it
73
- is also valid for `` C ` ` itself.
71
+ If an index `I` is valid for a slice obtained from a collection `C `, it
72
+ is also valid for `C ` itself.
74
73
75
- (5) If an index `` I `` is valid for a collection `` C ` `, it is also valid for
76
- a copy of `` C ` `.
74
+ (5) If an index ` I ` is valid for a collection ` C ` , it is also valid for
75
+ a copy of ` C ` .
77
76
78
- (6) If an index `` I `` is valid for a collection `` C ` `, it continues to be valid
79
- after a call to a non-mutating method on `` C ` `.
77
+ (6) If an index ` I ` is valid for a collection ` C ` , it continues to be valid
78
+ after a call to a non-mutating method on ` C ` .
80
79
81
80
(7) Calling a non-mutating method on a collection instance does not invalidate
82
81
any indexes.
@@ -124,56 +123,56 @@ user:
124
123
125
124
Consequences:
126
125
127
- - The setter of `` MutableCollection.subscript(_: Index) ` ` does not invalidate
126
+ - The setter of ` MutableCollection.subscript(_: Index) ` does not invalidate
128
127
any indices. Indices are composites of offsets, so replacing the value does
129
128
not change the shape of the data structure and preserves offsets.
130
129
131
130
- A value type mutable linked list cannot conform to
132
- `` MutableCollectionType ` `. An index for a linked list has to be implemented
131
+ ` MutableCollectionType ` . An index for a linked list has to be implemented
133
132
as a pointer to the list node to provide O(1) element access. Mutating an
134
133
element of a non-uniquely referenced linked list will create a copy of the
135
134
nodes that comprise the list. Indices obtained before the copy was made
136
135
would point to the old nodes and wouldn't be valid for the copy of the list.
137
136
138
137
It is still valid to have a value type linked list conform to
139
- `` CollectionType ` `, or to have a reference type mutable linked list conform
140
- to `` MutableCollection ` `.
138
+ ` CollectionType ` , or to have a reference type mutable linked list conform
139
+ to ` MutableCollection ` .
141
140
142
141
The following points apply to all collections by default, but specific
143
142
collection implementations can be less strict:
144
143
145
144
(1) A call to a mutating method on a collection instance, except the setter of
146
- `` MutableCollection.subscript(_: Index) ` `, invalidates all indices for that
145
+ ` MutableCollection.subscript(_: Index) ` , invalidates all indices for that
147
146
collection instance.
148
147
149
148
Consequences:
150
149
151
- - Passing a collection as an `` inout ` ` argument invalidates all indexes for
150
+ - Passing a collection as an ` inout ` argument invalidates all indexes for
152
151
that collection instance, unless the function explicitly documents stronger
153
- guarantees. (The function can call mutating methods on an `` inout ` ` argument
152
+ guarantees. (The function can call mutating methods on an ` inout ` argument
154
153
or completely replace it.)
155
154
156
- * `` Swift.swap() ` ` does not invalidate any indexes.
155
+ * ` Swift.swap() ` does not invalidate any indexes.
157
156
158
- Additional guarantees for `` Swift.Array `` , `` Swift.ContiguousArray `` , `` Swift.ArraySlice ` `
157
+ Additional guarantees for ` Swift.Array ` , ` Swift.ContiguousArray ` , ` Swift.ArraySlice `
159
158
==========================================================================================
160
159
161
160
** Valid array indexes can be created without using Array APIs.** Array indexes
162
- are plain integers. Integers that are dynamically in the range `` 0..<A.count ` `
163
- are valid indexes for the array or slice `` A ` `. It does not matter if an index
161
+ are plain integers. Integers that are dynamically in the range ` 0..<A.count `
162
+ are valid indexes for the array or slice ` A ` . It does not matter if an index
164
163
was obtained from the collection instance, or derived from input or unrelated
165
164
data.
166
165
167
166
** Traps are guaranteed.** Using an invalid index to designate elements of an
168
167
array or an array slice is guaranteed to perform a trap.
169
168
170
- Additional guarantees for `` Swift.Dictionary ` `
169
+ Additional guarantees for ` Swift.Dictionary `
171
170
==============================================
172
171
173
172
** Insertion into a Dictionary invalidates indexes only on a rehash.** If a
174
- `` Dictionary ` ` has enough free buckets (guaranteed by calling an initializer or
173
+ ` Dictionary ` has enough free buckets (guaranteed by calling an initializer or
175
174
reserving space), then inserting elements does not invalidate indexes.
176
175
177
- Note: unlike C++'s `` std::unordered_map ` `, removing elements from a
178
- `` Dictionary ` ` invalidates indexes.
176
+ Note: unlike C++'s ` std::unordered_map ` , removing elements from a
177
+ ` Dictionary ` invalidates indexes.
179
178
0 commit comments