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.
1111
1212pub use self :: LangItem :: * ;
1313
@@ -32,13 +32,17 @@ macro_rules! language_item_table {
3232 ) => {
3333
3434enum_from_u32! {
35+ /// A representation of all the valid language items in Rust.
3536 #[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash , RustcEncodable , RustcDecodable ) ]
3637 pub enum LangItem {
3738 $( $variant, ) *
3839 }
3940}
4041
4142impl LangItem {
43+ /// Returns the `name` in `#[lang = "$name"]`.
44+ /// For example, `LangItem::EqTraitLangItem`,
45+ /// that is `#[lang = "eq"]` would result in `"eq"`.
4246 fn name( self ) -> & ' static str {
4347 match self {
4448 $( $variant => $name, ) *
@@ -48,28 +52,38 @@ impl LangItem {
4852
4953#[ derive( HashStable ) ]
5054pub struct LanguageItems {
55+ /// Mappings from lang items to their possibly found `DefId`s.
56+ /// The index corresponds to the order in `LangItem`.
5157 pub items: Vec <Option <DefId >>,
58+ /// Lang items that were not found during collection.
5259 pub missing: Vec <LangItem >,
5360}
5461
5562impl 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 }
5866
59- LanguageItems {
60- items: vec![ $( foo ( $variant) ) ,* ] ,
67+ Self {
68+ items: vec![ $( init_none ( $variant) ) ,* ] ,
6169 missing: Vec :: new( ) ,
6270 }
6371 }
6472
73+ /// Returns the mappings to the possibly found `DefId`s for each lang item.
6574 pub fn items( & self ) -> & [ Option <DefId >] {
6675 & * self . items
6776 }
6877
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.
6981 pub fn require( & self , it: LangItem ) -> Result <DefId , String > {
7082 self . items[ it as usize ] . ok_or_else( || format!( "requires `{}` lang_item" , it. name( ) ) )
7183 }
7284
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.
7387 pub fn fn_trait_kind( & self , id: DefId ) -> Option <ty:: ClosureKind > {
7488 match Some ( id) {
7589 x if x == self . fn_trait( ) => Some ( ty:: ClosureKind :: Fn ) ,
@@ -80,6 +94,9 @@ impl LanguageItems {
8094 }
8195
8296 $(
97+ /// Returns the corresponding `DefId` for the lang item
98+ #[ doc = $name]
99+ /// if it exists.
83100 #[ allow( dead_code) ]
84101 pub fn $method( & self ) -> Option <DefId > {
85102 self . items[ $variant as usize ]
@@ -90,6 +107,7 @@ impl LanguageItems {
90107struct LanguageItemCollector <' a, ' tcx: ' a> {
91108 items: LanguageItems ,
92109 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.
93111 item_refs: FxHashMap <& ' static str , ( usize , Target ) >,
94112}
95113
@@ -105,32 +123,28 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
105123 } ,
106124 // Known lang item with attribute on incorrect target.
107125 Some ( ( _, expected_target) ) => {
108- let mut err = struct_span_err!(
126+ struct_span_err!(
109127 self . tcx. sess, span, E0718 ,
110128 "`{}` language item must be applied to a {}" ,
111129 value, expected_target,
112- ) ;
113- err. span_label(
130+ ) . span_label(
114131 span,
115132 format!(
116133 "attribute should be applied to a {}, not a {}" ,
117134 expected_target, actual_target,
118135 ) ,
119- ) ;
120- err. emit( ) ;
136+ ) . emit( ) ;
121137 } ,
122138 // Unknown lang item.
123139 _ => {
124- let mut err = struct_span_err!(
140+ struct_span_err!(
125141 self . tcx. sess, span, E0522 ,
126142 "definition of an unknown language item: `{}`" ,
127143 value
128- ) ;
129- err. span_label(
144+ ) . span_label(
130145 span,
131146 format!( "definition of unknown language item `{}`" , value)
132- ) ;
133- err. emit( ) ;
147+ ) . emit( ) ;
134148 } ,
135149 }
136150 }
@@ -190,32 +204,39 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
190204 }
191205}
192206
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.
193210pub 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+ } ) )
207217}
208218
219+ /// Traverse and collect all the lang items in all crates.
209220pub fn collect<' a, ' tcx>( tcx: TyCtxt <' a, ' tcx, ' tcx>) -> LanguageItems {
221+ // Initialize the collector.
210222 let mut collector = LanguageItemCollector :: new( tcx) ;
223+
224+ // Collect lang items in other crates.
211225 for & cnum in tcx. crates( ) . iter( ) {
212226 for & ( def_id, item_index) in tcx. defined_lang_items( cnum) . iter( ) {
213227 collector. collect_item( item_index, def_id) ;
214228 }
215229 }
230+
231+ // Collect lang items in this crate.
216232 tcx. hir( ) . krate( ) . visit_all_item_likes( & mut collector) ;
233+
234+ // Extract out the found lang items.
217235 let LanguageItemCollector { mut items, .. } = collector;
236+
237+ // Find all required but not-yet-defined lang items.
218238 weak_lang_items:: check_crate( tcx, & mut items) ;
239+
219240 items
220241}
221242
@@ -382,6 +403,8 @@ language_item_table! {
382403}
383404
384405impl < ' a , ' tcx , ' gcx > TyCtxt < ' a , ' tcx , ' gcx > {
406+ /// Returns the `DefId` for a given `LangItem`.
407+ /// If not found, fatally abort compilation.
385408 pub fn require_lang_item ( & self , lang_item : LangItem ) -> DefId {
386409 self . lang_items ( ) . require ( lang_item) . unwrap_or_else ( |msg| {
387410 self . sess . fatal ( & msg)
0 commit comments