Skip to content

Commit 6f8bec9

Browse files
committed
Warn if linking to a private item
1 parent 14e65d5 commit 6f8bec9

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

Diff for: src/librustdoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ extern crate rustc_metadata;
3434
extern crate rustc_middle;
3535
extern crate rustc_mir;
3636
extern crate rustc_parse;
37+
extern crate rustc_privacy;
3738
extern crate rustc_resolve;
3839
extern crate rustc_session;
3940
extern crate rustc_span as rustc_span;

Diff for: src/librustdoc/passes/collect_intra_doc_links.rs

+27-3
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
178178
let result = cx.enter_resolver(|resolver| {
179179
resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id)
180180
});
181+
debug!("{} resolved to {:?} in namespace {:?}", path_str, ns, result);
181182
let result = match result {
182183
Ok((_, Res::Err)) => Err(ErrorKind::ResolutionFailure),
183184
_ => result.map_err(|_| ErrorKind::ResolutionFailure),
@@ -202,7 +203,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
202203
}
203204
return Ok((res, Some(path_str.to_owned())));
204205
}
205-
_ => return Ok((res, extra_fragment.clone())),
206+
other => {
207+
debug!("failed to resolve {} in namespace {:?} (got {:?})", path_str, ns, other);
208+
debug!("extra_fragment is {:?}", extra_fragment);
209+
return Ok((res, extra_fragment.clone()));
210+
}
206211
};
207212

208213
if value != (ns == ValueNS) {
@@ -555,9 +560,11 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
555560
} else {
556561
(parts[0].to_owned(), None)
557562
};
563+
let resolved_self;
564+
let mut path_str;
558565
let (res, fragment) = {
559566
let mut kind = None;
560-
let mut path_str = if let Some(prefix) =
567+
path_str = if let Some(prefix) =
561568
["struct@", "enum@", "type@", "trait@", "union@"]
562569
.iter()
563570
.find(|p| link.starts_with(**p))
@@ -614,7 +621,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
614621
let base_node =
615622
if item.is_mod() && item.attrs.inner_docs { None } else { parent_node };
616623

617-
let resolved_self;
618624
// replace `Self` with suitable item's parent name
619625
if path_str.starts_with("Self::") {
620626
if let Some(ref name) = parent_name {
@@ -760,6 +766,24 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
760766
if let Res::PrimTy(_) = res {
761767
item.attrs.links.push((ori_link, None, fragment));
762768
} else {
769+
// ~~WRONG: TODO: I think this happens too late and we need to instead put this in `self.resolve`~~
770+
debug!("item {:?} resolved to {:?}", item, res);
771+
if let Some(local) = res.opt_def_id().and_then(|def_id| def_id.as_local()) {
772+
let hir_id = self.cx.tcx.hir().as_local_hir_id(local);
773+
if !self.cx.tcx.privacy_access_levels(rustc_hir::def_id::LOCAL_CRATE).is_exported(hir_id) {
774+
let item_name = item.name.as_deref().unwrap_or("<unknown>");
775+
build_diagnostic(
776+
cx,
777+
&item,
778+
path_str,
779+
&dox,
780+
link_range,
781+
&format!("public documentation for `{}` links to a private item", item_name),
782+
"this item is private",
783+
None,
784+
);
785+
}
786+
}
763787
let id = register_res(cx, res);
764788
item.attrs.links.push((ori_link, Some(id), fragment));
765789
}

0 commit comments

Comments
 (0)