mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Auto merge of #40950 - frewsxcv:rollup, r=frewsxcv
Rollup of 10 pull requests - Successful merges: #40694, #40842, #40869, #40888, #40898, #40904, #40925, #40928, #40929, #40934 - Failed merges:
This commit is contained in:
commit
40feadb966
3
src/Cargo.lock
generated
3
src/Cargo.lock
generated
@ -926,6 +926,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tidy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
|
@ -146,7 +146,6 @@
|
||||
- [proc_macro](proc-macro.md)
|
||||
- [proc_macro_internals](proc-macro-internals.md)
|
||||
- [process_try_wait](process-try-wait.md)
|
||||
- [pub_restricted](pub-restricted.md)
|
||||
- [question_mark_carrier](question-mark-carrier.md)
|
||||
- [quote](quote.md)
|
||||
- [rand](rand.md)
|
||||
@ -156,11 +155,11 @@
|
||||
- [relaxed_adts](relaxed-adts.md)
|
||||
- [repr_simd](repr-simd.md)
|
||||
- [retain_hash_collection](retain-hash-collection.md)
|
||||
- [reverse_cmp_key](reverse-cmp-key.md)
|
||||
- [rt](rt.md)
|
||||
- [rustc_attrs](rustc-attrs.md)
|
||||
- [rustc_diagnostic_macros](rustc-diagnostic-macros.md)
|
||||
- [rustc_private](rustc-private.md)
|
||||
- [rustdoc](rustdoc.md)
|
||||
- [rvalue_static_promotion](rvalue-static-promotion.md)
|
||||
- [sanitizer_runtime](sanitizer-runtime.md)
|
||||
- [sanitizer_runtime_lib](sanitizer-runtime-lib.md)
|
||||
@ -181,6 +180,7 @@
|
||||
- [step_by](step-by.md)
|
||||
- [step_trait](step-trait.md)
|
||||
- [stmt_expr_attributes](stmt-expr-attributes.md)
|
||||
- [str_checked_slicing](str-checked-slicing.md)
|
||||
- [str_escape](str-escape.md)
|
||||
- [str_internals](str-internals.md)
|
||||
- [struct_field_attributes](struct-field-attributes.md)
|
||||
|
@ -1,7 +0,0 @@
|
||||
# `pub_restricted`
|
||||
|
||||
The tracking issue for this feature is: [#32409]
|
||||
|
||||
[#38356]: https://github.com/rust-lang/rust/issues/32409
|
||||
|
||||
------------------------
|
7
src/doc/unstable-book/src/reverse-cmp-key.md
Normal file
7
src/doc/unstable-book/src/reverse-cmp-key.md
Normal file
@ -0,0 +1,7 @@
|
||||
# `reverse_cmp_key`
|
||||
|
||||
The tracking issue for this feature is: [#40893]
|
||||
|
||||
[#40893]: https://github.com/rust-lang/rust/issues/40893
|
||||
|
||||
------------------------
|
@ -1,7 +0,0 @@
|
||||
# `rustdoc`
|
||||
|
||||
The tracking issue for this feature is: [#27812]
|
||||
|
||||
[#27812]: https://github.com/rust-lang/rust/issues/27812
|
||||
|
||||
------------------------
|
@ -2,6 +2,8 @@
|
||||
|
||||
The tracking issue for this feature is: [#31844]
|
||||
|
||||
[#31844]: https://github.com/rust-lang/rust/issues/31844
|
||||
|
||||
------------------------
|
||||
|
||||
|
||||
|
7
src/doc/unstable-book/src/str-checked-slicing.md
Normal file
7
src/doc/unstable-book/src/str-checked-slicing.md
Normal file
@ -0,0 +1,7 @@
|
||||
# `str_checked_slicing`
|
||||
|
||||
The tracking issue for this feature is: [#39932]
|
||||
|
||||
[#39932]: https://github.com/rust-lang/rust/issues/39932
|
||||
|
||||
------------------------
|
@ -347,6 +347,15 @@ impl<T: PartialOrd> PartialOrd for Reverse<T> {
|
||||
fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
|
||||
other.0.partial_cmp(&self.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lt(&self, other: &Self) -> bool { other.0 < self.0 }
|
||||
#[inline]
|
||||
fn le(&self, other: &Self) -> bool { other.0 <= self.0 }
|
||||
#[inline]
|
||||
fn ge(&self, other: &Self) -> bool { other.0 >= self.0 }
|
||||
#[inline]
|
||||
fn gt(&self, other: &Self) -> bool { other.0 > self.0 }
|
||||
}
|
||||
|
||||
#[unstable(feature = "reverse_cmp_key", issue = "40893")]
|
||||
|
@ -337,27 +337,20 @@ macro_rules! try {
|
||||
|
||||
/// Write formatted data into a buffer
|
||||
///
|
||||
/// This macro accepts a 'writer' (any value with a `write_fmt` method), a format string, and a
|
||||
/// list of arguments to format.
|
||||
/// This macro accepts a format string, a list of arguments, and a 'writer'. Arguments will be
|
||||
/// formatted according to the specified format string and the result will be passed to the writer.
|
||||
/// The writer may be any value with a `write_fmt` method; generally this comes from an
|
||||
/// implementation of either the [`std::fmt::Write`] or the [`std::io::Write`] trait. The macro
|
||||
/// returns whatever the 'write_fmt' method returns; commonly a [`std::fmt::Result`], or an
|
||||
/// [`io::Result`].
|
||||
///
|
||||
/// The `write_fmt` method usually comes from an implementation of [`std::fmt::Write`][fmt_write]
|
||||
/// or [`std::io::Write`][io_write] traits. The term 'writer' refers to an implementation of one of
|
||||
/// these two traits.
|
||||
/// See [`std::fmt`] for more information on the format string syntax.
|
||||
///
|
||||
/// Passed arguments will be formatted according to the specified format string and the resulting
|
||||
/// string will be passed to the writer.
|
||||
///
|
||||
/// See [`std::fmt`][fmt] for more information on format syntax.
|
||||
///
|
||||
/// `write!` returns whatever the 'write_fmt' method returns.
|
||||
///
|
||||
/// Common return values include: [`fmt::Result`][fmt_result], [`io::Result`][io_result]
|
||||
///
|
||||
/// [fmt]: ../std/fmt/index.html
|
||||
/// [fmt_write]: ../std/fmt/trait.Write.html
|
||||
/// [io_write]: ../std/io/trait.Write.html
|
||||
/// [fmt_result]: ../std/fmt/type.Result.html
|
||||
/// [io_result]: ../std/io/type.Result.html
|
||||
/// [`std::fmt`]: ../std/fmt/index.html
|
||||
/// [`std::fmt::Write`]: ../std/fmt/trait.Write.html
|
||||
/// [`std::io::Write`]: ../std/io/trait.Write.html
|
||||
/// [`std::fmt::Result`]: ../std/fmt/type.Result.html
|
||||
/// [`io::Result`]: ../std/io/type.Result.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -396,27 +389,12 @@ macro_rules! write {
|
||||
/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
|
||||
/// (no additional CARRIAGE RETURN (`\r`/`U+000D`).
|
||||
///
|
||||
/// This macro accepts a 'writer' (any value with a `write_fmt` method), a format string, and a
|
||||
/// list of arguments to format.
|
||||
/// For more information, see [`write!`]. For information on the format string syntax, see
|
||||
/// [`std::fmt`].
|
||||
///
|
||||
/// The `write_fmt` method usually comes from an implementation of [`std::fmt::Write`][fmt_write]
|
||||
/// or [`std::io::Write`][io_write] traits. The term 'writer' refers to an implementation of one of
|
||||
/// these two traits.
|
||||
/// [`write!`]: macro.write.html
|
||||
/// [`std::fmt`]: ../std/fmt/index.html
|
||||
///
|
||||
/// Passed arguments will be formatted according to the specified format string and the resulting
|
||||
/// string will be passed to the writer, along with the appended newline.
|
||||
///
|
||||
/// See [`std::fmt`][fmt] for more information on format syntax.
|
||||
///
|
||||
/// `write!` returns whatever the 'write_fmt' method returns.
|
||||
///
|
||||
/// Common return values include: [`fmt::Result`][fmt_result], [`io::Result`][io_result]
|
||||
///
|
||||
/// [fmt]: ../std/fmt/index.html
|
||||
/// [fmt_write]: ../std/fmt/trait.Write.html
|
||||
/// [io_write]: ../std/io/trait.Write.html
|
||||
/// [fmt_result]: ../std/fmt/type.Result.html
|
||||
/// [io_result]: ../std/io/type.Result.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -288,6 +288,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn consume_body(&mut self, body: &hir::Body) {
|
||||
debug!("consume_body(body={:?})", body);
|
||||
|
||||
for arg in &body.arguments {
|
||||
let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id));
|
||||
|
||||
|
@ -54,7 +54,7 @@ r##"<!DOCTYPE html>
|
||||
{favicon}
|
||||
{in_header}
|
||||
</head>
|
||||
<body class="rustdoc">
|
||||
<body class="rustdoc {css_class}">
|
||||
<!--[if lte IE 8]>
|
||||
<div class="warning">
|
||||
This old browser is unsupported and will most likely display funky
|
||||
@ -80,7 +80,7 @@ r##"<!DOCTYPE html>
|
||||
</form>
|
||||
</nav>
|
||||
|
||||
<section id='main' class="content {css_class}">{content}</section>
|
||||
<section id='main' class="content">{content}</section>
|
||||
<section id='search' class="content hidden"></section>
|
||||
|
||||
<section class="footer"></section>
|
||||
|
@ -141,7 +141,7 @@ pre {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.source pre {
|
||||
.source .content pre {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
@ -149,7 +149,7 @@ img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.content.source {
|
||||
.source .content {
|
||||
margin-top: 50px;
|
||||
max-width: none;
|
||||
overflow: visible;
|
||||
@ -231,7 +231,7 @@ nav.sub {
|
||||
padding: 15px 0;
|
||||
}
|
||||
|
||||
.content.source pre.rust {
|
||||
.source .content pre.rust {
|
||||
white-space: pre;
|
||||
overflow: auto;
|
||||
padding-left: 0;
|
||||
|
@ -45,6 +45,10 @@ pre {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.source .sidebar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.sidebar .location {
|
||||
border-color: #000;
|
||||
background-color: #fff;
|
||||
|
@ -34,36 +34,55 @@ pub trait MetadataExt {
|
||||
#[allow(deprecated)]
|
||||
fn as_raw_stat(&self) -> &raw::stat;
|
||||
|
||||
/// Returns the device ID on which this file resides.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_dev(&self) -> u64;
|
||||
/// Returns the inode number.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_ino(&self) -> u64;
|
||||
/// Returns the file type and mode.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_mode(&self) -> u32;
|
||||
/// Returns the number of hard links to file.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_nlink(&self) -> u64;
|
||||
/// Returns the user ID of the file owner.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_uid(&self) -> u32;
|
||||
/// Returns the group ID of the file owner.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_gid(&self) -> u32;
|
||||
/// Returns the device ID that this file represents. Only relevant for special file.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_rdev(&self) -> u64;
|
||||
/// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
|
||||
///
|
||||
/// The size of a symbolic link is the length of the pathname it contains,
|
||||
/// without a terminating null byte.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_size(&self) -> u64;
|
||||
/// Returns the last access time.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_atime(&self) -> i64;
|
||||
/// Returns the last access time, nano seconds part.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_atime_nsec(&self) -> i64;
|
||||
/// Returns the last modification time.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_mtime(&self) -> i64;
|
||||
/// Returns the last modification time, nano seconds part.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_mtime_nsec(&self) -> i64;
|
||||
/// Returns the last status change time.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_ctime(&self) -> i64;
|
||||
/// Returns the last status change time, nano seconds part.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_ctime_nsec(&self) -> i64;
|
||||
/// Returns the "preferred" blocksize for efficient filesystem I/O.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_blksize(&self) -> u64;
|
||||
/// Returns the number of blocks allocated to the file, 512-byte units.
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_blocks(&self) -> u64;
|
||||
}
|
||||
|
@ -1056,6 +1056,20 @@ pub fn exit(code: i32) -> ! {
|
||||
/// will be run. If a clean shutdown is needed it is recommended to only call
|
||||
/// this function at a known point where there are no more destructors left
|
||||
/// to run.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::process;
|
||||
///
|
||||
/// fn main() {
|
||||
/// println!("aborting");
|
||||
///
|
||||
/// process::abort();
|
||||
///
|
||||
/// // execution never gets here
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "process_abort", since = "1.17.0")]
|
||||
pub fn abort() -> ! {
|
||||
unsafe { ::sys::abort_internal() };
|
||||
|
@ -72,6 +72,13 @@ pub trait IntoRawFd {
|
||||
fn into_raw_fd(self) -> RawFd;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for RawFd {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for fs::File {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
@ -84,6 +91,14 @@ impl FromRawFd for fs::File {
|
||||
fs::File::from_inner(sys::fs::File::from_inner(fd))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "into_raw_os", since = "1.4.0")]
|
||||
impl IntoRawFd for RawFd {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "into_raw_os", since = "1.4.0")]
|
||||
impl IntoRawFd for fs::File {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_private, rustdoc)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate syntax;
|
||||
extern crate rustdoc;
|
||||
|
@ -4,3 +4,4 @@ version = "0.1.0"
|
||||
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
||||
|
||||
[dependencies]
|
||||
regex = "0.2"
|
@ -24,8 +24,8 @@ use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum Status {
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Status {
|
||||
Stable,
|
||||
Removed,
|
||||
Unstable,
|
||||
@ -42,78 +42,21 @@ impl fmt::Display for Status {
|
||||
}
|
||||
}
|
||||
|
||||
struct Feature {
|
||||
level: Status,
|
||||
since: String,
|
||||
has_gate_test: bool,
|
||||
#[derive(Debug)]
|
||||
pub struct Feature {
|
||||
pub level: Status,
|
||||
pub since: String,
|
||||
pub has_gate_test: bool,
|
||||
}
|
||||
|
||||
pub fn check(path: &Path, bad: &mut bool) {
|
||||
let mut features = collect_lang_features(&path.join("libsyntax/feature_gate.rs"));
|
||||
let mut features = collect_lang_features(path);
|
||||
assert!(!features.is_empty());
|
||||
let mut lib_features = HashMap::<String, Feature>::new();
|
||||
|
||||
let lib_features = collect_lib_features(path, bad, &features);
|
||||
assert!(!lib_features.is_empty());
|
||||
|
||||
let mut contents = String::new();
|
||||
super::walk(path,
|
||||
&mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
|
||||
&mut |file| {
|
||||
let filename = file.file_name().unwrap().to_string_lossy();
|
||||
if !filename.ends_with(".rs") || filename == "features.rs" ||
|
||||
filename == "diagnostic_list.rs" {
|
||||
return;
|
||||
}
|
||||
|
||||
contents.truncate(0);
|
||||
t!(t!(File::open(&file), &file).read_to_string(&mut contents));
|
||||
|
||||
for (i, line) in contents.lines().enumerate() {
|
||||
let mut err = |msg: &str| {
|
||||
println!("{}:{}: {}", file.display(), i + 1, msg);
|
||||
*bad = true;
|
||||
};
|
||||
let level = if line.contains("[unstable(") {
|
||||
Status::Unstable
|
||||
} else if line.contains("[stable(") {
|
||||
Status::Stable
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
let feature_name = match find_attr_val(line, "feature") {
|
||||
Some(name) => name,
|
||||
None => {
|
||||
err("malformed stability attribute");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let since = match find_attr_val(line, "since") {
|
||||
Some(name) => name,
|
||||
None if level == Status::Stable => {
|
||||
err("malformed stability attribute");
|
||||
continue;
|
||||
}
|
||||
None => "None",
|
||||
};
|
||||
|
||||
if features.contains_key(feature_name) {
|
||||
err("duplicating a lang feature");
|
||||
}
|
||||
if let Some(ref s) = lib_features.get(feature_name) {
|
||||
if s.level != level {
|
||||
err("different stability level than before");
|
||||
}
|
||||
if s.since != since {
|
||||
err("different `since` than before");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
lib_features.insert(feature_name.to_owned(),
|
||||
Feature {
|
||||
level: level,
|
||||
since: since.to_owned(),
|
||||
has_gate_test: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
super::walk_many(&[&path.join("test/compile-fail"),
|
||||
&path.join("test/compile-fail-fulldeps"),
|
||||
@ -233,8 +176,9 @@ fn test_filen_gate(filen_underscore: &str,
|
||||
return false;
|
||||
}
|
||||
|
||||
fn collect_lang_features(path: &Path) -> HashMap<String, Feature> {
|
||||
pub fn collect_lang_features(base_src_path: &Path) -> HashMap<String, Feature> {
|
||||
let mut contents = String::new();
|
||||
let path = base_src_path.join("libsyntax/feature_gate.rs");
|
||||
t!(t!(File::open(path)).read_to_string(&mut contents));
|
||||
|
||||
contents.lines()
|
||||
@ -257,3 +201,71 @@ fn collect_lang_features(path: &Path) -> HashMap<String, Feature> {
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn collect_lib_features(base_src_path: &Path,
|
||||
bad: &mut bool,
|
||||
features: &HashMap<String, Feature>) -> HashMap<String, Feature> {
|
||||
let mut lib_features = HashMap::<String, Feature>::new();
|
||||
let mut contents = String::new();
|
||||
super::walk(base_src_path,
|
||||
&mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
|
||||
&mut |file| {
|
||||
let filename = file.file_name().unwrap().to_string_lossy();
|
||||
if !filename.ends_with(".rs") || filename == "features.rs" ||
|
||||
filename == "diagnostic_list.rs" {
|
||||
return;
|
||||
}
|
||||
|
||||
contents.truncate(0);
|
||||
t!(t!(File::open(&file), &file).read_to_string(&mut contents));
|
||||
|
||||
for (i, line) in contents.lines().enumerate() {
|
||||
let mut err = |msg: &str| {
|
||||
println!("{}:{}: {}", file.display(), i + 1, msg);
|
||||
*bad = true;
|
||||
};
|
||||
let level = if line.contains("[unstable(") {
|
||||
Status::Unstable
|
||||
} else if line.contains("[stable(") {
|
||||
Status::Stable
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
let feature_name = match find_attr_val(line, "feature") {
|
||||
Some(name) => name,
|
||||
None => {
|
||||
err("malformed stability attribute");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let since = match find_attr_val(line, "since") {
|
||||
Some(name) => name,
|
||||
None if level == Status::Stable => {
|
||||
err("malformed stability attribute");
|
||||
continue;
|
||||
}
|
||||
None => "None",
|
||||
};
|
||||
|
||||
if features.contains_key(feature_name) {
|
||||
err("duplicating a lang feature");
|
||||
}
|
||||
if let Some(ref s) = lib_features.get(feature_name) {
|
||||
if s.level != level {
|
||||
err("different stability level than before");
|
||||
}
|
||||
if s.since != since {
|
||||
err("different `since` than before");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
lib_features.insert(feature_name.to_owned(),
|
||||
Feature {
|
||||
level: level,
|
||||
since: since.to_owned(),
|
||||
has_gate_test: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
lib_features
|
||||
}
|
@ -14,6 +14,8 @@
|
||||
//! etc. This is run by default on `make check` and as part of the auto
|
||||
//! builders.
|
||||
|
||||
extern crate regex;
|
||||
|
||||
use std::fs;
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::env;
|
||||
@ -37,6 +39,7 @@ mod features;
|
||||
mod cargo;
|
||||
mod pal;
|
||||
mod deps;
|
||||
mod unstable_book;
|
||||
|
||||
fn main() {
|
||||
let path = env::args_os().skip(1).next().expect("need an argument");
|
||||
@ -51,6 +54,7 @@ fn main() {
|
||||
cargo::check(&path, &mut bad);
|
||||
features::check(&path, &mut bad);
|
||||
pal::check(&path, &mut bad);
|
||||
unstable_book::check(&path, &mut bad);
|
||||
if !args.iter().any(|s| *s == "--no-vendor") {
|
||||
deps::check(&path, &mut bad);
|
||||
}
|
||||
|
138
src/tools/tidy/src/unstable_book.rs
Normal file
138
src/tools/tidy/src/unstable_book.rs
Normal file
@ -0,0 +1,138 @@
|
||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
use std::io::{self, BufRead, Write};
|
||||
use std::path;
|
||||
use features::{collect_lang_features, collect_lib_features, Status};
|
||||
|
||||
const PATH_STR: &'static str = "doc/unstable-book/src";
|
||||
|
||||
const SUMMARY_FILE_NAME: &'static str = "SUMMARY.md";
|
||||
|
||||
static EXCLUDE: &'static [&'static str; 2] = &[SUMMARY_FILE_NAME, "the-unstable-book.md"];
|
||||
|
||||
/// Build the path to the Unstable Book source directory from the Rust 'src' directory
|
||||
fn unstable_book_path(base_src_path: &path::Path) -> path::PathBuf {
|
||||
base_src_path.join(PATH_STR)
|
||||
}
|
||||
|
||||
/// Build the path to the Unstable Book SUMMARY file from the Rust 'src' directory
|
||||
fn unstable_book_summary_path(base_src_path: &path::Path) -> path::PathBuf {
|
||||
unstable_book_path(base_src_path).join(SUMMARY_FILE_NAME)
|
||||
}
|
||||
|
||||
/// Open the Unstable Book SUMMARY file
|
||||
fn open_unstable_book_summary_file(base_src_path: &path::Path) -> fs::File {
|
||||
fs::File::open(unstable_book_summary_path(base_src_path))
|
||||
.expect("could not open Unstable Book SUMMARY.md")
|
||||
}
|
||||
|
||||
/// Test to determine if DirEntry is a file
|
||||
fn dir_entry_is_file(dir_entry: &fs::DirEntry) -> bool {
|
||||
dir_entry.file_type().expect("could not determine file type of directory entry").is_file()
|
||||
}
|
||||
|
||||
/// Retrieve names of all lang-related unstable features
|
||||
fn collect_unstable_lang_feature_names(base_src_path: &path::Path) -> HashSet<String> {
|
||||
collect_lang_features(base_src_path)
|
||||
.into_iter()
|
||||
.filter(|&(_, ref f)| f.level == Status::Unstable)
|
||||
.map(|(ref name, _)| name.to_owned())
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Retrieve names of all lib-related unstable features
|
||||
fn collect_unstable_lib_feature_names(base_src_path: &path::Path) -> HashSet<String> {
|
||||
let mut bad = true;
|
||||
let lang_features = collect_lang_features(base_src_path);
|
||||
collect_lib_features(base_src_path, &mut bad, &lang_features)
|
||||
.into_iter()
|
||||
.filter(|&(_, ref f)| f.level == Status::Unstable)
|
||||
.map(|(ref name, _)| name.to_owned())
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Retrieve names of all unstable features
|
||||
fn collect_unstable_feature_names(base_src_path: &path::Path) -> HashSet<String> {
|
||||
collect_unstable_lib_feature_names(base_src_path)
|
||||
.union(&collect_unstable_lang_feature_names(base_src_path))
|
||||
.map(|n| n.to_owned())
|
||||
.collect::<HashSet<_, _>>()
|
||||
}
|
||||
|
||||
/// Retrieve file names of all sections in the Unstable Book with:
|
||||
///
|
||||
/// * hyphens replaced by underscores
|
||||
/// * the markdown suffix ('.md') removed
|
||||
fn collect_unstable_book_section_file_names(base_src_path: &path::Path) -> HashSet<String> {
|
||||
fs::read_dir(unstable_book_path(base_src_path))
|
||||
.expect("could not read directory")
|
||||
.into_iter()
|
||||
.map(|entry| entry.expect("could not read directory entry"))
|
||||
.filter(dir_entry_is_file)
|
||||
.map(|entry| entry.file_name().into_string().unwrap())
|
||||
.filter(|n| EXCLUDE.iter().all(|e| n != e))
|
||||
.map(|n| n.trim_right_matches(".md").replace('-', "_"))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Retrieve unstable feature names that are in the Unstable Book SUMMARY file
|
||||
fn collect_unstable_book_summary_links(base_src_path: &path::Path) -> HashSet<String> {
|
||||
let summary_link_regex =
|
||||
::regex::Regex::new(r"^- \[(\S+)\]\(\S+\.md\)").expect("invalid regex");
|
||||
io::BufReader::new(open_unstable_book_summary_file(base_src_path))
|
||||
.lines()
|
||||
.map(|l| l.expect("could not read line from file"))
|
||||
.filter_map(|line| {
|
||||
summary_link_regex.captures(&line).map(|c| {
|
||||
c.get(1)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.to_owned()
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn check(path: &path::Path, bad: &mut bool) {
|
||||
let unstable_feature_names = collect_unstable_feature_names(path);
|
||||
let unstable_book_section_file_names = collect_unstable_book_section_file_names(path);
|
||||
let unstable_book_links = collect_unstable_book_summary_links(path);
|
||||
|
||||
// Check for Unstable Book section names with no corresponding SUMMARY.md link
|
||||
for feature_name in &unstable_book_section_file_names - &unstable_book_links {
|
||||
*bad = true;
|
||||
writeln!(io::stderr(),
|
||||
"The Unstable Book section '{}' needs to have a link in SUMMARY.md",
|
||||
feature_name)
|
||||
.expect("could not write to stderr")
|
||||
}
|
||||
|
||||
// Check for unstable features that don't have Unstable Book sections
|
||||
for feature_name in &unstable_feature_names - &unstable_book_section_file_names {
|
||||
*bad = true;
|
||||
writeln!(io::stderr(),
|
||||
"Unstable feature '{}' needs to have a section in The Unstable Book",
|
||||
feature_name)
|
||||
.expect("could not write to stderr")
|
||||
}
|
||||
|
||||
// Check for Unstable Book sections that don't have a corresponding unstable feature
|
||||
for feature_name in &unstable_book_section_file_names - &unstable_feature_names {
|
||||
*bad = true;
|
||||
writeln!(io::stderr(),
|
||||
"The Unstable Book has a section '{}' which doesn't correspond \
|
||||
to an unstable feature",
|
||||
feature_name)
|
||||
.expect("could not write to stderr")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user