1
- // Detecting language items.
2
- //
3
- // Language items are items that represent concepts intrinsic to the language
4
- // itself. Examples are:
5
- //
6
- // * Traits that specify "kinds"; e.g., "Sync", "Send".
7
- //
8
- // * Traits that represent operators; e.g., "Add", "Sub", "Index".
9
- //
10
- // * Functions called by the compiler itself.
1
+ //! Detecting language items.
2
+ //!
3
+ //! Language items are items that represent concepts intrinsic to the language
4
+ //! itself. Examples are:
5
+ //!
6
+ //! * Traits that specify "kinds"; e.g., "Sync", "Send".
7
+ //!
8
+ //! * Traits that represent operators; e.g., "Add", "Sub", "Index".
9
+ //!
10
+ //! * Functions called by the compiler itself.
11
11
12
12
pub use self :: LangItem :: * ;
13
13
@@ -32,13 +32,17 @@ macro_rules! language_item_table {
32
32
) => {
33
33
34
34
enum_from_u32! {
35
+ /// A representation of all the valid language items in Rust.
35
36
#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash , RustcEncodable , RustcDecodable ) ]
36
37
pub enum LangItem {
37
38
$( $variant, ) *
38
39
}
39
40
}
40
41
41
42
impl LangItem {
43
+ /// Returns the `name` in `#[lang = "$name"]`.
44
+ /// For example, `LangItem::EqTraitLangItem`,
45
+ /// that is `#[lang = "eq"]` would result in `"eq"`.
42
46
fn name( self ) -> & ' static str {
43
47
match self {
44
48
$( $variant => $name, ) *
@@ -48,28 +52,38 @@ impl LangItem {
48
52
49
53
#[ derive( HashStable ) ]
50
54
pub struct LanguageItems {
55
+ /// Mappings from lang items to their possibly found `DefId`s.
56
+ /// The index corresponds to the order in `LangItem`.
51
57
pub items: Vec <Option <DefId >>,
58
+ /// Lang items that were not found during collection.
52
59
pub missing: Vec <LangItem >,
53
60
}
54
61
55
62
impl LanguageItems {
56
- pub fn new( ) -> LanguageItems {
57
- fn foo( _: LangItem ) -> Option <DefId > { None }
63
+ /// Construct an empty collection of lang items and no missing ones.
64
+ pub fn new( ) -> Self {
65
+ fn init_none( _: LangItem ) -> Option <DefId > { None }
58
66
59
- LanguageItems {
60
- items: vec![ $( foo ( $variant) ) ,* ] ,
67
+ Self {
68
+ items: vec![ $( init_none ( $variant) ) ,* ] ,
61
69
missing: Vec :: new( ) ,
62
70
}
63
71
}
64
72
73
+ /// Returns the mappings to the possibly found `DefId`s for each lang item.
65
74
pub fn items( & self ) -> & [ Option <DefId >] {
66
75
& * self . items
67
76
}
68
77
78
+ /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
79
+ /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
80
+ /// returns an error message as a string.
69
81
pub fn require( & self , it: LangItem ) -> Result <DefId , String > {
70
82
self . items[ it as usize ] . ok_or_else( || format!( "requires `{}` lang_item" , it. name( ) ) )
71
83
}
72
84
85
+ /// Returns the kind of closure that `id`, which is one of the `Fn*` traits, corresponds to.
86
+ /// If `id` is not one of the `Fn*` traits, `None` is returned.
73
87
pub fn fn_trait_kind( & self , id: DefId ) -> Option <ty:: ClosureKind > {
74
88
match Some ( id) {
75
89
x if x == self . fn_trait( ) => Some ( ty:: ClosureKind :: Fn ) ,
@@ -80,6 +94,9 @@ impl LanguageItems {
80
94
}
81
95
82
96
$(
97
+ /// Returns the corresponding `DefId` for the lang item
98
+ #[ doc = $name]
99
+ /// if it exists.
83
100
#[ allow( dead_code) ]
84
101
pub fn $method( & self ) -> Option <DefId > {
85
102
self . items[ $variant as usize ]
@@ -90,6 +107,7 @@ impl LanguageItems {
90
107
struct LanguageItemCollector <' a, ' tcx: ' a> {
91
108
items: LanguageItems ,
92
109
tcx: TyCtxt <' a, ' tcx, ' tcx>,
110
+ /// A mapping from the name of the lang item to its order and the form it must be of.
93
111
item_refs: FxHashMap <& ' static str , ( usize , Target ) >,
94
112
}
95
113
@@ -105,32 +123,28 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
105
123
} ,
106
124
// Known lang item with attribute on incorrect target.
107
125
Some ( ( _, expected_target) ) => {
108
- let mut err = struct_span_err!(
126
+ struct_span_err!(
109
127
self . tcx. sess, span, E0718 ,
110
128
"`{}` language item must be applied to a {}" ,
111
129
value, expected_target,
112
- ) ;
113
- err. span_label(
130
+ ) . span_label(
114
131
span,
115
132
format!(
116
133
"attribute should be applied to a {}, not a {}" ,
117
134
expected_target, actual_target,
118
135
) ,
119
- ) ;
120
- err. emit( ) ;
136
+ ) . emit( ) ;
121
137
} ,
122
138
// Unknown lang item.
123
139
_ => {
124
- let mut err = struct_span_err!(
140
+ struct_span_err!(
125
141
self . tcx. sess, span, E0522 ,
126
142
"definition of an unknown language item: `{}`" ,
127
143
value
128
- ) ;
129
- err. span_label(
144
+ ) . span_label(
130
145
span,
131
146
format!( "definition of unknown language item `{}`" , value)
132
- ) ;
133
- err. emit( ) ;
147
+ ) . emit( ) ;
134
148
} ,
135
149
}
136
150
}
@@ -190,32 +204,39 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
190
204
}
191
205
}
192
206
207
+ /// Extract the first `lang = "$name"` out of a list of attributes.
208
+ /// The attributes `#[panic_handler]` and `#[alloc_error_handler]`
209
+ /// are also extracted out when found.
193
210
pub fn extract( attrs: & [ ast:: Attribute ] ) -> Option <( Symbol , Span ) > {
194
- for attribute in attrs {
195
- if attribute. check_name( "lang" ) {
196
- if let Some ( value) = attribute. value_str( ) {
197
- return Some ( ( value, attribute. span) ) ;
198
- }
199
- } else if attribute. check_name( "panic_handler" ) {
200
- return Some ( ( Symbol :: intern( "panic_impl" ) , attribute. span) )
201
- } else if attribute. check_name( "alloc_error_handler" ) {
202
- return Some ( ( Symbol :: intern( "oom" ) , attribute. span) )
203
- }
204
- }
205
-
206
- None
211
+ attrs. iter( ) . find_map( |attr| Some ( match attr {
212
+ _ if attr. check_name( "lang" ) => ( attr. value_str( ) ?, attr. span) ,
213
+ _ if attr. check_name( "panic_handler" ) => ( Symbol :: intern( "panic_impl" ) , attr. span) ,
214
+ _ if attr. check_name( "alloc_error_handler" ) => ( Symbol :: intern( "oom" ) , attr. span) ,
215
+ _ => return None ,
216
+ } ) )
207
217
}
208
218
219
+ /// Traverse and collect all the lang items in all crates.
209
220
pub fn collect<' a, ' tcx>( tcx: TyCtxt <' a, ' tcx, ' tcx>) -> LanguageItems {
221
+ // Initialize the collector.
210
222
let mut collector = LanguageItemCollector :: new( tcx) ;
223
+
224
+ // Collect lang items in other crates.
211
225
for & cnum in tcx. crates( ) . iter( ) {
212
226
for & ( def_id, item_index) in tcx. defined_lang_items( cnum) . iter( ) {
213
227
collector. collect_item( item_index, def_id) ;
214
228
}
215
229
}
230
+
231
+ // Collect lang items in this crate.
216
232
tcx. hir( ) . krate( ) . visit_all_item_likes( & mut collector) ;
233
+
234
+ // Extract out the found lang items.
217
235
let LanguageItemCollector { mut items, .. } = collector;
236
+
237
+ // Find all required but not-yet-defined lang items.
218
238
weak_lang_items:: check_crate( tcx, & mut items) ;
239
+
219
240
items
220
241
}
221
242
@@ -382,6 +403,8 @@ language_item_table! {
382
403
}
383
404
384
405
impl < ' a , ' tcx , ' gcx > TyCtxt < ' a , ' tcx , ' gcx > {
406
+ /// Returns the `DefId` for a given `LangItem`.
407
+ /// If not found, fatally abort compilation.
385
408
pub fn require_lang_item ( & self , lang_item : LangItem ) -> DefId {
386
409
self . lang_items ( ) . require ( lang_item) . unwrap_or_else ( |msg| {
387
410
self . sess . fatal ( & msg)
0 commit comments