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