From 3871988dfaa9d0f4629038d656ce9ba32ebc6e12 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 25 Jun 2018 23:36:37 +0900 Subject: [PATCH 1/3] Add a test for raw identifiers --- tests/target/raw_identifiers.rs | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tests/target/raw_identifiers.rs diff --git a/tests/target/raw_identifiers.rs b/tests/target/raw_identifiers.rs new file mode 100644 index 000000000000..a798743c514b --- /dev/null +++ b/tests/target/raw_identifiers.rs @@ -0,0 +1,50 @@ +#![feature(custom_attribute)] +#![feature(raw_identifiers)] +#![feature(extern_types)] +#![allow(invalid_type_param_default)] +#![allow(unused_attributes)] + +use r#foo as r#alias_foo; + +fn main() { + #[r#attr] + r#foo::r#bar(); + + let r#local = 3; + let r#async = r#foo(r#local); + r#macro!(); + + if let r#sub_pat @ r#Foo(_) = r#Foo(3) {} + + match r#async { + r#Foo | r#Bar => r#foo(), + } +} + +fn r#bar<'a, r#T>(r#x: &'a r#T) {} + +mod r#foo { + pub fn r#bar() {} +} + +enum r#Foo { + r#Bar {}, +} + +trait r#Trait { + type r#Type; +} + +impl r#Trait for r#Impl { + type r#Type = r#u32; + fn r#xxx(r#fjio: r#u32) {} +} + +extern "C" { + type r#ccc; + static r#static_val: u32; +} + +macro_rules! r#macro { + () => {}; +} From 3027c2137119b8c93252db9cdda35071c74c35db Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 25 Jun 2018 23:36:45 +0900 Subject: [PATCH 2/3] Handle raw identifiers --- src/imports.rs | 24 ++++++------ src/items.rs | 97 +++++++++++++++++++++++++++++++++---------------- src/macros.rs | 18 +++++---- src/patterns.rs | 6 +-- src/reorder.rs | 2 +- src/types.rs | 16 ++++---- src/utils.rs | 8 +++- src/vertical.rs | 4 +- src/visitor.rs | 9 +++-- 9 files changed, 117 insertions(+), 67 deletions(-) diff --git a/src/imports.rs b/src/imports.rs index b8639fdd67e1..ddb7262430d8 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -21,7 +21,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListIte use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; -use utils::mk_sp; +use utils::{mk_sp, rewrite_ident}; use visitor::FmtVisitor; use std::borrow::Cow; @@ -141,9 +141,12 @@ impl UseSegment { } } - fn from_path_segment(path_seg: &ast::PathSegment) -> Option { - let name = path_seg.ident.name.as_str(); - if name == "{{root}}" { + fn from_path_segment( + context: &RewriteContext, + path_seg: &ast::PathSegment, + ) -> Option { + let name = rewrite_ident(context, path_seg.ident); + if name.is_empty() || name == "{{root}}" { return None; } Some(if name == "self" { @@ -231,10 +234,9 @@ impl fmt::Display for UseTree { impl UseTree { // Rewrite use tree with `use ` and a trailing `;`. pub fn rewrite_top_level(&self, context: &RewriteContext, shape: Shape) -> Option { - let vis = self - .visibility - .as_ref() - .map_or(Cow::from(""), |vis| ::utils::format_visibility(&vis)); + let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| { + ::utils::format_visibility(context, &vis) + }); let use_str = self .rewrite(context, shape.offset_left(vis.len())?) .map(|s| { @@ -314,7 +316,7 @@ impl UseTree { attrs, }; for p in &a.prefix.segments { - if let Some(use_segment) = UseSegment::from_path_segment(p) { + if let Some(use_segment) = UseSegment::from_path_segment(context, p) { result.path.push(use_segment); } } @@ -347,12 +349,12 @@ impl UseTree { )); } UseTreeKind::Simple(ref rename, ..) => { - let mut name = (*path_to_imported_ident(&a.prefix).name.as_str()).to_owned(); + let mut name = rewrite_ident(context, path_to_imported_ident(&a.prefix)).to_owned(); let alias = rename.and_then(|ident| { if ident == path_to_imported_ident(&a.prefix) { None } else { - Some(ident.to_string()) + Some(rewrite_ident(context, ident).to_owned()) } }); diff --git a/src/items.rs b/src/items.rs index 05ac3a3fe36c..bef8fd795990 100644 --- a/src/items.rs +++ b/src/items.rs @@ -233,7 +233,7 @@ impl<'a> FnSig<'a> { fn to_str(&self, context: &RewriteContext) -> String { let mut result = String::with_capacity(128); // Vis defaultness constness unsafety abi. - result.push_str(&*format_visibility(&self.visibility)); + result.push_str(&*format_visibility(context, &self.visibility)); result.push_str(format_defaultness(self.defaultness)); result.push_str(format_constness(self.constness)); result.push_str(format_unsafety(self.unsafety)); @@ -437,7 +437,7 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, span: Span, ) { - let enum_header = format_header("enum ", ident, vis); + let enum_header = format_header(&self.get_context(), "enum ", ident, vis); self.push_str(&enum_header); let enum_snippet = self.snippet(span); @@ -571,10 +571,10 @@ impl<'a> FmtVisitor<'a> { )?, ast::VariantData::Unit(..) => { if let Some(ref expr) = field.node.disr_expr { - let lhs = format!("{} =", field.node.ident.name); + let lhs = format!("{} =", rewrite_ident(&context, field.node.ident)); rewrite_assign_rhs(&context, lhs, &*expr.value, shape)? } else { - field.node.ident.name.to_string() + rewrite_ident(&context, field.node.ident).to_owned() } } }; @@ -797,7 +797,7 @@ fn format_impl_ref_and_type( { let mut result = String::with_capacity(128); - result.push_str(&format_visibility(&item.vis)); + result.push_str(&format_visibility(context, &item.vis)); result.push_str(format_defaultness(defaultness)); result.push_str(format_unsafety(unsafety)); @@ -916,8 +916,8 @@ pub struct StructParts<'a> { } impl<'a> StructParts<'a> { - fn format_header(&self) -> String { - format_header(self.prefix, self.ident, self.vis) + fn format_header(&self, context: &RewriteContext) -> String { + format_header(context, self.prefix, self.ident, self.vis) } fn from_variant(variant: &'a ast::Variant) -> Self { @@ -977,7 +977,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let mut result = String::with_capacity(128); let header = format!( "{}{}{}trait ", - format_visibility(&item.vis), + format_visibility(context, &item.vis), format_unsafety(unsafety), format_auto(is_auto), ); @@ -988,7 +988,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let shape = Shape::indented(offset, context.config).offset_left(result.len())?; let generics_str = rewrite_generics( context, - &item.ident.to_string(), + rewrite_ident(context, item.ident), generics, shape, mk_sp(item.span.lo(), body_lo), @@ -999,7 +999,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if !generic_bounds.is_empty() { let ident_hi = context .snippet_provider - .span_after(item.span, &format!("{}", item.ident)); + .span_after(item.span, &item.ident.as_str()); let bound_hi = generic_bounds.last().unwrap().span().hi(); let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); if contains_comment(snippet) { @@ -1135,7 +1135,7 @@ pub fn format_trait_alias( generic_bounds: &ast::GenericBounds, shape: Shape, ) -> Option { - let alias = ident.name.as_str(); + let alias = rewrite_ident(context, ident); // 6 = "trait ", 2 = " =" let g_shape = shape.offset_left(6)?.sub_width(2)?; let generics_str = rewrite_generics(context, &alias, generics, g_shape, generics.span)?; @@ -1145,7 +1145,7 @@ pub fn format_trait_alias( } fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option { - let header_str = format_header(p.prefix, p.ident, p.vis); + let header_str = format_header(context, p.prefix, p.ident, p.vis); let generics_str = if let Some(generics) = p.generics { let hi = if generics.where_clause.predicates.is_empty() { generics.span.hi() @@ -1177,7 +1177,7 @@ pub fn format_struct_struct( let mut result = String::with_capacity(1024); let span = struct_parts.span; - let header_str = struct_parts.format_header(); + let header_str = struct_parts.format_header(context); result.push_str(&header_str); let header_hi = span.lo() + BytePos(header_str.len() as u32); @@ -1312,7 +1312,7 @@ fn format_tuple_struct( let mut result = String::with_capacity(1024); let span = struct_parts.span; - let header_str = struct_parts.format_header(); + let header_str = struct_parts.format_header(context); result.push_str(&header_str); let body_lo = if fields.is_empty() { @@ -1413,7 +1413,7 @@ pub fn rewrite_type_alias( ) -> Option { let mut result = String::with_capacity(128); - result.push_str(&format_visibility(vis)); + result.push_str(&format_visibility(context, vis)); result.push_str("type "); // 2 = `= ` @@ -1424,7 +1424,13 @@ pub fn rewrite_type_alias( context.snippet_provider.span_after(span, "type"), ty.span.lo(), ); - let generics_str = rewrite_generics(context, &ident.to_string(), generics, g_shape, g_span)?; + let generics_str = rewrite_generics( + context, + rewrite_ident(context, ident), + generics, + g_shape, + g_span, + )?; result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); @@ -1467,10 +1473,15 @@ pub fn rewrite_struct_field_prefix( context: &RewriteContext, field: &ast::StructField, ) -> Option { - let vis = format_visibility(&field.vis); + let vis = format_visibility(context, &field.vis); let type_annotation_spacing = type_annotation_spacing(context.config); Some(match field.ident { - Some(name) => format!("{}{}{}:", vis, name, type_annotation_spacing.0), + Some(name) => format!( + "{}{}{}:", + vis, + rewrite_ident(context, name), + type_annotation_spacing.0 + ), None => format!("{}", vis), }) } @@ -1623,7 +1634,7 @@ fn rewrite_static( ); let mut prefix = format!( "{}{}{} {}{}{}", - format_visibility(static_parts.vis), + format_visibility(context, static_parts.vis), static_parts.defaultness.map_or("", format_defaultness), static_parts.prefix, format_mutability(static_parts.mutability), @@ -1673,7 +1684,7 @@ pub fn rewrite_associated_type( context: &RewriteContext, indent: Indent, ) -> Option { - let prefix = format!("type {}", ident); + let prefix = format!("type {}", rewrite_ident(context, ident)); let type_bounds_str = if let Some(bounds) = generic_bounds_opt { if bounds.is_empty() { @@ -1881,8 +1892,13 @@ fn rewrite_fn_base( }; let fd = fn_sig.decl; let g_span = mk_sp(span.lo(), fd.output.span().lo()); - let generics_str = - rewrite_generics(context, &ident.to_string(), fn_sig.generics, shape, g_span)?; + let generics_str = rewrite_generics( + context, + rewrite_ident(context, ident), + fn_sig.generics, + shape, + g_span, + )?; result.push_str(&generics_str); let snuggle_angle_bracket = generics_str @@ -2665,8 +2681,18 @@ fn rewrite_comments_before_after_where( Some((before_comment, after_comment)) } -fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { - format!("{}{}{}", format_visibility(vis), item_name, ident) +fn format_header( + context: &RewriteContext, + item_name: &str, + ident: ast::Ident, + vis: &ast::Visibility, +) -> String { + format!( + "{}{}{}", + format_visibility(context, vis), + item_name, + rewrite_ident(context, ident) + ) } #[derive(PartialEq, Eq, Clone, Copy)] @@ -2771,15 +2797,24 @@ impl Rewrite for ast::ForeignItem { ast::ForeignItemKind::Static(ref ty, is_mutable) => { // FIXME(#21): we're dropping potential comments in between the // function keywords here. - let vis = format_visibility(&self.vis); + let vis = format_visibility(context, &self.vis); let mut_str = if is_mutable { "mut " } else { "" }; - let prefix = format!("{}static {}{}:", vis, mut_str, self.ident); + let prefix = format!( + "{}static {}{}:", + vis, + mut_str, + rewrite_ident(context, self.ident) + ); // 1 = ; rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";") } ast::ForeignItemKind::Ty => { - let vis = format_visibility(&self.vis); - Some(format!("{}type {};", vis, self.ident)) + let vis = format_visibility(context, &self.vis); + Some(format!( + "{}type {};", + vis, + rewrite_ident(context, self.ident) + )) } ast::ForeignItemKind::Macro(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Item) @@ -2803,11 +2838,11 @@ impl Rewrite for ast::ForeignItem { } /// Rewrite an inline mod. -pub fn rewrite_mod(item: &ast::Item) -> String { +pub fn rewrite_mod(context: &RewriteContext, item: &ast::Item) -> String { let mut result = String::with_capacity(32); - result.push_str(&*format_visibility(&item.vis)); + result.push_str(&*format_visibility(context, &item.vis)); result.push_str("mod "); - result.push_str(&item.ident.to_string()); + result.push_str(rewrite_ident(context, item.ident)); result.push(';'); result } diff --git a/src/macros.rs b/src/macros.rs index 512c3ac1c56e..e3539d3b6991 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -43,7 +43,7 @@ use overflow; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; -use utils::{format_visibility, mk_sp, wrap_str}; +use utils::{format_visibility, mk_sp, rewrite_ident, wrap_str}; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; @@ -116,10 +116,14 @@ fn parse_macro_arg(parser: &mut Parser) -> Option { } /// Rewrite macro name without using pretty-printer if possible. -fn rewrite_macro_name(path: &ast::Path, extra_ident: Option) -> String { +fn rewrite_macro_name( + context: &RewriteContext, + path: &ast::Path, + extra_ident: Option, +) -> String { let name = if path.segments.len() == 1 { // Avoid using pretty-printer in the common case. - format!("{}!", path.segments[0].ident) + format!("{}!", rewrite_ident(context, path.segments[0].ident)) } else { format!("{}!", path) }; @@ -170,7 +174,7 @@ pub fn rewrite_macro_inner( let original_style = macro_style(mac, context); - let macro_name = rewrite_macro_name(&mac.node.path, extra_ident); + let macro_name = rewrite_macro_name(context, &mac.node.path, extra_ident); let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { DelimToken::Bracket @@ -361,11 +365,11 @@ pub fn rewrite_macro_def( let mut result = if def.legacy { String::from("macro_rules!") } else { - format!("{}macro", format_visibility(vis)) + format!("{}macro", format_visibility(context, vis)) }; result += " "; - result += &ident.name.as_str(); + result += rewrite_ident(context, ident); let multi_branch_style = def.legacy || parsed_def.branches.len() != 1; @@ -1339,7 +1343,7 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) while parser.token != Token::Eof { // Parse a `lazy_static!` item. - let vis = ::utils::format_visibility(&parse_or!(parse_visibility, false)); + let vis = ::utils::format_visibility(context, &parse_or!(parse_visibility, false)); parser.eat_keyword(symbol::keywords::Static); parser.eat_keyword(symbol::keywords::Ref); let id = parse_or!(parse_ident); diff --git a/src/patterns.rs b/src/patterns.rs index fcab484287c8..943434b68eca 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -28,7 +28,7 @@ use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; use types::{rewrite_path, PathContext}; -use utils::{format_mutability, mk_sp}; +use utils::{format_mutability, mk_sp, rewrite_ident}; /// Returns true if the given pattern is short. A short pattern is defined by the following grammer: /// @@ -74,7 +74,7 @@ impl Rewrite for Pat { BindingMode::ByValue(mutability) => ("", mutability), }; let mut_infix = format_mutability(mutability); - let id_str = ident.name.to_string(); + let id_str = rewrite_ident(context, ident); let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. @@ -246,7 +246,7 @@ impl Rewrite for FieldPat { pat } else { let pat_str = pat?; - let id_str = self.ident.to_string(); + let id_str = rewrite_ident(context, self.ident); let one_line_width = id_str.len() + 2 + pat_str.len(); if one_line_width <= shape.width { Some(format!("{}: {}", id_str, pat_str)) diff --git a/src/reorder.rs b/src/reorder.rs index 3d2b098781de..9908c402a43c 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -100,7 +100,7 @@ fn rewrite_reorderable_item( let item_str = match item.node { ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, - ast::ItemKind::Mod(..) => rewrite_mod(item), + ast::ItemKind::Mod(..) => rewrite_mod(context, item), _ => return None, }; diff --git a/src/types.rs b/src/types.rs index 20c6cebeefdb..3608d582d980 100644 --- a/src/types.rs +++ b/src/types.rs @@ -29,7 +29,7 @@ use shape::Shape; use spanned::Spanned; use utils::{ colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, last_line_width, - mk_sp, + mk_sp, rewrite_ident, }; #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -187,8 +187,10 @@ impl<'a> Rewrite for SegmentParam<'a> { SegmentParam::Type(ty) => ty.rewrite(context, shape), SegmentParam::Binding(binding) => { let mut result = match context.config.type_punctuation_density() { - TypeDensity::Wide => format!("{} = ", binding.ident), - TypeDensity::Compressed => format!("{}=", binding.ident), + TypeDensity::Wide => format!("{} = ", rewrite_ident(context, binding.ident)), + TypeDensity::Compressed => { + format!("{}=", rewrite_ident(context, binding.ident)) + } }; let budget = shape.width.checked_sub(result.len())?; let rewrite = binding @@ -220,7 +222,7 @@ fn rewrite_segment( shape: Shape, ) -> Option { let mut result = String::with_capacity(128); - result.push_str(&segment.ident.name.as_str()); + result.push_str(rewrite_ident(context, segment.ident)); let ident_len = result.len(); let shape = if context.use_block_indent() { @@ -496,8 +498,8 @@ fn rewrite_bounded_lifetime( } impl Rewrite for ast::Lifetime { - fn rewrite(&self, _: &RewriteContext, _: Shape) -> Option { - Some(self.ident.to_string()) + fn rewrite(&self, context: &RewriteContext, _: Shape) -> Option { + Some(rewrite_ident(context, self.ident).to_owned()) } } @@ -532,7 +534,7 @@ impl Rewrite for ast::GenericParam { Some(ref rw) if !rw.is_empty() => result.push_str(&format!("{} ", rw)), _ => (), } - result.push_str(&self.ident.to_string()); + result.push_str(rewrite_ident(context, self.ident)); if !self.bounds.is_empty() { result.push_str(type_bound_colon(context)); result.push_str(&self.bounds.rewrite(context, shape)?) diff --git a/src/utils.rs b/src/utils.rs index 127a7ddb59e1..a8f8592d2f2f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -24,6 +24,10 @@ use shape::Shape; pub const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; pub const SKIP_ANNOTATION: &str = "rustfmt::skip"; +pub fn rewrite_ident<'a>(context: &'a RewriteContext, ident: ast::Ident) -> &'a str { + context.snippet(ident.span) +} + // Computes the length of a string's last line, minus offset. pub fn extra_offset(text: &str, shape: Shape) -> usize { match text.rfind('\n') { @@ -34,7 +38,7 @@ pub fn extra_offset(text: &str, shape: Shape) -> usize { } // Uses Cow to avoid allocating in the common cases. -pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { +pub fn format_visibility(context: &RewriteContext, vis: &Visibility) -> Cow<'static, str> { match vis.node { VisibilityKind::Public => Cow::from("pub "), VisibilityKind::Inherited => Cow::from(""), @@ -42,7 +46,7 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { VisibilityKind::Crate(CrateSugar::JustCrate) => Cow::from("crate "), VisibilityKind::Restricted { ref path, .. } => { let Path { ref segments, .. } = **path; - let mut segments_iter = segments.iter().map(|seg| seg.ident.name.to_string()); + let mut segments_iter = segments.iter().map(|seg| rewrite_ident(context, seg.ident)); if path.is_global() { segments_iter .next() diff --git a/src/vertical.rs b/src/vertical.rs index a8a8ee6cec3c..58422d782ac9 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -24,7 +24,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separat use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; -use utils::{contains_skip, is_attributes_extendable, mk_sp}; +use utils::{contains_skip, is_attributes_extendable, mk_sp, rewrite_ident}; pub trait AlignedItem { fn skip(&self) -> bool; @@ -88,7 +88,7 @@ impl AlignedItem for ast::Field { fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { let attrs_str = self.attrs.rewrite(context, shape)?; - let name = &self.ident.name.to_string(); + let name = rewrite_ident(context, self.ident); let missing_span = if self.attrs.is_empty() { mk_sp(self.span.lo(), self.span.lo()) } else { diff --git a/src/visitor.rs b/src/visitor.rs index c58122025de7..76fd3395ba9c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -28,7 +28,7 @@ use shape::{Indent, Shape}; use spanned::Spanned; use utils::{ self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec, - DEPR_SKIP_ANNOTATION, + rewrite_ident, DEPR_SKIP_ANNOTATION, }; use {ErrorKind, FormatReport, FormattingError}; @@ -682,9 +682,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { attrs: &[ast::Attribute], is_internal: bool, ) { - self.push_str(&*utils::format_visibility(vis)); + let vis_str = utils::format_visibility(&self.get_context(), vis); + self.push_str(&*vis_str); self.push_str("mod "); - self.push_str(&ident.to_string()); + // Calling `to_owned()` to work around borrow checker. + let ident_str = rewrite_ident(&self.get_context(), ident).to_owned(); + self.push_str(&ident_str); if is_internal { match self.config.brace_style() { From eb168f608a11972ca208a84a445b18d8c0cdce60 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 25 Jun 2018 23:41:44 +0900 Subject: [PATCH 3/3] Add more tests --- tests/target/raw_identifiers.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/target/raw_identifiers.rs b/tests/target/raw_identifiers.rs index a798743c514b..4abb22b88b7a 100644 --- a/tests/target/raw_identifiers.rs +++ b/tests/target/raw_identifiers.rs @@ -31,6 +31,10 @@ enum r#Foo { r#Bar {}, } +struct r#Struct { + r#field: r#FieldType, +} + trait r#Trait { type r#Type; } @@ -48,3 +52,10 @@ extern "C" { macro_rules! r#macro { () => {}; } + +macro_rules! foo { + ($x:expr) => { + let r#catch = $x + 1; + println!("{}", r#catch); + }; +}