creader.rs 40.0 KB
Newer Older
1
//! Validates all used crates and extern libraries and loads their metadata
2

3 4
use crate::dynamic_lib::DynamicLibrary;
use crate::locator::{CrateError, CrateLocator, CratePaths};
M
Mark Rousskov 已提交
5
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
6

7
use rustc_ast::expand::allocator::AllocatorKind;
U
Ujjwal Sharma 已提交
8
use rustc_ast::{self as ast, *};
9
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
10
use rustc_data_structures::svh::Svh;
11
use rustc_data_structures::sync::Lrc;
12
use rustc_expand::base::SyntaxExtension;
13
use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE};
14
use rustc_hir::definitions::Definitions;
15
use rustc_index::vec::IndexVec;
16
use rustc_middle::middle::cstore::{CrateDepKind, CrateSource, ExternCrate};
17
use rustc_middle::middle::cstore::{ExternCrateSource, MetadataLoaderDyn};
18
use rustc_middle::ty::TyCtxt;
19
use rustc_serialize::json::ToJson;
20
use rustc_session::config::{self, CrateType, ExternLocation};
21
use rustc_session::lint::{self, BuiltinLintDiagnostics, ExternDepSpec};
22
use rustc_session::output::validate_crate_name;
23
use rustc_session::search_paths::PathKind;
24
use rustc_session::Session;
25
use rustc_span::edition::Edition;
26
use rustc_span::symbol::{sym, Symbol};
27
use rustc_span::{Span, DUMMY_SP};
28
use rustc_target::spec::{PanicStrategy, TargetTriple};
29

30
use proc_macro::bridge::client::ProcMacro;
31
use std::collections::BTreeMap;
32
use std::path::Path;
33
use std::{cmp, env};
G
Gurpreet Singh 已提交
34
use tracing::{debug, info};
35

36 37 38
#[derive(Clone)]
pub struct CStore {
    metas: IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>,
39
    injected_panic_runtime: Option<CrateNum>,
40 41
    /// This crate needs an allocator and either provides it itself, or finds it in a dependency.
    /// If the above is true, then this field denotes the kind of the found allocator.
42
    allocator_kind: Option<AllocatorKind>,
43 44
    /// This crate has a `#[global_allocator]` item.
    has_global_allocator: bool,
45 46 47 48

    /// This map is used to verify we get no hash conflicts between
    /// `StableCrateId` values.
    stable_crate_ids: FxHashMap<StableCrateId, CrateNum>,
49 50 51

    /// Unused externs of the crate
    unused_externs: Vec<Symbol>,
52 53
}

C
Camille GILLOT 已提交
54 55 56 57 58 59
impl std::fmt::Debug for CStore {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("CStore").finish_non_exhaustive()
    }
}

60
pub struct CrateLoader<'a> {
61
    // Immutable configuration.
62
    sess: &'a Session,
63
    metadata_loader: Box<MetadataLoaderDyn>,
64
    local_crate_name: Symbol,
65 66
    // Mutable output.
    cstore: CStore,
67
    used_extern_options: FxHashSet<Symbol>,
68 69
}

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
pub enum LoadedMacro {
    MacroDef(ast::Item, Edition),
    ProcMacro(SyntaxExtension),
}

crate struct Library {
    pub source: CrateSource,
    pub metadata: MetadataBlob,
}

enum LoadResult {
    Previous(CrateNum),
    Loaded(Library),
}

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
/// A reference to `CrateMetadata` that can also give access to whole crate store when necessary.
#[derive(Clone, Copy)]
crate struct CrateMetadataRef<'a> {
    pub cdata: &'a CrateMetadata,
    pub cstore: &'a CStore,
}

impl std::ops::Deref for CrateMetadataRef<'_> {
    type Target = CrateMetadata;

    fn deref(&self) -> &Self::Target {
        self.cdata
    }
}

100 101 102 103 104
struct CrateDump<'a>(&'a CStore);

impl<'a> std::fmt::Debug for CrateDump<'a> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        writeln!(fmt, "resolved crates:")?;
O
Oliver Scherer 已提交
105 106
        // `iter_crate_data` does not allow returning values. Thus we use a mutable variable here
        // that aggregates the value (and any errors that could happen).
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
        let mut res = Ok(());
        self.0.iter_crate_data(|cnum, data| {
            res = res.and(
                try {
                    writeln!(fmt, "  name: {}", data.name())?;
                    writeln!(fmt, "  cnum: {}", cnum)?;
                    writeln!(fmt, "  hash: {}", data.hash())?;
                    writeln!(fmt, "  reqd: {:?}", data.dep_kind())?;
                    let CrateSource { dylib, rlib, rmeta } = data.source();
                    if let Some(dylib) = dylib {
                        writeln!(fmt, "  dylib: {}", dylib.0.display())?;
                    }
                    if let Some(rlib) = rlib {
                        writeln!(fmt, "   rlib: {}", rlib.0.display())?;
                    }
                    if let Some(rmeta) = rmeta {
                        writeln!(fmt, "   rmeta: {}", rmeta.0.display())?;
                    }
                },
            );
        });
        res
    }
B
Brian Anderson 已提交
130 131
}

132
impl CStore {
133
    pub fn from_tcx(tcx: TyCtxt<'_>) -> &CStore {
134 135 136 137
        tcx.cstore_untracked()
            .as_any()
            .downcast_ref::<CStore>()
            .expect("`tcx.cstore` is not a `CStore`")
138 139
    }

140
    fn alloc_new_crate_num(&mut self) -> CrateNum {
141 142 143
        self.metas.push(None);
        CrateNum::new(self.metas.len() - 1)
    }
144

145 146
    crate fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> {
        let cdata = self.metas[cnum]
M
Mark Rousskov 已提交
147
            .as_ref()
148 149
            .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum));
        CrateMetadataRef { cdata, cstore: self }
150
    }
151

152
    fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) {
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
        assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry");
        self.metas[cnum] = Some(Lrc::new(data));
    }

    crate fn iter_crate_data(&self, mut f: impl FnMut(CrateNum, &CrateMetadata)) {
        for (cnum, data) in self.metas.iter_enumerated() {
            if let Some(data) = data {
                f(cnum, data);
            }
        }
    }

    fn push_dependencies_in_postorder(&self, deps: &mut Vec<CrateNum>, cnum: CrateNum) {
        if !deps.contains(&cnum) {
            let data = self.get_crate_data(cnum);
            for &dep in data.dependencies().iter() {
                if dep != cnum {
                    self.push_dependencies_in_postorder(deps, dep);
                }
            }

            deps.push(cnum);
175 176
        }
    }
177 178 179 180 181 182 183 184 185 186 187

    crate fn crate_dependencies_in_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> {
        let mut deps = Vec::new();
        if cnum == LOCAL_CRATE {
            self.iter_crate_data(|cnum, _| self.push_dependencies_in_postorder(&mut deps, cnum));
        } else {
            self.push_dependencies_in_postorder(&mut deps, cnum);
        }
        deps
    }

188
    fn crate_dependencies_in_reverse_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> {
189 190 191 192
        let mut deps = self.crate_dependencies_in_postorder(cnum);
        deps.reverse();
        deps
    }
193 194 195 196 197 198 199 200

    crate fn injected_panic_runtime(&self) -> Option<CrateNum> {
        self.injected_panic_runtime
    }

    crate fn allocator_kind(&self) -> Option<AllocatorKind> {
        self.allocator_kind
    }
201 202 203 204

    crate fn has_global_allocator(&self) -> bool {
        self.has_global_allocator
    }
205 206

    pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) {
E
est31 已提交
207 208 209 210 211 212
        // We put the check for the option before the lint_level_at_node call
        // because the call mutates internal state and introducing it
        // leads to some ui tests failing.
        if !tcx.sess.opts.json_unused_externs {
            return;
        }
213 214 215
        let level = tcx
            .lint_level_at_node(lint::builtin::UNUSED_CRATE_DEPENDENCIES, rustc_hir::CRATE_HIR_ID)
            .0;
E
est31 已提交
216
        if level != lint::Level::Allow {
217 218 219 220 221 222 223 224 225
            let unused_externs =
                self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::<Vec<_>>();
            let unused_externs = unused_externs.iter().map(String::as_str).collect::<Vec<&str>>();
            tcx.sess
                .parse_sess
                .span_diagnostic
                .emit_unused_externs(level.as_str(), &unused_externs);
        }
    }
226 227
}

228
impl<'a> CrateLoader<'a> {
229 230
    pub fn new(
        sess: &'a Session,
231
        metadata_loader: Box<MetadataLoaderDyn>,
232 233
        local_crate_name: &str,
    ) -> Self {
234
        let mut stable_crate_ids = FxHashMap::default();
235
        stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
236

237
        CrateLoader {
238
            sess,
239
            metadata_loader,
240
            local_crate_name: Symbol::intern(local_crate_name),
241 242 243 244 245 246 247 248
            cstore: CStore {
                // We add an empty entry for LOCAL_CRATE (which maps to zero) in
                // order to make array indices in `metas` match with the
                // corresponding `CrateNum`. This first entry will always remain
                // `None`.
                metas: IndexVec::from_elem_n(None, 1),
                injected_panic_runtime: None,
                allocator_kind: None,
249
                has_global_allocator: false,
250
                stable_crate_ids,
251
                unused_externs: Vec::new(),
M
Mark Rousskov 已提交
252
            },
253
            used_extern_options: Default::default(),
K
Keegan McAllister 已提交
254 255 256
        }
    }

257 258 259 260 261 262 263 264
    pub fn cstore(&self) -> &CStore {
        &self.cstore
    }

    pub fn into_cstore(self) -> CStore {
        self.cstore
    }

265
    fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> {
266
        let mut ret = None;
A
Ariel Ben-Yehuda 已提交
267
        self.cstore.iter_crate_data(|cnum, data| {
M
Mark Rousskov 已提交
268
            if data.name() != name {
J
Joshua Nelson 已提交
269
                tracing::trace!("{} did not match {}", data.name(), name);
M
Mark Rousskov 已提交
270 271
                return;
            }
272 273

            match hash {
M
Mark Rousskov 已提交
274 275 276 277
                Some(hash) if hash == data.hash() => {
                    ret = Some(cnum);
                    return;
                }
J
Joshua Nelson 已提交
278 279 280 281
                Some(hash) => {
                    debug!("actual hash {} did not match expected {}", hash, data.hash());
                    return;
                }
282 283 284
                None => {}
            }

285 286 287 288 289
            // When the hash is None we're dealing with a top-level dependency
            // in which case we may have a specification on the command line for
            // this library. Even though an upstream library may have loaded
            // something of the same name, we have to make sure it was loaded
            // from the exact same location as well.
290 291 292 293
            //
            // We're also sure to compare *paths*, not actual byte slices. The
            // `source` stores paths which are normalized which may be different
            // from the strings on the command line.
294
            let source = self.cstore.get_crate_data(cnum).cdata.source();
295
            if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) {
296
                // Only use `--extern crate_name=path` here, not `--extern crate_name`.
E
Eric Huss 已提交
297 298
                if let Some(mut files) = entry.files() {
                    if files.any(|l| {
299 300 301 302
                        let l = l.canonicalized();
                        source.dylib.as_ref().map(|(p, _)| p) == Some(l)
                            || source.rlib.as_ref().map(|(p, _)| p) == Some(l)
                            || source.rmeta.as_ref().map(|(p, _)| p) == Some(l)
E
Eric Huss 已提交
303 304 305
                    }) {
                        ret = Some(cnum);
                    }
306
                }
M
Mark Rousskov 已提交
307
                return;
308 309 310 311 312 313 314 315
            }

            // Alright, so we've gotten this far which means that `data` has the
            // right name, we don't have a hash, and we don't have a --extern
            // pointing for ourselves. We're still not quite yet done because we
            // have to make sure that this crate was found in the crate lookup
            // path (this is a top-level dependency) as we don't want to
            // implicitly load anything inside the dependency lookup path.
M
Mark Rousskov 已提交
316 317 318 319 320 321 322
            let prev_kind = source
                .dylib
                .as_ref()
                .or(source.rlib.as_ref())
                .or(source.rmeta.as_ref())
                .expect("No sources for crate")
                .1;
V
Vadim Petrochenkov 已提交
323
            if kind.matches(prev_kind) {
324
                ret = Some(cnum);
J
Joshua Nelson 已提交
325 326 327 328 329
            } else {
                debug!(
                    "failed to load existing crate {}; kind {:?} did not match prev_kind {:?}",
                    name, kind, prev_kind
                );
330 331
            }
        });
332
        ret
333
    }
334

335
    fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> {
336
        // Check for (potential) conflicts with the local crate
337
        if self.sess.local_stable_crate_id() == root.stable_crate_id() {
338
            return Err(CrateError::SymbolConflictsCurrent(root.name()));
339 340 341
        }

        // Check for conflicts with any crate loaded so far
342
        let mut res = Ok(());
343
        self.cstore.iter_crate_data(|_, other| {
344
            if other.stable_crate_id() == root.stable_crate_id() && // same stable crate id
M
Mark Rousskov 已提交
345 346 347
               other.hash() != root.hash()
            {
                // but different SVH
348
                res = Err(CrateError::SymbolConflictsOthers(root.name()));
349 350
            }
        });
351 352

        res
353 354
    }

355 356 357 358 359 360 361 362 363 364 365 366 367 368
    fn verify_no_stable_crate_id_hash_conflicts(
        &mut self,
        root: &CrateRoot<'_>,
        cnum: CrateNum,
    ) -> Result<(), CrateError> {
        if let Some(existing) = self.cstore.stable_crate_ids.insert(root.stable_crate_id(), cnum) {
            let crate_name0 = root.name();
            let crate_name1 = self.cstore.get_crate_data(existing).name();
            return Err(CrateError::StableCrateIdCollision(crate_name0, crate_name1));
        }

        Ok(())
    }

369
    fn register_crate(
370
        &mut self,
371
        host_lib: Option<Library>,
372
        root: Option<&CratePaths>,
373
        lib: Library,
374
        dep_kind: CrateDepKind,
M
Mark Rousskov 已提交
375
        name: Symbol,
376
    ) -> Result<CrateNum, CrateError> {
377
        let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate");
378

379 380
        let Library { source, metadata } = lib;
        let crate_root = metadata.get_root();
381
        let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash());
382

M
Mark Rousskov 已提交
383
        let private_dep =
384
            self.sess.opts.externs.get(&name.as_str()).map_or(false, |e| e.is_private_dep);
385

386
        // Claim this crate number and cache it
387
        let cnum = self.cstore.alloc_new_crate_num();
388

389 390 391 392 393 394 395
        info!(
            "register crate `{}` (cnum = {}. private_dep = {})",
            crate_root.name(),
            cnum,
            private_dep
        );

396
        // Maintain a reference to the top most crate.
397
        // Stash paths for top-most crate locally if necessary.
398 399 400 401
        let crate_paths;
        let root = if let Some(root) = root {
            root
        } else {
402
            crate_paths = CratePaths::new(crate_root.name(), source.clone());
403
            &crate_paths
404
        };
405

406
        let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, dep_kind)?;
407

408
        let raw_proc_macros = if crate_root.is_proc_macro_crate() {
409
            let temp_root;
410
            let (dlsym_source, dlsym_root) = match &host_lib {
M
Mark Rousskov 已提交
411 412 413 414
                Some(host_lib) => (&host_lib.source, {
                    temp_root = host_lib.metadata.get_root();
                    &temp_root
                }),
415
                None => (&source, &crate_root),
416
            };
417
            let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
418
            Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.stable_crate_id())?)
419 420 421
        } else {
            None
        };
422

423 424 425 426 427 428 429 430
        // Perform some verification *after* resolve_crate_deps() above is
        // known to have been successful. It seems that - in error cases - the
        // cstore can be in a temporarily invalid state between cnum allocation
        // and dependency resolution and the verification code would produce
        // ICEs in that case (see #83045).
        self.verify_no_symbol_conflicts(&crate_root)?;
        self.verify_no_stable_crate_id_hash_conflicts(&crate_root, cnum)?;

431 432 433 434 435
        let crate_metadata = CrateMetadata::new(
            self.sess,
            metadata,
            crate_root,
            raw_proc_macros,
436
            cnum,
437 438 439 440 441
            cnum_map,
            dep_kind,
            source,
            private_dep,
            host_hash,
M
Mark Rousskov 已提交
442
        );
443

444 445
        self.cstore.set_crate_data(cnum, crate_metadata);

446
        Ok(cnum)
447
    }
448

449
    fn load_proc_macro<'b>(
450
        &self,
451
        locator: &mut CrateLocator<'b>,
452
        path_kind: PathKind,
B
bjorn3 已提交
453
        host_hash: Option<Svh>,
454
    ) -> Result<Option<(LoadResult, Option<Library>)>, CrateError>
455 456 457
    where
        'a: 'b,
    {
458
        // Use a new crate locator so trying to load a proc macro doesn't affect the error
459
        // message we emit
460
        let mut proc_macro_locator = locator.clone();
461 462

        // Try to load a proc macro
B
bjorn3 已提交
463
        proc_macro_locator.is_proc_macro = true;
464 465 466 467 468

        // Load the proc macro crate for the target
        let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros {
            proc_macro_locator.reset();
            let result = match self.load(&mut proc_macro_locator)? {
469 470 471 472 473
                Some(LoadResult::Previous(cnum)) => {
                    return Ok(Some((LoadResult::Previous(cnum), None)));
                }
                Some(LoadResult::Loaded(library)) => Some(LoadResult::Loaded(library)),
                None => return Ok(None),
474
            };
B
bjorn3 已提交
475
            locator.hash = host_hash;
476
            // Use the locator when looking for the host proc macro crate, as that is required
477
            // so we want it to affect the error message
478
            (locator, result)
479 480 481 482 483 484 485
        } else {
            (&mut proc_macro_locator, None)
        };

        // Load the proc macro crate for the host

        locator.reset();
B
bjorn3 已提交
486
        locator.is_proc_macro = true;
487 488 489 490
        locator.target = &self.sess.host;
        locator.triple = TargetTriple::from_triple(config::host_triple());
        locator.filesearch = self.sess.host_filesearch(path_kind);

491 492 493 494
        let host_result = match self.load(locator)? {
            Some(host_result) => host_result,
            None => return Ok(None),
        };
495

496
        Ok(Some(if self.sess.opts.debugging_opts.dual_proc_macros {
497 498 499 500
            let host_result = match host_result {
                LoadResult::Previous(..) => {
                    panic!("host and target proc macros must be loaded in lock-step")
                }
M
Mark Rousskov 已提交
501
                LoadResult::Loaded(library) => library,
502 503 504 505
            };
            (target_result.unwrap(), Some(host_result))
        } else {
            (host_result, None)
506
        }))
507 508
    }

509
    fn resolve_crate<'b>(
510
        &'b mut self,
511 512
        name: Symbol,
        span: Span,
513
        dep_kind: CrateDepKind,
514
    ) -> CrateNum {
515 516
        self.used_extern_options.insert(name);
        self.maybe_resolve_crate(name, dep_kind, None).unwrap_or_else(|err| {
517 518 519 520
            let missing_core =
                self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
            err.report(&self.sess, span, missing_core)
        })
521 522 523
    }

    fn maybe_resolve_crate<'b>(
524
        &'b mut self,
525
        name: Symbol,
526
        mut dep_kind: CrateDepKind,
527
        dep: Option<(&'b CratePaths, &'b CrateDep)>,
528
    ) -> Result<CrateNum, CrateError> {
529
        info!("resolving crate `{}`", name);
530 531 532
        if !name.as_str().is_ascii() {
            return Err(CrateError::NonAsciiName(name));
        }
M
msizanoen 已提交
533 534 535
        let (root, hash, host_hash, extra_filename, path_kind) = match dep {
            Some((root, dep)) => (
                Some(root),
536 537
                Some(dep.hash),
                dep.host_hash,
M
msizanoen 已提交
538
                Some(&dep.extra_filename[..]),
539
                PathKind::Dependency,
M
msizanoen 已提交
540 541
            ),
            None => (None, None, None, None, PathKind::Crate),
542
        };
543
        let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
544
            (LoadResult::Previous(cnum), None)
545 546
        } else {
            info!("falling back to a load");
547 548
            let mut locator = CrateLocator::new(
                self.sess,
549
                &*self.metadata_loader,
550
                name,
B
bjorn3 已提交
551 552
                hash,
                extra_filename,
553 554 555
                false, // is_host
                path_kind,
            );
J
John Kåre Alsaker 已提交
556

557 558 559
            match self.load(&mut locator)? {
                Some(res) => (res, None),
                None => {
560
                    dep_kind = CrateDepKind::MacrosOnly;
B
bjorn3 已提交
561
                    match self.load_proc_macro(&mut locator, path_kind, host_hash)? {
562
                        Some(res) => res,
B
bjorn3 已提交
563
                        None => return Err(locator.into_error(root.cloned())),
564 565 566
                    }
                }
            }
567 568 569
        };

        match result {
570
            (LoadResult::Previous(cnum), None) => {
A
Ariel Ben-Yehuda 已提交
571
                let data = self.cstore.get_crate_data(cnum);
572
                if data.is_proc_macro_crate() {
573
                    dep_kind = CrateDepKind::MacrosOnly;
574
                }
575
                data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind));
576
                Ok(cnum)
577
            }
578
            (LoadResult::Loaded(library), host_library) => {
579
                self.register_crate(host_library, root, library, dep_kind, name)
580
            }
M
Mark Rousskov 已提交
581
            _ => panic!(),
582
        }
583
    }
584

585 586 587 588 589
    fn load(&self, locator: &mut CrateLocator<'_>) -> Result<Option<LoadResult>, CrateError> {
        let library = match locator.maybe_load_library_crate()? {
            Some(library) => library,
            None => return Ok(None),
        };
590 591 592 593 594 595 596 597 598

        // In the case that we're loading a crate, but not matching
        // against a hash, we could load a crate which has the same hash
        // as an already loaded crate. If this is the case prevent
        // duplicates by just using the first crate.
        //
        // Note that we only do this for target triple crates, though, as we
        // don't want to match a host crate against an equivalent target one
        // already loaded.
599
        let root = library.metadata.get_root();
600 601 602
        // FIXME: why is this condition necessary? It was adding in #33625 but I
        // don't know why and the original author doesn't remember ...
        let can_reuse_cratenum =
B
bjorn3 已提交
603
            locator.triple == self.sess.opts.target_triple || locator.is_proc_macro;
604
        Ok(Some(if can_reuse_cratenum {
605 606
            let mut result = LoadResult::Loaded(library);
            self.cstore.iter_crate_data(|cnum, data| {
607
                if data.name() == root.name() && root.hash() == data.hash() {
608
                    assert!(locator.hash.is_none());
609
                    info!("load success, going to previous cnum: {}", cnum);
610 611 612
                    result = LoadResult::Previous(cnum);
                }
            });
613
            result
614
        } else {
615 616
            LoadResult::Loaded(library)
        }))
617 618
    }

619
    fn update_extern_crate(&self, cnum: CrateNum, extern_crate: ExternCrate) {
620
        let cmeta = self.cstore.get_crate_data(cnum);
621
        if cmeta.update_extern_crate(extern_crate) {
622 623
            // Propagate the extern crate info to dependencies if it was updated.
            let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate };
624
            for &dep_cnum in cmeta.dependencies().iter() {
625
                self.update_extern_crate(dep_cnum, extern_crate);
626
            }
627 628 629
        }
    }

630
    // Go through the crate metadata and load any crates that it references
M
Mark Rousskov 已提交
631 632 633 634 635 636
    fn resolve_crate_deps(
        &mut self,
        root: &CratePaths,
        crate_root: &CrateRoot<'_>,
        metadata: &MetadataBlob,
        krate: CrateNum,
637
        dep_kind: CrateDepKind,
638
    ) -> Result<CrateNumMap, CrateError> {
639
        debug!("resolving deps of external crate");
640
        if crate_root.is_proc_macro_crate() {
641
            return Ok(CrateNumMap::new());
642 643
        }

644 645 646
        // The map from crate numbers in the crate we're resolving to local crate numbers.
        // We map 0 and all other holes in the map to our parent crate. The "additional"
        // self-dependencies should be harmless.
647 648 649 650 651 652 653 654 655
        let deps = crate_root.decode_crate_deps(metadata);
        let mut crate_num_map = CrateNumMap::with_capacity(1 + deps.len());
        crate_num_map.push(krate);
        for dep in deps {
            info!(
                "resolving dep crate {} hash: `{}` extra filename: `{}`",
                dep.name, dep.hash, dep.extra_filename
            );
            let dep_kind = match dep_kind {
656
                CrateDepKind::MacrosOnly => CrateDepKind::MacrosOnly,
657 658 659 660 661
                _ => dep.kind,
            };
            let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((root, &dep)))?;
            crate_num_map.push(cnum);
        }
662 663

        debug!("resolve_crate_deps: cnum_map for {:?} is {:?}", krate, crate_num_map);
664
        Ok(crate_num_map)
665
    }
666

M
Mark Rousskov 已提交
667 668 669
    fn dlsym_proc_macros(
        &self,
        path: &Path,
670
        stable_crate_id: StableCrateId,
671
    ) -> Result<&'static [ProcMacro], CrateError> {
672 673
        // Make sure the path contains a / or the linker will search for it.
        let path = env::current_dir().unwrap().join(path);
M
Mark Rousskov 已提交
674
        let lib = match DynamicLibrary::open(&path) {
675
            Ok(lib) => lib,
676
            Err(s) => return Err(CrateError::DlOpen(s)),
677 678
        };

679
        let sym = self.sess.generate_proc_macro_decls_symbol(stable_crate_id);
680
        let decls = unsafe {
681 682
            let sym = match lib.symbol(&sym) {
                Ok(f) => f,
683
                Err(s) => return Err(CrateError::DlSym(s)),
684
            };
685
            *(sym as *const &[ProcMacro])
686 687 688 689
        };

        // Intentionally leak the dynamic library. We can't ever unload it
        // since the library can make things that will live arbitrarily long.
690
        std::mem::forget(lib);
691

692
        Ok(decls)
693
    }
694

695
    fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
696 697
        // If we're only compiling an rlib, then there's no need to select a
        // panic runtime, so we just skip this section entirely.
698
        let any_non_rlib = self.sess.crate_types().iter().any(|ct| *ct != CrateType::Rlib);
699 700
        if !any_non_rlib {
            info!("panic runtime injection skipped, only generating rlib");
M
Mark Rousskov 已提交
701
            return;
702 703 704 705 706 707 708 709 710
        }

        // If we need a panic runtime, we try to find an existing one here. At
        // the same time we perform some general validation of the DAG we've got
        // going such as ensuring everything has a compatible panic strategy.
        //
        // The logic for finding the panic runtime here is pretty much the same
        // as the allocator case with the only addition that the panic strategy
        // compilation mode also comes into play.
711
        let desired_strategy = self.sess.panic_strategy();
712
        let mut runtime_found = false;
713 714
        let mut needs_panic_runtime =
            self.sess.contains_name(&krate.attrs, sym::needs_panic_runtime);
715

716
        self.cstore.iter_crate_data(|cnum, data| {
717 718
            needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime();
            if data.is_panic_runtime() {
719 720
                // Inject a dependency from all #![needs_panic_runtime] to this
                // #![panic_runtime] crate.
M
Mark Rousskov 已提交
721 722 723
                self.inject_dependency_if(cnum, "a panic runtime", &|data| {
                    data.needs_panic_runtime()
                });
724
                runtime_found = runtime_found || data.dep_kind() == CrateDepKind::Explicit;
725 726 727 728 729 730 731
            }
        });

        // If an explicitly linked and matching panic runtime was found, or if
        // we just don't need one at all, then we're done here and there's
        // nothing else to do.
        if !needs_panic_runtime || runtime_found {
M
Mark Rousskov 已提交
732
            return;
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
        }

        // By this point we know that we (a) need a panic runtime and (b) no
        // panic runtime was explicitly linked. Here we just load an appropriate
        // default runtime for our panic strategy and then inject the
        // dependencies.
        //
        // We may resolve to an already loaded crate (as the crate may not have
        // been explicitly linked prior to this) and we may re-inject
        // dependencies again, but both of those situations are fine.
        //
        // Also note that we have yet to perform validation of the crate graph
        // in terms of everyone has a compatible panic runtime format, that's
        // performed later as part of the `dependency_format` module.
        let name = match desired_strategy {
748 749
            PanicStrategy::Unwind => sym::panic_unwind,
            PanicStrategy::Abort => sym::panic_abort,
750 751 752
        };
        info!("panic runtime not found -- loading {}", name);

753
        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit);
754
        let data = self.cstore.get_crate_data(cnum);
755 756 757

        // Sanity check the loaded crate to ensure it is indeed a panic runtime
        // and the panic strategy is indeed what we thought it was.
758
        if !data.is_panic_runtime() {
M
Mark Rousskov 已提交
759
            self.sess.err(&format!("the crate `{}` is not a panic runtime", name));
760
        }
761
        if data.panic_strategy() != desired_strategy {
M
Mark Rousskov 已提交
762 763
            self.sess.err(&format!(
                "the crate `{}` does not have the panic \
764
                                    strategy `{}`",
M
Mark Rousskov 已提交
765 766 767
                name,
                desired_strategy.desc()
            ));
768 769
        }

770
        self.cstore.injected_panic_runtime = Some(cnum);
M
Mark Rousskov 已提交
771
        self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime());
772 773
    }

774
    fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
775 776
        if self.sess.opts.debugging_opts.no_profiler_runtime
            || !(self.sess.instrument_coverage()
777
                || self.sess.opts.debugging_opts.profile
778
                || self.sess.opts.cg.profile_generate.enabled())
779
        {
780 781
            return;
        }
M
Marco Castelluccio 已提交
782

783
        info!("loading profiler");
784

785
        let name = Symbol::intern(&self.sess.opts.debugging_opts.profiler_runtime);
786 787 788 789 790 791
        if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
            self.sess.err(
                "`profiler_builtins` crate (required by compiler options) \
                        is not compatible with crate attribute `#![no_core]`",
            );
        }
M
Marco Castelluccio 已提交
792

793
        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit);
794 795 796 797 798
        let data = self.cstore.get_crate_data(cnum);

        // Sanity check the loaded crate to ensure it is indeed a profiler runtime
        if !data.is_profiler_runtime() {
            self.sess.err(&format!("the crate `{}` is not a profiler runtime", name));
799 800 801
        }
    }

M
Mark Rousskov 已提交
802
    fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
803
        self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) {
804
            [span1, span2, ..] => {
M
Mark Rousskov 已提交
805 806
                self.sess
                    .struct_span_err(*span2, "cannot define multiple global allocators")
E
Esteban Küber 已提交
807
                    .span_label(*span2, "cannot define a new global allocator")
808
                    .span_label(*span1, "previous global allocator defined here")
E
Esteban Küber 已提交
809
                    .emit();
810 811
                true
            }
M
Mark Rousskov 已提交
812
            spans => !spans.is_empty(),
813
        };
814 815 816 817

        // Check to see if we actually need an allocator. This desire comes
        // about through the `#![needs_allocator]` attribute and is typically
        // written down in liballoc.
818
        let mut needs_allocator = self.sess.contains_name(&krate.attrs, sym::needs_allocator);
819
        self.cstore.iter_crate_data(|_, data| {
820
            needs_allocator = needs_allocator || data.needs_allocator();
821
        });
822
        if !needs_allocator {
M
Mark Rousskov 已提交
823
            return;
824
        }
825

826 827 828
        // At this point we've determined that we need an allocator. Let's see
        // if our compilation session actually needs an allocator based on what
        // we're emitting.
J
Joshua Nelson 已提交
829
        let all_rlib = self.sess.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib));
830
        if all_rlib {
M
Mark Rousskov 已提交
831
            return;
832
        }
833

834 835 836
        // Ok, we need an allocator. Not only that but we're actually going to
        // create an artifact that needs one linked in. Let's go find the one
        // that we're going to link in.
837
        //
838 839 840
        // First up we check for global allocators. Look at the crate graph here
        // and see what's a global allocator, including if we ourselves are a
        // global allocator.
M
Mark Rousskov 已提交
841 842
        let mut global_allocator =
            self.cstore.has_global_allocator.then(|| Symbol::intern("this crate"));
843
        self.cstore.iter_crate_data(|_, data| {
844
            if !data.has_global_allocator() {
M
Mark Rousskov 已提交
845
                return;
846 847
            }
            match global_allocator {
848
                Some(other_crate) => {
M
Mark Rousskov 已提交
849 850
                    self.sess.err(&format!(
                        "the `#[global_allocator]` in {} \
851
                                            conflicts with global \
852
                                            allocator in: {}",
M
Mark Rousskov 已提交
853 854 855
                        other_crate,
                        data.name()
                    ));
856
                }
857
                None => global_allocator = Some(data.name()),
858 859 860
            }
        });
        if global_allocator.is_some() {
M
Mark Rousskov 已提交
861
            self.cstore.allocator_kind = Some(AllocatorKind::Global);
M
Mark Rousskov 已提交
862
            return;
863 864 865
        }

        // Ok we haven't found a global allocator but we still need an
866 867 868
        // allocator. At this point our allocator request is typically fulfilled
        // by the standard library, denoted by the `#![default_lib_allocator]`
        // attribute.
869
        let mut has_default = self.sess.contains_name(&krate.attrs, sym::default_lib_allocator);
870
        self.cstore.iter_crate_data(|_, data| {
871
            if data.has_default_lib_allocator() {
872
                has_default = true;
873
            }
874 875
        });

876
        if !has_default {
M
Mark Rousskov 已提交
877 878
            self.sess.err(
                "no global memory allocator found but one is \
879
                           required; link to std or \
880
                           add `#[global_allocator]` to a static item \
M
Mark Rousskov 已提交
881 882
                           that implements the GlobalAlloc trait.",
            );
883
        }
884
        self.cstore.allocator_kind = Some(AllocatorKind::Default);
885 886
    }

M
Mark Rousskov 已提交
887 888 889 890 891 892
    fn inject_dependency_if(
        &self,
        krate: CrateNum,
        what: &str,
        needs_dep: &dyn Fn(&CrateMetadata) -> bool,
    ) {
893 894 895 896
        // don't perform this validation if the session has errors, as one of
        // those errors may indicate a circular dependency which could cause
        // this to stack overflow.
        if self.sess.has_errors() {
M
Mark Rousskov 已提交
897
            return;
898 899
        }

900
        // Before we inject any dependencies, make sure we don't inject a
901 902
        // circular dependency by validating that this crate doesn't
        // transitively depend on any crates satisfying `needs_dep`.
903
        for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) {
904 905
            let data = self.cstore.get_crate_data(dep);
            if needs_dep(&data) {
M
Mark Rousskov 已提交
906 907
                self.sess.err(&format!(
                    "the crate `{}` cannot depend \
908 909
                                        on a crate that needs {}, but \
                                        it depends on `{}`",
M
Mark Rousskov 已提交
910 911 912 913
                    self.cstore.get_crate_data(krate).name(),
                    what,
                    data.name()
                ));
914 915
            }
        }
916 917 918 919 920

        // All crates satisfying `needs_dep` do not explicitly depend on the
        // crate provided for this compile, but in order for this compilation to
        // be successfully linked we need to inject a dependency (to order the
        // crates on the command line correctly).
A
Ariel Ben-Yehuda 已提交
921
        self.cstore.iter_crate_data(|cnum, data| {
922
            if !needs_dep(data) {
M
Mark Rousskov 已提交
923
                return;
924 925
            }

926
            info!("injecting a dep from {} to {}", cnum, krate);
927
            data.add_dependency(krate);
928 929
        });
    }
930

931 932 933 934
    fn report_unused_deps(&mut self, krate: &ast::Crate) {
        // Make a point span rather than covering the whole file
        let span = krate.span.shrink_to_lo();
        // Complain about anything left over
935 936 937 938 939
        for (name, entry) in self.sess.opts.externs.iter() {
            if let ExternLocation::FoundInLibrarySearchDirectories = entry.location {
                // Don't worry about pathless `--extern foo` sysroot references
                continue;
            }
940 941
            let name_interned = Symbol::intern(name);
            if self.used_extern_options.contains(&name_interned) {
942 943 944 945
                continue;
            }

            // Got a real unused --extern
946 947 948 949 950
            if self.sess.opts.json_unused_externs {
                self.cstore.unused_externs.push(name_interned);
                continue;
            }

951 952 953 954 955 956 957 958 959 960 961 962 963 964
            let diag = match self.sess.opts.extern_dep_specs.get(name) {
                Some(loc) => BuiltinLintDiagnostics::ExternDepSpec(name.clone(), loc.into()),
                None => {
                    // If we don't have a specific location, provide a json encoding of the `--extern`
                    // option.
                    let meta: BTreeMap<String, String> =
                        std::iter::once(("name".to_string(), name.to_string())).collect();
                    BuiltinLintDiagnostics::ExternDepSpec(
                        name.clone(),
                        ExternDepSpec::Json(meta.to_json()),
                    )
                }
            };
            self.sess.parse_sess.buffer_lint_with_diagnostic(
965 966 967 968 969 970 971 972
                    lint::builtin::UNUSED_CRATE_DEPENDENCIES,
                    span,
                    ast::CRATE_NODE_ID,
                    &format!(
                        "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
                        name,
                        self.local_crate_name,
                        name),
973
                    diag,
974 975 976 977
                );
        }
    }

978
    pub fn postprocess(&mut self, krate: &ast::Crate) {
979
        self.inject_profiler_runtime(krate);
980
        self.inject_allocator_crate(krate);
981
        self.inject_panic_runtime(krate);
982

983
        self.report_unused_deps(krate);
984 985

        info!("{:?}", CrateDump(&self.cstore));
986 987
    }

988 989 990 991
    pub fn process_extern_crate(
        &mut self,
        item: &ast::Item,
        definitions: &Definitions,
992
        def_id: LocalDefId,
993
    ) -> CrateNum {
V
varkor 已提交
994
        match item.kind {
995
            ast::ItemKind::ExternCrate(orig_name) => {
M
Mark Rousskov 已提交
996 997 998 999
                debug!(
                    "resolving extern crate stmt. ident: {} orig_name: {:?}",
                    item.ident, orig_name
                );
1000
                let name = match orig_name {
1001
                    Some(orig_name) => {
1002
                        validate_crate_name(self.sess, &orig_name.as_str(), Some(item.span));
1003
                        orig_name
1004 1005 1006
                    }
                    None => item.ident.name,
                };
1007
                let dep_kind = if self.sess.contains_name(&item.attrs, sym::no_link) {
1008
                    CrateDepKind::MacrosOnly
1009
                } else {
1010
                    CrateDepKind::Explicit
1011 1012
                };

1013
                let cnum = self.resolve_crate(name, item.span, dep_kind);
1014

1015
                let path_len = definitions.def_path(def_id).data.len();
1016 1017 1018
                self.update_extern_crate(
                    cnum,
                    ExternCrate {
1019
                        src: ExternCrateSource::Extern(def_id.to_def_id()),
1020
                        span: item.span,
S
Shotaro Yamada 已提交
1021
                        path_len,
1022
                        dependency_of: LOCAL_CRATE,
1023 1024 1025
                    },
                );
                cnum
1026
            }
1027
            _ => bug!(),
1028
        }
1029
    }
1030

1031
    pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum {
1032
        let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit);
1033 1034 1035 1036 1037 1038

        self.update_extern_crate(
            cnum,
            ExternCrate {
                src: ExternCrateSource::Path,
                span,
S
Shotaro Yamada 已提交
1039
                // to have the least priority in `update_extern_crate`
L
Lzu Tao 已提交
1040
                path_len: usize::MAX,
1041
                dependency_of: LOCAL_CRATE,
1042 1043 1044 1045 1046
            },
        );

        cnum
    }
1047

1048
    pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
1049
        self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok()
1050
    }
1051
}
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074

fn global_allocator_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> {
    struct Finder<'a> {
        sess: &'a Session,
        name: Symbol,
        spans: Vec<Span>,
    }
    impl<'ast, 'a> visit::Visitor<'ast> for Finder<'a> {
        fn visit_item(&mut self, item: &'ast ast::Item) {
            if item.ident.name == self.name
                && self.sess.contains_name(&item.attrs, sym::rustc_std_internal_symbol)
            {
                self.spans.push(item.span);
            }
            visit::walk_item(self, item)
        }
    }

    let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::alloc));
    let mut f = Finder { sess, name, spans: Vec::new() };
    visit::walk_crate(&mut f, krate);
    f.spans
}