mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-15 05:26:47 +00:00
Auto merge of #94814 - matthiaskrgr:rollup-a5sk366, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #94440 (Better error for normalization errors from parent crates that use `#![feature(generic_const_exprs)]`) - #94587 (Document new recommended use of `FromIterator::from_iter`) - #94644 (Fix soundness issue in scoped threads.) - #94740 (Unify impl blocks by wrapping them into a div) - #94753 (Improve rustdoc book) - #94796 (Allow `cargo run` instead of `cargo run -p bootstrap`) - #94805 (Revert accidental stabilization) - #94809 (RustWrapper: add missing include) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5f4e067719
@ -1,4 +1,5 @@
|
||||
[workspace]
|
||||
default-members = ["src/bootstrap"]
|
||||
members = [
|
||||
"src/bootstrap",
|
||||
"compiler/rustc",
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "llvm/Object/Archive.h"
|
||||
#include "llvm/Object/COFFImportFile.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Bitcode/BitcodeWriterPass.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
|
@ -35,34 +35,14 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
span: Span,
|
||||
) -> Result<(), NotConstEvaluatable> {
|
||||
debug!("is_const_evaluatable({:?})", uv);
|
||||
if infcx.tcx.features().generic_const_exprs {
|
||||
let tcx = infcx.tcx;
|
||||
let tcx = infcx.tcx;
|
||||
|
||||
if tcx.features().generic_const_exprs {
|
||||
match AbstractConst::new(tcx, uv)? {
|
||||
// We are looking at a generic abstract constant.
|
||||
Some(ct) => {
|
||||
for pred in param_env.caller_bounds() {
|
||||
match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||
if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
|
||||
// Try to unify with each subtree in the AbstractConst to allow for
|
||||
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
|
||||
// predicate for `(N + 1) * 2`
|
||||
let result =
|
||||
walk_abstract_const(tcx, b_ct, |b_ct| {
|
||||
match try_unify(tcx, ct, b_ct) {
|
||||
true => ControlFlow::BREAK,
|
||||
false => ControlFlow::CONTINUE,
|
||||
}
|
||||
});
|
||||
|
||||
if let ControlFlow::Break(()) = result {
|
||||
debug!("is_const_evaluatable: abstract_const ~~> ok");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {} // don't care
|
||||
}
|
||||
if satisfied_from_param_env(tcx, ct, param_env)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// We were unable to unify the abstract constant with
|
||||
@ -163,6 +143,33 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
// If we're evaluating a foreign constant, under a nightly compiler without generic
|
||||
// const exprs, AND it would've passed if that expression had been evaluated with
|
||||
// generic const exprs, then suggest using generic const exprs.
|
||||
if concrete.is_err()
|
||||
&& tcx.sess.is_nightly_build()
|
||||
&& !uv.def.did.is_local()
|
||||
&& !tcx.features().generic_const_exprs
|
||||
&& let Ok(Some(ct)) = AbstractConst::new(tcx, uv)
|
||||
&& satisfied_from_param_env(tcx, ct, param_env) == Ok(true)
|
||||
{
|
||||
tcx.sess
|
||||
.struct_span_fatal(
|
||||
// Slightly better span than just using `span` alone
|
||||
if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
|
||||
"failed to evaluate generic const expression",
|
||||
)
|
||||
.note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
|
||||
.span_suggestion_verbose(
|
||||
rustc_span::DUMMY_SP,
|
||||
"consider enabling this feature",
|
||||
"#![feature(generic_const_exprs)]\n".to_string(),
|
||||
rustc_errors::Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
rustc_errors::FatalError.raise();
|
||||
}
|
||||
|
||||
debug!(?concrete, "is_const_evaluatable");
|
||||
match concrete {
|
||||
Err(ErrorHandled::TooGeneric) => Err(match uv.has_infer_types_or_consts() {
|
||||
@ -178,6 +185,37 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fn satisfied_from_param_env<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ct: AbstractConst<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Result<bool, NotConstEvaluatable> {
|
||||
for pred in param_env.caller_bounds() {
|
||||
match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||
if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
|
||||
// Try to unify with each subtree in the AbstractConst to allow for
|
||||
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
|
||||
// predicate for `(N + 1) * 2`
|
||||
let result =
|
||||
walk_abstract_const(tcx, b_ct, |b_ct| match try_unify(tcx, ct, b_ct) {
|
||||
true => ControlFlow::BREAK,
|
||||
false => ControlFlow::CONTINUE,
|
||||
});
|
||||
|
||||
if let ControlFlow::Break(()) = result {
|
||||
debug!("is_const_evaluatable: abstract_const ~~> ok");
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {} // don't care
|
||||
}
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
/// A tree representing an anonymous constant.
|
||||
///
|
||||
/// This is only able to represent a subset of `MIR`,
|
||||
|
@ -1170,8 +1170,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
|
||||
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> const Drop for Box<T, A> {
|
||||
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
|
||||
fn drop(&mut self) {
|
||||
// FIXME: Do nothing, drop is currently performed by compiler.
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ fn const_box() {
|
||||
*boxed = 42;
|
||||
assert!(*boxed == 42);
|
||||
|
||||
*boxed
|
||||
*Box::leak(boxed)
|
||||
};
|
||||
|
||||
assert!(VALUE == 42);
|
||||
|
@ -4,9 +4,11 @@
|
||||
/// created from an iterator. This is common for types which describe a
|
||||
/// collection of some kind.
|
||||
///
|
||||
/// [`FromIterator::from_iter()`] is rarely called explicitly, and is instead
|
||||
/// used through [`Iterator::collect()`] method. See [`Iterator::collect()`]'s
|
||||
/// documentation for more examples.
|
||||
/// If you want to create a collection from the contents of an iterator, the
|
||||
/// [`Iterator::collect()`] method is preferred. However, when you need to
|
||||
/// specify the container type, [`FromIterator::from_iter()`] can be more
|
||||
/// readable than using a turbofish (e.g. `::<Vec<_>>()`). See the
|
||||
/// [`Iterator::collect()`] documentation for more examples of its use.
|
||||
///
|
||||
/// See also: [`IntoIterator`].
|
||||
///
|
||||
@ -32,6 +34,17 @@
|
||||
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
|
||||
/// ```
|
||||
///
|
||||
/// Using [`FromIterator::from_iter()`] as a more readable alternative to
|
||||
/// [`Iterator::collect()`]:
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::VecDeque;
|
||||
/// let first = (0..10).collect::<VecDeque<i32>>();
|
||||
/// let second = VecDeque::from_iter(0..10);
|
||||
///
|
||||
/// assert_eq!(first, second);
|
||||
/// ```
|
||||
///
|
||||
/// Implementing `FromIterator` for your type:
|
||||
///
|
||||
/// ```
|
||||
|
@ -364,6 +364,11 @@ extern crate std as realstd;
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
// The runtime entry point and a few unstable public functions used by the
|
||||
// compiler
|
||||
#[macro_use]
|
||||
pub mod rt;
|
||||
|
||||
// The Rust prelude
|
||||
pub mod prelude;
|
||||
|
||||
@ -548,11 +553,6 @@ pub mod arch {
|
||||
#[stable(feature = "simd_x86", since = "1.27.0")]
|
||||
pub use std_detect::is_x86_feature_detected;
|
||||
|
||||
// The runtime entry point and a few unstable public functions used by the
|
||||
// compiler
|
||||
#[macro_use]
|
||||
pub mod rt;
|
||||
|
||||
// Platform-abstraction modules
|
||||
mod sys;
|
||||
mod sys_common;
|
||||
|
@ -1287,12 +1287,31 @@ unsafe impl<'scope, T: Sync> Sync for Packet<'scope, T> {}
|
||||
|
||||
impl<'scope, T> Drop for Packet<'scope, T> {
|
||||
fn drop(&mut self) {
|
||||
// If this packet was for a thread that ran in a scope, the thread
|
||||
// panicked, and nobody consumed the panic payload, we make sure
|
||||
// the scope function will panic.
|
||||
let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_)));
|
||||
// Drop the result without causing unwinding.
|
||||
// This is only relevant for threads that aren't join()ed, as
|
||||
// join() will take the `result` and set it to None, such that
|
||||
// there is nothing left to drop here.
|
||||
// If this panics, we should handle that, because we're outside the
|
||||
// outermost `catch_unwind` of our thread.
|
||||
// We just abort in that case, since there's nothing else we can do.
|
||||
// (And even if we tried to handle it somehow, we'd also need to handle
|
||||
// the case where the panic payload we get out of it also panics on
|
||||
// drop, and so on. See issue #86027.)
|
||||
if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
*self.result.get_mut() = None;
|
||||
})) {
|
||||
rtabort!("thread result panicked on drop");
|
||||
}
|
||||
// Book-keeping so the scope knows when it's done.
|
||||
if let Some(scope) = self.scope {
|
||||
// If this packet was for a thread that ran in a scope, the thread
|
||||
// panicked, and nobody consumed the panic payload, we make sure
|
||||
// the scope function will panic.
|
||||
let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_)));
|
||||
// Now that there will be no more user code running on this thread
|
||||
// that can use 'scope, mark the thread as 'finished'.
|
||||
// It's important we only do this after the `result` has been dropped,
|
||||
// since dropping it might still use things it borrowed from 'scope.
|
||||
scope.decrement_num_running_threads(unhandled_panic);
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ use crate::mem;
|
||||
use crate::panic::panic_any;
|
||||
use crate::result;
|
||||
use crate::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
mpsc::{channel, Sender},
|
||||
Arc, Barrier,
|
||||
};
|
||||
use crate::thread::{self, ThreadId};
|
||||
use crate::thread::{self, Scope, ThreadId};
|
||||
use crate::time::Duration;
|
||||
use crate::time::Instant;
|
||||
|
||||
@ -293,5 +294,25 @@ fn test_thread_id_not_equal() {
|
||||
assert!(thread::current().id() != spawned_id);
|
||||
}
|
||||
|
||||
// NOTE: the corresponding test for stderr is in ui/thread-stderr, due
|
||||
// to the test harness apparently interfering with stderr configuration.
|
||||
#[test]
|
||||
fn test_scoped_threads_drop_result_before_join() {
|
||||
let actually_finished = &AtomicBool::new(false);
|
||||
struct X<'scope, 'env>(&'scope Scope<'scope, 'env>, &'env AtomicBool);
|
||||
impl Drop for X<'_, '_> {
|
||||
fn drop(&mut self) {
|
||||
thread::sleep(Duration::from_millis(20));
|
||||
let actually_finished = self.1;
|
||||
self.0.spawn(move || {
|
||||
thread::sleep(Duration::from_millis(20));
|
||||
actually_finished.store(true, Ordering::Relaxed);
|
||||
});
|
||||
}
|
||||
}
|
||||
thread::scope(|s| {
|
||||
s.spawn(move || {
|
||||
thread::sleep(Duration::from_millis(20));
|
||||
X(s, actually_finished)
|
||||
});
|
||||
});
|
||||
assert!(actually_finished.load(Ordering::Relaxed));
|
||||
}
|
||||
|
@ -4,3 +4,7 @@ title = "The rustdoc book"
|
||||
|
||||
[output.html]
|
||||
git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustdoc"
|
||||
|
||||
[output.html.redirect]
|
||||
"/the-doc-attribute.html" = "write-documentation/the-doc-attribute.html"
|
||||
"/documentation-tests.html" = "write-documentation/documentation-tests.html"
|
||||
|
@ -1,16 +1,15 @@
|
||||
# The Rustdoc Book
|
||||
|
||||
- [What is rustdoc?](what-is-rustdoc.md)
|
||||
- [Command-line arguments](command-line-arguments.md)
|
||||
- [How to read rustdoc output](how-to-read-rustdoc.md)
|
||||
- [How to write documentation](how-to-write-documentation.md)
|
||||
- [What to include (and exclude)](what-to-include.md)
|
||||
- [Command-line arguments](command-line-arguments.md)
|
||||
- [The `#[doc]` attribute](the-doc-attribute.md)
|
||||
- [Documentation tests](documentation-tests.md)
|
||||
- [Linking to items by name](linking-to-items-by-name.md)
|
||||
- [Lints](lints.md)
|
||||
- [What to include (and exclude)](write-documentation/what-to-include.md)
|
||||
- [The `#[doc]` attribute](write-documentation/the-doc-attribute.md)
|
||||
- [Linking to items by name](write-documentation/linking-to-items-by-name.md)
|
||||
- [Documentation tests](write-documentation/documentation-tests.md)
|
||||
- [Rustdoc-specific lints](lints.md)
|
||||
- [Advanced features](advanced-features.md)
|
||||
- [Unstable features](unstable-features.md)
|
||||
- [Website features](website-features.md)
|
||||
- [Passes](passes.md)
|
||||
- [Deprecated features](deprecated-features.md)
|
||||
- [References](references.md)
|
||||
|
@ -88,3 +88,25 @@ You can add multiple aliases at the same time by using a list:
|
||||
#[doc(alias("x", "big"))]
|
||||
pub struct BigX;
|
||||
```
|
||||
|
||||
## Custom search engines
|
||||
|
||||
If you find yourself often referencing online Rust docs you might enjoy using a custom search
|
||||
engine. This allows you to use the navigation bar directly to search a `rustdoc` website.
|
||||
Most browsers support this feature by letting you define a URL template containing `%s`
|
||||
which will be substituted for the search term. As an example, for the standard library you could use
|
||||
this template:
|
||||
|
||||
```text
|
||||
https://doc.rust-lang.org/stable/std/?search=%s
|
||||
```
|
||||
|
||||
Note that this will take you to a results page listing all matches. If you want to navigate to the first
|
||||
result right away (which is often the best match) use the following instead:
|
||||
|
||||
```text
|
||||
https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true
|
||||
```
|
||||
|
||||
This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL
|
||||
to automatically go to the first result.
|
||||
|
@ -177,7 +177,7 @@ $ rustdoc src/lib.rs --test
|
||||
```
|
||||
|
||||
This flag will run your code examples as tests. For more, see [the chapter
|
||||
on documentation tests](documentation-tests.md).
|
||||
on documentation tests](write-documentation/documentation-tests.md).
|
||||
|
||||
See also `--test-args`.
|
||||
|
||||
@ -190,7 +190,7 @@ $ rustdoc src/lib.rs --test --test-args ignored
|
||||
```
|
||||
|
||||
This flag will pass options to the test runner when running documentation tests.
|
||||
For more, see [the chapter on documentation tests](documentation-tests.md).
|
||||
For more, see [the chapter on documentation tests](write-documentation/documentation-tests.md).
|
||||
|
||||
See also `--test`.
|
||||
|
||||
@ -336,7 +336,7 @@ $ rustdoc src/lib.rs --sysroot /path/to/sysroot
|
||||
Similar to `rustc --sysroot`, this lets you change the sysroot `rustdoc` uses
|
||||
when compiling your code.
|
||||
|
||||
### `--edition`: control the edition of docs and doctests
|
||||
## `--edition`: control the edition of docs and doctests
|
||||
|
||||
Using this flag looks like this:
|
||||
|
||||
@ -403,12 +403,12 @@ encoded as UTF-8.
|
||||
## `--passes`: add more rustdoc passes
|
||||
|
||||
This flag is **deprecated**.
|
||||
For more details on passes, see [the chapter on them](passes.md).
|
||||
For more details on passes, see [the chapter on them](deprecated-features.md#passes).
|
||||
|
||||
## `--no-defaults`: don't run default passes
|
||||
|
||||
This flag is **deprecated**.
|
||||
For more details on passes, see [the chapter on them](passes.md).
|
||||
For more details on passes, see [the chapter on them](deprecated-features.md#passes).
|
||||
|
||||
## `-r`/`--input-format`: input format
|
||||
|
||||
@ -417,23 +417,3 @@ This flag is **deprecated** and **has no effect**.
|
||||
Rustdoc only supports Rust source code and Markdown input formats. If the
|
||||
file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file.
|
||||
Otherwise, it assumes that the input file is Rust.
|
||||
|
||||
# Unstable command line arguments
|
||||
|
||||
## `--nocapture`
|
||||
|
||||
When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be
|
||||
captured by rustdoc. Instead, the output will be directed to your terminal,
|
||||
as if you had run the test executable manually. This is especially useful
|
||||
for debugging your tests!
|
||||
|
||||
## `--check`
|
||||
|
||||
When this flag is supplied, rustdoc will type check and lint your code, but will not generate any
|
||||
documentation or run your doctests.
|
||||
|
||||
Using this flag looks like:
|
||||
|
||||
```bash
|
||||
rustdoc -Z unstable-options --check src/lib.rs
|
||||
```
|
||||
|
@ -1,4 +1,6 @@
|
||||
# Passes
|
||||
# Deprecated features
|
||||
|
||||
## Passes
|
||||
|
||||
Rustdoc has a concept called "passes". These are transformations that
|
||||
`rustdoc` runs on your documentation before producing its final output.
|
@ -26,7 +26,7 @@ At the top is some at-a-glance info and controls:
|
||||
- a button to collapse or expand the top-level documentation for that item
|
||||
(`[+]` or `[-]`),
|
||||
- a link to the source code (`[src]`),
|
||||
if [configured](the-doc-attribute.html#html_no_source),
|
||||
if [configured](write-documentation/the-doc-attribute.html#html_no_source),
|
||||
and present (the source may not be available if
|
||||
the documentation was created with `cargo doc --no-deps`),
|
||||
- and the version in which the item became stable,
|
||||
@ -52,7 +52,7 @@ For example, when looking at documentation for the crate root,
|
||||
it shows all the crates documented in the documentation bundle,
|
||||
and quick links to the modules, structs, traits, functions, and macros available
|
||||
from the current crate.
|
||||
At the top, it displays a [configurable logo](the-doc-attribute.html#html_logo_url)
|
||||
At the top, it displays a [configurable logo](write-documentation/the-doc-attribute.html#html_logo_url)
|
||||
alongside the current crate's name and version,
|
||||
or the current item whose documentation is being displayed.
|
||||
|
||||
|
@ -13,11 +13,11 @@ Note that, except for `missing_docs`, these lints are only available when runnin
|
||||
|
||||
Here is the list of the lints provided by `rustdoc`:
|
||||
|
||||
## broken_intra_doc_links
|
||||
## `broken_intra_doc_links`
|
||||
|
||||
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.md
|
||||
[intra-doc link]: write-documentation/linking-to-items-by-name.md
|
||||
|
||||
```rust
|
||||
/// I want to link to [`Nonexistent`] but it doesn't exist!
|
||||
@ -64,7 +64,7 @@ help: to link to the function, add parentheses
|
||||
|
||||
```
|
||||
|
||||
## private_intra_doc_links
|
||||
## `private_intra_doc_links`
|
||||
|
||||
This lint **warns by default**. This lint detects when [intra-doc links] from public to private items.
|
||||
For example:
|
||||
@ -104,9 +104,9 @@ warning: public documentation for `public` links to private item `private`
|
||||
= note: this link resolves only because you passed `--document-private-items`, but will break without
|
||||
```
|
||||
|
||||
[intra-doc links]: linking-to-items-by-name.html
|
||||
[intra-doc links]: write-documentation/linking-to-items-by-name.md
|
||||
|
||||
## missing_docs
|
||||
## `missing_docs`
|
||||
|
||||
This lint is **allowed by default**. It detects items missing documentation.
|
||||
For example:
|
||||
@ -130,7 +130,7 @@ warning: missing documentation for a function
|
||||
|
||||
Note that unlike other rustdoc lints, this lint is also available from `rustc` directly.
|
||||
|
||||
## missing_crate_level_docs
|
||||
## `missing_crate_level_docs`
|
||||
|
||||
This lint is **allowed by default**. It detects if there is no documentation
|
||||
at the crate root. For example:
|
||||
@ -154,7 +154,7 @@ warning in the future. This is intended as a means to introduce new users on
|
||||
get started, without providing overwhelming warnings like `missing_docs`
|
||||
might.
|
||||
|
||||
## missing_doc_code_examples
|
||||
## `missing_doc_code_examples`
|
||||
|
||||
This lint is **allowed by default** and is **nightly-only**. It detects when a documentation block
|
||||
is missing a code example. For example:
|
||||
@ -190,7 +190,7 @@ To fix the lint, you need to add a code example into the documentation block:
|
||||
pub fn no_code_example() {}
|
||||
```
|
||||
|
||||
## private_doc_tests
|
||||
## `private_doc_tests`
|
||||
|
||||
This lint is **allowed by default**. It detects documentation tests when they
|
||||
are on a private item. For example:
|
||||
@ -223,7 +223,7 @@ warning: Documentation test in private item
|
||||
| |___________^
|
||||
```
|
||||
|
||||
## invalid_codeblock_attributes
|
||||
## `invalid_codeblock_attributes`
|
||||
|
||||
This lint **warns by default**. It detects code block attributes in
|
||||
documentation examples that have potentially mis-typed values. For example:
|
||||
@ -259,7 +259,7 @@ warning: unknown attribute `should-panic`. Did you mean `should_panic`?
|
||||
In the example above, the correct form is `should_panic`. This helps detect
|
||||
typo mistakes for some common attributes.
|
||||
|
||||
## invalid_html_tags
|
||||
## `invalid_html_tags`
|
||||
|
||||
This lint is **allowed by default** and is **nightly-only**. It detects unclosed
|
||||
or invalid HTML tags. For example:
|
||||
@ -298,7 +298,7 @@ warning: unclosed HTML tag `h1`
|
||||
warning: 2 warnings emitted
|
||||
```
|
||||
|
||||
## invalid_rust_codeblocks
|
||||
## `invalid_rust_codeblocks`
|
||||
|
||||
This lint **warns by default**. It detects Rust code blocks in documentation
|
||||
examples that are invalid (e.g. empty, not parsable as Rust). For example:
|
||||
@ -342,7 +342,7 @@ warning: could not parse code block as Rust code
|
||||
= note: error from rustc: unterminated character literal
|
||||
```
|
||||
|
||||
## bare_urls
|
||||
## `bare_urls`
|
||||
|
||||
This lint is **warn-by-default**. It detects URLs which are not links.
|
||||
For example:
|
||||
|
@ -22,7 +22,7 @@ As detailed in [the chapter on documentation tests][doctest-attributes], you can
|
||||
nightly, you can optionally add an error number to state that a doctest should emit a specific error
|
||||
number:
|
||||
|
||||
[doctest-attributes]: documentation-tests.html#attributes
|
||||
[doctest-attributes]: write-documentation/documentation-tests.html#attributes
|
||||
|
||||
``````markdown
|
||||
```compile_fail,E0044
|
||||
@ -45,6 +45,8 @@ and enabled with a `#![feature(...)]` attribute in your crate.
|
||||
|
||||
### `#[doc(cfg)]`: Recording what platforms or features are required for code to be present
|
||||
|
||||
* Tracking issue: [#43781](https://github.com/rust-lang/rust/issues/43781)
|
||||
|
||||
You can use `#[doc(cfg(...))]` to tell Rustdoc exactly which platform items appear on.
|
||||
This has two effects:
|
||||
|
||||
@ -86,6 +88,8 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg].
|
||||
|
||||
### `doc_auto_cfg`: Automatically generate `#[doc(cfg)]`
|
||||
|
||||
* Tracking issue: [#43781](https://github.com/rust-lang/rust/issues/43781)
|
||||
|
||||
`doc_auto_cfg` is an extension to the `#[doc(cfg)]` feature. With it, you don't need to add
|
||||
`#[doc(cfg(...)]` anymore unless you want to override the default behaviour. So if we take the
|
||||
previous source code:
|
||||
@ -123,6 +127,8 @@ And `doc` won't show up anymore!
|
||||
|
||||
### Adding your trait to the "Notable traits" dialog
|
||||
|
||||
* Tracking issue: [#45040](https://github.com/rust-lang/rust/issues/45040)
|
||||
|
||||
Rustdoc keeps a list of a few traits that are believed to be "fundamental" to
|
||||
types that implement them. These traits are intended to be the primary interface
|
||||
for their implementers, and are often most of the API available to be documented
|
||||
@ -146,6 +152,8 @@ and [its tracking issue][issue-notable_trait].
|
||||
|
||||
### Exclude certain dependencies from documentation
|
||||
|
||||
* Tracking issue: [#44027](https://github.com/rust-lang/rust/issues/44027)
|
||||
|
||||
The standard library uses several dependencies which, in turn, use several types and traits from the
|
||||
standard library. In addition, there are several compiler-internal crates that are not considered to
|
||||
be part of the official standard library, and thus would be a distraction to include in
|
||||
@ -164,8 +172,7 @@ Book][unstable-masked] and [its tracking issue][issue-masked].
|
||||
[unstable-masked]: ../unstable-book/language-features/doc-masked.html
|
||||
[issue-masked]: https://github.com/rust-lang/rust/issues/44027
|
||||
|
||||
|
||||
## Document primitives
|
||||
### Document primitives
|
||||
|
||||
This is for Rust compiler internal use only.
|
||||
|
||||
@ -174,7 +181,7 @@ attributes. The `#[doc(primitive)]` attribute is used by the standard library to
|
||||
to generate documentation for primitive types, and requires `#![feature(rustdoc_internals)]` to
|
||||
enable.
|
||||
|
||||
## Document keywords
|
||||
### Document keywords
|
||||
|
||||
This is for Rust compiler internal use only.
|
||||
|
||||
@ -199,6 +206,8 @@ the flag in question to Rustdoc on the command-line. To do this from Cargo, you
|
||||
|
||||
### `--markdown-before-content`: include rendered Markdown before the content
|
||||
|
||||
* Tracking issue: [#44027](https://github.com/rust-lang/rust/issues/44027)
|
||||
|
||||
Using this flag looks like this:
|
||||
|
||||
```bash
|
||||
@ -241,7 +250,7 @@ attribute][doc-playground]. Please be aware that the official Rust Playground at
|
||||
https://play.rust-lang.org does not have every crate available, so if your examples require your
|
||||
crate, make sure the playground you provide has your crate available.
|
||||
|
||||
[doc-playground]: the-doc-attribute.html#html_playground_url
|
||||
[doc-playground]: write-documentation/the-doc-attribute.html#html_playground_url
|
||||
|
||||
If both `--playground-url` and `--markdown-playground-url` are present when rendering a standalone
|
||||
Markdown file, the URL given to `--markdown-playground-url` will take precedence. If both
|
||||
@ -279,6 +288,8 @@ between compilations.
|
||||
|
||||
### `--resource-suffix`: modifying the name of CSS/JavaScript in crate docs
|
||||
|
||||
* Tracking issue: [#54765](https://github.com/rust-lang/rust/issues/54765)
|
||||
|
||||
Using this flag looks like this:
|
||||
|
||||
```bash
|
||||
@ -331,6 +342,24 @@ Using `index-page` option enables `enable-index-page` option as well.
|
||||
|
||||
This feature allows the generation of a default index-page which lists the generated crates.
|
||||
|
||||
### `--nocapture`: disable output capture for test
|
||||
|
||||
When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be
|
||||
captured by rustdoc. Instead, the output will be directed to your terminal,
|
||||
as if you had run the test executable manually. This is especially useful
|
||||
for debugging your tests!
|
||||
|
||||
### `--check`: only checks the documentation
|
||||
|
||||
When this flag is supplied, rustdoc will type check and lint your code, but will not generate any
|
||||
documentation or run your doctests.
|
||||
|
||||
Using this flag looks like:
|
||||
|
||||
```bash
|
||||
rustdoc -Z unstable-options --check src/lib.rs
|
||||
```
|
||||
|
||||
### `--static-root-path`: control how static files are loaded in HTML output
|
||||
|
||||
Using this flag looks like this:
|
||||
@ -348,6 +377,8 @@ renamed with `--resource-suffix` will load from the given path.
|
||||
|
||||
### `--persist-doctests`: persist doctest executables after running
|
||||
|
||||
* Tracking issue: [#56925](https://github.com/rust-lang/rust/issues/56925)
|
||||
|
||||
Using this flag looks like this:
|
||||
|
||||
```bash
|
||||
@ -360,6 +391,8 @@ with this option, you can keep those binaries around for farther testing.
|
||||
|
||||
### `--show-coverage`: calculate the percentage of items with documentation
|
||||
|
||||
* Tracking issue: [#58154](https://github.com/rust-lang/rust/issues/58154)
|
||||
|
||||
Using this flag looks like this:
|
||||
|
||||
```bash
|
||||
@ -438,6 +471,8 @@ information.
|
||||
|
||||
### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests
|
||||
|
||||
* Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245)
|
||||
|
||||
Using this flag looks like this:
|
||||
|
||||
```bash
|
||||
@ -471,6 +506,8 @@ override `ignore`.
|
||||
|
||||
### `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it
|
||||
|
||||
* Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245)
|
||||
|
||||
Using these options looks like this:
|
||||
|
||||
```bash
|
||||
@ -488,6 +525,8 @@ Another use case would be to run a test inside an emulator, or through a Virtual
|
||||
|
||||
### `--with-examples`: include examples of uses of items as documentation
|
||||
|
||||
* Tracking issue: [#88791](https://github.com/rust-lang/rust/issues/88791)
|
||||
|
||||
This option, combined with `--scrape-examples-target-crate` and
|
||||
`--scrape-examples-output-path`, is used to implement the functionality in [RFC
|
||||
#3123](https://github.com/rust-lang/rfcs/pull/3123). Uses of an item (currently
|
||||
@ -515,6 +554,8 @@ add the `--scrape-tests` flag.
|
||||
|
||||
### `--check-cfg`: check configuration flags
|
||||
|
||||
* Tracking issue: [#82450](https://github.com/rust-lang/rust/issues/82450)
|
||||
|
||||
This flag accepts the same values as `rustc --check-cfg`, and uses it to check configuration flags.
|
||||
|
||||
Using this flag looks like this:
|
||||
|
@ -1,25 +0,0 @@
|
||||
# Website features
|
||||
|
||||
These features are about using the website generated by `rustdoc`.
|
||||
|
||||
## Custom search engines
|
||||
|
||||
If you find yourself often referencing online Rust docs you might enjoy using a custom search
|
||||
engine. This allows you to use the navigation bar directly to search a `rustdoc` website.
|
||||
Most browsers support this feature by letting you define a URL template containing `%s`
|
||||
which will be substituted for the search term. As an example, for the standard library you could use
|
||||
this template:
|
||||
|
||||
```text
|
||||
https://doc.rust-lang.org/stable/std/?search=%s
|
||||
```
|
||||
|
||||
Note that this will take you to a results page listing all matches. If you want to navigate to the first
|
||||
result right away (which is often the best match) use the following instead:
|
||||
|
||||
```text
|
||||
https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true
|
||||
```
|
||||
|
||||
This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL
|
||||
to automatically go to the first result.
|
@ -269,7 +269,7 @@ By default, this will still hide `unused` warnings, since so many examples use p
|
||||
you can add `#![warn(unused)]` to the top of your example if you want to see unused variables or dead code warnings.
|
||||
You can also use [`#![doc(test(attr(warn(unused))))]`][test-attr] in the crate root to enable warnings globally.
|
||||
|
||||
[test-attr]: ./the-doc-attribute.md#testattr
|
||||
[test-attr]: the-doc-attribute.md#testattr
|
||||
|
||||
## Documenting macros
|
||||
|
@ -35,7 +35,7 @@ link to `Option`.
|
||||
You can refer to anything in scope, and use paths, including `Self`, `self`, `super`, and
|
||||
`crate`. Associated items (functions, types, and constants) are supported, but [not for blanket
|
||||
trait implementations][#79682]. Rustdoc also supports linking to all primitives listed in
|
||||
[the standard library documentation](../std/index.html#primitives).
|
||||
[the standard library documentation](../../std/index.html#primitives).
|
||||
|
||||
[#79682]: https://github.com/rust-lang/rust/pull/79682
|
||||
|
@ -38,7 +38,7 @@ but given that docs are rendered via Markdown, it will remove these newlines.
|
||||
Another use case is for including external files as documentation:
|
||||
|
||||
```rust,no_run
|
||||
#[doc = include_str!("../README.md")]
|
||||
#[doc = include_str!("../../README.md")]
|
||||
# fn f() {}
|
||||
```
|
||||
|
||||
@ -73,7 +73,7 @@ left hand side of the docs.
|
||||
#![doc(html_logo_url = "https://example.com/logo.jpg")]
|
||||
```
|
||||
|
||||
This will put `<a href='index.html'><img src='{}' alt='logo' width='100'></a>` into
|
||||
This will put `<a href='../index.html'><img src='{}' alt='logo' width='100'></a>` into
|
||||
your docs, where the string for the attribute goes into the `{}`.
|
||||
|
||||
If you don't use this attribute, there will be no logo.
|
@ -122,4 +122,4 @@ Here is an example of a new theme, [Ayu].
|
||||
[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html#rustdoc-does-not-show-unhelpful-implementation-details-c-hidden
|
||||
[Documentation tests]: documentation-tests.md
|
||||
[on this blog]: https://blog.guillaume-gomez.fr/articles/2016-09-16+Generating+doc+with+rustdoc+and+a+custom+theme
|
||||
[rustdoc-lints]: lints.md
|
||||
[rustdoc-lints]: ../lints.md
|
@ -1460,6 +1460,7 @@ fn init_id_map() -> FxHashMap<String, usize> {
|
||||
map.insert("provided-methods".to_owned(), 1);
|
||||
map.insert("implementors".to_owned(), 1);
|
||||
map.insert("synthetic-implementors".to_owned(), 1);
|
||||
map.insert("implementations-list".to_owned(), 1);
|
||||
map.insert("trait-implementations-list".to_owned(), 1);
|
||||
map.insert("synthetic-implementations-list".to_owned(), 1);
|
||||
map.insert("blanket-implementations-list".to_owned(), 1);
|
||||
|
@ -1065,14 +1065,15 @@ fn render_assoc_items_inner(
|
||||
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
|
||||
if !non_trait.is_empty() {
|
||||
let mut tmp_buf = Buffer::empty_from(w);
|
||||
let render_mode = match what {
|
||||
let (render_mode, id) = match what {
|
||||
AssocItemRender::All => {
|
||||
tmp_buf.write_str(
|
||||
"<h2 id=\"implementations\" class=\"small-section-header\">\
|
||||
Implementations<a href=\"#implementations\" class=\"anchor\"></a>\
|
||||
</h2>",
|
||||
Implementations\
|
||||
<a href=\"#implementations\" class=\"anchor\"></a>\
|
||||
</h2>",
|
||||
);
|
||||
RenderMode::Normal
|
||||
(RenderMode::Normal, "implementations-list".to_owned())
|
||||
}
|
||||
AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
|
||||
let id =
|
||||
@ -1090,7 +1091,7 @@ fn render_assoc_items_inner(
|
||||
trait_ = trait_.print(cx),
|
||||
type_ = type_.print(cx),
|
||||
);
|
||||
RenderMode::ForDeref { mut_: deref_mut_ }
|
||||
(RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id))
|
||||
}
|
||||
};
|
||||
let mut impls_buf = Buffer::empty_from(w);
|
||||
@ -1115,7 +1116,9 @@ fn render_assoc_items_inner(
|
||||
}
|
||||
if !impls_buf.is_empty() {
|
||||
w.push_buffer(tmp_buf);
|
||||
write!(w, "<div id=\"{}\">", id);
|
||||
w.push_buffer(impls_buf);
|
||||
w.write_str("</div>");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1146,7 +1149,8 @@ fn render_assoc_items_inner(
|
||||
write!(
|
||||
w,
|
||||
"<h2 id=\"trait-implementations\" class=\"small-section-header\">\
|
||||
Trait Implementations<a href=\"#trait-implementations\" class=\"anchor\"></a>\
|
||||
Trait Implementations\
|
||||
<a href=\"#trait-implementations\" class=\"anchor\"></a>\
|
||||
</h2>\
|
||||
<div id=\"trait-implementations-list\">{}</div>",
|
||||
impls
|
||||
|
@ -741,7 +741,7 @@ function hideThemeButtonState() {
|
||||
} else {
|
||||
addClass(innerToggle, "will-expand");
|
||||
onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
|
||||
if (e.parentNode.id !== MAIN_ID ||
|
||||
if (e.parentNode.id !== "implementations-list" ||
|
||||
(!hasClass(e, "implementors-toggle") &&
|
||||
!hasClass(e, "type-contents-toggle")))
|
||||
{
|
||||
|
@ -12,10 +12,10 @@ assert-property: (".top-doc .docblock table", {"scrollWidth": "1573"})
|
||||
|
||||
// Logically, the ".docblock" and the "<p>" should have the same scroll width.
|
||||
compare-elements-property: (
|
||||
"#implementations + details .docblock",
|
||||
"#implementations + details .docblock > p",
|
||||
"#implementations-list > details .docblock",
|
||||
"#implementations-list > details .docblock > p",
|
||||
["scrollWidth"],
|
||||
)
|
||||
assert-property: ("#implementations + details .docblock", {"scrollWidth": "801"})
|
||||
assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "801"})
|
||||
// However, since there is overflow in the <table>, its scroll width is bigger.
|
||||
assert-property: ("#implementations + details .docblock table", {"scrollWidth": "1573"})
|
||||
assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1573"})
|
||||
|
@ -3,9 +3,9 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.borrow
|
||||
// In the blanket implementations list, "Borrow" is the second one, hence the ":nth(2)".
|
||||
assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"open": ""})
|
||||
// We first check that the impl block is open by default.
|
||||
assert-attribute: ("#implementations + details", {"open": ""})
|
||||
assert-attribute: ("#implementations-list details", {"open": ""})
|
||||
// To ensure that we will click on the currently hidden method.
|
||||
assert-text: (".sidebar-elems section .block li > a", "must_use")
|
||||
click: ".sidebar-elems section .block li > a"
|
||||
// We check that the impl block was opened as expected so that we can see the method.
|
||||
assert-attribute: ("#implementations + details", {"open": ""})
|
||||
assert-attribute: ("#implementations-list > details", {"open": ""})
|
||||
|
@ -1,3 +1,3 @@
|
||||
// This test ensures that the impl blocks are open by default.
|
||||
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
|
||||
assert-attribute: ("#main-content > details.implementors-toggle", {"open": ""})
|
||||
assert-attribute: ("#implementations-list details.implementors-toggle", {"open": ""})
|
||||
|
@ -14,7 +14,7 @@ assert-attribute: (".top-doc", {"open": ""})
|
||||
// Assert the position of the toggle on the top doc block.
|
||||
assert-position: (".top-doc summary::before", {"x": 4})
|
||||
// Assert the position of the toggle on the impl block.
|
||||
assert-position: ("#implementations + details > summary::before", {"x": 4})
|
||||
assert-position: ("#implementations-list > details > summary::before", {"x": 4})
|
||||
// Assert the position of the toggle on a method.
|
||||
assert-position: (
|
||||
"#trait-implementations-list .impl-items .method-toggle > summary::before",
|
||||
|
@ -24,7 +24,7 @@ wait-for: 50
|
||||
assert-text: ("#toggle-all-docs", "[+]")
|
||||
// We check that all <details> are collapsed (except for the impl block ones).
|
||||
assert-attribute-false: ("details.rustdoc-toggle:not(.implementors-toggle)", {"open": ""}, ALL)
|
||||
assert-attribute: ("details.rustdoc-toggle.implementors-toggle", {"open": ""})
|
||||
assert-attribute: ("#implementations-list > details.implementors-toggle", {"open": ""})
|
||||
// We now check that the other impl blocks are collapsed.
|
||||
assert-attribute-false: (
|
||||
"#blanket-implementations-list > details.rustdoc-toggle.implementors-toggle",
|
||||
|
@ -1,8 +1,10 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// @has issue_33054/impls/struct.Foo.html
|
||||
// @has - '//h3[@class="code-header in-band"]' 'impl Foo'
|
||||
// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo'
|
||||
// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
|
||||
// @count - '//*[@id="main-content"]/details/summary/*[@class="impl has-srclink"]' 1
|
||||
// @count - '//*[@id="main-content"]/div[@id="implementations-list"]/details/summary/*[@class="impl has-srclink"]' 1
|
||||
// @has issue_33054/impls/bar/trait.Bar.html
|
||||
// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo'
|
||||
// @count - '//*[@class="struct"]' 1
|
||||
|
@ -0,0 +1,21 @@
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
pub struct If<const CONDITION: bool>;
|
||||
|
||||
pub trait True {}
|
||||
|
||||
impl True for If<true> {}
|
||||
|
||||
pub struct FixedI32<const FRAC: u32>;
|
||||
|
||||
impl<const FRAC: u32> FromStr for FixedI32<FRAC>
|
||||
where
|
||||
If<{ FRAC <= 32 }>: True,
|
||||
{
|
||||
type Err = ();
|
||||
fn from_str(_s: &str) -> Result<Self, Self::Err> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
// aux-build:issue-94287-aux.rs
|
||||
// build-fail
|
||||
|
||||
extern crate issue_94287_aux;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
fn main() {
|
||||
let _ = <issue_94287_aux::FixedI32<16>>::from_str("");
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
error: failed to evaluate generic const expression
|
||||
--> $DIR/auxiliary/issue-94287-aux.rs:15:8
|
||||
|
|
||||
LL | If<{ FRAC <= 32 }>: True,
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the crate this constant originates from uses `#![feature(generic_const_exprs)]`
|
||||
help: consider enabling this feature
|
||||
|
|
||||
LL | #![feature(generic_const_exprs)]
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
4
src/test/ui/consts/drop_box.rs
Normal file
4
src/test/ui/consts/drop_box.rs
Normal file
@ -0,0 +1,4 @@
|
||||
const fn f<T>(_: Box<T>) {}
|
||||
//~^ ERROR destructors cannot be evaluated at compile-time
|
||||
|
||||
fn main() {}
|
11
src/test/ui/consts/drop_box.stderr
Normal file
11
src/test/ui/consts/drop_box.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0493]: destructors cannot be evaluated at compile-time
|
||||
--> $DIR/drop_box.rs:1:15
|
||||
|
|
||||
LL | const fn f<T>(_: Box<T>) {}
|
||||
| ^ - value is dropped here
|
||||
| |
|
||||
| constant functions cannot evaluate destructors
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0493`.
|
@ -489,16 +489,22 @@ fn is_exception(file: &Path, link: &str) -> bool {
|
||||
/// If the given HTML file contents is an HTML redirect, this returns the
|
||||
/// destination path given in the redirect.
|
||||
fn maybe_redirect(source: &str) -> Option<String> {
|
||||
const REDIRECT: &str = "<p>Redirecting to <a href=";
|
||||
const REDIRECT_RUSTDOC: (usize, &str) = (7, "<p>Redirecting to <a href=");
|
||||
const REDIRECT_MDBOOK: (usize, &str) = (8 - 7, "<p>Redirecting to... <a href=");
|
||||
|
||||
let mut lines = source.lines();
|
||||
let redirect_line = lines.nth(7)?;
|
||||
|
||||
redirect_line.find(REDIRECT).map(|i| {
|
||||
let rest = &redirect_line[(i + REDIRECT.len() + 1)..];
|
||||
let pos_quote = rest.find('"').unwrap();
|
||||
rest[..pos_quote].to_owned()
|
||||
})
|
||||
let mut find_redirect = |(line_rel, redirect_pattern): (usize, &str)| {
|
||||
let redirect_line = lines.nth(line_rel)?;
|
||||
|
||||
redirect_line.find(redirect_pattern).map(|i| {
|
||||
let rest = &redirect_line[(i + redirect_pattern.len() + 1)..];
|
||||
let pos_quote = rest.find('"').unwrap();
|
||||
rest[..pos_quote].to_owned()
|
||||
})
|
||||
};
|
||||
|
||||
find_redirect(REDIRECT_RUSTDOC).or_else(|| find_redirect(REDIRECT_MDBOOK))
|
||||
}
|
||||
|
||||
fn with_attrs_in_source<F: FnMut(&str, usize, &str)>(source: &str, attr: &str, mut f: F) {
|
||||
|
Loading…
Reference in New Issue
Block a user