| extern crate quote; |
| extern crate syn; |
| |
| mod features; |
| |
| #[macro_use] |
| mod macros; |
| |
| use quote::quote; |
| use syn::{Data, DeriveInput}; |
| |
| #[test] |
| fn test_unit() { |
| let input = quote! { |
| struct Unit; |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ vis: Inherited, |
| ⋮ ident: "Unit", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Unit, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| } |
| |
| #[test] |
| fn test_struct() { |
| let input = quote! { |
| #[derive(Debug, Clone)] |
| pub struct Item { |
| pub ident: Ident, |
| pub attrs: Vec<Attribute> |
| } |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ attrs: [ |
| ⋮ Attribute { |
| ⋮ style: Outer, |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "derive", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ tts: `( Debug , Clone )`, |
| ⋮ }, |
| ⋮ ], |
| ⋮ vis: Visibility::Public, |
| ⋮ ident: "Item", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Fields::Named { |
| ⋮ named: [ |
| ⋮ Field { |
| ⋮ vis: Visibility::Public, |
| ⋮ ident: Some("ident"), |
| ⋮ colon_token: Some, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "Ident", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ Field { |
| ⋮ vis: Visibility::Public, |
| ⋮ ident: Some("attrs"), |
| ⋮ colon_token: Some, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "Vec", |
| ⋮ arguments: PathArguments::AngleBracketed { |
| ⋮ args: [ |
| ⋮ Type(Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "Attribute", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }), |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮} |
| "###); |
| |
| snapshot!(input.attrs[0].interpret_meta().unwrap(), @r###" |
| ⋮Meta::List { |
| ⋮ ident: "derive", |
| ⋮ nested: [ |
| ⋮ Meta(Word("Debug")), |
| ⋮ Meta(Word("Clone")), |
| ⋮ ], |
| ⋮} |
| "###); |
| } |
| |
| #[test] |
| fn test_union() { |
| let input = quote! { |
| union MaybeUninit<T> { |
| uninit: (), |
| value: T |
| } |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ vis: Inherited, |
| ⋮ ident: "MaybeUninit", |
| ⋮ generics: Generics { |
| ⋮ lt_token: Some, |
| ⋮ params: [ |
| ⋮ Type(TypeParam { |
| ⋮ ident: "T", |
| ⋮ }), |
| ⋮ ], |
| ⋮ gt_token: Some, |
| ⋮ }, |
| ⋮ data: Data::Union { |
| ⋮ fields: FieldsNamed { |
| ⋮ named: [ |
| ⋮ Field { |
| ⋮ vis: Inherited, |
| ⋮ ident: Some("uninit"), |
| ⋮ colon_token: Some, |
| ⋮ ty: Type::Tuple, |
| ⋮ }, |
| ⋮ Field { |
| ⋮ vis: Inherited, |
| ⋮ ident: Some("value"), |
| ⋮ colon_token: Some, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "T", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮} |
| "###); |
| } |
| |
| #[test] |
| #[cfg(feature = "full")] |
| fn test_enum() { |
| let input = quote! { |
| /// See the std::result module documentation for details. |
| #[must_use] |
| pub enum Result<T, E> { |
| Ok(T), |
| Err(E), |
| Surprise = 0isize, |
| |
| // Smuggling data into a proc_macro_derive, |
| // in the style of https://github.com/dtolnay/proc-macro-hack |
| ProcMacroHack = (0, "data").0 |
| } |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ attrs: [ |
| ⋮ Attribute { |
| ⋮ style: Outer, |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "doc", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ tts: `= r" See the std::result module documentation for details."`, |
| ⋮ }, |
| ⋮ Attribute { |
| ⋮ style: Outer, |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "must_use", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ tts: ``, |
| ⋮ }, |
| ⋮ ], |
| ⋮ vis: Visibility::Public, |
| ⋮ ident: "Result", |
| ⋮ generics: Generics { |
| ⋮ lt_token: Some, |
| ⋮ params: [ |
| ⋮ Type(TypeParam { |
| ⋮ ident: "T", |
| ⋮ }), |
| ⋮ Type(TypeParam { |
| ⋮ ident: "E", |
| ⋮ }), |
| ⋮ ], |
| ⋮ gt_token: Some, |
| ⋮ }, |
| ⋮ data: Data::Enum { |
| ⋮ variants: [ |
| ⋮ Variant { |
| ⋮ ident: "Ok", |
| ⋮ fields: Fields::Unnamed { |
| ⋮ unnamed: [ |
| ⋮ Field { |
| ⋮ vis: Inherited, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "T", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ Variant { |
| ⋮ ident: "Err", |
| ⋮ fields: Fields::Unnamed { |
| ⋮ unnamed: [ |
| ⋮ Field { |
| ⋮ vis: Inherited, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "E", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ Variant { |
| ⋮ ident: "Surprise", |
| ⋮ fields: Unit, |
| ⋮ discriminant: Some(Expr::Lit { |
| ⋮ lit: 0, |
| ⋮ }), |
| ⋮ }, |
| ⋮ Variant { |
| ⋮ ident: "ProcMacroHack", |
| ⋮ fields: Unit, |
| ⋮ discriminant: Some(Expr::Field { |
| ⋮ base: Expr::Tuple { |
| ⋮ elems: [ |
| ⋮ Expr::Lit { |
| ⋮ lit: 0, |
| ⋮ }, |
| ⋮ Expr::Lit { |
| ⋮ lit: "data", |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ member: Unnamed(Index { |
| ⋮ index: 0, |
| ⋮ }), |
| ⋮ }), |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮} |
| "###); |
| |
| let meta_items: Vec<_> = input |
| .attrs |
| .into_iter() |
| .map(|attr| attr.interpret_meta().unwrap()) |
| .collect(); |
| |
| snapshot!(meta_items, @r###" |
| ⋮[ |
| ⋮ Meta::NameValue { |
| ⋮ ident: "doc", |
| ⋮ lit: " See the std::result module documentation for details.", |
| ⋮ }, |
| ⋮ Word("must_use"), |
| ⋮] |
| "###); |
| } |
| |
| #[test] |
| fn test_attr_with_path() { |
| let input = quote! { |
| #[::attr_args::identity |
| fn main() { assert_eq!(foo(), "Hello, world!"); }] |
| struct Dummy; |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ attrs: [ |
| ⋮ Attribute { |
| ⋮ style: Outer, |
| ⋮ path: Path { |
| ⋮ leading_colon: Some, |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "attr_args", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ PathSegment { |
| ⋮ ident: "identity", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ tts: `fn main ( ) { assert_eq ! ( foo ( ) , "Hello, world!" ) ; }`, |
| ⋮ }, |
| ⋮ ], |
| ⋮ vis: Inherited, |
| ⋮ ident: "Dummy", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Unit, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| |
| assert!(input.attrs[0].interpret_meta().is_none()); |
| } |
| |
| #[test] |
| fn test_attr_with_non_mod_style_path() { |
| let input = quote! { |
| #[inert <T>] |
| struct S; |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ attrs: [ |
| ⋮ Attribute { |
| ⋮ style: Outer, |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "inert", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ tts: `< T >`, |
| ⋮ }, |
| ⋮ ], |
| ⋮ vis: Inherited, |
| ⋮ ident: "S", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Unit, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| |
| assert!(input.attrs[0].interpret_meta().is_none()); |
| } |
| |
| #[test] |
| fn test_attr_with_mod_style_path_with_self() { |
| let input = quote! { |
| #[foo::self] |
| struct S; |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ attrs: [ |
| ⋮ Attribute { |
| ⋮ style: Outer, |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "foo", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ PathSegment { |
| ⋮ ident: "self", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ tts: ``, |
| ⋮ }, |
| ⋮ ], |
| ⋮ vis: Inherited, |
| ⋮ ident: "S", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Unit, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| |
| assert!(input.attrs[0].interpret_meta().is_none()); |
| } |
| |
| #[test] |
| fn test_pub_restricted() { |
| // Taken from tests/rust/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs |
| let input = quote! { |
| pub(in m) struct Z(pub(in m::n) u8); |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ vis: Visibility::Restricted { |
| ⋮ in_token: Some, |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "m", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ ident: "Z", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Fields::Unnamed { |
| ⋮ unnamed: [ |
| ⋮ Field { |
| ⋮ vis: Visibility::Restricted { |
| ⋮ in_token: Some, |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "m", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ PathSegment { |
| ⋮ ident: "n", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "u8", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| } |
| |
| #[test] |
| fn test_vis_crate() { |
| let input = quote! { |
| crate struct S; |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ vis: Visibility::Crate, |
| ⋮ ident: "S", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Unit, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| } |
| |
| #[test] |
| fn test_pub_restricted_crate() { |
| let input = quote! { |
| pub(crate) struct S; |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ vis: Visibility::Restricted { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "crate", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ ident: "S", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Unit, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| } |
| |
| #[test] |
| fn test_pub_restricted_super() { |
| let input = quote! { |
| pub(super) struct S; |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ vis: Visibility::Restricted { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "super", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ ident: "S", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Unit, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| } |
| |
| #[test] |
| fn test_pub_restricted_in_super() { |
| let input = quote! { |
| pub(in super) struct S; |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ vis: Visibility::Restricted { |
| ⋮ in_token: Some, |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "super", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ ident: "S", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Unit, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| } |
| |
| #[test] |
| fn test_fields_on_unit_struct() { |
| let input = quote! { |
| struct S; |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ vis: Inherited, |
| ⋮ ident: "S", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Unit, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| |
| let data = match input.data { |
| Data::Struct(data) => data, |
| _ => panic!("expected a struct"), |
| }; |
| |
| assert_eq!(0, data.fields.iter().count()); |
| } |
| |
| #[test] |
| fn test_fields_on_named_struct() { |
| let input = quote! { |
| struct S { |
| foo: i32, |
| pub bar: String, |
| } |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ vis: Inherited, |
| ⋮ ident: "S", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Fields::Named { |
| ⋮ named: [ |
| ⋮ Field { |
| ⋮ vis: Inherited, |
| ⋮ ident: Some("foo"), |
| ⋮ colon_token: Some, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "i32", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ Field { |
| ⋮ vis: Visibility::Public, |
| ⋮ ident: Some("bar"), |
| ⋮ colon_token: Some, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "String", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮} |
| "###); |
| |
| let data = match input.data { |
| Data::Struct(data) => data, |
| _ => panic!("expected a struct"), |
| }; |
| |
| snapshot!(data.fields.into_iter().collect::<Vec<_>>(), @r###" |
| ⋮[ |
| ⋮ Field { |
| ⋮ vis: Inherited, |
| ⋮ ident: Some("foo"), |
| ⋮ colon_token: Some, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "i32", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ Field { |
| ⋮ vis: Visibility::Public, |
| ⋮ ident: Some("bar"), |
| ⋮ colon_token: Some, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "String", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮] |
| "###); |
| } |
| |
| #[test] |
| fn test_fields_on_tuple_struct() { |
| let input = quote! { |
| struct S(i32, pub String); |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ vis: Inherited, |
| ⋮ ident: "S", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Fields::Unnamed { |
| ⋮ unnamed: [ |
| ⋮ Field { |
| ⋮ vis: Inherited, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "i32", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ Field { |
| ⋮ vis: Visibility::Public, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "String", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| |
| let data = match input.data { |
| Data::Struct(data) => data, |
| _ => panic!("expected a struct"), |
| }; |
| |
| snapshot!(data.fields.iter().collect::<Vec<_>>(), @r###" |
| ⋮[ |
| ⋮ Field { |
| ⋮ vis: Inherited, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "i32", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ Field { |
| ⋮ vis: Visibility::Public, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "String", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮] |
| "###); |
| } |
| |
| #[test] |
| fn test_ambiguous_crate() { |
| let input = quote! { |
| // The field type is `(crate::X)` not `crate (::X)`. |
| struct S(crate::X); |
| }; |
| |
| snapshot!(input as DeriveInput, @r###" |
| ⋮DeriveInput { |
| ⋮ vis: Inherited, |
| ⋮ ident: "S", |
| ⋮ generics: Generics, |
| ⋮ data: Data::Struct { |
| ⋮ fields: Fields::Unnamed { |
| ⋮ unnamed: [ |
| ⋮ Field { |
| ⋮ vis: Inherited, |
| ⋮ ty: Type::Path { |
| ⋮ path: Path { |
| ⋮ segments: [ |
| ⋮ PathSegment { |
| ⋮ ident: "crate", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ PathSegment { |
| ⋮ ident: "X", |
| ⋮ arguments: None, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ }, |
| ⋮ }, |
| ⋮ ], |
| ⋮ }, |
| ⋮ semi_token: Some, |
| ⋮ }, |
| ⋮} |
| "###); |
| } |