Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 68 additions & 25 deletions src/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand All @@ -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("::");
Expand All @@ -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<Self> {
if input.peek(Token![...]) {
input.parse::<Token![...]>()?;
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::<Token![~]>()?;

let lifetimes: Option<BoundLifetimes> = content.parse()?;

let constness = if content.peek(token::Bracket) {
let conditionally_const;
bracketed!(conditionally_const in content);
conditionally_const.parse::<Token![const]>()?;
TraitBoundConst::Conditional
} else if content.peek(Token![const]) {
content.parse::<Token![const]>()?;
let mut bound: TraitBound = content.parse()?;
bound.paren_token = paren_token;
Ok(TypeParamBoundVerbatim::TildeConst(bound))
} else if lookahead.peek(Token![...]) {
content.parse::<Token![...]>()?;
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::<Option<Token![::]>>()?;
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,
))
}
}

Expand All @@ -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);
}
}
}
Expand Down Expand Up @@ -381,3 +416,11 @@ impl Printer {
}
}
}

enum TraitBoundConst {
None,
#[cfg(feature = "verbatim")]
Conditional,
#[cfg(feature = "verbatim")]
Unconditional,
}