forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Preserve
SyntaxContext
for invalid/dummy spans in crate metadata
Fixes rust-lang#85197 We already preserved the `SyntaxContext` for invalid/dummy spans in the incremental cache, but we weren't doing the same for crate metadata. If an invalid (lo/hi from different files) span is written to the incremental cache, we will decode it with a 'dummy' location, but keep the original `SyntaxContext`. Since the crate metadata encoder was only checking for `DUMMY_SP` (dummy location + root `SyntaxContext`), the metadata encoder would treat it as a normal span, encoding the `SyntaxContext`. As a result, the final span encoded to the metadata would change across sessions, even if the crate itself was unchanged. This PR updates our encoding of spans in the crate metadata to mirror the encoding of spans into the incremental cache. We now always encode a `SyntaxContext`, and encode location information for spans with a non-dummy location.
- Loading branch information
1 parent
f724ee4
commit 9529cbd
Showing
7 changed files
with
113 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// revisions: rpass1 rpass2 | ||
|
||
extern crate respan; | ||
|
||
#[macro_use] | ||
#[path = "invalid-span-helper-mod.rs"] | ||
mod invalid_span_helper_mod; | ||
|
||
// Invoke a macro from a different file - this | ||
// allows us to get tokens with spans from different files | ||
helper!(1); |
14 changes: 14 additions & 0 deletions
14
src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-mod.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#[macro_export] | ||
macro_rules! helper { | ||
// Use `:tt` instead of `:ident` so that we don't get a `None`-delimited group | ||
($first:tt) => { | ||
pub fn foo<T>() { | ||
// The span of `$first` comes from another file, | ||
// so the expression `1 + $first` ends up with an | ||
// 'invalid' span that starts and ends in different files. | ||
// We use the `respan!` macro to give all tokens the same | ||
// `SyntaxContext`, so that the parser will try to merge the spans. | ||
respan::respan!(let a = 1 + $first;); | ||
} | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/test/incremental/issue-85197-invalid-span/auxiliary/respan.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// force-host | ||
// no-prefer-dynamic | ||
|
||
#![crate_type = "proc-macro"] | ||
|
||
extern crate proc_macro; | ||
use proc_macro::TokenStream; | ||
|
||
|
||
/// Copies the resolution information (the `SyntaxContext`) of the first | ||
/// token to all other tokens in the stream. Does not recurse into groups. | ||
#[proc_macro] | ||
pub fn respan(input: TokenStream) -> TokenStream { | ||
let first_span = input.clone().into_iter().next().unwrap().span(); | ||
input.into_iter().map(|mut tree| { | ||
tree.set_span(tree.span().resolved_at(first_span)); | ||
tree | ||
}).collect() | ||
} |
24 changes: 24 additions & 0 deletions
24
src/test/incremental/issue-85197-invalid-span/invalid_span_main.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// revisions: rpass1 rpass2 | ||
// aux-build:respan.rs | ||
// aux-build:invalid-span-helper-lib.rs | ||
|
||
// This issue has several different parts. The high level idea is: | ||
// 1. We create an 'invalid' span with the help of the `respan` proc-macro, | ||
// The compiler attempts to prevent the creation of invalid spans by | ||
// refusing to join spans with different `SyntaxContext`s. We work around | ||
// this by applying the same `SyntaxContext` to the span of every token, | ||
// using `Span::resolved_at` | ||
// 2. We using this invalid span in the body of a function, causing it to get | ||
// encoded into the `optimized_mir` | ||
// 3. We call the function from a different crate - since the function is generic, | ||
// monomorphization runs, causing `optimized_mir` to get called. | ||
// 4. We re-run compilation using our populated incremental cache, but without | ||
// making any changes. When we recompile the crate containing our generic function | ||
// (`invalid_span_helper_lib`), we load the span from the incremental cache, and | ||
// write it into the crate metadata. | ||
|
||
extern crate invalid_span_helper_lib; | ||
|
||
fn main() { | ||
invalid_span_helper_lib::foo::<u8>(); | ||
} |