Skip to content

Commit

Permalink
Add infallible expr scanner fallback for scanning invalid code
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Nov 3, 2024
1 parent 60bc0f2 commit c357f97
Showing 1 changed file with 34 additions and 1 deletion.
35 changes: 34 additions & 1 deletion impl/src/fmt.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down Expand Up @@ -119,6 +120,23 @@ impl Display<'_> {
}

fn explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
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::<TokenStream>().unwrap();
Ok(Set::new())
}

fn try_explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
let scan_expr = if is_syn_full() {
|input: ParseStream| input.parse::<Expr>().map(drop)
} else {
Expand All @@ -143,6 +161,21 @@ fn explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
Ok(named_args)
}

fn fallback_explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
let mut named_args = Set::new();

while !input.is_empty() {
if input.peek(Token![,]) && input.peek2(Ident::peek_any) && input.peek3(Token![=]) {
input.parse::<Token![,]>()?;
let ident = input.call(Ident::parse_any)?;
input.parse::<Token![=]>()?;
named_args.insert(ident);
}
}

Ok(named_args)
}

fn is_syn_full() -> bool {
// Expr::Block contains syn::Block which contains Vec<syn::Stmt>. In the
// current version of Syn, syn::Stmt is exhaustive and could only plausibly
Expand Down

0 comments on commit c357f97

Please sign in to comment.