From 38d93c76aedde037557b2c31dfc074f99f4ceb76 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 18 Aug 2025 17:15:47 -0700 Subject: [PATCH] Replace ~const syntax with [const] conditionally const syntax --- src/generics.rs | 93 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 25 deletions(-) diff --git a/src/generics.rs b/src/generics.rs index 3f225b8..6c9688b 100644 --- a/src/generics.rs +++ b/src/generics.rs @@ -105,8 +105,7 @@ impl Printer { match type_param_bound { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] TypeParamBound::Trait(trait_bound) => { - let tilde_const = false; - self.trait_bound(trait_bound, tilde_const); + self.trait_bound(trait_bound, TraitBoundConst::None); } TypeParamBound::Lifetime(lifetime) => self.lifetime(lifetime), TypeParamBound::PreciseCapture(precise_capture) => { @@ -117,17 +116,21 @@ impl Printer { } } - fn trait_bound(&mut self, trait_bound: &TraitBound, tilde_const: bool) { + fn trait_bound(&mut self, trait_bound: &TraitBound, constness: TraitBoundConst) { if trait_bound.paren_token.is_some() { self.word("("); } - if tilde_const { - self.word("~const "); - } - self.trait_bound_modifier(&trait_bound.modifier); if let Some(bound_lifetimes) = &trait_bound.lifetimes { self.bound_lifetimes(bound_lifetimes); } + match constness { + TraitBoundConst::None => {} + #[cfg(feature = "verbatim")] + TraitBoundConst::Conditional => self.word("[const] "), + #[cfg(feature = "verbatim")] + TraitBoundConst::Unconditional => self.word("const "), + } + self.trait_bound_modifier(&trait_bound.modifier); for segment in trait_bound.path.segments.iter().delimited() { if !segment.is_first || trait_bound.path.leading_colon.is_some() { self.word("::"); @@ -154,34 +157,67 @@ impl Printer { #[cfg(feature = "verbatim")] fn type_param_bound_verbatim(&mut self, tokens: &TokenStream) { use syn::parse::{Parse, ParseStream, Result}; - use syn::{parenthesized, token, Token}; + use syn::{ + bracketed, parenthesized, token, ParenthesizedGenericArguments, Path, PathArguments, + Token, + }; enum TypeParamBoundVerbatim { Ellipsis, - TildeConst(TraitBound), + Const(TraitBound, TraitBoundConst), } impl Parse for TypeParamBoundVerbatim { fn parse(input: ParseStream) -> Result { + if input.peek(Token![...]) { + input.parse::()?; + return Ok(TypeParamBoundVerbatim::Ellipsis); + } + let content; - let (paren_token, content) = if input.peek(token::Paren) { - (Some(parenthesized!(content in input)), &content) + let content = if input.peek(token::Paren) { + parenthesized!(content in input); + &content } else { - (None, input) + input }; - let lookahead = content.lookahead1(); - if lookahead.peek(Token![~]) { - content.parse::()?; + + let lifetimes: Option = content.parse()?; + + let constness = if content.peek(token::Bracket) { + let conditionally_const; + bracketed!(conditionally_const in content); + conditionally_const.parse::()?; + TraitBoundConst::Conditional + } else if content.peek(Token![const]) { content.parse::()?; - let mut bound: TraitBound = content.parse()?; - bound.paren_token = paren_token; - Ok(TypeParamBoundVerbatim::TildeConst(bound)) - } else if lookahead.peek(Token![...]) { - content.parse::()?; - Ok(TypeParamBoundVerbatim::Ellipsis) + TraitBoundConst::Unconditional } else { - Err(lookahead.error()) + TraitBoundConst::None + }; + + let modifier: TraitBoundModifier = content.parse()?; + + let mut path: Path = content.parse()?; + if path.segments.last().unwrap().arguments.is_empty() + && (content.peek(token::Paren) + || content.peek(Token![::]) && content.peek3(token::Paren)) + { + content.parse::>()?; + let args: ParenthesizedGenericArguments = content.parse()?; + let parenthesized = PathArguments::Parenthesized(args); + path.segments.last_mut().unwrap().arguments = parenthesized; } + + Ok(TypeParamBoundVerbatim::Const( + TraitBound { + paren_token: None, + modifier, + lifetimes, + path, + }, + constness, + )) } } @@ -194,9 +230,8 @@ impl Printer { TypeParamBoundVerbatim::Ellipsis => { self.word("..."); } - TypeParamBoundVerbatim::TildeConst(trait_bound) => { - let tilde_const = true; - self.trait_bound(&trait_bound, tilde_const); + TypeParamBoundVerbatim::Const(trait_bound, constness) => { + self.trait_bound(&trait_bound, constness); } } } @@ -381,3 +416,11 @@ impl Printer { } } } + +enum TraitBoundConst { + None, + #[cfg(feature = "verbatim")] + Conditional, + #[cfg(feature = "verbatim")] + Unconditional, +}