Skip to content

Commit 1b2fdb7

Browse files
committed
Move proc-macro type sections to bottom
1 parent 846670c commit 1b2fdb7

File tree

1 file changed

+101
-101
lines changed

1 file changed

+101
-101
lines changed

src/procedural-macros.md

Lines changed: 101 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,107 @@ can roughly be thought of as lexical token. For example `foo` is an `Ident`
5959
token, `.` is a `Punct` token, and `1.2` is a `Literal` token. The `TokenStream`
6060
type, unlike `Vec<TokenTree>`, is cheap to clone (like `Rc<T>`).
6161

62+
### Spans
63+
64+
All tokens have an associated `Span`. A `Span` is currently an opaque value you
65+
cannot modify (but you can manufacture). `Span`s represent an extent of source
66+
code within a program and are primarily used for error reporting currently. You
67+
can modify the `Span` of any token, and by doing so if the compiler would like
68+
to print an error for the token in question it'll use the `Span` that you
69+
manufactured.
70+
71+
For example let's create a wonky procedural macro which swaps the spans of the
72+
first two tokens:
73+
74+
```rust,ignore
75+
// my-macro/src/lib.rs
76+
extern crate proc_macro;
77+
78+
use proc_macro::*;
79+
80+
#[proc_macro]
81+
pub fn swap_spans(input: TokenStream) -> TokenStream {
82+
let mut iter = input.into_iter();
83+
let mut a = iter.next().unwrap();
84+
let mut b = iter.next().unwrap();
85+
let a_span = a.span();
86+
a.set_span(b.span());
87+
b.set_span(a_span);
88+
return vec![a, b].into_iter().chain(iter).collect()
89+
}
90+
```
91+
92+
```rust,ignore
93+
extern crate my_macro;
94+
95+
my_macro::swap_spans! {
96+
fn _() {}
97+
}
98+
99+
fn main() {}
100+
```
101+
102+
and compile it:
103+
104+
```sh
105+
$ cargo run
106+
Compiling foo v0.1.0 (file://.../foo)
107+
error: expected identifier, found reserved identifier `_`
108+
--> src/main.rs:4:5
109+
|
110+
4 | fn _() {}
111+
| ^^ expected identifier, found reserved identifier
112+
113+
error: aborting due to previous error
114+
```
115+
116+
notice how the error message is pointing to the wrong span! This is because we
117+
swapped the spans of the first two tokens, giving the compiler false information
118+
about where the tokens came from.
119+
120+
### Procedural macros and hygiene
121+
122+
Currently all procedural macros are "unhygienic". This means that all procedural
123+
macros behave as if the output token stream was simply written inline to the
124+
code it's next to. This means that it's affected by external items and also
125+
affected by external imports and such.
126+
127+
Macro authors need to be careful to ensure their macros work in as many contexts
128+
as possible given this limitation. This often includes using absolute paths to
129+
items in libraries (`::std::option::Option` instead of `Option`) or
130+
by ensuring that generated functions have names that are unlikely to clash with
131+
other functions (like `__internal_foo` instead of `foo`).
132+
133+
Eventually more support for hygiene will be added to make it easier to write a
134+
robust macro.
135+
136+
### Limitations of procedural macros
137+
138+
Procedural macros are not currently quite as powerful as `macro_rules!`-defined
139+
macros in some respects. These limitations include:
140+
141+
* Procedural bang macros can only be invoked in *item* contexts. For example you
142+
can't define your own `format!` yet because that's only ever invoked in an
143+
expression context. Put another way, procedural bang macros can only expand to
144+
items (things like functions, impls, etc), not expressions.
145+
146+
This is primarily due to the lack of hygiene with procedural macros. Once a
147+
better hygiene story is stabilized this restriction will likely be lifted.
148+
149+
* Procedural macros cannot expand to definitions of `macro_rules!` macros (none
150+
of them). This restriction may be lifted over time but for now this is a
151+
conservative limitation while compiler bugs are worked through and a design is
152+
agreed upon.
153+
154+
* Procedural attributes can only be attached to items, not expressions. For
155+
example `#[my_attr] fn foo() {}` is ok but `#[my_attr] return 3` is not. This
156+
is again due to the lack of hygiene today but this restriction may eventually
157+
be lifted.
158+
159+
* Error reporting is currently quite primitive. While an unstable diagnostic API
160+
exists on stable your only option is to `panic!` or to in some cases expand to
161+
an invocation of the `compile_error!` macro with a custom message.
162+
62163
### Bang Macros
63164

64165
This flavor of procedural macro is like writing `macro_rules!` only you get to
@@ -313,106 +414,5 @@ argument. Notably these arguments do not include the delimiters used to enclose
313414
the arguments (like procedural bang macros. Furthermore we can see the item
314415
continue to operate on it, either replacing it or augmenting it.
315416

316-
### Spans
317-
318-
All tokens have an associated `Span`. A `Span` is currently an opaque value you
319-
cannot modify (but you can manufacture). `Span`s represent an extent of source
320-
code within a program and are primarily used for error reporting currently. You
321-
can modify the `Span` of any token, and by doing so if the compiler would like
322-
to print an error for the token in question it'll use the `Span` that you
323-
manufactured.
324-
325-
For example let's create a wonky procedural macro which swaps the spans of the
326-
first two tokens:
327-
328-
```rust,ignore
329-
// my-macro/src/lib.rs
330-
extern crate proc_macro;
331-
332-
use proc_macro::*;
333-
334-
#[proc_macro]
335-
pub fn swap_spans(input: TokenStream) -> TokenStream {
336-
let mut iter = input.into_iter();
337-
let mut a = iter.next().unwrap();
338-
let mut b = iter.next().unwrap();
339-
let a_span = a.span();
340-
a.set_span(b.span());
341-
b.set_span(a_span);
342-
return vec![a, b].into_iter().chain(iter).collect()
343-
}
344-
```
345-
346-
```rust,ignore
347-
extern crate my_macro;
348-
349-
my_macro::swap_spans! {
350-
fn _() {}
351-
}
352-
353-
fn main() {}
354-
```
355-
356-
and compile it:
357-
358-
```sh
359-
$ cargo run
360-
Compiling foo v0.1.0 (file://.../foo)
361-
error: expected identifier, found reserved identifier `_`
362-
--> src/main.rs:4:5
363-
|
364-
4 | fn _() {}
365-
| ^^ expected identifier, found reserved identifier
366-
367-
error: aborting due to previous error
368-
```
369-
370-
notice how the error message is pointing to the wrong span! This is because we
371-
swapped the spans of the first two tokens, giving the compiler false information
372-
about where the tokens came from.
373-
374-
### Procedural macros and hygiene
375-
376-
Currently all procedural macros are "unhygienic". This means that all procedural
377-
macros behave as if the output token stream was simply written inline to the
378-
code it's next to. This means that it's affected by external items and also
379-
affected by external imports and such.
380-
381-
Macro authors need to be careful to ensure their macros work in as many contexts
382-
as possible given this limitation. This often includes using absolute paths to
383-
items in libraries (`::std::option::Option` instead of `Option`) or
384-
by ensuring that generated functions have names that are unlikely to clash with
385-
other functions (like `__internal_foo` instead of `foo`).
386-
387-
Eventually more support for hygiene will be added to make it easier to write a
388-
robust macro.
389-
390-
### Limitations of procedural macros
391-
392-
Procedural macros are not currently quite as powerful as `macro_rules!`-defined
393-
macros in some respects. These limitations include:
394-
395-
* Procedural bang macros can only be invoked in *item* contexts. For example you
396-
can't define your own `format!` yet because that's only ever invoked in an
397-
expression context. Put another way, procedural bang macros can only expand to
398-
items (things like functions, impls, etc), not expressions.
399-
400-
This is primarily due to the lack of hygiene with procedural macros. Once a
401-
better hygiene story is stabilized this restriction will likely be lifted.
402-
403-
* Procedural macros cannot expand to definitions of `macro_rules!` macros (none
404-
of them). This restriction may be lifted over time but for now this is a
405-
conservative limitation while compiler bugs are worked through and a design is
406-
agreed upon.
407-
408-
* Procedural attributes can only be attached to items, not expressions. For
409-
example `#[my_attr] fn foo() {}` is ok but `#[my_attr] return 3` is not. This
410-
is again due to the lack of hygiene today but this restriction may eventually
411-
be lifted.
412-
413-
* Error reporting is currently quite primitive. While an unstable diagnostic API
414-
exists on stable your only option is to `panic!` or to in some cases expand to
415-
an invocation of the `compile_error!` macro with a custom message.
416-
417417
[crate type]: linkage.html
418418
[proc_macro crate]: ../proc_macro/index.html

0 commit comments

Comments
 (0)