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

Rollup of 6 pull requests #96015

Merged
merged 21 commits into from
Apr 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7e81b0a
Improve Rustdoc UI for scraped examples with multiline arguments, fix
willcrichton Jan 22, 2022
d58c9df
Only highlight identifier in scraped examples, not arguments
willcrichton Jan 25, 2022
f1e3e2c
Use PathSegment::ident for scraping method calls
willcrichton Jan 25, 2022
ae5d0cb
Improve alignment of additional scraped examples, add scrape examples…
willcrichton Jan 28, 2022
7cca693
Fix markdown issue, remove hard-coded rust-lang.org url
willcrichton Jan 28, 2022
bb3ed6f
Improve styling on scrape examples help button
willcrichton Jan 28, 2022
318e457
Clarify that scrape examples is unstable
willcrichton Jan 29, 2022
d1416d5
Add scrape examples help page
willcrichton Feb 15, 2022
b9ecdca
Don't panic when scraping invalid calls
willcrichton Mar 28, 2022
7cdef08
Document that DirEntry holds the directory open
sourcefrog Apr 12, 2022
6a18b68
Add Rustdoc book link to scrape examples help. Remove remaining panic
willcrichton Apr 12, 2022
71ad003
Improve error message when there's no checksum
Apr 13, 2022
212e98b
Add missing article to fix "few" to "a few".
hkBst Apr 13, 2022
c008d45
Add a missing article
hkBst Apr 13, 2022
9b9f677
fix: wrong trait import suggestion for T:
Apr 13, 2022
db61452
Rollup merge of #93217 - willcrichton:example-analyzer, r=GuillaumeGomez
Dylan-DPC Apr 13, 2022
d449a63
Rollup merge of #95885 - gimbles:patch-1, r=Mark-Simulacrum
Dylan-DPC Apr 13, 2022
032358b
Rollup merge of #95962 - sourcefrog:doc-direntry, r=Dylan-DPC
Dylan-DPC Apr 13, 2022
648d65a
Rollup merge of #95991 - PoorlyDefinedBehaviour:fix/issue_95898, r=fe…
Dylan-DPC Apr 13, 2022
e8050c0
Rollup merge of #96005 - hkBst:patch-1, r=Dylan-DPC
Dylan-DPC Apr 13, 2022
e95f2db
Rollup merge of #96006 - hkBst:patch-2, r=Dylan-DPC
Dylan-DPC Apr 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions compiler/rustc_typeck/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1880,9 +1880,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let sp = hir.span(id);
let sp = if let Some(first_bound) = has_bounds {
// `sp` only covers `T`, change it so that it covers
// `T:` when appropriate
sp.until(first_bound.span())
} else if let Some(colon_sp) =
// If the generic param is declared with a colon but without bounds:
// fn foo<T:>(t: T) { ... }
param.colon_span_for_suggestions(
self.inh.tcx.sess.source_map(),
)
{
sp.to(colon_sp)
} else {
sp
};
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/convert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@ pub const fn identity<T>(x: T) -> T {
/// If you need to do a costly conversion it is better to implement [`From`] with type
/// `&T` or write a custom function.
///
/// `AsRef` has the same signature as [`Borrow`], but [`Borrow`] is different in few aspects:
/// `AsRef` has the same signature as [`Borrow`], but [`Borrow`] is different in a few aspects:
///
/// - Unlike `AsRef`, [`Borrow`] has a blanket impl for any `T`, and can be used to accept either
/// a reference or a value.
/// - [`Borrow`] also requires that [`Hash`], [`Eq`] and [`Ord`] for borrowed value are
/// - [`Borrow`] also requires that [`Hash`], [`Eq`] and [`Ord`] for a borrowed value are
/// equivalent to those of the owned value. For this reason, if you want to
/// borrow only a single field of a struct you can implement `AsRef`, but not [`Borrow`].
///
Expand Down
10 changes: 10 additions & 0 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,16 @@ pub struct ReadDir(fs_imp::ReadDir);
/// An instance of `DirEntry` represents an entry inside of a directory on the
/// filesystem. Each entry can be inspected via methods to learn about the full
/// path or possibly other metadata through per-platform extension traits.
///
/// # Platform-specific behavior
///
/// On Unix, the `DirEntry` struct contains an internal reference to the open
/// directory. Holding `DirEntry` objects will consume a file handle even
/// after the `ReadDir` iterator is dropped.
///
/// Note that this [may change in the future][changes].
///
/// [changes]: io#platform-specific-behavior
#[stable(feature = "rust1", since = "1.0.0")]
pub struct DirEntry(fs_imp::DirEntry);

Expand Down
6 changes: 5 additions & 1 deletion src/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,11 @@ def get(base, url, path, checksums, verbose=False, do_verify=True, help_on_error
try:
if do_verify:
if url not in checksums:
raise RuntimeError("src/stage0.json doesn't contain a checksum for {}".format(url))
raise RuntimeError(("src/stage0.json doesn't contain a checksum for {}. "
"Pre-built artifacts might not available for this "
"target at this time, see https://doc.rust-lang.org/nightly"
"/rustc/platform-support.html for more information.")
.format(url))
sha256 = checksums[url]
if os.path.exists(path):
if verify(path, sha256, False):
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustdoc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- [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)
- [Scraped examples](scraped-examples.md)
- [Advanced features](advanced-features.md)
- [Unstable features](unstable-features.md)
- [Deprecated features](deprecated-features.md)
Expand Down
55 changes: 55 additions & 0 deletions src/doc/rustdoc/src/scraped-examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Scraped examples

Rustdoc has an unstable feature where it can automatically scrape examples of items being documented from the `examples/` directory of a Cargo workspace. These examples will be included within the generated documentation for that item. For example, if your library contains a public function:

```rust,ignore (needs-other-file)
// a_crate/src/lib.rs
pub fn a_func() {}
```

And you have an example calling this function:

```rust,ignore (needs-other-file)
// a_crate/examples/ex.rs
fn main() {
a_crate::a_func();
}
```

Then this code snippet will be included in the documentation for `a_func`. This documentation is inserted by Rustdoc and cannot be manually edited by the crate author.


## How to use this feature

This feature is unstable, so you can enable it by calling Rustdoc with the unstable `rustdoc-scrape-examples` flag:

```bash
cargo doc -Zunstable-options -Zrustdoc-scrape-examples=examples
```

To enable this feature on [docs.rs](https://docs.rs), add this to your Cargo.toml:

```toml
[package.metadata.docs.rs]
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples=examples"]
```


## How it works

When you run `cargo doc`, Rustdoc will analyze all the crates that match Cargo's `--examples` filter for instances of items being documented. Then Rustdoc will include the source code of these instances in the generated documentation.

Rustdoc has a few techniques to ensure these examples don't overwhelm documentation readers, and that it doesn't blow up the page size:

1. For a given item, a maximum of 5 examples are included in the page. The remaining examples are just links to source code.
2. Only one example is shown by default, and the remaining examples are hidden behind a toggle.
3. For a given file that contains examples, only the item containing the examples will be included in the generated documentation.

For a given item, Rustdoc sorts its examples based on the size of the example &mdash; smaller ones are shown first.


## FAQ

### My example is not showing up in the documentation

This feature uses Cargo's convention for finding examples. You should ensure that `cargo check --examples` includes your example file.
19 changes: 17 additions & 2 deletions src/librustdoc/html/render/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use super::print_item::{full_path, item_path, print_item};
use super::search_index::build_index;
use super::write_shared::write_shared;
use super::{
collect_spans_and_sources, print_sidebar, settings, AllTypes, LinkFromSrc, NameDoc, StylePath,
BASIC_KEYWORDS,
collect_spans_and_sources, print_sidebar, scrape_examples_help, settings, AllTypes,
LinkFromSrc, NameDoc, StylePath, BASIC_KEYWORDS,
};

use crate::clean::{self, types::ExternalLocation, ExternalCrate};
Expand Down Expand Up @@ -551,6 +551,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
let crate_name = self.tcx().crate_name(LOCAL_CRATE);
let final_file = self.dst.join(crate_name.as_str()).join("all.html");
let settings_file = self.dst.join("settings.html");
let scrape_examples_help_file = self.dst.join("scrape-examples-help.html");

let mut root_path = self.dst.to_str().expect("invalid path").to_owned();
if !root_path.ends_with('/') {
Expand Down Expand Up @@ -606,6 +607,20 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
&self.shared.style_files,
);
self.shared.fs.write(settings_file, v)?;

if self.shared.layout.scrape_examples_extension {
page.title = "About scraped examples";
page.description = "How the scraped examples feature works in Rustdoc";
let v = layout::render(
&self.shared.layout,
&page,
"",
scrape_examples_help(&*self.shared),
&self.shared.style_files,
);
self.shared.fs.write(scrape_examples_help_file, v)?;
}

if let Some(ref redirections) = self.shared.redirections {
if !redirections.borrow().is_empty() {
let redirect_map_path =
Expand Down
36 changes: 35 additions & 1 deletion src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ use crate::html::format::{
use crate::html::highlight;
use crate::html::markdown::{HeadingOffset, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine};
use crate::html::sources;
use crate::html::static_files::SCRAPE_EXAMPLES_HELP_MD;
use crate::scrape_examples::{CallData, CallLocation};
use crate::try_none;
use crate::DOC_RUST_LANG_ORG_CHANNEL;

/// A pair of name and its optional document.
crate type NameDoc = (String, Option<String>);
Expand Down Expand Up @@ -460,6 +462,34 @@ fn settings(root_path: &str, suffix: &str, theme_names: Vec<String>) -> Result<S
))
}

fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
let mut content = SCRAPE_EXAMPLES_HELP_MD.to_owned();
content.push_str(&format!(
"## More information\n\n\
If you want more information about this feature, please read the [corresponding chapter in the Rustdoc book]({}/rustdoc/scraped-examples.html).",
DOC_RUST_LANG_ORG_CHANNEL));

let mut ids = IdMap::default();
format!(
"<div class=\"main-heading\">\
<h1 class=\"fqn\">\
<span class=\"in-band\">About scraped examples</span>\
</h1>\
</div>\
<div>{}</div>",
Markdown {
content: &content,
links: &[],
ids: &mut ids,
error_codes: shared.codes,
edition: shared.edition(),
playground: &shared.playground,
heading_offset: HeadingOffset::H1
}
.into_string()
)
}

fn document(
w: &mut Buffer,
cx: &Context<'_>,
Expand Down Expand Up @@ -2743,7 +2773,9 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
<span></span>\
<h5 id=\"{id}\">\
<a href=\"#{id}\">Examples found in repository</a>\
<a class=\"scrape-help\" href=\"{root_path}scrape-examples-help.html\">?</a>\
</h5>",
root_path = cx.root_path(),
id = id
);

Expand Down Expand Up @@ -2795,9 +2827,10 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
.locations
.iter()
.map(|loc| {
let (byte_lo, byte_hi) = loc.call_expr.byte_span;
let (byte_lo, byte_hi) = loc.call_ident.byte_span;
let (line_lo, line_hi) = loc.call_expr.line_span;
let byte_range = (byte_lo - byte_min, byte_hi - byte_min);

let line_range = (line_lo - line_min, line_hi - line_min);
let (line_url, line_title) = link_to_loc(call_data, loc);

Expand Down Expand Up @@ -2913,6 +2946,7 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
<summary class=\"hideme\">\
<span>More examples</span>\
</summary>\
<div class=\"hide-more\">Hide additional examples</div>\
<div class=\"more-scraped-examples\">\
<div class=\"toggle-line\"><div class=\"toggle-line-inner\"></div></div>\
<div class=\"more-scraped-examples-inner\">"
Expand Down
Loading