Rust: Tracking issue for RFC 1946 - intra-rustdoc links

Created on 25 Jul 2017  ·  159Comments  ·  Source: rust-lang/rust

RFC: https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md
RFC PR: https://github.com/rust-lang/rfcs/pull/1946

Todo:

  • [x] Land https://github.com/rust-lang/rust/pull/47046
  • [x] Make it work with cross-crate imports (https://github.com/rust-lang/rust/issues/65983, https://github.com/rust-lang/rust/pull/47046#issuecomment-354824520)
  • [x] Make it work for proc macros https://github.com/rust-lang/rust/issues/73173
  • [x] Make it warn more on resolution errors (#49542)
  • [x] Make warnings/errors use better spans than the first line of docs

    • [x] first step: attribute (#51111)

    • [x] point to actual link in doc comment (#51391)

    • [x] Add lint for link resolution failure (#51382)

  • [x] Implied Shortcut Reference Links (https://github.com/rust-lang/rust/pull/48335)
  • [x] Enum variants and UFCS/associated methods (https://github.com/rust-lang/rust/pull/47701)
  • [x] Primitives (#49459)
  • [x] Use the right resolution scopes for inner doc comments on things that aren't modules (#55364)
  • [x] Handle fields and variants (#49512)

    • [x] Handle fields inside struct variants (#66704)

  • [x] Support Self (#49583)
  • [x] Write documentation (https://github.com/rust-lang/rust/issues/66000)
  • [x] Stabilization (#74430 - current impl is gated to only run on nightly, but does not require a feature gate)
  • [x] Handle methods from traits implementations
  • [x] Support anchors (#66675)
  • [ ] Support missing primitive types (such as slices) (#63351)
  • [x] Allow referring to Self::item (for cmp on Ord)
  • [x] Fix current crate linking when no module is provided in the path (for example, Foo won't link to the crate's Foo type for some reason)
  • [x] doc(hidden) reexports can break intra-doc links (https://github.com/rust-lang/rust/issues/73363)
  • [x] Support associated items in contexts other than documenting a trait method (#74489)

Other related issues:

  • [x] Suppress privacy errors with document-private-types (#74134, fix at https://github.com/rust-lang/rust/pull/74147)
  • [x] provide option to turn intra-link resolution errors into proper errors (#50082)
A-intra-doc-links B-RFC-approved C-tracking-issue T-dev-tools T-rustdoc

Most helpful comment

All 159 comments

Preliminary implementation notes:

Getting just the links from the markdown is relatively straightforward. You'll need to do this twice, to capture the behavior in both the Hoedown and Pulldown markdown renderers. Thankfully, each has a way of capturing links as they are parsed from the document. (While capturing the link you can also look for the "struct/enum/mod/macro/static/etc" marker to aid in resolution down the line.)

In Hoedown, the render function in src/librustdoc/html/markdown.rs captures all the events as they are captured. Hoedown uses a system of registering callbacks on the renderer configuration to capture each event separately. The link event and its related linkfn function pointer signature are already present in the file, so you would need to create and use that callback to capture and modify links as they appear.

For Pulldown, the parser is surfaced as an Iterator of events. There are already a handful of iterator wrappers present in html/markdown.rs, so adding another one (and using it in the impl fmt::Display for Markdown farther down) shouldn't be a big deal. I'm... honestly not that familiar with how Pulldown represents link definitions in its Event/Tag enums, so more research would be needed to effectively get link text for that.

Now, with the links in hand, you need to do two things, neither of which i know offhand since they involve interfacing with the compiler:

  • Attempt to parse the link as a path (if it's not a valid Rust path, just emit the URL as-is and skip the rest of this)
  • Resolve the path in the "current" module (emit a warning if resolution fails)

Presumably there's a way to make the resolution come up with a DefId? Even after cleaning the AST, rustdoc still deals in those, so if that's the case there are ways to map that to the proper relative link.

I've got a WIP going on in https://github.com/manishearth/rust/tree/correct-resolver-fail , which works off of Misdreavus' WIP (they did most of the work).

Note that that branch is now live as https://github.com/rust-lang/rust/pull/47046, which i'm polishing and finishing up.

Note for people watching this thread but not https://github.com/rust-lang/rust/pull/47046: We're trying to wind that PR down to get a minimal version landed, so an initial implementation is fairly close.

One thing that appears to not work in #47046 (and I don't think is ever explicitly addressed in the RFC) is how to link to primitives like u32 or bool.

Yeah I have to investigate that

@killercup @QuietMisdreavus should we turn the error into a warning ? I don't like the idea of crate docs breaking because someone introduced a name into a glob import

@Manishearth does rustdoc have some idea of "lint levels"? What are the current deprecation warnings? Just println!s?

We can just struct_span_warn instead. rustc can emit warnings not tied to actual warning names. There are no lint levels.

Alright, let's do that for now. In the end I'd really like to have a way to
check the docs for errors but that's a more involved/fragile process I
imagine.

Manish Goregaokar notifications@github.com schrieb am Mi. 24. Jan. 2018
um 09:17:

We can just struct_span_warn instead. rustc can emit warnings not tied to
actual warning names. There are no lint levels.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/issues/43466#issuecomment-360053947,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AABOXw-H_Wyi-zoTpfv_fqi-ovlRv5a9ks5tNucqgaJpZM4OiBhy
.

Shortcut links being implemented at https://github.com/rust-lang/rust/pull/48335

If [std::convert::Into] will work as part of this RFC, will [std::convert::Into#generic-implementations] also work for linking to specific sections of that documentation?

Not currently. This can be implemented.

९ मार्च, २०१८ २:१४ म.उ. रोजी, "Sunjay Varma" notifications@github.com ने
लिहिले:

If [std::convert::Into] will work as part of this RFC, will
[std::convert::Into#generic-implementations] also work for linking to
specific sections of that documentation?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/issues/43466#issuecomment-371960444,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABivSDtAilMsFhw14CgjbtGG_KChGK7nks5tcv7hgaJpZM4OiBhy
.

I can't seem to get links to struct fields to work (either [MyStruct.field] or [MyStruct::field]). Am I missing something, or is it not implemented? If not, is it planned to be supported?

MyStruct::field should work

Oh, wait, no, struct fields don't work yet. We can add those later.

Was their any discussion about linking to dev-dependencies? For example in a facade heavy crate like futures it may be that some sub-crates want to link back to the prelude at ::futures::prelude directly. One way this could be done is simply including dev-dependencies in the doc build and relying on the implicit use of crates in Edition 2018.

Edge-case error I found: apparently, if a crate is marked as no_std, then this also applies to autolinks; I can't link f64::powi in a no_std crate even if the crate itself doesn't need it. This seems like a relatively easy bug to fix imho.

Based on a conversation just now: It would be cool if we could add in a section to pages to collect "back-links", or a listing of pages that contain doc-links to a given page.

One thing I would really love was if [method] in the documentation for some type T linked to [T::method] automatically. It makes it a little easier to write documentation text that flows nicely and doesn't seem awkward (I _know_ you're talking about a method on T, that's the text I'm reading!)

@jonhoo

That would be ambiguous though, if a top level item existed with the same name.

I would personally be happy if [Self::method] worked.

Maybe [method][T::method] works today? (As in, [text shown][link-or-reference-identifier].)

We could establish a priority to resolve ambiguities.

@crumblingstatue Self::method is nice, though I would want it to be rendered as just method. This shows up a lot in documentation of the form:

/// To make a new `Foo`, you likely want to use [`from_bar`] to wrap an existing [`Bar`].
/// You can also use [`mock`] to get a fake `Foo` for use in tests.
struct Foo;

If these cases, Foo::from_bar and Foo::mock would seem a bit redundant, and make the sentence harder to follow.

@jonhoo I think it should be fine if it was written as [Self::method], as it is unambiguous, but rustdoc would recognize that it's a method, and rendered it as just method. If the user really wanted to keep the Self:: part in the rendered version for some reason, they could just write [Self::method](Self::method).

EDIT: Jeezus, I was on phone, and couldn't find the backtick on the virtual keyboard.

In the futures crate we get a lot of intra doc resolution warnings. The curious thing is that these warnings are always for another crate than the crate for which the docs are currently being built.

E.g. futures-util-preview on its own builds with no warnings. However, futures-executor-preview, which depends on futures-util-preview, builds with warnings from futures-util-preview.

https://travis-ci.org/rust-lang-nursery/futures-rs/jobs/412557090

Should "point to actual link in doc comment" be checked off since #51391 is merged?

Also "Add lint for link resolution failure" (#51382)

And looks like "Support Self" was added in #52368.

Checked the 3 of them.

I'm finding a resolution failure that is puzzling me:

pub struct Foo {}

impl Foo {
    /// [`baz`]
    pub fn bar() {}

    /// [`bar`](Self::bar)
    pub fn baz() {}
}

Neither bar nor baz resolve.

It makes sense to me that [`baz`] wouldn't resolve - the name in-scope is Foo::baz (since it hasn't been pulled in by a use statement) so that seems fine to me.

That Self::bar doesn't resolve either seems odd. @GuillaumeGomez Does self resolution work when written on associated methods?

Self doesn't resolve the same way IIRC, so we'd have to explicitly support it

As @Manishearth said.

This is only tangentially related, but is there any way at all we could help improve the situation for README's that are generated from rustdoc with this change? I'm thinking specifically of https://github.com/livioribeiro/cargo-readme/issues/18, though I'm sure there are other cases where the relative links won't resolve. Could we generate absolute links instead based on the documentation key in Cargo.toml (if present)?

Here's another interesting issue:

If you take the module docs in liballoc/rc.rs and remove the //! [`Rc`]: struct.Rc.html line, you get a bunch of resolution failures. However, I'm having trouble reproducing this in a small example, so I wonder if it's an artifact of how std is organized. Does this have to do with the cross-crate imports bullet point above?

When building docs with deny warnings on nightly, currently you get a bunch of errors related to intra rustdoc links not being resolvable. It looks like the errors are coming from building docs for the standard library itself.

Can we add something to the Rust CI to check for these warnings, or otherwise disable issuing these warnings when building downstream crates?

Example:

➜  futures-rs git:(update) ✗ RUSTDOCFLAGS=-Dwarnings cargo doc --all --exclude futures-preview --exclude futures-executor-preview --exclude futures-test-preview
 Documenting futures-util-preview v0.3.0-alpha.6 (/usr/local/google/home/cramertj/src/futures-rs/futures-util)
error: `[SocketAddrV4]` cannot be resolved, ignoring it...                                                
    |                                                                                                     
    = note: `-D intra-doc-link-resolution-failure` implied by `-D warnings`                               
    = note: the link appears in this line:                                                                

             Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].                                       
                         ^^^^^^^^^^^^^^                                                                   
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[SocketAddr::V4]` cannot be resolved, ignoring it...                                              
    |                                                                                                     
    = note: the link appears in this line:                                                                

             Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].                                       
                                                 ^^^^^^^^^^^^^^^^                                         
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[Mutex::new]` cannot be resolved, ignoring it...                                                  
    |                                                                                                     
    = note: the link appears in this line:                                                                

             This is equivalent to [`Mutex::new`].                                                        
                                    ^^^^^^^^^^^^                                                          
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[SocketAddrV6]` cannot be resolved, ignoring it...                                                
    |                                                                                                     
    = note: the link appears in this line:                                                                

             Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].                                       
                         ^^^^^^^^^^^^^^                                                                   
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[SocketAddr::V6]` cannot be resolved, ignoring it...                                              
    |                                                                                                     
    = note: the link appears in this line:                                                                

             Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].                                       
                                                 ^^^^^^^^^^^^^^^^                                         
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[OsString]` cannot be resolved, ignoring it...                                                    
    |                                                                                                     
    = note: the link appears in this line:                                                                

             Converts a [`String`] into a [`OsString`].                                                   
                                           ^^^^^^^^^^                                                     
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[IpAddr]` cannot be resolved, ignoring it...                                                      
    |                                                                                                     
    = note: the link appears in this line:                                                                

             Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].                     
                                            ^^^^^^^^                                                      
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[SocketAddr]` cannot be resolved, ignoring it...                                                  
    |                                                                                                     
    = note: the link appears in this line:                                                                

             Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].                     
                                                                       ^^^^^^^^^^^^                       
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[SocketAddr::V4]` cannot be resolved, ignoring it...                                              
    |                                                                                                     
    = note: the link appears in this line:                                                                

             This conversion creates a [`SocketAddr::V4`] for a [`IpAddr::V4`]                            
                                        ^^^^^^^^^^^^^^^^                                                  
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[IpAddr::V4]` cannot be resolved, ignoring it...                                                  
    |                                                                                                     
    = note: the link appears in this line:                                                                

             This conversion creates a [`SocketAddr::V4`] for a [`IpAddr::V4`]                            
                                                                 ^^^^^^^^^^^^                             
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[SocketAddr::V6]` cannot be resolved, ignoring it...                                              
    |                                                                                                     
    = note: the link appears in this line:                                                                

             and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`].                                       
                            ^^^^^^^^^^^^^^^^                                                              
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[IpAddr::V6]` cannot be resolved, ignoring it...                                                  
    |                                                                                                     
    = note: the link appears in this line:                                                                

             and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`].                                       
                                                     ^^^^^^^^^^^^                                         
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[SocketAddr]` cannot be resolved, ignoring it...                                                  
    |                                                                                                     
    = note: the link appears in this line:                                                                

             `u16` is treated as port of the newly created [`SocketAddr`].                                
                                                            ^^^^^^^^^^^^                                  
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[RwLock::new]` cannot be resolved, ignoring it...                                                 
    |                                                                                                     
    = note: the link appears in this line:                                                                

             This is equivalent to [`RwLock::new`].                                                       
                                    ^^^^^^^^^^^^^                                                         
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[DefaultHasher::new]` cannot be resolved, ignoring it...                                          
     |                                                                                                    
     = note: the link appears in this line:                                                               

              Creates a new `DefaultHasher` using [`new`][DefaultHasher::new].                            
                                                          ^^^^^^^^^^^^^^^^^^                              
     = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                 

error: `[Weak]` cannot be resolved, ignoring it...                                                        
    |                                                                                                     
    = note: the link appears in this line:                                                                

             [`Weak`], so we `drop` the inner value.                                                      
              ^^^^^^                                                                                      
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[Weak]` cannot be resolved, ignoring it...                                                        
    |                                                                                                     
    = note: the link appears in this line:                                                                

             [`Weak`], so we `drop` the inner value.                                                      
              ^^^^^^                                                                                      
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                  

error: `[Weak::upgrade]` cannot be resolved, ignoring it...                                               
     |                                                                                                    
     = note: the link appears in this line:                                                               

              Calling [`upgrade`][Weak::upgrade] on the return value always                               
                                  ^^^^^^^^^^^^^                                                           
     = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                 

error: `[Weak::upgrade]` cannot be resolved, ignoring it...                                               
     |                                                                                                    
     = note: the link appears in this line:                                                               

              it. Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`].           
                                      ^^^^^^^^^^^^^                                                       
     = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`                 

error: Could not document `futures-util-preview`.                                                         

Caused by:
  process didn't exit successfully: `rustdoc --edition=2018 --crate-name futures_util futures-util/src/lib.rs --color always -o /usr/local/google/home/cramertj/src/futures-rs/target/doc --cfg 'feature="default"' --cfg 'feature="either"' --cfg 'feature="futures-core-preview"' --cfg 'feature="futures-io-preview"' --cfg 'feature="futures-sink-preview"' --cfg 'feature="slab"' --cfg 'feature="std"' -L dependency=/usr/local/google/home/cramertj/src/futures-rs/target/debug/deps --extern either=/usr/local/google/home/cramertj/src/futures-rs/target/debug/deps/libeither-758c45227b7be9c5.rmeta --extern futures_channel=/usr/local/google/home/cramertj/src/futures-rs/target/debug/deps/libfutures_channel-65413d051bb1740e.rmeta --extern futures_core=/usr/local/google/home/cramertj/src/futures-rs/target/debug/deps/libfutures_core-46ea778441081a49.rmeta --extern futures_io=/usr/local/google/home/cramertj/src/futures-rs/target/debug/deps/libfutures_io-bb7a8db4df7a5605.rmeta --extern futures_sink=/usr/local/google/home/cramertj/src/futures-rs/target/debug/deps/libfutures_sink-20c7bbdd565b6353.rmeta --extern pin_utils=/usr/local/google/home/cramertj/src/futures-rs/target/debug/deps/libpin_utils-9603bf9d2932b1e6.rmeta --extern slab=/usr/local/google/home/cramertj/src/futures-rs/target/debug/deps/libslab-6bf6029d2c4c1117.rmeta -Dwarnings` (exit code: 1)

@cramertj I was actually putting together a PR to deny the warnings, but it appears that some of the existing failures are caused by issues in the implementation rather than errors in the documentation. So, like you said, it might be best to silence them when documenting downstream crates for now.

I assume that "Make it work with cross-crate imports" in the OP is referring to things like docs on externally-defined trait implementations failing to resolve and causing warnings to appear, even though the docs are valid in the crate that defined the trait? Is this still blocked on something else (and if so, is there somewhere with more details for tracking it than a comment on the old PR)?

The issue @MajorBreakfast is hitting in https://github.com/rust-lang/rust/issues/43466#issuecomment-410650216 is still happening and is a serious blocker for me-- even when building with --no-deps, I'm getting warnings and errors from upstream documentation resolution failures.

(am unblocked through the magic of RUSTDOC env var, shell scripts, and the --cap-lints setting, but still this should get fixed XD)

[dependencies]
futures-preview = "0.3.0-alpha.7"
#![deny(warnings)]

extern crate futures;

This is enough to trigger a failure right now. (I'll need to narrow it down, but using a crate with some specific use of intra-links will work.) I thought i'd fixed this kind of erroneous error with https://github.com/rust-lang/rust/pull/53162#issuecomment-422834964 but it turns out it wasn't good enough. I'm building/testing a fix right now that refuses to run link collection on non-local items. It may be a bit drastic (and breaks docs which actually work in this situation) but it finally silence this kind of issue until we can actually support them.

Narrowed it down:

// inner crate

use std::fmt::Debug;

pub trait SomeTrait {}

/// this is an impl for [SomeTrait]
impl<T: Debug> SomeTrait for T {}

I bet the PR i linked doesn't touch this impl because it's generic, so it could apply to any number of local items.

In Rocket, we have two libraries in a workspace: a core library, rocket, and a contrib library rocket_contrib. rocket_contrib is not a dependency of rocket, but rocket refers to rocket_contrib in its documentation often.

Because rocket_contrib is not a dependency of rocket, cross-crate links are not resolving:

This is [rocket_contrib], a broken link.

Is there any workaround to this? I've tried adding --extern rocket_contrib=path/to.rmeta manually via RUSTDOCFLAGS, as well as using -Z unstable-options --extern-html-root-url rocket_contrib=https://rocket-contrib.docs, but neither work. Even if the latter worked, it isn't a great solution as it'll produce absolute links, partially defeating the purpose.

In general, I think cargo and/or rustdoc should automatically add all crates in the same workspace to the resolution domain for inter-crate links, making something like [rocket_contrb] work out of the box.

@SergioBenitez, have you tried adding a docs feature to the rocket lib that you set when building docs and that enables an optional dependency on rocket_contrib?

(Sorry to respond here without having followed this issue or impl much!)

automatically add all crates in the same workspace to the resolution domain for inter-crate links, making something like [rocket_contrb] work out of the box.

This will cause issues with the docs when built outside the workspace, e.g. when someone runs cargo doc -p rocket --open to get locally built docs in their project. Changing RUSTDOCFLAGS or having an optional feature has similar problems.

Earlier I suggested including dev-dependencies during doc builds to solve the same issue, or maybe there could be an additional doc-dependencies section?

@killercup I considered that, but unfortunately that would introduce a cyclic dependency.

@Nemo157 I instinctively tried that - placing the dependency in [dev-dependencies] - actually. Although I secretly hoped it didn't work as I really don't want to build/check contrib when working on core. A special doc-dependencies section would resolve this particular issue if it allowed cyclic dependencies.

Currently it's possible to link to fields of structs via a form of psuedo-path:

/// [`Foo::bar`]
pub struct Foo { pub bar: () }

Similarly it would be useful if it were possible to link to fields of a variant of an enum, probably via the same sort of psuedo-path:

/// [`Bar::Baz::quux`]
pub enum Bar {
    Baz { quux: () }
}

I'm trying to ascertain the readiness of this feature for release use, and was hoping the tracking issue might help. While it is working great for me on recent nightly builds, on the just released stable rust 1.30.0 (da5f414c2 2018-10-24), I'm surprised to find that the feature still isn't complete: some links using rust paths aren't resolved to html links.

Is this feature intended to be nightly only? Or is there flags or feature's to be set in order to use it with the rust stable channel? Should I file a new issue for the missed links on 1.30?

There's a big hole in the current implementation, documentation for
re-exported items doesn't work. Re-exports are used a lot in the ecosystem
so this is a stabilization blocker. It's nontrivial to implement since it
requires some architectural changes.

Also, yeah, file issues for missing links, cc me.

On Thu, Oct 25, 2018, 6:12 PM David Kellum notifications@github.com wrote:

I'm trying to ascertain the readiness of this feature for release use, and
was hoping the tracking issue might help. While it is working great for me
on recent nightly builds, on the just released stable rust 1.30.0 (da5f414
https://github.com/rust-lang/rust/commit/da5f414c2c0bfe5198934493f04c676e2b23ff2e
2018-10-24), I'm surprised to find that the feature still isn't complete:
some links using rust paths aren't resolved to html links.

Is this feature intended to be nightly only? Or is there flags or
feature's to be set in order to use it with the rust stable channel? Should
I file a new issue for the missed links on 1.30?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/issues/43466#issuecomment-433132537,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABivSBJ2j47jDYuOKpSrRxK79UEKGTQvks5uofEJgaJpZM4OiBhy
.

@Manishearth I'm not privy to how Rust tends to handle these sorts of things, so I realize this might go against established practice, but it seems to me like it would be useful to have what currently exists in stable, but just not promoted as something that actually works. It's not dangerous and is useful in its current state. I guess the risk is that nobody ever finishes the support for re-exports and we're stuck with a half working feature?

The problem is more that the brokenness of re-exports is subtle. If folks
start using this in documentation, they may not notice that it's broken in
re-exports, which will end up showing ugly documentation.

I'm not going to push back strongly though, if the docs team feels that
early stabilization is okay that sounds good to me.

On Thu, Oct 25, 2018, 6:37 PM Peter Wagenet notifications@github.com
wrote:

@Manishearth https://github.com/Manishearth I'm not privy to how Rust
tends to handle these sorts of things, so I realize this might go against
established practice, but it seems to me like it would be useful to have
what currently exists in stable, but just not promoted as something that
actually works. It's not dangerous and is useful in its current state. I
guess the risk is that nobody ever finishes the support for re-exports and
we're stuck with a half working feature?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/issues/43466#issuecomment-433140448,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABivSNWV6v8XoU8stua09siBxVMwoeRuks5uofbKgaJpZM4OiBhy
.

@Manishearth I've found it super useful in its current form, but I can see the worry around things being subtly broken.

I misinterpreted what I was initially seeing on 1.30: _all_, not just some, rust path style links (this feature) are not resolved on this latest (and prior) stable releases. Besides that not being explained anywhere I can find, the output is slightly confusing because the implicit type links are shown as obviously broken, e.g. "[SomeStruct]" where as links explicitly using a rust path are included verbatim, e.g. <a href="mod1::SomeStruct">, as would be expected without this feature being present.

As it seems now the intent for this was to be nightly-only until further along, shouldn't this tracking issue be edited to include the following, as it might save the next prospective user some confusion (@nrc)?

  • [ ] Stabilization PR (current implementation is nightly only, but not feature gated)

I agree that this is value add as found on current nightly. Authors can just avoid using the new link style for re-exports, as well as links to other crates which are not dependencies, until these are resolved.

But as it stands, its a bit difficult to justify using the feature when it will not generate correct links for a user-local cargo doc even on the latest stable, not to mention the minimum stable rust version. Please consider if keeping this off for stable, with no option or flag, is now more likely to cause trouble with broken links (as this starts getting used with nightly) vs any regressions stabilizing might otherwise cause, given that the new style link targets would never have worked without the feature?

Random idea: If it is planned to keep this semi-usable* for a few more months, it might interesting to see if we can make nightly rustdoc optionally print out the generated relative links (with obvious issues when docs are rendered in more than one place). I don't think we have precendence for this, but if you someone wants to have a fun project, they might even try to integrate this with rustfix (i.e., yield 'suggestion-like' output where you appen \n/// [$a]: $b for each link).

* You can use it right now, with the obvious missing features mentioned above. Since docs.rs uses a nightly compiler version where the intra doc links work, a lot of people reading the docs for your crate will see the correct links. People trying to build the docs will be disappointed, though.

@dekellum You are correct in your observations: The feature is currently written so that links will only ever resolve when running on a nightly (or locally-compiled) rustdoc. In any other situation, they will be passed through in the way you observed.

The current implementation of intra-doc links is not only incomplete, as @Manishearth mentioned, but is also bug-ridden: There have long been issues of spurious "dead links" being found in crates which aren't using intra-doc links at all. This, combined with the fact that we emit a proper warning lint for these resolution errors, led to situations where innocent crates suddenly broke because they had #![deny(warnings)] set.

To be honest, running this without a proper feature gate is shaky, in terms of how unstable features work in the rest of the compiler and rustdoc, but until recently i was uncertain if we could properly introduce a #![feature] gate to the compiler without a matching use in rustc itself. (All the #![feature] attributes that rustdoc currently uses are tied to attributes, so their check code is also in the compiler.) I would be willing to introduce a feature gate for this, since it would also stamp down on the false positive rate across the ecosystem.

However, it leads to similar broken-link situations. Imagine crate A which uses intra-doc links, complete with having the feature set. Now imagine crate B, which re-exports items from crate A to inline them into its own documentation, but doesn't use intra-doc links itself. Because crate B doesn't have the feature set, now those links from the crate A items won't resolve, even if they were accidentally correct because those items were re-exported into the right positions!

(This situation exists today; these crates are futures and hyper, though the items from futures that hyper re-exports don't have any links on them.)

I'm very hesitant to "partially stabilize" these links, because of the subtleties with re-exports that @Manishearth mentioned. It's too easy to use any part of this feature and get it to a position where it doesn't work. And the major hurdle for making that work requires a deep compiler refactor that is hard to find a champion for. If it comes down to it, if there is another Rust All-Hands early next year like the one in Berlin earlier this year, i may try getting the right people in a room together to design this problem out. However, that won't be able to happen for another few months.

I wonder if the standard library crates will need special treatment by this feature? For example, the link to the REPLACEMENT_CHAR constant in String docs needs to resolve to std::char::REPLACEMENT_CHAR or core::char::REPLACEMENT_CHAR depending if the String docs are being rendered as part of the libstd or liballoc docs.

Small bug report (let me know if this isn't the correct place to report this):

Currently, intra-doc links respect #[no_std] in a way that I'm not sure that they should. It means that simple links like [`String`] fail to link to the correct place in the standard library documentation.

Well, it's part of the issue indeed. I'll add a bullet point for it.

The problem is that we use the same resolver that the compiler has made - which means that it's affected by #![no_std]. To universally load in libstd for intra-doc links, we either need to totally ignore #![no_std] when building docs (which may cause erroneous compilation errors) or have some way to find and load libstd's information (and prelude, since you mentioned String specifically) after rustdoc takes over from the compiler. I'm sure it's possible, but it's more cumbersome than it seems.

It definitely seems like one of those cases where what is technically correct and what is expected are different, and we should design in favor of the latter.

The easiest stopgap solution I can see would be to add a new compiler attribute, doc, so that users can write:

#![cfg_attr(not(doc), no_std)]

Do I get it right that super, self, crate are not supported for path resolution?
super does not seem to throw a warning of failed resolution where the other two do. However it creates a link as: <a href="super::AsyncSeekExt::seek"><code>seek</code></a> which obviously doesn't work.

Hmm, they should work, but I think the implementation is buggy around them
right now.

On Tue, Apr 30, 2019, 7:18 AM Naja Melan notifications@github.com wrote:

Do I get it right that super, self, crate are not supported for path
resolution?
super does not seem to throw a warning of failed resolution where the
other two do. However it creates a link as: href="super::AsyncSeekExt::seek">seek which obviously
doesn't work.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/issues/43466#issuecomment-487969870,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAMK6SBZ5WJAKVCP2PSGO53PTBIJZANCNFSM4DUIDBZA
.

Ok, we do seem to have success with crate actually, but super is definitely broken.

I didn't see it mention in the RFC or this issue, but is there a way to link to a documentation header in another crate?

For example, I'd like to link to the _syntax_ header of the regex crate. I can do something like this:

[see the regex syntax]: https://docs.rs/regex/latest/regex/#syntax

But not something like this (which would be preferred, as that would link to the correct version of the syntax documentation):

[see the regex syntax]: regex#syntax

No, intra doc links doesn't currently support linking to sections. It could. It doesn't support linking to other docs.rs either, but that's trickier to get right.

It doesn't support linking to other docs.rs either, but that's trickier to get right.

What do you mean by this? Quick testing shows that intra-rustdoc links works fine with locally available docs, or html_root_url specified in a dependency, or --extern-html-root-url overrides on the command line.

If you're referring to the fact there's no default external doc location when html_root_url isn't set, that is independent of the intra-rustdoc feature, it will presumably just work if html_root_url is updated to be able to default that.

What do you mean by this?

I mean the general case of linking to an external crate on docs.rs if it's not a dependency of yours or you are not on docs.rs.

Ok, so just #42301, which applies to all links to external documentation including intra-rustdoc links.

I filed #62830, in which the "module@" disambiguator does not seem to be respected.

I filed #62833 to propose support for linking to sections, [link text][MyStruct#my-section].

I filed #62834 about recognizing [`SomeType<T, U, V>`] as an intra doc link.

@dtolnay I'm not fan of such things... For instance, what should we do with [`Vec<String>`]? Only link to Vec and forget about String? I think it's better to remain "explicit" on what we want to be linked and not link to more than necessary. In your case, I think it should be "[`SomeType`]``".

@GuillaumeGomez I would be on board with linking if and only if the type parameters in the link match the names of the type's generic parameters, for example [`SomeType<T, U, V>`] would get linked but [`SomeType<String, String, ()>`] would not.

That'd force to check all the generic parameters, not very ideal...

Would you be able to clarify what is not ideal about checking generic parameters? Is it difficult to implement? If that's the only thing, would you consider accepting a PR that takes care of the implementation?

No it's not difficult. It's just not ideal because it creates additional rules that I find useless. The goal of a feature is to be simple enough to let users use it without having to wonder:

  1. Is it something I can do?
  2. What will be the outcome?

In this case, we can consider that the first point wouldn't be an issue but the second definitely would.

In your case, I think it should be [`SomeType`]`<T, U, V>`.

It would be great if there were better support for rendering this style of linking then, currently they have weird spacing, opened https://github.com/rust-lang/rust/issues/62867 about it.

While this is unstable it should at least produce warnings with non-nightly compilers to avoid catching users off-guard: https://www.reddit.com/r/rust/comments/cm7rhv/hey_rustaceans_got_an_easy_question_ask_here/ew0nvo2/?context=1000

Opened as #63305

I see that #49459 has been merged to add support for primitive types, however I'm trying to link to slice::rotate_left and it doesn't seem to be supported. Looking at the state of the code since this PR, it seems like there's been a few changes, and that a more complete list of primitive types are represented. I tested pointer::is_null as well, to test if it's just polymorphic primitives, and it seems that might be the issue, since it also doesn't work as a intra-link.

Am I missing something?

@nixpulvis It's still very unstable and experimental. A lot remains to be done. Can you open an issue about it and cc me on it please?

Would it be possible to have this resolve links to trait implementation? For example:

/// To get an iterator on `MyStruct` call [MyStruct::into_iter].
/// The above generates a warning, "cannot be resolved ignoring".
/// Ideally it would generate a link to the method below.
pub struct MyStruct {
    // ...
}

impl IntoIterator for MyStruct {
    /// Specific documentation for my into_iter method.
    fn into_iter(self) -> Self::IntoIter {
        // ...
    }
}

@benkay86 Normally it should work as is. But like said above, it's still very experimental.

@benkay86 Normally it should work as is. But like said above, it's still very experimental.

It doesn't seem to work for me... on rustc 1.39.0-nightly (f0b58fcf0 2019-09-11)

@najamelan This comment isn't very helpful... Can you provide us details like the markdown, the context, etc... ?

Fully reproducible example:

/// To get an iterator on `MyStruct` call [MyStruct::go].
/// The above generates a warning, "cannot be resolved ignoring".
/// Ideally it would generate a link to the method below.
pub struct MyStruct {}


/// SomeTrait documentation
pub trait SomeTrait
{
    fn go();
}

impl SomeTrait for MyStruct {
    /// Specific documentation for my into_iter method.
    fn go() {}
}
$ rustdoc --version
rustdoc 1.39.0-nightly (6ef275e6c 2019-09-24)

$ cargo doc --no-deps --all-features
 Documenting doctrait v0.1.0 (/data/doc/code/doctrait)
warning: `[MyStruct::go]` cannot be resolved, ignoring it...
 --> src/lib.rs:1:44
  |
1 | /// To get an iterator on `MyStruct` call [MyStruct::go].
  |                                            ^^^^^^^^^^^^ cannot be resolved, ignoring
  |
  = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
  = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`

    Finished dev [unoptimized + debuginfo] target(s) in 0.90s

So, trait methods aren't working. Thanks for the feedback. Adding it to the points.

I filed https://github.com/rust-lang/rust/issues/65354 to have the disambiguator stripped from the link text in something like
/// [`trait@Name`].

Is there any centralised documentation for how exactly this feature works, considering how it's changed so much from the initial RFC? Like, specifically document what kinds of links should work and which shouldn't, and if parts of the text are removed from the final result?

Like, I get that it's not going to be stabilised any time soon, but many folks use this feature and it's hard to reason which things work and which don't at the moment.

The only thing blocking stabilization now is #65983

Isn't documentation also a blocker? 😅

That's usually a part of stabilization.

Is there any way to hide any crate:: prefix when linking to types not within the current module and not in scope when using shorthand links?

I notice in some of my documentation, I have _some_ types imported, and can link to them using [`MyStruct`] but when I want to link to some other type that is not imported because it isn't actively used in the module, I have to use [`crate::OtherStruct`], which looks a bit off in the documentation.

I realise I can name the link whatever I want and then turn it into an actual link later by adding a reference, but that increases the bloat of the comment in the code itself.

I guess it's a minor thing, and there's no clean way to solve this that isn't probably at least somewhat surprising to some, but I wanted to mention it nonetheless.

@JeanMertz Have you tried something like:

[`OtherStruct`][crate::OtherStruct]

One way that I tend to do this is using the (currently unstable, but pending stabilisation in #61351) #[cfg(rustdoc)].

i.e., at the top of the file, I put:

#[cfg(rustdoc)]
use crate::OtherStruct;

and then you can reference the type without the crate:: prefix.

You can do this without the #[cfg(rustdoc)] by simply adding #[allow(unused)], although I prefer the former as it will still lint if you don't actually use the import.

Could someone in the know please file an issue around "Handle fields inside struct variants" so that I know what might be needed in order to close off that blocker?

It's not a blocker. It's about giving the ability to link directly to a struct field by naming it MyStruct::field in the link.

It's about giving the ability to link directly to a struct field by naming it MyStruct::field in the link.

Isn't that ambiguous when there is also an inherent method with the same name? It's also "syntactically unnatural" to refer to struct fields in this way, though I can't think of a better way right now.

Yeah, that's why there's no issue for it, it's something we may want to add
and if we do we'd have to figure out how. It's not a blocker.

Thanks,
-Manish Goregaokar

On Sat, Nov 9, 2019 at 5:29 PM Mikhail Zabaluev notifications@github.com
wrote:

It's about giving the ability to link directly to a struct field by naming
it MyStruct::field in the link.

Isn't that ambiguous when there is also an inherent method with the same
name? It's also "syntactically unnatural" to refer to struct fields in this
way, though I can't think of a better way right now.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/issues/43466?email_source=notifications&email_token=AAMK6SGWZDOP5WGCY6N3NSDQS5PXNA5CNFSM4DUIDBZKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDUTC3A#issuecomment-552153452,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAMK6SAW4YG76SI75FMRNXLQS5PXNANCNFSM4DUIDBZA
.

@Manishearth Aha, thanks. I misunderstood the presence of something in the top comment with a tickybox as being something which had to be done. Is there an issue capturing the desire to link to a struct's field so that it doesn't get lost if this issue is closed? Or is there a process for splitting out remaining issues when we close a tracking issue?

We can file an issue now if you want, but basically any leftover non
blockers will be filed as issues once this is closed.

On Sat, Nov 9, 2019, 11:23 PM Daniel Silverstone notifications@github.com
wrote:

@Manishearth https://github.com/Manishearth Aha, thanks. I
misunderstood the presence of something in the top comment with a tickybox
as being something which had to be done. Is there an issue capturing the
desire to link to a struct's field so that it doesn't get lost if this
issue is closed? Or is there a process for splitting out remaining issues
when we close a tracking issue?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/issues/43466?email_source=notifications&email_token=AAMK6SADZOO5DIPJGOHSXP3QS6ZHDA5CNFSM4DUIDBZKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDUXEXY#issuecomment-552170079,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAMK6SHUBJZWYTJ6NPMYFETQS6ZHDANCNFSM4DUIDBZA
.

Okay, if raising issues when this closes is the process then that's perfect. I'm not in a rush to have that issue, I was just trying to properly understand (a) what was actually considered blocking for stabilisation, and (b) what the process was to deal with remaining things if it wasn't all blocking. Thank you for clarifying things @Manishearth

Cross crate imports and documentation are the only stabilization blockers AIUI. Documentation can be done during the stabilization process.

If someone wants to add docs earlier they can be added to the unstable book, and then moved over to the reference.

@kinnison seems like @da-x has a similar thing in progress at https://github.com/da-x/rust/commit/1856989cdf2ba2fb956fc06a1a919f099e94dc7f for #21934

@Manishearth Oooh interesting, thank you. I shall have to have a look when @da-x gets closer to completion. I have plenty to be doing before I try for the better resolution, so if their work makes life easier for us, then that's excellent.

You should coordinate with them and see if there's a way y'all can work
together! It's possible their work is already sufficient for your purposes
here.

On Sun, Nov 10, 2019, 11:52 PM Daniel Silverstone notifications@github.com
wrote:

@Manishearth https://github.com/Manishearth Oooh interesting, thank
you. I shall have to have a look when @da-x https://github.com/da-x
gets closer to completion. I have plenty to be doing before I try for the
better resolution, so if their work makes life easier for us, then that's
excellent.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/issues/43466?email_source=notifications&email_token=AAMK6SEZGZ3JSICF5JLWEHLQTEFMZA5CNFSM4DUIDBZKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDV6RVI#issuecomment-552331477,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAMK6SCMFT3W2NDT3THMUPLQTEFMZANCNFSM4DUIDBZA
.

When I tried using intra-doc links in libstd docs a few months ago, I was told they are still experimental and should not be used yet. What is the current status? When writing new docs / adding new links to existing docs, should I use intra-doc links?

Cross crate imports and documentation are the only stabilization blockers AIUI. Documentation can be done during the stabilization process.

Would it be possible to land the current intra-doc feature without cross crate imports? That would hit most of my needs for intra-doc resolution and still leaves open the option to land cross-crate imports later.

The problem is that anyone might re-export a type from your crate and then the documentation will be broken.

So the user of the feature can't know in advance when it will break.

I guess we could still stabilize it with this caveat and request people to work with upstream authors to remove these links when reexporting.

If you're targetting docs built by docs.rs it should be "fine". But as long as we don't have everything fixed, I don't think this is a good idea to stabilize it yet.

I don't if this is already on someone's radar but, linking to re-exported macros doesn't work at the moment. Simple test case:

In Cargo.toml:

[dependencies]
log = "0.4.8"
//! [`info`]
//!
//! [`info`]: crate::info

pub use log::info;

It fails with the following:

warning: `[crate::info]` cannot be resolved, ignoring it.
 --> src/lib.rs:3:15
  |
3 | //! [`info`]: crate::info
  |               ^^^^^^^^^^^ cannot be resolved, ignoring
  |
  = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
  = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`

Versions:
rustc 1.43.0-nightly (564758c4c 2020-03-08)
cargo 1.43.0-nightly (bda50510d 2020-03-02)

* [ ]  Handle methods from traits implementations

This should be fixed now. See

* Allow referring to `Self::item` (for `cmp` on `Ord`)

Perhaps this is fixed now, see

If not please. please provide a minimal example for it to clarify it.

I don't understand how to link to a re-exported procedural macro. The RFC indicates that linking to _a_ macro is possible, but none of my attempts appear to successfully link.

Reproduction

Cargo.toml

[package]
name = "repro"
version = "0.1.0"
edition = "2018"

[dependencies]
the-macro = { path = "the-macro" }

src/lib.rs

//! Please check out the procedural macro:
//!
//! - [Repro]
//! - [Repro][]
//! - [Repro](Repro)
//!
//! - [Repro!]
//! - [Repro!][]
//! - [Repro!](Repro!)
//!
//! - [macro Repro]
//! - [macro Repro][]
//! - [macro Repro](macro@Repro)
//!
//! - [macro Repro!]
//! - [macro Repro!][]
//! - [macro Repro!](macro@Repro!)

pub use the_macro::Repro;

the-macro/Cargo.toml

[package]
name = "the-macro"
version = "0.1.0"
edition = "2018"

[lib]
proc-macro = true

[dependencies]

the-macro/src/lib.rs

use proc_macro::TokenStream;

#[proc_macro_derive(Repro)]
pub fn repro_derive(input: TokenStream) -> TokenStream {
    input
}

@shepmaster the re-export is the problem, see https://github.com/rust-lang/rust/issues/65983. As a workaround, you might be able to use the absolute path (the_macro::Repro), but I haven't tested that.

might be able to use the absolute path (the_macro::Repro)

Yeah, that was one I tried in my project but didn't reflect in the reproduction. It didn't seem to work either.


Attempts

//! - [the_macro::Repro]
//! - [the_macro::Repro][]
//! - [the_macro::Repro](the_macro::Repro)
//!
//! - [the_macro::Repro!]
//! - [the_macro::Repro!][]
//! - [the_macro::Repro!](the_macro::Repro!)
//!
//! - [the_macro::Repro]
//! - [the_macro::Repro][]
//! - [the_macro::Repro](the_macro::Repro)

I'm not sure, right now cross-doc links are pretty broken. Hopefully https://github.com/rust-lang/rust/pull/73101 will land in the next few weeks, you could try again afterwards.

@jyn514 the cross crate bug is unrelated to the one being described by @shepmaster

You should totally be able to link _to_ a pub use in the current implementation, so what @shepmaster describes is an independent bug

Can confirm that linking to pub use works, but not if it's a proc macro being used. Macro scoping is weird so that's probably it.

Oh, this has nothing to do with pub use, we're just completely incapable of linking to derive macros

Note: once https://github.com/rust-lang/rust/pull/73101 lands all of the blocker issues for this will have resolved and we should be a go for stabilizing the feature with docs. Note that it has baked as nightly-only for ages now.

I'll write documentation once it's merged then. We still have a few other points which need to be solved before stabilization though, but we're getting close! :)

I haven't had time to make a minimal repro, but there still appears to be an issue with linking to free-functions on cross-crate inlined docs like here even using the rustdoc from #73101.

@GuillaumeGomez I've already got some of the docs written.

It's not clear to me if the remaining issues should block stabilization, I think they can be treated as just another bug. We don't typically block stabilization on minor bugs whose fix will not impact the feature.

Do we have a general consensus on what kinds of changes are considered major or minor when it comes to doc syntax?

@clarfon I don't think there are or needs to be rigid rules around that. When a feature is considered for stabilization, the relevant team looks at the status of the feature, and decides if it's ready. Like I said, _typically_ bugs where the fix is not likely to severely change the feature are okay to have. In this case the major blocker, the cross-crate issue, was one where we weren't even sure if it was possible to implement, and it might have changed how the feature worked. It was also just a major piece of functionality.

The current remaining issues are no_std linking _to std_: this is a quality of life improvement where you can still link to std items from a no_std crate. The other one is about linking to the docs of the slice primitive, which is also a quality of life improvement, since people do that rarely.

I don't think there need to be strict rules, but I was mostly asking because I figure that this might come up more as rustdoc becomes more robust and changes to its syntax can throw deny-by-default warnings. My general assumption is that regardless of whether something might "break" that docs are considered separate enough to ignore these issues in favour of pushing out changes sooner, but I figure that a potential clarification on that might be helpful to avoid this confusion in the future.

@clarfon oh that's fair.

When it comes to _lints_ the general Rust stabilty model is that new warn-by-default lints are always okay, deny-by-default lints should _usually_ go through some cycles of warn-by-default unless there are special circumstances.

Okay, so I've narrowed @Nemo157's bug down to the is_public() check in https://github.com/rust-lang/rust/blob/4fb54ed484e2239a3e9eff3be17df00d2a162be3/src/librustdoc/html/format.rs#L471 failing. Removing that line lets the link work just fine.

Annoyingly, any attempt to narrow down the testcase is failing for me.

What's happening though is that the def_id is absent from the access_levels map. I'm not sure why.

Aha, it's the pub mod __reexport. Moving that to the end of the file fixes the issue @Nemo157 . I'll try to file a bug about this.

FWIW the following part

Fix current crate linking when no module is provided in the path (for example, Foo won't link to the crate's Foo type for some reason)

doesn't seem to occur anymore. This might have been an issue during the edition changes to resolution

Removing the no_std issue in the list because https://github.com/rust-lang/rust/issues/73423 is actually a broader rustdoc bug

FWIW, I support stabilizing even with the remaining bugs. This flag is already used pervasively, for example, I believe all of docs.rs uses this.

There's a WIP PR implementing resolving intra-rustdoc links, and traditional path-based links, in rust-analyzer here.

That's really great, thanks!

Should we add suggestions to part of the tracking issue? For example,

warning: `[extend]` cannot be resolved, ignoring it.
   --> src/vec.rs:704:45
    |
704 |     /// Note that this function is same as [`extend`] except that it is specialized to work with
    |                                             ^^^^^^^^ cannot be resolved, ignoring
    |
    = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`

Could be

warning: `[extend]` cannot be resolved, ignoring it.
   --> src/vec.rs:704:45
    |
704 |     /// Note that this function is same as [`extend`] except that it is specialized to work with
    |                                             ^^^^^^^^ cannot be resolved, ignoring
    |
    = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
    = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
    = help: a link with a similar exists: `#method.extend`

Or we could guide them to do

    /// [`extend`]: #method.extend

(I personally am not sure how to do this, I wish I could help out with diagnostics https://github.com/rust-lang/rust/issues/71389)

I think this should be a separate issue, it shouldn't block stabilizing the feature.

@pickfire File a separate issue. Also the diagnostics here should be to suggest Self::extend() IMO.

I think it's a fair bit more involved to introduce this diagnostic fwiw

Status update: All the code for this has been written (that I know of), it's just waiting on a very long PR trail:

Once that is done, we can make a stabilization PR 🎉 . The beta release is on Tuesday, which this will most likely miss; if it miraculously makes Tuesday we'll delay stabilization until afterwards because #73566 makes a lot of internal changes and should see a full 6 weeks on nightly before making it to beta.

Additionally I'd love to see https://github.com/rust-lang/rust/pull/74137 -> https://github.com/rust-lang/rustc-perf/pull/675 merged before #73566 since I expect it to improve rustdoc's performance quite a lot. That shouldn't block intra-doc links, though. EDIT: this landed 🎉

@jyn514 feel free to include #74070 in #73566 btw, we can land both at once

@Manishearth I'd rather not, #74070 is a good change even if we have to revert #73566. Also it can be rolled-up and #73566 shouldn't be.

* #74070 -> #73566 -> #73101 -> #73365

Once that is done, we can make a stabilization PR 🎉 .

Once that is done we'll have an initial functional implementation. The next step is testing it. A big part of that will be to start using it in the std docs and seeing if it can fix the issues it was designed for (#32129, #32130).

@ollie27 We have had a functional implementation for three years now. It has been used in the stdlib docs for ages, and is used across the ecosystem. The ability for reexports to work correctly was a blocker to stabilization, but it is not a huge feature that will be used a lot. The reason stabilization was blocked on reexports was that we determined that the bug fix could be complicated and might require rearchitecting the feature, which made us reluctant to stabilize earlier.

seeing if it can fix the issues it was designed for (#32129, #32130)

I hadn't seen these issues earlier, and we should absolutely fix them using intra doc links, but I don't want to block stabilization on that. We've had this feature mostly working for ages.

Alright, so the current status of this is that we have a stack of PRs blocking all remaining major issues (https://github.com/rust-lang/rust/issues/65983, https://github.com/rust-lang/rust/issues/73363): https://github.com/rust-lang/rust/pull/74347 -> https://github.com/rust-lang/rust/pull/73566 -> https://github.com/rust-lang/rust/pull/73101 -> https://github.com/rust-lang/rust/pull/73365

Between @GuillaumeGomez, @jyn514, and myself, we hope to stabilize this shortly thereafter. @GuillaumeGomez will be filing an FCP but as we're currently mostly waiting for the final chips to fall in place, I wanted to front-load some of the discussions that may happen during that FCP. Hopefully when we make that FCP it is simply some rubber-stamping if we have these discussions earlier.

@rust-lang/rustdoc What are your thoughts on stabilizing this shortly after the last few patches land? I recall @ollie27 having some concerns. I don't recall if @kinnison has said anything on this point.

My position on this (I think this is shared by Guillaume and Joshua) is that this feature has been cooking on nightly for three years now. The cross-crate import issue was a blocker not because it was a major piece of functionality, but rather because there was a chance we wouldn't be able to implement it in a neat manner and would paint ourselves into a corner by committing to it. It's clear that that's not the case. If we're worried about the code for cross-crate imports itself being broken, that's what the release train schedule is for -- we can undo these patches and stabilization for twelve weeks if this happens.

I think that once the remaining stack lands, we're in good shape to stabilise. There're bound to be corner cases we've not found etc. and documentation which could be improved, but getting this out and usable by the general developer community will be immensely useful.

https://github.com/rust-lang/rust/issues/65983 has landed, so now we're ready for stabilization. https://github.com/rust-lang/rust/issues/73363 should land soon

It should be noted that in the RFC discussion it was determined that exact knowledge of the item type should not be necessary; only knowing the namespace should suffice. It is acceptable that the tool resolving the links allows (and successfully resolves) a link with the wrong prefix that is in the same namespace. E.g., given an struct Foo, it may be possible to link to it using [enum Foo], or, given a mod bar, it may be possible to link to that using [struct bar].

After https://github.com/rust-lang/rust/pull/75079 this is no longer the case. Should the RFC be updated?

@jyn514 go for it

Triage: https://github.com/rust-lang/rust/pull/74489 has been merged, so its mark can be checked, I believe?

Was this page helpful?
0 / 5 - 0 ratings