From 71f92bb8123a1307bb52af63b13637d774c744eb Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Sat, 29 Feb 2020 23:54:13 -0500 Subject: [PATCH 01/40] [tidy] update documentation from `make check` to `x.py test` --- src/tools/tidy/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index ec8b14c288a2f..0b43396505138 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -1,8 +1,8 @@ //! Tidy checks source code in this repository. //! //! This program runs all of the various tidy checks for style, cleanliness, -//! etc. This is run by default on `make check` and as part of the auto -//! builders. +//! etc. This is run by default on `./x.py test` and as part of the auto +//! builders. The tidy checks can be executed with `./x.py test src/tools/tidy`. #![deny(warnings)] From 8858d71d28d68a0063f3ccab1fbf378d69afc78b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 16 Nov 2019 16:12:09 +0100 Subject: [PATCH 02/40] Put back output-format option for show-coverage --- src/librustdoc/config.rs | 59 +++++++++++++++++++++++++---- src/librustdoc/core.rs | 2 + src/librustdoc/html/render.rs | 3 +- src/librustdoc/html/render/cache.rs | 1 + 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 33b3e800374e3..99a55f3c68282 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -1,5 +1,6 @@ use std::collections::BTreeMap; use std::ffi::OsStr; +use std::convert::TryFrom; use std::fmt; use std::path::PathBuf; @@ -24,6 +25,33 @@ use crate::opts; use crate::passes::{self, Condition, DefaultPassOption}; use crate::theme; +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum OutputFormat { + Json, + HTML, +} + +impl OutputFormat { + pub fn is_json(&self) -> bool { + match *self { + OutputFormat::Json => true, + _ => false, + } + } +} + +impl TryFrom<&str> for OutputFormat { + type Error = String; + + fn try_from(value: &str) -> Result { + match value { + "json" => Ok(OutputFormat::Json), + "html" => Ok(OutputFormat::HTML), + _ => Err(format!("unknown output format `{}`", value)), + } + } +} + /// Configuration options for rustdoc. #[derive(Clone)] pub struct Options { @@ -115,6 +143,8 @@ pub struct Options { pub crate_version: Option, /// Collected options specific to outputting final pages. pub render_options: RenderOptions, + /// Output format rendering (used only for "show-coverage" option for the moment) + pub output_format: Option, } impl fmt::Debug for Options { @@ -425,14 +455,6 @@ impl Options { } } - match matches.opt_str("w").as_ref().map(|s| &**s) { - Some("html") | None => {} - Some(s) => { - diag.struct_err(&format!("unknown output format: {}", s)).emit(); - return Err(1); - } - } - let index_page = matches.opt_str("index-page").map(|s| PathBuf::from(&s)); if let Some(ref index_page) = index_page { if !index_page.is_file() { @@ -469,6 +491,23 @@ impl Options { } }; + let output_format = match matches.opt_str("output-format") { + Some(s) => match OutputFormat::try_from(s.as_str()) { + Ok(o) => { + if o.is_json() && !show_coverage { + diag.struct_err("json output format isn't supported for doc generation") + .emit(); + return Err(1); + } + Some(o) + } + Err(e) => { + diag.struct_err(&e).emit(); + return Err(1); + } + } + None => None, + }; let crate_name = matches.opt_str("crate-name"); let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro); let playground_url = matches.opt_str("playground-url"); @@ -553,6 +592,7 @@ impl Options { generate_search_filter, generate_redirect_pages, }, + output_format, }) } @@ -568,6 +608,9 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Han for flag in deprecated_flags.iter() { if matches.opt_present(flag) { + if *flag == "output-format" && matches.opt_present("show-coverage") { + continue; + } let mut err = diag.struct_warn(&format!("the '{}' flag is considered deprecated", flag)); err.warn( diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 8bc34e949f175..b9ae3d53afc04 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -228,6 +228,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt mut manual_passes, display_warnings, render_options, + output_format, .. } = options; @@ -385,6 +386,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut renderinfo = RenderInfo::default(); renderinfo.access_levels = access_levels; + renderinfo.output_format = output_format; let mut ctxt = DocContext { tcx, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4dd2a6562a4cd..016054c688ddc 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -60,7 +60,7 @@ use serde::ser::SerializeSeq; use serde::{Serialize, Serializer}; use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy}; -use crate::config::RenderOptions; +use crate::config::{OutputFormat, RenderOptions}; use crate::docfs::{DocFS, ErrorStorage, PathError}; use crate::doctree; use crate::html::escape::Escape; @@ -270,6 +270,7 @@ pub struct RenderInfo { pub deref_trait_did: Option, pub deref_mut_trait_did: Option, pub owned_box_did: Option, + pub output_format: Option, } // Helper structs for rendering items/sidebars and carrying along contextual diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index a0a35e4ce4b85..4198369eca8f5 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -139,6 +139,7 @@ impl Cache { deref_trait_did, deref_mut_trait_did, owned_box_did, + .. } = renderinfo; let external_paths = From 10492c392af127074d13593ae0dd5067286e8e15 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 16 Nov 2019 16:12:29 +0100 Subject: [PATCH 03/40] Add support for json output in show-coverage option --- .../passes/calculate_doc_coverage.rs | 67 ++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index d4a7f3313a49b..0ca5a956bdb69 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -1,4 +1,5 @@ use crate::clean; +use crate::config::OutputFormat; use crate::core::DocContext; use crate::fold::{self, DocFolder}; use crate::passes::Pass; @@ -6,6 +7,7 @@ use crate::passes::Pass; use rustc_ast::attr; use rustc_span::symbol::sym; use rustc_span::FileName; +use serialize::json::{ToJson, Json}; use std::collections::BTreeMap; use std::ops; @@ -16,8 +18,8 @@ pub const CALCULATE_DOC_COVERAGE: Pass = Pass { description: "counts the number of items with and without documentation", }; -fn calculate_doc_coverage(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate { - let mut calc = CoverageCalculator::default(); +fn calculate_doc_coverage( krate: clean::Crate, ctx: &DocContext<'_>) -> clean::Crate { + let mut calc = CoverageCalculator::new(ctx.renderinfo.borrow().output_format); let krate = calc.fold_crate(krate); calc.print_results(); @@ -64,13 +66,72 @@ impl ops::AddAssign for ItemCount { } } -#[derive(Default)] struct CoverageCalculator { items: BTreeMap, + output_format: Option, +} + +fn limit_filename_len(filename: String) -> String { + // if a filename is too long, shorten it so we don't blow out the table + // FIXME(misdreavus): this needs to count graphemes, and probably also track + // double-wide characters... + if filename.len() > 35 { + "...".to_string() + &filename[filename.len() - 32..] + } else { + filename + } +} + +impl ToJson for CoverageCalculator { + fn to_json(&self) -> Json { + let mut total = ItemCount::default(); + let mut entries = BTreeMap::default(); + + entries.insert("files".to_owned(), Json::Array(self.items + .iter() + .filter_map(|(file, &count)| { + count.percentage().map(|percent| { + (limit_filename_len(file.to_string()), count, percent) + }) + }) + .map(|(name, count, percentage)| { + let mut fields = BTreeMap::default(); + + fields.insert("documented".to_owned(), Json::U64(count.with_docs)); + fields.insert("total".to_owned(), Json::U64(count.total)); + fields.insert("percentage".to_owned(), Json::F64(percentage)); + + total += count; + + let mut obj = BTreeMap::default(); + obj.insert(name, Json::Object(fields)); + + Json::Object(obj) + }) + .collect::>())); + let mut fields = BTreeMap::default(); + fields.insert("documented".to_owned(), Json::U64(total.with_docs)); + fields.insert("total".to_owned(), Json::U64(total.total)); + fields.insert("percentage".to_owned(), Json::F64(total.percentage().unwrap_or(0.0))); + + entries.insert("total".to_owned(), Json::Object(fields)); + Json::Object(entries) + } } impl CoverageCalculator { + fn new(output_format: Option) -> CoverageCalculator { + CoverageCalculator { + items: Default::default(), + output_format, + } + } + fn print_results(&self) { + if self.output_format.map(|o| o.is_json()).unwrap_or_else(|| false) { + println!("{}", self.to_json().pretty()); + return; + } let mut total = ItemCount::default(); fn print_table_line() { From 15babed8b7936e03ed4cd57afd5c91c44dc4f0be Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 16 Nov 2019 16:23:27 +0100 Subject: [PATCH 04/40] add tests for rustdoc output-format json --- src/test/rustdoc-ui/coverage/json.rs | 27 ++++++++++++++++++++ src/test/rustdoc-ui/coverage/json.stdout | 7 +++++ src/test/rustdoc/output-format-fail-check.rs | 5 ++++ 3 files changed, 39 insertions(+) create mode 100644 src/test/rustdoc-ui/coverage/json.rs create mode 100644 src/test/rustdoc-ui/coverage/json.stdout create mode 100644 src/test/rustdoc/output-format-fail-check.rs diff --git a/src/test/rustdoc-ui/coverage/json.rs b/src/test/rustdoc-ui/coverage/json.rs new file mode 100644 index 0000000000000..8b80244f825c4 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/json.rs @@ -0,0 +1,27 @@ +// build-pass +// compile-flags:-Z unstable-options --show-coverage + +pub mod foo { + /// Hello! + pub struct Foo; + /// Bar + pub enum Bar { A } +} + +/// X +pub struct X; + +/// Bar +pub mod bar { + /// bar + pub struct Bar; + /// X + pub enum X { Y } +} + +/// yolo +pub enum Yolo { X } + +pub struct Xo { + x: T, +} diff --git a/src/test/rustdoc-ui/coverage/json.stdout b/src/test/rustdoc-ui/coverage/json.stdout new file mode 100644 index 0000000000000..be56a8c0ffafa --- /dev/null +++ b/src/test/rustdoc-ui/coverage/json.stdout @@ -0,0 +1,7 @@ ++-------------------------------------+------------+------------+------------+ +| File | Documented | Total | Percentage | ++-------------------------------------+------------+------------+------------+ +| ...test/rustdoc-ui/coverage/json.rs | 7 | 13 | 53.8% | ++-------------------------------------+------------+------------+------------+ +| Total | 7 | 13 | 53.8% | ++-------------------------------------+------------+------------+------------+ diff --git a/src/test/rustdoc/output-format-fail-check.rs b/src/test/rustdoc/output-format-fail-check.rs new file mode 100644 index 0000000000000..a78811078be29 --- /dev/null +++ b/src/test/rustdoc/output-format-fail-check.rs @@ -0,0 +1,5 @@ +// compile-flags:-Z unstable-options --output-format +// should-fail + +/// toudoum! +pub struct SomeStruct; From f1070b152546827e599cdee1f64c55faaf8bf082 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 17 Feb 2020 13:53:27 +0100 Subject: [PATCH 05/40] Replace ToJson with serde --- src/librustdoc/config.rs | 16 ++-- .../passes/calculate_doc_coverage.rs | 90 ++++++------------- src/test/rustdoc-ui/coverage/html.rs | 4 + src/test/rustdoc-ui/coverage/html.stderr | 2 + src/test/rustdoc-ui/coverage/json.rs | 2 +- src/test/rustdoc-ui/coverage/json.stdout | 8 +- .../coverage}/output-format-fail-check.rs | 1 - .../coverage/output-format-fail-check.stderr | 6 ++ 8 files changed, 51 insertions(+), 78 deletions(-) create mode 100644 src/test/rustdoc-ui/coverage/html.rs create mode 100644 src/test/rustdoc-ui/coverage/html.stderr rename src/test/{rustdoc => rustdoc-ui/coverage}/output-format-fail-check.rs (85%) create mode 100644 src/test/rustdoc-ui/coverage/output-format-fail-check.stderr diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 99a55f3c68282..58c8a7d82bfb5 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use std::ffi::OsStr; use std::convert::TryFrom; +use std::ffi::OsStr; use std::fmt; use std::path::PathBuf; @@ -28,12 +28,12 @@ use crate::theme; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum OutputFormat { Json, - HTML, + Html, } impl OutputFormat { pub fn is_json(&self) -> bool { - match *self { + match self { OutputFormat::Json => true, _ => false, } @@ -46,7 +46,7 @@ impl TryFrom<&str> for OutputFormat { fn try_from(value: &str) -> Result { match value { "json" => Ok(OutputFormat::Json), - "html" => Ok(OutputFormat::HTML), + "html" => Ok(OutputFormat::Html), _ => Err(format!("unknown output format `{}`", value)), } } @@ -498,6 +498,12 @@ impl Options { diag.struct_err("json output format isn't supported for doc generation") .emit(); return Err(1); + } else if !o.is_json() && show_coverage { + diag.struct_err( + "html output format isn't supported for the --show-coverage option", + ) + .emit(); + return Err(1); } Some(o) } @@ -505,7 +511,7 @@ impl Options { diag.struct_err(&e).emit(); return Err(1); } - } + }, None => None, }; let crate_name = matches.opt_str("crate-name"); diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 0ca5a956bdb69..f48224512ba4f 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -7,7 +7,8 @@ use crate::passes::Pass; use rustc_ast::attr; use rustc_span::symbol::sym; use rustc_span::FileName; -use serialize::json::{ToJson, Json}; +use serde::Serialize; +use serde_json; use std::collections::BTreeMap; use std::ops; @@ -18,16 +19,16 @@ pub const CALCULATE_DOC_COVERAGE: Pass = Pass { description: "counts the number of items with and without documentation", }; -fn calculate_doc_coverage( krate: clean::Crate, ctx: &DocContext<'_>) -> clean::Crate { - let mut calc = CoverageCalculator::new(ctx.renderinfo.borrow().output_format); +fn calculate_doc_coverage(krate: clean::Crate, ctx: &DocContext<'_>) -> clean::Crate { + let mut calc = CoverageCalculator::new(); let krate = calc.fold_crate(krate); - calc.print_results(); + calc.print_results(ctx.renderinfo.borrow().output_format); krate } -#[derive(Default, Copy, Clone)] +#[derive(Default, Copy, Clone, Serialize)] struct ItemCount { total: u64, with_docs: u64, @@ -68,68 +69,37 @@ impl ops::AddAssign for ItemCount { struct CoverageCalculator { items: BTreeMap, - output_format: Option, } fn limit_filename_len(filename: String) -> String { - // if a filename is too long, shorten it so we don't blow out the table - // FIXME(misdreavus): this needs to count graphemes, and probably also track - // double-wide characters... - if filename.len() > 35 { - "...".to_string() + &filename[filename.len() - 32..] + let nb_chars = filename.chars().count(); + if nb_chars > 35 { + "...".to_string() + + &filename[filename.char_indices().nth(nb_chars - 32).map(|x| x.0).unwrap_or(0)..] } else { filename } } -impl ToJson for CoverageCalculator { - fn to_json(&self) -> Json { - let mut total = ItemCount::default(); - let mut entries = BTreeMap::default(); - - entries.insert("files".to_owned(), Json::Array(self.items - .iter() - .filter_map(|(file, &count)| { - count.percentage().map(|percent| { - (limit_filename_len(file.to_string()), count, percent) - }) - }) - .map(|(name, count, percentage)| { - let mut fields = BTreeMap::default(); - - fields.insert("documented".to_owned(), Json::U64(count.with_docs)); - fields.insert("total".to_owned(), Json::U64(count.total)); - fields.insert("percentage".to_owned(), Json::F64(percentage)); - - total += count; - - let mut obj = BTreeMap::default(); - obj.insert(name, Json::Object(fields)); - - Json::Object(obj) - }) - .collect::>())); - let mut fields = BTreeMap::default(); - fields.insert("documented".to_owned(), Json::U64(total.with_docs)); - fields.insert("total".to_owned(), Json::U64(total.total)); - fields.insert("percentage".to_owned(), Json::F64(total.percentage().unwrap_or(0.0))); - - entries.insert("total".to_owned(), Json::Object(fields)); - Json::Object(entries) +impl CoverageCalculator { + fn new() -> CoverageCalculator { + CoverageCalculator { items: Default::default() } } -} -impl CoverageCalculator { - fn new(output_format: Option) -> CoverageCalculator { - CoverageCalculator { - items: Default::default(), - output_format, - } + fn to_json(&self) -> String { + serde_json::to_string( + &self + .items + .iter() + .map(|(k, v)| (k.to_string(), v)) + .collect::>(), + ) + .expect("failed to convert JSON data to string") } - fn print_results(&self) { - if self.output_format.map(|o| o.is_json()).unwrap_or_else(|| false) { - println!("{}", self.to_json().pretty()); + fn print_results(&self, output_format: Option) { + if output_format.map(|o| o.is_json()).unwrap_or_else(|| false) { + println!("{}", self.to_json()); return; } let mut total = ItemCount::default(); @@ -154,15 +124,7 @@ impl CoverageCalculator { for (file, &count) in &self.items { if let Some(percentage) = count.percentage() { - let mut name = file.to_string(); - // if a filename is too long, shorten it so we don't blow out the table - // FIXME(misdreavus): this needs to count graphemes, and probably also track - // double-wide characters... - if name.len() > 35 { - name = "...".to_string() + &name[name.len() - 32..]; - } - - print_table_record(&name, count, percentage); + print_table_record(&limit_filename_len(file.to_string()), count, percentage); total += count; } diff --git a/src/test/rustdoc-ui/coverage/html.rs b/src/test/rustdoc-ui/coverage/html.rs new file mode 100644 index 0000000000000..181cb4c5061a7 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/html.rs @@ -0,0 +1,4 @@ +// compile-flags:-Z unstable-options --output-format html --show-coverage + +/// Foo +pub struct Xo; diff --git a/src/test/rustdoc-ui/coverage/html.stderr b/src/test/rustdoc-ui/coverage/html.stderr new file mode 100644 index 0000000000000..adca375d4bce5 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/html.stderr @@ -0,0 +1,2 @@ +error: html output format isn't supported for the --show-coverage option + diff --git a/src/test/rustdoc-ui/coverage/json.rs b/src/test/rustdoc-ui/coverage/json.rs index 8b80244f825c4..b1220b32e9194 100644 --- a/src/test/rustdoc-ui/coverage/json.rs +++ b/src/test/rustdoc-ui/coverage/json.rs @@ -1,5 +1,5 @@ // build-pass -// compile-flags:-Z unstable-options --show-coverage +// compile-flags:-Z unstable-options --output-format json --show-coverage pub mod foo { /// Hello! diff --git a/src/test/rustdoc-ui/coverage/json.stdout b/src/test/rustdoc-ui/coverage/json.stdout index be56a8c0ffafa..63b22a7d94b00 100644 --- a/src/test/rustdoc-ui/coverage/json.stdout +++ b/src/test/rustdoc-ui/coverage/json.stdout @@ -1,7 +1 @@ -+-------------------------------------+------------+------------+------------+ -| File | Documented | Total | Percentage | -+-------------------------------------+------------+------------+------------+ -| ...test/rustdoc-ui/coverage/json.rs | 7 | 13 | 53.8% | -+-------------------------------------+------------+------------+------------+ -| Total | 7 | 13 | 53.8% | -+-------------------------------------+------------+------------+------------+ +{"$DIR/json.rs":{"total":13,"with_docs":7}} diff --git a/src/test/rustdoc/output-format-fail-check.rs b/src/test/rustdoc-ui/coverage/output-format-fail-check.rs similarity index 85% rename from src/test/rustdoc/output-format-fail-check.rs rename to src/test/rustdoc-ui/coverage/output-format-fail-check.rs index a78811078be29..30b525df76359 100644 --- a/src/test/rustdoc/output-format-fail-check.rs +++ b/src/test/rustdoc-ui/coverage/output-format-fail-check.rs @@ -1,5 +1,4 @@ // compile-flags:-Z unstable-options --output-format -// should-fail /// toudoum! pub struct SomeStruct; diff --git a/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr b/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr new file mode 100644 index 0000000000000..9e9aa0e050163 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr @@ -0,0 +1,6 @@ +warning: the 'output-format' flag is considered deprecated + | + = warning: see issue #44136 for more information + +error: too many file operands + From 1c01646e6f1ed540fa1be66f3389181ad5644778 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Feb 2020 17:20:32 +0100 Subject: [PATCH 06/40] Extend json detection in runtest --- src/tools/compiletest/src/runtest.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ac808b1f14e13..86621e8812b4c 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3204,7 +3204,9 @@ impl<'test> TestCx<'test> { let json = cflags.contains("--error-format json") || cflags.contains("--error-format pretty-json") || cflags.contains("--error-format=json") - || cflags.contains("--error-format=pretty-json"); + || cflags.contains("--error-format=pretty-json") + || cflags.contains("--output-format json") + || cflags.contains("--output-format=json"); let mut normalized = output.to_string(); From b6466273ba3d019433a8665fb337bfedeaf209ef Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 2 Mar 2020 13:20:32 +0100 Subject: [PATCH 07/40] remove output-format test --- src/test/rustdoc-ui/coverage/output-format-fail-check.rs | 4 ---- .../rustdoc-ui/coverage/output-format-fail-check.stderr | 6 ------ 2 files changed, 10 deletions(-) delete mode 100644 src/test/rustdoc-ui/coverage/output-format-fail-check.rs delete mode 100644 src/test/rustdoc-ui/coverage/output-format-fail-check.stderr diff --git a/src/test/rustdoc-ui/coverage/output-format-fail-check.rs b/src/test/rustdoc-ui/coverage/output-format-fail-check.rs deleted file mode 100644 index 30b525df76359..0000000000000 --- a/src/test/rustdoc-ui/coverage/output-format-fail-check.rs +++ /dev/null @@ -1,4 +0,0 @@ -// compile-flags:-Z unstable-options --output-format - -/// toudoum! -pub struct SomeStruct; diff --git a/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr b/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr deleted file mode 100644 index 9e9aa0e050163..0000000000000 --- a/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr +++ /dev/null @@ -1,6 +0,0 @@ -warning: the 'output-format' flag is considered deprecated - | - = warning: see issue #44136 for more information - -error: too many file operands - From 528cbc4879ceab332d509e4959fcea8baa7e8b92 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Mar 2020 16:43:03 +0100 Subject: [PATCH 08/40] fix memory leak when vec::IntoIter panics during drop --- src/liballoc/vec.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 61416f2b906d3..913e261ef12a5 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2626,13 +2626,21 @@ impl Clone for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T> Drop for IntoIter { fn drop(&mut self) { + struct DropGuard<'a, T>(&'a mut IntoIter); + + impl Drop for DropGuard<'_, T> { + fn drop(&mut self) { + // RawVec handles deallocation + let _ = unsafe { RawVec::from_raw_parts(self.0.buf.as_ptr(), self.0.cap) }; + } + } + + let guard = DropGuard(self); // destroy the remaining elements unsafe { - ptr::drop_in_place(self.as_mut_slice()); + ptr::drop_in_place(guard.0.as_mut_slice()); } - - // RawVec handles deallocation - let _ = unsafe { RawVec::from_raw_parts(self.buf.as_ptr(), self.cap) }; + // now `guard` will be dropped and do the rest } } From 1a9fc18e830dc57731e2976edb5c5f0fabc5019c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Mar 2020 11:16:23 +0100 Subject: [PATCH 09/40] panic_bounds_check: use caller_location, like PanicFnLangItem --- src/libcore/panicking.rs | 18 ++++++++++++++++++ src/librustc_codegen_ssa/mir/block.rs | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 61b764f2d6206..d58a7cfec951b 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -52,6 +52,24 @@ pub fn panic(expr: &str) -> ! { panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), Location::caller()) } +#[cfg(not(bootstrap))] +#[cold] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[track_caller] +#[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access +fn panic_bounds_check(index: usize, len: usize) -> ! { + if cfg!(feature = "panic_immediate_abort") { + unsafe { super::intrinsics::abort() } + } + + panic_fmt( + format_args!("index out of bounds: the len is {} but the index is {}", len, index), + Location::caller(), + ) +} + +// For bootstrap, we need a variant with the old argument order. +#[cfg(bootstrap)] #[cold] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index a1b54607b809e..f22c0216a78d1 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -415,11 +415,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { AssertKind::BoundsCheck { ref len, ref index } => { let len = self.codegen_operand(&mut bx, len).immediate(); let index = self.codegen_operand(&mut bx, index).immediate(); - (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len]) + // It's `fn panic_bounds_check(index: usize, len: usize)`, and + // `#[track_caller]` adds an implicit third argument. + (lang_items::PanicBoundsCheckFnLangItem, vec![index, len, location]) } _ => { let msg_str = Symbol::intern(msg.description()); let msg = bx.const_str(msg_str); + // It's `pub fn panic(expr: &str)`, with the wide reference being passed + // as two arguments, and `#[track_caller]` adds an implicit third argument. (lang_items::PanicFnLangItem, vec![msg.0, msg.1, location]) } }; From 51b60b75e79e39dcbb1fa96d72f4cbb82df7f2ae Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Mar 2020 16:56:45 +0100 Subject: [PATCH 10/40] Improve readability --- src/librustc_codegen_ssa/mir/block.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index f22c0216a78d1..6963f1d811a9b 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -415,8 +415,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { AssertKind::BoundsCheck { ref len, ref index } => { let len = self.codegen_operand(&mut bx, len).immediate(); let index = self.codegen_operand(&mut bx, index).immediate(); - // It's `fn panic_bounds_check(index: usize, len: usize)`, and - // `#[track_caller]` adds an implicit third argument. + // It's `fn panic_bounds_check(index: usize, len: usize)`, + // and `#[track_caller]` adds an implicit third argument. (lang_items::PanicBoundsCheckFnLangItem, vec![index, len, location]) } _ => { From f34e0664a1fa63f89f2257dba7d0d13445f58c02 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Mar 2020 19:58:58 +0100 Subject: [PATCH 11/40] remove no-longer needed span from Miri Machine hook --- src/librustc_mir/const_eval/machine.rs | 1 - src/librustc_mir/interpret/machine.rs | 1 - src/librustc_mir/interpret/terminator.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index ed8029834680c..bb661d3d2a30a 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -280,7 +280,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, fn assert_panic( ecx: &mut InterpCx<'mir, 'tcx, Self>, - _span: Span, msg: &AssertMessage<'tcx>, _unwind: Option, ) -> InterpResult<'tcx> { diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 6615cc608fb54..087517ff4e31d 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -165,7 +165,6 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Called to evaluate `Assert` MIR terminators that trigger a panic. fn assert_panic( ecx: &mut InterpCx<'mir, 'tcx, Self>, - span: Span, msg: &mir::AssertMessage<'tcx>, unwind: Option, ) -> InterpResult<'tcx>; diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index ea8378574a3e0..b5c34daf8a318 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -95,7 +95,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if expected == cond_val { self.go_to_block(target); } else { - M::assert_panic(self, terminator.source_info.span, msg, cleanup)?; + M::assert_panic(self, msg, cleanup)?; } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 0560f77f5c99f..4c353d1ae22e7 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -197,7 +197,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { fn assert_panic( _ecx: &mut InterpCx<'mir, 'tcx, Self>, - _span: Span, _msg: &rustc::mir::AssertMessage<'tcx>, _unwind: Option, ) -> InterpResult<'tcx> { From 0982c58edc5b9fe4cfc8b22bc3edaa95e4f5c638 Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 9 Mar 2020 21:40:00 -0400 Subject: [PATCH 12/40] update tidy documentation to recommend ./x.py test tidy --- src/tools/tidy/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 0b43396505138..909529d730784 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -2,7 +2,7 @@ //! //! This program runs all of the various tidy checks for style, cleanliness, //! etc. This is run by default on `./x.py test` and as part of the auto -//! builders. The tidy checks can be executed with `./x.py test src/tools/tidy`. +//! builders. The tidy checks can be executed with `./x.py test tidy`. #![deny(warnings)] From 259b06e33f533096f0b46beca8719fd4afceb78b Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 9 Mar 2020 21:55:56 -0400 Subject: [PATCH 13/40] add documentation of x.py tool testing --- src/bootstrap/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index c501378bff549..87da7327fe619 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -55,6 +55,9 @@ The script accepts commands, flags, and arguments to determine what to do: # run all unit tests ./x.py test + # execute tool tests + ./x.py test tidy + # execute the UI test suite ./x.py test src/test/ui From 9f734c978c4c32eea552d45fef582804c1d2b9bf Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 9 Mar 2020 22:04:59 -0400 Subject: [PATCH 14/40] Add documentation of tool testing with x.py script --- src/bootstrap/flags.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 516be6a30c235..a8b76c44f79d3 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -359,7 +359,7 @@ Arguments: subcommand_help.push_str( "\n Arguments: - This subcommand accepts a number of paths to directories to tests that + This subcommand accepts a number of paths to test directories that should be compiled and run. For example: ./x.py test src/test/ui @@ -367,11 +367,15 @@ Arguments: ./x.py test src/libstd --stage 0 --no-doc ./x.py test src/test/ui --bless ./x.py test src/test/ui --compare-mode nll - + Note that `test src/test/* --stage N` does NOT depend on `build src/rustc --stage N`; just like `build src/libstd --stage N` it tests the compiler produced by the previous stage. + Execute tool tests with a tool name argument: + + ./x.py test tidy + If no arguments are passed then the complete artifacts for that stage are compiled and tested. From 4922b683de170c70260b73426ccf16172fa63b7f Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 9 Mar 2020 22:15:41 -0400 Subject: [PATCH 15/40] remove trailing whitespace (tidy) --- src/bootstrap/flags.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index a8b76c44f79d3..4b04ee84c31db 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -367,7 +367,7 @@ Arguments: ./x.py test src/libstd --stage 0 --no-doc ./x.py test src/test/ui --bless ./x.py test src/test/ui --compare-mode nll - + Note that `test src/test/* --stage N` does NOT depend on `build src/rustc --stage N`; just like `build src/libstd --stage N` it tests the compiler produced by the previous stage. From c60d581eb15d6fbe17a657da7c1de4dc82b70b68 Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 9 Mar 2020 23:00:41 -0400 Subject: [PATCH 16/40] update x.py tidy testing command --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d6840b20c89ac..a58d4f2a7c6a4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -142,7 +142,7 @@ the issue in question. Please make sure your pull request is in compliance with Rust's style guidelines by running - $ python x.py test src/tools/tidy + $ python x.py test tidy Make this check before every pull request (and every new commit in a pull request); you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) From 6f2c01bcfbdcaa9686ceb37cce29564a2d662828 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Mishra Date: Tue, 10 Mar 2020 08:33:14 +0530 Subject: [PATCH 17/40] Add long error explanation for E0739 --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_error_codes/error_codes/E0739.md | 13 +++++++++++++ .../ui/rfc-2091-track-caller/only-for-fns.stderr | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/librustc_error_codes/error_codes/E0739.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 11d1209923fb2..0e14e2196caf0 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -411,6 +411,7 @@ E0735: include_str!("./error_codes/E0735.md"), E0736: include_str!("./error_codes/E0736.md"), E0737: include_str!("./error_codes/E0737.md"), E0738: include_str!("./error_codes/E0738.md"), +E0739: include_str!("./error_codes/E0739.md"), E0740: include_str!("./error_codes/E0740.md"), E0741: include_str!("./error_codes/E0741.md"), E0742: include_str!("./error_codes/E0742.md"), @@ -610,5 +611,4 @@ E0748: include_str!("./error_codes/E0748.md"), E0722, // Malformed `#[optimize]` attribute E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions E0726, // non-explicit (not `'_`) elided lifetime in unsupported position - E0739, // invalid track_caller application/syntax } diff --git a/src/librustc_error_codes/error_codes/E0739.md b/src/librustc_error_codes/error_codes/E0739.md new file mode 100644 index 0000000000000..d3016f53a94b0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0739.md @@ -0,0 +1,13 @@ +`#[track_caller]` can not be applied on struct. + +Erroneous code example: + +```compile_fail,E0739 +#![feature(track_caller)] +#[track_caller] +struct Bar { + a: u8, +} +``` + +[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr index 7becb9c5b60af..c2fb8fa1eb6ca 100644 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr @@ -8,3 +8,4 @@ LL | struct S; error: aborting due to previous error +For more information about this error, try `rustc --explain E0739`. From 761c8c1eefa8cecb1a55628674690c53cc8c473b Mon Sep 17 00:00:00 2001 From: Ayush Kumar Mishra Date: Tue, 10 Mar 2020 09:07:29 +0530 Subject: [PATCH 18/40] Removed trailing whitespace --- src/librustc_error_codes/error_codes/E0739.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0739.md b/src/librustc_error_codes/error_codes/E0739.md index d3016f53a94b0..707751066edbc 100644 --- a/src/librustc_error_codes/error_codes/E0739.md +++ b/src/librustc_error_codes/error_codes/E0739.md @@ -1,4 +1,4 @@ -`#[track_caller]` can not be applied on struct. +`#[track_caller]` can not be applied on struct. Erroneous code example: From 9596dc2a47861d73996a550cba7caf55b2737c17 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 01:47:15 +0100 Subject: [PATCH 19/40] parse_labeled_expr: simplify --- src/librustc_parse/parser/expr.rs | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 16ea2773b2009..e0e6fd5eed6b7 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1069,24 +1069,22 @@ impl<'a> Parser<'a> { fn parse_labeled_expr(&mut self, label: Label, attrs: AttrVec) -> PResult<'a, P> { let lo = label.ident.span; + let label = Some(label); self.expect(&token::Colon)?; if self.eat_keyword(kw::While) { - return self.parse_while_expr(Some(label), lo, attrs); - } - if self.eat_keyword(kw::For) { - return self.parse_for_expr(Some(label), lo, attrs); - } - if self.eat_keyword(kw::Loop) { - return self.parse_loop_expr(Some(label), lo, attrs); - } - if self.token == token::OpenDelim(token::Brace) { - return self.parse_block_expr(Some(label), lo, BlockCheckMode::Default, attrs); + self.parse_while_expr(label, lo, attrs) + } else if self.eat_keyword(kw::For) { + self.parse_for_expr(label, lo, attrs) + } else if self.eat_keyword(kw::Loop) { + self.parse_loop_expr(label, lo, attrs) + } else if self.check(&token::OpenDelim(token::Brace)) { + self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs) + } else { + let msg = "expected `while`, `for`, `loop` or `{` after a label"; + self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); + // Continue as an expression in an effort to recover on `'label: non_block_expr`. + self.parse_expr() } - - let msg = "expected `while`, `for`, `loop` or `{` after a label"; - self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); - // Continue as an expression in an effort to recover on `'label: non_block_expr`. - self.parse_expr() } /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead. From c303c4463cd3530c634dac8614feac7723ab0c58 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 02:46:13 +0100 Subject: [PATCH 20/40] use error_block_no_opening_brace more --- src/librustc_parse/parser/stmt.rs | 6 ++- src/test/ui/parser/block-no-opening-brace.rs | 30 +++++++++++ .../ui/parser/block-no-opening-brace.stderr | 53 +++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/parser/block-no-opening-brace.rs create mode 100644 src/test/ui/parser/block-no-opening-brace.stderr diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 3864ec3aaa163..511d4bfccd2cf 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -304,7 +304,11 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtBlock, |x| (Vec::new(), x)); let lo = self.token.span; - self.expect(&token::OpenDelim(token::Brace))?; + + if !self.eat(&token::OpenDelim(token::Brace)) { + return self.error_block_no_opening_brace(); + } + Ok((self.parse_inner_attributes()?, self.parse_block_tail(lo, BlockCheckMode::Default)?)) } diff --git a/src/test/ui/parser/block-no-opening-brace.rs b/src/test/ui/parser/block-no-opening-brace.rs new file mode 100644 index 0000000000000..169625bf8973b --- /dev/null +++ b/src/test/ui/parser/block-no-opening-brace.rs @@ -0,0 +1,30 @@ +// edition:2018 + +#![feature(try_blocks)] + +fn main() {} + +fn f1() { + loop + let x = 0; //~ ERROR expected `{`, found keyword `let` + } + +fn f2() { + while true + let x = 0; //~ ERROR expected `{`, found keyword `let` + } + +fn f3() { + for x in 0..1 + let x = 0; //~ ERROR expected `{`, found keyword `let` + } + +fn f4() { + try //~ ERROR expected expression, found reserved keyword `try` + let x = 0; + } + +fn f5() { + async //~ ERROR async closures are unstable + let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let` + } diff --git a/src/test/ui/parser/block-no-opening-brace.stderr b/src/test/ui/parser/block-no-opening-brace.stderr new file mode 100644 index 0000000000000..56db1147360de --- /dev/null +++ b/src/test/ui/parser/block-no-opening-brace.stderr @@ -0,0 +1,53 @@ +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:9:6 + | +LL | let x = 0; + | ^^^------- + | | + | expected `{` + | help: try placing this code inside a block: `{ let x = 0; }` + +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:14:6 + | +LL | let x = 0; + | ^^^------- + | | + | expected `{` + | help: try placing this code inside a block: `{ let x = 0; }` + +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:19:6 + | +LL | let x = 0; + | ^^^------- + | | + | expected `{` + | help: try placing this code inside a block: `{ let x = 0; }` + +error: expected expression, found reserved keyword `try` + --> $DIR/block-no-opening-brace.rs:23:4 + | +LL | try + | ^^^ expected expression + +error: expected one of `move`, `|`, or `||`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:29:6 + | +LL | async + | - expected one of `move`, `|`, or `||` +LL | let x = 0; + | ^^^ unexpected token + +error[E0658]: async closures are unstable + --> $DIR/block-no-opening-brace.rs:28:4 + | +LL | async + | ^^^^^ + | + = note: see issue #62290 for more information + = help: add `#![feature(async_closure)]` to the crate attributes to enable + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. From 883e90dd81b207cc5d9e85c02f628432b7f8d65d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 03:24:58 +0100 Subject: [PATCH 21/40] simplify parse_inner_attributes --- src/librustc_parse/parser/attr.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs index bdd78e671a8b3..1e7f5b662f3d2 100644 --- a/src/librustc_parse/parser/attr.rs +++ b/src/librustc_parse/parser/attr.rs @@ -201,12 +201,8 @@ impl<'a> Parser<'a> { let mut attrs: Vec = vec![]; loop { match self.token.kind { - token::Pound => { - // Don't even try to parse if it's not an inner attribute. - if !self.look_ahead(1, |t| t == &token::Not) { - break; - } - + // Only try to parse if it is an inner attribute (has `!`). + token::Pound if self.look_ahead(1, |t| t == &token::Not) => { let attr = self.parse_attribute(true)?; assert_eq!(attr.style, ast::AttrStyle::Inner); attrs.push(attr); From 8ee220c447911c519ebbd118e1415d961317b18d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 05:49:30 +0100 Subject: [PATCH 22/40] more reuse in block parsing & improve diagnostics. --- src/librustc_ast/token.rs | 10 +++++ src/librustc_parse/parser/expr.rs | 16 ++++---- src/librustc_parse/parser/stmt.rs | 17 +++++--- .../label_break_value_illegal_uses.stderr | 5 ++- src/test/ui/parser/bad-interpolated-block.rs | 15 +++++++ .../ui/parser/bad-interpolated-block.stderr | 39 +++++++++++++++++++ src/test/ui/parser/closure-return-syntax.rs | 2 +- .../ui/parser/closure-return-syntax.stderr | 7 +++- .../unsafe/unsafe-block-without-braces.stderr | 7 ++-- 9 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/parser/bad-interpolated-block.rs create mode 100644 src/test/ui/parser/bad-interpolated-block.stderr diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs index b67b7d346f756..3fc6444168e24 100644 --- a/src/librustc_ast/token.rs +++ b/src/librustc_ast/token.rs @@ -535,6 +535,16 @@ impl Token { false } + // Is the token an interpolated block (`$b:block`)? + pub fn is_whole_block(&self) -> bool { + if let Interpolated(ref nt) = self.kind { + if let NtBlock(..) = **nt { + return true; + } + } + false + } + /// Returns `true` if the token is either the `mut` or `const` keyword. pub fn is_mutability(&self) -> bool { self.is_keyword(kw::Mut) || self.is_keyword(kw::Const) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index e0e6fd5eed6b7..b1c5eaf8973ab 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1077,7 +1077,7 @@ impl<'a> Parser<'a> { self.parse_for_expr(label, lo, attrs) } else if self.eat_keyword(kw::Loop) { self.parse_loop_expr(label, lo, attrs) - } else if self.check(&token::OpenDelim(token::Brace)) { + } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() { self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs) } else { let msg = "expected `while`, `for`, `loop` or `{` after a label"; @@ -1361,18 +1361,20 @@ impl<'a> Parser<'a> { opt_label: Option