1 #[cfg(feature = "parsing")] 2 use crate::lookahead; 3 use proc_macro2::{Ident, Span}; 4 use std::cmp::Ordering; 5 use std::fmt::{self, Display}; 6 use std::hash::{Hash, Hasher}; 7 8 /// A Rust lifetime: `'a`. 9 /// 10 /// Lifetime names must conform to the following rules: 11 /// 12 /// - Must start with an apostrophe. 13 /// - Must not consist of just an apostrophe: `'`. 14 /// - Character after the apostrophe must be `_` or a Unicode code point with 15 /// the XID_Start property. 16 /// - All following characters must be Unicode code points with the XID_Continue 17 /// property. 18 pub struct Lifetime { 19 pub apostrophe: Span, 20 pub ident: Ident, 21 } 22 23 impl Lifetime { 24 /// # Panics 25 /// 26 /// Panics if the lifetime does not conform to the bulleted rules above. 27 /// 28 /// # Invocation 29 /// 30 /// ``` 31 /// # use proc_macro2::Span; 32 /// # use syn::Lifetime; 33 /// # 34 /// # fn f() -> Lifetime { 35 /// Lifetime::new("'a", Span::call_site()) 36 /// # } 37 /// ``` new(symbol: &str, span: Span) -> Self38 pub fn new(symbol: &str, span: Span) -> Self { 39 if !symbol.starts_with('\'') { 40 panic!( 41 "lifetime name must start with apostrophe as in \"'a\", got {:?}", 42 symbol 43 ); 44 } 45 46 if symbol == "'" { 47 panic!("lifetime name must not be empty"); 48 } 49 50 if !crate::ident::xid_ok(&symbol[1..]) { 51 panic!("{:?} is not a valid lifetime name", symbol); 52 } 53 54 Lifetime { 55 apostrophe: span, 56 ident: Ident::new(&symbol[1..], span), 57 } 58 } 59 span(&self) -> Span60 pub fn span(&self) -> Span { 61 self.apostrophe 62 .join(self.ident.span()) 63 .unwrap_or(self.apostrophe) 64 } 65 set_span(&mut self, span: Span)66 pub fn set_span(&mut self, span: Span) { 67 self.apostrophe = span; 68 self.ident.set_span(span); 69 } 70 } 71 72 impl Display for Lifetime { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result73 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 74 "'".fmt(formatter)?; 75 self.ident.fmt(formatter) 76 } 77 } 78 79 impl Clone for Lifetime { clone(&self) -> Self80 fn clone(&self) -> Self { 81 Lifetime { 82 apostrophe: self.apostrophe, 83 ident: self.ident.clone(), 84 } 85 } 86 } 87 88 impl PartialEq for Lifetime { eq(&self, other: &Lifetime) -> bool89 fn eq(&self, other: &Lifetime) -> bool { 90 self.ident.eq(&other.ident) 91 } 92 } 93 94 impl Eq for Lifetime {} 95 96 impl PartialOrd for Lifetime { partial_cmp(&self, other: &Lifetime) -> Option<Ordering>97 fn partial_cmp(&self, other: &Lifetime) -> Option<Ordering> { 98 Some(self.cmp(other)) 99 } 100 } 101 102 impl Ord for Lifetime { cmp(&self, other: &Lifetime) -> Ordering103 fn cmp(&self, other: &Lifetime) -> Ordering { 104 self.ident.cmp(&other.ident) 105 } 106 } 107 108 impl Hash for Lifetime { hash<H: Hasher>(&self, h: &mut H)109 fn hash<H: Hasher>(&self, h: &mut H) { 110 self.ident.hash(h); 111 } 112 } 113 114 #[cfg(feature = "parsing")] 115 pub_if_not_doc! { 116 #[doc(hidden)] 117 #[allow(non_snake_case)] 118 pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime { 119 match marker {} 120 } 121 } 122 123 #[cfg(feature = "parsing")] 124 pub(crate) mod parsing { 125 use crate::error::Result; 126 use crate::lifetime::Lifetime; 127 use crate::parse::{Parse, ParseStream}; 128 129 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 130 impl Parse for Lifetime { parse(input: ParseStream) -> Result<Self>131 fn parse(input: ParseStream) -> Result<Self> { 132 input.step(|cursor| { 133 cursor 134 .lifetime() 135 .ok_or_else(|| cursor.error("expected lifetime")) 136 }) 137 } 138 } 139 } 140 141 #[cfg(feature = "printing")] 142 mod printing { 143 use crate::lifetime::Lifetime; 144 use proc_macro2::{Punct, Spacing, TokenStream}; 145 use quote::{ToTokens, TokenStreamExt}; 146 147 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 148 impl ToTokens for Lifetime { to_tokens(&self, tokens: &mut TokenStream)149 fn to_tokens(&self, tokens: &mut TokenStream) { 150 let mut apostrophe = Punct::new('\'', Spacing::Joint); 151 apostrophe.set_span(self.apostrophe); 152 tokens.append(apostrophe); 153 self.ident.to_tokens(tokens); 154 } 155 } 156 } 157