Skip to content

Commit 32bc019

Browse files
Clarify line!/column! treatment within expansion.
1 parent 327a5ec commit 32bc019

File tree

1 file changed

+36
-8
lines changed

1 file changed

+36
-8
lines changed

text/3791-crate-attr.md

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@ Any crate-level attribute is valid to pass to `--crate-attr`.
6868

6969
Formally, the expansion behaves as follows:
7070

71-
1. The crate is parsed as if `--crate-attr` were not present.
71+
1. The crate root (initial file given to rustc) is parsed as if `--crate-attr` were not present.
7272
2. The attributes in `--crate-attr` are parsed.
73-
3. The attributes are injected at the top of the crate root.
74-
4. Macro expansion is performed.
73+
3. The attributes are injected at the top of the crate root (see below for
74+
relative ordering to any existing attributes).
75+
4. Compilation continues as normal.
7576

7677
As a consequence, this feature does not affect [shebang parsing], nor can it affect nor be affected by comments that appear on the first source line.
7778

@@ -86,6 +87,9 @@ If the attribute is already present in the source code, it behaves exactly as it
8687
For example, duplicating `no_std` is idempotent; duplicating `crate_type` generates both types; and duplicating `crate_name` is idempotent if the names are the same and a hard error otherwise.
8788
It is suggested, but not required, that the implementation not warn on idempotent attributes, even if it would normally warn that duplicate attributes are unused.
8889

90+
The compiler is free to re-order steps 1 and 2 in the above order if desirable.
91+
This shouldn't have any user-observable effect beyond changes in diagnostics.
92+
8993
## Doctests
9094

9195
`--crate-attr` is also a rustdoc flag. Rustdoc behaves identically to rustc for the main crate being compiled.
@@ -124,7 +128,10 @@ My awesome crate
124128

125129
## Spans, modules, and editions
126130

127-
`file!`, `include!`, `include_str!`, and `module_path!` all behave the same as when written in source code.
131+
`include!`, `include_str!`, and `module_path!` all behave the same as when
132+
written in source code at the top of the crate root. That is, any module or
133+
path-relative resolution within the `--crate-attr` attribute should be treated
134+
the same as ocurring within the crate root.
128135

129136
`--crate-attr` shares an edition with the crate (i.e. it is affected by `--edition`). This may be observable because `doc` attributes can invoke arbitrary macros. Consider this use of [indoc]:
130137
```
@@ -135,7 +142,30 @@ My awesome crate
135142
```
136143
Edition-related changes to how proc-macros are passed tokens may need to consider how crate-attr is affected.
137144

138-
The behavior of `line!` and `column!` are not specified; see "Unresolved questions".
145+
`file!`, `line!`, `column!` *within* the --crate-attr attribute use a synthetic
146+
file (e.g., file might be `<cli-arg>`). This avoids ambiguity for the span
147+
overlapping actual bytes in any existing files on disk, and matches precedent
148+
in other toolchains, e.g., see clang's output for `--include` on the command
149+
line:
150+
151+
```shell
152+
$ touch t.h
153+
$ clang t.h --include foo.h
154+
<built-in>:1:10: fatal error: 'foo.h' file not found
155+
1 | #include "foo.h"
156+
| ^~~~~~~
157+
1 error generated.
158+
```
159+
160+
The line and column will ideally be relative to the individual --crate-attr
161+
command line flag, though this is considered a best-effort detail for quality
162+
of diagnostics. They will not be affected by the injected `#![` surrounding
163+
the parsed
164+
attribute.
165+
166+
The original source parsing (i.e., the file provided to rustc) is not affected
167+
by the injected attributes, in effect, they are treated as ocurring within 0
168+
bytes at the start of the file.
139169

140170
[indoc]: https://docs.rs/indoc/latest/indoc/
141171

@@ -153,7 +183,7 @@ In practice, this has not be a large drawback for `crate_name` and `crate_type`,
153183
- We could apply `--crate-attr` after attributes in the source, instead of before. This has two drawbacks:
154184
1. It has different behavior for lints than the existing A/W/D flags, so those flags could not semantically be unified with crate-attr. We would be adding yet another precedence group.
155185
2. It does not allow configuring a "default" option for a workspace and then overriding it in a single crate.
156-
- We could add a syntax for passing multiple attributes in a single CLI flag. We would have to find a syntax that avoids ambiguity *and* that does not mis-parse the data inside string literals (i.e. picking a fixed string, such as `|`, would not work because it has to take quote nesting into account). This greatly complicates the implementation for little benefit.
186+
- We could add a syntax for passing multiple attributes in a single CLI flag. We would have to find a syntax that avoids ambiguity *and* that does not mis-parse the data inside string literals (i.e. picking a fixed string, such as `|`, would not work because it has to take quote nesting into account). This greatly complicates the implementation for little benefit. We also already have @file syntax to pass in arguments from a file which provides an escape hatch if this is truly helpful.
157187

158188
This cannot be done in a library or macro. It can be done in an external tool, but only by modifying the source in place, which requires first parsing it, and in general is much more brittle than this approach (for example, preventing the argument from injecting a unterminated block comment, or from injecting a non-attribute grammar production, becomes much harder).
159189

@@ -171,8 +201,6 @@ In the author's opinion, having source injected via this mechanism does not make
171201

172202
- Is `--crate-name` equivalent to `--crate-attr=crate_name`? As currently implemented, the answer is no. Fixing this is hard; see https://github.com/rust-lang/rust/issues/91632 and https://github.com/rust-lang/rust/pull/108221#issuecomment-1435765434 (these do not directly answer why, but I am not aware of any documentation that does).
173203

174-
- How should macros that give information about source code behave when used in this attribute? For example, `line!` does not seem to have an obvious behavior, and `column!` could either include or not include the surrounding `#![]`.
175-
176204
# Future possibilities
177205
[future-possibilities]: #future-possibilities
178206

0 commit comments

Comments
 (0)