From f82a0cf8f06c71263c2caa26e759f337d2778153 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 23 Sep 2026 13:21:41 -0700 Subject: [PATCH] Keep track of nested turbofish depth --- impl/src/attr.rs | 33 ++++++++++++++++++++++++++++++++- tests/test_expr.rs | 15 +++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/impl/src/attr.rs b/impl/src/attr.rs index 7ad83e02..e266759f 100644 --- a/impl/src/attr.rs +++ b/impl/src/attr.rs @@ -195,6 +195,7 @@ fn parse_error_attribute<'a>(attrs: &mut Attrs<'a>, attr: &'a Attribute) -> Resu fn parse_token_expr(input: ParseStream, mut begin_expr: bool) -> Result { let mut tokens = Vec::new(); + let mut turbofish = 0usize; while !input.is_empty() { if input.peek(token::Group) { let group: TokenTree = input.parse()?; @@ -247,6 +248,18 @@ fn parse_token_expr(input: ParseStream, mut begin_expr: bool) -> Result 0 || follows_path_sep(&tokens) { + turbofish += 1; + } + false + } else if turbofish > 0 && input.peek(Token![>]) && !follows_hyphen(&tokens) { + turbofish -= 1; + true + } else { + false + }; + begin_expr = input.peek(Token![break]) || input.peek(Token![continue]) || input.peek(Token![if]) @@ -262,7 +275,7 @@ fn parse_token_expr(input: ParseStream, mut begin_expr: bool) -> Result]) + || input.peek(Token![>]) && !closes_turbofish || input.peek(Token![<]) || input.peek(Token![|]) || input.peek(Token![%]) @@ -299,6 +312,24 @@ fn parse_token_expr(input: ParseStream, mut begin_expr: bool) -> Result bool { + matches!( + tokens.last_chunk(), + Some([TokenTree::Punct(p), TokenTree::Punct(q)]) + if p.spacing() == Spacing::Joint + && p.as_char() == ':' + && q.as_char() == ':', + ) +} + +fn follows_hyphen(tokens: &[TokenTree]) -> bool { + matches!( + tokens.last(), + Some(TokenTree::Punct(p)) + if p.spacing() == Spacing::Joint && p.as_char() == '-', + ) +} + impl ToTokens for Display<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { if self.infinite_recursive { diff --git a/tests/test_expr.rs b/tests/test_expr.rs index 1872fb5a..65b45cca 100644 --- a/tests/test_expr.rs +++ b/tests/test_expr.rs @@ -116,3 +116,18 @@ fn test_assoc_type_equality_constraint() { }, ); } + +// Regression test for https://github.com/dtolnay/thiserror/issues/332 +#[test] +fn test_turbofish() { + #[derive(Error, Debug)] + #[error( + "{} {} {}", + None::.is_some(), + Vec::>::new().len(), + (0..3).filter(|_| Option:: u8>>::None.is_none()).count(), + )] + pub struct Error; + + assert("false 0 3", Error); +}