Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audit uses of apply_mark in built-in macros + Remove default macro transparencies #63823

Merged
merged 5 commits into from
Aug 24, 2019

Conversation

petrochenkov
Copy link
Contributor

@petrochenkov petrochenkov commented Aug 22, 2019

Every use of apply_mark in a built-in or procedural macro is supposed to look like this

location.with_ctxt(SyntaxContext::root().apply_mark(ecx.current_expansion.id))

where SyntaxContext::root() means that the built-in/procedural macro is defined directly, rather than expanded from some other macro.

However, few people understood what apply_mark does, so we had a lot of copy-pasted uses of it looking e.g. like

span = span.apply_mark(ecx.current_expansion.id);

, which doesn't really make sense for procedural macros, but at the same time is not too harmful, if the macros use the traditional macro_rules hygiene.

So, to fight this, we stop using apply_mark directly in built-in macro implementations, and follow the example of regular proc macros instead and use analogues of Span::def_site() and Span::call_site(), which are much more intuitive and less error-prone.

  • ecx.with_def_site_ctxt(span) takes the span's location and combines it with a def-site context.
  • ecx.with_call_site_ctxt(span) takes the span's location and combines it with a call-site context.

Even if called multiple times (which sometimes happens due to some historical messiness of the built-in macro code) these functions will produce the same result, unlike apply_mark which will grow the mark chain further in this case.


After apply_marks in built-in macros are eliminated, the remaining apply_marks are very few in number, so we can start passing the previously implicit Transparency argument to them explicitly, thus eliminating the need in default_transparency fields in hygiene structures and #[rustc_macro_transparency] annotations on built-in macros.

So, the task of making built-in macros opaque can now be formulated as "eliminate with_legacy_ctxt in favor of with_def_site_ctxt" rather than "replace #[rustc_macro_transparency = "semitransparent"] with #[rustc_macro_transparency = "opaque"]".

r? @matthewjasper

Replace them with equivalents of `Span::{def_site,call_site}` from proc macro API.
The new API is much less error prone and doesn't rely on macros having default transparency.
… contexts

Using `ExpnId`s default transparency here instead of the mark's real transparency was actually incorrect.
All transparancies are passed explicitly now.
Also remove `#[rustc_macro_transparency]` annotations from built-in macros, they are no longer used.
`#[rustc_macro_transparency]` only makes sense for declarative macros now.
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 22, 2019
@@ -575,9 +550,15 @@ impl Span {
/// The returned span belongs to the created expansion and has the new properties,
/// but its location is inherited from the current span.
pub fn fresh_expansion(self, expn_data: ExpnData) -> Span {
self.fresh_expansion_with_transparency(expn_data, Transparency::SemiTransparent)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Transparency::Transparent makes more sense here? This expansion isn't for a macro so it can't be used for hygienic resolution anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of the things using fresh_expansion currently use gensyms too, so it may be better to organize opaque expansions for them.
Transparency::SemiTransparent is used here just to keep the pre-existing behavior for now.

@matthewjasper
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Aug 24, 2019

📌 Commit 6548a5f has been approved by matthewjasper

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 24, 2019
@bors
Copy link
Contributor

bors commented Aug 24, 2019

⌛ Testing commit 6548a5f with merge 5ade61a...

bors added a commit that referenced this pull request Aug 24, 2019
Audit uses of `apply_mark` in built-in macros + Remove default macro transparencies

Every use of `apply_mark` in a built-in or procedural macro is supposed to look like this
```rust
location.with_ctxt(SyntaxContext::root().apply_mark(ecx.current_expansion.id))
```
where `SyntaxContext::root()` means that the built-in/procedural macro is defined directly, rather than expanded from some other macro.

However, few people understood what `apply_mark` does, so we had a lot of copy-pasted uses of it looking e.g. like
```rust
span = span.apply_mark(ecx.current_expansion.id);
```
, which doesn't really make sense for procedural macros, but at the same time is not too harmful, if the macros use the traditional `macro_rules` hygiene.

So, to fight this, we stop using `apply_mark` directly in built-in macro implementations, and follow the example of regular proc macros instead and use analogues of `Span::def_site()` and `Span::call_site()`, which are much more intuitive and less error-prone.
- `ecx.with_def_site_ctxt(span)` takes the `span`'s location and combines it with a def-site context.
- `ecx.with_call_site_ctxt(span)` takes the `span`'s location and combines it with a call-site context.

Even if called multiple times (which sometimes happens due to some historical messiness of the built-in macro code) these functions will produce the same result, unlike `apply_mark` which will grow  the mark chain further in this case.

---

After `apply_mark`s in built-in macros are eliminated, the remaining `apply_mark`s are very few in number, so we can start passing the previously implicit `Transparency` argument to them explicitly, thus eliminating the need in `default_transparency` fields in hygiene structures and `#[rustc_macro_transparency]` annotations on built-in macros.

So, the task of making built-in macros opaque can now be formulated as "eliminate `with_legacy_ctxt` in favor of `with_def_site_ctxt`" rather than "replace `#[rustc_macro_transparency = "semitransparent"]` with `#[rustc_macro_transparency = "opaque"]`".

r? @matthewjasper
@bors
Copy link
Contributor

bors commented Aug 24, 2019

☀️ Test successful - checks-azure
Approved by: matthewjasper
Pushing 5ade61a to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Aug 24, 2019
@bors bors merged commit 6548a5f into rust-lang:master Aug 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants