From d3b0276a253e4f2a7247d4d4c40f187a424628f7 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 28 Mar 2021 18:13:35 -0400 Subject: [PATCH 1/2] Parse generic associated type equality constraint --- src/path.rs | 74 ++++++++++++++++++++++++++++++++++++----------- tests/repo/mod.rs | 6 ---- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/src/path.rs b/src/path.rs index 90e2970d30..19522304a6 100644 --- a/src/path.rs +++ b/src/path.rs @@ -245,7 +245,44 @@ pub mod parsing { return const_argument(input).map(GenericArgument::Const); } - input.parse().map(GenericArgument::Type) + #[cfg(feature = "full")] + let begin = input.fork(); + + let argument: Type = input.parse()?; + + #[cfg(feature = "full")] + { + if match &argument { + Type::Path(argument) + if argument.qself.is_none() + && argument.path.leading_colon.is_none() + && argument.path.segments.len() == 1 => + { + match argument.path.segments[0].arguments { + PathArguments::AngleBracketed(_) => true, + _ => false, + } + } + _ => false, + } { + if if input.peek(Token![=]) { + input.parse::()?; + input.parse::()?; + true + } else if input.peek(Token![:]) { + input.parse::()?; + input.call(constraint_bounds)?; + true + } else { + false + } { + let verbatim = verbatim::between(begin, input); + return Ok(GenericArgument::Type(Type::Verbatim(verbatim))); + } + } + } + + Ok(GenericArgument::Type(argument)) } } @@ -368,26 +405,29 @@ pub mod parsing { Ok(Constraint { ident: input.parse()?, colon_token: input.parse()?, - bounds: { - let mut bounds = Punctuated::new(); - loop { - if input.peek(Token![,]) || input.peek(Token![>]) { - break; - } - let value = input.parse()?; - bounds.push_value(value); - if !input.peek(Token![+]) { - break; - } - let punct = input.parse()?; - bounds.push_punct(punct); - } - bounds - }, + bounds: constraint_bounds(input)?, }) } } + #[cfg(feature = "full")] + fn constraint_bounds(input: ParseStream) -> Result> { + let mut bounds = Punctuated::new(); + loop { + if input.peek(Token![,]) || input.peek(Token![>]) { + break; + } + let value = input.parse()?; + bounds.push_value(value); + if !input.peek(Token![+]) { + break; + } + let punct = input.parse()?; + bounds.push_punct(punct); + } + Ok(bounds) + } + impl Path { /// Parse a `Path` containing no path arguments on any of its segments. /// diff --git a/tests/repo/mod.rs b/tests/repo/mod.rs index eeebbb8279..24b620c51f 100644 --- a/tests/repo/mod.rs +++ b/tests/repo/mod.rs @@ -12,12 +12,6 @@ const REVISION: &str = "52e3dffa50cfffdcfa145c0cc0ba48b49abc0c07"; #[rustfmt::skip] static EXCLUDE: &[&str] = &[ - // TODO: generic associated type equality constraint - // https://github.com/dtolnay/syn/issues/979 - "src/test/pretty/gat-bounds.rs", - "src/test/ui/generic-associated-types/generic-associated-type-bounds.rs", - "src/test/ui/generic-associated-types/issue-80433-reduced.rs", - // Compile-fail expr parameter in const generic position: f::<1 + 2>() "src/test/ui/const-generics/closing-args-token.rs", "src/test/ui/const-generics/const-expression-parameter.rs", From 69e5f706778f99043343607ab10236598a3aba9e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 28 Mar 2021 21:35:19 -0400 Subject: [PATCH 2/2] Resolve collapsible_if lint in generic associated type equality parsing error: this `if` statement can be collapsed --> src/path.rs:255:17 | 255 | / if match &argument { 256 | | Type::Path(argument) 257 | | if argument.qself.is_none() 258 | | && argument.path.leading_colon.is_none() ... | 281 | | } 282 | | } | |_________________^ | = note: `-D clippy::collapsible-if` implied by `-D clippy::all` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if --- src/path.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/path.rs b/src/path.rs index 19522304a6..df1788db53 100644 --- a/src/path.rs +++ b/src/path.rs @@ -264,21 +264,19 @@ pub mod parsing { } } _ => false, + } && if input.peek(Token![=]) { + input.parse::()?; + input.parse::()?; + true + } else if input.peek(Token![:]) { + input.parse::()?; + input.call(constraint_bounds)?; + true + } else { + false } { - if if input.peek(Token![=]) { - input.parse::()?; - input.parse::()?; - true - } else if input.peek(Token![:]) { - input.parse::()?; - input.call(constraint_bounds)?; - true - } else { - false - } { - let verbatim = verbatim::between(begin, input); - return Ok(GenericArgument::Type(Type::Verbatim(verbatim))); - } + let verbatim = verbatim::between(begin, input); + return Ok(GenericArgument::Type(Type::Verbatim(verbatim))); } }