]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
223e47cc LB |
2 | // file at the top-level directory of this distribution and at |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
223e47cc LB |
11 | // Decoding metadata from a single crate's metadata |
12 | ||
1a4d82fc | 13 | #![allow(non_camel_case_types)] |
223e47cc | 14 | |
1a4d82fc JJ |
15 | use self::Family::*; |
16 | ||
54a0048b | 17 | use astencode::decode_inlined_item; |
92a42be0 SL |
18 | use cstore::{self, crate_metadata}; |
19 | use common::*; | |
20 | use encoder::def_to_u64; | |
21 | use index; | |
9cc50fc6 | 22 | use tls_context; |
92a42be0 SL |
23 | use tydecode::TyDecoder; |
24 | ||
54a0048b SL |
25 | use rustc::hir::svh::Svh; |
26 | use rustc::hir::map as hir_map; | |
92a42be0 | 27 | use rustc::util::nodemap::FnvHashMap; |
54a0048b | 28 | use rustc::hir; |
e9174d1e | 29 | |
92a42be0 | 30 | use middle::cstore::{LOCAL_CRATE, FoundAst, InlinedItem, LinkagePreference}; |
9cc50fc6 | 31 | use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls}; |
54a0048b SL |
32 | use rustc::hir::def::Def; |
33 | use rustc::hir::def_id::{DefId, DefIndex}; | |
1a4d82fc | 34 | use middle::lang_items; |
54a0048b SL |
35 | use rustc::ty::subst; |
36 | use rustc::ty::{ImplContainer, TraitContainer}; | |
37 | use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, VariantKind}; | |
38 | ||
39 | use rustc_const_math::ConstInt; | |
1a4d82fc | 40 | |
9cc50fc6 SL |
41 | use rustc::mir; |
42 | use rustc::mir::visit::MutVisitor; | |
43 | ||
44 | use std::cell::Cell; | |
c34b1796 AL |
45 | use std::io::prelude::*; |
46 | use std::io; | |
1a4d82fc | 47 | use std::rc::Rc; |
970d7e83 | 48 | use std::str; |
1a4d82fc JJ |
49 | |
50 | use rbml::reader; | |
51 | use rbml; | |
52 | use serialize::Decodable; | |
b039eaaf | 53 | use syntax::attr; |
54a0048b | 54 | use syntax::parse::token::{self, IdentInterner}; |
1a4d82fc | 55 | use syntax::ast; |
7453a54e SL |
56 | use syntax::abi::Abi; |
57 | use syntax::codemap::{self, Span, BytePos, NO_EXPANSION}; | |
b039eaaf | 58 | use syntax::print::pprust; |
1a4d82fc | 59 | use syntax::ptr::P; |
223e47cc | 60 | |
c34b1796 | 61 | |
e9174d1e | 62 | pub type Cmd<'a> = &'a crate_metadata; |
223e47cc | 63 | |
e9174d1e | 64 | impl crate_metadata { |
b039eaaf | 65 | fn get_item(&self, item_id: DefIndex) -> Option<rbml::Doc> { |
e9174d1e SL |
66 | self.index.lookup_item(self.data(), item_id).map(|pos| { |
67 | reader::doc_at(self.data(), pos as usize).unwrap().doc | |
68 | }) | |
223e47cc | 69 | } |
223e47cc | 70 | |
b039eaaf | 71 | fn lookup_item(&self, item_id: DefIndex) -> rbml::Doc { |
e9174d1e | 72 | match self.get_item(item_id) { |
54a0048b | 73 | None => bug!("lookup_item: id not found: {:?}", item_id), |
e9174d1e SL |
74 | Some(d) => d |
75 | } | |
970d7e83 | 76 | } |
223e47cc LB |
77 | } |
78 | ||
e9174d1e SL |
79 | pub fn load_index(data: &[u8]) -> index::Index { |
80 | let index = reader::get_doc(rbml::Doc::new(data), tag_index); | |
b039eaaf SL |
81 | index::Index::from_rbml(index) |
82 | } | |
83 | ||
84 | pub fn crate_rustc_version(data: &[u8]) -> Option<String> { | |
85 | let doc = rbml::Doc::new(data); | |
86 | reader::maybe_get_doc(doc, tag_rustc_version).map(|s| s.as_str()) | |
87 | } | |
88 | ||
89 | pub fn load_xrefs(data: &[u8]) -> index::DenseIndex { | |
90 | let index = reader::get_doc(rbml::Doc::new(data), tag_xref_index); | |
91 | index::DenseIndex::from_buf(index.data, index.start, index.end) | |
223e47cc LB |
92 | } |
93 | ||
7453a54e | 94 | #[derive(Clone, Copy, Debug, PartialEq)] |
223e47cc | 95 | enum Family { |
970d7e83 LB |
96 | ImmStatic, // c |
97 | MutStatic, // b | |
223e47cc | 98 | Fn, // f |
223e47cc | 99 | StaticMethod, // F |
1a4d82fc | 100 | Method, // h |
223e47cc | 101 | Type, // y |
223e47cc LB |
102 | Mod, // m |
103 | ForeignMod, // n | |
104 | Enum, // t | |
7453a54e | 105 | Variant(VariantKind), // V, v, w |
223e47cc | 106 | Impl, // i |
9cc50fc6 | 107 | DefaultImpl, // d |
223e47cc | 108 | Trait, // I |
7453a54e | 109 | Struct(VariantKind), // S, s, u |
223e47cc | 110 | PublicField, // g |
1a4d82fc JJ |
111 | InheritedField, // N |
112 | Constant, // C | |
223e47cc LB |
113 | } |
114 | ||
1a4d82fc | 115 | fn item_family(item: rbml::Doc) -> Family { |
223e47cc LB |
116 | let fam = reader::get_doc(item, tag_items_data_item_family); |
117 | match reader::doc_as_u8(fam) as char { | |
1a4d82fc | 118 | 'C' => Constant, |
970d7e83 LB |
119 | 'c' => ImmStatic, |
120 | 'b' => MutStatic, | |
223e47cc | 121 | 'f' => Fn, |
223e47cc | 122 | 'F' => StaticMethod, |
1a4d82fc | 123 | 'h' => Method, |
223e47cc | 124 | 'y' => Type, |
223e47cc LB |
125 | 'm' => Mod, |
126 | 'n' => ForeignMod, | |
127 | 't' => Enum, | |
7453a54e SL |
128 | 'V' => Variant(VariantKind::Struct), |
129 | 'v' => Variant(VariantKind::Tuple), | |
130 | 'w' => Variant(VariantKind::Unit), | |
223e47cc | 131 | 'i' => Impl, |
c34b1796 | 132 | 'd' => DefaultImpl, |
223e47cc | 133 | 'I' => Trait, |
7453a54e SL |
134 | 'S' => Struct(VariantKind::Struct), |
135 | 's' => Struct(VariantKind::Tuple), | |
136 | 'u' => Struct(VariantKind::Unit), | |
223e47cc | 137 | 'g' => PublicField, |
223e47cc | 138 | 'N' => InheritedField, |
54a0048b | 139 | c => bug!("unexpected family char: {}", c) |
223e47cc LB |
140 | } |
141 | } | |
142 | ||
54a0048b | 143 | fn item_visibility(item: rbml::Doc) -> ty::Visibility { |
223e47cc | 144 | match reader::maybe_get_doc(item, tag_items_data_item_visibility) { |
54a0048b | 145 | None => ty::Visibility::Public, |
223e47cc LB |
146 | Some(visibility_doc) => { |
147 | match reader::doc_as_u8(visibility_doc) as char { | |
54a0048b SL |
148 | 'y' => ty::Visibility::Public, |
149 | 'i' => ty::Visibility::PrivateExternal, | |
150 | _ => bug!("unknown visibility character") | |
223e47cc LB |
151 | } |
152 | } | |
153 | } | |
154 | } | |
155 | ||
e9174d1e | 156 | fn fn_constness(item: rbml::Doc) -> hir::Constness { |
62682a34 | 157 | match reader::maybe_get_doc(item, tag_items_data_item_constness) { |
e9174d1e | 158 | None => hir::Constness::NotConst, |
62682a34 SL |
159 | Some(constness_doc) => { |
160 | match reader::doc_as_u8(constness_doc) as char { | |
e9174d1e SL |
161 | 'c' => hir::Constness::Const, |
162 | 'n' => hir::Constness::NotConst, | |
54a0048b SL |
163 | _ => bug!("unknown constness character") |
164 | } | |
165 | } | |
166 | } | |
167 | } | |
168 | ||
169 | fn item_defaultness(item: rbml::Doc) -> hir::Defaultness { | |
170 | match reader::maybe_get_doc(item, tag_items_data_item_defaultness) { | |
171 | None => hir::Defaultness::Default, // should occur only for default impls on traits | |
172 | Some(defaultness_doc) => { | |
173 | match reader::doc_as_u8(defaultness_doc) as char { | |
174 | 'd' => hir::Defaultness::Default, | |
175 | 'f' => hir::Defaultness::Final, | |
176 | _ => bug!("unknown defaultness character") | |
62682a34 SL |
177 | } |
178 | } | |
179 | } | |
180 | } | |
181 | ||
c34b1796 | 182 | fn item_sort(item: rbml::Doc) -> Option<char> { |
62682a34 SL |
183 | reader::tagged_docs(item, tag_item_trait_item_sort).nth(0).map(|doc| { |
184 | doc.as_str_slice().as_bytes()[0] as char | |
185 | }) | |
223e47cc LB |
186 | } |
187 | ||
1a4d82fc JJ |
188 | fn item_symbol(item: rbml::Doc) -> String { |
189 | reader::get_doc(item, tag_items_data_item_symbol).as_str().to_string() | |
223e47cc LB |
190 | } |
191 | ||
e9174d1e | 192 | fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> DefId { |
d9579d0f | 193 | let id = reader::doc_as_u64(d); |
b039eaaf SL |
194 | let index = DefIndex::new((id & 0xFFFF_FFFF) as usize); |
195 | let def_id = DefId { krate: (id >> 32) as u32, index: index }; | |
d9579d0f AL |
196 | translate_def_id(cdata, def_id) |
197 | } | |
198 | ||
e9174d1e | 199 | fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option<DefId> { |
62682a34 SL |
200 | reader::tagged_docs(d, tag_items_data_parent_item).nth(0).map(|did| { |
201 | translated_def_id(cdata, did) | |
202 | }) | |
223e47cc LB |
203 | } |
204 | ||
e9174d1e | 205 | fn item_require_parent_item(cdata: Cmd, d: rbml::Doc) -> DefId { |
d9579d0f | 206 | translated_def_id(cdata, reader::get_doc(d, tag_items_data_parent_item)) |
223e47cc LB |
207 | } |
208 | ||
e9174d1e | 209 | fn item_def_id(d: rbml::Doc, cdata: Cmd) -> DefId { |
d9579d0f | 210 | translated_def_id(cdata, reader::get_doc(d, tag_def_id)) |
223e47cc LB |
211 | } |
212 | ||
62682a34 SL |
213 | fn reexports<'a>(d: rbml::Doc<'a>) -> reader::TaggedDocsIterator<'a> { |
214 | reader::tagged_docs(d, tag_items_data_item_reexport) | |
223e47cc LB |
215 | } |
216 | ||
54a0048b | 217 | fn variant_disr_val(d: rbml::Doc) -> Option<u64> { |
1a4d82fc JJ |
218 | reader::maybe_get_doc(d, tag_disr_val).and_then(|val_doc| { |
219 | reader::with_doc_data(val_doc, |data| { | |
85aaf69f | 220 | str::from_utf8(data).ok().and_then(|s| s.parse().ok()) |
1a4d82fc JJ |
221 | }) |
222 | }) | |
223 | } | |
224 | ||
54a0048b | 225 | fn doc_type<'tcx>(doc: rbml::Doc, tcx: &TyCtxt<'tcx>, cdata: Cmd) -> Ty<'tcx> { |
223e47cc | 226 | let tp = reader::get_doc(doc, tag_items_data_item_type); |
e9174d1e | 227 | TyDecoder::with_doc(tcx, cdata.cnum, tp, |
b039eaaf | 228 | &mut |did| translate_def_id(cdata, did)) |
e9174d1e | 229 | .parse_ty() |
223e47cc LB |
230 | } |
231 | ||
54a0048b | 232 | fn maybe_doc_type<'tcx>(doc: rbml::Doc, tcx: &TyCtxt<'tcx>, cdata: Cmd) -> Option<Ty<'tcx>> { |
62682a34 | 233 | reader::maybe_get_doc(doc, tag_items_data_item_type).map(|tp| { |
e9174d1e | 234 | TyDecoder::with_doc(tcx, cdata.cnum, tp, |
b039eaaf | 235 | &mut |did| translate_def_id(cdata, did)) |
e9174d1e | 236 | .parse_ty() |
62682a34 SL |
237 | }) |
238 | } | |
239 | ||
e9174d1e | 240 | pub fn item_type<'tcx>(_item_id: DefId, item: rbml::Doc, |
54a0048b | 241 | tcx: &TyCtxt<'tcx>, cdata: Cmd) -> Ty<'tcx> { |
970d7e83 LB |
242 | doc_type(item, tcx, cdata) |
243 | } | |
244 | ||
54a0048b | 245 | fn doc_trait_ref<'tcx>(doc: rbml::Doc, tcx: &TyCtxt<'tcx>, cdata: Cmd) |
d9579d0f | 246 | -> ty::TraitRef<'tcx> { |
e9174d1e | 247 | TyDecoder::with_doc(tcx, cdata.cnum, doc, |
b039eaaf | 248 | &mut |did| translate_def_id(cdata, did)) |
e9174d1e | 249 | .parse_trait_ref() |
223e47cc LB |
250 | } |
251 | ||
54a0048b | 252 | fn item_trait_ref<'tcx>(doc: rbml::Doc, tcx: &TyCtxt<'tcx>, cdata: Cmd) |
d9579d0f | 253 | -> ty::TraitRef<'tcx> { |
970d7e83 LB |
254 | let tp = reader::get_doc(doc, tag_item_trait_ref); |
255 | doc_trait_ref(tp, tcx, cdata) | |
256 | } | |
257 | ||
1a4d82fc | 258 | fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name { |
223e47cc | 259 | let name = reader::get_doc(item, tag_paths_data_name); |
970d7e83 | 260 | let string = name.as_str_slice(); |
1a4d82fc JJ |
261 | match intr.find(string) { |
262 | None => token::intern(string), | |
263 | Some(val) => val, | |
970d7e83 | 264 | } |
223e47cc LB |
265 | } |
266 | ||
7453a54e SL |
267 | fn family_to_variant_kind<'tcx>(family: Family) -> Option<ty::VariantKind> { |
268 | match family { | |
269 | Struct(VariantKind::Struct) | Variant(VariantKind::Struct) => | |
270 | Some(ty::VariantKind::Struct), | |
271 | Struct(VariantKind::Tuple) | Variant(VariantKind::Tuple) => | |
272 | Some(ty::VariantKind::Tuple), | |
273 | Struct(VariantKind::Unit) | Variant(VariantKind::Unit) => | |
274 | Some(ty::VariantKind::Unit), | |
275 | _ => None, | |
276 | } | |
277 | } | |
278 | ||
e9174d1e | 279 | fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: DefId) -> DefLike { |
223e47cc LB |
280 | let fam = item_family(item); |
281 | match fam { | |
d9579d0f AL |
282 | Constant => { |
283 | // Check whether we have an associated const item. | |
b039eaaf SL |
284 | match item_sort(item) { |
285 | Some('C') | Some('c') => { | |
7453a54e | 286 | DlDef(Def::AssociatedConst(did)) |
b039eaaf SL |
287 | } |
288 | _ => { | |
289 | // Regular const item. | |
7453a54e | 290 | DlDef(Def::Const(did)) |
b039eaaf | 291 | } |
d9579d0f AL |
292 | } |
293 | } | |
7453a54e SL |
294 | ImmStatic => DlDef(Def::Static(did, false)), |
295 | MutStatic => DlDef(Def::Static(did, true)), | |
296 | Struct(..) => DlDef(Def::Struct(did)), | |
297 | Fn => DlDef(Def::Fn(did)), | |
1a4d82fc | 298 | Method | StaticMethod => { |
7453a54e | 299 | DlDef(Def::Method(did)) |
c34b1796 AL |
300 | } |
301 | Type => { | |
302 | if item_sort(item) == Some('t') { | |
d9579d0f | 303 | let trait_did = item_require_parent_item(cdata, item); |
7453a54e | 304 | DlDef(Def::AssociatedTy(trait_did, did)) |
c34b1796 | 305 | } else { |
7453a54e | 306 | DlDef(Def::TyAlias(did)) |
1a4d82fc | 307 | } |
223e47cc | 308 | } |
7453a54e SL |
309 | Mod => DlDef(Def::Mod(did)), |
310 | ForeignMod => DlDef(Def::ForeignMod(did)), | |
311 | Variant(..) => { | |
d9579d0f | 312 | let enum_did = item_require_parent_item(cdata, item); |
7453a54e | 313 | DlDef(Def::Variant(enum_did, did)) |
223e47cc | 314 | } |
7453a54e SL |
315 | Trait => DlDef(Def::Trait(did)), |
316 | Enum => DlDef(Def::Enum(did)), | |
c34b1796 | 317 | Impl | DefaultImpl => DlImpl(did), |
1a4d82fc JJ |
318 | PublicField | InheritedField => DlField, |
319 | } | |
320 | } | |
321 | ||
e9174d1e | 322 | fn parse_unsafety(item_doc: rbml::Doc) -> hir::Unsafety { |
1a4d82fc JJ |
323 | let unsafety_doc = reader::get_doc(item_doc, tag_unsafety); |
324 | if reader::doc_as_u8(unsafety_doc) != 0 { | |
e9174d1e | 325 | hir::Unsafety::Unsafe |
1a4d82fc | 326 | } else { |
e9174d1e | 327 | hir::Unsafety::Normal |
223e47cc LB |
328 | } |
329 | } | |
330 | ||
85aaf69f SL |
331 | fn parse_paren_sugar(item_doc: rbml::Doc) -> bool { |
332 | let paren_sugar_doc = reader::get_doc(item_doc, tag_paren_sugar); | |
333 | reader::doc_as_u8(paren_sugar_doc) != 0 | |
334 | } | |
335 | ||
e9174d1e | 336 | fn parse_polarity(item_doc: rbml::Doc) -> hir::ImplPolarity { |
85aaf69f SL |
337 | let polarity_doc = reader::get_doc(item_doc, tag_polarity); |
338 | if reader::doc_as_u8(polarity_doc) != 0 { | |
e9174d1e | 339 | hir::ImplPolarity::Negative |
85aaf69f | 340 | } else { |
e9174d1e | 341 | hir::ImplPolarity::Positive |
85aaf69f SL |
342 | } |
343 | } | |
344 | ||
1a4d82fc JJ |
345 | fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec<ast::Name> { |
346 | let names_doc = reader::get_doc(item_doc, tag_associated_type_names); | |
62682a34 SL |
347 | reader::tagged_docs(names_doc, tag_associated_type_name) |
348 | .map(|name_doc| token::intern(name_doc.as_str_slice())) | |
349 | .collect() | |
223e47cc LB |
350 | } |
351 | ||
1a4d82fc | 352 | pub fn get_trait_def<'tcx>(cdata: Cmd, |
b039eaaf | 353 | item_id: DefIndex, |
54a0048b | 354 | tcx: &TyCtxt<'tcx>) -> ty::TraitDef<'tcx> |
970d7e83 | 355 | { |
e9174d1e | 356 | let item_doc = cdata.lookup_item(item_id); |
1a4d82fc | 357 | let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics); |
1a4d82fc JJ |
358 | let unsafety = parse_unsafety(item_doc); |
359 | let associated_type_names = parse_associated_type_names(item_doc); | |
85aaf69f | 360 | let paren_sugar = parse_paren_sugar(item_doc); |
1a4d82fc | 361 | |
9cc50fc6 SL |
362 | ty::TraitDef::new(unsafety, |
363 | paren_sugar, | |
364 | generics, | |
365 | item_trait_ref(item_doc, tcx, cdata), | |
366 | associated_type_names) | |
970d7e83 LB |
367 | } |
368 | ||
e9174d1e SL |
369 | pub fn get_adt_def<'tcx>(intr: &IdentInterner, |
370 | cdata: Cmd, | |
b039eaaf | 371 | item_id: DefIndex, |
54a0048b | 372 | tcx: &TyCtxt<'tcx>) -> ty::AdtDefMaster<'tcx> |
e9174d1e | 373 | { |
54a0048b | 374 | fn expect_variant_kind(family: Family) -> ty::VariantKind { |
7453a54e SL |
375 | match family_to_variant_kind(family) { |
376 | Some(kind) => kind, | |
54a0048b | 377 | _ => bug!("unexpected family: {:?}", family), |
9cc50fc6 SL |
378 | } |
379 | } | |
e9174d1e SL |
380 | fn get_enum_variants<'tcx>(intr: &IdentInterner, |
381 | cdata: Cmd, | |
54a0048b | 382 | doc: rbml::Doc) -> Vec<ty::VariantDefData<'tcx, 'tcx>> { |
e9174d1e SL |
383 | let mut disr_val = 0; |
384 | reader::tagged_docs(doc, tag_items_data_item_variant).map(|p| { | |
385 | let did = translated_def_id(cdata, p); | |
b039eaaf | 386 | let item = cdata.lookup_item(did.index); |
e9174d1e SL |
387 | |
388 | if let Some(disr) = variant_disr_val(item) { | |
389 | disr_val = disr; | |
390 | } | |
391 | let disr = disr_val; | |
392 | disr_val = disr_val.wrapping_add(1); | |
393 | ||
394 | ty::VariantDefData { | |
395 | did: did, | |
396 | name: item_name(intr, item), | |
54a0048b SL |
397 | fields: get_variant_fields(intr, cdata, item), |
398 | disr_val: ConstInt::Infer(disr), | |
399 | kind: expect_variant_kind(item_family(item)), | |
e9174d1e SL |
400 | } |
401 | }).collect() | |
402 | } | |
403 | fn get_variant_fields<'tcx>(intr: &IdentInterner, | |
404 | cdata: Cmd, | |
54a0048b SL |
405 | doc: rbml::Doc) -> Vec<ty::FieldDefData<'tcx, 'tcx>> { |
406 | let mut index = 0; | |
e9174d1e SL |
407 | reader::tagged_docs(doc, tag_item_field).map(|f| { |
408 | let ff = item_family(f); | |
409 | match ff { | |
410 | PublicField | InheritedField => {}, | |
54a0048b | 411 | _ => bug!("expected field, found {:?}", ff) |
e9174d1e SL |
412 | }; |
413 | ty::FieldDefData::new(item_def_id(f, cdata), | |
414 | item_name(intr, f), | |
415 | struct_field_family_to_visibility(ff)) | |
416 | }).chain(reader::tagged_docs(doc, tag_item_unnamed_field).map(|f| { | |
417 | let ff = item_family(f); | |
54a0048b SL |
418 | let name = intr.intern(&index.to_string()); |
419 | index += 1; | |
420 | ty::FieldDefData::new(item_def_id(f, cdata), name, | |
e9174d1e SL |
421 | struct_field_family_to_visibility(ff)) |
422 | })).collect() | |
423 | } | |
424 | fn get_struct_variant<'tcx>(intr: &IdentInterner, | |
425 | cdata: Cmd, | |
426 | doc: rbml::Doc, | |
54a0048b | 427 | did: DefId) -> ty::VariantDefData<'tcx, 'tcx> { |
e9174d1e SL |
428 | ty::VariantDefData { |
429 | did: did, | |
430 | name: item_name(intr, doc), | |
54a0048b SL |
431 | fields: get_variant_fields(intr, cdata, doc), |
432 | disr_val: ConstInt::Infer(0), | |
433 | kind: expect_variant_kind(item_family(doc)), | |
e9174d1e SL |
434 | } |
435 | } | |
436 | ||
437 | let doc = cdata.lookup_item(item_id); | |
b039eaaf | 438 | let did = DefId { krate: cdata.cnum, index: item_id }; |
e9174d1e | 439 | let (kind, variants) = match item_family(doc) { |
b039eaaf SL |
440 | Enum => { |
441 | (ty::AdtKind::Enum, | |
54a0048b | 442 | get_enum_variants(intr, cdata, doc)) |
b039eaaf | 443 | } |
7453a54e | 444 | Struct(..) => { |
b039eaaf SL |
445 | let ctor_did = |
446 | reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor). | |
447 | map_or(did, |ctor_doc| translated_def_id(cdata, ctor_doc)); | |
448 | (ty::AdtKind::Struct, | |
54a0048b | 449 | vec![get_struct_variant(intr, cdata, doc, ctor_did)]) |
b039eaaf | 450 | } |
54a0048b SL |
451 | _ => bug!("get_adt_def called on a non-ADT {:?} - {:?}", |
452 | item_family(doc), did) | |
e9174d1e SL |
453 | }; |
454 | ||
455 | let adt = tcx.intern_adt_def(did, kind, variants); | |
456 | ||
457 | // this needs to be done *after* the variant is interned, | |
458 | // to support recursive structures | |
459 | for variant in &adt.variants { | |
460 | if variant.kind() == ty::VariantKind::Tuple && | |
461 | adt.adt_kind() == ty::AdtKind::Enum { | |
462 | // tuple-like enum variant fields aren't real items - get the types | |
463 | // from the ctor. | |
464 | debug!("evaluating the ctor-type of {:?}", | |
465 | variant.name); | |
b039eaaf | 466 | let ctor_ty = get_type(cdata, variant.did.index, tcx).ty; |
e9174d1e SL |
467 | debug!("evaluating the ctor-type of {:?}.. {:?}", |
468 | variant.name, | |
469 | ctor_ty); | |
470 | let field_tys = match ctor_ty.sty { | |
54a0048b | 471 | ty::TyFnDef(_, _, &ty::BareFnTy { sig: ty::Binder(ty::FnSig { |
e9174d1e SL |
472 | ref inputs, .. |
473 | }), ..}) => { | |
474 | // tuple-struct constructors don't have escaping regions | |
475 | assert!(!inputs.has_escaping_regions()); | |
476 | inputs | |
477 | }, | |
54a0048b | 478 | _ => bug!("tuple-variant ctor is not an ADT") |
e9174d1e SL |
479 | }; |
480 | for (field, &ty) in variant.fields.iter().zip(field_tys.iter()) { | |
481 | field.fulfill_ty(ty); | |
482 | } | |
483 | } else { | |
484 | for field in &variant.fields { | |
485 | debug!("evaluating the type of {:?}::{:?}", variant.name, field.name); | |
b039eaaf | 486 | let ty = get_type(cdata, field.did.index, tcx).ty; |
e9174d1e SL |
487 | field.fulfill_ty(ty); |
488 | debug!("evaluating the type of {:?}::{:?}: {:?}", | |
489 | variant.name, field.name, ty); | |
490 | } | |
491 | } | |
492 | } | |
493 | ||
494 | adt | |
495 | } | |
496 | ||
85aaf69f | 497 | pub fn get_predicates<'tcx>(cdata: Cmd, |
b039eaaf | 498 | item_id: DefIndex, |
54a0048b | 499 | tcx: &TyCtxt<'tcx>) |
85aaf69f SL |
500 | -> ty::GenericPredicates<'tcx> |
501 | { | |
e9174d1e | 502 | let item_doc = cdata.lookup_item(item_id); |
85aaf69f SL |
503 | doc_predicates(item_doc, tcx, cdata, tag_item_generics) |
504 | } | |
223e47cc | 505 | |
c34b1796 | 506 | pub fn get_super_predicates<'tcx>(cdata: Cmd, |
b039eaaf | 507 | item_id: DefIndex, |
54a0048b | 508 | tcx: &TyCtxt<'tcx>) |
c34b1796 AL |
509 | -> ty::GenericPredicates<'tcx> |
510 | { | |
e9174d1e | 511 | let item_doc = cdata.lookup_item(item_id); |
c34b1796 AL |
512 | doc_predicates(item_doc, tcx, cdata, tag_item_super_predicates) |
513 | } | |
514 | ||
54a0048b | 515 | pub fn get_type<'tcx>(cdata: Cmd, id: DefIndex, tcx: &TyCtxt<'tcx>) |
85aaf69f SL |
516 | -> ty::TypeScheme<'tcx> |
517 | { | |
e9174d1e | 518 | let item_doc = cdata.lookup_item(id); |
b039eaaf | 519 | let t = item_type(DefId { krate: cdata.cnum, index: id }, item_doc, tcx, |
223e47cc | 520 | cdata); |
85aaf69f | 521 | let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics); |
1a4d82fc JJ |
522 | ty::TypeScheme { |
523 | generics: generics, | |
223e47cc LB |
524 | ty: t |
525 | } | |
526 | } | |
527 | ||
b039eaaf | 528 | pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option<attr::Stability> { |
e9174d1e | 529 | let item = cdata.lookup_item(id); |
1a4d82fc JJ |
530 | reader::maybe_get_doc(item, tag_items_data_item_stability).map(|doc| { |
531 | let mut decoder = reader::Decoder::new(doc); | |
532 | Decodable::decode(&mut decoder).unwrap() | |
533 | }) | |
223e47cc LB |
534 | } |
535 | ||
9cc50fc6 SL |
536 | pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option<attr::Deprecation> { |
537 | let item = cdata.lookup_item(id); | |
538 | reader::maybe_get_doc(item, tag_items_data_item_deprecation).map(|doc| { | |
539 | let mut decoder = reader::Decoder::new(doc); | |
540 | Decodable::decode(&mut decoder).unwrap() | |
541 | }) | |
542 | } | |
543 | ||
54a0048b SL |
544 | pub fn get_visibility(cdata: Cmd, id: DefIndex) -> ty::Visibility { |
545 | item_visibility(cdata.lookup_item(id)) | |
546 | } | |
547 | ||
548 | pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option<DefId> { | |
549 | let item = cdata.lookup_item(id); | |
550 | reader::maybe_get_doc(item, tag_items_data_parent_impl).map(|doc| { | |
551 | translated_def_id(cdata, doc) | |
552 | }) | |
553 | } | |
554 | ||
b039eaaf | 555 | pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec<attr::ReprAttr> { |
e9174d1e | 556 | let item = cdata.lookup_item(id); |
1a4d82fc JJ |
557 | match reader::maybe_get_doc(item, tag_items_data_item_repr).map(|doc| { |
558 | let mut decoder = reader::Decoder::new(doc); | |
559 | Decodable::decode(&mut decoder).unwrap() | |
560 | }) { | |
561 | Some(attrs) => attrs, | |
562 | None => Vec::new(), | |
563 | } | |
223e47cc LB |
564 | } |
565 | ||
85aaf69f | 566 | pub fn get_impl_polarity<'tcx>(cdata: Cmd, |
b039eaaf | 567 | id: DefIndex) |
e9174d1e | 568 | -> Option<hir::ImplPolarity> |
85aaf69f | 569 | { |
e9174d1e | 570 | let item_doc = cdata.lookup_item(id); |
85aaf69f SL |
571 | let fam = item_family(item_doc); |
572 | match fam { | |
573 | Family::Impl => { | |
574 | Some(parse_polarity(item_doc)) | |
575 | } | |
576 | _ => None | |
577 | } | |
578 | } | |
579 | ||
e9174d1e SL |
580 | pub fn get_custom_coerce_unsized_kind<'tcx>( |
581 | cdata: Cmd, | |
b039eaaf | 582 | id: DefIndex) |
e9174d1e SL |
583 | -> Option<ty::adjustment::CustomCoerceUnsized> |
584 | { | |
585 | let item_doc = cdata.lookup_item(id); | |
d9579d0f AL |
586 | reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| { |
587 | let mut decoder = reader::Decoder::new(kind_doc); | |
588 | Decodable::decode(&mut decoder).unwrap() | |
589 | }) | |
590 | } | |
591 | ||
1a4d82fc | 592 | pub fn get_impl_trait<'tcx>(cdata: Cmd, |
b039eaaf | 593 | id: DefIndex, |
54a0048b | 594 | tcx: &TyCtxt<'tcx>) |
d9579d0f | 595 | -> Option<ty::TraitRef<'tcx>> |
970d7e83 | 596 | { |
e9174d1e | 597 | let item_doc = cdata.lookup_item(id); |
1a4d82fc JJ |
598 | let fam = item_family(item_doc); |
599 | match fam { | |
c34b1796 | 600 | Family::Impl | Family::DefaultImpl => { |
1a4d82fc JJ |
601 | reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| { |
602 | doc_trait_ref(tp, tcx, cdata) | |
603 | }) | |
604 | } | |
605 | _ => None | |
970d7e83 | 606 | } |
223e47cc LB |
607 | } |
608 | ||
b039eaaf | 609 | pub fn get_symbol(cdata: Cmd, id: DefIndex) -> String { |
e9174d1e SL |
610 | return item_symbol(cdata.lookup_item(id)); |
611 | } | |
612 | ||
613 | /// If you have a crate_metadata, call get_symbol instead | |
b039eaaf | 614 | pub fn get_symbol_from_buf(data: &[u8], id: DefIndex) -> String { |
e9174d1e SL |
615 | let index = load_index(data); |
616 | let pos = index.lookup_item(data, id).unwrap(); | |
617 | let doc = reader::doc_at(data, pos as usize).unwrap().doc; | |
618 | item_symbol(doc) | |
223e47cc LB |
619 | } |
620 | ||
223e47cc | 621 | /// Iterates over the language items in the given crate. |
1a4d82fc | 622 | pub fn each_lang_item<F>(cdata: Cmd, mut f: F) -> bool where |
b039eaaf | 623 | F: FnMut(DefIndex, usize) -> bool, |
1a4d82fc JJ |
624 | { |
625 | let root = rbml::Doc::new(cdata.data()); | |
223e47cc | 626 | let lang_items = reader::get_doc(root, tag_lang_items); |
62682a34 | 627 | reader::tagged_docs(lang_items, tag_lang_items_item).all(|item_doc| { |
223e47cc | 628 | let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id); |
c34b1796 | 629 | let id = reader::doc_as_u32(id_doc) as usize; |
b039eaaf SL |
630 | let index_doc = reader::get_doc(item_doc, tag_lang_items_item_index); |
631 | let index = DefIndex::from_u32(reader::doc_as_u32(index_doc)); | |
223e47cc | 632 | |
b039eaaf | 633 | f(index, id) |
1a4d82fc | 634 | }) |
223e47cc LB |
635 | } |
636 | ||
1a4d82fc JJ |
637 | fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>, |
638 | cdata: Cmd, | |
639 | item_doc: rbml::Doc, | |
640 | mut get_crate_data: G, | |
641 | mut callback: F) where | |
54a0048b | 642 | F: FnMut(DefLike, ast::Name, ty::Visibility), |
1a4d82fc JJ |
643 | G: FnMut(ast::CrateNum) -> Rc<crate_metadata>, |
644 | { | |
645 | // Iterate over all children. | |
62682a34 | 646 | for child_info_doc in reader::tagged_docs(item_doc, tag_mod_child) { |
d9579d0f | 647 | let child_def_id = translated_def_id(cdata, child_info_doc); |
1a4d82fc JJ |
648 | |
649 | // This item may be in yet another crate if it was the child of a | |
650 | // reexport. | |
651 | let crate_data = if child_def_id.krate == cdata.cnum { | |
652 | None | |
653 | } else { | |
654 | Some(get_crate_data(child_def_id.krate)) | |
655 | }; | |
656 | let crate_data = match crate_data { | |
657 | Some(ref cdata) => &**cdata, | |
658 | None => cdata | |
659 | }; | |
970d7e83 | 660 | |
1a4d82fc | 661 | // Get the item. |
b039eaaf | 662 | match crate_data.get_item(child_def_id.index) { |
1a4d82fc JJ |
663 | None => {} |
664 | Some(child_item_doc) => { | |
665 | // Hand off the item to the callback. | |
7453a54e | 666 | let child_name = item_name(&intr, child_item_doc); |
d9579d0f | 667 | let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id); |
1a4d82fc JJ |
668 | let visibility = item_visibility(child_item_doc); |
669 | callback(def_like, child_name, visibility); | |
970d7e83 LB |
670 | } |
671 | } | |
62682a34 | 672 | } |
1a4d82fc JJ |
673 | |
674 | // As a special case, iterate over all static methods of | |
675 | // associated implementations too. This is a bit of a botch. | |
676 | // --pcwalton | |
62682a34 SL |
677 | for inherent_impl_def_id_doc in reader::tagged_docs(item_doc, |
678 | tag_items_data_item_inherent_impl) { | |
679 | let inherent_impl_def_id = item_def_id(inherent_impl_def_id_doc, cdata); | |
b039eaaf | 680 | if let Some(inherent_impl_doc) = cdata.get_item(inherent_impl_def_id.index) { |
62682a34 SL |
681 | for impl_item_def_id_doc in reader::tagged_docs(inherent_impl_doc, |
682 | tag_item_impl_item) { | |
1a4d82fc JJ |
683 | let impl_item_def_id = item_def_id(impl_item_def_id_doc, |
684 | cdata); | |
b039eaaf | 685 | if let Some(impl_method_doc) = cdata.get_item(impl_item_def_id.index) { |
1a4d82fc JJ |
686 | if let StaticMethod = item_family(impl_method_doc) { |
687 | // Hand off the static method to the callback. | |
7453a54e | 688 | let static_method_name = item_name(&intr, impl_method_doc); |
d9579d0f AL |
689 | let static_method_def_like = item_to_def_like(cdata, impl_method_doc, |
690 | impl_item_def_id); | |
1a4d82fc JJ |
691 | callback(static_method_def_like, |
692 | static_method_name, | |
693 | item_visibility(impl_method_doc)); | |
694 | } | |
223e47cc | 695 | } |
62682a34 | 696 | } |
970d7e83 | 697 | } |
62682a34 | 698 | } |
1a4d82fc | 699 | |
62682a34 | 700 | for reexport_doc in reexports(item_doc) { |
1a4d82fc JJ |
701 | let def_id_doc = reader::get_doc(reexport_doc, |
702 | tag_items_data_item_reexport_def_id); | |
d9579d0f | 703 | let child_def_id = translated_def_id(cdata, def_id_doc); |
1a4d82fc JJ |
704 | |
705 | let name_doc = reader::get_doc(reexport_doc, | |
706 | tag_items_data_item_reexport_name); | |
707 | let name = name_doc.as_str_slice(); | |
708 | ||
709 | // This reexport may be in yet another crate. | |
710 | let crate_data = if child_def_id.krate == cdata.cnum { | |
711 | None | |
970d7e83 | 712 | } else { |
1a4d82fc | 713 | Some(get_crate_data(child_def_id.krate)) |
970d7e83 | 714 | }; |
1a4d82fc JJ |
715 | let crate_data = match crate_data { |
716 | Some(ref cdata) => &**cdata, | |
717 | None => cdata | |
970d7e83 LB |
718 | }; |
719 | ||
1a4d82fc | 720 | // Get the item. |
b039eaaf | 721 | if let Some(child_item_doc) = crate_data.get_item(child_def_id.index) { |
1a4d82fc | 722 | // Hand off the item to the callback. |
d9579d0f | 723 | let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id); |
1a4d82fc JJ |
724 | // These items have a public visibility because they're part of |
725 | // a public re-export. | |
54a0048b | 726 | callback(def_like, token::intern(name), ty::Visibility::Public); |
970d7e83 | 727 | } |
62682a34 | 728 | } |
1a4d82fc | 729 | } |
970d7e83 | 730 | |
1a4d82fc JJ |
731 | /// Iterates over each child of the given item. |
732 | pub fn each_child_of_item<F, G>(intr: Rc<IdentInterner>, | |
733 | cdata: Cmd, | |
b039eaaf | 734 | id: DefIndex, |
1a4d82fc JJ |
735 | get_crate_data: G, |
736 | callback: F) where | |
54a0048b | 737 | F: FnMut(DefLike, ast::Name, ty::Visibility), |
1a4d82fc JJ |
738 | G: FnMut(ast::CrateNum) -> Rc<crate_metadata>, |
739 | { | |
740 | // Find the item. | |
e9174d1e | 741 | let item_doc = match cdata.get_item(id) { |
1a4d82fc JJ |
742 | None => return, |
743 | Some(item_doc) => item_doc, | |
744 | }; | |
970d7e83 | 745 | |
1a4d82fc JJ |
746 | each_child_of_item_or_crate(intr, |
747 | cdata, | |
748 | item_doc, | |
749 | get_crate_data, | |
750 | callback) | |
223e47cc LB |
751 | } |
752 | ||
1a4d82fc JJ |
753 | /// Iterates over all the top-level crate items. |
754 | pub fn each_top_level_item_of_crate<F, G>(intr: Rc<IdentInterner>, | |
755 | cdata: Cmd, | |
756 | get_crate_data: G, | |
757 | callback: F) where | |
54a0048b | 758 | F: FnMut(DefLike, ast::Name, ty::Visibility), |
1a4d82fc JJ |
759 | G: FnMut(ast::CrateNum) -> Rc<crate_metadata>, |
760 | { | |
761 | let root_doc = rbml::Doc::new(cdata.data()); | |
970d7e83 LB |
762 | let misc_info_doc = reader::get_doc(root_doc, tag_misc_info); |
763 | let crate_items_doc = reader::get_doc(misc_info_doc, | |
764 | tag_misc_info_crate_items); | |
765 | ||
1a4d82fc JJ |
766 | each_child_of_item_or_crate(intr, |
767 | cdata, | |
768 | crate_items_doc, | |
769 | get_crate_data, | |
770 | callback) | |
771 | } | |
772 | ||
b039eaaf | 773 | pub fn get_item_name(intr: &IdentInterner, cdata: Cmd, id: DefIndex) -> ast::Name { |
e9174d1e | 774 | item_name(intr, cdata.lookup_item(id)) |
1a4d82fc JJ |
775 | } |
776 | ||
54a0048b | 777 | pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &TyCtxt<'tcx>, id: DefIndex) |
92a42be0 | 778 | -> FoundAst<'tcx> { |
b039eaaf | 779 | debug!("Looking up item: {:?}", id); |
e9174d1e | 780 | let item_doc = cdata.lookup_item(id); |
b039eaaf | 781 | let item_did = item_def_id(item_doc, cdata); |
54a0048b SL |
782 | let parent_def_id = DefId { |
783 | krate: cdata.cnum, | |
784 | index: def_key(cdata, id).parent.unwrap() | |
9cc50fc6 | 785 | }; |
54a0048b SL |
786 | let mut parent_def_path = def_path(cdata, id); |
787 | parent_def_path.data.pop(); | |
788 | if let Some(ast_doc) = reader::maybe_get_doc(item_doc, tag_ast as usize) { | |
789 | let ii = decode_inlined_item(cdata, | |
790 | tcx, | |
791 | parent_def_path, | |
792 | parent_def_id, | |
793 | ast_doc, | |
794 | item_did); | |
795 | return FoundAst::Found(ii); | |
796 | } else if let Some(parent_did) = item_parent_item(cdata, item_doc) { | |
797 | // Remove the last element from the paths, since we are now | |
798 | // trying to inline the parent. | |
799 | let grandparent_def_id = DefId { | |
800 | krate: cdata.cnum, | |
801 | index: def_key(cdata, parent_def_id.index).parent.unwrap() | |
802 | }; | |
803 | let mut grandparent_def_path = parent_def_path; | |
804 | grandparent_def_path.data.pop(); | |
805 | let parent_doc = cdata.lookup_item(parent_did.index); | |
806 | if let Some(ast_doc) = reader::maybe_get_doc(parent_doc, tag_ast as usize) { | |
807 | let ii = decode_inlined_item(cdata, | |
808 | tcx, | |
809 | grandparent_def_path, | |
810 | grandparent_def_id, | |
811 | ast_doc, | |
812 | parent_did); | |
813 | if let &InlinedItem::Item(ref i) = ii { | |
814 | return FoundAst::FoundParent(parent_did, i); | |
223e47cc | 815 | } |
223e47cc | 816 | } |
223e47cc | 817 | } |
54a0048b | 818 | FoundAst::NotFound |
223e47cc LB |
819 | } |
820 | ||
7453a54e SL |
821 | pub fn is_item_mir_available<'tcx>(cdata: Cmd, id: DefIndex) -> bool { |
822 | if let Some(item_doc) = cdata.get_item(id) { | |
823 | return reader::maybe_get_doc(item_doc, tag_mir as usize).is_some(); | |
824 | } | |
825 | ||
826 | false | |
827 | } | |
828 | ||
9cc50fc6 | 829 | pub fn maybe_get_item_mir<'tcx>(cdata: Cmd, |
54a0048b | 830 | tcx: &TyCtxt<'tcx>, |
9cc50fc6 SL |
831 | id: DefIndex) |
832 | -> Option<mir::repr::Mir<'tcx>> { | |
833 | let item_doc = cdata.lookup_item(id); | |
834 | ||
835 | return reader::maybe_get_doc(item_doc, tag_mir as usize).map(|mir_doc| { | |
836 | let dcx = tls_context::DecodingContext { | |
837 | crate_metadata: cdata, | |
838 | tcx: tcx, | |
839 | }; | |
840 | let mut decoder = reader::Decoder::new(mir_doc); | |
841 | ||
842 | let mut mir = decoder.read_opaque(|opaque_decoder, _| { | |
843 | tls::enter_decoding_context(&dcx, opaque_decoder, |_, opaque_decoder| { | |
844 | Decodable::decode(opaque_decoder) | |
845 | }) | |
846 | }).unwrap(); | |
847 | ||
7453a54e SL |
848 | assert!(decoder.position() == mir_doc.end); |
849 | ||
9cc50fc6 SL |
850 | let mut def_id_and_span_translator = MirDefIdAndSpanTranslator { |
851 | crate_metadata: cdata, | |
852 | codemap: tcx.sess.codemap(), | |
853 | last_filemap_index_hint: Cell::new(0), | |
854 | }; | |
855 | ||
856 | def_id_and_span_translator.visit_mir(&mut mir); | |
857 | ||
858 | mir | |
859 | }); | |
860 | ||
861 | struct MirDefIdAndSpanTranslator<'cdata, 'codemap> { | |
862 | crate_metadata: Cmd<'cdata>, | |
863 | codemap: &'codemap codemap::CodeMap, | |
864 | last_filemap_index_hint: Cell<usize> | |
865 | } | |
866 | ||
867 | impl<'v, 'cdata, 'codemap> mir::visit::MutVisitor<'v> | |
868 | for MirDefIdAndSpanTranslator<'cdata, 'codemap> | |
869 | { | |
870 | fn visit_def_id(&mut self, def_id: &mut DefId) { | |
871 | *def_id = translate_def_id(self.crate_metadata, *def_id); | |
872 | } | |
873 | ||
874 | fn visit_span(&mut self, span: &mut Span) { | |
875 | *span = translate_span(self.crate_metadata, | |
876 | self.codemap, | |
877 | &self.last_filemap_index_hint, | |
878 | *span); | |
879 | } | |
880 | } | |
881 | } | |
882 | ||
1a4d82fc | 883 | fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory { |
e9174d1e | 884 | fn get_mutability(ch: u8) -> hir::Mutability { |
223e47cc | 885 | match ch as char { |
e9174d1e SL |
886 | 'i' => hir::MutImmutable, |
887 | 'm' => hir::MutMutable, | |
54a0048b | 888 | _ => bug!("unknown mutability character: `{}`", ch as char), |
223e47cc LB |
889 | } |
890 | } | |
891 | ||
970d7e83 LB |
892 | let explicit_self_doc = reader::get_doc(item, tag_item_trait_method_explicit_self); |
893 | let string = explicit_self_doc.as_str_slice(); | |
223e47cc | 894 | |
1a4d82fc | 895 | let explicit_self_kind = string.as_bytes()[0]; |
970d7e83 | 896 | match explicit_self_kind as char { |
9cc50fc6 SL |
897 | 's' => ty::ExplicitSelfCategory::Static, |
898 | 'v' => ty::ExplicitSelfCategory::ByValue, | |
899 | '~' => ty::ExplicitSelfCategory::ByBox, | |
1a4d82fc | 900 | // FIXME(#4846) expl. region |
223e47cc | 901 | '&' => { |
9cc50fc6 | 902 | ty::ExplicitSelfCategory::ByReference( |
1a4d82fc JJ |
903 | ty::ReEmpty, |
904 | get_mutability(string.as_bytes()[1])) | |
223e47cc | 905 | } |
54a0048b | 906 | _ => bug!("unknown self type code: `{}`", explicit_self_kind as char) |
223e47cc LB |
907 | } |
908 | } | |
909 | ||
1a4d82fc | 910 | /// Returns the def IDs of all the items in the given implementation. |
b039eaaf | 911 | pub fn get_impl_items(cdata: Cmd, impl_id: DefIndex) |
1a4d82fc | 912 | -> Vec<ty::ImplOrTraitItemId> { |
e9174d1e | 913 | reader::tagged_docs(cdata.lookup_item(impl_id), tag_item_impl_item).map(|doc| { |
1a4d82fc JJ |
914 | let def_id = item_def_id(doc, cdata); |
915 | match item_sort(doc) { | |
b039eaaf | 916 | Some('C') | Some('c') => ty::ConstTraitItemId(def_id), |
62682a34 SL |
917 | Some('r') | Some('p') => ty::MethodTraitItemId(def_id), |
918 | Some('t') => ty::TypeTraitItemId(def_id), | |
54a0048b | 919 | _ => bug!("unknown impl item sort"), |
1a4d82fc | 920 | } |
62682a34 | 921 | }).collect() |
1a4d82fc JJ |
922 | } |
923 | ||
924 | pub fn get_trait_name(intr: Rc<IdentInterner>, | |
925 | cdata: Cmd, | |
b039eaaf | 926 | id: DefIndex) |
1a4d82fc | 927 | -> ast::Name { |
e9174d1e | 928 | let doc = cdata.lookup_item(id); |
7453a54e | 929 | item_name(&intr, doc) |
1a4d82fc JJ |
930 | } |
931 | ||
b039eaaf | 932 | pub fn is_static_method(cdata: Cmd, id: DefIndex) -> bool { |
e9174d1e | 933 | let doc = cdata.lookup_item(id); |
1a4d82fc | 934 | match item_sort(doc) { |
c34b1796 | 935 | Some('r') | Some('p') => { |
9cc50fc6 | 936 | get_explicit_self(doc) == ty::ExplicitSelfCategory::Static |
1a4d82fc | 937 | } |
c34b1796 | 938 | _ => false |
223e47cc | 939 | } |
223e47cc LB |
940 | } |
941 | ||
1a4d82fc JJ |
942 | pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>, |
943 | cdata: Cmd, | |
b039eaaf | 944 | id: DefIndex, |
54a0048b SL |
945 | tcx: &TyCtxt<'tcx>) |
946 | -> Option<ty::ImplOrTraitItem<'tcx>> { | |
e9174d1e | 947 | let item_doc = cdata.lookup_item(id); |
970d7e83 | 948 | |
62682a34 | 949 | let def_id = item_def_id(item_doc, cdata); |
1a4d82fc | 950 | |
54a0048b SL |
951 | let container_id = if let Some(id) = item_parent_item(cdata, item_doc) { |
952 | id | |
953 | } else { | |
954 | return None; | |
955 | }; | |
b039eaaf | 956 | let container_doc = cdata.lookup_item(container_id.index); |
1a4d82fc JJ |
957 | let container = match item_family(container_doc) { |
958 | Trait => TraitContainer(container_id), | |
959 | _ => ImplContainer(container_id), | |
960 | }; | |
961 | ||
7453a54e | 962 | let name = item_name(&intr, item_doc); |
62682a34 | 963 | let vis = item_visibility(item_doc); |
54a0048b | 964 | let defaultness = item_defaultness(item_doc); |
1a4d82fc | 965 | |
54a0048b | 966 | Some(match item_sort(item_doc) { |
b039eaaf | 967 | sort @ Some('C') | sort @ Some('c') => { |
62682a34 | 968 | let ty = doc_type(item_doc, tcx, cdata); |
d9579d0f AL |
969 | ty::ConstTraitItem(Rc::new(ty::AssociatedConst { |
970 | name: name, | |
971 | ty: ty, | |
972 | vis: vis, | |
54a0048b | 973 | defaultness: defaultness, |
d9579d0f AL |
974 | def_id: def_id, |
975 | container: container, | |
b039eaaf | 976 | has_value: sort == Some('C') |
d9579d0f AL |
977 | })) |
978 | } | |
c34b1796 | 979 | Some('r') | Some('p') => { |
62682a34 SL |
980 | let generics = doc_generics(item_doc, tcx, cdata, tag_method_ty_generics); |
981 | let predicates = doc_predicates(item_doc, tcx, cdata, tag_method_ty_generics); | |
b039eaaf SL |
982 | let ity = tcx.lookup_item_type(def_id).ty; |
983 | let fty = match ity.sty { | |
54a0048b SL |
984 | ty::TyFnDef(_, _, fty) => fty.clone(), |
985 | _ => bug!( | |
b039eaaf | 986 | "the type {:?} of the method {:?} is not a function?", |
54a0048b | 987 | ity, name) |
b039eaaf | 988 | }; |
62682a34 | 989 | let explicit_self = get_explicit_self(item_doc); |
1a4d82fc JJ |
990 | |
991 | ty::MethodTraitItem(Rc::new(ty::Method::new(name, | |
992 | generics, | |
85aaf69f | 993 | predicates, |
1a4d82fc JJ |
994 | fty, |
995 | explicit_self, | |
996 | vis, | |
54a0048b | 997 | defaultness, |
1a4d82fc | 998 | def_id, |
b039eaaf | 999 | container))) |
1a4d82fc | 1000 | } |
c34b1796 | 1001 | Some('t') => { |
62682a34 | 1002 | let ty = maybe_doc_type(item_doc, tcx, cdata); |
1a4d82fc JJ |
1003 | ty::TypeTraitItem(Rc::new(ty::AssociatedType { |
1004 | name: name, | |
62682a34 | 1005 | ty: ty, |
1a4d82fc | 1006 | vis: vis, |
54a0048b | 1007 | defaultness: defaultness, |
1a4d82fc JJ |
1008 | def_id: def_id, |
1009 | container: container, | |
1010 | })) | |
1011 | } | |
54a0048b SL |
1012 | _ => return None |
1013 | }) | |
1a4d82fc JJ |
1014 | } |
1015 | ||
b039eaaf | 1016 | pub fn get_trait_item_def_ids(cdata: Cmd, id: DefIndex) |
1a4d82fc | 1017 | -> Vec<ty::ImplOrTraitItemId> { |
e9174d1e | 1018 | let item = cdata.lookup_item(id); |
62682a34 | 1019 | reader::tagged_docs(item, tag_item_trait_item).map(|mth| { |
1a4d82fc JJ |
1020 | let def_id = item_def_id(mth, cdata); |
1021 | match item_sort(mth) { | |
b039eaaf | 1022 | Some('C') | Some('c') => ty::ConstTraitItemId(def_id), |
62682a34 SL |
1023 | Some('r') | Some('p') => ty::MethodTraitItemId(def_id), |
1024 | Some('t') => ty::TypeTraitItemId(def_id), | |
54a0048b | 1025 | _ => bug!("unknown trait item sort"), |
1a4d82fc | 1026 | } |
62682a34 | 1027 | }).collect() |
223e47cc LB |
1028 | } |
1029 | ||
b039eaaf | 1030 | pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> ty::ItemVariances { |
e9174d1e | 1031 | let item_doc = cdata.lookup_item(id); |
1a4d82fc JJ |
1032 | let variance_doc = reader::get_doc(item_doc, tag_item_variances); |
1033 | let mut decoder = reader::Decoder::new(variance_doc); | |
1034 | Decodable::decode(&mut decoder).unwrap() | |
1035 | } | |
1036 | ||
1037 | pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>, | |
1038 | cdata: Cmd, | |
b039eaaf | 1039 | id: DefIndex, |
54a0048b | 1040 | tcx: &TyCtxt<'tcx>) |
1a4d82fc | 1041 | -> Vec<Rc<ty::Method<'tcx>>> { |
e9174d1e | 1042 | let item = cdata.lookup_item(id); |
223e47cc | 1043 | |
62682a34 | 1044 | reader::tagged_docs(item, tag_item_trait_item).filter_map(|mth_id| { |
970d7e83 | 1045 | let did = item_def_id(mth_id, cdata); |
b039eaaf | 1046 | let mth = cdata.lookup_item(did.index); |
223e47cc | 1047 | |
c34b1796 | 1048 | if item_sort(mth) == Some('p') { |
1a4d82fc JJ |
1049 | let trait_item = get_impl_or_trait_item(intr.clone(), |
1050 | cdata, | |
b039eaaf | 1051 | did.index, |
1a4d82fc | 1052 | tcx); |
54a0048b | 1053 | if let Some(ty::MethodTraitItem(ref method)) = trait_item { |
62682a34 SL |
1054 | Some((*method).clone()) |
1055 | } else { | |
1056 | None | |
1a4d82fc | 1057 | } |
62682a34 SL |
1058 | } else { |
1059 | None | |
1a4d82fc | 1060 | } |
62682a34 | 1061 | }).collect() |
223e47cc LB |
1062 | } |
1063 | ||
d9579d0f AL |
1064 | pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>, |
1065 | cdata: Cmd, | |
b039eaaf | 1066 | id: DefIndex, |
54a0048b | 1067 | tcx: &TyCtxt<'tcx>) |
d9579d0f | 1068 | -> Vec<Rc<ty::AssociatedConst<'tcx>>> { |
e9174d1e | 1069 | let item = cdata.lookup_item(id); |
d9579d0f | 1070 | |
62682a34 SL |
1071 | [tag_item_trait_item, tag_item_impl_item].iter().flat_map(|&tag| { |
1072 | reader::tagged_docs(item, tag).filter_map(|ac_id| { | |
d9579d0f | 1073 | let did = item_def_id(ac_id, cdata); |
b039eaaf SL |
1074 | let ac_doc = cdata.lookup_item(did.index); |
1075 | ||
1076 | match item_sort(ac_doc) { | |
1077 | Some('C') | Some('c') => { | |
1078 | let trait_item = get_impl_or_trait_item(intr.clone(), | |
1079 | cdata, | |
1080 | did.index, | |
1081 | tcx); | |
54a0048b | 1082 | if let Some(ty::ConstTraitItem(ref ac)) = trait_item { |
b039eaaf SL |
1083 | Some((*ac).clone()) |
1084 | } else { | |
1085 | None | |
1086 | } | |
d9579d0f | 1087 | } |
b039eaaf | 1088 | _ => None |
d9579d0f | 1089 | } |
62682a34 SL |
1090 | }) |
1091 | }).collect() | |
d9579d0f AL |
1092 | } |
1093 | ||
7453a54e SL |
1094 | pub fn get_variant_kind(cdata: Cmd, node_id: DefIndex) -> Option<VariantKind> |
1095 | { | |
1096 | let item = cdata.lookup_item(node_id); | |
1097 | family_to_variant_kind(item_family(item)) | |
1098 | } | |
1099 | ||
1100 | pub fn get_struct_ctor_def_id(cdata: Cmd, node_id: DefIndex) -> Option<DefId> | |
1101 | { | |
1102 | let item = cdata.lookup_item(node_id); | |
1103 | reader::maybe_get_doc(item, tag_items_data_item_struct_ctor). | |
1104 | map(|ctor_doc| translated_def_id(cdata, ctor_doc)) | |
1105 | } | |
1106 | ||
1a4d82fc JJ |
1107 | /// If node_id is the constructor of a tuple struct, retrieve the NodeId of |
1108 | /// the actual type definition, otherwise, return None | |
1109 | pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd, | |
b039eaaf | 1110 | node_id: DefIndex) |
e9174d1e | 1111 | -> Option<DefId> |
1a4d82fc | 1112 | { |
e9174d1e | 1113 | let item = cdata.lookup_item(node_id); |
62682a34 SL |
1114 | reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor).next().map(|_| { |
1115 | item_require_parent_item(cdata, item) | |
1116 | }) | |
1a4d82fc JJ |
1117 | } |
1118 | ||
85aaf69f | 1119 | pub fn get_item_attrs(cdata: Cmd, |
b039eaaf SL |
1120 | orig_node_id: DefIndex) |
1121 | -> Vec<ast::Attribute> { | |
1a4d82fc JJ |
1122 | // The attributes for a tuple struct are attached to the definition, not the ctor; |
1123 | // we assume that someone passing in a tuple struct ctor is actually wanting to | |
1124 | // look at the definition | |
1125 | let node_id = get_tuple_struct_definition_if_ctor(cdata, orig_node_id); | |
b039eaaf | 1126 | let node_id = node_id.map(|x| x.index).unwrap_or(orig_node_id); |
e9174d1e | 1127 | let item = cdata.lookup_item(node_id); |
85aaf69f | 1128 | get_attributes(item) |
1a4d82fc JJ |
1129 | } |
1130 | ||
b039eaaf | 1131 | pub fn get_struct_field_attrs(cdata: Cmd) -> FnvHashMap<DefId, Vec<ast::Attribute>> { |
1a4d82fc JJ |
1132 | let data = rbml::Doc::new(cdata.data()); |
1133 | let fields = reader::get_doc(data, tag_struct_fields); | |
62682a34 | 1134 | reader::tagged_docs(fields, tag_struct_field).map(|field| { |
b039eaaf | 1135 | let def_id = translated_def_id(cdata, reader::get_doc(field, tag_def_id)); |
1a4d82fc | 1136 | let attrs = get_attributes(field); |
b039eaaf | 1137 | (def_id, attrs) |
62682a34 | 1138 | }).collect() |
1a4d82fc JJ |
1139 | } |
1140 | ||
54a0048b | 1141 | fn struct_field_family_to_visibility(family: Family) -> ty::Visibility { |
223e47cc | 1142 | match family { |
54a0048b SL |
1143 | PublicField => ty::Visibility::Public, |
1144 | InheritedField => ty::Visibility::PrivateExternal, | |
1145 | _ => bug!() | |
223e47cc LB |
1146 | } |
1147 | } | |
1148 | ||
b039eaaf | 1149 | pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: DefIndex) |
e9174d1e SL |
1150 | -> Vec<ast::Name> { |
1151 | let item = cdata.lookup_item(id); | |
54a0048b | 1152 | let mut index = 0; |
e9174d1e SL |
1153 | reader::tagged_docs(item, tag_item_field).map(|an_item| { |
1154 | item_name(intr, an_item) | |
1155 | }).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|_| { | |
54a0048b SL |
1156 | let name = intr.intern(&index.to_string()); |
1157 | index += 1; | |
1158 | name | |
62682a34 | 1159 | })).collect() |
223e47cc LB |
1160 | } |
1161 | ||
b039eaaf | 1162 | fn get_meta_items(md: rbml::Doc) -> Vec<P<ast::MetaItem>> { |
62682a34 | 1163 | reader::tagged_docs(md, tag_meta_item_word).map(|meta_item_doc| { |
223e47cc | 1164 | let nd = reader::get_doc(meta_item_doc, tag_meta_item_name); |
1a4d82fc | 1165 | let n = token::intern_and_get_ident(nd.as_str_slice()); |
62682a34 SL |
1166 | attr::mk_word_item(n) |
1167 | }).chain(reader::tagged_docs(md, tag_meta_item_name_value).map(|meta_item_doc| { | |
223e47cc LB |
1168 | let nd = reader::get_doc(meta_item_doc, tag_meta_item_name); |
1169 | let vd = reader::get_doc(meta_item_doc, tag_meta_item_value); | |
1a4d82fc JJ |
1170 | let n = token::intern_and_get_ident(nd.as_str_slice()); |
1171 | let v = token::intern_and_get_ident(vd.as_str_slice()); | |
7453a54e | 1172 | // FIXME (#623): Should be able to decode MetaItemKind::NameValue variants, |
223e47cc | 1173 | // but currently the encoder just drops them |
62682a34 SL |
1174 | attr::mk_name_value_item_str(n, v) |
1175 | })).chain(reader::tagged_docs(md, tag_meta_item_list).map(|meta_item_doc| { | |
223e47cc | 1176 | let nd = reader::get_doc(meta_item_doc, tag_meta_item_name); |
1a4d82fc | 1177 | let n = token::intern_and_get_ident(nd.as_str_slice()); |
223e47cc | 1178 | let subitems = get_meta_items(meta_item_doc); |
62682a34 SL |
1179 | attr::mk_list_item(n, subitems) |
1180 | })).collect() | |
223e47cc LB |
1181 | } |
1182 | ||
b039eaaf | 1183 | fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> { |
223e47cc | 1184 | match reader::maybe_get_doc(md, tag_attributes) { |
62682a34 SL |
1185 | Some(attrs_d) => { |
1186 | reader::tagged_docs(attrs_d, tag_attribute).map(|attr_doc| { | |
1187 | let is_sugared_doc = reader::doc_as_u8( | |
1188 | reader::get_doc(attr_doc, tag_attribute_is_sugared_doc) | |
1189 | ) == 1; | |
1190 | let meta_items = get_meta_items(attr_doc); | |
1191 | // Currently it's only possible to have a single meta item on | |
1192 | // an attribute | |
1193 | assert_eq!(meta_items.len(), 1); | |
1194 | let meta_item = meta_items.into_iter().nth(0).unwrap(); | |
1a4d82fc | 1195 | codemap::Spanned { |
b039eaaf | 1196 | node: ast::Attribute_ { |
1a4d82fc | 1197 | id: attr::mk_attr_id(), |
b039eaaf | 1198 | style: ast::AttrStyle::Outer, |
223e47cc | 1199 | value: meta_item, |
1a4d82fc | 1200 | is_sugared_doc: is_sugared_doc, |
223e47cc | 1201 | }, |
1a4d82fc | 1202 | span: codemap::DUMMY_SP |
62682a34 SL |
1203 | } |
1204 | }).collect() | |
1205 | }, | |
1206 | None => vec![], | |
223e47cc | 1207 | } |
223e47cc LB |
1208 | } |
1209 | ||
1a4d82fc | 1210 | fn list_crate_attributes(md: rbml::Doc, hash: &Svh, |
c34b1796 | 1211 | out: &mut io::Write) -> io::Result<()> { |
54a0048b | 1212 | write!(out, "=Crate Attributes ({})=\n", *hash)?; |
223e47cc | 1213 | |
970d7e83 | 1214 | let r = get_attributes(md); |
85aaf69f | 1215 | for attr in &r { |
54a0048b | 1216 | write!(out, "{}\n", pprust::attribute_to_string(attr))?; |
223e47cc LB |
1217 | } |
1218 | ||
1a4d82fc | 1219 | write!(out, "\n\n") |
223e47cc LB |
1220 | } |
1221 | ||
b039eaaf | 1222 | pub fn get_crate_attributes(data: &[u8]) -> Vec<ast::Attribute> { |
1a4d82fc | 1223 | get_attributes(rbml::Doc::new(data)) |
223e47cc LB |
1224 | } |
1225 | ||
1a4d82fc JJ |
1226 | #[derive(Clone)] |
1227 | pub struct CrateDep { | |
1228 | pub cnum: ast::CrateNum, | |
1229 | pub name: String, | |
1230 | pub hash: Svh, | |
e9174d1e | 1231 | pub explicitly_linked: bool, |
223e47cc LB |
1232 | } |
1233 | ||
1a4d82fc | 1234 | pub fn get_crate_deps(data: &[u8]) -> Vec<CrateDep> { |
1a4d82fc | 1235 | let cratedoc = rbml::Doc::new(data); |
223e47cc | 1236 | let depsdoc = reader::get_doc(cratedoc, tag_crate_deps); |
62682a34 | 1237 | |
c34b1796 | 1238 | fn docstr(doc: rbml::Doc, tag_: usize) -> String { |
970d7e83 | 1239 | let d = reader::get_doc(doc, tag_); |
1a4d82fc | 1240 | d.as_str_slice().to_string() |
223e47cc | 1241 | } |
62682a34 SL |
1242 | |
1243 | reader::tagged_docs(depsdoc, tag_crate_dep).enumerate().map(|(crate_num, depdoc)| { | |
1a4d82fc | 1244 | let name = docstr(depdoc, tag_crate_dep_crate_name); |
54a0048b | 1245 | let hash = Svh::new(docstr(depdoc, tag_crate_dep_hash)); |
e9174d1e SL |
1246 | let doc = reader::get_doc(depdoc, tag_crate_dep_explicitly_linked); |
1247 | let explicitly_linked = reader::doc_as_u8(doc) != 0; | |
62682a34 SL |
1248 | CrateDep { |
1249 | cnum: crate_num as u32 + 1, | |
1a4d82fc JJ |
1250 | name: name, |
1251 | hash: hash, | |
e9174d1e | 1252 | explicitly_linked: explicitly_linked, |
62682a34 SL |
1253 | } |
1254 | }).collect() | |
223e47cc LB |
1255 | } |
1256 | ||
c34b1796 | 1257 | fn list_crate_deps(data: &[u8], out: &mut io::Write) -> io::Result<()> { |
54a0048b | 1258 | write!(out, "=External Dependencies=\n")?; |
85aaf69f | 1259 | for dep in &get_crate_deps(data) { |
54a0048b | 1260 | write!(out, "{} {}-{}\n", dep.cnum, dep.name, dep.hash)?; |
223e47cc | 1261 | } |
54a0048b | 1262 | write!(out, "\n")?; |
1a4d82fc JJ |
1263 | Ok(()) |
1264 | } | |
223e47cc | 1265 | |
1a4d82fc JJ |
1266 | pub fn maybe_get_crate_hash(data: &[u8]) -> Option<Svh> { |
1267 | let cratedoc = rbml::Doc::new(data); | |
1268 | reader::maybe_get_doc(cratedoc, tag_crate_hash).map(|doc| { | |
54a0048b | 1269 | Svh::new(doc.as_str_slice().to_string()) |
1a4d82fc | 1270 | }) |
223e47cc LB |
1271 | } |
1272 | ||
1a4d82fc JJ |
1273 | pub fn get_crate_hash(data: &[u8]) -> Svh { |
1274 | let cratedoc = rbml::Doc::new(data); | |
223e47cc | 1275 | let hashdoc = reader::get_doc(cratedoc, tag_crate_hash); |
54a0048b | 1276 | Svh::new(hashdoc.as_str_slice().to_string()) |
223e47cc LB |
1277 | } |
1278 | ||
54a0048b | 1279 | pub fn maybe_get_crate_name(data: &[u8]) -> Option<&str> { |
1a4d82fc JJ |
1280 | let cratedoc = rbml::Doc::new(data); |
1281 | reader::maybe_get_doc(cratedoc, tag_crate_crate_name).map(|doc| { | |
54a0048b | 1282 | doc.as_str_slice() |
1a4d82fc JJ |
1283 | }) |
1284 | } | |
223e47cc | 1285 | |
54a0048b SL |
1286 | pub fn get_crate_disambiguator<'a>(data: &'a [u8]) -> &'a str { |
1287 | let crate_doc = rbml::Doc::new(data); | |
1288 | let disambiguator_doc = reader::get_doc(crate_doc, tag_crate_disambiguator); | |
1289 | let slice: &'a str = disambiguator_doc.as_str_slice(); | |
1290 | slice | |
1291 | } | |
1292 | ||
1a4d82fc JJ |
1293 | pub fn get_crate_triple(data: &[u8]) -> Option<String> { |
1294 | let cratedoc = rbml::Doc::new(data); | |
1295 | let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple); | |
1296 | triple_doc.map(|s| s.as_str().to_string()) | |
223e47cc LB |
1297 | } |
1298 | ||
54a0048b | 1299 | pub fn get_crate_name(data: &[u8]) -> &str { |
1a4d82fc | 1300 | maybe_get_crate_name(data).expect("no crate name in crate") |
223e47cc LB |
1301 | } |
1302 | ||
c34b1796 | 1303 | pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Write) -> io::Result<()> { |
223e47cc | 1304 | let hash = get_crate_hash(bytes); |
1a4d82fc | 1305 | let md = rbml::Doc::new(bytes); |
54a0048b | 1306 | list_crate_attributes(md, &hash, out)?; |
1a4d82fc | 1307 | list_crate_deps(bytes, out) |
223e47cc LB |
1308 | } |
1309 | ||
1310 | // Translates a def_id from an external crate to a def_id for the current | |
1311 | // compilation environment. We use this when trying to load types from | |
1312 | // external crates - if those types further refer to types in other crates | |
1313 | // then we must translate the crate number from that encoded in the external | |
1314 | // crate to the correct local crate number. | |
e9174d1e SL |
1315 | pub fn translate_def_id(cdata: Cmd, did: DefId) -> DefId { |
1316 | if did.is_local() { | |
b039eaaf | 1317 | return DefId { krate: cdata.cnum, index: did.index }; |
223e47cc LB |
1318 | } |
1319 | ||
e9174d1e | 1320 | match cdata.cnum_map.borrow().get(&did.krate) { |
1a4d82fc | 1321 | Some(&n) => { |
e9174d1e | 1322 | DefId { |
1a4d82fc | 1323 | krate: n, |
b039eaaf | 1324 | index: did.index, |
1a4d82fc JJ |
1325 | } |
1326 | } | |
54a0048b | 1327 | None => bug!("didn't find a crate in the cnum_map") |
223e47cc LB |
1328 | } |
1329 | } | |
1330 | ||
d9579d0f AL |
1331 | // Translate a DefId from the current compilation environment to a DefId |
1332 | // for an external crate. | |
e9174d1e | 1333 | fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option<DefId> { |
d9579d0f | 1334 | if did.krate == cdata.cnum { |
b039eaaf | 1335 | return Some(DefId { krate: LOCAL_CRATE, index: did.index }); |
d9579d0f AL |
1336 | } |
1337 | ||
e9174d1e | 1338 | for (&local, &global) in cdata.cnum_map.borrow().iter() { |
d9579d0f | 1339 | if global == did.krate { |
b039eaaf | 1340 | return Some(DefId { krate: local, index: did.index }); |
d9579d0f AL |
1341 | } |
1342 | } | |
1343 | ||
1344 | None | |
1a4d82fc JJ |
1345 | } |
1346 | ||
9cc50fc6 SL |
1347 | /// Translates a `Span` from an extern crate to the corresponding `Span` |
1348 | /// within the local crate's codemap. | |
1349 | pub fn translate_span(cdata: Cmd, | |
1350 | codemap: &codemap::CodeMap, | |
1351 | last_filemap_index_hint: &Cell<usize>, | |
1352 | span: codemap::Span) | |
1353 | -> codemap::Span { | |
1354 | let span = if span.lo > span.hi { | |
1355 | // Currently macro expansion sometimes produces invalid Span values | |
1356 | // where lo > hi. In order not to crash the compiler when trying to | |
1357 | // translate these values, let's transform them into something we | |
1358 | // can handle (and which will produce useful debug locations at | |
1359 | // least some of the time). | |
1360 | // This workaround is only necessary as long as macro expansion is | |
1361 | // not fixed. FIXME(#23480) | |
1362 | codemap::mk_sp(span.lo, span.lo) | |
1363 | } else { | |
1364 | span | |
1365 | }; | |
1366 | ||
1367 | let imported_filemaps = cdata.imported_filemaps(&codemap); | |
1368 | let filemap = { | |
1369 | // Optimize for the case that most spans within a translated item | |
1370 | // originate from the same filemap. | |
1371 | let last_filemap_index = last_filemap_index_hint.get(); | |
1372 | let last_filemap = &imported_filemaps[last_filemap_index]; | |
1373 | ||
1374 | if span.lo >= last_filemap.original_start_pos && | |
1375 | span.lo <= last_filemap.original_end_pos && | |
1376 | span.hi >= last_filemap.original_start_pos && | |
1377 | span.hi <= last_filemap.original_end_pos { | |
1378 | last_filemap | |
1379 | } else { | |
1380 | let mut a = 0; | |
1381 | let mut b = imported_filemaps.len(); | |
1382 | ||
1383 | while b - a > 1 { | |
1384 | let m = (a + b) / 2; | |
1385 | if imported_filemaps[m].original_start_pos > span.lo { | |
1386 | b = m; | |
1387 | } else { | |
1388 | a = m; | |
1389 | } | |
1390 | } | |
1391 | ||
1392 | last_filemap_index_hint.set(a); | |
1393 | &imported_filemaps[a] | |
1394 | } | |
1395 | }; | |
1396 | ||
1397 | let lo = (span.lo - filemap.original_start_pos) + | |
1398 | filemap.translated_filemap.start_pos; | |
1399 | let hi = (span.hi - filemap.original_start_pos) + | |
1400 | filemap.translated_filemap.start_pos; | |
1401 | ||
1402 | codemap::mk_sp(lo, hi) | |
1403 | } | |
1404 | ||
d9579d0f | 1405 | pub fn each_inherent_implementation_for_type<F>(cdata: Cmd, |
b039eaaf | 1406 | id: DefIndex, |
d9579d0f | 1407 | mut callback: F) |
e9174d1e | 1408 | where F: FnMut(DefId), |
1a4d82fc | 1409 | { |
e9174d1e | 1410 | let item_doc = cdata.lookup_item(id); |
62682a34 | 1411 | for impl_doc in reader::tagged_docs(item_doc, tag_items_data_item_inherent_impl) { |
d9579d0f AL |
1412 | if reader::maybe_get_doc(impl_doc, tag_item_trait_ref).is_none() { |
1413 | callback(item_def_id(impl_doc, cdata)); | |
1414 | } | |
62682a34 | 1415 | } |
1a4d82fc JJ |
1416 | } |
1417 | ||
1418 | pub fn each_implementation_for_trait<F>(cdata: Cmd, | |
e9174d1e | 1419 | def_id: DefId, |
1a4d82fc | 1420 | mut callback: F) where |
e9174d1e | 1421 | F: FnMut(DefId), |
1a4d82fc | 1422 | { |
d9579d0f AL |
1423 | // Do a reverse lookup beforehand to avoid touching the crate_num |
1424 | // hash map in the loop below. | |
1425 | if let Some(crate_local_did) = reverse_translate_def_id(cdata, def_id) { | |
1426 | let def_id_u64 = def_to_u64(crate_local_did); | |
1427 | ||
1428 | let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls); | |
b039eaaf SL |
1429 | for trait_doc in reader::tagged_docs(impls_doc, tag_impls_trait) { |
1430 | let trait_def_id = reader::get_doc(trait_doc, tag_def_id); | |
1431 | if reader::doc_as_u64(trait_def_id) != def_id_u64 { | |
1432 | continue; | |
1433 | } | |
1434 | for impl_doc in reader::tagged_docs(trait_doc, tag_impls_trait_impl) { | |
1435 | callback(translated_def_id(cdata, impl_doc)); | |
d9579d0f | 1436 | } |
62682a34 | 1437 | } |
d9579d0f | 1438 | } |
1a4d82fc JJ |
1439 | } |
1440 | ||
54a0048b | 1441 | pub fn get_trait_of_item(cdata: Cmd, id: DefIndex, tcx: &TyCtxt) |
e9174d1e SL |
1442 | -> Option<DefId> { |
1443 | let item_doc = cdata.lookup_item(id); | |
d9579d0f | 1444 | let parent_item_id = match item_parent_item(cdata, item_doc) { |
1a4d82fc JJ |
1445 | None => return None, |
1446 | Some(item_id) => item_id, | |
1447 | }; | |
b039eaaf | 1448 | let parent_item_doc = cdata.lookup_item(parent_item_id.index); |
1a4d82fc JJ |
1449 | match item_family(parent_item_doc) { |
1450 | Trait => Some(item_def_id(parent_item_doc, cdata)), | |
c34b1796 | 1451 | Impl | DefaultImpl => { |
1a4d82fc JJ |
1452 | reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref) |
1453 | .map(|_| item_trait_ref(parent_item_doc, tcx, cdata).def_id) | |
1454 | } | |
1455 | _ => None | |
1456 | } | |
1457 | } | |
1458 | ||
1459 | ||
1460 | pub fn get_native_libraries(cdata: Cmd) | |
1461 | -> Vec<(cstore::NativeLibraryKind, String)> { | |
1462 | let libraries = reader::get_doc(rbml::Doc::new(cdata.data()), | |
1463 | tag_native_libraries); | |
62682a34 | 1464 | reader::tagged_docs(libraries, tag_native_libraries_lib).map(|lib_doc| { |
1a4d82fc JJ |
1465 | let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind); |
1466 | let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name); | |
1467 | let kind: cstore::NativeLibraryKind = | |
9346a6ac | 1468 | cstore::NativeLibraryKind::from_u32(reader::doc_as_u32(kind_doc)).unwrap(); |
1a4d82fc | 1469 | let name = name_doc.as_str().to_string(); |
62682a34 SL |
1470 | (kind, name) |
1471 | }).collect() | |
1a4d82fc JJ |
1472 | } |
1473 | ||
b039eaaf | 1474 | pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<DefIndex> { |
1a4d82fc | 1475 | reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn) |
b039eaaf | 1476 | .map(|doc| DefIndex::from_u32(reader::doc_as_u32(doc))) |
1a4d82fc JJ |
1477 | } |
1478 | ||
1479 | pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where | |
7453a54e | 1480 | F: FnMut(ast::Name, Vec<ast::Attribute>, Span, String) -> bool, |
1a4d82fc JJ |
1481 | { |
1482 | let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs); | |
62682a34 | 1483 | for macro_doc in reader::tagged_docs(macros, tag_macro_def) { |
1a4d82fc JJ |
1484 | let name = item_name(intr, macro_doc); |
1485 | let attrs = get_attributes(macro_doc); | |
7453a54e | 1486 | let span = get_macro_span(macro_doc); |
1a4d82fc | 1487 | let body = reader::get_doc(macro_doc, tag_macro_def_body); |
7453a54e | 1488 | if !f(name, attrs, span, body.as_str().to_string()) { |
62682a34 SL |
1489 | break; |
1490 | } | |
1491 | } | |
1a4d82fc JJ |
1492 | } |
1493 | ||
7453a54e SL |
1494 | pub fn get_macro_span(doc: rbml::Doc) -> Span { |
1495 | let lo_doc = reader::get_doc(doc, tag_macro_def_span_lo); | |
1496 | let lo = BytePos(reader::doc_as_u32(lo_doc)); | |
1497 | let hi_doc = reader::get_doc(doc, tag_macro_def_span_hi); | |
1498 | let hi = BytePos(reader::doc_as_u32(hi_doc)); | |
1499 | return Span { lo: lo, hi: hi, expn_id: NO_EXPANSION }; | |
1500 | } | |
1501 | ||
1a4d82fc | 1502 | pub fn get_dylib_dependency_formats(cdata: Cmd) |
92a42be0 | 1503 | -> Vec<(ast::CrateNum, LinkagePreference)> |
1a4d82fc JJ |
1504 | { |
1505 | let formats = reader::get_doc(rbml::Doc::new(cdata.data()), | |
1506 | tag_dylib_dependency_formats); | |
1507 | let mut result = Vec::new(); | |
1508 | ||
1509 | debug!("found dylib deps: {}", formats.as_str_slice()); | |
1510 | for spec in formats.as_str_slice().split(',') { | |
9346a6ac | 1511 | if spec.is_empty() { continue } |
1a4d82fc JJ |
1512 | let cnum = spec.split(':').nth(0).unwrap(); |
1513 | let link = spec.split(':').nth(1).unwrap(); | |
1514 | let cnum: ast::CrateNum = cnum.parse().unwrap(); | |
e9174d1e | 1515 | let cnum = match cdata.cnum_map.borrow().get(&cnum) { |
1a4d82fc | 1516 | Some(&n) => n, |
54a0048b | 1517 | None => bug!("didn't find a crate in the cnum_map") |
1a4d82fc JJ |
1518 | }; |
1519 | result.push((cnum, if link == "d" { | |
92a42be0 | 1520 | LinkagePreference::RequireDynamic |
1a4d82fc | 1521 | } else { |
92a42be0 | 1522 | LinkagePreference::RequireStatic |
1a4d82fc JJ |
1523 | })); |
1524 | } | |
1525 | return result; | |
1526 | } | |
1527 | ||
1528 | pub fn get_missing_lang_items(cdata: Cmd) | |
1529 | -> Vec<lang_items::LangItem> | |
1530 | { | |
1531 | let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_lang_items); | |
62682a34 SL |
1532 | reader::tagged_docs(items, tag_lang_items_missing).map(|missing_docs| { |
1533 | lang_items::LangItem::from_u32(reader::doc_as_u32(missing_docs)).unwrap() | |
1534 | }).collect() | |
1a4d82fc JJ |
1535 | } |
1536 | ||
b039eaaf | 1537 | pub fn get_method_arg_names(cdata: Cmd, id: DefIndex) -> Vec<String> { |
e9174d1e | 1538 | let method_doc = cdata.lookup_item(id); |
1a4d82fc JJ |
1539 | match reader::maybe_get_doc(method_doc, tag_method_argument_names) { |
1540 | Some(args_doc) => { | |
62682a34 SL |
1541 | reader::tagged_docs(args_doc, tag_method_argument_name).map(|name_doc| { |
1542 | name_doc.as_str_slice().to_string() | |
1543 | }).collect() | |
1544 | }, | |
1545 | None => vec![], | |
1a4d82fc | 1546 | } |
1a4d82fc JJ |
1547 | } |
1548 | ||
e9174d1e | 1549 | pub fn get_reachable_ids(cdata: Cmd) -> Vec<DefId> { |
1a4d82fc | 1550 | let items = reader::get_doc(rbml::Doc::new(cdata.data()), |
e9174d1e SL |
1551 | tag_reachable_ids); |
1552 | reader::tagged_docs(items, tag_reachable_id).map(|doc| { | |
1553 | DefId { | |
1a4d82fc | 1554 | krate: cdata.cnum, |
b039eaaf | 1555 | index: DefIndex::from_u32(reader::doc_as_u32(doc)), |
62682a34 SL |
1556 | } |
1557 | }).collect() | |
1a4d82fc JJ |
1558 | } |
1559 | ||
b039eaaf | 1560 | pub fn is_typedef(cdata: Cmd, id: DefIndex) -> bool { |
e9174d1e | 1561 | let item_doc = cdata.lookup_item(id); |
1a4d82fc JJ |
1562 | match item_family(item_doc) { |
1563 | Type => true, | |
1564 | _ => false, | |
1565 | } | |
1566 | } | |
1567 | ||
b039eaaf | 1568 | pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool { |
e9174d1e | 1569 | let item_doc = cdata.lookup_item(id); |
62682a34 | 1570 | match fn_constness(item_doc) { |
e9174d1e SL |
1571 | hir::Constness::Const => true, |
1572 | hir::Constness::NotConst => false, | |
62682a34 SL |
1573 | } |
1574 | } | |
1575 | ||
54a0048b | 1576 | pub fn is_extern_item(cdata: Cmd, id: DefIndex, tcx: &TyCtxt) -> bool { |
7453a54e SL |
1577 | let item_doc = match cdata.get_item(id) { |
1578 | Some(doc) => doc, | |
1579 | None => return false, | |
1580 | }; | |
1581 | let applicable = match item_family(item_doc) { | |
92a42be0 | 1582 | ImmStatic | MutStatic => true, |
7453a54e SL |
1583 | Fn => { |
1584 | let ty::TypeScheme { generics, ty } = get_type(cdata, id, tcx); | |
1585 | let no_generics = generics.types.is_empty(); | |
1586 | match ty.sty { | |
54a0048b SL |
1587 | ty::TyFnDef(_, _, fn_ty) | ty::TyFnPtr(fn_ty) |
1588 | if fn_ty.abi != Abi::Rust => return no_generics, | |
7453a54e SL |
1589 | _ => no_generics, |
1590 | } | |
1591 | }, | |
92a42be0 | 1592 | _ => false, |
7453a54e SL |
1593 | }; |
1594 | ||
1595 | if applicable { | |
1596 | attr::contains_extern_indicator(tcx.sess.diagnostic(), | |
1597 | &get_attributes(item_doc)) | |
1598 | } else { | |
1599 | false | |
92a42be0 SL |
1600 | } |
1601 | } | |
1602 | ||
b039eaaf | 1603 | pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool { |
e9174d1e | 1604 | let item_doc = cdata.lookup_item(id); |
62682a34 SL |
1605 | match item_family(item_doc) { |
1606 | Impl => true, | |
1607 | _ => false, | |
1608 | } | |
1609 | } | |
1610 | ||
1a4d82fc | 1611 | fn doc_generics<'tcx>(base_doc: rbml::Doc, |
54a0048b | 1612 | tcx: &TyCtxt<'tcx>, |
1a4d82fc | 1613 | cdata: Cmd, |
c34b1796 | 1614 | tag: usize) |
1a4d82fc JJ |
1615 | -> ty::Generics<'tcx> |
1616 | { | |
1617 | let doc = reader::get_doc(base_doc, tag); | |
1618 | ||
1619 | let mut types = subst::VecPerParamSpace::empty(); | |
62682a34 | 1620 | for p in reader::tagged_docs(doc, tag_type_param_def) { |
e9174d1e SL |
1621 | let bd = |
1622 | TyDecoder::with_doc(tcx, cdata.cnum, p, | |
b039eaaf | 1623 | &mut |did| translate_def_id(cdata, did)) |
e9174d1e | 1624 | .parse_type_param_def(); |
1a4d82fc | 1625 | types.push(bd.space, bd); |
62682a34 | 1626 | } |
1a4d82fc JJ |
1627 | |
1628 | let mut regions = subst::VecPerParamSpace::empty(); | |
62682a34 | 1629 | for rp_doc in reader::tagged_docs(doc, tag_region_param_def) { |
1a4d82fc JJ |
1630 | let ident_str_doc = reader::get_doc(rp_doc, |
1631 | tag_region_param_def_ident); | |
7453a54e | 1632 | let name = item_name(&token::get_ident_interner(), ident_str_doc); |
1a4d82fc JJ |
1633 | let def_id_doc = reader::get_doc(rp_doc, |
1634 | tag_region_param_def_def_id); | |
d9579d0f | 1635 | let def_id = translated_def_id(cdata, def_id_doc); |
1a4d82fc JJ |
1636 | |
1637 | let doc = reader::get_doc(rp_doc, tag_region_param_def_space); | |
c34b1796 | 1638 | let space = subst::ParamSpace::from_uint(reader::doc_as_u64(doc) as usize); |
1a4d82fc JJ |
1639 | |
1640 | let doc = reader::get_doc(rp_doc, tag_region_param_def_index); | |
1641 | let index = reader::doc_as_u64(doc) as u32; | |
1642 | ||
62682a34 | 1643 | let bounds = reader::tagged_docs(rp_doc, tag_items_data_region).map(|p| { |
e9174d1e | 1644 | TyDecoder::with_doc(tcx, cdata.cnum, p, |
b039eaaf | 1645 | &mut |did| translate_def_id(cdata, did)) |
e9174d1e | 1646 | .parse_region() |
62682a34 | 1647 | }).collect(); |
1a4d82fc JJ |
1648 | |
1649 | regions.push(space, ty::RegionParameterDef { name: name, | |
1650 | def_id: def_id, | |
1651 | space: space, | |
1652 | index: index, | |
1653 | bounds: bounds }); | |
62682a34 | 1654 | } |
1a4d82fc | 1655 | |
85aaf69f SL |
1656 | ty::Generics { types: types, regions: regions } |
1657 | } | |
1658 | ||
b039eaaf SL |
1659 | fn doc_predicate<'tcx>(cdata: Cmd, |
1660 | doc: rbml::Doc, | |
54a0048b | 1661 | tcx: &TyCtxt<'tcx>) |
b039eaaf SL |
1662 | -> ty::Predicate<'tcx> |
1663 | { | |
1664 | let predicate_pos = cdata.xref_index.lookup( | |
1665 | cdata.data(), reader::doc_as_u32(doc)).unwrap() as usize; | |
1666 | TyDecoder::new( | |
1667 | cdata.data(), cdata.cnum, predicate_pos, tcx, | |
1668 | &mut |did| translate_def_id(cdata, did) | |
1669 | ).parse_predicate() | |
1670 | } | |
1671 | ||
85aaf69f | 1672 | fn doc_predicates<'tcx>(base_doc: rbml::Doc, |
54a0048b | 1673 | tcx: &TyCtxt<'tcx>, |
85aaf69f | 1674 | cdata: Cmd, |
c34b1796 | 1675 | tag: usize) |
85aaf69f SL |
1676 | -> ty::GenericPredicates<'tcx> |
1677 | { | |
1678 | let doc = reader::get_doc(base_doc, tag); | |
1679 | ||
1a4d82fc | 1680 | let mut predicates = subst::VecPerParamSpace::empty(); |
b039eaaf SL |
1681 | for predicate_doc in reader::tagged_docs(doc, tag_type_predicate) { |
1682 | predicates.push(subst::TypeSpace, | |
1683 | doc_predicate(cdata, predicate_doc, tcx)); | |
1684 | } | |
1685 | for predicate_doc in reader::tagged_docs(doc, tag_self_predicate) { | |
1686 | predicates.push(subst::SelfSpace, | |
1687 | doc_predicate(cdata, predicate_doc, tcx)); | |
1688 | } | |
1689 | for predicate_doc in reader::tagged_docs(doc, tag_fn_predicate) { | |
1690 | predicates.push(subst::FnSpace, | |
1691 | doc_predicate(cdata, predicate_doc, tcx)); | |
62682a34 | 1692 | } |
1a4d82fc | 1693 | |
85aaf69f | 1694 | ty::GenericPredicates { predicates: predicates } |
1a4d82fc JJ |
1695 | } |
1696 | ||
b039eaaf | 1697 | pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool { |
e9174d1e | 1698 | let trait_doc = cdata.lookup_item(trait_id); |
c34b1796 AL |
1699 | assert!(item_family(trait_doc) == Family::Trait); |
1700 | let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait); | |
1701 | reader::doc_as_u8(defaulted_doc) != 0 | |
1702 | } | |
1703 | ||
b039eaaf | 1704 | pub fn is_default_impl(cdata: Cmd, impl_id: DefIndex) -> bool { |
e9174d1e | 1705 | let impl_doc = cdata.lookup_item(impl_id); |
c34b1796 AL |
1706 | item_family(impl_doc) == Family::DefaultImpl |
1707 | } | |
1708 | ||
1709 | pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> { | |
1710 | let crate_doc = rbml::Doc::new(metadata); | |
1711 | let cm_doc = reader::get_doc(crate_doc, tag_codemap); | |
1712 | ||
62682a34 | 1713 | reader::tagged_docs(cm_doc, tag_codemap_filemap).map(|filemap_doc| { |
c34b1796 | 1714 | let mut decoder = reader::Decoder::new(filemap_doc); |
9cc50fc6 SL |
1715 | decoder.read_opaque(|opaque_decoder, _| { |
1716 | Decodable::decode(opaque_decoder) | |
1717 | }).unwrap() | |
62682a34 | 1718 | }).collect() |
c34b1796 | 1719 | } |
e9174d1e | 1720 | |
b039eaaf SL |
1721 | pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind { |
1722 | let closure_doc = cdata.lookup_item(closure_id); | |
1723 | let closure_kind_doc = reader::get_doc(closure_doc, tag_items_closure_kind); | |
1724 | let mut decoder = reader::Decoder::new(closure_kind_doc); | |
1725 | ty::ClosureKind::decode(&mut decoder).unwrap() | |
1726 | } | |
1727 | ||
54a0048b | 1728 | pub fn closure_ty<'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: &TyCtxt<'tcx>) |
b039eaaf SL |
1729 | -> ty::ClosureTy<'tcx> { |
1730 | let closure_doc = cdata.lookup_item(closure_id); | |
1731 | let closure_ty_doc = reader::get_doc(closure_doc, tag_items_closure_ty); | |
1732 | TyDecoder::with_doc(tcx, cdata.cnum, closure_ty_doc, &mut |did| translate_def_id(cdata, did)) | |
1733 | .parse_closure_ty() | |
1734 | } | |
1735 | ||
54a0048b SL |
1736 | pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey { |
1737 | debug!("def_key: id={:?}", id); | |
1738 | let item_doc = cdata.lookup_item(id); | |
b039eaaf SL |
1739 | match reader::maybe_get_doc(item_doc, tag_def_key) { |
1740 | Some(def_key_doc) => { | |
1741 | let mut decoder = reader::Decoder::new(def_key_doc); | |
1742 | hir_map::DefKey::decode(&mut decoder).unwrap() | |
1743 | } | |
1744 | None => { | |
54a0048b | 1745 | bug!("failed to find block with tag {:?} for item with family {:?}", |
b039eaaf SL |
1746 | tag_def_key, |
1747 | item_family(item_doc)) | |
1748 | } | |
1749 | } | |
1750 | } | |
1751 | ||
1752 | pub fn def_path(cdata: Cmd, id: DefIndex) -> hir_map::DefPath { | |
1753 | debug!("def_path(id={:?})", id); | |
54a0048b | 1754 | hir_map::DefPath::make(cdata.cnum, id, |parent| def_key(cdata, parent)) |
b039eaaf | 1755 | } |