Skip to content

Commit

Permalink
Insert turbofish into paths in expression position
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Aug 17, 2024
1 parent 3bb65aa commit e459ee7
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 72 deletions.
7 changes: 4 additions & 3 deletions src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@ pub(crate) mod parsing {
mod printing {
use crate::attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue};
use crate::path;
use crate::path::printing::PathStyle;
use proc_macro2::TokenStream;
use quote::ToTokens;

Expand All @@ -797,7 +798,7 @@ mod printing {
impl ToTokens for Meta {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
Meta::Path(path) => path::printing::print_mod_style(tokens, path),
Meta::Path(path) => path::printing::print_path(tokens, path, PathStyle::Mod),
Meta::List(meta_list) => meta_list.to_tokens(tokens),
Meta::NameValue(meta_name_value) => meta_name_value.to_tokens(tokens),
}
Expand All @@ -807,15 +808,15 @@ mod printing {
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
impl ToTokens for MetaList {
fn to_tokens(&self, tokens: &mut TokenStream) {
path::printing::print_mod_style(tokens, &self.path);
path::printing::print_path(tokens, &self.path, PathStyle::Mod);
self.delimiter.surround(tokens, self.tokens.clone());
}
}

#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
impl ToTokens for MetaNameValue {
fn to_tokens(&self, tokens: &mut TokenStream) {
path::printing::print_mod_style(tokens, &self.path);
path::printing::print_path(tokens, &self.path, PathStyle::Mod);
self.eq_token.to_tokens(tokens);
self.value.to_tokens(tokens);
}
Expand Down
13 changes: 10 additions & 3 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3013,6 +3013,7 @@ pub(crate) mod printing {
use crate::fixup::FixupContext;
use crate::op::BinOp;
use crate::path;
use crate::path::printing::PathStyle;
use crate::precedence::Precedence;
use crate::token;
#[cfg(feature = "full")]
Expand Down Expand Up @@ -3626,7 +3627,13 @@ pub(crate) mod printing {
);
e.dot_token.to_tokens(tokens);
e.method.to_tokens(tokens);
e.turbofish.to_tokens(tokens);
if let Some(turbofish) = &e.turbofish {
path::printing::print_angle_bracketed_generic_arguments(
tokens,
turbofish,
PathStyle::Expr,
);
}
e.paren_token.surround(tokens, |tokens| {
e.args.to_tokens(tokens);
});
Expand All @@ -3646,7 +3653,7 @@ pub(crate) mod printing {
impl ToTokens for ExprPath {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
path::printing::print_path(tokens, &self.qself, &self.path);
path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
}
}

Expand Down Expand Up @@ -3733,7 +3740,7 @@ pub(crate) mod printing {
impl ToTokens for ExprStruct {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
path::printing::print_path(tokens, &self.qself, &self.path);
path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
self.brace_token.surround(tokens, |tokens| {
self.fields.to_tokens(tokens);
if let Some(dot2_token) = &self.dot2_token {
Expand Down
3 changes: 2 additions & 1 deletion src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2895,6 +2895,7 @@ mod printing {
};
use crate::mac::MacroDelimiter;
use crate::path;
use crate::path::printing::PathStyle;
use crate::print::TokensOrDefault;
use crate::ty::Type;
use proc_macro2::TokenStream;
Expand Down Expand Up @@ -3136,7 +3137,7 @@ mod printing {
impl ToTokens for ItemMacro {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
path::printing::print_mod_style(tokens, &self.mac.path);
path::printing::print_path(tokens, &self.mac.path, PathStyle::Mod);
self.mac.bang_token.to_tokens(tokens);
self.ident.to_tokens(tokens);
match &self.mac.delimiter {
Expand Down
3 changes: 2 additions & 1 deletion src/mac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ pub(crate) mod parsing {
mod printing {
use crate::mac::{Macro, MacroDelimiter};
use crate::path;
use crate::path::printing::PathStyle;
use crate::token;
use proc_macro2::{Delimiter, TokenStream};
use quote::ToTokens;
Expand All @@ -216,7 +217,7 @@ mod printing {
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
impl ToTokens for Macro {
fn to_tokens(&self, tokens: &mut TokenStream) {
path::printing::print_mod_style(tokens, &self.path);
path::printing::print_path(tokens, &self.path, PathStyle::Mod);
self.bang_token.to_tokens(tokens);
self.delimiter.surround(tokens, self.tokens.clone());
}
Expand Down
5 changes: 3 additions & 2 deletions src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,7 @@ mod printing {
PatTuple, PatTupleStruct, PatType, PatWild,
};
use crate::path;
use crate::path::printing::PathStyle;
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};

Expand Down Expand Up @@ -880,7 +881,7 @@ mod printing {
impl ToTokens for PatStruct {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
path::printing::print_path(tokens, &self.qself, &self.path);
path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
self.brace_token.surround(tokens, |tokens| {
self.fields.to_tokens(tokens);
// NOTE: We need a comma before the dot2 token if it is present.
Expand Down Expand Up @@ -915,7 +916,7 @@ mod printing {
impl ToTokens for PatTupleStruct {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(self.attrs.outer());
path::printing::print_path(tokens, &self.qself, &self.path);
path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
self.paren_token.surround(tokens, |tokens| {
self.elems.to_tokens(tokens);
});
Expand Down
182 changes: 122 additions & 60 deletions src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,33 +702,62 @@ pub(crate) mod printing {
use quote::ToTokens;
use std::cmp;

pub(crate) enum PathStyle {
Expr,
Mod,
AsWritten,
}

impl Copy for PathStyle {}

impl Clone for PathStyle {
fn clone(&self) -> Self {
*self
}
}

#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
impl ToTokens for Path {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.leading_colon.to_tokens(tokens);
self.segments.to_tokens(tokens);
print_path(tokens, self, PathStyle::AsWritten);
}
}

pub(crate) fn print_path(tokens: &mut TokenStream, path: &Path, style: PathStyle) {
path.leading_colon.to_tokens(tokens);
for segment in path.segments.pairs() {
print_path_segment(tokens, segment.value(), style);
segment.punct().to_tokens(tokens);
}
}

#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
impl ToTokens for PathSegment {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.ident.to_tokens(tokens);
self.arguments.to_tokens(tokens);
print_path_segment(tokens, self, PathStyle::AsWritten);
}
}

fn print_path_segment(tokens: &mut TokenStream, segment: &PathSegment, style: PathStyle) {
segment.ident.to_tokens(tokens);
print_path_arguments(tokens, &segment.arguments, style);
}

#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
impl ToTokens for PathArguments {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
PathArguments::None => {}
PathArguments::AngleBracketed(arguments) => {
arguments.to_tokens(tokens);
}
PathArguments::Parenthesized(arguments) => {
arguments.to_tokens(tokens);
}
print_path_arguments(tokens, self, PathStyle::AsWritten);
}
}

fn print_path_arguments(tokens: &mut TokenStream, arguments: &PathArguments, style: PathStyle) {
match arguments {
PathArguments::None => {}
PathArguments::AngleBracketed(arguments) => {
print_angle_bracketed_generic_arguments(tokens, arguments, style);
}
PathArguments::Parenthesized(arguments) => {
print_parenthesized_generic_arguments(tokens, arguments, style);
}
}
}
Expand All @@ -753,44 +782,56 @@ pub(crate) mod printing {
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
impl ToTokens for AngleBracketedGenericArguments {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.colon2_token.to_tokens(tokens);
self.lt_token.to_tokens(tokens);

// Print lifetimes before types/consts/bindings, regardless of their
// order in self.args.
let mut trailing_or_empty = true;
for param in self.args.pairs() {
match param.value() {
GenericArgument::Lifetime(_) => {
param.to_tokens(tokens);
trailing_or_empty = param.punct().is_some();
}
GenericArgument::Type(_)
| GenericArgument::Const(_)
| GenericArgument::AssocType(_)
| GenericArgument::AssocConst(_)
| GenericArgument::Constraint(_) => {}
print_angle_bracketed_generic_arguments(tokens, self, PathStyle::AsWritten);
}
}

pub(crate) fn print_angle_bracketed_generic_arguments(
tokens: &mut TokenStream,
arguments: &AngleBracketedGenericArguments,
style: PathStyle,
) {
if let PathStyle::Mod = style {
return;
}

conditionally_print_turbofish(tokens, &arguments.colon2_token, style);
arguments.lt_token.to_tokens(tokens);

// Print lifetimes before types/consts/bindings, regardless of their
// order in args.
let mut trailing_or_empty = true;
for param in arguments.args.pairs() {
match param.value() {
GenericArgument::Lifetime(_) => {
param.to_tokens(tokens);
trailing_or_empty = param.punct().is_some();
}
GenericArgument::Type(_)
| GenericArgument::Const(_)
| GenericArgument::AssocType(_)
| GenericArgument::AssocConst(_)
| GenericArgument::Constraint(_) => {}
}
for param in self.args.pairs() {
match param.value() {
GenericArgument::Type(_)
| GenericArgument::Const(_)
| GenericArgument::AssocType(_)
| GenericArgument::AssocConst(_)
| GenericArgument::Constraint(_) => {
if !trailing_or_empty {
<Token![,]>::default().to_tokens(tokens);
}
param.to_tokens(tokens);
trailing_or_empty = param.punct().is_some();
}
for param in arguments.args.pairs() {
match param.value() {
GenericArgument::Type(_)
| GenericArgument::Const(_)
| GenericArgument::AssocType(_)
| GenericArgument::AssocConst(_)
| GenericArgument::Constraint(_) => {
if !trailing_or_empty {
<Token![,]>::default().to_tokens(tokens);
}
GenericArgument::Lifetime(_) => {}
param.to_tokens(tokens);
trailing_or_empty = param.punct().is_some();
}
GenericArgument::Lifetime(_) => {}
}

self.gt_token.to_tokens(tokens);
}

arguments.gt_token.to_tokens(tokens);
}

#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
Expand Down Expand Up @@ -826,18 +867,36 @@ pub(crate) mod printing {
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
impl ToTokens for ParenthesizedGenericArguments {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.paren_token.surround(tokens, |tokens| {
self.inputs.to_tokens(tokens);
});
self.output.to_tokens(tokens);
print_parenthesized_generic_arguments(tokens, self, PathStyle::AsWritten);
}
}

fn print_parenthesized_generic_arguments(
tokens: &mut TokenStream,
arguments: &ParenthesizedGenericArguments,
style: PathStyle,
) {
if let PathStyle::Mod = style {
return;
}

conditionally_print_turbofish(tokens, &None, style);
arguments.paren_token.surround(tokens, |tokens| {
arguments.inputs.to_tokens(tokens);
});
arguments.output.to_tokens(tokens);
}

pub(crate) fn print_path(tokens: &mut TokenStream, qself: &Option<QSelf>, path: &Path) {
pub(crate) fn print_qpath(
tokens: &mut TokenStream,
qself: &Option<QSelf>,
path: &Path,
style: PathStyle,
) {
let qself = match qself {
Some(qself) => qself,
None => {
path.to_tokens(tokens);
print_path(tokens, path, style);
return;
}
};
Expand All @@ -850,28 +909,31 @@ pub(crate) mod printing {
TokensOrDefault(&qself.as_token).to_tokens(tokens);
path.leading_colon.to_tokens(tokens);
for (i, segment) in segments.by_ref().take(pos).enumerate() {
print_path_segment(tokens, segment.value(), PathStyle::AsWritten);
if i + 1 == pos {
segment.value().to_tokens(tokens);
qself.gt_token.to_tokens(tokens);
segment.punct().to_tokens(tokens);
} else {
segment.to_tokens(tokens);
}
segment.punct().to_tokens(tokens);
}
} else {
qself.gt_token.to_tokens(tokens);
path.leading_colon.to_tokens(tokens);
}
for segment in segments {
segment.to_tokens(tokens);
print_path_segment(tokens, segment.value(), style);
segment.punct().to_tokens(tokens);
}
}

pub(crate) fn print_mod_style(tokens: &mut TokenStream, path: &Path) {
path.leading_colon.to_tokens(tokens);
for segment in path.segments.pairs() {
segment.value().ident.to_tokens(tokens);
segment.punct().to_tokens(tokens);
fn conditionally_print_turbofish(
tokens: &mut TokenStream,
colon2_token: &Option<Token![::]>,
style: PathStyle,
) {
match style {
PathStyle::Expr => TokensOrDefault(colon2_token).to_tokens(tokens),
PathStyle::Mod => unreachable!(),
PathStyle::AsWritten => colon2_token.to_tokens(tokens),
}
}

Expand Down
Loading

0 comments on commit e459ee7

Please sign in to comment.