Auto merge of #72478 - Dylan-DPC:rollup-vval8du, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #71289 (Allow using `Self::` in doc) - #72375 (Improve E0599 explanation) - #72385 (Add some teams to prioritization exclude_labels) - #72395 (Allow rust-highfive to label issues it creates.) - #72453 (Add flag to open docs: x.py doc --open) - #72459 (Add core::future::IntoFuture) - #72461 (Clean up E0600 explanation) Failed merges: r? @ghost
This commit is contained in:
commit
75b0a68f35
@ -213,6 +213,7 @@ dependencies = [
|
||||
"lazy_static 1.4.0",
|
||||
"libc",
|
||||
"num_cpus",
|
||||
"opener",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -48,6 +48,7 @@ toml = "0.5"
|
||||
lazy_static = "1.3.0"
|
||||
time = "0.1"
|
||||
ignore = "0.4.10"
|
||||
opener = "0.4"
|
||||
|
||||
[target.'cfg(windows)'.dependencies.winapi]
|
||||
version = "0.3"
|
||||
|
@ -503,7 +503,7 @@ impl<'a> Builder<'a> {
|
||||
Subcommand::Check { ref paths } => (Kind::Check, &paths[..]),
|
||||
Subcommand::Clippy { ref paths } => (Kind::Clippy, &paths[..]),
|
||||
Subcommand::Fix { ref paths } => (Kind::Fix, &paths[..]),
|
||||
Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]),
|
||||
Subcommand::Doc { ref paths, .. } => (Kind::Doc, &paths[..]),
|
||||
Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]),
|
||||
Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]),
|
||||
Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
|
||||
|
@ -70,6 +70,35 @@ book!(
|
||||
RustdocBook, "src/doc/rustdoc", "rustdoc";
|
||||
);
|
||||
|
||||
fn open(builder: &Builder<'_>, path: impl AsRef<Path>) {
|
||||
if builder.config.dry_run || !builder.config.cmd.open() {
|
||||
return;
|
||||
}
|
||||
|
||||
let path = path.as_ref();
|
||||
builder.info(&format!("Opening doc {}", path.display()));
|
||||
if let Err(err) = opener::open(path) {
|
||||
builder.info(&format!("{}\n", err));
|
||||
}
|
||||
}
|
||||
|
||||
// "src/libstd" -> ["src", "libstd"]
|
||||
//
|
||||
// Used for deciding whether a particular step is one requested by the user on
|
||||
// the `x.py doc` command line, which determines whether `--open` will open that
|
||||
// page.
|
||||
fn components_simplified(path: &PathBuf) -> Vec<&str> {
|
||||
path.iter().map(|component| component.to_str().unwrap_or("???")).collect()
|
||||
}
|
||||
|
||||
fn is_explicit_request(builder: &Builder<'_>, path: &str) -> bool {
|
||||
builder
|
||||
.paths
|
||||
.iter()
|
||||
.map(components_simplified)
|
||||
.any(|requested| requested.iter().copied().eq(path.split("/")))
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct UnstableBook {
|
||||
target: Interned<String>,
|
||||
@ -200,6 +229,12 @@ impl Step for TheBook {
|
||||
|
||||
invoke_rustdoc(builder, compiler, target, path);
|
||||
}
|
||||
|
||||
if is_explicit_request(builder, "src/doc/book") {
|
||||
let out = builder.doc_out(target);
|
||||
let index = out.join("book").join("index.html");
|
||||
open(builder, &index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,6 +373,13 @@ impl Step for Standalone {
|
||||
}
|
||||
builder.run(&mut cmd);
|
||||
}
|
||||
|
||||
// We open doc/index.html as the default if invoked as `x.py doc --open`
|
||||
// with no particular explicit doc requested (e.g. src/libcore).
|
||||
if builder.paths.is_empty() || is_explicit_request(builder, "src/doc") {
|
||||
let index = out.join("index.html");
|
||||
open(builder, &index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -418,10 +460,25 @@ impl Step for Std {
|
||||
|
||||
builder.run(&mut cargo.into());
|
||||
};
|
||||
for krate in &["alloc", "core", "std", "proc_macro", "test"] {
|
||||
let krates = ["alloc", "core", "std", "proc_macro", "test"];
|
||||
for krate in &krates {
|
||||
run_cargo_rustdoc_for(krate);
|
||||
}
|
||||
builder.cp_r(&my_out, &out);
|
||||
|
||||
// Look for src/libstd, src/libcore etc in the `x.py doc` arguments and
|
||||
// open the corresponding rendered docs.
|
||||
for path in builder.paths.iter().map(components_simplified) {
|
||||
if path.get(0) == Some(&"src")
|
||||
&& path.get(1).map_or(false, |dir| dir.starts_with("lib"))
|
||||
{
|
||||
let requested_crate = &path[1][3..];
|
||||
if krates.contains(&requested_crate) {
|
||||
let index = out.join(requested_crate).join("index.html");
|
||||
open(builder, &index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ pub enum Subcommand {
|
||||
},
|
||||
Doc {
|
||||
paths: Vec<PathBuf>,
|
||||
open: bool,
|
||||
},
|
||||
Test {
|
||||
paths: Vec<PathBuf>,
|
||||
@ -248,6 +249,9 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
|
||||
"bench" => {
|
||||
opts.optmulti("", "test-args", "extra arguments", "ARGS");
|
||||
}
|
||||
"doc" => {
|
||||
opts.optflag("", "open", "open the docs in a browser");
|
||||
}
|
||||
"clean" => {
|
||||
opts.optflag("", "all", "clean all build artifacts");
|
||||
}
|
||||
@ -404,6 +408,7 @@ Arguments:
|
||||
./x.py doc src/doc/book
|
||||
./x.py doc src/doc/nomicon
|
||||
./x.py doc src/doc/book src/libstd
|
||||
./x.py doc src/libstd --open
|
||||
|
||||
If no arguments are passed then everything is documented:
|
||||
|
||||
@ -479,7 +484,7 @@ Arguments:
|
||||
},
|
||||
},
|
||||
"bench" => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
|
||||
"doc" => Subcommand::Doc { paths },
|
||||
"doc" => Subcommand::Doc { paths, open: matches.opt_present("open") },
|
||||
"clean" => {
|
||||
if !paths.is_empty() {
|
||||
println!("\nclean does not take a path argument\n");
|
||||
@ -613,6 +618,13 @@ impl Subcommand {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(&self) -> bool {
|
||||
match *self {
|
||||
Subcommand::Doc { open, .. } => open,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn split(s: &[String]) -> Vec<String> {
|
||||
|
27
src/libcore/future/into_future.rs
Normal file
27
src/libcore/future/into_future.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use crate::future::Future;
|
||||
|
||||
/// Conversion into a `Future`.
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
pub trait IntoFuture {
|
||||
/// The output that the future will produce on completion.
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
type Output;
|
||||
|
||||
/// Which kind of future are we turning this into?
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
type Future: Future<Output = Self::Output>;
|
||||
|
||||
/// Creates a future from a value.
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
fn into_future(self) -> Self::Future;
|
||||
}
|
||||
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
impl<F: Future> IntoFuture for F {
|
||||
type Output = F::Output;
|
||||
type Future = F;
|
||||
|
||||
fn into_future(self) -> Self::Future {
|
||||
self
|
||||
}
|
||||
}
|
@ -10,12 +10,16 @@ use crate::{
|
||||
};
|
||||
|
||||
mod future;
|
||||
mod into_future;
|
||||
mod pending;
|
||||
mod ready;
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub use self::future::Future;
|
||||
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
pub use into_future::IntoFuture;
|
||||
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
pub use pending::{pending, Pending};
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
|
@ -9,3 +9,18 @@ let x = Mouth;
|
||||
x.chocolate(); // error: no method named `chocolate` found for type `Mouth`
|
||||
// in the current scope
|
||||
```
|
||||
|
||||
In this case, you need to implement the `chocolate` method to fix the error:
|
||||
|
||||
```
|
||||
struct Mouth;
|
||||
|
||||
impl Mouth {
|
||||
fn chocolate(&self) { // We implement the `chocolate` method here.
|
||||
println!("Hmmm! I love chocolate!");
|
||||
}
|
||||
}
|
||||
|
||||
let x = Mouth;
|
||||
x.chocolate(); // ok!
|
||||
```
|
||||
|
@ -1,6 +1,6 @@
|
||||
An unary operator was used on a type which doesn't implement it.
|
||||
|
||||
Example of erroneous code:
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0600
|
||||
enum Question {
|
||||
|
@ -431,6 +431,43 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
||||
|
||||
look_for_tests(&cx, &dox, &item, true);
|
||||
|
||||
// find item's parent to resolve `Self` in item's docs below
|
||||
let parent_name = self.cx.as_local_hir_id(item.def_id).and_then(|item_hir| {
|
||||
let parent_hir = self.cx.tcx.hir().get_parent_item(item_hir);
|
||||
let item_parent = self.cx.tcx.hir().find(parent_hir);
|
||||
match item_parent {
|
||||
Some(hir::Node::Item(hir::Item {
|
||||
kind:
|
||||
hir::ItemKind::Impl {
|
||||
self_ty:
|
||||
hir::Ty {
|
||||
kind:
|
||||
hir::TyKind::Path(hir::QPath::Resolved(
|
||||
_,
|
||||
hir::Path { segments, .. },
|
||||
)),
|
||||
..
|
||||
},
|
||||
..
|
||||
},
|
||||
..
|
||||
})) => segments.first().and_then(|seg| Some(seg.ident.to_string())),
|
||||
Some(hir::Node::Item(hir::Item {
|
||||
ident, kind: hir::ItemKind::Enum(..), ..
|
||||
}))
|
||||
| Some(hir::Node::Item(hir::Item {
|
||||
ident, kind: hir::ItemKind::Struct(..), ..
|
||||
}))
|
||||
| Some(hir::Node::Item(hir::Item {
|
||||
ident, kind: hir::ItemKind::Union(..), ..
|
||||
}))
|
||||
| Some(hir::Node::Item(hir::Item {
|
||||
ident, kind: hir::ItemKind::Trait(..), ..
|
||||
})) => Some(ident.to_string()),
|
||||
_ => None,
|
||||
}
|
||||
});
|
||||
|
||||
for (ori_link, link_range) in markdown_links(&dox) {
|
||||
// Bail early for real links.
|
||||
if ori_link.contains('/') {
|
||||
@ -467,7 +504,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
||||
};
|
||||
let (res, fragment) = {
|
||||
let mut kind = None;
|
||||
let path_str = if let Some(prefix) =
|
||||
let mut path_str = if let Some(prefix) =
|
||||
["struct@", "enum@", "type@", "trait@", "union@"]
|
||||
.iter()
|
||||
.find(|p| link.starts_with(**p))
|
||||
@ -521,6 +558,15 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
||||
let base_node =
|
||||
if item.is_mod() && item.attrs.inner_docs { None } else { parent_node };
|
||||
|
||||
let resolved_self;
|
||||
// replace `Self` with suitable item's parent name
|
||||
if path_str.starts_with("Self::") {
|
||||
if let Some(ref name) = parent_name {
|
||||
resolved_self = format!("{}::{}", name, &path_str[6..]);
|
||||
path_str = &resolved_self;
|
||||
}
|
||||
}
|
||||
|
||||
match kind {
|
||||
Some(ns @ ValueNS) => {
|
||||
match self.resolve(
|
||||
@ -529,7 +575,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
||||
¤t_item,
|
||||
base_node,
|
||||
&extra_fragment,
|
||||
None,
|
||||
Some(&item),
|
||||
) {
|
||||
Ok(res) => res,
|
||||
Err(ErrorKind::ResolutionFailure) => {
|
||||
@ -552,7 +598,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
||||
¤t_item,
|
||||
base_node,
|
||||
&extra_fragment,
|
||||
None,
|
||||
Some(&item),
|
||||
) {
|
||||
Ok(res) => res,
|
||||
Err(ErrorKind::ResolutionFailure) => {
|
||||
@ -577,7 +623,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
||||
¤t_item,
|
||||
base_node,
|
||||
&extra_fragment,
|
||||
None,
|
||||
Some(&item),
|
||||
) {
|
||||
Err(ErrorKind::AnchorFailure(msg)) => {
|
||||
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
|
||||
|
@ -2,4 +2,16 @@
|
||||
|
||||
#[doc(inline)]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub use core::future::*;
|
||||
pub use core::future::Future;
|
||||
|
||||
#[doc(inline)]
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
pub use core::future::{from_generator, get_context, ResumeTy};
|
||||
|
||||
#[doc(inline)]
|
||||
#[unstable(feature = "future_readiness_fns", issue = "70921")]
|
||||
pub use core::future::{pending, ready, Pending, Ready};
|
||||
|
||||
#[doc(inline)]
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
pub use core::future::IntoFuture;
|
||||
|
@ -266,12 +266,15 @@
|
||||
#![feature(external_doc)]
|
||||
#![feature(fn_traits)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(future_readiness_fns)]
|
||||
#![feature(gen_future)]
|
||||
#![feature(generator_trait)]
|
||||
#![feature(global_asm)]
|
||||
#![feature(hash_raw_entry)]
|
||||
#![feature(hashmap_internals)]
|
||||
#![feature(int_error_internals)]
|
||||
#![feature(int_error_matching)]
|
||||
#![feature(into_future)]
|
||||
#![feature(integer_atomics)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(libc)]
|
||||
|
@ -1,5 +1,7 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// @has foo/index.html '//a/@href' '../foo/struct.Foo.html#method.new'
|
||||
// @has foo/struct.Foo.html '//a/@href' '../foo/struct.Foo.html#method.new'
|
||||
|
||||
@ -27,3 +29,89 @@ impl Bar {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MyStruct {
|
||||
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#structfield.struct_field'
|
||||
|
||||
/// [`struct_field`]
|
||||
///
|
||||
/// [`struct_field`]: Self::struct_field
|
||||
pub struct_field: u8,
|
||||
}
|
||||
|
||||
pub enum MyEnum {
|
||||
// @has foo/enum.MyEnum.html '//a/@href' '../foo/enum.MyEnum.html#EnumVariant.v'
|
||||
|
||||
/// [`EnumVariant`]
|
||||
///
|
||||
/// [`EnumVariant`]: Self::EnumVariant
|
||||
EnumVariant,
|
||||
}
|
||||
|
||||
pub union MyUnion {
|
||||
// @has foo/union.MyUnion.html '//a/@href' '../foo/union.MyUnion.html#structfield.union_field'
|
||||
|
||||
/// [`union_field`]
|
||||
///
|
||||
/// [`union_field`]: Self::union_field
|
||||
pub union_field: f32,
|
||||
}
|
||||
|
||||
pub trait MyTrait {
|
||||
// @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#associatedtype.AssoType'
|
||||
|
||||
/// [`AssoType`]
|
||||
///
|
||||
/// [`AssoType`]: Self::AssoType
|
||||
type AssoType;
|
||||
|
||||
// @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#associatedconstant.ASSO_CONST'
|
||||
|
||||
/// [`ASSO_CONST`]
|
||||
///
|
||||
/// [`ASSO_CONST`]: Self::ASSO_CONST
|
||||
const ASSO_CONST: i32 = 1;
|
||||
|
||||
// @has foo/trait.MyTrait.html '//a/@href' '../foo/trait.MyTrait.html#method.asso_fn'
|
||||
|
||||
/// [`asso_fn`]
|
||||
///
|
||||
/// [`asso_fn`]: Self::asso_fn
|
||||
fn asso_fn() {}
|
||||
}
|
||||
|
||||
impl MyStruct {
|
||||
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.for_impl'
|
||||
|
||||
/// [`for_impl`]
|
||||
///
|
||||
/// [`for_impl`]: Self::for_impl
|
||||
pub fn for_impl() {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl MyTrait for MyStruct {
|
||||
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedtype.AssoType'
|
||||
|
||||
/// [`AssoType`]
|
||||
///
|
||||
/// [`AssoType`]: Self::AssoType
|
||||
type AssoType = u32;
|
||||
|
||||
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedconstant.ASSO_CONST'
|
||||
|
||||
/// [`ASSO_CONST`]
|
||||
///
|
||||
/// [`ASSO_CONST`]: Self::ASSO_CONST
|
||||
const ASSO_CONST: i32 = 10;
|
||||
|
||||
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.asso_fn'
|
||||
|
||||
/// [`asso_fn`]
|
||||
///
|
||||
/// [`asso_fn`]: Self::asso_fn
|
||||
fn asso_fn() {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,19 @@ MAINTAINERS = {
|
||||
'rustc-dev-guide': {'mark-i-m', 'spastorino', 'amanjeev', 'JohnTitor'},
|
||||
}
|
||||
|
||||
LABELS = {
|
||||
'miri': ['A-miri', 'C-bug'],
|
||||
'rls': ['A-rls', 'C-bug'],
|
||||
'rustfmt': ['C-bug'],
|
||||
'book': ['C-bug'],
|
||||
'nomicon': ['C-bug'],
|
||||
'reference': ['C-bug'],
|
||||
'rust-by-example': ['C-bug'],
|
||||
'embedded-book': ['C-bug'],
|
||||
'edition-guide': ['C-bug'],
|
||||
'rustc-dev-guide': ['C-bug'],
|
||||
}
|
||||
|
||||
REPOS = {
|
||||
'miri': 'https://github.com/rust-lang/miri',
|
||||
'rls': 'https://github.com/rust-lang/rls',
|
||||
@ -132,6 +145,7 @@ def issue(
|
||||
assignees,
|
||||
relevant_pr_number,
|
||||
relevant_pr_user,
|
||||
labels,
|
||||
):
|
||||
# Open an issue about the toolstate failure.
|
||||
if status == 'test-fail':
|
||||
@ -155,6 +169,7 @@ def issue(
|
||||
)),
|
||||
'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
|
||||
'assignees': list(assignees),
|
||||
'labels': labels,
|
||||
})
|
||||
print("Creating issue:\n{}".format(request))
|
||||
response = urllib2.urlopen(urllib2.Request(
|
||||
@ -235,7 +250,7 @@ def update_latest(
|
||||
try:
|
||||
issue(
|
||||
tool, create_issue_for_status, MAINTAINERS.get(tool, ''),
|
||||
relevant_pr_number, relevant_pr_user,
|
||||
relevant_pr_number, relevant_pr_user, LABELS.get(tool, ''),
|
||||
)
|
||||
except urllib2.HTTPError as e:
|
||||
# network errors will simply end up not creating an issue, but that's better
|
||||
|
@ -37,5 +37,9 @@ label = "ICEBreaker-Cleanup-Crew"
|
||||
[prioritize]
|
||||
label = "I-prioritize"
|
||||
prioritize_on = ["regression-from-stable-to-stable", "regression-from-stable-to-beta", "regression-from-stable-to-nightly"]
|
||||
priority_labels = "P-*"
|
||||
exclude_labels = [
|
||||
"P-*",
|
||||
"T-infra",
|
||||
"T-release",
|
||||
]
|
||||
zulip_stream = 227806
|
||||
|
Loading…
Reference in New Issue
Block a user