Skip to content

Commit

Permalink
Handle nested syn::Type:::Group
Browse files Browse the repository at this point in the history
Currently, rustc does not pass the exact original TokenStream to
proc-macros in several cases. This has many undesirable effects, such as
losing correct location information in error message.
See rust-lang/rust#43081 for more details

In the future, rustc will begin passing the correct TokenStream to
proc-macros. As a result, `syn` may wrap a type in one or more
`syn::Type::Group`s (if the proc-macro input came from a `macro_rules!` expansion).

I've determined that this can cause `oauth1-request-derive` to fail to match
a `Type::Path`. This PR should properly handle nested groups, allowing
your crate to work with both old and new input.

If you have any questions, feel free to ask me. See rust-lang/rust#72622
for more details.
  • Loading branch information
Aaron1011 committed May 31, 2020
1 parent 97c90e4 commit 6405232
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 19 deletions.
6 changes: 5 additions & 1 deletion oauth1-request-derive/src/method_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ impl<'a> ToTokens for MethodBody<'a> {
}

let ty_is_option = f.meta.option.get().map(|v| **v).unwrap_or_else(|| {
if let Type::Path(ref ty_path) = f.ty {
let mut ty = &f.ty;
while let Type::Group(g) = ty {
ty = &g.elem;
}
if let Type::Path(ref ty_path) = ty {
let path = &ty_path.path;
path.leading_colon.is_none()
&& path.segments.len() == 1
Expand Down
22 changes: 4 additions & 18 deletions oauth1-request-derive/tests/compile-fail/typeck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@ use std::fmt::{self, Formatter};

#[derive(oauth1_request_derive::Authorize)]
//~^ ERROR: mismatched types
//~| expected u8, found ()
//~^^^ ERROR: mismatched types
//~| expected (), found u8
//~^^^^^ ERROR: `()` doesn't implement `std::fmt::Display`
//~^^^^^^ ERROR: the trait bound `(): std::convert::AsRef<str>` is not satisfied
//~^^^^^^^ ERROR: the trait bound `u8: std::convert::AsRef<str>` is not satisfied
// FIXME: move these errors to (1) to (5) respectively
//~| ERROR: `()` doesn't implement `std::fmt::Display`
//~| ERROR: mismatched types
struct Test {
not_display: (),
//^ (3)
Expand All @@ -20,31 +15,26 @@ struct Test {

#[oauth1(fmt = "fmt_arg_not_ref")]
//~^ ERROR: mismatched types
//~| expected reference, found ()
fmt_arg_not_ref: (),

#[oauth1(fmt = "fmt_arg_mismatch")]
//^ (1)
fmt_arg_mismatch: (),

#[oauth1(fmt = "fmt_trait_bound_unsatisfied")]
//^ (4)
//~^ the trait bound `(): std::convert::AsRef<str>`
fmt_trait_bound_unsatisfied: (),

#[oauth1(fmt = "fmt_ret_mismatch")]
//~^ ERROR: mismatched types
//~| expected struct `std::fmt::Error`, found ()
fmt_ret_mismatch: (),

#[oauth1(fmt = "NOT_FN")]
//~^ ERROR: mismatched types
//~| expected fn pointer, found ()
fmt_not_fn: (),

#[oauth1(option = "true")]
option_not_option: u8,
//~^ ERROR: mismatched types
//~| expected enum `std::option::Option`, found u8

#[oauth1(skip_if = "skip_if_too_many_args")]
//~^ ERROR: mismatched types
Expand All @@ -53,25 +43,21 @@ struct Test {

#[oauth1(skip_if = "skip_if_arg_not_ref")]
//~^ ERROR: mismatched types
//~| expected reference, found u8
skip_if_arg_not_ref: u8,

#[oauth1(skip_if = "skip_if_arg_mismatch")]
//^ (2)
skip_if_arg_mismatch: u8,

#[oauth1(skip_if = "skip_if_trait_bound_unsatisfied")]
//- (5)
//~^ ERROR: the trait bound `u8: std::convert::AsRef<str>`
skip_if_trait_bound_unsatisfied: u8,

#[oauth1(skip_if = "skip_if_ret_mismatch")]
//~^ ERROR: mismatched types
//~| expected bool, found enum `std::option::Option`
skip_if_ret_mismatch: u8,

#[oauth1(skip_if = "NOT_FN")]
//~^ ERROR: mismatched types
//~| expected fn pointer, found ()
skip_if_not_fn: u8,
}

Expand Down

0 comments on commit 6405232

Please sign in to comment.