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

use old ctx if has same expand environment during decode span #127279

Merged
merged 1 commit into from
Aug 22, 2024

Conversation

bvanjoi
Copy link
Contributor

@bvanjoi bvanjoi commented Jul 3, 2024

Fixes #112680

The root reason why #112680 failed with incremental compilation on the second attempt is the difference in opaque between the span of the field ident and the span in the incremental cache at tcx.def_ident_span(field.did).

  • Let's call the span of ident as span_a, which is generated by apply_mark_internal. Its content is similar to:
span_a_ctx -> SyntaxContextData {
      opaque: span_a_ctx,
      opaque_and_semitransparent: span_a_ctx,
      // ....
}
  • And call the span of tcx.def_ident_span as span_b, which is generated by decode_syntax_context. Its content is:
span_b_ctx -> SyntaxContextData {
      opaque: span_b_ctx,
      // note `span_b_ctx` is not same as `span_a_ctx`
      opaque_and_semitransparent: span_b_ctx,
      // ....
}

Although they have the same parent (both refer to the root) and outer_expn, I cannot find the specific connection between them. Therefore, I chose a solution that may not be the best: give up the incremental compile cache to ensure we can use span_a in this case.

r? @petrochenkov Do you have any advice on this? Or perhaps this solution is acceptable?

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 3, 2024
@petrochenkov
Copy link
Contributor

Could you check if the issue reproduces with #119412?
ident in macros from other crates is known to have buggy spans, but I don't know whether this issue is related to that or not.

@bvanjoi
Copy link
Contributor Author

bvanjoi commented Jul 4, 2024

Could you check if the issue reproduces with #119412

Unfortunately, this issue still exists

@cjgillot
Copy link
Contributor

cjgillot commented Jul 4, 2024

Whether def_ident_span is cached on disk or not must not change the returned value. If it does, the bug is in cache decoding. Avoiding the cache will just hide the bug until another code path hits it.

@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 4, 2024
@bvanjoi
Copy link
Contributor Author

bvanjoi commented Jul 4, 2024

Whether def_ident_span is cached on disk or not must not change the returned value

Yep, but I think this might be an omission point during decoding spans that come from the disk cache: sometimes it may not be necessary to generate a new ctxt, and using the old one is enough. So in the latest PR, I added this condition: if it comes from the same macro expand environment and the old ctxt exists, then use the old one.

This means the span_b will become:

span_b_ctx -> SyntaxContextData {
      opaque: span_a.opaque,
      opaque_and_semitransparent: span_a.opaque_and_semitransparent,
      // ....
}

I'm not sure if it's completely correct, but it's more convincing than simply disabling the disk cache for ident spans.

@bvanjoi bvanjoi changed the title not cache def_ident_span from disk use old ctx if has same expand environment during decode span Jul 4, 2024
@cjgillot cjgillot self-assigned this Jul 4, 2024
@petrochenkov
Copy link
Contributor

I think the new fix is in the right direction.

In SyntaxContextData these three fields are substantial

    outer_expn: ExpnId,
    outer_transparency: Transparency,
    parent: SyntaxContext,

and these two fields are caches / precomputed values for some operations on the substantial fields

    /// This context, but with all transparent and semi-transparent expansions filtered away.
    opaque: SyntaxContext,
    /// This context, but with all transparent expansions filtered away.
    opaque_and_semitransparent: SyntaxContext,

The last field seems to also be ignored during decoding (with a reasonable explanation).

    /// Name of the crate to which `$crate` with this context would resolve.
    dollar_crate_name: Symbol,

So there are two possible strategies for encoding/decoding SyntaxContextData.

  • Encode/decode both the substantial and the auxiliary fields.
    This strategy is used now but apparently there's a bug somewhere that prevents the decoded fields from matching.
    I'm actually interested why they don't match, maybe the root issue is somewhere else and the new fix will just hide it as well.
  • Encode/decode only the substantial fields.
    Recompute the remaining fields (possibly using a cache as well, see syntax_context_map for an example).
    We should do this if it is faster than encoding/decoding the auxiliary fields.
    However, I still think we need to first figure out why the auxiliary fields decoding misbehaves now.

@bvanjoi
Copy link
Contributor Author

bvanjoi commented Jul 5, 2024

why they don't match

As you can see, the fields outer_expn, outer_transparency, and parent have not changed, so we don't need to consider them. I'd like to explain why opaque is not equal between the first compilation and the second with incremental compilation.

The content of span which need to encode is:

span_a_ctx -> SyntaxContextData {
      opaque: span_a_ctx, 
      //~^ note that `span_a_data.opaque` and `span_a_ctx` have the same value
      // ....
}

And during the second compilation:

  • It will create span_a_ctx again during MarkerVisior which occurs before processing the incremental file.

  • And it will try to handle the disk cache when using the query system. The span_a_data.opaque will be deserialized into raw_id.

    And then the new ctxt(that is span_b_ctx) with dummy data will be appended because this is the first time raw_id is loaded during decoding, see code here

    Then it begins to decode the content of span_a_data.opaque and enters decode_syntax_context again. Because the raw_id is the same as before, it encounters a cycle and directly returns the span_b_ctx(see here).

    And now the content of span_b_data.opaque is different from span_a_data_created_during_seoncd_compilation.opaque, so make this issue.

@Dylan-DPC
Copy link
Member

@bvanjoi any updates on this?

@bvanjoi
Copy link
Contributor Author

bvanjoi commented Aug 21, 2024

@rustbot ready

I think it was ready to merge.

cc@petrochenkov or @cjgillot

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 21, 2024
@petrochenkov
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Aug 21, 2024

📌 Commit 07481b9 has been approved by petrochenkov

It is now in the queue for this repository.

@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 21, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 21, 2024
…iaskrgr

Rollup of 9 pull requests

Successful merges:

 - rust-lang#127279 (use old ctx if has same expand environment during decode span)
 - rust-lang#127945 (Implement `debug_more_non_exhaustive`)
 - rust-lang#128941 ( Improve diagnostic-related lints: `untranslatable_diagnostic` & `diagnostic_outside_of_impl`)
 - rust-lang#129070 (Point at explicit `'static` obligations on a trait)
 - rust-lang#129187 (bootstrap: fix clean's remove_dir_all implementation)
 - rust-lang#129231 (improve submodule updates)
 - rust-lang#129264 (Update `library/Cargo.toml` in weekly job)
 - rust-lang#129284 (rustdoc: animate the `:target` highlight)
 - rust-lang#129302 (compiletest: use `std::fs::remove_dir_all` now that it is available)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 21, 2024
…iaskrgr

Rollup of 9 pull requests

Successful merges:

 - rust-lang#127279 (use old ctx if has same expand environment during decode span)
 - rust-lang#127945 (Implement `debug_more_non_exhaustive`)
 - rust-lang#128941 ( Improve diagnostic-related lints: `untranslatable_diagnostic` & `diagnostic_outside_of_impl`)
 - rust-lang#129070 (Point at explicit `'static` obligations on a trait)
 - rust-lang#129187 (bootstrap: fix clean's remove_dir_all implementation)
 - rust-lang#129231 (improve submodule updates)
 - rust-lang#129264 (Update `library/Cargo.toml` in weekly job)
 - rust-lang#129284 (rustdoc: animate the `:target` highlight)
 - rust-lang#129302 (compiletest: use `std::fs::remove_dir_all` now that it is available)

r? `@ghost`
`@rustbot` modify labels: rollup
jieyouxu added a commit to jieyouxu/rust that referenced this pull request Aug 22, 2024
use old ctx if has same expand environment during decode span

Fixes rust-lang#112680

The root reason why rust-lang#112680 failed with incremental compilation on the second attempt is the difference in `opaque` between the span of the field [`ident`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir_typeck/src/expr.rs#L2348) and the span in the incremental cache at `tcx.def_ident_span(field.did)`.

-  Let's call the span of `ident` as `span_a`, which is generated by [`apply_mark_internal`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_span/src/hygiene.rs#L553-L554). Its content is similar to:

```rs
span_a_ctx -> SyntaxContextData {
      opaque: span_a_ctx,
      opaque_and_semitransparent: span_a_ctx,
      // ....
}
```

- And call the span of `tcx.def_ident_span` as `span_b`, which is generated by [`decode_syntax_context`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_span/src/hygiene.rs#L1390). Its content is:

```rs
span_b_ctx -> SyntaxContextData {
      opaque: span_b_ctx,
      // note `span_b_ctx` is not same as `span_a_ctx`
      opaque_and_semitransparent: span_b_ctx,
      // ....
}
```

Although they have the same `parent` (both refer to the root) and `outer_expn`, I cannot find the specific connection between them. Therefore, I chose a solution that may not be the best: give up the incremental compile cache to ensure we can use `span_a` in this case.

r?  ``@petrochenkov`` Do you have any advice on this? Or perhaps this solution is acceptable?
bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 22, 2024
…iaskrgr

Rollup of 9 pull requests

Successful merges:

 - rust-lang#127279 (use old ctx if has same expand environment during decode span)
 - rust-lang#127945 (Implement `debug_more_non_exhaustive`)
 - rust-lang#128941 ( Improve diagnostic-related lints: `untranslatable_diagnostic` & `diagnostic_outside_of_impl`)
 - rust-lang#129070 (Point at explicit `'static` obligations on a trait)
 - rust-lang#129187 (bootstrap: fix clean's remove_dir_all implementation)
 - rust-lang#129231 (improve submodule updates)
 - rust-lang#129264 (Update `library/Cargo.toml` in weekly job)
 - rust-lang#129284 (rustdoc: animate the `:target` highlight)
 - rust-lang#129302 (compiletest: use `std::fs::remove_dir_all` now that it is available)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 221b53c into rust-lang:master Aug 22, 2024
6 checks passed
@rustbot rustbot added this to the 1.82.0 milestone Aug 22, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Aug 22, 2024
Rollup merge of rust-lang#127279 - bvanjoi:fix-112680, r=petrochenkov

use old ctx if has same expand environment during decode span

Fixes rust-lang#112680

The root reason why rust-lang#112680 failed with incremental compilation on the second attempt is the difference in `opaque` between the span of the field [`ident`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir_typeck/src/expr.rs#L2348) and the span in the incremental cache at `tcx.def_ident_span(field.did)`.

-  Let's call the span of `ident` as `span_a`, which is generated by [`apply_mark_internal`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_span/src/hygiene.rs#L553-L554). Its content is similar to:

```rs
span_a_ctx -> SyntaxContextData {
      opaque: span_a_ctx,
      opaque_and_semitransparent: span_a_ctx,
      // ....
}
```

- And call the span of `tcx.def_ident_span` as `span_b`, which is generated by [`decode_syntax_context`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_span/src/hygiene.rs#L1390). Its content is:

```rs
span_b_ctx -> SyntaxContextData {
      opaque: span_b_ctx,
      // note `span_b_ctx` is not same as `span_a_ctx`
      opaque_and_semitransparent: span_b_ctx,
      // ....
}
```

Although they have the same `parent` (both refer to the root) and `outer_expn`, I cannot find the specific connection between them. Therefore, I chose a solution that may not be the best: give up the incremental compile cache to ensure we can use `span_a` in this case.

r?  `@petrochenkov` Do you have any advice on this? Or perhaps this solution is acceptable?
@pnkfelix
Copy link
Member

pnkfelix commented Aug 29, 2024

As a heads up, this seems to have been responsible for the (minor) incr-patched regressions reported on rollup PR #129365, as you can see from #129365 (comment)

Having said that, the degree of the regression here is minor, and the fix here is patching over a legitimate problem. So I am not going to actually mark this with the perf regression label.

Nonetheless It might be worth still investigating the potential deeper cause of the problem being patched over, as described by @petrochenkov above. If we were to do that, we might be able to revert this PR. (Who knows what end effect all that will have on performance; its unknown, so I'm not going to claim it will recover the minor performance regression flagged above...)

bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 30, 2024
…xt, r=<try>

dont clone old syntax context

I guess this regression was caused by too many clones, so this is an attempt to use the old value rather than cloning it. Perhaps a better approach would be to ensure that only the substantial fields mentioned in this [comment](rust-lang#127279 (comment)) are cacheable.

Anyway, let's run a perf test to see if this can solve the problem.

r? `@pnkfelix` or `@petrochenkov`
bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 31, 2024
perform less decoding if it has the same syntax context

Following this [comment](rust-lang#127279 (comment))

r? `@petrochenkov`
bors added a commit to rust-lang-ci/rust that referenced this pull request Sep 11, 2024
perform less decoding if it has the same syntax context

Following this [comment](rust-lang#127279 (comment))

r? `@petrochenkov`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

decl_macro incremental compilation bug: missing field
7 participants