Skip to content

Commit

Permalink
Auto merge of #76934 - camelid:rustdoc-allow-generic-params, r=jyn514
Browse files Browse the repository at this point in the history
Allow generic parameters in intra-doc links

Fixes #62834.

---

The contents of the generics will be mostly ignored (except for warning
if fully-qualified syntax is used, which is currently unsupported in
intra-doc links - see issue #74563).

* Allow links like `Vec<T>`, `Result<T, E>`, and `Option<Box<T>>`
* Allow links like `Vec::<T>::new()`
* Warn on
  * Unbalanced angle brackets (e.g. `Vec<T` or `Vec<T>>`)
  * Missing type to apply generics to (`<T>` or `<Box<T>>`)
  * Use of fully-qualified syntax (`<Vec as IntoIterator>::into_iter`)
  * Invalid path separator (`Vec:<T>:new`)
  * Too many angle brackets (`Vec<<T>>`)
  * Empty angle brackets (`Vec<>`)

Note that this implementation *does* allow some constructs that aren't
valid in the actual Rust syntax, for example `Box::<T>new()`. That may
not be supported in rustdoc in the future; it is an implementation
detail.
  • Loading branch information
bors committed Oct 10, 2020
2 parents 790d19c + e2424a2 commit b1af43b
Show file tree
Hide file tree
Showing 12 changed files with 441 additions and 20 deletions.
16 changes: 11 additions & 5 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ rustc_queries! {
/// Computes the `DefId` of the corresponding const parameter in case the `key` is a
/// const argument and returns `None` otherwise.
///
/// ```rust
/// ```ignore (incomplete)
/// let a = foo::<7>();
/// // ^ Calling `opt_const_param_of` for this argument,
///
Expand Down Expand Up @@ -162,10 +162,12 @@ rustc_queries! {
/// Specifically this is the bounds written on the trait's type
/// definition, or those after the `impl` keyword
///
/// ```ignore (incomplete)
/// type X: Bound + 'lt
/// ^^^^^^^^^^^
/// // ^^^^^^^^^^^
/// impl Debug + Display
/// ^^^^^^^^^^^^^^^
/// // ^^^^^^^^^^^^^^^
/// ```
///
/// `key` is the `DefId` of the associated type or opaque type.
///
Expand All @@ -176,18 +178,22 @@ rustc_queries! {

/// Elaborated version of the predicates from `explicit_item_bounds`.
///
/// Example for
/// For example:
///
/// ```
/// trait MyTrait {
/// type MyAType: Eq + ?Sized`
/// type MyAType: Eq + ?Sized;
/// }
/// ```
///
/// `explicit_item_bounds` returns `[<Self as MyTrait>::MyAType: Eq]`,
/// and `item_bounds` returns
/// ```text
/// [
/// <Self as Trait>::MyAType: Eq,
/// <Self as Trait>::MyAType: PartialEq<<Self as Trait>::MyAType>
/// ]
/// ```
///
/// Bounds from the parent (e.g. with nested impl trait) are not included.
query item_bounds(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
Expand Down
3 changes: 3 additions & 0 deletions library/core/src/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@
//! ```
//!
//! [`Box<T>`]: ../../std/boxed/struct.Box.html
//! [`Box<U>`]: ../../std/boxed/struct.Box.html
//! [`num::NonZero*`]: crate::num
//! [`ptr::NonNull<U>`]: crate::ptr::NonNull

#![stable(feature = "rust1", since = "1.0.0")]

Expand Down
2 changes: 1 addition & 1 deletion src/doc/rustdoc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
- [Linking to items by name](linking-to-items-by-name.md)
- [Lints](lints.md)
- [Passes](passes.md)
- [Advanced Features](advanced-features.md)
- [Advanced features](advanced-features.md)
- [Unstable features](unstable-features.md)
2 changes: 1 addition & 1 deletion src/doc/rustdoc/src/advanced-features.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Advanced Features
# Advanced features

The features listed on this page fall outside the rest of the main categories.

Expand Down
41 changes: 35 additions & 6 deletions src/doc/rustdoc/src/linking-to-items-by-name.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Linking to items by name

Rustdoc is capable of directly linking to other rustdoc pages in Markdown documentation using the path of item as a link.
Rustdoc is capable of directly linking to other rustdoc pages using the path of
the item as a link.

For example, in the following code all of the links will link to the rustdoc page for `Bar`:

Expand All @@ -19,15 +20,26 @@ pub struct Foo3;
/// This struct is also not [`Bar`]
pub struct Foo4;

/// This struct *is* [`Bar`]!
pub struct Bar;
```

You can refer to anything in scope, and use paths, including `Self`, `self`, `super`, and `crate`. You may also use `foo()` and `foo!()` to refer to methods/functions and macros respectively. Backticks around the link will be stripped.
Backticks around the link will be stripped, so ``[`Option`]`` will correctly
link to `Option`.

You can refer to anything in scope, and use paths, including `Self`, `self`,
`super`, and `crate`. You may also use `foo()` and `foo!()` to refer to methods/functions and macros, respectively.

You can also refer to items with generic parameters like `Vec<T>`. The link will
resolve as if you had written ``[`Vec<T>`](Vec)``. Fully-qualified syntax (for example,
`<Vec as IntoIterator>::into_iter()`) is [not yet supported][fqs-issue], however.

[fqs-issue]: https://github.com/rust-lang/rust/issues/74563

```rust,edition2018
use std::sync::mpsc::Receiver;
/// This is an version of [`Receiver`], with support for [`std::future`].
/// This is a version of [`Receiver<T>`] with support for [`std::future`].
///
/// You can obtain a [`std::future::Future`] by calling [`Self::recv()`].
pub struct AsyncReceiver<T> {
Expand All @@ -44,13 +56,15 @@ impl<T> AsyncReceiver<T> {
You can also link to sections using URL fragment specifiers:

```rust
/// This is a special implementation of [positional parameters]
/// This is a special implementation of [positional parameters].
///
/// [positional parameters]: std::fmt#formatting-parameters
struct MySpecialFormatter;
```

Paths in Rust have three namespaces: type, value, and macro. Items from these namespaces are allowed to overlap. In case of ambiguity, rustdoc will warn about the ambiguity and ask you to disambiguate, which can be done by using a prefix like `struct@`, `enum@`, `type@`, `trait@`, `union@`, `const@`, `static@`, `value@`, `function@`, `mod@`, `fn@`, `module@`, `method@`, `prim@`, `primitive@`, `macro@`, or `derive@`:
Paths in Rust have three namespaces: type, value, and macro. Item names must be
unique within their namespace, but can overlap with items outside of their
namespace. In case of ambiguity, rustdoc will warn about the ambiguity and ask you to disambiguate, which can be done by using a prefix like `struct@`, `enum@`, `type@`, `trait@`, `union@`, `const@`, `static@`, `value@`, `fn@`, `function@`, `mod@`, `module@`, `method@`, `prim@`, `primitive@`, `macro@`, or `derive@`:

```rust
/// See also: [`Foo`](struct@Foo)
Expand All @@ -62,4 +76,19 @@ struct Foo {}
fn Foo() {}
```

Note: Because of how `macro_rules` macros are scoped in Rust, the intra-doc links of a `macro_rules` macro will be resolved relative to the crate root, as opposed to the module it is defined in.
You can also disambiguate for functions by adding `()` after the function name,
or for macros by adding `!` after the macro name:

```rust
/// See also: [`Foo`](struct@Foo)
struct Bar;

/// This is different from [`Foo()`]
struct Foo {}

fn Foo() {}
```

Note: Because of how `macro_rules!` macros are scoped in Rust, the intra-doc links of a `macro_rules!` macro will be resolved [relative to the crate root][#72243], as opposed to the module it is defined in.

[#72243]: https://github.com/rust-lang/rust/issues/72243
10 changes: 5 additions & 5 deletions src/doc/rustdoc/src/lints.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
can use them like any other lints by doing this:

```rust,ignore
#![allow(missing_docs)] // allowing the lint, no message
#![warn(missing_docs)] // warn if there is missing docs
#![deny(missing_docs)] // rustdoc will fail if there is missing docs
#![allow(missing_docs)] // allows the lint, no diagnostics will be reported
#![warn(missing_docs)] // warn if there are missing docs
#![deny(missing_docs)] // error if there are missing docs
```

Here is the list of the lints provided by `rustdoc`:

## broken_intra_doc_links

This lint **warns by default**. This lint detects when an [intra-doc link] fails to get resolved. For example:
This lint **warns by default**. This lint detects when an [intra-doc link] fails to be resolved. For example:

[intra-doc link]: linking-to-items-by-name.html
[intra-doc link]: linking-to-items-by-name.md

```rust
/// I want to link to [`Nonexistent`] but it doesn't exist!
Expand Down
2 changes: 2 additions & 0 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
html_playground_url = "https://play.rust-lang.org/"
)]
#![feature(rustc_private)]
#![feature(array_methods)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(or_patterns)]
#![feature(peekable_next_if)]
#![feature(test)]
#![feature(crate_visibility_modifier)]
#![feature(never_type)]
Expand Down
Loading

0 comments on commit b1af43b

Please sign in to comment.