Skip to content

Commit 0a4217d

Browse files
committed
rustc_metadata: Make crate loading fully speculative
1 parent 4044cbc commit 0a4217d

14 files changed

+453
-471
lines changed

src/librustc_metadata/creader.rs

+78-105
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
//! Validates all used crates and extern libraries and loads their metadata
22
3-
use crate::locator::{CrateLocator, CratePaths};
3+
use crate::dynamic_lib::DynamicLibrary;
4+
use crate::locator::{CrateError, CrateLocator, CratePaths};
45
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
56

67
use rustc_ast::expand::allocator::{global_allocator_spans, AllocatorKind};
78
use rustc_ast::{ast, attr};
89
use rustc_data_structures::fx::FxHashSet;
910
use rustc_data_structures::svh::Svh;
1011
use rustc_data_structures::sync::Lrc;
11-
use rustc_errors::struct_span_err;
1212
use rustc_expand::base::SyntaxExtension;
1313
use rustc_hir::def_id::{CrateNum, LocalDefId, LOCAL_CRATE};
1414
use rustc_hir::definitions::Definitions;
1515
use rustc_index::vec::IndexVec;
16-
use rustc_middle::middle::cstore::DepKind;
17-
use rustc_middle::middle::cstore::{
18-
CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn,
19-
};
16+
use rustc_middle::middle::cstore::{CrateSource, DepKind, ExternCrate};
17+
use rustc_middle::middle::cstore::{ExternCrateSource, MetadataLoaderDyn};
2018
use rustc_middle::ty::TyCtxt;
2119
use rustc_session::config::{self, CrateType, ExternLocation};
2220
use rustc_session::lint;
@@ -31,7 +29,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple};
3129
use log::{debug, info, log_enabled};
3230
use proc_macro::bridge::client::ProcMacro;
3331
use std::path::Path;
34-
use std::{cmp, fs};
32+
use std::{cmp, env, fs};
3533

3634
#[derive(Clone)]
3735
pub struct CStore {
@@ -69,18 +67,6 @@ enum LoadResult {
6967
Loaded(Library),
7068
}
7169

72-
enum LoadError<'a> {
73-
LocatorError(CrateLocator<'a>),
74-
}
75-
76-
impl<'a> LoadError<'a> {
77-
fn report(self) -> ! {
78-
match self {
79-
LoadError::LocatorError(locator) => locator.report_errs(),
80-
}
81-
}
82-
}
83-
8470
/// A reference to `CrateMetadata` that can also give access to whole crate store when necessary.
8571
#[derive(Clone, Copy)]
8672
crate struct CrateMetadataRef<'a> {
@@ -280,60 +266,43 @@ impl<'a> CrateLoader<'a> {
280266
ret
281267
}
282268

283-
fn verify_no_symbol_conflicts(&self, span: Span, root: &CrateRoot<'_>) {
269+
fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> {
284270
// Check for (potential) conflicts with the local crate
285271
if self.local_crate_name == root.name()
286272
&& self.sess.local_crate_disambiguator() == root.disambiguator()
287273
{
288-
struct_span_err!(
289-
self.sess,
290-
span,
291-
E0519,
292-
"the current crate is indistinguishable from one of its \
293-
dependencies: it has the same crate-name `{}` and was \
294-
compiled with the same `-C metadata` arguments. This \
295-
will result in symbol conflicts between the two.",
296-
root.name()
297-
)
298-
.emit()
274+
return Err(CrateError::SymbolConflictsCurrent(root.name()));
299275
}
300276

301277
// Check for conflicts with any crate loaded so far
278+
let mut res = Ok(());
302279
self.cstore.iter_crate_data(|_, other| {
303280
if other.name() == root.name() && // same crate-name
304-
other.disambiguator() == root.disambiguator() && // same crate-disambiguator
281+
other.disambiguator() == root.disambiguator() && // same crate-disambiguator
305282
other.hash() != root.hash()
306283
{
307284
// but different SVH
308-
struct_span_err!(
309-
self.sess,
310-
span,
311-
E0523,
312-
"found two different crates with name `{}` that are \
313-
not distinguished by differing `-C metadata`. This \
314-
will result in symbol conflicts between the two.",
315-
root.name()
316-
)
317-
.emit();
285+
res = Err(CrateError::SymbolConflictsOthers(root.name()));
318286
}
319287
});
288+
289+
res
320290
}
321291

322292
fn register_crate(
323293
&mut self,
324294
host_lib: Option<Library>,
325295
root: Option<&CratePaths>,
326-
span: Span,
327296
lib: Library,
328297
dep_kind: DepKind,
329298
name: Symbol,
330-
) -> CrateNum {
299+
) -> Result<CrateNum, CrateError> {
331300
let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate");
332301

333302
let Library { source, metadata } = lib;
334303
let crate_root = metadata.get_root();
335304
let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash());
336-
self.verify_no_symbol_conflicts(span, &crate_root);
305+
self.verify_no_symbol_conflicts(&crate_root)?;
337306

338307
let private_dep =
339308
self.sess.opts.externs.get(&name.as_str()).map(|e| e.is_private_dep).unwrap_or(false);
@@ -353,7 +322,7 @@ impl<'a> CrateLoader<'a> {
353322
&crate_paths
354323
};
355324

356-
let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
325+
let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, dep_kind)?;
357326

358327
let raw_proc_macros = if crate_root.is_proc_macro_crate() {
359328
let temp_root;
@@ -365,7 +334,7 @@ impl<'a> CrateLoader<'a> {
365334
None => (&source, &crate_root),
366335
};
367336
let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
368-
Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator(), span))
337+
Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator())?)
369338
} else {
370339
None
371340
};
@@ -386,14 +355,14 @@ impl<'a> CrateLoader<'a> {
386355
),
387356
);
388357

389-
cnum
358+
Ok(cnum)
390359
}
391360

392361
fn load_proc_macro<'b>(
393362
&self,
394363
locator: &mut CrateLocator<'b>,
395364
path_kind: PathKind,
396-
) -> Option<(LoadResult, Option<Library>)>
365+
) -> Result<Option<(LoadResult, Option<Library>)>, CrateError>
397366
where
398367
'a: 'b,
399368
{
@@ -408,8 +377,11 @@ impl<'a> CrateLoader<'a> {
408377
let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros {
409378
proc_macro_locator.reset();
410379
let result = match self.load(&mut proc_macro_locator)? {
411-
LoadResult::Previous(cnum) => return Some((LoadResult::Previous(cnum), None)),
412-
LoadResult::Loaded(library) => Some(LoadResult::Loaded(library)),
380+
Some(LoadResult::Previous(cnum)) => {
381+
return Ok(Some((LoadResult::Previous(cnum), None)));
382+
}
383+
Some(LoadResult::Loaded(library)) => Some(LoadResult::Loaded(library)),
384+
None => return Ok(None),
413385
};
414386
locator.hash = locator.host_hash;
415387
// Use the locator when looking for the host proc macro crate, as that is required
@@ -427,9 +399,12 @@ impl<'a> CrateLoader<'a> {
427399
locator.triple = TargetTriple::from_triple(config::host_triple());
428400
locator.filesearch = self.sess.host_filesearch(path_kind);
429401

430-
let host_result = self.load(locator)?;
402+
let host_result = match self.load(locator)? {
403+
Some(host_result) => host_result,
404+
None => return Ok(None),
405+
};
431406

432-
Some(if self.sess.opts.debugging_opts.dual_proc_macros {
407+
Ok(Some(if self.sess.opts.debugging_opts.dual_proc_macros {
433408
let host_result = match host_result {
434409
LoadResult::Previous(..) => {
435410
panic!("host and target proc macros must be loaded in lock-step")
@@ -439,7 +414,7 @@ impl<'a> CrateLoader<'a> {
439414
(target_result.unwrap(), Some(host_result))
440415
} else {
441416
(host_result, None)
442-
})
417+
}))
443418
}
444419

445420
fn resolve_crate<'b>(
@@ -452,25 +427,20 @@ impl<'a> CrateLoader<'a> {
452427
if dep.is_none() {
453428
self.used_extern_options.insert(name);
454429
}
455-
if !name.as_str().is_ascii() {
456-
self.sess
457-
.struct_span_err(
458-
span,
459-
&format!("cannot load a crate with a non-ascii name `{}`", name,),
460-
)
461-
.emit();
462-
}
463-
self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report())
430+
self.maybe_resolve_crate(name, dep_kind, dep)
431+
.unwrap_or_else(|err| err.report(self.sess, span))
464432
}
465433

466434
fn maybe_resolve_crate<'b>(
467435
&'b mut self,
468436
name: Symbol,
469-
span: Span,
470437
mut dep_kind: DepKind,
471438
dep: Option<(&'b CratePaths, &'b CrateDep)>,
472-
) -> Result<CrateNum, LoadError<'b>> {
439+
) -> Result<CrateNum, CrateError> {
473440
info!("resolving crate `{}`", name);
441+
if !name.as_str().is_ascii() {
442+
return Err(CrateError::NonAsciiName(name));
443+
}
474444
let (root, hash, host_hash, extra_filename, path_kind) = match dep {
475445
Some((root, dep)) => (
476446
Some(root),
@@ -494,18 +464,20 @@ impl<'a> CrateLoader<'a> {
494464
extra_filename,
495465
false, // is_host
496466
path_kind,
497-
span,
498467
root,
499468
Some(false), // is_proc_macro
500469
);
501470

502-
self.load(&mut locator)
503-
.map(|r| (r, None))
504-
.or_else(|| {
471+
match self.load(&mut locator)? {
472+
Some(res) => (res, None),
473+
None => {
505474
dep_kind = DepKind::MacrosOnly;
506-
self.load_proc_macro(&mut locator, path_kind)
507-
})
508-
.ok_or_else(move || LoadError::LocatorError(locator))?
475+
match self.load_proc_macro(&mut locator, path_kind)? {
476+
Some(res) => res,
477+
None => return Err(locator.into_error()),
478+
}
479+
}
480+
}
509481
};
510482

511483
match result {
@@ -518,14 +490,17 @@ impl<'a> CrateLoader<'a> {
518490
Ok(cnum)
519491
}
520492
(LoadResult::Loaded(library), host_library) => {
521-
Ok(self.register_crate(host_library, root, span, library, dep_kind, name))
493+
self.register_crate(host_library, root, library, dep_kind, name)
522494
}
523495
_ => panic!(),
524496
}
525497
}
526498

527-
fn load(&self, locator: &mut CrateLocator<'_>) -> Option<LoadResult> {
528-
let library = locator.maybe_load_library_crate()?;
499+
fn load(&self, locator: &mut CrateLocator<'_>) -> Result<Option<LoadResult>, CrateError> {
500+
let library = match locator.maybe_load_library_crate()? {
501+
Some(library) => library,
502+
None => return Ok(None),
503+
};
529504

530505
// In the case that we're loading a crate, but not matching
531506
// against a hash, we could load a crate which has the same hash
@@ -536,7 +511,7 @@ impl<'a> CrateLoader<'a> {
536511
// don't want to match a host crate against an equivalent target one
537512
// already loaded.
538513
let root = library.metadata.get_root();
539-
if locator.triple == self.sess.opts.target_triple {
514+
Ok(Some(if locator.triple == self.sess.opts.target_triple {
540515
let mut result = LoadResult::Loaded(library);
541516
self.cstore.iter_crate_data(|cnum, data| {
542517
if data.name() == root.name() && root.hash() == data.hash() {
@@ -545,10 +520,10 @@ impl<'a> CrateLoader<'a> {
545520
result = LoadResult::Previous(cnum);
546521
}
547522
});
548-
Some(result)
523+
result
549524
} else {
550-
Some(LoadResult::Loaded(library))
551-
}
525+
LoadResult::Loaded(library)
526+
}))
552527
}
553528

554529
fn update_extern_crate(&self, cnum: CrateNum, extern_crate: ExternCrate) {
@@ -569,53 +544,51 @@ impl<'a> CrateLoader<'a> {
569544
crate_root: &CrateRoot<'_>,
570545
metadata: &MetadataBlob,
571546
krate: CrateNum,
572-
span: Span,
573547
dep_kind: DepKind,
574-
) -> CrateNumMap {
548+
) -> Result<CrateNumMap, CrateError> {
575549
debug!("resolving deps of external crate");
576550
if crate_root.is_proc_macro_crate() {
577-
return CrateNumMap::new();
551+
return Ok(CrateNumMap::new());
578552
}
579553

580554
// The map from crate numbers in the crate we're resolving to local crate numbers.
581555
// We map 0 and all other holes in the map to our parent crate. The "additional"
582556
// self-dependencies should be harmless.
583-
std::iter::once(krate)
584-
.chain(crate_root.decode_crate_deps(metadata).map(|dep| {
585-
info!(
586-
"resolving dep crate {} hash: `{}` extra filename: `{}`",
587-
dep.name, dep.hash, dep.extra_filename
588-
);
589-
let dep_kind = match dep_kind {
590-
DepKind::MacrosOnly => DepKind::MacrosOnly,
591-
_ => dep.kind,
592-
};
593-
self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep)))
594-
}))
595-
.collect()
557+
let deps = crate_root.decode_crate_deps(metadata);
558+
let mut crate_num_map = CrateNumMap::with_capacity(1 + deps.len());
559+
crate_num_map.push(krate);
560+
for dep in deps {
561+
info!(
562+
"resolving dep crate {} hash: `{}` extra filename: `{}`",
563+
dep.name, dep.hash, dep.extra_filename
564+
);
565+
let dep_kind = match dep_kind {
566+
DepKind::MacrosOnly => DepKind::MacrosOnly,
567+
_ => dep.kind,
568+
};
569+
let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((root, &dep)))?;
570+
crate_num_map.push(cnum);
571+
}
572+
Ok(crate_num_map)
596573
}
597574

598575
fn dlsym_proc_macros(
599576
&self,
600577
path: &Path,
601578
disambiguator: CrateDisambiguator,
602-
span: Span,
603-
) -> &'static [ProcMacro] {
604-
use crate::dynamic_lib::DynamicLibrary;
605-
use std::env;
606-
579+
) -> Result<&'static [ProcMacro], CrateError> {
607580
// Make sure the path contains a / or the linker will search for it.
608581
let path = env::current_dir().unwrap().join(path);
609582
let lib = match DynamicLibrary::open(&path) {
610583
Ok(lib) => lib,
611-
Err(err) => self.sess.span_fatal(span, &err),
584+
Err(s) => return Err(CrateError::DlOpen(s)),
612585
};
613586

614587
let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator);
615588
let decls = unsafe {
616589
let sym = match lib.symbol(&sym) {
617590
Ok(f) => f,
618-
Err(err) => self.sess.span_fatal(span, &err),
591+
Err(s) => return Err(CrateError::DlSym(s)),
619592
};
620593
*(sym as *const &[ProcMacro])
621594
};
@@ -624,7 +597,7 @@ impl<'a> CrateLoader<'a> {
624597
// since the library can make things that will live arbitrarily long.
625598
std::mem::forget(lib);
626599

627-
decls
600+
Ok(decls)
628601
}
629602

630603
fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
@@ -952,7 +925,7 @@ impl<'a> CrateLoader<'a> {
952925
cnum
953926
}
954927

955-
pub fn maybe_process_path_extern(&mut self, name: Symbol, span: Span) -> Option<CrateNum> {
956-
self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()
928+
pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
929+
self.maybe_resolve_crate(name, DepKind::Explicit, None).ok()
957930
}
958931
}

0 commit comments

Comments
 (0)