Skip to content

Commit 64b5464

Browse files
committed
rustdoc: Use Fn trait sugar for external paths
Fix #19909
1 parent c639cf6 commit 64b5464

File tree

1 file changed

+46
-12
lines changed

1 file changed

+46
-12
lines changed

src/librustdoc/clean/mod.rs

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -515,21 +515,55 @@ impl Clean<Vec<TyParamBound>> for ty::ExistentialBounds {
515515
}
516516
}
517517

518-
fn external_path(cx: &DocContext, name: &str, substs: &subst::Substs) -> Path {
518+
fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
519+
substs: &subst::Substs) -> PathParameters {
520+
use rustc::middle::ty::sty;
519521
let lifetimes = substs.regions().get_slice(subst::TypeSpace)
520522
.iter()
521523
.filter_map(|v| v.clean(cx))
522524
.collect();
523525
let types = substs.types.get_slice(subst::TypeSpace).to_vec();
524-
let types = types.clean(cx);
526+
527+
match (trait_did, cx.tcx_opt()) {
528+
// Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
529+
(Some(did), Some(ref tcx)) if tcx.lang_items.fn_trait_kind(did).is_some() => {
530+
assert_eq!(types.len(), 2);
531+
let inputs = match types[0].sty {
532+
sty::ty_tup(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
533+
_ => {
534+
return PathParameters::AngleBracketed {
535+
lifetimes: lifetimes,
536+
types: types.clean(cx)
537+
}
538+
}
539+
};
540+
let output = match types[1].sty {
541+
sty::ty_tup(ref v) if v.is_empty() => None, // -> ()
542+
_ => Some(types[1].clean(cx))
543+
};
544+
PathParameters::Parenthesized {
545+
inputs: inputs,
546+
output: output
547+
}
548+
},
549+
(_, _) => {
550+
PathParameters::AngleBracketed {
551+
lifetimes: lifetimes,
552+
types: types.clean(cx),
553+
}
554+
}
555+
}
556+
}
557+
558+
// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
559+
// from Fn<(A, B,), C> to Fn(A, B) -> C
560+
fn external_path(cx: &DocContext, name: &str, trait_did: Option<ast::DefId>,
561+
substs: &subst::Substs) -> Path {
525562
Path {
526563
global: false,
527564
segments: vec![PathSegment {
528565
name: name.to_string(),
529-
params: PathParameters::AngleBracketed {
530-
lifetimes: lifetimes,
531-
types: types,
532-
}
566+
params: external_path_params(cx, trait_did, substs)
533567
}],
534568
}
535569
}
@@ -544,16 +578,16 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
544578
let (did, path) = match *self {
545579
ty::BoundSend =>
546580
(tcx.lang_items.send_trait().unwrap(),
547-
external_path(cx, "Send", &empty)),
581+
external_path(cx, "Send", None, &empty)),
548582
ty::BoundSized =>
549583
(tcx.lang_items.sized_trait().unwrap(),
550-
external_path(cx, "Sized", &empty)),
584+
external_path(cx, "Sized", None, &empty)),
551585
ty::BoundCopy =>
552586
(tcx.lang_items.copy_trait().unwrap(),
553-
external_path(cx, "Copy", &empty)),
587+
external_path(cx, "Copy", None, &empty)),
554588
ty::BoundSync =>
555589
(tcx.lang_items.sync_trait().unwrap(),
556-
external_path(cx, "Sync", &empty)),
590+
external_path(cx, "Sync", None, &empty)),
557591
};
558592
let fqn = csearch::get_item_path(tcx, did);
559593
let fqn = fqn.into_iter().map(|i| i.to_string()).collect();
@@ -586,7 +620,7 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
586620
let fqn = fqn.into_iter().map(|i| i.to_string())
587621
.collect::<Vec<String>>();
588622
let path = external_path(cx, fqn.last().unwrap().as_slice(),
589-
&self.substs);
623+
Some(self.def_id), &self.substs);
590624
cx.external_paths.borrow_mut().as_mut().unwrap().insert(self.def_id,
591625
(fqn, TypeTrait));
592626

@@ -1437,7 +1471,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
14371471
_ => TypeEnum,
14381472
};
14391473
let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
1440-
substs);
1474+
None, substs);
14411475
cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, kind));
14421476
ResolvedPath {
14431477
path: path,

0 commit comments

Comments
 (0)