]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | // Detecting language items. |
2 | // | |
3 | // Language items are items that represent concepts intrinsic to the language | |
4 | // itself. Examples are: | |
5 | // | |
0731742a | 6 | // * Traits that specify "kinds"; e.g., "Sync", "Send". |
223e47cc | 7 | // |
0731742a | 8 | // * Traits that represent operators; e.g., "Add", "Sub", "Index". |
223e47cc LB |
9 | // |
10 | // * Functions called by the compiler itself. | |
11 | ||
1a4d82fc | 12 | pub use self::LangItem::*; |
223e47cc | 13 | |
9fa01778 XL |
14 | use crate::hir::def_id::DefId; |
15 | use crate::hir::check_attr::Target; | |
16 | use crate::ty::{self, TyCtxt}; | |
17 | use crate::middle::weak_lang_items; | |
18 | use crate::util::nodemap::FxHashMap; | |
223e47cc | 19 | |
b039eaaf | 20 | use syntax::ast; |
476ff2be | 21 | use syntax::symbol::Symbol; |
2c00a5a8 | 22 | use syntax_pos::Span; |
9fa01778 XL |
23 | use crate::hir::itemlikevisit::ItemLikeVisitor; |
24 | use crate::hir; | |
1a4d82fc | 25 | |
1a4d82fc JJ |
26 | // The actual lang items defined come at the end of this file in one handy table. |
27 | // So you probably just want to nip down to the end. | |
3157f602 | 28 | macro_rules! language_item_table { |
1a4d82fc | 29 | ( |
0bf4aa26 | 30 | $( $variant:ident, $name:expr, $method:ident, $target:path; )* |
1a4d82fc JJ |
31 | ) => { |
32 | ||
9346a6ac | 33 | enum_from_u32! { |
ff7c6d11 | 34 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
9346a6ac AL |
35 | pub enum LangItem { |
36 | $($variant,)* | |
37 | } | |
223e47cc LB |
38 | } |
39 | ||
ea8adc8c XL |
40 | impl LangItem { |
41 | fn name(self) -> &'static str { | |
42 | match self { | |
43 | $( $variant => $name, )* | |
44 | } | |
45 | } | |
46 | } | |
47 | ||
223e47cc | 48 | pub struct LanguageItems { |
e9174d1e | 49 | pub items: Vec<Option<DefId>>, |
1a4d82fc | 50 | pub missing: Vec<LangItem>, |
223e47cc LB |
51 | } |
52 | ||
970d7e83 | 53 | impl LanguageItems { |
223e47cc | 54 | pub fn new() -> LanguageItems { |
e9174d1e | 55 | fn foo(_: LangItem) -> Option<DefId> { None } |
1a4d82fc | 56 | |
223e47cc | 57 | LanguageItems { |
c30ab7b3 | 58 | items: vec![$(foo($variant)),*], |
1a4d82fc | 59 | missing: Vec::new(), |
223e47cc LB |
60 | } |
61 | } | |
62 | ||
7453a54e SL |
63 | pub fn items(&self) -> &[Option<DefId>] { |
64 | &*self.items | |
223e47cc LB |
65 | } |
66 | ||
e9174d1e | 67 | pub fn require(&self, it: LangItem) -> Result<DefId, String> { |
ea8adc8c | 68 | self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name())) |
c1a9b12d SL |
69 | } |
70 | ||
e9174d1e | 71 | pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> { |
ea8adc8c XL |
72 | match Some(id) { |
73 | x if x == self.fn_trait() => Some(ty::ClosureKind::Fn), | |
74 | x if x == self.fn_mut_trait() => Some(ty::ClosureKind::FnMut), | |
75 | x if x == self.fn_once_trait() => Some(ty::ClosureKind::FnOnce), | |
76 | _ => None | |
1a4d82fc | 77 | } |
223e47cc | 78 | } |
1a4d82fc JJ |
79 | |
80 | $( | |
81 | #[allow(dead_code)] | |
e9174d1e | 82 | pub fn $method(&self) -> Option<DefId> { |
c34b1796 | 83 | self.items[$variant as usize] |
1a4d82fc JJ |
84 | } |
85 | )* | |
223e47cc LB |
86 | } |
87 | ||
b039eaaf | 88 | struct LanguageItemCollector<'a, 'tcx: 'a> { |
970d7e83 | 89 | items: LanguageItems, |
ea8adc8c | 90 | tcx: TyCtxt<'a, 'tcx, 'tcx>, |
0bf4aa26 | 91 | item_refs: FxHashMap<&'static str, (usize, Target)>, |
223e47cc LB |
92 | } |
93 | ||
476ff2be | 94 | impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { |
e9174d1e | 95 | fn visit_item(&mut self, item: &hir::Item) { |
2c00a5a8 | 96 | if let Some((value, span)) = extract(&item.attrs) { |
0bf4aa26 XL |
97 | let actual_target = Target::from_item(item); |
98 | match self.item_refs.get(&*value.as_str()).cloned() { | |
99 | // Known lang item with attribute on correct target. | |
100 | Some((item_index, expected_target)) if actual_target == expected_target => { | |
0731742a | 101 | let def_id = self.tcx.hir().local_def_id(item.id); |
0bf4aa26 XL |
102 | self.collect_item(item_index, def_id); |
103 | }, | |
104 | // Known lang item with attribute on incorrect target. | |
105 | Some((_, expected_target)) => { | |
106 | let mut err = struct_span_err!( | |
107 | self.tcx.sess, span, E0718, | |
108 | "`{}` language item must be applied to a {}", | |
109 | value, expected_target, | |
110 | ); | |
111 | err.span_label( | |
112 | span, | |
113 | format!( | |
114 | "attribute should be applied to a {}, not a {}", | |
115 | expected_target, actual_target, | |
116 | ), | |
117 | ); | |
118 | err.emit(); | |
119 | }, | |
120 | // Unknown lang item. | |
121 | _ => { | |
122 | let mut err = struct_span_err!( | |
123 | self.tcx.sess, span, E0522, | |
124 | "definition of an unknown language item: `{}`", | |
125 | value | |
126 | ); | |
127 | err.span_label( | |
128 | span, | |
129 | format!("definition of unknown language item `{}`", value) | |
130 | ); | |
131 | err.emit(); | |
132 | }, | |
1a4d82fc | 133 | } |
1a4d82fc | 134 | } |
1a4d82fc | 135 | } |
476ff2be | 136 | |
32a655c1 SL |
137 | fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { |
138 | // at present, lang items are always items, not trait items | |
139 | } | |
140 | ||
476ff2be SL |
141 | fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { |
142 | // at present, lang items are always items, not impl items | |
143 | } | |
1a4d82fc JJ |
144 | } |
145 | ||
b039eaaf | 146 | impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { |
ea8adc8c | 147 | fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItemCollector<'a, 'tcx> { |
0bf4aa26 | 148 | let mut item_refs = FxHashMap::default(); |
1a4d82fc | 149 | |
0bf4aa26 | 150 | $( item_refs.insert($name, ($variant as usize, $target)); )* |
970d7e83 LB |
151 | |
152 | LanguageItemCollector { | |
ea8adc8c | 153 | tcx, |
970d7e83 | 154 | items: LanguageItems::new(), |
041b39d2 | 155 | item_refs, |
970d7e83 LB |
156 | } |
157 | } | |
158 | ||
ea8adc8c | 159 | fn collect_item(&mut self, item_index: usize, item_def_id: DefId) { |
223e47cc | 160 | // Check for duplicates. |
0bf4aa26 XL |
161 | if let Some(original_def_id) = self.items.items[item_index] { |
162 | if original_def_id != item_def_id { | |
ea8adc8c | 163 | let name = LangItem::from_u32(item_index as u32).unwrap().name(); |
0731742a | 164 | let mut err = match self.tcx.hir().span_if_local(item_def_id) { |
a7813a04 | 165 | Some(span) => struct_span_err!( |
ea8adc8c | 166 | self.tcx.sess, |
a7813a04 XL |
167 | span, |
168 | E0152, | |
169 | "duplicate lang item found: `{}`.", | |
170 | name), | |
ea8adc8c | 171 | None => self.tcx.sess.struct_err(&format!( |
a7813a04 | 172 | "duplicate lang item in crate `{}`: `{}`.", |
ea8adc8c | 173 | self.tcx.crate_name(item_def_id.krate), |
a7813a04 XL |
174 | name)), |
175 | }; | |
0731742a | 176 | if let Some(span) = self.tcx.hir().span_if_local(original_def_id) { |
0bf4aa26 | 177 | span_note!(&mut err, span, "first defined here."); |
54a0048b SL |
178 | } else { |
179 | err.note(&format!("first defined in crate `{}`.", | |
ea8adc8c | 180 | self.tcx.crate_name(original_def_id.krate))); |
54a0048b SL |
181 | } |
182 | err.emit(); | |
223e47cc | 183 | } |
223e47cc LB |
184 | } |
185 | ||
186 | // Matched. | |
187 | self.items.items[item_index] = Some(item_def_id); | |
188 | } | |
1a4d82fc | 189 | } |
223e47cc | 190 | |
2c00a5a8 | 191 | pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { |
85aaf69f | 192 | for attribute in attrs { |
cc61c64b XL |
193 | if attribute.check_name("lang") { |
194 | if let Some(value) = attribute.value_str() { | |
2c00a5a8 | 195 | return Some((value, attribute.span)); |
cc61c64b | 196 | } |
a1dfa0c6 | 197 | } else if attribute.check_name("panic_handler") { |
94b46f34 | 198 | return Some((Symbol::intern("panic_impl"), attribute.span)) |
8faf50e0 XL |
199 | } else if attribute.check_name("alloc_error_handler") { |
200 | return Some((Symbol::intern("oom"), attribute.span)) | |
223e47cc LB |
201 | } |
202 | } | |
203 | ||
0bf4aa26 | 204 | None |
223e47cc LB |
205 | } |
206 | ||
ea8adc8c XL |
207 | pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems { |
208 | let mut collector = LanguageItemCollector::new(tcx); | |
209 | for &cnum in tcx.crates().iter() { | |
210 | for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() { | |
211 | collector.collect_item(item_index, def_id); | |
212 | } | |
213 | } | |
0731742a | 214 | tcx.hir().krate().visit_all_item_likes(&mut collector); |
1a4d82fc | 215 | let LanguageItemCollector { mut items, .. } = collector; |
ea8adc8c | 216 | weak_lang_items::check_crate(tcx, &mut items); |
970d7e83 | 217 | items |
223e47cc | 218 | } |
1a4d82fc JJ |
219 | |
220 | // End of the macro | |
221 | } | |
222 | } | |
223 | ||
3157f602 | 224 | language_item_table! { |
0bf4aa26 XL |
225 | // Variant name, Name, Method name, Target; |
226 | CharImplItem, "char", char_impl, Target::Impl; | |
227 | StrImplItem, "str", str_impl, Target::Impl; | |
228 | SliceImplItem, "slice", slice_impl, Target::Impl; | |
229 | SliceU8ImplItem, "slice_u8", slice_u8_impl, Target::Impl; | |
230 | StrAllocImplItem, "str_alloc", str_alloc_impl, Target::Impl; | |
231 | SliceAllocImplItem, "slice_alloc", slice_alloc_impl, Target::Impl; | |
232 | SliceU8AllocImplItem, "slice_u8_alloc", slice_u8_alloc_impl, Target::Impl; | |
233 | ConstPtrImplItem, "const_ptr", const_ptr_impl, Target::Impl; | |
234 | MutPtrImplItem, "mut_ptr", mut_ptr_impl, Target::Impl; | |
235 | I8ImplItem, "i8", i8_impl, Target::Impl; | |
236 | I16ImplItem, "i16", i16_impl, Target::Impl; | |
237 | I32ImplItem, "i32", i32_impl, Target::Impl; | |
238 | I64ImplItem, "i64", i64_impl, Target::Impl; | |
239 | I128ImplItem, "i128", i128_impl, Target::Impl; | |
240 | IsizeImplItem, "isize", isize_impl, Target::Impl; | |
241 | U8ImplItem, "u8", u8_impl, Target::Impl; | |
242 | U16ImplItem, "u16", u16_impl, Target::Impl; | |
243 | U32ImplItem, "u32", u32_impl, Target::Impl; | |
244 | U64ImplItem, "u64", u64_impl, Target::Impl; | |
245 | U128ImplItem, "u128", u128_impl, Target::Impl; | |
246 | UsizeImplItem, "usize", usize_impl, Target::Impl; | |
247 | F32ImplItem, "f32", f32_impl, Target::Impl; | |
248 | F64ImplItem, "f64", f64_impl, Target::Impl; | |
249 | F32RuntimeImplItem, "f32_runtime", f32_runtime_impl, Target::Impl; | |
250 | F64RuntimeImplItem, "f64_runtime", f64_runtime_impl, Target::Impl; | |
251 | ||
252 | SizedTraitLangItem, "sized", sized_trait, Target::Trait; | |
253 | UnsizeTraitLangItem, "unsize", unsize_trait, Target::Trait; | |
254 | CopyTraitLangItem, "copy", copy_trait, Target::Trait; | |
255 | CloneTraitLangItem, "clone", clone_trait, Target::Trait; | |
256 | SyncTraitLangItem, "sync", sync_trait, Target::Trait; | |
257 | FreezeTraitLangItem, "freeze", freeze_trait, Target::Trait; | |
258 | ||
259 | DropTraitLangItem, "drop", drop_trait, Target::Trait; | |
260 | ||
261 | CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait, Target::Trait; | |
a1dfa0c6 | 262 | DispatchFromDynTraitLangItem,"dispatch_from_dyn", dispatch_from_dyn_trait, Target::Trait; |
0bf4aa26 XL |
263 | |
264 | AddTraitLangItem, "add", add_trait, Target::Trait; | |
265 | SubTraitLangItem, "sub", sub_trait, Target::Trait; | |
266 | MulTraitLangItem, "mul", mul_trait, Target::Trait; | |
267 | DivTraitLangItem, "div", div_trait, Target::Trait; | |
268 | RemTraitLangItem, "rem", rem_trait, Target::Trait; | |
269 | NegTraitLangItem, "neg", neg_trait, Target::Trait; | |
270 | NotTraitLangItem, "not", not_trait, Target::Trait; | |
271 | BitXorTraitLangItem, "bitxor", bitxor_trait, Target::Trait; | |
272 | BitAndTraitLangItem, "bitand", bitand_trait, Target::Trait; | |
273 | BitOrTraitLangItem, "bitor", bitor_trait, Target::Trait; | |
274 | ShlTraitLangItem, "shl", shl_trait, Target::Trait; | |
275 | ShrTraitLangItem, "shr", shr_trait, Target::Trait; | |
276 | AddAssignTraitLangItem, "add_assign", add_assign_trait, Target::Trait; | |
277 | SubAssignTraitLangItem, "sub_assign", sub_assign_trait, Target::Trait; | |
278 | MulAssignTraitLangItem, "mul_assign", mul_assign_trait, Target::Trait; | |
279 | DivAssignTraitLangItem, "div_assign", div_assign_trait, Target::Trait; | |
280 | RemAssignTraitLangItem, "rem_assign", rem_assign_trait, Target::Trait; | |
281 | BitXorAssignTraitLangItem, "bitxor_assign", bitxor_assign_trait, Target::Trait; | |
282 | BitAndAssignTraitLangItem, "bitand_assign", bitand_assign_trait, Target::Trait; | |
283 | BitOrAssignTraitLangItem, "bitor_assign", bitor_assign_trait, Target::Trait; | |
284 | ShlAssignTraitLangItem, "shl_assign", shl_assign_trait, Target::Trait; | |
285 | ShrAssignTraitLangItem, "shr_assign", shr_assign_trait, Target::Trait; | |
286 | IndexTraitLangItem, "index", index_trait, Target::Trait; | |
287 | IndexMutTraitLangItem, "index_mut", index_mut_trait, Target::Trait; | |
288 | ||
289 | UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type, Target::Struct; | |
a1dfa0c6 | 290 | VaListTypeLangItem, "va_list", va_list, Target::Struct; |
0bf4aa26 XL |
291 | |
292 | DerefTraitLangItem, "deref", deref_trait, Target::Trait; | |
293 | DerefMutTraitLangItem, "deref_mut", deref_mut_trait, Target::Trait; | |
0731742a | 294 | ReceiverTraitLangItem, "receiver", receiver_trait, Target::Trait; |
0bf4aa26 XL |
295 | |
296 | FnTraitLangItem, "fn", fn_trait, Target::Trait; | |
297 | FnMutTraitLangItem, "fn_mut", fn_mut_trait, Target::Trait; | |
298 | FnOnceTraitLangItem, "fn_once", fn_once_trait, Target::Trait; | |
299 | ||
300 | GeneratorStateLangItem, "generator_state", gen_state, Target::Enum; | |
301 | GeneratorTraitLangItem, "generator", gen_trait, Target::Trait; | |
9fa01778 XL |
302 | UnpinTraitLangItem, "unpin", unpin_trait, Target::Trait; |
303 | PinTypeLangItem, "pin", pin_type, Target::Struct; | |
0bf4aa26 XL |
304 | |
305 | EqTraitLangItem, "eq", eq_trait, Target::Trait; | |
306 | PartialOrdTraitLangItem, "partial_ord", partial_ord_trait, Target::Trait; | |
307 | OrdTraitLangItem, "ord", ord_trait, Target::Trait; | |
1a4d82fc | 308 | |
1a4d82fc JJ |
309 | // A number of panic-related lang items. The `panic` item corresponds to |
310 | // divide-by-zero and various panic cases with `match`. The | |
311 | // `panic_bounds_check` item is for indexing arrays. | |
312 | // | |
313 | // The `begin_unwind` lang item has a predefined symbol name and is sort of | |
314 | // a "weak lang item" in the sense that a crate is not required to have it | |
315 | // defined to use it, but a final product is required to define it | |
316 | // somewhere. Additionally, there are restrictions on crates that use a weak | |
317 | // lang item, but do not have it defined. | |
0bf4aa26 XL |
318 | PanicFnLangItem, "panic", panic_fn, Target::Fn; |
319 | PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn, Target::Fn; | |
320 | PanicInfoLangItem, "panic_info", panic_info, Target::Struct; | |
321 | PanicImplLangItem, "panic_impl", panic_impl, Target::Fn; | |
b7449926 | 322 | // Libstd panic entry point. Necessary for const eval to be able to catch it |
0bf4aa26 | 323 | BeginPanicFnLangItem, "begin_panic", begin_panic_fn, Target::Fn; |
1a4d82fc | 324 | |
0bf4aa26 XL |
325 | ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn, Target::Fn; |
326 | BoxFreeFnLangItem, "box_free", box_free_fn, Target::Fn; | |
327 | DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn, Target::Fn; | |
328 | OomLangItem, "oom", oom, Target::Fn; | |
329 | AllocLayoutLangItem, "alloc_layout", alloc_layout, Target::Struct; | |
1a4d82fc | 330 | |
0bf4aa26 | 331 | StartFnLangItem, "start", start_fn, Target::Fn; |
1a4d82fc | 332 | |
0bf4aa26 XL |
333 | EhPersonalityLangItem, "eh_personality", eh_personality, Target::Fn; |
334 | EhUnwindResumeLangItem, "eh_unwind_resume", eh_unwind_resume, Target::Fn; | |
335 | MSVCTryFilterLangItem, "msvc_try_filter", msvc_try_filter, Target::Static; | |
1a4d82fc | 336 | |
0bf4aa26 | 337 | OwnedBoxLangItem, "owned_box", owned_box, Target::Struct; |
1a4d82fc | 338 | |
0bf4aa26 | 339 | PhantomDataItem, "phantom_data", phantom_data, Target::Struct; |
85aaf69f | 340 | |
0bf4aa26 | 341 | ManuallyDropItem, "manually_drop", manually_drop, Target::Struct; |
8faf50e0 | 342 | |
0bf4aa26 | 343 | DebugTraitLangItem, "debug_trait", debug_trait, Target::Trait; |
ff7c6d11 XL |
344 | |
345 | // A lang item for each of the 128-bit operators we can optionally lower. | |
0bf4aa26 XL |
346 | I128AddFnLangItem, "i128_add", i128_add_fn, Target::Fn; |
347 | U128AddFnLangItem, "u128_add", u128_add_fn, Target::Fn; | |
348 | I128SubFnLangItem, "i128_sub", i128_sub_fn, Target::Fn; | |
349 | U128SubFnLangItem, "u128_sub", u128_sub_fn, Target::Fn; | |
350 | I128MulFnLangItem, "i128_mul", i128_mul_fn, Target::Fn; | |
351 | U128MulFnLangItem, "u128_mul", u128_mul_fn, Target::Fn; | |
352 | I128DivFnLangItem, "i128_div", i128_div_fn, Target::Fn; | |
353 | U128DivFnLangItem, "u128_div", u128_div_fn, Target::Fn; | |
354 | I128RemFnLangItem, "i128_rem", i128_rem_fn, Target::Fn; | |
355 | U128RemFnLangItem, "u128_rem", u128_rem_fn, Target::Fn; | |
356 | I128ShlFnLangItem, "i128_shl", i128_shl_fn, Target::Fn; | |
357 | U128ShlFnLangItem, "u128_shl", u128_shl_fn, Target::Fn; | |
358 | I128ShrFnLangItem, "i128_shr", i128_shr_fn, Target::Fn; | |
359 | U128ShrFnLangItem, "u128_shr", u128_shr_fn, Target::Fn; | |
ff7c6d11 XL |
360 | // And overflow versions for the operators that are checkable. |
361 | // While MIR calls these Checked*, they return (T,bool), not Option<T>. | |
0bf4aa26 XL |
362 | I128AddoFnLangItem, "i128_addo", i128_addo_fn, Target::Fn; |
363 | U128AddoFnLangItem, "u128_addo", u128_addo_fn, Target::Fn; | |
364 | I128SuboFnLangItem, "i128_subo", i128_subo_fn, Target::Fn; | |
365 | U128SuboFnLangItem, "u128_subo", u128_subo_fn, Target::Fn; | |
366 | I128MuloFnLangItem, "i128_mulo", i128_mulo_fn, Target::Fn; | |
367 | U128MuloFnLangItem, "u128_mulo", u128_mulo_fn, Target::Fn; | |
368 | I128ShloFnLangItem, "i128_shlo", i128_shlo_fn, Target::Fn; | |
369 | U128ShloFnLangItem, "u128_shlo", u128_shlo_fn, Target::Fn; | |
370 | I128ShroFnLangItem, "i128_shro", i128_shro_fn, Target::Fn; | |
371 | U128ShroFnLangItem, "u128_shro", u128_shro_fn, Target::Fn; | |
ff7c6d11 | 372 | |
94b46f34 | 373 | // Align offset for stride != 1, must not panic. |
0bf4aa26 XL |
374 | AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn; |
375 | ||
376 | TerminationTraitLangItem, "termination", termination, Target::Trait; | |
94b46f34 | 377 | |
0bf4aa26 XL |
378 | Arc, "arc", arc, Target::Struct; |
379 | Rc, "rc", rc, Target::Struct; | |
1a4d82fc | 380 | } |
476ff2be | 381 | |
ea8adc8c | 382 | impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> { |
476ff2be | 383 | pub fn require_lang_item(&self, lang_item: LangItem) -> DefId { |
ea8adc8c | 384 | self.lang_items().require(lang_item).unwrap_or_else(|msg| { |
476ff2be SL |
385 | self.sess.fatal(&msg) |
386 | }) | |
387 | } | |
388 | } |