From c357f9728e4c5497dec5128d8ed258b82bbd163a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 2 Nov 2024 21:05:30 -0700 Subject: [PATCH 1/2] Add infallible expr scanner fallback for scanning invalid code --- impl/src/fmt.rs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/impl/src/fmt.rs b/impl/src/fmt.rs index df75044..a15aeb6 100644 --- a/impl/src/fmt.rs +++ b/impl/src/fmt.rs @@ -1,10 +1,11 @@ use crate::ast::Field; use crate::attr::{Display, Trait}; use crate::scan_expr; -use proc_macro2::TokenTree; +use proc_macro2::{TokenStream, TokenTree}; use quote::{format_ident, quote, quote_spanned}; use std::collections::{BTreeSet as Set, HashMap as Map}; use syn::ext::IdentExt; +use syn::parse::discouraged::Speculative; use syn::parse::{ParseStream, Parser}; use syn::{Expr, Ident, Index, LitStr, Member, Result, Token}; @@ -119,6 +120,23 @@ impl Display<'_> { } fn explicit_named_args(input: ParseStream) -> Result> { + let ahead = input.fork(); + if let Ok(set) = try_explicit_named_args(&ahead) { + input.advance_to(&ahead); + return Ok(set); + } + + let ahead = input.fork(); + if let Ok(set) = fallback_explicit_named_args(&ahead) { + input.advance_to(&ahead); + return Ok(set); + } + + input.parse::().unwrap(); + Ok(Set::new()) +} + +fn try_explicit_named_args(input: ParseStream) -> Result> { let scan_expr = if is_syn_full() { |input: ParseStream| input.parse::().map(drop) } else { @@ -143,6 +161,21 @@ fn explicit_named_args(input: ParseStream) -> Result> { Ok(named_args) } +fn fallback_explicit_named_args(input: ParseStream) -> Result> { + let mut named_args = Set::new(); + + while !input.is_empty() { + if input.peek(Token![,]) && input.peek2(Ident::peek_any) && input.peek3(Token![=]) { + input.parse::()?; + let ident = input.call(Ident::parse_any)?; + input.parse::()?; + named_args.insert(ident); + } + } + + Ok(named_args) +} + fn is_syn_full() -> bool { // Expr::Block contains syn::Block which contains Vec. In the // current version of Syn, syn::Stmt is exhaustive and could only plausibly From 0ab908aab0dc12415ce34241fdc23bb722bd0eba Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 2 Nov 2024 21:12:28 -0700 Subject: [PATCH 2/2] Ignore expected unnecessary_wraps pedantic clippy lint warning: this function's return value is unnecessarily wrapped by `Result` --> impl/src/fmt.rs:122:1 | 122 | / fn explicit_named_args(input: ParseStream) -> Result> { 123 | | let ahead = input.fork(); 124 | | if let Ok(set) = try_explicit_named_args(&ahead) { 125 | | input.advance_to(&ahead); ... | 136 | | Ok(Set::new()) 137 | | } | |_^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps = note: `-W clippy::unnecessary-wraps` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::unnecessary_wraps)]` help: remove `Result` from the return type... | 122 | fn explicit_named_args(input: ParseStream) -> std::collections::BTreeSet { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ help: ...and then change returning expressions | 126 ~ return set; 127 | } ... 131 | input.advance_to(&ahead); 132 ~ return set; 133 | } 134 | 135 | input.parse::().unwrap(); 136 ~ Set::new() | --- impl/src/fmt.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/impl/src/fmt.rs b/impl/src/fmt.rs index a15aeb6..153a423 100644 --- a/impl/src/fmt.rs +++ b/impl/src/fmt.rs @@ -119,6 +119,7 @@ impl Display<'_> { } } +#[allow(clippy::unnecessary_wraps)] fn explicit_named_args(input: ParseStream) -> Result> { let ahead = input.fork(); if let Ok(set) = try_explicit_named_args(&ahead) {