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