Skip to content

Commit e91ad5f

Browse files
committed
Auto merge of rust-lang#92159 - petrochenkov:decoditer, r=cjgillot
rustc_metadata: Switch crate data iteration from a callback to iterator The iteration looks more conventional this way, and some allocations are avoided.
2 parents cc65bf3 + 046a682 commit e91ad5f

File tree

2 files changed

+70
-99
lines changed

2 files changed

+70
-99
lines changed

compiler/rustc_metadata/src/creader.rs

+67-94
Original file line numberDiff line numberDiff line change
@@ -102,30 +102,23 @@ struct CrateDump<'a>(&'a CStore);
102102
impl<'a> std::fmt::Debug for CrateDump<'a> {
103103
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104104
writeln!(fmt, "resolved crates:")?;
105-
// `iter_crate_data` does not allow returning values. Thus we use a mutable variable here
106-
// that aggregates the value (and any errors that could happen).
107-
let mut res = Ok(());
108-
self.0.iter_crate_data(|cnum, data| {
109-
res = res.and(
110-
try {
111-
writeln!(fmt, " name: {}", data.name())?;
112-
writeln!(fmt, " cnum: {}", cnum)?;
113-
writeln!(fmt, " hash: {}", data.hash())?;
114-
writeln!(fmt, " reqd: {:?}", data.dep_kind())?;
115-
let CrateSource { dylib, rlib, rmeta } = data.source();
116-
if let Some(dylib) = dylib {
117-
writeln!(fmt, " dylib: {}", dylib.0.display())?;
118-
}
119-
if let Some(rlib) = rlib {
120-
writeln!(fmt, " rlib: {}", rlib.0.display())?;
121-
}
122-
if let Some(rmeta) = rmeta {
123-
writeln!(fmt, " rmeta: {}", rmeta.0.display())?;
124-
}
125-
},
126-
);
127-
});
128-
res
105+
for (cnum, data) in self.0.iter_crate_data() {
106+
writeln!(fmt, " name: {}", data.name())?;
107+
writeln!(fmt, " cnum: {}", cnum)?;
108+
writeln!(fmt, " hash: {}", data.hash())?;
109+
writeln!(fmt, " reqd: {:?}", data.dep_kind())?;
110+
let CrateSource { dylib, rlib, rmeta } = data.source();
111+
if let Some(dylib) = dylib {
112+
writeln!(fmt, " dylib: {}", dylib.0.display())?;
113+
}
114+
if let Some(rlib) = rlib {
115+
writeln!(fmt, " rlib: {}", rlib.0.display())?;
116+
}
117+
if let Some(rmeta) = rmeta {
118+
writeln!(fmt, " rmeta: {}", rmeta.0.display())?;
119+
}
120+
}
121+
Ok(())
129122
}
130123
}
131124

@@ -154,12 +147,10 @@ impl CStore {
154147
self.metas[cnum] = Some(Lrc::new(data));
155148
}
156149

157-
crate fn iter_crate_data(&self, mut f: impl FnMut(CrateNum, &CrateMetadata)) {
158-
for (cnum, data) in self.metas.iter_enumerated() {
159-
if let Some(data) = data {
160-
f(cnum, data);
161-
}
162-
}
150+
crate fn iter_crate_data(&self) -> impl Iterator<Item = (CrateNum, &CrateMetadata)> {
151+
self.metas
152+
.iter_enumerated()
153+
.filter_map(|(cnum, data)| data.as_ref().map(|data| (cnum, &**data)))
163154
}
164155

165156
fn push_dependencies_in_postorder(&self, deps: &mut Vec<CrateNum>, cnum: CrateNum) {
@@ -178,7 +169,9 @@ impl CStore {
178169
crate fn crate_dependencies_in_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> {
179170
let mut deps = Vec::new();
180171
if cnum == LOCAL_CRATE {
181-
self.iter_crate_data(|cnum, _| self.push_dependencies_in_postorder(&mut deps, cnum));
172+
for (cnum, _) in self.iter_crate_data() {
173+
self.push_dependencies_in_postorder(&mut deps, cnum);
174+
}
182175
} else {
183176
self.push_dependencies_in_postorder(&mut deps, cnum);
184177
}
@@ -263,21 +256,17 @@ impl<'a> CrateLoader<'a> {
263256
}
264257

265258
fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> {
266-
let mut ret = None;
267-
self.cstore.iter_crate_data(|cnum, data| {
259+
for (cnum, data) in self.cstore.iter_crate_data() {
268260
if data.name() != name {
269261
tracing::trace!("{} did not match {}", data.name(), name);
270-
return;
262+
continue;
271263
}
272264

273265
match hash {
274-
Some(hash) if hash == data.hash() => {
275-
ret = Some(cnum);
276-
return;
277-
}
266+
Some(hash) if hash == data.hash() => return Some(cnum),
278267
Some(hash) => {
279268
debug!("actual hash {} did not match expected {}", hash, data.hash());
280-
return;
269+
continue;
281270
}
282271
None => {}
283272
}
@@ -301,10 +290,10 @@ impl<'a> CrateLoader<'a> {
301290
|| source.rlib.as_ref().map(|(p, _)| p) == Some(l)
302291
|| source.rmeta.as_ref().map(|(p, _)| p) == Some(l)
303292
}) {
304-
ret = Some(cnum);
293+
return Some(cnum);
305294
}
306295
}
307-
return;
296+
continue;
308297
}
309298

310299
// Alright, so we've gotten this far which means that `data` has the
@@ -321,15 +310,16 @@ impl<'a> CrateLoader<'a> {
321310
.expect("No sources for crate")
322311
.1;
323312
if kind.matches(prev_kind) {
324-
ret = Some(cnum);
313+
return Some(cnum);
325314
} else {
326315
debug!(
327316
"failed to load existing crate {}; kind {:?} did not match prev_kind {:?}",
328317
name, kind, prev_kind
329318
);
330319
}
331-
});
332-
ret
320+
}
321+
322+
None
333323
}
334324

335325
fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> {
@@ -339,17 +329,14 @@ impl<'a> CrateLoader<'a> {
339329
}
340330

341331
// 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
345-
other.hash() != root.hash()
346-
{
347-
// but different SVH
348-
res = Err(CrateError::SymbolConflictsOthers(root.name()));
332+
for (_, other) in self.cstore.iter_crate_data() {
333+
// Same stable crate id but different SVH
334+
if other.stable_crate_id() == root.stable_crate_id() && other.hash() != root.hash() {
335+
return Err(CrateError::SymbolConflictsOthers(root.name()));
349336
}
350-
});
337+
}
351338

352-
res
339+
Ok(())
353340
}
354341

355342
fn verify_no_stable_crate_id_hash_conflicts(
@@ -607,13 +594,14 @@ impl<'a> CrateLoader<'a> {
607594
locator.triple == self.sess.opts.target_triple || locator.is_proc_macro;
608595
Ok(Some(if can_reuse_cratenum {
609596
let mut result = LoadResult::Loaded(library);
610-
self.cstore.iter_crate_data(|cnum, data| {
597+
for (cnum, data) in self.cstore.iter_crate_data() {
611598
if data.name() == root.name() && root.hash() == data.hash() {
612599
assert!(locator.hash.is_none());
613600
info!("load success, going to previous cnum: {}", cnum);
614601
result = LoadResult::Previous(cnum);
602+
break;
615603
}
616-
});
604+
}
617605
result
618606
} else {
619607
LoadResult::Loaded(library)
@@ -711,7 +699,7 @@ impl<'a> CrateLoader<'a> {
711699
let mut needs_panic_runtime =
712700
self.sess.contains_name(&krate.attrs, sym::needs_panic_runtime);
713701

714-
self.cstore.iter_crate_data(|cnum, data| {
702+
for (cnum, data) in self.cstore.iter_crate_data() {
715703
needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime();
716704
if data.is_panic_runtime() {
717705
// Inject a dependency from all #![needs_panic_runtime] to this
@@ -721,7 +709,7 @@ impl<'a> CrateLoader<'a> {
721709
});
722710
runtime_found = runtime_found || data.dep_kind() == CrateDepKind::Explicit;
723711
}
724-
});
712+
}
725713

726714
// If an explicitly linked and matching panic runtime was found, or if
727715
// we just don't need one at all, then we're done here and there's
@@ -813,11 +801,9 @@ impl<'a> CrateLoader<'a> {
813801
// Check to see if we actually need an allocator. This desire comes
814802
// about through the `#![needs_allocator]` attribute and is typically
815803
// written down in liballoc.
816-
let mut needs_allocator = self.sess.contains_name(&krate.attrs, sym::needs_allocator);
817-
self.cstore.iter_crate_data(|_, data| {
818-
needs_allocator = needs_allocator || data.needs_allocator();
819-
});
820-
if !needs_allocator {
804+
if !self.sess.contains_name(&krate.attrs, sym::needs_allocator)
805+
&& !self.cstore.iter_crate_data().any(|(_, data)| data.needs_allocator())
806+
{
821807
return;
822808
}
823809

@@ -838,23 +824,19 @@ impl<'a> CrateLoader<'a> {
838824
// global allocator.
839825
let mut global_allocator =
840826
self.cstore.has_global_allocator.then(|| Symbol::intern("this crate"));
841-
self.cstore.iter_crate_data(|_, data| {
842-
if !data.has_global_allocator() {
843-
return;
844-
}
845-
match global_allocator {
846-
Some(other_crate) => {
847-
self.sess.err(&format!(
848-
"the `#[global_allocator]` in {} \
849-
conflicts with global \
850-
allocator in: {}",
827+
for (_, data) in self.cstore.iter_crate_data() {
828+
if data.has_global_allocator() {
829+
match global_allocator {
830+
Some(other_crate) => self.sess.err(&format!(
831+
"the `#[global_allocator]` in {} conflicts with global allocator in: {}",
851832
other_crate,
852833
data.name()
853-
));
834+
)),
835+
None => global_allocator = Some(data.name()),
854836
}
855-
None => global_allocator = Some(data.name()),
856837
}
857-
});
838+
}
839+
858840
if global_allocator.is_some() {
859841
self.cstore.allocator_kind = Some(AllocatorKind::Global);
860842
return;
@@ -864,19 +846,12 @@ impl<'a> CrateLoader<'a> {
864846
// allocator. At this point our allocator request is typically fulfilled
865847
// by the standard library, denoted by the `#![default_lib_allocator]`
866848
// attribute.
867-
let mut has_default = self.sess.contains_name(&krate.attrs, sym::default_lib_allocator);
868-
self.cstore.iter_crate_data(|_, data| {
869-
if data.has_default_lib_allocator() {
870-
has_default = true;
871-
}
872-
});
873-
874-
if !has_default {
849+
if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator)
850+
&& !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator())
851+
{
875852
self.sess.err(
876-
"no global memory allocator found but one is \
877-
required; link to std or \
878-
add `#[global_allocator]` to a static item \
879-
that implements the GlobalAlloc trait",
853+
"no global memory allocator found but one is required; link to std or add \
854+
`#[global_allocator]` to a static item that implements the GlobalAlloc trait",
880855
);
881856
}
882857
self.cstore.allocator_kind = Some(AllocatorKind::Default);
@@ -916,14 +891,12 @@ impl<'a> CrateLoader<'a> {
916891
// crate provided for this compile, but in order for this compilation to
917892
// be successfully linked we need to inject a dependency (to order the
918893
// crates on the command line correctly).
919-
self.cstore.iter_crate_data(|cnum, data| {
920-
if !needs_dep(data) {
921-
return;
894+
for (cnum, data) in self.cstore.iter_crate_data() {
895+
if needs_dep(data) {
896+
info!("injecting a dep from {} to {}", cnum, krate);
897+
data.add_dependency(krate);
922898
}
923-
924-
info!("injecting a dep from {} to {}", cnum, krate);
925-
data.add_dependency(krate);
926-
});
899+
}
927900
}
928901

929902
fn report_unused_deps(&mut self, krate: &ast::Crate) {

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ pub fn provide(providers: &mut Providers) {
372372
tcx.arena
373373
.alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE))
374374
},
375-
crates: |tcx, ()| tcx.arena.alloc_slice(&CStore::from_tcx(tcx).crates_untracked()),
375+
crates: |tcx, ()| tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).crates_untracked()),
376376

377377
..*providers
378378
};
@@ -449,10 +449,8 @@ impl CStore {
449449
self.get_crate_data(def.krate).def_kind(def.index)
450450
}
451451

452-
pub fn crates_untracked(&self) -> Vec<CrateNum> {
453-
let mut result = vec![];
454-
self.iter_crate_data(|cnum, _| result.push(cnum));
455-
result
452+
pub fn crates_untracked(&self) -> impl Iterator<Item = CrateNum> + '_ {
453+
self.iter_crate_data().map(|(cnum, _)| cnum)
456454
}
457455

458456
pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {

0 commit comments

Comments
 (0)