Skip to content
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

Correctly using intra-rustdoc links in no_std crates is difficult #76252

Closed
dylni opened this issue Sep 2, 2020 · 12 comments
Closed

Correctly using intra-rustdoc links in no_std crates is difficult #76252

dylni opened this issue Sep 2, 2020 · 12 comments
Labels
A-intra-doc-links Area: Intra-doc links, the ability to link to items in docs by name C-discussion Category: Discussion or questions that doesn't represent real issues. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.

Comments

@dylni
Copy link
Contributor

dylni commented Sep 2, 2020

AFAICT, if your crate has this line:

#![cfg_attr(not(feature = "std"), no_std)]

and you use a intra-rustdoc link for any std item, these lines must be added to build documentation with --no-default-features:

#[cfg(doc)]
extern crate std;

Then, to use items from the prelude in documentation, you'll also want:

#[cfg(doc)]
use std::prelude::v1::*

However, this defeats the purpose of the prelude being imported automatically. Would it be possible for rustdoc to add these lines even when building with #![no_std]?

This should also help solve #73423, because the std crate would always be in scope.

@jonas-schievink jonas-schievink 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 Sep 2, 2020
@jonas-schievink
Copy link
Contributor

Depending on the target documentation is built for, libstd might not exist, so these lines cannot be added automatically without breaking a lot of embedded crates. However it seems like a bug that rustdoc does not inject the core library and libcore prelude instead.

@dylni
Copy link
Contributor Author

dylni commented Sep 2, 2020

I figured there was something I was missing about this. That seems reasonable, but the problem would still exist when mentioning items only defined in std or alloc.

I'm not sure what the best resolution for that would be, but if crates use extern crate std to have it in scope, the documentation would also fail to build on those targets. Could rustdoc default to a target that libstd is build for? It might make the link resolution more complex, but this seems like an easy thing to get wrong on the crate side.

@jyn514
Copy link
Member

jyn514 commented Sep 2, 2020

Some thoughts, not for or against this feature yet:

#[cfg(doc)]
extern crate std;

This will break if another crate depends on your docs: #75855

the problem would still exist when using items only defined in std or alloc

This is a more general problem than intra-doc links: #73423

However it seems like a bug that rustdoc does not inject the core library and libcore prelude instead.

Rustdoc should do this already, no? This works fine locally:

#![no_std]
//! Link to [`Option`]

Could rustdoc default to a target that libstd is build for?

Hmm ... that would break any crate that uses cfg(target = "...") and force crates to use cfg(any(doc, target = "...")). It is also not backwards compatible.

@jyn514
Copy link
Member

jyn514 commented Sep 2, 2020

I think I would recommend passing --feature std when documenting your crate. Adding a silent --target seems very liable to break, and adding extern crate std means that you can't document the crate for targets without the standard library.

@jyn514
Copy link
Member

jyn514 commented Sep 2, 2020

This should also help solve #73423, because the std crate would always be in scope.

Actually you just made me remember why injecting extern crate std; isn't possible - that means you can't document either std or core.

@jyn514
Copy link
Member

jyn514 commented Sep 2, 2020

I'll leave this open because I think the discussion is useful, but I don't think rustdoc is going to change it's behavior here.

@dylni
Copy link
Contributor Author

dylni commented Sep 2, 2020

This will break if another crate depends on your docs: #75855

I wasn't aware dependencies are built without cfg(doc). That does make the idea pretty useless.

Hmm ... that would break any crate that uses cfg(target = "...") and force crates to use cfg(any(doc, target = "...")). It is also not backwards compatible.

I'm not sure I understand, but I agree it's not a great idea.

that means you can't document either std or core.

Right, I guess this would almost require rustdoc to know how to map each item to its documentation link, which seems error-prone.

I think I would recommend passing --feature std when documenting your crate.

My specific problem is that I am using an alloc type in documentation for a #![no_std] trait. In documentation for this method, I link to ToString. If I understand correctly, if I change that link to intra-rustdoc, it will break if a reverse-dependency that doesn't use the std feature builds its documentation.

This use case might just be too hard to support.

@jyn514
Copy link
Member

jyn514 commented Sep 2, 2020

This will break if another crate depends on your docs: #75855

I wasn't aware dependencies are built without cfg(doc). That does make the idea pretty useless.

Hmm, that seems like something we could change without too much trouble. cc @rust-lang/rustdoc , what do you think about setting cfg(doc) for dependencies?

I'm not sure I understand

There could be items that are only documented on certain platforms, e.g. winapi is an empty crate on Linux. So if rustdoc overrides the target the documentation would be wrong.

My specific problem is that I am using an alloc type in documentation for a #![no_std] trait

In this particular case, if you had extern crate alloc that would work even with no_std. But in general you're correct that it would break.

@dylni
Copy link
Contributor Author

dylni commented Sep 2, 2020

There could be items that are only documented on certain platforms, e.g. winapi is an empty crate on Linux. So if rustdoc overrides the target the documentation would be wrong.

I see what you mean now. I actually meant that rustdoc could only use that default when resolving std links, without changing the build target. However, that wouldn't work anyway if no libstd target is installed.

In this particular case, if you had extern crate alloc that would work even with no_std.

I should have given a better example. The crate-level documentation references println!, so it still needs std.

@Manishearth
Copy link
Member

Hmm, that seems like something we could change without too much trouble. cc @rust-lang/rustdoc , what do you think about setting cfg(doc) for dependencies?

I feel like this breaks metadata-only dep doc builds

@jyn514
Copy link
Member

jyn514 commented Sep 3, 2020

You mean like when documenting with --no-deps from cargo? I thought that didn't run rustdoc at all and only ran cargo check.

@jyn514
Copy link
Member

jyn514 commented Jul 12, 2021

I'm going to close this because I don't think it's actionable; setting cfg(doc) for dependencies seems like the only thing we could reasonably change and that's already tracked by rust-lang/cargo#8811.

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 C-discussion Category: Discussion or questions that doesn't represent real issues. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants