]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/creader.rs
Auto merge of #43651 - petrochenkov:foreign-life, r=eddyb
[rust.git] / src / librustc_metadata / creader.rs
1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
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
11 //! Validates all used crates and extern libraries and loads their metadata
12
13 use cstore::{self, CStore, CrateSource, MetadataBlob};
14 use locator::{self, CratePaths};
15 use schema::{CrateRoot, Tracked};
16
17 use rustc::hir::def_id::{CrateNum, DefIndex};
18 use rustc::hir::svh::Svh;
19 use rustc::middle::allocator::AllocatorKind;
20 use rustc::middle::cstore::DepKind;
21 use rustc::session::Session;
22 use rustc::session::config::{Sanitizer, self};
23 use rustc_back::PanicStrategy;
24 use rustc::session::search_paths::PathKind;
25 use rustc::middle;
26 use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
27 use rustc::util::common::record_time;
28 use rustc::util::nodemap::FxHashSet;
29 use rustc::middle::cstore::NativeLibrary;
30 use rustc::hir::map::Definitions;
31
32 use std::cell::{RefCell, Cell};
33 use std::ops::Deref;
34 use std::path::PathBuf;
35 use std::rc::Rc;
36 use std::{cmp, fs};
37
38 use syntax::ast;
39 use syntax::abi::Abi;
40 use syntax::attr;
41 use syntax::ext::base::SyntaxExtension;
42 use syntax::feature_gate::{self, GateIssue};
43 use syntax::symbol::Symbol;
44 use syntax::visit;
45 use syntax_pos::{Span, DUMMY_SP};
46 use log;
47
48 pub struct Library {
49     pub dylib: Option<(PathBuf, PathKind)>,
50     pub rlib: Option<(PathBuf, PathKind)>,
51     pub rmeta: Option<(PathBuf, PathKind)>,
52     pub metadata: MetadataBlob,
53 }
54
55 pub struct CrateLoader<'a> {
56     pub sess: &'a Session,
57     cstore: &'a CStore,
58     next_crate_num: CrateNum,
59     local_crate_name: Symbol,
60 }
61
62 fn dump_crates(cstore: &CStore) {
63     info!("resolved crates:");
64     cstore.iter_crate_data(|_, data| {
65         info!("  name: {}", data.name());
66         info!("  cnum: {}", data.cnum);
67         info!("  hash: {}", data.hash());
68         info!("  reqd: {:?}", data.dep_kind.get());
69         let CrateSource { dylib, rlib, rmeta } = data.source.clone();
70         dylib.map(|dl| info!("  dylib: {}", dl.0.display()));
71         rlib.map(|rl|  info!("   rlib: {}", rl.0.display()));
72         rmeta.map(|rl| info!("   rmeta: {}", rl.0.display()));
73     });
74 }
75
76 #[derive(Debug)]
77 struct ExternCrateInfo {
78     ident: Symbol,
79     name: Symbol,
80     id: ast::NodeId,
81     dep_kind: DepKind,
82 }
83
84 fn register_native_lib(sess: &Session,
85                        cstore: &CStore,
86                        span: Option<Span>,
87                        lib: NativeLibrary) {
88     if lib.name.as_str().is_empty() {
89         match span {
90             Some(span) => {
91                 struct_span_err!(sess, span, E0454,
92                                  "#[link(name = \"\")] given with empty name")
93                     .span_label(span, "empty name given")
94                     .emit();
95             }
96             None => {
97                 sess.err("empty library name given via `-l`");
98             }
99         }
100         return
101     }
102     let is_osx = sess.target.target.options.is_like_osx;
103     if lib.kind == cstore::NativeFramework && !is_osx {
104         let msg = "native frameworks are only available on macOS targets";
105         match span {
106             Some(span) => span_err!(sess, span, E0455, "{}", msg),
107             None => sess.err(msg),
108         }
109     }
110     if lib.cfg.is_some() && !sess.features.borrow().link_cfg {
111         feature_gate::emit_feature_err(&sess.parse_sess,
112                                        "link_cfg",
113                                        span.unwrap(),
114                                        GateIssue::Language,
115                                        "is feature gated");
116     }
117     if lib.kind == cstore::NativeStaticNobundle && !sess.features.borrow().static_nobundle {
118         feature_gate::emit_feature_err(&sess.parse_sess,
119                                        "static_nobundle",
120                                        span.unwrap(),
121                                        GateIssue::Language,
122                                        "kind=\"static-nobundle\" is feature gated");
123     }
124     cstore.add_used_library(lib);
125 }
126
127 fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
128     match lib.cfg {
129         Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None),
130         None => true,
131     }
132 }
133
134 // Extra info about a crate loaded for plugins or exported macros.
135 struct ExtensionCrate {
136     metadata: PMDSource,
137     dylib: Option<PathBuf>,
138     target_only: bool,
139 }
140
141 enum PMDSource {
142     Registered(Rc<cstore::CrateMetadata>),
143     Owned(Library),
144 }
145
146 impl Deref for PMDSource {
147     type Target = MetadataBlob;
148
149     fn deref(&self) -> &MetadataBlob {
150         match *self {
151             PMDSource::Registered(ref cmd) => &cmd.blob,
152             PMDSource::Owned(ref lib) => &lib.metadata
153         }
154     }
155 }
156
157 enum LoadResult {
158     Previous(CrateNum),
159     Loaded(Library),
160 }
161
162 impl<'a> CrateLoader<'a> {
163     pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self {
164         CrateLoader {
165             sess: sess,
166             cstore: cstore,
167             next_crate_num: cstore.next_crate_num(),
168             local_crate_name: Symbol::intern(local_crate_name),
169         }
170     }
171
172     fn extract_crate_info(&self, i: &ast::Item) -> Option<ExternCrateInfo> {
173         match i.node {
174             ast::ItemKind::ExternCrate(ref path_opt) => {
175                 debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
176                        i.ident, path_opt);
177                 let name = match *path_opt {
178                     Some(name) => {
179                         validate_crate_name(Some(self.sess), &name.as_str(),
180                                             Some(i.span));
181                         name
182                     }
183                     None => i.ident.name,
184                 };
185                 Some(ExternCrateInfo {
186                     ident: i.ident.name,
187                     name: name,
188                     id: i.id,
189                     dep_kind: if attr::contains_name(&i.attrs, "no_link") {
190                         DepKind::UnexportedMacrosOnly
191                     } else {
192                         DepKind::Explicit
193                     },
194                 })
195             }
196             _ => None
197         }
198     }
199
200     fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind)
201                       -> Option<CrateNum> {
202         let mut ret = None;
203         self.cstore.iter_crate_data(|cnum, data| {
204             if data.name != name { return }
205
206             match hash {
207                 Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
208                 Some(..) => return,
209                 None => {}
210             }
211
212             // When the hash is None we're dealing with a top-level dependency
213             // in which case we may have a specification on the command line for
214             // this library. Even though an upstream library may have loaded
215             // something of the same name, we have to make sure it was loaded
216             // from the exact same location as well.
217             //
218             // We're also sure to compare *paths*, not actual byte slices. The
219             // `source` stores paths which are normalized which may be different
220             // from the strings on the command line.
221             let source = self.cstore.used_crate_source(cnum);
222             if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) {
223                 let found = locs.iter().any(|l| {
224                     let l = fs::canonicalize(l).ok();
225                     source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
226                     source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
227                 });
228                 if found {
229                     ret = Some(cnum);
230                 }
231                 return
232             }
233
234             // Alright, so we've gotten this far which means that `data` has the
235             // right name, we don't have a hash, and we don't have a --extern
236             // pointing for ourselves. We're still not quite yet done because we
237             // have to make sure that this crate was found in the crate lookup
238             // path (this is a top-level dependency) as we don't want to
239             // implicitly load anything inside the dependency lookup path.
240             let prev_kind = source.dylib.as_ref().or(source.rlib.as_ref())
241                                   .or(source.rmeta.as_ref())
242                                   .expect("No sources for crate").1;
243             if ret.is_none() && (prev_kind == kind || prev_kind == PathKind::All) {
244                 ret = Some(cnum);
245             }
246         });
247         return ret;
248     }
249
250     fn verify_no_symbol_conflicts(&self,
251                                   span: Span,
252                                   root: &CrateRoot) {
253         // Check for (potential) conflicts with the local crate
254         if self.local_crate_name == root.name &&
255            self.sess.local_crate_disambiguator() == root.disambiguator {
256             span_fatal!(self.sess, span, E0519,
257                         "the current crate is indistinguishable from one of its \
258                          dependencies: it has the same crate-name `{}` and was \
259                          compiled with the same `-C metadata` arguments. This \
260                          will result in symbol conflicts between the two.",
261                         root.name)
262         }
263
264         // Check for conflicts with any crate loaded so far
265         self.cstore.iter_crate_data(|_, other| {
266             if other.name() == root.name && // same crate-name
267                other.disambiguator() == root.disambiguator &&  // same crate-disambiguator
268                other.hash() != root.hash { // but different SVH
269                 span_fatal!(self.sess, span, E0523,
270                         "found two different crates with name `{}` that are \
271                          not distinguished by differing `-C metadata`. This \
272                          will result in symbol conflicts between the two.",
273                         root.name)
274             }
275         });
276     }
277
278     fn register_crate(&mut self,
279                       root: &Option<CratePaths>,
280                       ident: Symbol,
281                       name: Symbol,
282                       span: Span,
283                       lib: Library,
284                       dep_kind: DepKind)
285                       -> (CrateNum, Rc<cstore::CrateMetadata>) {
286         info!("register crate `extern crate {} as {}`", name, ident);
287         let crate_root = lib.metadata.get_root();
288         self.verify_no_symbol_conflicts(span, &crate_root);
289
290         // Claim this crate number and cache it
291         let cnum = self.next_crate_num;
292         self.next_crate_num = CrateNum::from_u32(cnum.as_u32() + 1);
293
294         // Stash paths for top-most crate locally if necessary.
295         let crate_paths = if root.is_none() {
296             Some(CratePaths {
297                 ident: ident.to_string(),
298                 dylib: lib.dylib.clone().map(|p| p.0),
299                 rlib:  lib.rlib.clone().map(|p| p.0),
300                 rmeta: lib.rmeta.clone().map(|p| p.0),
301             })
302         } else {
303             None
304         };
305         // Maintain a reference to the top most crate.
306         let root = if root.is_some() { root } else { &crate_paths };
307
308         let Library { dylib, rlib, rmeta, metadata } = lib;
309
310         let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
311
312         let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
313             crate_root.def_path_table.decode(&metadata)
314         });
315
316         let exported_symbols = crate_root.exported_symbols
317                                          .map(|x| x.decode(&metadata).collect());
318
319         let trait_impls = crate_root
320             .impls
321             .map(|impls| {
322                 impls.decode(&metadata)
323                      .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
324                      .collect()
325             });
326
327         let mut cmeta = cstore::CrateMetadata {
328             name: name,
329             extern_crate: Cell::new(None),
330             def_path_table: Rc::new(def_path_table),
331             exported_symbols: exported_symbols,
332             trait_impls: trait_impls,
333             proc_macros: crate_root.macro_derive_registrar.map(|_| {
334                 self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
335             }),
336             root: crate_root,
337             blob: metadata,
338             cnum_map: RefCell::new(cnum_map),
339             cnum: cnum,
340             codemap_import_info: RefCell::new(vec![]),
341             attribute_cache: RefCell::new([Vec::new(), Vec::new()]),
342             dep_kind: Cell::new(dep_kind),
343             source: cstore::CrateSource {
344                 dylib: dylib,
345                 rlib: rlib,
346                 rmeta: rmeta,
347             },
348             // Initialize this with an empty set. The field is populated below
349             // after we were able to deserialize its contents.
350             dllimport_foreign_items: Tracked::new(FxHashSet()),
351         };
352
353         let dllimports: Tracked<FxHashSet<_>> = cmeta
354             .root
355             .native_libraries
356             .map(|native_libraries| {
357                 let native_libraries: Vec<_> = native_libraries.decode(&cmeta)
358                                                                .collect();
359                 native_libraries
360                     .iter()
361                     .filter(|lib| relevant_lib(self.sess, lib) &&
362                                   lib.kind == cstore::NativeLibraryKind::NativeUnknown)
363                     .flat_map(|lib| lib.foreign_items.iter())
364                     .map(|id| *id)
365                     .collect()
366             });
367
368         cmeta.dllimport_foreign_items = dllimports;
369
370         let cmeta = Rc::new(cmeta);
371         self.cstore.set_crate_data(cnum, cmeta.clone());
372         (cnum, cmeta)
373     }
374
375     fn resolve_crate(&mut self,
376                      root: &Option<CratePaths>,
377                      ident: Symbol,
378                      name: Symbol,
379                      hash: Option<&Svh>,
380                      span: Span,
381                      path_kind: PathKind,
382                      mut dep_kind: DepKind)
383                      -> (CrateNum, Rc<cstore::CrateMetadata>) {
384         info!("resolving crate `extern crate {} as {}`", name, ident);
385         let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
386             LoadResult::Previous(cnum)
387         } else {
388             info!("falling back to a load");
389             let mut locate_ctxt = locator::Context {
390                 sess: self.sess,
391                 span: span,
392                 ident: ident,
393                 crate_name: name,
394                 hash: hash.map(|a| &*a),
395                 filesearch: self.sess.target_filesearch(path_kind),
396                 target: &self.sess.target.target,
397                 triple: &self.sess.opts.target_triple,
398                 root: root,
399                 rejected_via_hash: vec![],
400                 rejected_via_triple: vec![],
401                 rejected_via_kind: vec![],
402                 rejected_via_version: vec![],
403                 rejected_via_filename: vec![],
404                 should_match_name: true,
405                 is_proc_macro: Some(false),
406                 metadata_loader: &*self.cstore.metadata_loader,
407             };
408
409             self.load(&mut locate_ctxt).or_else(|| {
410                 dep_kind = DepKind::UnexportedMacrosOnly;
411
412                 let mut proc_macro_locator = locator::Context {
413                     target: &self.sess.host,
414                     triple: config::host_triple(),
415                     filesearch: self.sess.host_filesearch(path_kind),
416                     rejected_via_hash: vec![],
417                     rejected_via_triple: vec![],
418                     rejected_via_kind: vec![],
419                     rejected_via_version: vec![],
420                     rejected_via_filename: vec![],
421                     is_proc_macro: Some(true),
422                     ..locate_ctxt
423                 };
424
425                 self.load(&mut proc_macro_locator)
426             }).unwrap_or_else(|| locate_ctxt.report_errs())
427         };
428
429         match result {
430             LoadResult::Previous(cnum) => {
431                 let data = self.cstore.get_crate_data(cnum);
432                 if data.root.macro_derive_registrar.is_some() {
433                     dep_kind = DepKind::UnexportedMacrosOnly;
434                 }
435                 data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind));
436                 (cnum, data)
437             }
438             LoadResult::Loaded(library) => {
439                 self.register_crate(root, ident, name, span, library, dep_kind)
440             }
441         }
442     }
443
444     fn load(&mut self, locate_ctxt: &mut locator::Context) -> Option<LoadResult> {
445         let library = match locate_ctxt.maybe_load_library_crate() {
446             Some(lib) => lib,
447             None => return None,
448         };
449
450         // In the case that we're loading a crate, but not matching
451         // against a hash, we could load a crate which has the same hash
452         // as an already loaded crate. If this is the case prevent
453         // duplicates by just using the first crate.
454         //
455         // Note that we only do this for target triple crates, though, as we
456         // don't want to match a host crate against an equivalent target one
457         // already loaded.
458         let root = library.metadata.get_root();
459         if locate_ctxt.triple == self.sess.opts.target_triple {
460             let mut result = LoadResult::Loaded(library);
461             self.cstore.iter_crate_data(|cnum, data| {
462                 if data.name() == root.name && root.hash == data.hash() {
463                     assert!(locate_ctxt.hash.is_none());
464                     info!("load success, going to previous cnum: {}", cnum);
465                     result = LoadResult::Previous(cnum);
466                 }
467             });
468             Some(result)
469         } else {
470             Some(LoadResult::Loaded(library))
471         }
472     }
473
474     fn update_extern_crate(&mut self,
475                            cnum: CrateNum,
476                            mut extern_crate: ExternCrate,
477                            visited: &mut FxHashSet<(CrateNum, bool)>)
478     {
479         if !visited.insert((cnum, extern_crate.direct)) { return }
480
481         let cmeta = self.cstore.get_crate_data(cnum);
482         let old_extern_crate = cmeta.extern_crate.get();
483
484         // Prefer:
485         // - something over nothing (tuple.0);
486         // - direct extern crate to indirect (tuple.1);
487         // - shorter paths to longer (tuple.2).
488         let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
489         let old_rank = match old_extern_crate {
490             None => (false, false, !0),
491             Some(ref c) => (true, c.direct, !c.path_len),
492         };
493
494         if old_rank >= new_rank {
495             return; // no change needed
496         }
497
498         cmeta.extern_crate.set(Some(extern_crate));
499         // Propagate the extern crate info to dependencies.
500         extern_crate.direct = false;
501         for &dep_cnum in cmeta.cnum_map.borrow().iter() {
502             self.update_extern_crate(dep_cnum, extern_crate, visited);
503         }
504     }
505
506     // Go through the crate metadata and load any crates that it references
507     fn resolve_crate_deps(&mut self,
508                           root: &Option<CratePaths>,
509                           crate_root: &CrateRoot,
510                           metadata: &MetadataBlob,
511                           krate: CrateNum,
512                           span: Span,
513                           dep_kind: DepKind)
514                           -> cstore::CrateNumMap {
515         debug!("resolving deps of external crate");
516         if crate_root.macro_derive_registrar.is_some() {
517             return cstore::CrateNumMap::new();
518         }
519
520         // The map from crate numbers in the crate we're resolving to local crate numbers.
521         // We map 0 and all other holes in the map to our parent crate. The "additional"
522         // self-dependencies should be harmless.
523         ::std::iter::once(krate).chain(crate_root.crate_deps
524                                                  .get_untracked()
525                                                  .decode(metadata)
526                                                  .map(|dep| {
527             debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
528             if dep.kind == DepKind::UnexportedMacrosOnly {
529                 return krate;
530             }
531             let dep_kind = match dep_kind {
532                 DepKind::MacrosOnly => DepKind::MacrosOnly,
533                 _ => dep.kind,
534             };
535             let (local_cnum, ..) = self.resolve_crate(
536                 root, dep.name, dep.name, Some(&dep.hash), span, PathKind::Dependency, dep_kind,
537             );
538             local_cnum
539         })).collect()
540     }
541
542     fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate {
543         info!("read extension crate {} `extern crate {} as {}` dep_kind={:?}",
544               info.id, info.name, info.ident, info.dep_kind);
545         let target_triple = &self.sess.opts.target_triple[..];
546         let is_cross = target_triple != config::host_triple();
547         let mut target_only = false;
548         let mut locate_ctxt = locator::Context {
549             sess: self.sess,
550             span: span,
551             ident: info.ident,
552             crate_name: info.name,
553             hash: None,
554             filesearch: self.sess.host_filesearch(PathKind::Crate),
555             target: &self.sess.host,
556             triple: config::host_triple(),
557             root: &None,
558             rejected_via_hash: vec![],
559             rejected_via_triple: vec![],
560             rejected_via_kind: vec![],
561             rejected_via_version: vec![],
562             rejected_via_filename: vec![],
563             should_match_name: true,
564             is_proc_macro: None,
565             metadata_loader: &*self.cstore.metadata_loader,
566         };
567         let library = self.load(&mut locate_ctxt).or_else(|| {
568             if !is_cross {
569                 return None
570             }
571             // Try loading from target crates. This will abort later if we
572             // try to load a plugin registrar function,
573             target_only = true;
574
575             locate_ctxt.target = &self.sess.target.target;
576             locate_ctxt.triple = target_triple;
577             locate_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate);
578
579             self.load(&mut locate_ctxt)
580         });
581         let library = match library {
582             Some(l) => l,
583             None => locate_ctxt.report_errs(),
584         };
585
586         let (dylib, metadata) = match library {
587             LoadResult::Previous(cnum) => {
588                 let data = self.cstore.get_crate_data(cnum);
589                 (data.source.dylib.clone(), PMDSource::Registered(data))
590             }
591             LoadResult::Loaded(library) => {
592                 let dylib = library.dylib.clone();
593                 let metadata = PMDSource::Owned(library);
594                 (dylib, metadata)
595             }
596         };
597
598         ExtensionCrate {
599             metadata: metadata,
600             dylib: dylib.map(|p| p.0),
601             target_only: target_only,
602         }
603     }
604
605     /// Load custom derive macros.
606     ///
607     /// Note that this is intentionally similar to how we load plugins today,
608     /// but also intentionally separate. Plugins are likely always going to be
609     /// implemented as dynamic libraries, but we have a possible future where
610     /// custom derive (and other macro-1.1 style features) are implemented via
611     /// executables and custom IPC.
612     fn load_derive_macros(&mut self, root: &CrateRoot, dylib: Option<PathBuf>, span: Span)
613                           -> Vec<(ast::Name, Rc<SyntaxExtension>)> {
614         use std::{env, mem};
615         use proc_macro::TokenStream;
616         use proc_macro::__internal::Registry;
617         use rustc_back::dynamic_lib::DynamicLibrary;
618         use syntax_ext::deriving::custom::ProcMacroDerive;
619         use syntax_ext::proc_macro_impl::{AttrProcMacro, BangProcMacro};
620
621         let path = match dylib {
622             Some(dylib) => dylib,
623             None => span_bug!(span, "proc-macro crate not dylib"),
624         };
625         // Make sure the path contains a / or the linker will search for it.
626         let path = env::current_dir().unwrap().join(path);
627         let lib = match DynamicLibrary::open(Some(&path)) {
628             Ok(lib) => lib,
629             Err(err) => self.sess.span_fatal(span, &err),
630         };
631
632         let sym = self.sess.generate_derive_registrar_symbol(root.disambiguator,
633                                                              root.macro_derive_registrar.unwrap());
634         let registrar = unsafe {
635             let sym = match lib.symbol(&sym) {
636                 Ok(f) => f,
637                 Err(err) => self.sess.span_fatal(span, &err),
638             };
639             mem::transmute::<*mut u8, fn(&mut Registry)>(sym)
640         };
641
642         struct MyRegistrar(Vec<(ast::Name, Rc<SyntaxExtension>)>);
643
644         impl Registry for MyRegistrar {
645             fn register_custom_derive(&mut self,
646                                       trait_name: &str,
647                                       expand: fn(TokenStream) -> TokenStream,
648                                       attributes: &[&'static str]) {
649                 let attrs = attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
650                 let derive = ProcMacroDerive::new(expand, attrs.clone());
651                 let derive = SyntaxExtension::ProcMacroDerive(Box::new(derive), attrs);
652                 self.0.push((Symbol::intern(trait_name), Rc::new(derive)));
653             }
654
655             fn register_attr_proc_macro(&mut self,
656                                         name: &str,
657                                         expand: fn(TokenStream, TokenStream) -> TokenStream) {
658                 let expand = SyntaxExtension::AttrProcMacro(
659                     Box::new(AttrProcMacro { inner: expand })
660                 );
661                 self.0.push((Symbol::intern(name), Rc::new(expand)));
662             }
663
664             fn register_bang_proc_macro(&mut self,
665                                         name: &str,
666                                         expand: fn(TokenStream) -> TokenStream) {
667                 let expand = SyntaxExtension::ProcMacro(
668                     Box::new(BangProcMacro { inner: expand })
669                 );
670                 self.0.push((Symbol::intern(name), Rc::new(expand)));
671             }
672         }
673
674         let mut my_registrar = MyRegistrar(Vec::new());
675         registrar(&mut my_registrar);
676
677         // Intentionally leak the dynamic library. We can't ever unload it
678         // since the library can make things that will live arbitrarily long.
679         mem::forget(lib);
680         my_registrar.0
681     }
682
683     /// Look for a plugin registrar. Returns library path, crate
684     /// SVH and DefIndex of the registrar function.
685     pub fn find_plugin_registrar(&mut self,
686                                  span: Span,
687                                  name: &str)
688                                  -> Option<(PathBuf, Symbol, DefIndex)> {
689         let ekrate = self.read_extension_crate(span, &ExternCrateInfo {
690              name: Symbol::intern(name),
691              ident: Symbol::intern(name),
692              id: ast::DUMMY_NODE_ID,
693              dep_kind: DepKind::UnexportedMacrosOnly,
694         });
695
696         if ekrate.target_only {
697             // Need to abort before syntax expansion.
698             let message = format!("plugin `{}` is not available for triple `{}` \
699                                    (only found {})",
700                                   name,
701                                   config::host_triple(),
702                                   self.sess.opts.target_triple);
703             span_fatal!(self.sess, span, E0456, "{}", &message);
704         }
705
706         let root = ekrate.metadata.get_root();
707         match (ekrate.dylib.as_ref(), root.plugin_registrar_fn) {
708             (Some(dylib), Some(reg)) => {
709                 Some((dylib.to_path_buf(), root.disambiguator, reg))
710             }
711             (None, Some(_)) => {
712                 span_err!(self.sess, span, E0457,
713                           "plugin `{}` only found in rlib format, but must be available \
714                            in dylib format",
715                           name);
716                 // No need to abort because the loading code will just ignore this
717                 // empty dylib.
718                 None
719             }
720             _ => None,
721         }
722     }
723
724     fn get_foreign_items_of_kind(&self, kind: cstore::NativeLibraryKind) -> Vec<DefIndex> {
725         let mut items = vec![];
726         let libs = self.cstore.get_used_libraries();
727         for lib in libs.borrow().iter() {
728             if relevant_lib(self.sess, lib) && lib.kind == kind {
729                 items.extend(&lib.foreign_items);
730             }
731         }
732         items
733     }
734
735     fn register_statically_included_foreign_items(&mut self) {
736         for id in self.get_foreign_items_of_kind(cstore::NativeStatic) {
737             self.cstore.add_statically_included_foreign_item(id);
738         }
739         for id in self.get_foreign_items_of_kind(cstore::NativeStaticNobundle) {
740             self.cstore.add_statically_included_foreign_item(id);
741         }
742     }
743
744     fn register_dllimport_foreign_items(&mut self) {
745         let mut dllimports = self.cstore.dllimport_foreign_items.borrow_mut();
746         for id in self.get_foreign_items_of_kind(cstore::NativeUnknown) {
747             dllimports.insert(id);
748         }
749     }
750
751     fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
752         // If we're only compiling an rlib, then there's no need to select a
753         // panic runtime, so we just skip this section entirely.
754         let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| {
755             *ct != config::CrateTypeRlib
756         });
757         if !any_non_rlib {
758             info!("panic runtime injection skipped, only generating rlib");
759             return
760         }
761
762         // If we need a panic runtime, we try to find an existing one here. At
763         // the same time we perform some general validation of the DAG we've got
764         // going such as ensuring everything has a compatible panic strategy.
765         //
766         // The logic for finding the panic runtime here is pretty much the same
767         // as the allocator case with the only addition that the panic strategy
768         // compilation mode also comes into play.
769         let desired_strategy = self.sess.panic_strategy();
770         let mut runtime_found = false;
771         let mut needs_panic_runtime = attr::contains_name(&krate.attrs,
772                                                           "needs_panic_runtime");
773
774         let dep_graph = &self.sess.dep_graph;
775
776         self.cstore.iter_crate_data(|cnum, data| {
777             needs_panic_runtime = needs_panic_runtime ||
778                                   data.needs_panic_runtime(dep_graph);
779             if data.is_panic_runtime(dep_graph) {
780                 // Inject a dependency from all #![needs_panic_runtime] to this
781                 // #![panic_runtime] crate.
782                 self.inject_dependency_if(cnum, "a panic runtime",
783                                           &|data| data.needs_panic_runtime(dep_graph));
784                 runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit;
785             }
786         });
787
788         // If an explicitly linked and matching panic runtime was found, or if
789         // we just don't need one at all, then we're done here and there's
790         // nothing else to do.
791         if !needs_panic_runtime || runtime_found {
792             return
793         }
794
795         // By this point we know that we (a) need a panic runtime and (b) no
796         // panic runtime was explicitly linked. Here we just load an appropriate
797         // default runtime for our panic strategy and then inject the
798         // dependencies.
799         //
800         // We may resolve to an already loaded crate (as the crate may not have
801         // been explicitly linked prior to this) and we may re-inject
802         // dependencies again, but both of those situations are fine.
803         //
804         // Also note that we have yet to perform validation of the crate graph
805         // in terms of everyone has a compatible panic runtime format, that's
806         // performed later as part of the `dependency_format` module.
807         let name = match desired_strategy {
808             PanicStrategy::Unwind => Symbol::intern("panic_unwind"),
809             PanicStrategy::Abort => Symbol::intern("panic_abort"),
810         };
811         info!("panic runtime not found -- loading {}", name);
812
813         let dep_kind = DepKind::Implicit;
814         let (cnum, data) =
815             self.resolve_crate(&None, name, name, None, DUMMY_SP, PathKind::Crate, dep_kind);
816
817         // Sanity check the loaded crate to ensure it is indeed a panic runtime
818         // and the panic strategy is indeed what we thought it was.
819         if !data.is_panic_runtime(dep_graph) {
820             self.sess.err(&format!("the crate `{}` is not a panic runtime",
821                                    name));
822         }
823         if data.panic_strategy(dep_graph) != desired_strategy {
824             self.sess.err(&format!("the crate `{}` does not have the panic \
825                                     strategy `{}`",
826                                    name, desired_strategy.desc()));
827         }
828
829         self.sess.injected_panic_runtime.set(Some(cnum));
830         self.inject_dependency_if(cnum, "a panic runtime",
831                                   &|data| data.needs_panic_runtime(dep_graph));
832     }
833
834     fn inject_sanitizer_runtime(&mut self) {
835         if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer {
836             // Sanitizers can only be used on some tested platforms with
837             // executables linked to `std`
838             const ASAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu",
839                                                       "x86_64-apple-darwin"];
840             const TSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu",
841                                                       "x86_64-apple-darwin"];
842             const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
843             const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
844
845             let supported_targets = match *sanitizer {
846                 Sanitizer::Address => ASAN_SUPPORTED_TARGETS,
847                 Sanitizer::Thread => TSAN_SUPPORTED_TARGETS,
848                 Sanitizer::Leak => LSAN_SUPPORTED_TARGETS,
849                 Sanitizer::Memory => MSAN_SUPPORTED_TARGETS,
850             };
851             if !supported_targets.contains(&&*self.sess.target.target.llvm_target) {
852                 self.sess.err(&format!("{:?}Sanitizer only works with the `{}` target",
853                     sanitizer,
854                     supported_targets.join("` or `")
855                 ));
856                 return
857             }
858
859             // firstyear 2017 - during testing I was unable to access an OSX machine
860             // to make this work on different crate types. As a result, today I have
861             // only been able to test and support linux as a target.
862             if self.sess.target.target.llvm_target == "x86_64-unknown-linux-gnu" {
863                 if !self.sess.crate_types.borrow().iter().all(|ct| {
864                     match *ct {
865                         // Link the runtime
866                         config::CrateTypeStaticlib |
867                         config::CrateTypeExecutable => true,
868                         // This crate will be compiled with the required
869                         // instrumentation pass
870                         config::CrateTypeRlib |
871                         config::CrateTypeDylib |
872                         config::CrateTypeCdylib =>
873                             false,
874                         _ => {
875                             self.sess.err(&format!("Only executables, staticlibs, \
876                                 cdylibs, dylibs and rlibs can be compiled with \
877                                 `-Z sanitizer`"));
878                             false
879                         }
880                     }
881                 }) {
882                     return
883                 }
884             } else {
885                 if !self.sess.crate_types.borrow().iter().all(|ct| {
886                     match *ct {
887                         // Link the runtime
888                         config::CrateTypeExecutable => true,
889                         // This crate will be compiled with the required
890                         // instrumentation pass
891                         config::CrateTypeRlib => false,
892                         _ => {
893                             self.sess.err(&format!("Only executables and rlibs can be \
894                                                     compiled with `-Z sanitizer`"));
895                             false
896                         }
897                     }
898                 }) {
899                     return
900                 }
901             }
902
903             let mut uses_std = false;
904             self.cstore.iter_crate_data(|_, data| {
905                 if data.name == "std" {
906                     uses_std = true;
907                 }
908             });
909
910             if uses_std {
911                 let name = match *sanitizer {
912                     Sanitizer::Address => "rustc_asan",
913                     Sanitizer::Leak => "rustc_lsan",
914                     Sanitizer::Memory => "rustc_msan",
915                     Sanitizer::Thread => "rustc_tsan",
916                 };
917                 info!("loading sanitizer: {}", name);
918
919                 let symbol = Symbol::intern(name);
920                 let dep_kind = DepKind::Explicit;
921                 let (_, data) =
922                     self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP,
923                                        PathKind::Crate, dep_kind);
924
925                 // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
926                 if !data.is_sanitizer_runtime(&self.sess.dep_graph) {
927                     self.sess.err(&format!("the crate `{}` is not a sanitizer runtime",
928                                            name));
929                 }
930             } else {
931                 self.sess.err(&format!("Must link std to be compiled with `-Z sanitizer`"));
932             }
933         }
934     }
935
936     fn inject_profiler_runtime(&mut self) {
937         if self.sess.opts.debugging_opts.profile {
938             info!("loading profiler");
939
940             let symbol = Symbol::intern("profiler_builtins");
941             let dep_kind = DepKind::Implicit;
942             let (_, data) =
943                 self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP,
944                                    PathKind::Crate, dep_kind);
945
946             // Sanity check the loaded crate to ensure it is indeed a profiler runtime
947             if !data.is_profiler_runtime(&self.sess.dep_graph) {
948                 self.sess.err(&format!("the crate `profiler_builtins` is not \
949                                         a profiler runtime"));
950             }
951         }
952     }
953
954     fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
955         let has_global_allocator = has_global_allocator(krate);
956         if has_global_allocator {
957             self.sess.has_global_allocator.set(true);
958         }
959
960         // Check to see if we actually need an allocator. This desire comes
961         // about through the `#![needs_allocator]` attribute and is typically
962         // written down in liballoc.
963         let mut needs_allocator = attr::contains_name(&krate.attrs,
964                                                       "needs_allocator");
965         let dep_graph = &self.sess.dep_graph;
966         self.cstore.iter_crate_data(|_, data| {
967             needs_allocator = needs_allocator || data.needs_allocator(dep_graph);
968         });
969         if !needs_allocator {
970             return
971         }
972
973         // At this point we've determined that we need an allocator. Let's see
974         // if our compilation session actually needs an allocator based on what
975         // we're emitting.
976         let mut need_lib_alloc = false;
977         let mut need_exe_alloc = false;
978         for ct in self.sess.crate_types.borrow().iter() {
979             match *ct {
980                 config::CrateTypeExecutable => need_exe_alloc = true,
981                 config::CrateTypeDylib |
982                 config::CrateTypeProcMacro |
983                 config::CrateTypeCdylib |
984                 config::CrateTypeStaticlib => need_lib_alloc = true,
985                 config::CrateTypeRlib => {}
986             }
987         }
988         if !need_lib_alloc && !need_exe_alloc {
989             return
990         }
991
992         // Ok, we need an allocator. Not only that but we're actually going to
993         // create an artifact that needs one linked in. Let's go find the one
994         // that we're going to link in.
995         //
996         // First up we check for global allocators. Look at the crate graph here
997         // and see what's a global allocator, including if we ourselves are a
998         // global allocator.
999         let dep_graph = &self.sess.dep_graph;
1000         let mut global_allocator = if has_global_allocator {
1001             Some(None)
1002         } else {
1003             None
1004         };
1005         self.cstore.iter_crate_data(|_, data| {
1006             if !data.has_global_allocator(dep_graph) {
1007                 return
1008             }
1009             match global_allocator {
1010                 Some(Some(other_crate)) => {
1011                     self.sess.err(&format!("the #[global_allocator] in {} \
1012                                             conflicts with this global \
1013                                             allocator in: {}",
1014                                            other_crate,
1015                                            data.name()));
1016                 }
1017                 Some(None) => {
1018                     self.sess.err(&format!("the #[global_allocator] in this \
1019                                             crate conflicts with global \
1020                                             allocator in: {}", data.name()));
1021                 }
1022                 None => global_allocator = Some(Some(data.name())),
1023             }
1024         });
1025         if global_allocator.is_some() {
1026             self.sess.allocator_kind.set(Some(AllocatorKind::Global));
1027             return
1028         }
1029
1030         // Ok we haven't found a global allocator but we still need an
1031         // allocator. At this point we'll either fall back to the "library
1032         // allocator" or the "exe allocator" depending on a few variables. Let's
1033         // figure out which one.
1034         //
1035         // Note that here we favor linking to the "library allocator" as much as
1036         // possible. If we're not creating rustc's version of libstd
1037         // (need_lib_alloc and prefer_dynamic) then we select `None`, and if the
1038         // exe allocation crate doesn't exist for this target then we also
1039         // select `None`.
1040         let exe_allocation_crate =
1041             if need_lib_alloc && !self.sess.opts.cg.prefer_dynamic {
1042                 None
1043             } else {
1044                 self.sess.target.target.options.exe_allocation_crate.as_ref()
1045             };
1046
1047         match exe_allocation_crate {
1048             // We've determined that we're injecting an "exe allocator" which
1049             // means that we're going to load up a whole new crate. An example
1050             // of this is that we're producing a normal binary on Linux which
1051             // means we need to load the `alloc_jemalloc` crate to link as an
1052             // allocator.
1053             Some(krate) => {
1054                 self.sess.allocator_kind.set(Some(AllocatorKind::DefaultExe));
1055                 let name = Symbol::intern(krate);
1056                 let dep_kind = DepKind::Implicit;
1057                 let (cnum, _data) =
1058                     self.resolve_crate(&None,
1059                                        name,
1060                                        name,
1061                                        None,
1062                                        DUMMY_SP,
1063                                        PathKind::Crate, dep_kind);
1064                 self.sess.injected_allocator.set(Some(cnum));
1065             //     self.cstore.iter_crate_data(|_, data| {
1066             //         if !data.needs_allocator(dep_graph) {
1067             //             return
1068             //         }
1069             //         data.cnum_map.borrow_mut().push(cnum);
1070             //     });
1071             }
1072
1073             // We're not actually going to inject an allocator, we're going to
1074             // require that something in our crate graph is the default lib
1075             // allocator. This is typically libstd, so this'll rarely be an
1076             // error.
1077             None => {
1078                 self.sess.allocator_kind.set(Some(AllocatorKind::DefaultLib));
1079                 let mut found_lib_allocator =
1080                     attr::contains_name(&krate.attrs, "default_lib_allocator");
1081                 self.cstore.iter_crate_data(|_, data| {
1082                     if !found_lib_allocator {
1083                         if data.has_default_lib_allocator(dep_graph) {
1084                             found_lib_allocator = true;
1085                         }
1086                     }
1087                 });
1088                 if found_lib_allocator {
1089                     return
1090                 }
1091                 self.sess.err("no #[default_lib_allocator] found but one is \
1092                                required; is libstd not linked?");
1093             }
1094         }
1095
1096         fn has_global_allocator(krate: &ast::Crate) -> bool {
1097             struct Finder(bool);
1098             let mut f = Finder(false);
1099             visit::walk_crate(&mut f, krate);
1100             return f.0;
1101
1102             impl<'ast> visit::Visitor<'ast> for Finder {
1103                 fn visit_item(&mut self, i: &'ast ast::Item) {
1104                     if attr::contains_name(&i.attrs, "global_allocator") {
1105                         self.0 = true;
1106                     }
1107                     visit::walk_item(self, i)
1108                 }
1109             }
1110         }
1111     }
1112
1113
1114     fn inject_dependency_if(&self,
1115                             krate: CrateNum,
1116                             what: &str,
1117                             needs_dep: &Fn(&cstore::CrateMetadata) -> bool) {
1118         // don't perform this validation if the session has errors, as one of
1119         // those errors may indicate a circular dependency which could cause
1120         // this to stack overflow.
1121         if self.sess.has_errors() {
1122             return
1123         }
1124
1125         // Before we inject any dependencies, make sure we don't inject a
1126         // circular dependency by validating that this crate doesn't
1127         // transitively depend on any crates satisfying `needs_dep`.
1128         for dep in self.cstore.crate_dependencies_in_rpo(krate) {
1129             let data = self.cstore.get_crate_data(dep);
1130             if needs_dep(&data) {
1131                 self.sess.err(&format!("the crate `{}` cannot depend \
1132                                         on a crate that needs {}, but \
1133                                         it depends on `{}`",
1134                                        self.cstore.get_crate_data(krate).name(),
1135                                        what,
1136                                        data.name()));
1137             }
1138         }
1139
1140         // All crates satisfying `needs_dep` do not explicitly depend on the
1141         // crate provided for this compile, but in order for this compilation to
1142         // be successfully linked we need to inject a dependency (to order the
1143         // crates on the command line correctly).
1144         self.cstore.iter_crate_data(|cnum, data| {
1145             if !needs_dep(data) {
1146                 return
1147             }
1148
1149             info!("injecting a dep from {} to {}", cnum, krate);
1150             data.cnum_map.borrow_mut().push(krate);
1151         });
1152     }
1153 }
1154
1155 impl<'a> CrateLoader<'a> {
1156     pub fn preprocess(&mut self, krate: &ast::Crate) {
1157         for attr in &krate.attrs {
1158             if attr.path == "link_args" {
1159                 if let Some(linkarg) = attr.value_str() {
1160                     self.cstore.add_used_link_args(&linkarg.as_str());
1161                 }
1162             }
1163         }
1164     }
1165
1166     fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod,
1167                            definitions: &Definitions) {
1168         if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic {
1169             return;
1170         }
1171
1172         // First, add all of the custom #[link_args] attributes
1173         for m in i.attrs.iter().filter(|a| a.check_name("link_args")) {
1174             if let Some(linkarg) = m.value_str() {
1175                 self.cstore.add_used_link_args(&linkarg.as_str());
1176             }
1177         }
1178
1179         // Next, process all of the #[link(..)]-style arguments
1180         for m in i.attrs.iter().filter(|a| a.check_name("link")) {
1181             let items = match m.meta_item_list() {
1182                 Some(item) => item,
1183                 None => continue,
1184             };
1185             let kind = items.iter().find(|k| {
1186                 k.check_name("kind")
1187             }).and_then(|a| a.value_str()).map(Symbol::as_str);
1188             let kind = match kind.as_ref().map(|s| &s[..]) {
1189                 Some("static") => cstore::NativeStatic,
1190                 Some("static-nobundle") => cstore::NativeStaticNobundle,
1191                 Some("dylib") => cstore::NativeUnknown,
1192                 Some("framework") => cstore::NativeFramework,
1193                 Some(k) => {
1194                     struct_span_err!(self.sess, m.span, E0458,
1195                               "unknown kind: `{}`", k)
1196                         .span_label(m.span, "unknown kind").emit();
1197                     cstore::NativeUnknown
1198                 }
1199                 None => cstore::NativeUnknown
1200             };
1201             let n = items.iter().find(|n| {
1202                 n.check_name("name")
1203             }).and_then(|a| a.value_str());
1204             let n = match n {
1205                 Some(n) => n,
1206                 None => {
1207                     struct_span_err!(self.sess, m.span, E0459,
1208                                      "#[link(...)] specified without `name = \"foo\"`")
1209                         .span_label(m.span, "missing `name` argument").emit();
1210                     Symbol::intern("foo")
1211                 }
1212             };
1213             let cfg = items.iter().find(|k| {
1214                 k.check_name("cfg")
1215             }).and_then(|a| a.meta_item_list());
1216             let cfg = cfg.map(|list| {
1217                 list[0].meta_item().unwrap().clone()
1218             });
1219             let foreign_items = fm.items.iter()
1220                 .map(|it| definitions.opt_def_index(it.id).unwrap())
1221                 .collect();
1222             let lib = NativeLibrary {
1223                 name: n,
1224                 kind: kind,
1225                 cfg: cfg,
1226                 foreign_items: foreign_items,
1227             };
1228             register_native_lib(self.sess, self.cstore, Some(m.span), lib);
1229         }
1230     }
1231 }
1232
1233 impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
1234     fn postprocess(&mut self, krate: &ast::Crate) {
1235         // inject the sanitizer runtime before the allocator runtime because all
1236         // sanitizers force the use of the `alloc_system` allocator
1237         self.inject_sanitizer_runtime();
1238         self.inject_profiler_runtime();
1239         self.inject_allocator_crate(krate);
1240         self.inject_panic_runtime(krate);
1241
1242         if log_enabled!(log::LogLevel::Info) {
1243             dump_crates(&self.cstore);
1244         }
1245
1246         // Process libs passed on the command line
1247         // First, check for errors
1248         let mut renames = FxHashSet();
1249         for &(ref name, ref new_name, _) in &self.sess.opts.libs {
1250             if let &Some(ref new_name) = new_name {
1251                 if new_name.is_empty() {
1252                     self.sess.err(
1253                         &format!("an empty renaming target was specified for library `{}`",name));
1254                 } else if !self.cstore.get_used_libraries().borrow().iter()
1255                                                            .any(|lib| lib.name == name as &str) {
1256                     self.sess.err(&format!("renaming of the library `{}` was specified, \
1257                                             however this crate contains no #[link(...)] \
1258                                             attributes referencing this library.", name));
1259                 } else if renames.contains(name) {
1260                     self.sess.err(&format!("multiple renamings were specified for library `{}` .",
1261                                             name));
1262                 } else {
1263                     renames.insert(name);
1264                 }
1265             }
1266         }
1267         // Update kind and, optionally, the name of all native libaries
1268         // (there may be more than one) with the specified name.
1269         for &(ref name, ref new_name, kind) in &self.sess.opts.libs {
1270             let mut found = false;
1271             for lib in self.cstore.get_used_libraries().borrow_mut().iter_mut() {
1272                 if lib.name == name as &str {
1273                     let mut changed = false;
1274                     if let Some(k) = kind {
1275                         lib.kind = k;
1276                         changed = true;
1277                     }
1278                     if let &Some(ref new_name) = new_name {
1279                         lib.name = Symbol::intern(new_name);
1280                         changed = true;
1281                     }
1282                     if !changed {
1283                         self.sess.warn(&format!("redundant linker flag specified for library `{}`",
1284                                                 name));
1285                     }
1286
1287                     found = true;
1288                 }
1289             }
1290             if !found {
1291                 // Add if not found
1292                 let new_name = new_name.as_ref().map(|s| &**s); // &Option<String> -> Option<&str>
1293                 let lib = NativeLibrary {
1294                     name: Symbol::intern(new_name.unwrap_or(name)),
1295                     kind: if let Some(k) = kind { k } else { cstore::NativeUnknown },
1296                     cfg: None,
1297                     foreign_items: Vec::new(),
1298                 };
1299                 register_native_lib(self.sess, self.cstore, None, lib);
1300             }
1301         }
1302         self.register_statically_included_foreign_items();
1303         self.register_dllimport_foreign_items();
1304     }
1305
1306     fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
1307         match item.node {
1308             ast::ItemKind::ForeignMod(ref fm) => {
1309                 self.process_foreign_mod(item, fm, definitions)
1310             },
1311             ast::ItemKind::ExternCrate(_) => {
1312                 let info = self.extract_crate_info(item).unwrap();
1313                 let (cnum, ..) = self.resolve_crate(
1314                     &None, info.ident, info.name, None, item.span, PathKind::Crate, info.dep_kind,
1315                 );
1316
1317                 let def_id = definitions.opt_local_def_id(item.id).unwrap();
1318                 let len = definitions.def_path(def_id.index).data.len();
1319
1320                 let extern_crate =
1321                     ExternCrate { def_id: def_id, span: item.span, direct: true, path_len: len };
1322                 self.update_extern_crate(cnum, extern_crate, &mut FxHashSet());
1323                 self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
1324             }
1325             _ => {}
1326         }
1327     }
1328 }