Skip to content

Commit cad964a

Browse files
committed
Auto merge of #32461 - mitaa:rdoc-anchors, r=alexcrichton
rustdoc: Correct anchor for links to associated trait items fixes #28478 r? @alexcrichton
2 parents 44a77f6 + 4e0abdb commit cad964a

File tree

15 files changed

+473
-196
lines changed

15 files changed

+473
-196
lines changed

src/doc/style/features/traits/generics.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ explicitly implement to be used by this generic function.
2727
* _Inference_. Since the type parameters to generic functions can usually be
2828
inferred, generic functions can help cut down on verbosity in code where
2929
explicit conversions or other method calls would usually be necessary. See the
30-
[overloading/implicits use case](#use-case-limited-overloading-andor-implicit-conversions)
31-
below.
30+
overloading/implicits use case below.
3231
* _Precise types_. Because generics give a _name_ to the specific type
3332
implementing a trait, it is possible to be precise about places where that
3433
exact type is required or produced. For example, a function
@@ -51,7 +50,7 @@ explicitly implement to be used by this generic function.
5150
a `Vec<T>` contains elements of a single concrete type (and, indeed, the
5251
vector representation is specialized to lay these out in line). Sometimes
5352
heterogeneous collections are useful; see
54-
[trait objects](#use-case-trait-objects) below.
53+
trait objects below.
5554
* _Signature verbosity_. Heavy use of generics can bloat function signatures.
5655
**[Ed. note]** This problem may be mitigated by some language improvements; stay tuned.
5756

src/libcore/iter.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ pub trait Iterator {
434434
/// `None`. Once `None` is encountered, `count()` returns the number of
435435
/// times it called [`next()`].
436436
///
437-
/// [`next()`]: #method.next
437+
/// [`next()`]: #tymethod.next
438438
///
439439
/// # Overflow Behavior
440440
///
@@ -497,7 +497,7 @@ pub trait Iterator {
497497
/// This method will evaluate the iterator `n` times, discarding those elements.
498498
/// After it does so, it will call [`next()`] and return its value.
499499
///
500-
/// [`next()`]: #method.next
500+
/// [`next()`]: #tymethod.next
501501
///
502502
/// Like most indexing operations, the count starts from zero, so `nth(0)`
503503
/// returns the first value, `nth(1)` the second, and so on.

src/librustdoc/clean/inline.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rustc::middle::const_eval;
2626

2727
use core::DocContext;
2828
use doctree;
29-
use clean::{self, Attributes};
29+
use clean::{self, Attributes, GetDefId};
3030

3131
use super::{Clean, ToSource};
3232

@@ -414,15 +414,22 @@ pub fn build_impl(cx: &DocContext,
414414
clean::RegionBound(..) => unreachable!(),
415415
}
416416
});
417-
if let Some(clean::ResolvedPath { did, .. }) = trait_ {
418-
if Some(did) == cx.deref_trait_did.get() {
419-
super::build_deref_target_impls(cx, &trait_items, ret);
420-
}
417+
if trait_.def_id() == cx.deref_trait_did.get() {
418+
super::build_deref_target_impls(cx, &trait_items, ret);
421419
}
420+
421+
let provided = trait_.def_id().map(|did| {
422+
cx.tcx().provided_trait_methods(did)
423+
.into_iter()
424+
.map(|meth| meth.name.to_string())
425+
.collect()
426+
}).unwrap_or(HashSet::new());
427+
422428
ret.push(clean::Item {
423429
inner: clean::ImplItem(clean::Impl {
424430
unsafety: hir::Unsafety::Normal, // FIXME: this should be decoded
425431
derived: clean::detect_derived(&attrs),
432+
provided_trait_methods: provided,
426433
trait_: trait_,
427434
for_: ty.ty.clean(cx),
428435
generics: (&ty.generics, &predicates, subst::TypeSpace).clean(cx),

src/librustdoc/clean/mod.rs

+45-35
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use rustc::middle::stability;
4444

4545
use rustc_front::hir;
4646

47-
use std::collections::HashMap;
47+
use std::collections::{HashMap, HashSet};
4848
use std::path::PathBuf;
4949
use std::rc::Rc;
5050
use std::u32;
@@ -559,15 +559,9 @@ impl TyParamBound {
559559
fn is_sized_bound(&self, cx: &DocContext) -> bool {
560560
use rustc_front::hir::TraitBoundModifier as TBM;
561561
if let Some(tcx) = cx.tcx_opt() {
562-
let sized_did = match tcx.lang_items.sized_trait() {
563-
Some(did) => did,
564-
None => return false
565-
};
566-
if let TyParamBound::TraitBound(PolyTrait {
567-
trait_: Type::ResolvedPath { did, .. }, ..
568-
}, TBM::None) = *self {
569-
if did == sized_did {
570-
return true
562+
if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
563+
if trait_.def_id() == tcx.lang_items.sized_trait() {
564+
return true;
571565
}
572566
}
573567
}
@@ -724,15 +718,18 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
724718
}
725719
}
726720

727-
TraitBound(PolyTrait {
728-
trait_: ResolvedPath {
729-
path: path,
730-
typarams: None,
731-
did: self.def_id,
732-
is_generic: false,
721+
TraitBound(
722+
PolyTrait {
723+
trait_: ResolvedPath {
724+
path: path,
725+
typarams: None,
726+
did: self.def_id,
727+
is_generic: false,
728+
},
729+
lifetimes: late_bounds,
733730
},
734-
lifetimes: late_bounds
735-
}, hir::TraitBoundModifier::None)
731+
hir::TraitBoundModifier::None
732+
)
736733
}
737734
}
738735

@@ -932,7 +929,6 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
932929
&'a ty::GenericPredicates<'tcx>,
933930
subst::ParamSpace) {
934931
fn clean(&self, cx: &DocContext) -> Generics {
935-
use std::collections::HashSet;
936932
use self::WherePredicate as WP;
937933

938934
let (gens, preds, space) = *self;
@@ -1486,6 +1482,16 @@ pub enum TypeKind {
14861482
TypeTypedef,
14871483
}
14881484

1485+
pub trait GetDefId {
1486+
fn def_id(&self) -> Option<DefId>;
1487+
}
1488+
1489+
impl<T: GetDefId> GetDefId for Option<T> {
1490+
fn def_id(&self) -> Option<DefId> {
1491+
self.as_ref().and_then(|d| d.def_id())
1492+
}
1493+
}
1494+
14891495
impl Type {
14901496
pub fn primitive_type(&self) -> Option<PrimitiveType> {
14911497
match *self {
@@ -1499,7 +1505,9 @@ impl Type {
14991505
_ => None,
15001506
}
15011507
}
1508+
}
15021509

1510+
impl GetDefId for Type {
15031511
fn def_id(&self) -> Option<DefId> {
15041512
match *self {
15051513
ResolvedPath { did, .. } => Some(did),
@@ -1884,18 +1892,11 @@ impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
18841892
Item {
18851893
source: Span::empty(),
18861894
name: Some(field.name.clean(cx)),
1887-
attrs: Vec::new(),
1895+
attrs: cx.tcx().get_attrs(field.did).clean(cx),
18881896
visibility: Some(field.vis),
1889-
// FIXME: this is not accurate, we need an id for
1890-
// the specific field but we're using the id
1891-
// for the whole variant. Thus we read the
1892-
// stability from the whole variant as well.
1893-
// Struct variants are experimental and need
1894-
// more infrastructure work before we can get
1895-
// at the needed information here.
1896-
def_id: self.did,
1897-
stability: get_stability(cx, self.did),
1898-
deprecation: get_deprecation(cx, self.did),
1897+
def_id: field.did,
1898+
stability: get_stability(cx, field.did),
1899+
deprecation: get_deprecation(cx, field.did),
18991900
inner: StructFieldItem(
19001901
TypedStructField(field.unsubst_ty().clean(cx))
19011902
)
@@ -1908,7 +1909,7 @@ impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
19081909
name: Some(self.name.clean(cx)),
19091910
attrs: inline::load_attrs(cx, cx.tcx(), self.did),
19101911
source: Span::empty(),
1911-
visibility: Some(hir::Public),
1912+
visibility: Some(hir::Inherited),
19121913
def_id: self.did,
19131914
inner: VariantItem(Variant { kind: kind }),
19141915
stability: get_stability(cx, self.did),
@@ -2208,6 +2209,7 @@ impl Clean<ImplPolarity> for hir::ImplPolarity {
22082209
pub struct Impl {
22092210
pub unsafety: hir::Unsafety,
22102211
pub generics: Generics,
2212+
pub provided_trait_methods: HashSet<String>,
22112213
pub trait_: Option<Type>,
22122214
pub for_: Type,
22132215
pub items: Vec<Item>,
@@ -2227,12 +2229,19 @@ impl Clean<Vec<Item>> for doctree::Impl {
22272229

22282230
// If this impl block is an implementation of the Deref trait, then we
22292231
// need to try inlining the target's inherent impl blocks as well.
2230-
if let Some(ResolvedPath { did, .. }) = trait_ {
2231-
if Some(did) == cx.deref_trait_did.get() {
2232-
build_deref_target_impls(cx, &items, &mut ret);
2233-
}
2232+
if trait_.def_id() == cx.deref_trait_did.get() {
2233+
build_deref_target_impls(cx, &items, &mut ret);
22342234
}
22352235

2236+
let provided = trait_.def_id().and_then(|did| {
2237+
cx.tcx_opt().map(|tcx| {
2238+
tcx.provided_trait_methods(did)
2239+
.into_iter()
2240+
.map(|meth| meth.name.to_string())
2241+
.collect()
2242+
})
2243+
}).unwrap_or(HashSet::new());
2244+
22362245
ret.push(Item {
22372246
name: None,
22382247
attrs: self.attrs.clean(cx),
@@ -2244,6 +2253,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
22442253
inner: ImplItem(Impl {
22452254
unsafety: self.unsafety,
22462255
generics: self.generics.clean(cx),
2256+
provided_trait_methods: provided,
22472257
trait_: trait_,
22482258
for_: self.for_.clean(cx),
22492259
items: items,

src/librustdoc/html/markdown.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -607,15 +607,15 @@ mod tests {
607607
fn issue_17736() {
608608
let markdown = "# title";
609609
format!("{}", Markdown(markdown));
610-
reset_ids();
610+
reset_ids(true);
611611
}
612612

613613
#[test]
614614
fn test_header() {
615615
fn t(input: &str, expect: &str) {
616616
let output = format!("{}", Markdown(input));
617617
assert_eq!(output, expect);
618-
reset_ids();
618+
reset_ids(true);
619619
}
620620

621621
t("# Foo bar", "\n<h1 id='foo-bar' class='section-header'>\
@@ -654,7 +654,7 @@ mod tests {
654654
<a href='#panics-1'>Panics</a></h1>");
655655
};
656656
test();
657-
reset_ids();
657+
reset_ids(true);
658658
test();
659659
}
660660

0 commit comments

Comments
 (0)