Skip to content

Fix links to extern types in rustdoc (fixes #78777) #79182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 21, 2020

Conversation

lochsh
Copy link
Contributor

@lochsh lochsh commented Nov 18, 2020

r? @jyn514
Fixes #78777.
The initial fix we tried was:

diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 8be9482acff..c4b7086fdb1 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -433,8 +433,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             Res::PrimTy(prim) => Some(
                 self.resolve_primitive_associated_item(prim, ns, module_id, item_name, item_str),
             ),
-            Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::TyAlias, did) => {
+            Res::Def(kind, did) if kind.ns() == Some(Namespace::TypeNS) => {
                 debug!("looking for associated item named {} for item {:?}", item_name, did);
+
                 // Checks if item_name belongs to `impl SomeItem`
                 let assoc_item = cx
                     .tcx

However, this caused traits to be matched, resulting in a panic when resolve_associated_trait_item is called further down in this function.

This PR also adds an error message for that panic. Currently it will look something like:

thread 'rustc' panicked at 'Not a type: DefIndex(8624)', compiler/rustc_metadata/src/rmeta/decoder.rs:951:32

I wasn't sure how to get a better debug output than DefIndex(...), and am open to suggestions.

@rust-highfive

This comment has been minimized.

@rust-highfive
Copy link
Contributor

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @jyn514 (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Nov 18, 2020
@lochsh lochsh changed the title Fix links to extern types in rustdoc (fixed #78777) Fix links to extern types in rustdoc (fixes #78777) Nov 18, 2020
@jyn514 jyn514 added A-intra-doc-links Area: Intra-doc links, the ability to link to items in docs by name T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Nov 18, 2020
Copy link
Member

@jyn514 jyn514 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! @petrochenkov might want to look at the rustc_metadata change, but the work on intra-doc links looks great :)

| DefKind::Union
| DefKind::Enum
| DefKind::TyAlias
| DefKind::ForeignTy,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be interested to see if the following cause crashes:

  • OpaqueTy
  • AssocTy

(I got these from https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def/enum.DefKind.html.)

AssocTy will definitely require larger refactors to fix properly (we'd have to call resolve_associated_trait_item recursively or something like that) but I think OpaqueTy may work without further changes. If so, please add a test case:

//! Link to [Opaque::Ty]
#![feature(type_alias_impl_trait)]

type Opaque = impl Trait;

pub trait Trait {
  type Ty;
}

impl Trait for () {
    type Ty = usize;
}

pub fn f() -> Opaque {
}

Copy link
Contributor Author

@lochsh lochsh Nov 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, I get the same behaviour for this test case whether DefKind::OpaqueTy is included in the match pattern or not:

warning: unresolved link to `Opaque::Ty`
 --> test.rs:1:14
  |
1 | //! Link to [Opaque::Ty]
  |              ^^^^^^^^^^ the type alias `Opaque` has no associated item named `Ty`
  |
  = note: `#[warn(broken_intra_doc_links)]` on by default

warning: 1 warning emitted

Here is the log output that seems relevant:

Opaque)))) in namespace TypeNS                                                                                                                                                                                                   [69/81]
DEBUG rustdoc::passes::collect_intra_doc_links looking for associated item named Ty for item DefId(0:3 ~ test[8787]::Opaque)
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "Send", args: AngleBracketed { args: [], bindings: []
 } }] }, param_names: None, did: DefId(2:2047 ~ core[fe86]::marker::Send), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "Sync", args: AngleBracketed { args: [], bindings: []
 } }] }, param_names: None, did: DefId(2:2059 ~ core[fe86]::marker::Sync), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "Unpin", args: AngleBracketed { args: [], bindings: [
] } }] }, param_names: None, did: DefId(2:2088 ~ core[fe86]::marker::Unpin), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "Freeze", args: AngleBracketed { args: [], bindings:
[] } }] }, param_names: None, did: DefId(2:2075 ~ core[fe86]::marker::Freeze), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "UnwindSafe", args: AngleBracketed { args: [], bindin
gs: [] } }] }, param_names: None, did: DefId(1:3925 ~ std[7f8a]::panic::UnwindSafe), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "RefUnwindSafe", args: AngleBracketed { args: [], bin
dings: [] } }] }, param_names: None, did: DefId(1:3926 ~ std[7f8a]::panic::RefUnwindSafe), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "From", args: AngleBracketed { args: [Type(Generic("T
"))], bindings: [] } }] }, param_names: None, did: DefId(2:1965 ~ core[fe86]::convert::From), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "Into", args: AngleBracketed { args: [Type(Generic("U
"))], bindings: [] } }] }, param_names: None, did: DefId(2:1962 ~ core[fe86]::convert::Into), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "Borrow", args: AngleBracketed { args: [Type(Generic(
"T"))], bindings: [] } }] }, param_names: None, did: DefId(2:1722 ~ core[fe86]::borrow::Borrow), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "BorrowMut", args: AngleBracketed { args: [Type(Gener
ic("T"))], bindings: [] } }] }, param_names: None, did: DefId(2:1725 ~ core[fe86]::borrow::BorrowMut), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "TryFrom", args: AngleBracketed { args: [Type(Generic
("U"))], bindings: [] } }] }, param_names: None, did: DefId(2:1972 ~ core[fe86]::convert::TryFrom), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "TryInto", args: AngleBracketed { args: [Type(Generic
("U"))], bindings: [] } }] }, param_names: None, did: DefId(2:1968 ~ core[fe86]::convert::TryInto), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering auto or blanket impl for trait Some(ResolvedPath { path: Path { global: false, res: Err, segments: [PathSegment { name: "Any", args: AngleBracketed { args: [], bindings: []
} }] }, param_names: None, did: DefId(2:2576 ~ core[fe86]::any::Any), is_generic: false })
DEBUG rustdoc::passes::collect_intra_doc_links considering traits {}
DEBUG rustdoc::passes::collect_intra_doc_links the candidates were []
DEBUG rustdoc::passes::collect_intra_doc_links got associated item kind None
DEBUG rustdoc::passes::collect_intra_doc_links Opaque::Ty resolved to Err(()) in namespace ValueNS
DEBUG rustdoc::passes::collect_intra_doc_links Opaque resolved to Ok((Path { span: test.rs:1:1: 1:1 (#0), segments: [PathSegment { ident: Opaque#0, id: NodeId(38), args: None }], tokens: None }, Def(TyAlias, DefId(0:3 ~ test[8787]::
Opaque)))) in namespace TypeNS
DEBUG rustdoc::passes::collect_intra_doc_links looking for associated item named Ty for item DefId(0:3 ~ test[8787]::Opaque)
DEBUG rustdoc::passes::collect_intra_doc_links considering traits {}
DEBUG rustdoc::passes::collect_intra_doc_links the candidates were []
DEBUG rustdoc::passes::collect_intra_doc_links got associated item kind None
DEBUG rustdoc::passes::collect_intra_doc_links looking for variants or fields named Ty for DefId(0:3 ~ test[8787]::Opaque)
DEBUG rustdoc::passes::collect_intra_doc_links looking for enum variant Opaque::Ty
DEBUG rustdoc::passes::collect_intra_doc_links Opaque resolved to Ok((Path { span: test.rs:1:1: 1:1 (#0), segments: [PathSegment { ident: Opaque#0, id: NodeId(39), args: None }], tokens: None }, Def(TyAlias, DefId(0:3 ~ test[8787]::
Opaque)))) in namespace TypeNS
DEBUG rustdoc::passes::collect_intra_doc_links found partial_res=Def(TyAlias, DefId(0:3 ~ test[8787]::Opaque))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, ok. The bug here is that considering traits {} should have Trait, but we can fix it later, I'm not sure this is actually something rustdoc should do since impl Trait is supposed to hide which type is being returned.

@jyn514 jyn514 added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 18, 2020
@jyn514
Copy link
Member

jyn514 commented Nov 21, 2020

@bors r+ rollup

Thanks for working on this!

@bors
Copy link
Collaborator

bors commented Nov 21, 2020

📌 Commit 32cd4bc has been approved by jyn514

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 21, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request Nov 21, 2020
Rollup of 8 pull requests

Successful merges:

 - rust-lang#77844 (clarify rules for ZST Boxes)
 - rust-lang#79067 (Refactor the abi handling code a bit)
 - rust-lang#79182 (Fix links to extern types in rustdoc (fixes rust-lang#78777))
 - rust-lang#79231 (Exhaustively match in variant count instrinsic)
 - rust-lang#79238 (Direct RUSTC_LOG (tracing/log) output to stderr instead of stdout.)
 - rust-lang#79256 (Fix typos)
 - rust-lang#79264 (Get rid of some doctree items)
 - rust-lang#79272 (Support building clone shims for arrays with generic size)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 5d428ca into rust-lang:master Nov 21, 2020
@rustbot rustbot added this to the 1.50.0 milestone Nov 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-intra-doc-links Area: Intra-doc links, the ability to link to items in docs by name S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

rustdoc: Referencing methods on extern_types does not resolve
5 participants