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

Avoid stringifying and reparsing a TokenStream #144

Merged
merged 1 commit into from
Sep 30, 2020

Conversation

Aaron1011
Copy link
Contributor

This PR changes removes uses of the pattern syn::parse_str(tokens.to_string()),
which loses Span information. In addition to making error messages
less precise, it can break code that depends on the hygiene information
carried by Span. Instead, syn::parse_quote is used to parse a
TokenStream into the desired AST struct.

I've added a test which demonstrates one of the problems with
the previous code - using $crate would previously cause
a panic, but now compiles successfully.

This PR changes removes uses of the pattern `syn::parse_str(tokens.to_string())`,
which loses `Span` information. In addition to making error messages
less precise, it can break code that depends on the hygiene information
carried by `Span`. Instead, `syn::parse_quote` is used to parse a
`TokenStream` into the desired AST struct.

I've added a test which demonstrates one of the problems with
the previous code - using `$crate` would previously cause
a panic, but now compiles successfully.
@Aaron1011
Copy link
Contributor Author

Note that this PR might break some users of this crate.

@JelteF
Copy link
Owner

JelteF commented Sep 28, 2020

Thanks for the PR! Do you have an example of code that doesn't work now?

@Aaron1011
Copy link
Contributor Author

Aaron1011 commented Sep 28, 2020

@JelteF: The code I added to tests/lib.rs will cause a panic without this PR. I haven't found an example of code that fails to compile on the latest nightly without this change, but I can try to construct one if you'd like.

@Aaron1011
Copy link
Contributor Author

I'm not sure why the macOS jobs failed - it looks like they didn't even start?

@Aaron1011
Copy link
Contributor Author

@JelteF: Assuming that this PR gets merged, could you make a new point release afterwards? I'm planning to merge a Rust PR (rust-lang/rust#77153) soon, which will expose additional issues caused by throwing away hygiene information.

@JelteF
Copy link
Owner

JelteF commented Sep 29, 2020 via email

@Aaron1011
Copy link
Contributor Author

@JelteF: In general, preserving hygiene can break crates that were incorrectly relying on certain path being accessible. For example, there have been several bugs in rustc that incorrectly allowed code like this to compile:

macro_rules! use_it {
    ($code:block) => {
        let a = "25";
        $code
    }
}

fn main() {
    use_it!({
        let b = a;
    });
}

When the compiler started properly preserving hygiene, the function main() stopped compiling, since a is not supposed to be accessible in the let a = b; statement.

This PR isn't addressing a compiler bug, but the underlying principle is the same.

In this particular case, the only things being stringified are types (it looks like they get used in generic bounds). Currently, the only stable types of hygiene are call-site and mixed-site hygiene (see https://doc.rust-lang.org/beta/proc_macro/struct.Span.html#method.call_site and https://doc.rust-lang.org/beta/proc_macro/struct.Span.html#method.mixed_site), which means that there can't be multiple types at the same path, but with different hygiene. In the context of derive_more, this means that the only thing that should change is how crate and $crate are handled.

TL;DR - I was being overly cautious. The only thing that this could possibly break is code using the unstable Span::def_site() hygiene, which likely still has bugs. I think this should be good to merge.

@JelteF JelteF merged commit db01d84 into JelteF:master Sep 30, 2020
@JelteF
Copy link
Owner

JelteF commented Sep 30, 2020

Released as 0.99.11, good luck with your rustc PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants