Auto merge of #113958 - lukas-code:doc-links, r=GuillaumeGomez,petrochenkov
fix intra-doc links on nested `use` and `extern crate` items This PR fixes two rustdoc ICEs that happen if there are any intra-doc links on nested `use` or `extern crate` items, for example: ```rust /// Re-export [`fmt`] and [`io`]. pub use std::{fmt, io}; // "nested" use = use with braces /// Re-export [`std`]. pub extern crate std; ``` Nested use items were incorrectly considered private and therefore didn't have their intra-doc links resolved. I fixed this by always resolving intra-doc links for nested `use` items that are declared `pub`. <details> During AST->HIR lowering, nested `use` items are desugared like this: ```rust pub use std::{}; // "list stem" pub use std::fmt; pub use std::io; ``` Each of these HIR nodes has it's own effective visibility and the list stem is always considered private. To check the effective visibility of an AST node, the AST node is mapped to a HIR node with `Resolver::local_def_id`, which returns the (private) list stem for nested use items. </details> For `extern crate`, there was a hack in rustdoc that stored the `DefId` of the crate itself in the cleaned item, instead of the `DefId` of the `extern crate` item. This made rustdoc look at the resolved links of the extern crate's crate root instead of the `extern crate` item. I've removed this hack and instead translate the `DefId` in the appropriate places. As as side effect of fixing `extern crate`, i've turned ```rust #[doc(masked)] extern crate self as _; ``` into a no-op instead of hiding all trait impls. Proper verification for `doc(masked)` is included as a bonus. fixes https://github.com/rust-lang/rust/issues/113896
This commit is contained in:
commit
beef07fe8f
17 changed files with 246 additions and 144 deletions
|
@ -2244,13 +2244,12 @@ pub fn provide(providers: &mut Providers) {
|
||||||
tcx.resolutions(())
|
tcx.resolutions(())
|
||||||
.doc_link_resolutions
|
.doc_link_resolutions
|
||||||
.get(&def_id)
|
.get(&def_id)
|
||||||
.expect("no resolutions for a doc link")
|
.unwrap_or_else(|| span_bug!(tcx.def_span(def_id), "no resolutions for a doc link"))
|
||||||
},
|
},
|
||||||
doc_link_traits_in_scope: |tcx, def_id| {
|
doc_link_traits_in_scope: |tcx, def_id| {
|
||||||
tcx.resolutions(())
|
tcx.resolutions(()).doc_link_traits_in_scope.get(&def_id).unwrap_or_else(|| {
|
||||||
.doc_link_traits_in_scope
|
span_bug!(tcx.def_span(def_id), "no traits in scope for a doc link")
|
||||||
.get(&def_id)
|
})
|
||||||
.expect("no traits in scope for a doc link")
|
|
||||||
},
|
},
|
||||||
traits: |tcx, LocalCrate| {
|
traits: |tcx, LocalCrate| {
|
||||||
let mut traits = Vec::new();
|
let mut traits = Vec::new();
|
||||||
|
|
|
@ -211,6 +211,17 @@ passes_doc_keyword_not_mod =
|
||||||
passes_doc_keyword_only_impl =
|
passes_doc_keyword_only_impl =
|
||||||
`#[doc(keyword = "...")]` should be used on impl blocks
|
`#[doc(keyword = "...")]` should be used on impl blocks
|
||||||
|
|
||||||
|
passes_doc_masked_not_extern_crate_self =
|
||||||
|
this attribute cannot be applied to an `extern crate self` item
|
||||||
|
.label = not applicable on `extern crate self` items
|
||||||
|
.extern_crate_self_label = `extern crate self` defined here
|
||||||
|
|
||||||
|
passes_doc_masked_only_extern_crate =
|
||||||
|
this attribute can only be applied to an `extern crate` item
|
||||||
|
.label = only applicable on `extern crate` items
|
||||||
|
.not_an_extern_crate_label = not an `extern crate` item
|
||||||
|
.note = read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
|
||||||
|
|
||||||
passes_doc_test_literal = `#![doc(test(...)]` does not take a literal
|
passes_doc_test_literal = `#![doc(test(...)]` does not take a literal
|
||||||
|
|
||||||
passes_doc_test_takes_list =
|
passes_doc_test_takes_list =
|
||||||
|
|
|
@ -878,6 +878,44 @@ impl CheckAttrVisitor<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_doc_masked(
|
||||||
|
&self,
|
||||||
|
attr: &Attribute,
|
||||||
|
meta: &NestedMetaItem,
|
||||||
|
hir_id: HirId,
|
||||||
|
target: Target,
|
||||||
|
) -> bool {
|
||||||
|
if target != Target::ExternCrate {
|
||||||
|
self.tcx.emit_spanned_lint(
|
||||||
|
INVALID_DOC_ATTRIBUTES,
|
||||||
|
hir_id,
|
||||||
|
meta.span(),
|
||||||
|
errors::DocMaskedOnlyExternCrate {
|
||||||
|
attr_span: meta.span(),
|
||||||
|
item_span: (attr.style == AttrStyle::Outer)
|
||||||
|
.then(|| self.tcx.hir().span(hir_id)),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.tcx.extern_mod_stmt_cnum(hir_id.owner).is_none() {
|
||||||
|
self.tcx.emit_spanned_lint(
|
||||||
|
INVALID_DOC_ATTRIBUTES,
|
||||||
|
hir_id,
|
||||||
|
meta.span(),
|
||||||
|
errors::DocMaskedNotExternCrateSelf {
|
||||||
|
attr_span: meta.span(),
|
||||||
|
item_span: (attr.style == AttrStyle::Outer)
|
||||||
|
.then(|| self.tcx.hir().span(hir_id)),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks that an attribute is *not* used at the crate level. Returns `true` if valid.
|
/// Checks that an attribute is *not* used at the crate level. Returns `true` if valid.
|
||||||
fn check_attr_not_crate_level(
|
fn check_attr_not_crate_level(
|
||||||
&self,
|
&self,
|
||||||
|
@ -1048,6 +1086,17 @@ impl CheckAttrVisitor<'_> {
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sym::masked
|
||||||
|
if !self.check_doc_masked(
|
||||||
|
attr,
|
||||||
|
meta,
|
||||||
|
hir_id,
|
||||||
|
target,
|
||||||
|
) =>
|
||||||
|
{
|
||||||
|
is_valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
// no_default_passes: deprecated
|
// no_default_passes: deprecated
|
||||||
// passes: deprecated
|
// passes: deprecated
|
||||||
// plugins: removed, but rustdoc warns about it itself
|
// plugins: removed, but rustdoc warns about it itself
|
||||||
|
|
|
@ -267,6 +267,25 @@ pub struct DocInlineOnlyUse {
|
||||||
pub item_span: Option<Span>,
|
pub item_span: Option<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(LintDiagnostic)]
|
||||||
|
#[diag(passes_doc_masked_only_extern_crate)]
|
||||||
|
#[note]
|
||||||
|
pub struct DocMaskedOnlyExternCrate {
|
||||||
|
#[label]
|
||||||
|
pub attr_span: Span,
|
||||||
|
#[label(passes_not_an_extern_crate_label)]
|
||||||
|
pub item_span: Option<Span>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(LintDiagnostic)]
|
||||||
|
#[diag(passes_doc_masked_not_extern_crate_self)]
|
||||||
|
pub struct DocMaskedNotExternCrateSelf {
|
||||||
|
#[label]
|
||||||
|
pub attr_span: Span,
|
||||||
|
#[label(passes_extern_crate_self_label)]
|
||||||
|
pub item_span: Option<Span>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(passes_doc_attr_not_crate_level)]
|
#[diag(passes_doc_attr_not_crate_level)]
|
||||||
pub struct DocAttrNotCrateLevel<'a> {
|
pub struct DocAttrNotCrateLevel<'a> {
|
||||||
|
|
|
@ -549,6 +549,7 @@ enum MaybeExported<'a> {
|
||||||
Ok(NodeId),
|
Ok(NodeId),
|
||||||
Impl(Option<DefId>),
|
Impl(Option<DefId>),
|
||||||
ImplItem(Result<DefId, &'a Visibility>),
|
ImplItem(Result<DefId, &'a Visibility>),
|
||||||
|
NestedUse(&'a Visibility),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MaybeExported<'_> {
|
impl MaybeExported<'_> {
|
||||||
|
@ -559,7 +560,9 @@ impl MaybeExported<'_> {
|
||||||
trait_def_id.as_local()
|
trait_def_id.as_local()
|
||||||
}
|
}
|
||||||
MaybeExported::Impl(None) => return true,
|
MaybeExported::Impl(None) => return true,
|
||||||
MaybeExported::ImplItem(Err(vis)) => return vis.kind.is_pub(),
|
MaybeExported::ImplItem(Err(vis)) | MaybeExported::NestedUse(vis) => {
|
||||||
|
return vis.kind.is_pub();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
def_id.map_or(true, |def_id| r.effective_visibilities.is_exported(def_id))
|
def_id.map_or(true, |def_id| r.effective_visibilities.is_exported(def_id))
|
||||||
}
|
}
|
||||||
|
@ -2284,7 +2287,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
fn resolve_item(&mut self, item: &'ast Item) {
|
fn resolve_item(&mut self, item: &'ast Item) {
|
||||||
let mod_inner_docs =
|
let mod_inner_docs =
|
||||||
matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs);
|
matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs);
|
||||||
if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..)) {
|
if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..) | ItemKind::Use(..)) {
|
||||||
self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
|
self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2428,6 +2431,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::Use(ref use_tree) => {
|
ItemKind::Use(ref use_tree) => {
|
||||||
|
let maybe_exported = match use_tree.kind {
|
||||||
|
UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id),
|
||||||
|
UseTreeKind::Nested(_) => MaybeExported::NestedUse(&item.vis),
|
||||||
|
};
|
||||||
|
self.resolve_doc_links(&item.attrs, maybe_exported);
|
||||||
|
|
||||||
self.future_proof_import(use_tree);
|
self.future_proof_import(use_tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2643,15 +2643,12 @@ fn clean_extern_crate<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
|
vec![Item::from_def_id_and_parts(
|
||||||
vec![Item {
|
krate_owner_def_id,
|
||||||
name: Some(name),
|
Some(name),
|
||||||
attrs: Box::new(Attributes::from_ast(attrs)),
|
ExternCrateItem { src: orig_name },
|
||||||
item_id: crate_def_id.into(),
|
cx,
|
||||||
kind: Box::new(ExternCrateItem { src: orig_name }),
|
)]
|
||||||
cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
|
||||||
inline_stmt_id: Some(krate_owner_def_id),
|
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean_use_statement<'tcx>(
|
fn clean_use_statement<'tcx>(
|
||||||
|
|
|
@ -38,11 +38,15 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
|
||||||
for it in &module.items {
|
for it in &module.items {
|
||||||
// `compiler_builtins` should be masked too, but we can't apply
|
// `compiler_builtins` should be masked too, but we can't apply
|
||||||
// `#[doc(masked)]` to the injected `extern crate` because it's unstable.
|
// `#[doc(masked)]` to the injected `extern crate` because it's unstable.
|
||||||
if it.is_extern_crate()
|
if cx.tcx.is_compiler_builtins(it.item_id.krate()) {
|
||||||
&& (it.attrs.has_doc_flag(sym::masked)
|
|
||||||
|| cx.tcx.is_compiler_builtins(it.item_id.krate()))
|
|
||||||
{
|
|
||||||
cx.cache.masked_crates.insert(it.item_id.krate());
|
cx.cache.masked_crates.insert(it.item_id.krate());
|
||||||
|
} else if it.is_extern_crate()
|
||||||
|
&& it.attrs.has_doc_flag(sym::masked)
|
||||||
|
&& let Some(def_id) = it.item_id.as_def_id()
|
||||||
|
&& let Some(local_def_id) = def_id.as_local()
|
||||||
|
&& let Some(cnum) = cx.tcx.extern_mod_stmt_cnum(local_def_id)
|
||||||
|
{
|
||||||
|
cx.cache.masked_crates.insert(cnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc_metadata::creader::{CStore, LoadedMacro};
|
use rustc_metadata::creader::{CStore, LoadedMacro};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
@ -662,6 +662,14 @@ pub(crate) fn href_with_root_path(
|
||||||
// documented on their parent's page
|
// documented on their parent's page
|
||||||
tcx.parent(did)
|
tcx.parent(did)
|
||||||
}
|
}
|
||||||
|
DefKind::ExternCrate => {
|
||||||
|
// Link to the crate itself, not the `extern crate` item.
|
||||||
|
if let Some(local_did) = did.as_local() {
|
||||||
|
tcx.extern_mod_stmt_cnum(local_did).unwrap_or(LOCAL_CRATE).as_def_id()
|
||||||
|
} else {
|
||||||
|
did
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => did,
|
_ => did,
|
||||||
};
|
};
|
||||||
let cache = cx.cache();
|
let cache = cx.cache();
|
||||||
|
|
|
@ -14,7 +14,7 @@ use rustc_hir::def::{DefKind, Namespace, PerNS};
|
||||||
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
|
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
|
||||||
use rustc_hir::Mutability;
|
use rustc_hir::Mutability;
|
||||||
use rustc_middle::ty::{Ty, TyCtxt};
|
use rustc_middle::ty::{Ty, TyCtxt};
|
||||||
use rustc_middle::{bug, ty};
|
use rustc_middle::{bug, span_bug, ty};
|
||||||
use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
|
use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
|
||||||
use rustc_resolve::rustdoc::{strip_generics_from_path, MalformedGenerics};
|
use rustc_resolve::rustdoc::{strip_generics_from_path, MalformedGenerics};
|
||||||
use rustc_session::lint::Lint;
|
use rustc_session::lint::Lint;
|
||||||
|
@ -402,7 +402,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
||||||
// `doc_link_resolutions` is missing a `path_str`, that means that there are valid links
|
// `doc_link_resolutions` is missing a `path_str`, that means that there are valid links
|
||||||
// that are being missed. To fix the ICE, change
|
// that are being missed. To fix the ICE, change
|
||||||
// `rustc_resolve::rustdoc::attrs_to_preprocessed_links` to cache the link.
|
// `rustc_resolve::rustdoc::attrs_to_preprocessed_links` to cache the link.
|
||||||
.unwrap_or_else(|| panic!("no resolution for {:?} {:?} {:?}", path_str, ns, module_id))
|
.unwrap_or_else(|| {
|
||||||
|
span_bug!(
|
||||||
|
self.cx.tcx.def_span(item_id),
|
||||||
|
"no resolution for {path_str:?} {ns:?} {module_id:?}",
|
||||||
|
)
|
||||||
|
})
|
||||||
.and_then(|res| res.try_into().ok())
|
.and_then(|res| res.try_into().ok())
|
||||||
.or_else(|| resolve_primitive(path_str, ns));
|
.or_else(|| resolve_primitive(path_str, ns));
|
||||||
debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
|
debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
|
||||||
|
@ -963,6 +968,7 @@ fn preprocessed_markdown_links(s: &str) -> Vec<PreprocessedMarkdownLink> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LinkCollector<'_, '_> {
|
impl LinkCollector<'_, '_> {
|
||||||
|
#[instrument(level = "debug", skip_all)]
|
||||||
fn resolve_links(&mut self, item: &Item) {
|
fn resolve_links(&mut self, item: &Item) {
|
||||||
if !self.cx.render_options.document_private
|
if !self.cx.render_options.document_private
|
||||||
&& let Some(def_id) = item.item_id.as_def_id()
|
&& let Some(def_id) = item.item_id.as_def_id()
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Test that we don't ICE with broken links that don't show up in the docs.
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
// edition: 2021
|
||||||
|
|
||||||
|
/// [1]
|
||||||
|
//~^ WARN unresolved link to `1`
|
||||||
|
//~| WARN unresolved link to `1`
|
||||||
|
pub use {std, core};
|
||||||
|
|
||||||
|
/// [2]
|
||||||
|
pub use {};
|
||||||
|
|
||||||
|
/// [3]
|
||||||
|
//~^ WARN unresolved link to `3`
|
||||||
|
pub extern crate alloc;
|
|
@ -0,0 +1,27 @@
|
||||||
|
warning: unresolved link to `3`
|
||||||
|
--> $DIR/broken-link-in-unused-doc-string.rs:14:6
|
||||||
|
|
|
||||||
|
LL | /// [3]
|
||||||
|
| ^ no item named `3` in scope
|
||||||
|
|
|
||||||
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
|
= note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
|
||||||
|
|
||||||
|
warning: unresolved link to `1`
|
||||||
|
--> $DIR/broken-link-in-unused-doc-string.rs:6:6
|
||||||
|
|
|
||||||
|
LL | /// [1]
|
||||||
|
| ^ no item named `1` in scope
|
||||||
|
|
|
||||||
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
|
|
||||||
|
warning: unresolved link to `1`
|
||||||
|
--> $DIR/broken-link-in-unused-doc-string.rs:6:6
|
||||||
|
|
|
||||||
|
LL | /// [1]
|
||||||
|
| ^ no item named `1` in scope
|
||||||
|
|
|
||||||
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||||
|
|
||||||
|
warning: 3 warnings emitted
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
#![feature(doc_masked)]
|
||||||
|
|
||||||
|
#![doc(masked)]
|
||||||
|
//~^ ERROR this attribute can only be applied to an `extern crate` item
|
||||||
|
//~| WARN is being phased out
|
||||||
|
|
||||||
#[doc(test(no_crate_inject))]
|
#[doc(test(no_crate_inject))]
|
||||||
//~^ ERROR can only be applied at the crate level
|
//~^ ERROR can only be applied at the crate level
|
||||||
|
@ -30,3 +35,13 @@ pub mod bar {
|
||||||
//~^^ ERROR conflicting doc inlining attributes
|
//~^^ ERROR conflicting doc inlining attributes
|
||||||
//~| HELP remove one of the conflicting attributes
|
//~| HELP remove one of the conflicting attributes
|
||||||
pub use bar::baz;
|
pub use bar::baz;
|
||||||
|
|
||||||
|
#[doc(masked)]
|
||||||
|
//~^ ERROR this attribute can only be applied to an `extern crate` item
|
||||||
|
//~| WARN is being phased out
|
||||||
|
pub struct Masked;
|
||||||
|
|
||||||
|
#[doc(masked)]
|
||||||
|
//~^ ERROR this attribute cannot be applied to an `extern crate self` item
|
||||||
|
//~| WARN is being phased out
|
||||||
|
pub extern crate self as reexport;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: this attribute can only be applied at the crate level
|
error: this attribute can only be applied at the crate level
|
||||||
--> $DIR/invalid-doc-attr.rs:4:7
|
--> $DIR/invalid-doc-attr.rs:9:7
|
||||||
|
|
|
|
||||||
LL | #[doc(test(no_crate_inject))]
|
LL | #[doc(test(no_crate_inject))]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -19,7 +19,7 @@ LL | #![doc(test(no_crate_inject))]
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error: this attribute can only be applied to a `use` item
|
error: this attribute can only be applied to a `use` item
|
||||||
--> $DIR/invalid-doc-attr.rs:9:7
|
--> $DIR/invalid-doc-attr.rs:14:7
|
||||||
|
|
|
|
||||||
LL | #[doc(inline)]
|
LL | #[doc(inline)]
|
||||||
| ^^^^^^ only applicable on `use` items
|
| ^^^^^^ only applicable on `use` items
|
||||||
|
@ -32,7 +32,7 @@ LL | pub fn foo() {}
|
||||||
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
|
||||||
|
|
||||||
error: this attribute can only be applied at the crate level
|
error: this attribute can only be applied at the crate level
|
||||||
--> $DIR/invalid-doc-attr.rs:15:12
|
--> $DIR/invalid-doc-attr.rs:20:12
|
||||||
|
|
|
|
||||||
LL | #![doc(test(no_crate_inject))]
|
LL | #![doc(test(no_crate_inject))]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -42,7 +42,7 @@ LL | #![doc(test(no_crate_inject))]
|
||||||
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
|
||||||
|
|
||||||
error: conflicting doc inlining attributes
|
error: conflicting doc inlining attributes
|
||||||
--> $DIR/invalid-doc-attr.rs:28:7
|
--> $DIR/invalid-doc-attr.rs:33:7
|
||||||
|
|
|
|
||||||
LL | #[doc(inline)]
|
LL | #[doc(inline)]
|
||||||
| ^^^^^^ this attribute...
|
| ^^^^^^ this attribute...
|
||||||
|
@ -51,8 +51,43 @@ LL | #[doc(no_inline)]
|
||||||
|
|
|
|
||||||
= help: remove one of the conflicting attributes
|
= help: remove one of the conflicting attributes
|
||||||
|
|
||||||
|
error: this attribute can only be applied to an `extern crate` item
|
||||||
|
--> $DIR/invalid-doc-attr.rs:39:7
|
||||||
|
|
|
||||||
|
LL | #[doc(masked)]
|
||||||
|
| ^^^^^^ only applicable on `extern crate` items
|
||||||
|
...
|
||||||
|
LL | pub struct Masked;
|
||||||
|
| ----------------- not an `extern crate` item
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
|
= note: read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
|
||||||
|
|
||||||
|
error: this attribute cannot be applied to an `extern crate self` item
|
||||||
|
--> $DIR/invalid-doc-attr.rs:44:7
|
||||||
|
|
|
||||||
|
LL | #[doc(masked)]
|
||||||
|
| ^^^^^^ not applicable on `extern crate self` items
|
||||||
|
...
|
||||||
|
LL | pub extern crate self as reexport;
|
||||||
|
| --------------------------------- `extern crate self` defined here
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
|
|
||||||
|
error: this attribute can only be applied to an `extern crate` item
|
||||||
|
--> $DIR/invalid-doc-attr.rs:5:8
|
||||||
|
|
|
||||||
|
LL | #![doc(masked)]
|
||||||
|
| ^^^^^^ only applicable on `extern crate` items
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
|
= note: read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
|
||||||
|
|
||||||
error: this attribute can only be applied at the crate level
|
error: this attribute can only be applied at the crate level
|
||||||
--> $DIR/invalid-doc-attr.rs:19:11
|
--> $DIR/invalid-doc-attr.rs:24:11
|
||||||
|
|
|
|
||||||
LL | #[doc(test(no_crate_inject))]
|
LL | #[doc(test(no_crate_inject))]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -62,7 +97,7 @@ LL | #[doc(test(no_crate_inject))]
|
||||||
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
|
||||||
|
|
||||||
error: this attribute can only be applied to a `use` item
|
error: this attribute can only be applied to a `use` item
|
||||||
--> $DIR/invalid-doc-attr.rs:22:11
|
--> $DIR/invalid-doc-attr.rs:27:11
|
||||||
|
|
|
|
||||||
LL | #[doc(inline)]
|
LL | #[doc(inline)]
|
||||||
| ^^^^^^ only applicable on `use` items
|
| ^^^^^^ only applicable on `use` items
|
||||||
|
@ -74,5 +109,5 @@ LL | pub fn baz() {}
|
||||||
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
||||||
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
|
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
|
|
16
tests/rustdoc/intra-doc/nested-use.rs
Normal file
16
tests/rustdoc/intra-doc/nested-use.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// Regression test for issue #113896: Intra-doc links on nested use items.
|
||||||
|
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
// @has foo/struct.Foo.html
|
||||||
|
// @has - '//a[@href="struct.Foo.html"]' 'Foo'
|
||||||
|
// @has - '//a[@href="struct.Bar.html"]' 'Bar'
|
||||||
|
|
||||||
|
/// [`Foo`]
|
||||||
|
pub use m::{Foo, Bar};
|
||||||
|
|
||||||
|
mod m {
|
||||||
|
/// [`Bar`]
|
||||||
|
pub struct Foo;
|
||||||
|
pub struct Bar;
|
||||||
|
}
|
|
@ -4,10 +4,11 @@
|
||||||
// ignore-cross-compile
|
// ignore-cross-compile
|
||||||
|
|
||||||
// @has issue_33178/index.html
|
// @has issue_33178/index.html
|
||||||
// @has - //a/@title empty
|
// @has - '//a[@title="mod empty"][@href="../empty/index.html"]' empty
|
||||||
// @has - //a/@href ../empty/index.html
|
|
||||||
pub extern crate empty;
|
pub extern crate empty;
|
||||||
|
|
||||||
// @has - //a/@title variant_struct
|
// @has - '//a[@title="mod variant_struct"][@href="../variant_struct/index.html"]' variant_struct
|
||||||
// @has - //a/@href ../variant_struct/index.html
|
|
||||||
pub extern crate variant_struct as foo;
|
pub extern crate variant_struct as foo;
|
||||||
|
|
||||||
|
// @has - '//a[@title="mod issue_33178"][@href="index.html"]' self
|
||||||
|
pub extern crate self as bar;
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
#![crate_type = "lib"]
|
|
||||||
#![deny(warnings)]
|
|
||||||
|
|
||||||
#[doc(test(no_crate_inject))]
|
|
||||||
//~^ ERROR can only be applied at the crate level
|
|
||||||
//~| WARN is being phased out
|
|
||||||
//~| HELP to apply to the crate, use an inner attribute
|
|
||||||
//~| SUGGESTION !
|
|
||||||
#[doc(inline)]
|
|
||||||
//~^ ERROR can only be applied to a `use` item
|
|
||||||
//~| WARN is being phased out
|
|
||||||
pub fn foo() {}
|
|
||||||
|
|
||||||
pub mod bar {
|
|
||||||
#![doc(test(no_crate_inject))]
|
|
||||||
//~^ ERROR can only be applied at the crate level
|
|
||||||
//~| WARN is being phased out
|
|
||||||
|
|
||||||
#[doc(test(no_crate_inject))]
|
|
||||||
//~^ ERROR can only be applied at the crate level
|
|
||||||
//~| WARN is being phased out
|
|
||||||
#[doc(inline)]
|
|
||||||
//~^ ERROR can only be applied to a `use` item
|
|
||||||
//~| WARN is being phased out
|
|
||||||
pub fn baz() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(inline)]
|
|
||||||
#[doc(no_inline)]
|
|
||||||
//~^^ ERROR conflicting doc inlining attributes
|
|
||||||
//~| HELP remove one of the conflicting attributes
|
|
||||||
pub use bar::baz;
|
|
|
@ -1,78 +0,0 @@
|
||||||
error: this attribute can only be applied at the crate level
|
|
||||||
--> $DIR/invalid-doc-attr.rs:4:7
|
|
||||||
|
|
|
||||||
LL | #[doc(test(no_crate_inject))]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
|
||||||
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
|
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/invalid-doc-attr.rs:2:9
|
|
||||||
|
|
|
||||||
LL | #![deny(warnings)]
|
|
||||||
| ^^^^^^^^
|
|
||||||
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
|
|
||||||
help: to apply to the crate, use an inner attribute
|
|
||||||
|
|
|
||||||
LL | #![doc(test(no_crate_inject))]
|
|
||||||
| +
|
|
||||||
|
|
||||||
error: this attribute can only be applied to a `use` item
|
|
||||||
--> $DIR/invalid-doc-attr.rs:9:7
|
|
||||||
|
|
|
||||||
LL | #[doc(inline)]
|
|
||||||
| ^^^^^^ only applicable on `use` items
|
|
||||||
...
|
|
||||||
LL | pub fn foo() {}
|
|
||||||
| ------------ not a `use` item
|
|
||||||
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
|
||||||
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
|
|
||||||
|
|
||||||
error: this attribute can only be applied at the crate level
|
|
||||||
--> $DIR/invalid-doc-attr.rs:15:12
|
|
||||||
|
|
|
||||||
LL | #![doc(test(no_crate_inject))]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
|
||||||
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
|
|
||||||
|
|
||||||
error: conflicting doc inlining attributes
|
|
||||||
--> $DIR/invalid-doc-attr.rs:28:7
|
|
||||||
|
|
|
||||||
LL | #[doc(inline)]
|
|
||||||
| ^^^^^^ this attribute...
|
|
||||||
LL | #[doc(no_inline)]
|
|
||||||
| ^^^^^^^^^ ...conflicts with this attribute
|
|
||||||
|
|
|
||||||
= help: remove one of the conflicting attributes
|
|
||||||
|
|
||||||
error: this attribute can only be applied at the crate level
|
|
||||||
--> $DIR/invalid-doc-attr.rs:19:11
|
|
||||||
|
|
|
||||||
LL | #[doc(test(no_crate_inject))]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
|
||||||
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
|
|
||||||
|
|
||||||
error: this attribute can only be applied to a `use` item
|
|
||||||
--> $DIR/invalid-doc-attr.rs:22:11
|
|
||||||
|
|
|
||||||
LL | #[doc(inline)]
|
|
||||||
| ^^^^^^ only applicable on `use` items
|
|
||||||
...
|
|
||||||
LL | pub fn baz() {}
|
|
||||||
| ------------ not a `use` item
|
|
||||||
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
|
|
||||||
= note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
|
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue