You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/expressions/operator-expr.md
+47Lines changed: 47 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -79,6 +79,50 @@ let a = && && mut 10;
79
79
leta=&&&&mut10;
80
80
```
81
81
82
+
### Raw address-of operators
83
+
84
+
Related to the borrow operators are the *raw address-of operators*, which do not have first-class syntax, but are exposed via the macros [`ptr::addr_of!(expr)`][addr_of] and [`ptr::addr_of_mut!(expr)`][addr_of_mut].
85
+
The expression `expr` is evaluated in place expression context.
86
+
`ptr::addr_of!(expr)` then creates a const raw pointer of type `*const T` to the given place, and `ptr::addr_of_mut!(expr)` creates a mutable raw pointer of type `*mut T`.
87
+
88
+
The raw address-of operators must be used instead of a borrow operator whenever the place expression could evaluate to a place that is not properly aligned or does not store a valid value as determined by its type, or whenever creating a reference would introduce incorrect aliasing assumptions.
89
+
In those situations, using a borrow operator would cause [undefined behavior] by creating an invalid reference, but a raw pointer may still be constructed using an address-of operator.
90
+
91
+
The following is an example of creating a raw pointer to an unaligned place through a `packed` struct:
92
+
93
+
```rust
94
+
usestd::ptr;
95
+
96
+
#[repr(packed)]
97
+
structPacked {
98
+
f1:u8,
99
+
f2:u16,
100
+
}
101
+
102
+
letpacked=Packed { f1:1, f2:2 };
103
+
// `&packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
Copy file name to clipboardExpand all lines: src/macros-by-example.md
+47Lines changed: 47 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -193,6 +193,53 @@ compiler knows how to expand them properly:
193
193
not have the same number. This requirement applies to every layer of nested
194
194
repetitions.
195
195
196
+
## Dollar-dollar ($$)
197
+
198
+
`$$` expands to a single `$`.
199
+
200
+
Since metavariable expressions always apply during the expansion of a macro, they cannot be used in recursive macro definitions and this is where `$$` expressions comes into play, i.e., `$$` can be used to resolve ambiguities in nested macros.
201
+
202
+
The following example illustrates a macro that fails to compile due to the ambiguity of the repetition in a nested macro:
203
+
204
+
```rust,compile_fail
205
+
macro_rules! foo_error {
206
+
() => {
207
+
macro_rules! bar_error {
208
+
( $( $any:tt )* ) => { $( $any )* };
209
+
// ^^^^^^^^^^^ error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth
210
+
}
211
+
};
212
+
}
213
+
214
+
foo_error!();
215
+
```
216
+
217
+
The following resolves the problem by escaping the `$` in the repetition with `$$`:
218
+
219
+
```rust
220
+
macro_rules!foo_ok {
221
+
() => {
222
+
macro_rules!bar_ok {
223
+
( $$( $any:tt )* ) => { $$( $any )* };
224
+
}
225
+
};
226
+
}
227
+
228
+
foo_ok!();
229
+
```
230
+
231
+
One consequence of such expansion is that deeper nested levels make dollar-dollar declarations grown linearly, starting at `$$`, then `$$$$`, then `$$$$$` and so on. This is also necessary to be fully featured so that it is possible to specify names of metavariables using other metavariables at each nesting level.
232
+
233
+
```ignore
234
+
$foo => bar => bar // Evaluate foo at level 1
235
+
$$foo => $foo => bar // Evaluate foo at level 2
236
+
$$$foo => $bar => baz // Evaluate foo at level 1, and use that as a name at level 2
0 commit comments