Commit f5bdd1af authored by Aaron Hill's avatar Aaron Hill Committed by Bastian Köcher
Browse files

Use proper span when emitting 'self' identifier (#210)

Normally, the span of a field has the same hygiene context as
`Span::call_site`. However, it's possible for a struct definition
to be 'constructed' via a `macro_rules` macro such that the field
has a different hygiene context. This will cause the expanded code
to be unable to resolve any references to `self`, resulting in a
compilation error.

This pull request uses `quote!` instead of `quote_spanned!` when
emitting a 'self' identifier. `quote_spanned!` is still used for
everything else in the emitted method, meaning that error messages
will still point to the proper field.

I've included a test case which triggers this issue on
Rust 1.43.1. It's current difficult to hit this issue
other than in this artificial case, but that will change
once rust-lang/rust#72622 is re-landed.
parent 06b55920
......@@ -70,16 +70,19 @@ fn encode_single_field(
}
};
// This may have different hygiene than the field span
let i_self = quote! { self };
quote_spanned! { field.span() =>
fn encode_to<EncOut: _parity_scale_codec::Output>(&self, dest: &mut EncOut) {
fn encode_to<EncOut: _parity_scale_codec::Output>(&#i_self, dest: &mut EncOut) {
_parity_scale_codec::Encode::encode_to(&#final_field_variable, dest)
}
fn encode(&self) -> _parity_scale_codec::alloc::vec::Vec<u8> {
fn encode(&#i_self) -> _parity_scale_codec::alloc::vec::Vec<u8> {
_parity_scale_codec::Encode::encode(&#final_field_variable)
}
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&#i_self, f: F) -> R {
_parity_scale_codec::Encode::using_encoded(&#final_field_variable, f)
}
}
......
......@@ -526,3 +526,18 @@ fn crafted_input_for_vec_t() {
);
}
#[test]
fn weird_derive() {
// Tests that compilation succeeds when the macro invocation
// hygiene context is different from the field hygiene context.
macro_rules! make_struct {
(#[$attr:meta]) => (
#[$attr]
pub struct MyStruct {
field: u8
}
)
}
make_struct!(#[derive(Encode, Decode)]);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment