Skip to content

Commit c213c68

Browse files
committed
box ResolutionFailures on the heap
This decreases the size of the `Result`s being returned, improving performance in the common case.
1 parent cd72d90 commit c213c68

File tree

1 file changed

+32
-37
lines changed

1 file changed

+32
-37
lines changed

src/librustdoc/passes/collect_intra_doc_links.rs

+32-37
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,16 @@ pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_>) -> Crate {
4848
}
4949

5050
enum ErrorKind<'a> {
51-
Resolve(ResolutionFailure<'a>),
51+
Resolve(Box<ResolutionFailure<'a>>),
5252
AnchorFailure(AnchorFailure),
5353
}
5454

55+
impl<'a> From<ResolutionFailure<'a>> for ErrorKind<'a> {
56+
fn from(err: ResolutionFailure<'a>) -> Self {
57+
ErrorKind::Resolve(box err)
58+
}
59+
}
60+
5561
#[derive(Debug)]
5662
enum ResolutionFailure<'a> {
5763
/// This resolved, but with the wrong namespace.
@@ -142,10 +148,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
142148
.expect("fold_item should ensure link is non-empty");
143149
let variant_name =
144150
// we're not sure this is a variant at all, so use the full string
145-
split.next().map(|f| Symbol::intern(f)).ok_or(ErrorKind::Resolve(ResolutionFailure::NotInScope{
151+
split.next().map(|f| Symbol::intern(f)).ok_or_else(|| ResolutionFailure::NotInScope {
146152
module_id,
147153
name: path_str.into(),
148-
}))?;
154+
})?;
149155
let path = split
150156
.next()
151157
.map(|f| {
@@ -156,21 +162,18 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
156162
}
157163
f.to_owned()
158164
})
159-
.ok_or(ErrorKind::Resolve(ResolutionFailure::NotInScope {
165+
.ok_or_else(|| ResolutionFailure::NotInScope {
160166
module_id,
161167
name: variant_name.to_string().into(),
162-
}))?;
168+
})?;
163169
let ty_res = cx
164170
.enter_resolver(|resolver| {
165171
resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id)
166172
})
167173
.map(|(_, res)| res)
168174
.unwrap_or(Res::Err);
169175
if let Res::Err = ty_res {
170-
return Err(ErrorKind::Resolve(ResolutionFailure::NotInScope {
171-
module_id,
172-
name: path.into(),
173-
}));
176+
return Err(ResolutionFailure::NotInScope { module_id, name: path.into() }.into());
174177
}
175178
let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
176179
match ty_res {
@@ -184,7 +187,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
184187
{
185188
// This is just to let `fold_item` know that this shouldn't be considered;
186189
// it's a bug for the error to make it to the user
187-
return Err(ErrorKind::Resolve(ResolutionFailure::Dummy));
190+
return Err(ResolutionFailure::Dummy.into());
188191
}
189192
match cx.tcx.type_of(did).kind() {
190193
ty::Adt(def, _) if def.is_enum() => {
@@ -197,10 +200,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
197200
)),
198201
))
199202
} else {
200-
Err(ErrorKind::Resolve(ResolutionFailure::NotAVariant(
201-
ty_res,
202-
variant_field_name,
203-
)))
203+
Err(ResolutionFailure::NotAVariant(ty_res, variant_field_name).into())
204204
}
205205
}
206206
_ => unreachable!(),
@@ -226,7 +226,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
226226
// Even with the shorter path, it didn't resolve, so say that.
227227
ResolutionFailure::NoAssocItem(ty_res, variant_name)
228228
};
229-
Err(ErrorKind::Resolve(kind))
229+
Err(kind.into())
230230
}
231231
}
232232
}
@@ -344,7 +344,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
344344
};
345345

346346
if value != (ns == ValueNS) {
347-
return Err(ErrorKind::Resolve(ResolutionFailure::WrongNamespace(res, ns)));
347+
return Err(ResolutionFailure::WrongNamespace(res, ns).into());
348348
}
349349
} else if let Some((path, prim)) = is_primitive(path_str, ns) {
350350
if extra_fragment.is_some() {
@@ -373,16 +373,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
373373
// So we can be sure that `rustc_resolve` was accurate when it said it wasn't resolved.
374374
.ok_or_else(|| {
375375
debug!("found no `::`, assumming {} was correctly not in scope", item_name);
376-
ErrorKind::Resolve(ResolutionFailure::NotInScope {
377-
module_id,
378-
name: item_name.to_string().into(),
379-
})
376+
ResolutionFailure::NotInScope { module_id, name: item_name.to_string().into() }
380377
})?;
381378

382379
if let Some((path, prim)) = is_primitive(&path_root, TypeNS) {
383-
let impls = primitive_impl(cx, &path).ok_or_else(|| {
384-
ErrorKind::Resolve(ResolutionFailure::NoPrimitiveImpl(prim, path_root.into()))
385-
})?;
380+
let impls = primitive_impl(cx, &path)
381+
.ok_or_else(|| ResolutionFailure::NoPrimitiveImpl(prim, path_root.into()))?;
386382
for &impl_ in impls {
387383
let link = cx
388384
.tcx
@@ -409,11 +405,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
409405
item_name,
410406
ns.descr()
411407
);
412-
return Err(ErrorKind::Resolve(ResolutionFailure::NoPrimitiveAssocItem {
408+
return Err(ResolutionFailure::NoPrimitiveAssocItem {
413409
res: prim,
414410
prim_name: path,
415411
assoc_item: item_name,
416-
}));
412+
}
413+
.into());
417414
}
418415

419416
let ty_res = cx
@@ -445,7 +442,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
445442
}
446443
ResolutionFailure::NotInScope { module_id, name: path_root.into() }
447444
});
448-
Err(ErrorKind::Resolve(kind))
445+
Err(kind.into())
449446
};
450447
}
451448
Ok(res) => res,
@@ -548,9 +545,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
548545
}
549546
} else {
550547
// We already know this isn't in ValueNS, so no need to check variant_field
551-
return Err(ErrorKind::Resolve(ResolutionFailure::NoAssocItem(
552-
ty_res, item_name,
553-
)));
548+
return Err(ResolutionFailure::NoAssocItem(ty_res, item_name).into());
554549
}
555550
}
556551
Res::Def(DefKind::Trait, did) => cx
@@ -585,12 +580,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
585580
if ns == Namespace::ValueNS {
586581
self.variant_field(path_str, current_item, module_id, extra_fragment)
587582
} else {
588-
Err(ErrorKind::Resolve(ResolutionFailure::NoAssocItem(ty_res, item_name)))
583+
Err(ResolutionFailure::NoAssocItem(ty_res, item_name).into())
589584
}
590585
})
591586
} else {
592587
debug!("attempting to resolve item without parent module: {}", path_str);
593-
Err(ErrorKind::Resolve(ResolutionFailure::NoParentItem))
588+
Err(ResolutionFailure::NoParentItem.into())
594589
}
595590
}
596591

@@ -611,7 +606,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
611606
let check_full_res_inner = |this: &Self, result: Result<Res, ErrorKind<'_>>| {
612607
let res = match result {
613608
Ok(res) => Some(res),
614-
Err(ErrorKind::Resolve(kind)) => kind.full_res(),
609+
Err(ErrorKind::Resolve(box kind)) => kind.full_res(),
615610
Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(res))) => {
616611
Some(res)
617612
}
@@ -626,7 +621,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
626621
};
627622
let check_full_res_macro = |this: &Self| {
628623
let result = this.macro_resolve(path_str, base_node);
629-
check_full_res_inner(this, result.map_err(ErrorKind::Resolve))
624+
check_full_res_inner(this, result.map_err(ErrorKind::from))
630625
};
631626
match ns {
632627
Namespace::MacroNS => check_full_res_macro(self),
@@ -970,7 +965,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
970965
match self.resolve(path_str, ns, &current_item, base_node, &extra_fragment)
971966
{
972967
Ok(res) => res,
973-
Err(ErrorKind::Resolve(mut kind)) => {
968+
Err(ErrorKind::Resolve(box mut kind)) => {
974969
// We only looked in one namespace. Try to give a better error if possible.
975970
if kind.full_res().is_none() {
976971
let other_ns = if ns == ValueNS { TypeNS } else { ValueNS };
@@ -1028,7 +1023,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
10281023
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
10291024
continue;
10301025
}
1031-
Err(ErrorKind::Resolve(kind)) => Err(kind),
1026+
Err(ErrorKind::Resolve(box kind)) => Err(kind),
10321027
},
10331028
value_ns: match self.resolve(
10341029
path_str,
@@ -1042,7 +1037,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
10421037
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
10431038
continue;
10441039
}
1045-
Err(ErrorKind::Resolve(kind)) => Err(kind),
1040+
Err(ErrorKind::Resolve(box kind)) => Err(kind),
10461041
}
10471042
.and_then(|(res, fragment)| {
10481043
// Constructors are picked up in the type namespace.
@@ -1816,7 +1811,7 @@ fn handle_variant(
18161811
let parent = if let Some(parent) = cx.tcx.parent(res.def_id()) {
18171812
parent
18181813
} else {
1819-
return Err(ErrorKind::Resolve(ResolutionFailure::NoParentItem));
1814+
return Err(ResolutionFailure::NoParentItem.into());
18201815
};
18211816
let parent_def = Res::Def(DefKind::Enum, parent);
18221817
let variant = cx.tcx.expect_variant_res(res);

0 commit comments

Comments
 (0)