]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_metadata/src/creader.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_metadata / src / creader.rs
CommitLineData
1a4d82fc 1//! Validates all used crates and extern libraries and loads their metadata
223e47cc 2
9ffffee4 3use crate::errors;
3dfed10e 4use crate::locator::{CrateError, CrateLocator, CratePaths};
dfeec247 5use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
92a42be0 6
49aad941 7use rustc_ast::expand::allocator::{alloc_error_handler_name, global_fn_name, AllocatorKind};
3dfed10e 8use rustc_ast::{self as ast, *};
353b0b11 9use rustc_data_structures::fx::FxHashSet;
b7449926 10use rustc_data_structures::svh::Svh;
353b0b11 11use rustc_data_structures::sync::{MappedReadGuard, MappedWriteGuard, ReadGuard, WriteGuard};
dfeec247 12use rustc_expand::base::SyntaxExtension;
353b0b11 13use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, StableCrateIdMap, LOCAL_CRATE};
ba9703b0 14use rustc_hir::definitions::Definitions;
49aad941 15use rustc_index::IndexVec;
ba9703b0 16use rustc_middle::ty::TyCtxt;
f035d41b 17use rustc_session::config::{self, CrateType, ExternLocation};
9ffffee4 18use rustc_session::cstore::ExternCrateSource;
c295e0f8 19use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate};
04454e1e 20use rustc_session::lint;
ba9703b0
XL
21use rustc_session::output::validate_crate_name;
22use rustc_session::search_paths::PathKind;
136023e0 23use rustc_session::Session;
dfeec247
XL
24use rustc_span::edition::Edition;
25use rustc_span::symbol::{sym, Symbol};
26use rustc_span::{Span, DUMMY_SP};
83c7162d 27use rustc_target::spec::{PanicStrategy, TargetTriple};
dfeec247 28
e1599b0c 29use proc_macro::bridge::client::ProcMacro;
49aad941 30use std::error::Error;
3c0e092e 31use std::ops::Fn;
dfeec247 32use std::path::Path;
9ffffee4
FG
33use std::time::Duration;
34use std::{cmp, env, iter};
60c5eb7d 35
60c5eb7d 36pub struct CStore {
9ffffee4 37 metas: IndexVec<CrateNum, Option<Box<CrateMetadata>>>,
60c5eb7d
XL
38 injected_panic_runtime: Option<CrateNum>,
39 /// This crate needs an allocator and either provides it itself, or finds it in a dependency.
40 /// If the above is true, then this field denotes the kind of the found allocator.
41 allocator_kind: Option<AllocatorKind>,
487cf647
FG
42 /// This crate needs an allocation error handler and either provides it itself, or finds it in a dependency.
43 /// If the above is true, then this field denotes the kind of the found allocator.
44 alloc_error_handler_kind: Option<AllocatorKind>,
60c5eb7d
XL
45 /// This crate has a `#[global_allocator]` item.
46 has_global_allocator: bool,
487cf647
FG
47 /// This crate has a `#[alloc_error_handler]` item.
48 has_alloc_error_handler: bool,
6a06907d 49
353b0b11
FG
50 /// The interned [StableCrateId]s.
51 pub(crate) stable_crate_ids: StableCrateIdMap,
cdc7bbd5
XL
52
53 /// Unused externs of the crate
54 unused_externs: Vec<Symbol>,
e9174d1e
SL
55}
56
136023e0
XL
57impl std::fmt::Debug for CStore {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 f.debug_struct("CStore").finish_non_exhaustive()
60 }
61}
62
9ffffee4 63pub struct CrateLoader<'a, 'tcx: 'a> {
e74abb32 64 // Immutable configuration.
9ffffee4 65 tcx: TyCtxt<'tcx>,
e74abb32 66 // Mutable output.
9c376795
FG
67 cstore: &'a mut CStore,
68 used_extern_options: &'a mut FxHashSet<Symbol>,
223e47cc
LB
69}
70
9ffffee4
FG
71impl<'a, 'tcx> std::ops::Deref for CrateLoader<'a, 'tcx> {
72 type Target = TyCtxt<'tcx>;
73
74 fn deref(&self) -> &Self::Target {
75 &self.tcx
76 }
77}
78
60c5eb7d
XL
79pub enum LoadedMacro {
80 MacroDef(ast::Item, Edition),
81 ProcMacro(SyntaxExtension),
82}
83
923072b8 84pub(crate) struct Library {
60c5eb7d
XL
85 pub source: CrateSource,
86 pub metadata: MetadataBlob,
1a4d82fc 87}
e9174d1e 88
a7813a04 89enum LoadResult {
9e0c209e 90 Previous(CrateNum),
c30ab7b3 91 Loaded(Library),
a7813a04
XL
92}
93
74b04a01
XL
94/// A reference to `CrateMetadata` that can also give access to whole crate store when necessary.
95#[derive(Clone, Copy)]
923072b8 96pub(crate) struct CrateMetadataRef<'a> {
74b04a01
XL
97 pub cdata: &'a CrateMetadata,
98 pub cstore: &'a CStore,
99}
100
101impl std::ops::Deref for CrateMetadataRef<'_> {
102 type Target = CrateMetadata;
103
104 fn deref(&self) -> &Self::Target {
105 self.cdata
106 }
107}
108
3dfed10e
XL
109struct CrateDump<'a>(&'a CStore);
110
111impl<'a> std::fmt::Debug for CrateDump<'a> {
112 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113 writeln!(fmt, "resolved crates:")?;
a2a8927a
XL
114 for (cnum, data) in self.0.iter_crate_data() {
115 writeln!(fmt, " name: {}", data.name())?;
9c376795 116 writeln!(fmt, " cnum: {cnum}")?;
a2a8927a
XL
117 writeln!(fmt, " hash: {}", data.hash())?;
118 writeln!(fmt, " reqd: {:?}", data.dep_kind())?;
119 let CrateSource { dylib, rlib, rmeta } = data.source();
120 if let Some(dylib) = dylib {
121 writeln!(fmt, " dylib: {}", dylib.0.display())?;
122 }
123 if let Some(rlib) = rlib {
124 writeln!(fmt, " rlib: {}", rlib.0.display())?;
125 }
126 if let Some(rmeta) = rmeta {
127 writeln!(fmt, " rmeta: {}", rmeta.0.display())?;
128 }
129 }
130 Ok(())
3dfed10e 131 }
60c5eb7d
XL
132}
133
134impl CStore {
9ffffee4 135 pub fn from_tcx(tcx: TyCtxt<'_>) -> MappedReadGuard<'_, CStore> {
353b0b11
FG
136 ReadGuard::map(tcx.untracked().cstore.read(), |cstore| {
137 cstore.as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`")
9ffffee4 138 })
60c5eb7d
XL
139 }
140
353b0b11
FG
141 pub fn from_tcx_mut(tcx: TyCtxt<'_>) -> MappedWriteGuard<'_, CStore> {
142 WriteGuard::map(tcx.untracked().cstore.write(), |cstore| {
143 cstore.untracked_as_any().downcast_mut().expect("`tcx.cstore` is not a `CStore`")
144 })
145 }
146
147 fn intern_stable_crate_id(&mut self, root: &CrateRoot) -> Result<CrateNum, CrateError> {
148 assert_eq!(self.metas.len(), self.stable_crate_ids.len());
149 let num = CrateNum::new(self.stable_crate_ids.len());
150 if let Some(&existing) = self.stable_crate_ids.get(&root.stable_crate_id()) {
49aad941
FG
151 // Check for (potential) conflicts with the local crate
152 if existing == LOCAL_CRATE {
153 Err(CrateError::SymbolConflictsCurrent(root.name()))
154 } else if let Some(crate_name1) = self.metas[existing].as_ref().map(|data| data.name())
155 {
156 let crate_name0 = root.name();
353b0b11
FG
157 Err(CrateError::StableCrateIdCollision(crate_name0, crate_name1))
158 } else {
49aad941 159 Err(CrateError::NotFound(root.name()))
353b0b11
FG
160 }
161 } else {
162 self.metas.push(None);
163 self.stable_crate_ids.insert(root.stable_crate_id(), num);
164 Ok(num)
165 }
60c5eb7d
XL
166 }
167
923072b8
FG
168 pub fn has_crate_data(&self, cnum: CrateNum) -> bool {
169 self.metas[cnum].is_some()
170 }
171
172 pub(crate) fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> {
74b04a01 173 let cdata = self.metas[cnum]
dfeec247 174 .as_ref()
9c376795 175 .unwrap_or_else(|| panic!("Failed to get crate data for {cnum:?}"));
74b04a01 176 CrateMetadataRef { cdata, cstore: self }
60c5eb7d
XL
177 }
178
179 fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) {
180 assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry");
9ffffee4 181 self.metas[cnum] = Some(Box::new(data));
60c5eb7d
XL
182 }
183
923072b8 184 pub(crate) fn iter_crate_data(&self) -> impl Iterator<Item = (CrateNum, &CrateMetadata)> {
a2a8927a
XL
185 self.metas
186 .iter_enumerated()
487cf647 187 .filter_map(|(cnum, data)| data.as_deref().map(|data| (cnum, data)))
60c5eb7d
XL
188 }
189
190 fn push_dependencies_in_postorder(&self, deps: &mut Vec<CrateNum>, cnum: CrateNum) {
191 if !deps.contains(&cnum) {
192 let data = self.get_crate_data(cnum);
353b0b11 193 for dep in data.dependencies() {
60c5eb7d
XL
194 if dep != cnum {
195 self.push_dependencies_in_postorder(deps, dep);
196 }
197 }
198
199 deps.push(cnum);
200 }
201 }
202
923072b8 203 pub(crate) fn crate_dependencies_in_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> {
60c5eb7d
XL
204 let mut deps = Vec::new();
205 if cnum == LOCAL_CRATE {
a2a8927a
XL
206 for (cnum, _) in self.iter_crate_data() {
207 self.push_dependencies_in_postorder(&mut deps, cnum);
208 }
60c5eb7d
XL
209 } else {
210 self.push_dependencies_in_postorder(&mut deps, cnum);
211 }
212 deps
213 }
214
215 fn crate_dependencies_in_reverse_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> {
216 let mut deps = self.crate_dependencies_in_postorder(cnum);
217 deps.reverse();
218 deps
219 }
220
923072b8 221 pub(crate) fn injected_panic_runtime(&self) -> Option<CrateNum> {
60c5eb7d
XL
222 self.injected_panic_runtime
223 }
224
923072b8 225 pub(crate) fn allocator_kind(&self) -> Option<AllocatorKind> {
60c5eb7d
XL
226 self.allocator_kind
227 }
228
487cf647
FG
229 pub(crate) fn alloc_error_handler_kind(&self) -> Option<AllocatorKind> {
230 self.alloc_error_handler_kind
231 }
232
923072b8 233 pub(crate) fn has_global_allocator(&self) -> bool {
60c5eb7d
XL
234 self.has_global_allocator
235 }
cdc7bbd5 236
487cf647
FG
237 pub(crate) fn has_alloc_error_handler(&self) -> bool {
238 self.has_alloc_error_handler
239 }
240
cdc7bbd5 241 pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) {
04454e1e
FG
242 let json_unused_externs = tcx.sess.opts.json_unused_externs;
243
cdc7bbd5
XL
244 // We put the check for the option before the lint_level_at_node call
245 // because the call mutates internal state and introducing it
246 // leads to some ui tests failing.
04454e1e 247 if !json_unused_externs.is_enabled() {
cdc7bbd5
XL
248 return;
249 }
250 let level = tcx
251 .lint_level_at_node(lint::builtin::UNUSED_CRATE_DEPENDENCIES, rustc_hir::CRATE_HIR_ID)
252 .0;
253 if level != lint::Level::Allow {
254 let unused_externs =
255 self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::<Vec<_>>();
256 let unused_externs = unused_externs.iter().map(String::as_str).collect::<Vec<&str>>();
04454e1e
FG
257 tcx.sess.parse_sess.span_diagnostic.emit_unused_externs(
258 level,
259 json_unused_externs.is_loud(),
260 &unused_externs,
261 );
cdc7bbd5
XL
262 }
263 }
9c376795
FG
264
265 pub fn new(sess: &Session) -> CStore {
353b0b11 266 let mut stable_crate_ids = StableCrateIdMap::default();
9c376795
FG
267 stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
268 CStore {
269 // We add an empty entry for LOCAL_CRATE (which maps to zero) in
270 // order to make array indices in `metas` match with the
271 // corresponding `CrateNum`. This first entry will always remain
272 // `None`.
9ffffee4 273 metas: IndexVec::from_iter(iter::once(None)),
9c376795
FG
274 injected_panic_runtime: None,
275 allocator_kind: None,
276 alloc_error_handler_kind: None,
277 has_global_allocator: false,
278 has_alloc_error_handler: false,
279 stable_crate_ids,
280 unused_externs: Vec::new(),
281 }
282 }
60c5eb7d
XL
283}
284
9ffffee4 285impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
e74abb32 286 pub fn new(
9ffffee4 287 tcx: TyCtxt<'tcx>,
9c376795 288 cstore: &'a mut CStore,
9c376795 289 used_extern_options: &'a mut FxHashSet<Symbol>,
e74abb32 290 ) -> Self {
9ffffee4 291 CrateLoader { tcx, cstore, used_extern_options }
223e47cc 292 }
e74abb32 293
60c5eb7d 294 fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> {
a2a8927a 295 for (cnum, data) in self.cstore.iter_crate_data() {
dfeec247 296 if data.name() != name {
f2b60f7d 297 trace!("{} did not match {}", data.name(), name);
a2a8927a 298 continue;
dfeec247 299 }
223e47cc 300
1a4d82fc 301 match hash {
a2a8927a 302 Some(hash) if hash == data.hash() => return Some(cnum),
1b1a35ee
XL
303 Some(hash) => {
304 debug!("actual hash {} did not match expected {}", hash, data.hash());
a2a8927a 305 continue;
1b1a35ee 306 }
1a4d82fc
JJ
307 None => {}
308 }
223e47cc 309
85aaf69f
SL
310 // When the hash is None we're dealing with a top-level dependency
311 // in which case we may have a specification on the command line for
312 // this library. Even though an upstream library may have loaded
313 // something of the same name, we have to make sure it was loaded
314 // from the exact same location as well.
1a4d82fc
JJ
315 //
316 // We're also sure to compare *paths*, not actual byte slices. The
317 // `source` stores paths which are normalized which may be different
318 // from the strings on the command line.
74b04a01 319 let source = self.cstore.get_crate_data(cnum).cdata.source();
a2a8927a 320 if let Some(entry) = self.sess.opts.externs.get(name.as_str()) {
b7449926 321 // Only use `--extern crate_name=path` here, not `--extern crate_name`.
60c5eb7d
XL
322 if let Some(mut files) = entry.files() {
323 if files.any(|l| {
5869c6ff
XL
324 let l = l.canonicalized();
325 source.dylib.as_ref().map(|(p, _)| p) == Some(l)
326 || source.rlib.as_ref().map(|(p, _)| p) == Some(l)
327 || source.rmeta.as_ref().map(|(p, _)| p) == Some(l)
60c5eb7d 328 }) {
a2a8927a 329 return Some(cnum);
60c5eb7d 330 }
1a4d82fc 331 }
a2a8927a 332 continue;
85aaf69f
SL
333 }
334
335 // Alright, so we've gotten this far which means that `data` has the
336 // right name, we don't have a hash, and we don't have a --extern
337 // pointing for ourselves. We're still not quite yet done because we
338 // have to make sure that this crate was found in the crate lookup
339 // path (this is a top-level dependency) as we don't want to
340 // implicitly load anything inside the dependency lookup path.
dfeec247
XL
341 let prev_kind = source
342 .dylib
343 .as_ref()
344 .or(source.rlib.as_ref())
345 .or(source.rmeta.as_ref())
346 .expect("No sources for crate")
347 .1;
60c5eb7d 348 if kind.matches(prev_kind) {
a2a8927a 349 return Some(cnum);
1b1a35ee
XL
350 } else {
351 debug!(
352 "failed to load existing crate {}; kind {:?} did not match prev_kind {:?}",
353 name, kind, prev_kind
354 );
1a4d82fc 355 }
a2a8927a
XL
356 }
357
358 None
1a4d82fc 359 }
223e47cc 360
532ac7d7
XL
361 fn register_crate(
362 &mut self,
363 host_lib: Option<Library>,
e74abb32 364 root: Option<&CratePaths>,
532ac7d7 365 lib: Library,
3dfed10e 366 dep_kind: CrateDepKind,
dfeec247 367 name: Symbol,
3dfed10e 368 ) -> Result<CrateNum, CrateError> {
e74abb32
XL
369 let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate");
370
371 let Library { source, metadata } = lib;
372 let crate_root = metadata.get_root();
60c5eb7d 373 let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash());
b039eaaf 374
dfeec247 375 let private_dep =
49aad941 376 self.sess.opts.externs.get(name.as_str()).is_some_and(|e| e.is_private_dep);
48663c56 377
223e47cc 378 // Claim this crate number and cache it
353b0b11 379 let cnum = self.cstore.intern_stable_crate_id(&crate_root)?;
1a4d82fc 380
3dfed10e
XL
381 info!(
382 "register crate `{}` (cnum = {}. private_dep = {})",
383 crate_root.name(),
384 cnum,
385 private_dep
386 );
387
e74abb32 388 // Maintain a reference to the top most crate.
1a4d82fc 389 // Stash paths for top-most crate locally if necessary.
e74abb32
XL
390 let crate_paths;
391 let root = if let Some(root) = root {
392 root
1a4d82fc 393 } else {
60c5eb7d 394 crate_paths = CratePaths::new(crate_root.name(), source.clone());
e74abb32 395 &crate_paths
1a4d82fc 396 };
1a4d82fc 397
3dfed10e 398 let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, dep_kind)?;
1a4d82fc 399
60c5eb7d 400 let raw_proc_macros = if crate_root.is_proc_macro_crate() {
e74abb32
XL
401 let temp_root;
402 let (dlsym_source, dlsym_root) = match &host_lib {
dfeec247
XL
403 Some(host_lib) => (&host_lib.source, {
404 temp_root = host_lib.metadata.get_root();
405 &temp_root
406 }),
e74abb32
XL
407 None => (&source, &crate_root),
408 };
409 let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
136023e0 410 Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.stable_crate_id())?)
60c5eb7d
XL
411 } else {
412 None
413 };
e1599b0c 414
3dfed10e
XL
415 let crate_metadata = CrateMetadata::new(
416 self.sess,
04454e1e 417 &self.cstore,
3dfed10e
XL
418 metadata,
419 crate_root,
420 raw_proc_macros,
3b2f2976 421 cnum,
3dfed10e
XL
422 cnum_map,
423 dep_kind,
424 source,
425 private_dep,
426 host_hash,
dfeec247 427 );
1a4d82fc 428
3dfed10e
XL
429 self.cstore.set_crate_data(cnum, crate_metadata);
430
431 Ok(cnum)
1a4d82fc
JJ
432 }
433
dc9dc135 434 fn load_proc_macro<'b>(
e74abb32 435 &self,
60c5eb7d 436 locator: &mut CrateLocator<'b>,
532ac7d7 437 path_kind: PathKind,
c295e0f8 438 host_hash: Option<Svh>,
3dfed10e 439 ) -> Result<Option<(LoadResult, Option<Library>)>, CrateError>
532ac7d7 440 where
dc9dc135 441 'a: 'b,
532ac7d7 442 {
60c5eb7d 443 // Use a new crate locator so trying to load a proc macro doesn't affect the error
532ac7d7 444 // message we emit
60c5eb7d 445 let mut proc_macro_locator = locator.clone();
532ac7d7
XL
446
447 // Try to load a proc macro
c295e0f8 448 proc_macro_locator.is_proc_macro = true;
532ac7d7
XL
449
450 // Load the proc macro crate for the target
064997fb 451 let (locator, target_result) = if self.sess.opts.unstable_opts.dual_proc_macros {
532ac7d7
XL
452 proc_macro_locator.reset();
453 let result = match self.load(&mut proc_macro_locator)? {
3dfed10e
XL
454 Some(LoadResult::Previous(cnum)) => {
455 return Ok(Some((LoadResult::Previous(cnum), None)));
456 }
457 Some(LoadResult::Loaded(library)) => Some(LoadResult::Loaded(library)),
458 None => return Ok(None),
532ac7d7 459 };
c295e0f8 460 locator.hash = host_hash;
60c5eb7d 461 // Use the locator when looking for the host proc macro crate, as that is required
532ac7d7 462 // so we want it to affect the error message
60c5eb7d 463 (locator, result)
532ac7d7
XL
464 } else {
465 (&mut proc_macro_locator, None)
466 };
467
468 // Load the proc macro crate for the host
469
470 locator.reset();
c295e0f8 471 locator.is_proc_macro = true;
532ac7d7
XL
472 locator.target = &self.sess.host;
473 locator.triple = TargetTriple::from_triple(config::host_triple());
474 locator.filesearch = self.sess.host_filesearch(path_kind);
475
5e7ed085
FG
476 let Some(host_result) = self.load(locator)? else {
477 return Ok(None);
3dfed10e 478 };
532ac7d7 479
064997fb 480 Ok(Some(if self.sess.opts.unstable_opts.dual_proc_macros {
532ac7d7
XL
481 let host_result = match host_result {
482 LoadResult::Previous(..) => {
483 panic!("host and target proc macros must be loaded in lock-step")
484 }
dfeec247 485 LoadResult::Loaded(library) => library,
532ac7d7
XL
486 };
487 (target_result.unwrap(), Some(host_result))
488 } else {
489 (host_result, None)
3dfed10e 490 }))
532ac7d7
XL
491 }
492
9c376795
FG
493 fn resolve_crate(
494 &mut self,
b7449926 495 name: Symbol,
b7449926 496 span: Span,
3dfed10e 497 dep_kind: CrateDepKind,
a2a8927a 498 ) -> Option<CrateNum> {
c295e0f8 499 self.used_extern_options.insert(name);
a2a8927a
XL
500 match self.maybe_resolve_crate(name, dep_kind, None) {
501 Ok(cnum) => Some(cnum),
502 Err(err) => {
503 let missing_core =
504 self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
505 err.report(&self.sess, span, missing_core);
506 None
507 }
508 }
e74abb32
XL
509 }
510
511 fn maybe_resolve_crate<'b>(
512 &'b mut self,
513 name: Symbol,
3dfed10e 514 mut dep_kind: CrateDepKind,
e74abb32 515 dep: Option<(&'b CratePaths, &'b CrateDep)>,
3dfed10e 516 ) -> Result<CrateNum, CrateError> {
e74abb32 517 info!("resolving crate `{}`", name);
3dfed10e
XL
518 if !name.as_str().is_ascii() {
519 return Err(CrateError::NonAsciiName(name));
520 }
e74abb32
XL
521 let (root, hash, host_hash, extra_filename, path_kind) = match dep {
522 Some((root, dep)) => (
523 Some(root),
60c5eb7d
XL
524 Some(dep.hash),
525 dep.host_hash,
e74abb32 526 Some(&dep.extra_filename[..]),
60c5eb7d 527 PathKind::Dependency,
e74abb32
XL
528 ),
529 None => (None, None, None, None, PathKind::Crate),
530 };
476ff2be 531 let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
532ac7d7 532 (LoadResult::Previous(cnum), None)
476ff2be
SL
533 } else {
534 info!("falling back to a load");
9ffffee4 535 let metadata_loader = self.tcx.metadata_loader(()).borrow();
60c5eb7d
XL
536 let mut locator = CrateLocator::new(
537 self.sess,
9ffffee4 538 &**metadata_loader,
60c5eb7d 539 name,
48663c56
XL
540 hash,
541 extra_filename,
60c5eb7d
XL
542 false, // is_host
543 path_kind,
60c5eb7d 544 );
476ff2be 545
3dfed10e
XL
546 match self.load(&mut locator)? {
547 Some(res) => (res, None),
548 None => {
549 dep_kind = CrateDepKind::MacrosOnly;
c295e0f8 550 match self.load_proc_macro(&mut locator, path_kind, host_hash)? {
3dfed10e 551 Some(res) => res,
c295e0f8 552 None => return Err(locator.into_error(root.cloned())),
3dfed10e
XL
553 }
554 }
555 }
92a42be0
SL
556 };
557
558 match result {
532ac7d7 559 (LoadResult::Previous(cnum), None) => {
92a42be0 560 let data = self.cstore.get_crate_data(cnum);
60c5eb7d 561 if data.is_proc_macro_crate() {
3dfed10e 562 dep_kind = CrateDepKind::MacrosOnly;
e9174d1e 563 }
60c5eb7d 564 data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind));
e74abb32 565 Ok(cnum)
92a42be0 566 }
532ac7d7 567 (LoadResult::Loaded(library), host_library) => {
3dfed10e 568 self.register_crate(host_library, root, library, dep_kind, name)
1a4d82fc 569 }
dfeec247 570 _ => panic!(),
1a4d82fc
JJ
571 }
572 }
573
3dfed10e 574 fn load(&self, locator: &mut CrateLocator<'_>) -> Result<Option<LoadResult>, CrateError> {
5e7ed085
FG
575 let Some(library) = locator.maybe_load_library_crate()? else {
576 return Ok(None);
3dfed10e 577 };
a7813a04
XL
578
579 // In the case that we're loading a crate, but not matching
580 // against a hash, we could load a crate which has the same hash
581 // as an already loaded crate. If this is the case prevent
582 // duplicates by just using the first crate.
583 //
584 // Note that we only do this for target triple crates, though, as we
585 // don't want to match a host crate against an equivalent target one
586 // already loaded.
9e0c209e 587 let root = library.metadata.get_root();
136023e0
XL
588 // FIXME: why is this condition necessary? It was adding in #33625 but I
589 // don't know why and the original author doesn't remember ...
590 let can_reuse_cratenum =
c295e0f8 591 locator.triple == self.sess.opts.target_triple || locator.is_proc_macro;
136023e0 592 Ok(Some(if can_reuse_cratenum {
a7813a04 593 let mut result = LoadResult::Loaded(library);
a2a8927a 594 for (cnum, data) in self.cstore.iter_crate_data() {
60c5eb7d
XL
595 if data.name() == root.name() && root.hash() == data.hash() {
596 assert!(locator.hash.is_none());
9e0c209e 597 info!("load success, going to previous cnum: {}", cnum);
a7813a04 598 result = LoadResult::Previous(cnum);
a2a8927a 599 break;
a7813a04 600 }
a2a8927a 601 }
3dfed10e 602 result
a7813a04 603 } else {
3dfed10e
XL
604 LoadResult::Loaded(library)
605 }))
a7813a04
XL
606 }
607
60c5eb7d 608 fn update_extern_crate(&self, cnum: CrateNum, extern_crate: ExternCrate) {
54a0048b 609 let cmeta = self.cstore.get_crate_data(cnum);
60c5eb7d
XL
610 if cmeta.update_extern_crate(extern_crate) {
611 // Propagate the extern crate info to dependencies if it was updated.
612 let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate };
353b0b11 613 for dep_cnum in cmeta.dependencies() {
60c5eb7d
XL
614 self.update_extern_crate(dep_cnum, extern_crate);
615 }
54a0048b
SL
616 }
617 }
618
1a4d82fc 619 // Go through the crate metadata and load any crates that it references
dfeec247
XL
620 fn resolve_crate_deps(
621 &mut self,
622 root: &CratePaths,
923072b8 623 crate_root: &CrateRoot,
dfeec247
XL
624 metadata: &MetadataBlob,
625 krate: CrateNum,
3dfed10e
XL
626 dep_kind: CrateDepKind,
627 ) -> Result<CrateNumMap, CrateError> {
1a4d82fc 628 debug!("resolving deps of external crate");
60c5eb7d 629 if crate_root.is_proc_macro_crate() {
3dfed10e 630 return Ok(CrateNumMap::new());
476ff2be
SL
631 }
632
633 // The map from crate numbers in the crate we're resolving to local crate numbers.
634 // We map 0 and all other holes in the map to our parent crate. The "additional"
3157f602 635 // self-dependencies should be harmless.
3dfed10e
XL
636 let deps = crate_root.decode_crate_deps(metadata);
637 let mut crate_num_map = CrateNumMap::with_capacity(1 + deps.len());
638 crate_num_map.push(krate);
639 for dep in deps {
640 info!(
641 "resolving dep crate {} hash: `{}` extra filename: `{}`",
642 dep.name, dep.hash, dep.extra_filename
643 );
644 let dep_kind = match dep_kind {
645 CrateDepKind::MacrosOnly => CrateDepKind::MacrosOnly,
646 _ => dep.kind,
647 };
648 let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((root, &dep)))?;
649 crate_num_map.push(cnum);
650 }
651
652 debug!("resolve_crate_deps: cnum_map for {:?} is {:?}", krate, crate_num_map);
653 Ok(crate_num_map)
1a4d82fc
JJ
654 }
655
dfeec247
XL
656 fn dlsym_proc_macros(
657 &self,
658 path: &Path,
136023e0 659 stable_crate_id: StableCrateId,
3dfed10e 660 ) -> Result<&'static [ProcMacro], CrateError> {
c30ab7b3
SL
661 // Make sure the path contains a / or the linker will search for it.
662 let path = env::current_dir().unwrap().join(path);
9ffffee4 663 let lib = load_dylib(&path, 5).map_err(|err| CrateError::DlOpen(err))?;
c30ab7b3 664
a2a8927a
XL
665 let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id);
666 let sym = unsafe { lib.get::<*const &[ProcMacro]>(sym_name.as_bytes()) }
667 .map_err(|err| CrateError::DlSym(err.to_string()))?;
c30ab7b3 668
c30ab7b3
SL
669 // Intentionally leak the dynamic library. We can't ever unload it
670 // since the library can make things that will live arbitrarily long.
a2a8927a 671 let sym = unsafe { sym.into_raw() };
e1599b0c 672 std::mem::forget(lib);
a1dfa0c6 673
a2a8927a 674 Ok(unsafe { **sym })
1a4d82fc
JJ
675 }
676
a7813a04
XL
677 fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
678 // If we're only compiling an rlib, then there's no need to select a
679 // panic runtime, so we just skip this section entirely.
f9f354fc 680 let any_non_rlib = self.sess.crate_types().iter().any(|ct| *ct != CrateType::Rlib);
a7813a04
XL
681 if !any_non_rlib {
682 info!("panic runtime injection skipped, only generating rlib");
dfeec247 683 return;
a7813a04
XL
684 }
685
686 // If we need a panic runtime, we try to find an existing one here. At
687 // the same time we perform some general validation of the DAG we've got
688 // going such as ensuring everything has a compatible panic strategy.
689 //
690 // The logic for finding the panic runtime here is pretty much the same
691 // as the allocator case with the only addition that the panic strategy
692 // compilation mode also comes into play.
c30ab7b3 693 let desired_strategy = self.sess.panic_strategy();
a7813a04 694 let mut runtime_found = false;
353b0b11 695 let mut needs_panic_runtime = attr::contains_name(&krate.attrs, sym::needs_panic_runtime);
7cac9316 696
a2a8927a 697 for (cnum, data) in self.cstore.iter_crate_data() {
60c5eb7d
XL
698 needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime();
699 if data.is_panic_runtime() {
a7813a04
XL
700 // Inject a dependency from all #![needs_panic_runtime] to this
701 // #![panic_runtime] crate.
dfeec247
XL
702 self.inject_dependency_if(cnum, "a panic runtime", &|data| {
703 data.needs_panic_runtime()
704 });
3dfed10e 705 runtime_found = runtime_found || data.dep_kind() == CrateDepKind::Explicit;
a7813a04 706 }
a2a8927a 707 }
a7813a04
XL
708
709 // If an explicitly linked and matching panic runtime was found, or if
710 // we just don't need one at all, then we're done here and there's
711 // nothing else to do.
712 if !needs_panic_runtime || runtime_found {
dfeec247 713 return;
a7813a04
XL
714 }
715
716 // By this point we know that we (a) need a panic runtime and (b) no
717 // panic runtime was explicitly linked. Here we just load an appropriate
718 // default runtime for our panic strategy and then inject the
719 // dependencies.
720 //
721 // We may resolve to an already loaded crate (as the crate may not have
722 // been explicitly linked prior to this) and we may re-inject
723 // dependencies again, but both of those situations are fine.
724 //
725 // Also note that we have yet to perform validation of the crate graph
726 // in terms of everyone has a compatible panic runtime format, that's
727 // performed later as part of the `dependency_format` module.
728 let name = match desired_strategy {
3dfed10e
XL
729 PanicStrategy::Unwind => sym::panic_unwind,
730 PanicStrategy::Abort => sym::panic_abort,
a7813a04
XL
731 };
732 info!("panic runtime not found -- loading {}", name);
733
a2a8927a 734 let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
e74abb32 735 let data = self.cstore.get_crate_data(cnum);
a7813a04
XL
736
737 // Sanity check the loaded crate to ensure it is indeed a panic runtime
738 // and the panic strategy is indeed what we thought it was.
60c5eb7d 739 if !data.is_panic_runtime() {
9ffffee4 740 self.sess.emit_err(errors::CrateNotPanicRuntime { crate_name: name });
a7813a04 741 }
064997fb 742 if data.required_panic_strategy() != Some(desired_strategy) {
9ffffee4
FG
743 self.sess
744 .emit_err(errors::NoPanicStrategy { crate_name: name, strategy: desired_strategy });
a7813a04
XL
745 }
746
60c5eb7d 747 self.cstore.injected_panic_runtime = Some(cnum);
dfeec247 748 self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime());
8bb4bdeb
XL
749 }
750
fc512014 751 fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
064997fb 752 if self.sess.opts.unstable_opts.no_profiler_runtime
94222f64 753 || !(self.sess.instrument_coverage()
064997fb 754 || self.sess.opts.unstable_opts.profile
94222f64 755 || self.sess.opts.cg.profile_generate.enabled())
ba9703b0 756 {
136023e0
XL
757 return;
758 }
041b39d2 759
136023e0 760 info!("loading profiler");
fc512014 761
064997fb 762 let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime);
353b0b11 763 if name == sym::profiler_builtins && attr::contains_name(&krate.attrs, sym::no_core) {
9ffffee4 764 self.sess.emit_err(errors::ProfilerBuiltinsNeedsCore);
136023e0 765 }
041b39d2 766
a2a8927a 767 let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
136023e0
XL
768 let data = self.cstore.get_crate_data(cnum);
769
770 // Sanity check the loaded crate to ensure it is indeed a profiler runtime
771 if !data.is_profiler_runtime() {
9ffffee4 772 self.sess.emit_err(errors::NotProfilerRuntime { crate_name: name });
041b39d2
XL
773 }
774 }
775
60c5eb7d 776 fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
353b0b11 777 self.cstore.has_global_allocator = match &*global_allocator_spans(krate) {
416331ca 778 [span1, span2, ..] => {
9ffffee4 779 self.sess.emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
416331ca
XL
780 true
781 }
dfeec247 782 spans => !spans.is_empty(),
416331ca 783 };
353b0b11 784 self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(krate) {
487cf647 785 [span1, span2, ..] => {
9ffffee4
FG
786 self.sess
787 .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
487cf647
FG
788 true
789 }
790 spans => !spans.is_empty(),
791 };
041b39d2
XL
792
793 // Check to see if we actually need an allocator. This desire comes
794 // about through the `#![needs_allocator]` attribute and is typically
795 // written down in liballoc.
353b0b11 796 if !attr::contains_name(&krate.attrs, sym::needs_allocator)
a2a8927a
XL
797 && !self.cstore.iter_crate_data().any(|(_, data)| data.needs_allocator())
798 {
dfeec247 799 return;
041b39d2 800 }
e9174d1e 801
041b39d2
XL
802 // At this point we've determined that we need an allocator. Let's see
803 // if our compilation session actually needs an allocator based on what
804 // we're emitting.
29967ef6 805 let all_rlib = self.sess.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib));
a1dfa0c6 806 if all_rlib {
dfeec247 807 return;
041b39d2 808 }
e9174d1e 809
041b39d2
XL
810 // Ok, we need an allocator. Not only that but we're actually going to
811 // create an artifact that needs one linked in. Let's go find the one
812 // that we're going to link in.
e9174d1e 813 //
041b39d2
XL
814 // First up we check for global allocators. Look at the crate graph here
815 // and see what's a global allocator, including if we ourselves are a
816 // global allocator.
dfeec247
XL
817 let mut global_allocator =
818 self.cstore.has_global_allocator.then(|| Symbol::intern("this crate"));
a2a8927a
XL
819 for (_, data) in self.cstore.iter_crate_data() {
820 if data.has_global_allocator() {
821 match global_allocator {
5e7ed085 822 Some(other_crate) => {
9ffffee4 823 self.sess.emit_err(errors::ConflictingGlobalAlloc {
f2b60f7d
FG
824 crate_name: data.name(),
825 other_crate_name: other_crate,
826 });
5e7ed085 827 }
a2a8927a 828 None => global_allocator = Some(data.name()),
041b39d2 829 }
041b39d2 830 }
a2a8927a 831 }
487cf647
FG
832 let mut alloc_error_handler =
833 self.cstore.has_alloc_error_handler.then(|| Symbol::intern("this crate"));
834 for (_, data) in self.cstore.iter_crate_data() {
835 if data.has_alloc_error_handler() {
836 match alloc_error_handler {
837 Some(other_crate) => {
9ffffee4 838 self.sess.emit_err(errors::ConflictingAllocErrorHandler {
487cf647
FG
839 crate_name: data.name(),
840 other_crate_name: other_crate,
841 });
842 }
843 None => alloc_error_handler = Some(data.name()),
844 }
845 }
846 }
a2a8927a 847
041b39d2 848 if global_allocator.is_some() {
60c5eb7d 849 self.cstore.allocator_kind = Some(AllocatorKind::Global);
487cf647
FG
850 } else {
851 // Ok we haven't found a global allocator but we still need an
852 // allocator. At this point our allocator request is typically fulfilled
853 // by the standard library, denoted by the `#![default_lib_allocator]`
854 // attribute.
353b0b11 855 if !attr::contains_name(&krate.attrs, sym::default_lib_allocator)
487cf647
FG
856 && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator())
857 {
9ffffee4 858 self.sess.emit_err(errors::GlobalAllocRequired);
487cf647
FG
859 }
860 self.cstore.allocator_kind = Some(AllocatorKind::Default);
041b39d2 861 }
e9174d1e 862
487cf647
FG
863 if alloc_error_handler.is_some() {
864 self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Global);
865 } else {
866 // The alloc crate provides a default allocation error handler if
867 // one isn't specified.
487cf647 868 self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default);
e9174d1e 869 }
e9174d1e
SL
870 }
871
49aad941
FG
872 fn inject_forced_externs(&mut self) {
873 for (name, entry) in self.sess.opts.externs.iter() {
874 if entry.force {
875 let name_interned = Symbol::intern(name);
876 if !self.used_extern_options.contains(&name_interned) {
877 self.resolve_crate(name_interned, DUMMY_SP, CrateDepKind::Explicit);
878 }
879 }
880 }
881 }
882
dfeec247
XL
883 fn inject_dependency_if(
884 &self,
885 krate: CrateNum,
886 what: &str,
887 needs_dep: &dyn Fn(&CrateMetadata) -> bool,
888 ) {
a7813a04
XL
889 // don't perform this validation if the session has errors, as one of
890 // those errors may indicate a circular dependency which could cause
891 // this to stack overflow.
5e7ed085 892 if self.sess.has_errors().is_some() {
dfeec247 893 return;
a7813a04
XL
894 }
895
e9174d1e 896 // Before we inject any dependencies, make sure we don't inject a
a7813a04
XL
897 // circular dependency by validating that this crate doesn't
898 // transitively depend on any crates satisfying `needs_dep`.
60c5eb7d 899 for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) {
3157f602
XL
900 let data = self.cstore.get_crate_data(dep);
901 if needs_dep(&data) {
9ffffee4 902 self.sess.emit_err(errors::NoTransitiveNeedsDep {
f2b60f7d
FG
903 crate_name: self.cstore.get_crate_data(krate).name(),
904 needs_crate_name: what,
905 deps_crate_name: data.name(),
906 });
3157f602
XL
907 }
908 }
a7813a04
XL
909
910 // All crates satisfying `needs_dep` do not explicitly depend on the
911 // crate provided for this compile, but in order for this compilation to
912 // be successfully linked we need to inject a dependency (to order the
913 // crates on the command line correctly).
a2a8927a
XL
914 for (cnum, data) in self.cstore.iter_crate_data() {
915 if needs_dep(data) {
916 info!("injecting a dep from {} to {}", cnum, krate);
917 data.add_dependency(krate);
e9174d1e 918 }
a2a8927a 919 }
e9174d1e 920 }
e9174d1e 921
f9f354fc
XL
922 fn report_unused_deps(&mut self, krate: &ast::Crate) {
923 // Make a point span rather than covering the whole file
5e7ed085 924 let span = krate.spans.inner_span.shrink_to_lo();
f9f354fc 925 // Complain about anything left over
f035d41b
XL
926 for (name, entry) in self.sess.opts.externs.iter() {
927 if let ExternLocation::FoundInLibrarySearchDirectories = entry.location {
928 // Don't worry about pathless `--extern foo` sysroot references
929 continue;
930 }
49aad941 931 if entry.nounused_dep || entry.force {
04454e1e
FG
932 // We're not worried about this one
933 continue;
934 }
cdc7bbd5
XL
935 let name_interned = Symbol::intern(name);
936 if self.used_extern_options.contains(&name_interned) {
6a06907d
XL
937 continue;
938 }
939
940 // Got a real unused --extern
04454e1e 941 if self.sess.opts.json_unused_externs.is_enabled() {
cdc7bbd5
XL
942 self.cstore.unused_externs.push(name_interned);
943 continue;
944 }
945
04454e1e 946 self.sess.parse_sess.buffer_lint(
f9f354fc
XL
947 lint::builtin::UNUSED_CRATE_DEPENDENCIES,
948 span,
949 ast::CRATE_NODE_ID,
49aad941 950 format!(
f9f354fc
XL
951 "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
952 name,
9ffffee4 953 self.tcx.crate_name(LOCAL_CRATE),
f9f354fc
XL
954 name),
955 );
f9f354fc
XL
956 }
957 }
958
b7449926 959 pub fn postprocess(&mut self, krate: &ast::Crate) {
49aad941 960 self.inject_forced_externs();
fc512014 961 self.inject_profiler_runtime(krate);
041b39d2 962 self.inject_allocator_crate(krate);
c30ab7b3 963 self.inject_panic_runtime(krate);
c34b1796 964
f9f354fc 965 self.report_unused_deps(krate);
cdc7bbd5
XL
966
967 info!("{:?}", CrateDump(&self.cstore));
9e0c209e 968 }
c34b1796 969
b7449926 970 pub fn process_extern_crate(
e74abb32
XL
971 &mut self,
972 item: &ast::Item,
f035d41b 973 def_id: LocalDefId,
9ffffee4 974 definitions: &Definitions,
a2a8927a 975 ) -> Option<CrateNum> {
e74abb32 976 match item.kind {
0531ce1d 977 ast::ItemKind::ExternCrate(orig_name) => {
dfeec247
XL
978 debug!(
979 "resolving extern crate stmt. ident: {} orig_name: {:?}",
980 item.ident, orig_name
981 );
e74abb32 982 let name = match orig_name {
0531ce1d 983 Some(orig_name) => {
487cf647 984 validate_crate_name(self.sess, orig_name, Some(item.span));
0531ce1d 985 orig_name
ff7c6d11
XL
986 }
987 None => item.ident.name,
988 };
353b0b11 989 let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) {
3dfed10e 990 CrateDepKind::MacrosOnly
ff7c6d11 991 } else {
3dfed10e 992 CrateDepKind::Explicit
ff7c6d11
XL
993 };
994
a2a8927a 995 let cnum = self.resolve_crate(name, item.span, dep_kind)?;
476ff2be 996
9ffffee4 997 let path_len = definitions.def_path(def_id).data.len();
83c7162d
XL
998 self.update_extern_crate(
999 cnum,
1000 ExternCrate {
ba9703b0 1001 src: ExternCrateSource::Extern(def_id.to_def_id()),
83c7162d
XL
1002 span: item.span,
1003 path_len,
e74abb32 1004 dependency_of: LOCAL_CRATE,
83c7162d 1005 },
83c7162d 1006 );
a2a8927a 1007 Some(cnum)
c30ab7b3 1008 }
83c7162d 1009 _ => bug!(),
c34b1796 1010 }
c34b1796 1011 }
ff7c6d11 1012
a2a8927a
XL
1013 pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option<CrateNum> {
1014 let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit)?;
83c7162d
XL
1015
1016 self.update_extern_crate(
1017 cnum,
1018 ExternCrate {
1019 src: ExternCrateSource::Path,
1020 span,
1021 // to have the least priority in `update_extern_crate`
f035d41b 1022 path_len: usize::MAX,
e74abb32 1023 dependency_of: LOCAL_CRATE,
83c7162d 1024 },
83c7162d
XL
1025 );
1026
a2a8927a 1027 Some(cnum)
83c7162d
XL
1028 }
1029
3dfed10e
XL
1030 pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
1031 self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok()
1032 }
1033}
1034
353b0b11
FG
1035fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> {
1036 struct Finder {
3dfed10e
XL
1037 name: Symbol,
1038 spans: Vec<Span>,
1039 }
353b0b11 1040 impl<'ast> visit::Visitor<'ast> for Finder {
3dfed10e
XL
1041 fn visit_item(&mut self, item: &'ast ast::Item) {
1042 if item.ident.name == self.name
353b0b11 1043 && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
3dfed10e
XL
1044 {
1045 self.spans.push(item.span);
1046 }
1047 visit::walk_item(self, item)
1048 }
ff7c6d11 1049 }
3dfed10e 1050
49aad941 1051 let name = Symbol::intern(&global_fn_name(sym::alloc));
353b0b11 1052 let mut f = Finder { name, spans: Vec::new() };
3dfed10e
XL
1053 visit::walk_crate(&mut f, krate);
1054 f.spans
c34b1796 1055}
487cf647 1056
353b0b11
FG
1057fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec<Span> {
1058 struct Finder {
487cf647
FG
1059 name: Symbol,
1060 spans: Vec<Span>,
1061 }
353b0b11 1062 impl<'ast> visit::Visitor<'ast> for Finder {
487cf647
FG
1063 fn visit_item(&mut self, item: &'ast ast::Item) {
1064 if item.ident.name == self.name
353b0b11 1065 && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
487cf647
FG
1066 {
1067 self.spans.push(item.span);
1068 }
1069 visit::walk_item(self, item)
1070 }
1071 }
1072
49aad941 1073 let name = Symbol::intern(alloc_error_handler_name(AllocatorKind::Global));
353b0b11 1074 let mut f = Finder { name, spans: Vec::new() };
487cf647
FG
1075 visit::walk_crate(&mut f, krate);
1076 f.spans
1077}
9ffffee4
FG
1078
1079// On Windows the compiler would sometimes intermittently fail to open the
1080// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
1081// system still holds a lock on the file, so we retry a few times before calling it
1082// an error.
1083fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, String> {
1084 assert!(max_attempts > 0);
1085
1086 let mut last_error = None;
1087
1088 for attempt in 0..max_attempts {
1089 match unsafe { libloading::Library::new(&path) } {
1090 Ok(lib) => {
1091 if attempt > 0 {
1092 debug!(
1093 "Loaded proc-macro `{}` after {} attempts.",
1094 path.display(),
1095 attempt + 1
1096 );
1097 }
1098 return Ok(lib);
1099 }
1100 Err(err) => {
1101 // Only try to recover from this specific error.
1102 if !matches!(err, libloading::Error::LoadLibraryExW { .. }) {
1103 return Err(err.to_string());
1104 }
1105
1106 last_error = Some(err);
1107 std::thread::sleep(Duration::from_millis(100));
1108 debug!("Failed to load proc-macro `{}`. Retrying.", path.display());
1109 }
1110 }
1111 }
1112
1113 debug!("Failed to load proc-macro `{}` even after {} attempts.", path.display(), max_attempts);
49aad941
FG
1114
1115 let last_error = last_error.unwrap();
1116 let message = if let Some(src) = last_error.source() {
1117 format!("{last_error} ({src}) (retried {max_attempts} times)")
1118 } else {
1119 format!("{last_error} (retried {max_attempts} times)")
1120 };
1121 Err(message)
9ffffee4 1122}