From 902904a79a5498438e93f41d728615b54c679f19 Mon Sep 17 00:00:00 2001 From: Daiki Mizukami Date: Wed, 24 Apr 2019 20:12:24 +0900 Subject: [PATCH 01/19] std: Derive `Default` for `io::Cursor` --- src/libstd/io/cursor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 247d45c3ec9..abef36e7b2e 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -72,7 +72,7 @@ use core::convert::TryInto; /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct Cursor { inner: T, pos: u64, From f007e6f442adafae3e5f2f7f635dc12463bbe0bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 22 Apr 2019 19:37:23 -0700 Subject: [PATCH 02/19] Identify when a stmt could have been parsed as an expr There are some expressions that can be parsed as a statement without a trailing semicolon depending on the context, which can lead to confusing errors due to the same looking code being accepted in some places and not others. Identify these cases and suggest enclosing in parenthesis making the parse non-ambiguous without changing the accepted grammar. --- src/librustc_typeck/check/mod.rs | 28 ++++++- src/libsyntax/parse/lexer/mod.rs | 3 +- src/libsyntax/parse/mod.rs | 4 +- src/libsyntax/parse/parser.rs | 64 ++++++++++++++- src/libsyntax/util/parser.rs | 22 +++++ src/test/ui/parser/expr-as-stmt.fixed | 34 ++++++++ src/test/ui/parser/expr-as-stmt.rs | 34 ++++++++ src/test/ui/parser/expr-as-stmt.stderr | 80 +++++++++++++++++++ .../parser/match-arrows-block-then-binop.rs | 6 +- .../match-arrows-block-then-binop.stderr | 6 ++ 10 files changed, 270 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/parser/expr-as-stmt.fixed create mode 100644 src/test/ui/parser/expr-as-stmt.rs create mode 100644 src/test/ui/parser/expr-as-stmt.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f1163847892..61270716dfc 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4165,9 +4165,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { oprnd_t = self.make_overloaded_place_return_type(method).ty; self.write_method_call(expr.hir_id, method); } else { - type_error_struct!(tcx.sess, expr.span, oprnd_t, E0614, - "type `{}` cannot be dereferenced", - oprnd_t).emit(); + let mut err = type_error_struct!( + tcx.sess, + expr.span, + oprnd_t, + E0614, + "type `{}` cannot be dereferenced", + oprnd_t, + ); + let sp = tcx.sess.source_map().start_point(expr.span); + if let Some(sp) = tcx.sess.parse_sess.abiguous_block_expr_parse + .borrow().get(&sp) + { + if let Ok(snippet) = tcx.sess.source_map() + .span_to_snippet(*sp) + { + err.span_suggestion( + *sp, + "parenthesis are required to parse this \ + as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + } + } + err.emit(); oprnd_t = tcx.types.err; } } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index cf8f8abe2ab..e7d79a647d3 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1899,7 +1899,7 @@ mod tests { use std::io; use std::path::PathBuf; use syntax_pos::{BytePos, Span, NO_EXPANSION}; - use rustc_data_structures::fx::FxHashSet; + use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_data_structures::sync::Lock; fn mk_sess(sm: Lrc) -> ParseSess { @@ -1918,6 +1918,7 @@ mod tests { raw_identifier_spans: Lock::new(Vec::new()), registered_diagnostics: Lock::new(ErrorMap::new()), buffered_lints: Lock::new(vec![]), + abiguous_block_expr_parse: Lock::new(FxHashMap::default()), } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 1abc7832ffa..94bbd5ba2f7 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -16,7 +16,7 @@ use rustc_data_structures::sync::{Lrc, Lock}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; use log::debug; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use std::borrow::Cow; use std::iter; use std::path::{Path, PathBuf}; @@ -47,6 +47,7 @@ pub struct ParseSess { included_mod_stack: Lock>, source_map: Lrc, pub buffered_lints: Lock>, + pub abiguous_block_expr_parse: Lock>, } impl ParseSess { @@ -70,6 +71,7 @@ impl ParseSess { included_mod_stack: Lock::new(vec![]), source_map, buffered_lints: Lock::new(vec![]), + abiguous_block_expr_parse: Lock::new(FxHashMap::default()), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8efe84cdf01..3c7f477cc8f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -186,6 +186,7 @@ enum PrevTokenKind { Interpolated, Eof, Ident, + BitOr, Other, } @@ -1410,6 +1411,7 @@ impl<'a> Parser<'a> { token::DocComment(..) => PrevTokenKind::DocComment, token::Comma => PrevTokenKind::Comma, token::BinOp(token::Plus) => PrevTokenKind::Plus, + token::BinOp(token::Or) => PrevTokenKind::BitOr, token::Interpolated(..) => PrevTokenKind::Interpolated, token::Eof => PrevTokenKind::Eof, token::Ident(..) => PrevTokenKind::Ident, @@ -2925,6 +2927,19 @@ impl<'a> Parser<'a> { let msg = format!("expected expression, found {}", self.this_token_descr()); let mut err = self.fatal(&msg); + let sp = self.sess.source_map().start_point(self.span); + if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow() + .get(&sp) + { + if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { + err.span_suggestion( + *sp, + "parenthesis are required to parse this as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + } + } err.span_label(self.span, "expected expression"); return Err(err); } @@ -3616,9 +3631,41 @@ impl<'a> Parser<'a> { } }; - if self.expr_is_complete(&lhs) { - // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 - return Ok(lhs); + match (self.expr_is_complete(&lhs), AssocOp::from_token(&self.token)) { + (true, None) => { + // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 + return Ok(lhs); + } + (false, _) => {} // continue parsing the expression + (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` + (true, Some(AssocOp::Subtract)) | // `{ 42 } -5` + (true, Some(AssocOp::Add)) => { // `{ 42 } + 42 + // These cases are ambiguous and can't be identified in the parser alone + let sp = self.sess.source_map().start_point(self.span); + self.sess.abiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); + return Ok(lhs); + } + (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => { + return Ok(lhs); + } + (true, Some(_)) => { + // #54186, #54482, #59975 + // We've found an expression that would be parsed as a statement, but the next + // token implies this should be parsed as an expression. + let mut err = self.sess.span_diagnostic.struct_span_err( + self.span, + "ambiguous parse", + ); + let snippet = self.sess.source_map().span_to_snippet(lhs.span) + .unwrap_or_else(|_| pprust::expr_to_string(&lhs)); + err.span_suggestion( + lhs.span, + "parenthesis are required to parse this as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + err.emit(); + } } self.expected_tokens.push(TokenType::Operator); while let Some(op) = AssocOp::from_token(&self.token) { @@ -4929,6 +4976,17 @@ impl<'a> Parser<'a> { ); let mut err = self.fatal(&msg); err.span_label(self.span, format!("expected {}", expected)); + let sp = self.sess.source_map().start_point(self.span); + if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow().get(&sp) { + if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { + err.span_suggestion( + *sp, + "parenthesis are required to parse this as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + } + } return Err(err); } } diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index 5f15ede7b0b..d76dede8155 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -207,6 +207,28 @@ impl AssocOp { ObsoleteInPlace | Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None } } + + pub fn can_continue_expr_unambiguously(&self) -> bool { + use AssocOp::*; + match self { + BitXor | // `{ 42 } ^ 3` + Assign | // `{ 42 } = { 42 }` + Divide | // `{ 42 } / 42` + Modulus | // `{ 42 } % 2` + ShiftRight | // `{ 42 } >> 2` + LessEqual | // `{ 42 } <= 3` + Greater | // `{ 42 } > 3` + GreaterEqual | // `{ 42 } >= 3` + AssignOp(_) | // `{ 42 } +=` + LAnd | // `{ 42 } &&foo` + As | // `{ 42 } as usize` + // Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect + // NotEqual | // `{ 42 } != { 42 } struct literals parser recovery. + Colon => true, // `{ 42 }: usize` + _ => false, + } + + } } pub const PREC_RESET: i8 = -100; diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed new file mode 100644 index 00000000000..a0abd00a15c --- /dev/null +++ b/src/test/ui/parser/expr-as-stmt.fixed @@ -0,0 +1,34 @@ +// run-rustfix +#![allow(unused_variables)] +#![allow(dead_code)] +#![allow(unused_must_use)] + +fn foo() -> i32 { + ({2}) + {2} //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn bar() -> i32 { + ({2}) + 2 //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn zul() -> u32 { + let foo = 3; + ({ 42 }) + foo; //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types + 32 +} + +fn baz() -> i32 { + ({ 3 }) * 3 //~ ERROR type `{integer}` cannot be dereferenced + //~^ ERROR mismatched types +} + +fn qux(a: Option, b: Option) -> bool { + (if let Some(x) = a { true } else { false }) + && //~ ERROR ambiguous parse + if let Some(y) = a { true } else { false } +} + +fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs new file mode 100644 index 00000000000..cf2e7266a4a --- /dev/null +++ b/src/test/ui/parser/expr-as-stmt.rs @@ -0,0 +1,34 @@ +// run-rustfix +#![allow(unused_variables)] +#![allow(dead_code)] +#![allow(unused_must_use)] + +fn foo() -> i32 { + {2} + {2} //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn bar() -> i32 { + {2} + 2 //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn zul() -> u32 { + let foo = 3; + { 42 } + foo; //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types + 32 +} + +fn baz() -> i32 { + { 3 } * 3 //~ ERROR type `{integer}` cannot be dereferenced + //~^ ERROR mismatched types +} + +fn qux(a: Option, b: Option) -> bool { + if let Some(x) = a { true } else { false } + && //~ ERROR ambiguous parse + if let Some(y) = a { true } else { false } +} + +fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr new file mode 100644 index 00000000000..03119605432 --- /dev/null +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -0,0 +1,80 @@ +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:7:9 + | +LL | {2} + {2} + | --- ^ expected expression + | | + | help: parenthesis are required to parse this as an expression: `({2})` + +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:12:9 + | +LL | {2} + 2 + | --- ^ expected expression + | | + | help: parenthesis are required to parse this as an expression: `({2})` + +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:18:12 + | +LL | { 42 } + foo; + | ------ ^ expected expression + | | + | help: parenthesis are required to parse this as an expression: `({ 42 })` + +error: ambiguous parse + --> $DIR/expr-as-stmt.rs:30:5 + | +LL | if let Some(x) = a { true } else { false } + | ------------------------------------------ help: parenthesis are required to parse this as an expression: `(if let Some(x) = a { true } else { false })` +LL | && + | ^^ + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:7:6 + | +LL | {2} + {2} + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:12:6 + | +LL | {2} + 2 + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:18:7 + | +LL | { 42 } + foo; + | ^^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:24:7 + | +LL | { 3 } * 3 + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error[E0614]: type `{integer}` cannot be dereferenced + --> $DIR/expr-as-stmt.rs:24:11 + | +LL | { 3 } * 3 + | ----- ^^^ + | | + | help: parenthesis are required to parse this as an expression: `({ 3 })` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0308, E0614. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/match-arrows-block-then-binop.rs b/src/test/ui/parser/match-arrows-block-then-binop.rs index 1a40d674929..56c917c7462 100644 --- a/src/test/ui/parser/match-arrows-block-then-binop.rs +++ b/src/test/ui/parser/match-arrows-block-then-binop.rs @@ -1,7 +1,7 @@ fn main() { - - match 0 { + let _ = match 0 { 0 => { + 0 } + 5 //~ ERROR expected pattern, found `+` - } + }; } diff --git a/src/test/ui/parser/match-arrows-block-then-binop.stderr b/src/test/ui/parser/match-arrows-block-then-binop.stderr index a844cac189a..0d7f81645b4 100644 --- a/src/test/ui/parser/match-arrows-block-then-binop.stderr +++ b/src/test/ui/parser/match-arrows-block-then-binop.stderr @@ -3,6 +3,12 @@ error: expected pattern, found `+` | LL | } + 5 | ^ expected pattern +help: parenthesis are required to parse this as an expression + | +LL | 0 => ({ +LL | 0 +LL | }) + 5 + | error: aborting due to previous error From bff0be37845a96010fa2161bbf137fadfe763ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 29 Apr 2019 14:35:09 -0700 Subject: [PATCH 03/19] Add test case for #47287 --- src/test/ui/parser/expr-as-stmt.fixed | 6 ++++++ src/test/ui/parser/expr-as-stmt.rs | 6 ++++++ src/test/ui/parser/expr-as-stmt.stderr | 14 +++++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed index a0abd00a15c..123f06e7707 100644 --- a/src/test/ui/parser/expr-as-stmt.fixed +++ b/src/test/ui/parser/expr-as-stmt.fixed @@ -31,4 +31,10 @@ fn qux(a: Option, b: Option) -> bool { if let Some(y) = a { true } else { false } } +fn moo(x: u32) -> bool { + (match x { + _ => 1, + }) > 0 //~ ERROR ambiguous parse +} + fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs index cf2e7266a4a..6f713c08940 100644 --- a/src/test/ui/parser/expr-as-stmt.rs +++ b/src/test/ui/parser/expr-as-stmt.rs @@ -31,4 +31,10 @@ fn qux(a: Option, b: Option) -> bool { if let Some(y) = a { true } else { false } } +fn moo(x: u32) -> bool { + match x { + _ => 1, + } > 0 //~ ERROR ambiguous parse +} + fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index 03119605432..be577b8f36f 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -30,6 +30,18 @@ LL | if let Some(x) = a { true } else { false } LL | && | ^^ +error: ambiguous parse + --> $DIR/expr-as-stmt.rs:37:7 + | +LL | } > 0 + | ^ +help: parenthesis are required to parse this as an expression + | +LL | (match x { +LL | _ => 1, +LL | }) > 0 + | + error[E0308]: mismatched types --> $DIR/expr-as-stmt.rs:7:6 | @@ -74,7 +86,7 @@ LL | { 3 } * 3 | | | help: parenthesis are required to parse this as an expression: `({ 3 })` -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0308, E0614. For more information about an error, try `rustc --explain E0308`. From 617ce2b7ee330bbcc7ce8eb87160c71ad995639b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 30 Apr 2019 20:37:42 -0700 Subject: [PATCH 04/19] Reword ambigous parse error to fit with the current error --- src/libsyntax/parse/parser.rs | 11 ++++++----- src/test/ui/parser/expr-as-stmt.fixed | 4 ++-- src/test/ui/parser/expr-as-stmt.rs | 4 ++-- src/test/ui/parser/expr-as-stmt.stderr | 8 ++++---- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3c7f477cc8f..fbd1203dec9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3649,13 +3649,14 @@ impl<'a> Parser<'a> { return Ok(lhs); } (true, Some(_)) => { - // #54186, #54482, #59975 // We've found an expression that would be parsed as a statement, but the next // token implies this should be parsed as an expression. - let mut err = self.sess.span_diagnostic.struct_span_err( - self.span, - "ambiguous parse", - ); + // For example: `if let Some(x) = x { x } else { 0 } / 2` + let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &format!( + "expected expression, found `{}`", + pprust::token_to_string(&self.token), + )); + err.span_label(self.span, "expected expression"); let snippet = self.sess.source_map().span_to_snippet(lhs.span) .unwrap_or_else(|_| pprust::expr_to_string(&lhs)); err.span_suggestion( diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed index 123f06e7707..1ce6f9c2503 100644 --- a/src/test/ui/parser/expr-as-stmt.fixed +++ b/src/test/ui/parser/expr-as-stmt.fixed @@ -27,14 +27,14 @@ fn baz() -> i32 { fn qux(a: Option, b: Option) -> bool { (if let Some(x) = a { true } else { false }) - && //~ ERROR ambiguous parse + && //~ ERROR expected expression if let Some(y) = a { true } else { false } } fn moo(x: u32) -> bool { (match x { _ => 1, - }) > 0 //~ ERROR ambiguous parse + }) > 0 //~ ERROR expected expression } fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs index 6f713c08940..b526c17488e 100644 --- a/src/test/ui/parser/expr-as-stmt.rs +++ b/src/test/ui/parser/expr-as-stmt.rs @@ -27,14 +27,14 @@ fn baz() -> i32 { fn qux(a: Option, b: Option) -> bool { if let Some(x) = a { true } else { false } - && //~ ERROR ambiguous parse + && //~ ERROR expected expression if let Some(y) = a { true } else { false } } fn moo(x: u32) -> bool { match x { _ => 1, - } > 0 //~ ERROR ambiguous parse + } > 0 //~ ERROR expected expression } fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index be577b8f36f..1725ba944c5 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -22,19 +22,19 @@ LL | { 42 } + foo; | | | help: parenthesis are required to parse this as an expression: `({ 42 })` -error: ambiguous parse +error: expected expression, found `&&` --> $DIR/expr-as-stmt.rs:30:5 | LL | if let Some(x) = a { true } else { false } | ------------------------------------------ help: parenthesis are required to parse this as an expression: `(if let Some(x) = a { true } else { false })` LL | && - | ^^ + | ^^ expected expression -error: ambiguous parse +error: expected expression, found `>` --> $DIR/expr-as-stmt.rs:37:7 | LL | } > 0 - | ^ + | ^ expected expression help: parenthesis are required to parse this as an expression | LL | (match x { From 145add7ccfa14e74ff770ee10e0cf2d6609c7e70 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 30 Mar 2019 17:18:54 +0000 Subject: [PATCH 05/19] Add test for slice drop shims --- src/test/mir-opt/slice-drop-shim.rs | 92 +++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/test/mir-opt/slice-drop-shim.rs diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs new file mode 100644 index 00000000000..f558ec18ba9 --- /dev/null +++ b/src/test/mir-opt/slice-drop-shim.rs @@ -0,0 +1,92 @@ +fn main() { + std::ptr::drop_in_place::<[String]> as unsafe fn(_); +} + +// END RUST SOURCE + +// START rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir +// let mut _2: usize; +// let mut _3: bool; +// let mut _4: usize; +// let mut _5: usize; +// let mut _6: &mut std::string::String; +// let mut _7: bool; +// let mut _8: &mut std::string::String; +// let mut _9: bool; +// let mut _10: *mut std::string::String; +// let mut _11: usize; +// let mut _12: *mut std::string::String; +// let mut _13: &mut std::string::String; +// let mut _14: bool; +// let mut _15: &mut std::string::String; +// let mut _16: bool; +// let mut _17: *mut [std::string::String]; +// bb0: { +// goto -> bb15; +// } +// bb1: { +// return; +// } +// bb2 (cleanup): { +// resume; +// } +// bb3 (cleanup): { +// _6 = &mut (*_1)[_4]; +// _4 = Add(_4, const 1usize); +// drop((*_6)) -> bb4; +// } +// bb4 (cleanup): { +// _7 = Eq(_4, _5); +// switchInt(move _7) -> [false: bb3, otherwise: bb2]; +// } +// bb5: { +// _8 = &mut (*_1)[_4]; +// _4 = Add(_4, const 1usize); +// drop((*_8)) -> [return: bb6, unwind: bb4]; +// } +// bb6: { +// _9 = Eq(_4, _5); +// switchInt(move _9) -> [false: bb5, otherwise: bb1]; +// } +// bb7: { +// _5 = Len((*_1)); +// _4 = const 0usize; +// goto -> bb6; +// } +// bb8: { +// goto -> bb7; +// } +// bb9 (cleanup): { +// _13 = &mut (*_10); +// _10 = Offset(_10, const 1usize); +// drop((*_13)) -> bb10; +// } +// bb10 (cleanup): { +// _14 = Eq(_10, _12); +// switchInt(move _14) -> [false: bb9, otherwise: bb2]; +// } +// bb11: { +// _15 = &mut (*_10); +// _10 = Offset(_10, const 1usize); +// drop((*_15)) -> [return: bb12, unwind: bb10]; +// } +// bb12: { +// _16 = Eq(_10, _12); +// switchInt(move _16) -> [false: bb11, otherwise: bb1]; +// } +// bb13: { +// _11 = Len((*_1)); +// _17 = &mut (*_1); +// _10 = move _17 as *mut std::string::String (Misc); +// _12 = Offset(_10, move _11); +// goto -> bb12; +// } +// bb14: { +// goto -> bb13; +// } +// bb15: { +// _2 = SizeOf(std::string::String); +// _3 = Eq(move _2, const 0usize); +// switchInt(move _3) -> [false: bb14, otherwise: bb8]; +// } +// END rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir From 6fff547828c13d311bc3e3034f190747b9367816 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 29 Apr 2019 20:38:08 +0100 Subject: [PATCH 06/19] Slightly simplify the MIR for slice drop shims --- src/librustc_mir/util/elaborate_drops.rs | 122 ++++++++++++----------- src/test/mir-opt/slice-drop-shim.rs | 72 +++++++------ 2 files changed, 99 insertions(+), 95 deletions(-) diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 856783bcbaa..98ca7c32675 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -10,7 +10,7 @@ use rustc::ty::util::IntTypeExt; use rustc_data_structures::indexed_vec::Idx; use crate::util::patch::MirPatch; -use std::u32; +use std::convert::TryInto; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum DropFlagState { @@ -545,10 +545,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> self.elaborator.patch().new_block(result) } - /// create a loop that drops an array: - /// - + /// Create a loop that drops an array: /// + /// ```text /// loop-block: /// can_go = cur == length_or_end /// if can_go then succ else drop-block @@ -561,15 +560,16 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> /// cur = cur + 1 /// } /// drop(ptr) - fn drop_loop(&mut self, - succ: BasicBlock, - cur: Local, - length_or_end: &Place<'tcx>, - ety: Ty<'tcx>, - unwind: Unwind, - ptr_based: bool) - -> BasicBlock - { + /// ``` + fn drop_loop( + &mut self, + succ: BasicBlock, + cur: Local, + length_or_end: &Place<'tcx>, + ety: Ty<'tcx>, + unwind: Unwind, + ptr_based: bool, + ) -> BasicBlock { let copy = |place: &Place<'tcx>| Operand::Copy(place.clone()); let move_ = |place: &Place<'tcx>| Operand::Move(place.clone()); let tcx = self.tcx(); @@ -591,13 +591,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> elem: ProjectionElem::Deref, })) ), - Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Base(PlaceBase::Local(cur))), one)) + Rvalue::BinaryOp(BinOp::Offset, move_(&Place::Base(PlaceBase::Local(cur))), one)) } else { (Rvalue::Ref( tcx.lifetimes.re_erased, BorrowKind::Mut { allow_two_phase_borrow: false }, self.place.clone().index(cur)), - Rvalue::BinaryOp(BinOp::Add, copy(&Place::Base(PlaceBase::Local(cur))), one)) + Rvalue::BinaryOp(BinOp::Add, move_(&Place::Base(PlaceBase::Local(cur))), one)) }; let drop_block = BasicBlockData { @@ -647,9 +647,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> // } if let Some(size) = opt_size { - assert!(size <= (u32::MAX as u64), - "move out check doesn't implemented for array bigger then u32"); - let size = size as u32; + let size: u32 = size.try_into().unwrap_or_else(|_| { + bug!("move out check isn't implemented for array sizes bigger than u32::MAX"); + }); let fields: Vec<(Place<'tcx>, Option)> = (0..size).map(|i| { (self.place.clone().elem(ProjectionElem::ConstantIndex{ offset: i, @@ -667,33 +667,42 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let move_ = |place: &Place<'tcx>| Operand::Move(place.clone()); let tcx = self.tcx(); - let size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); - let size_is_zero = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool))); + let elem_size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); + let len = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); + + static USIZE_SWITCH_ZERO: &[u128] = &[0]; + let base_block = BasicBlockData { statements: vec![ - self.assign(size, Rvalue::NullaryOp(NullOp::SizeOf, ety)), - self.assign(size_is_zero, Rvalue::BinaryOp(BinOp::Eq, - move_(size), - self.constant_usize(0))) + self.assign(elem_size, Rvalue::NullaryOp(NullOp::SizeOf, ety)), + self.assign(len, Rvalue::Len(self.place.clone())), ], is_cleanup: self.unwind.is_cleanup(), terminator: Some(Terminator { source_info: self.source_info, - kind: TerminatorKind::if_( - tcx, - move_(size_is_zero), - self.drop_loop_pair(ety, false), - self.drop_loop_pair(ety, true) - ) + kind: TerminatorKind::SwitchInt { + discr: move_(elem_size), + switch_ty: tcx.types.usize, + values: From::from(USIZE_SWITCH_ZERO), + targets: vec![ + self.drop_loop_pair(ety, false, len.clone()), + self.drop_loop_pair(ety, true, len.clone()), + ], + }, }) }; self.elaborator.patch().new_block(base_block) } - // create a pair of drop-loops of `place`, which drops its contents - // even in the case of 1 panic. If `ptr_based`, create a pointer loop, - // otherwise create an index loop. - fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock { + /// Ceates a pair of drop-loops of `place`, which drops its contents, even + /// in the case of 1 panic. If `ptr_based`, creates a pointer loop, + /// otherwise create an index loop. + fn drop_loop_pair( + &mut self, + ety: Ty<'tcx>, + ptr_based: bool, + length: Place<'tcx>, + ) -> BasicBlock { debug!("drop_loop_pair({:?}, {:?})", ety, ptr_based); let tcx = self.tcx(); let iter_ty = if ptr_based { @@ -703,7 +712,6 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> }; let cur = self.new_temp(iter_ty); - let length = Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); let length_or_end = if ptr_based { // FIXME check if we want to make it return a `Place` directly // if all use sites want a `Place::Base` anyway. @@ -722,9 +730,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> ptr_based) }); - let succ = self.succ; // FIXME(#43234) let loop_block = self.drop_loop( - succ, + self.succ, cur, &length_or_end, ety, @@ -732,31 +739,32 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> ptr_based); let cur = Place::Base(PlaceBase::Local(cur)); - let zero = self.constant_usize(0); - let mut drop_block_stmts = vec![]; - drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.place.clone()))); - if ptr_based { + let drop_block_stmts = if ptr_based { let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place)); let tmp = Place::Base(PlaceBase::Local(self.new_temp(tmp_ty))); // tmp = &mut P; // cur = tmp as *mut T; // end = Offset(cur, len); - drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - self.place.clone() - ))); - drop_block_stmts.push(self.assign(&cur, Rvalue::Cast( - CastKind::Misc, Operand::Move(tmp), iter_ty - ))); - drop_block_stmts.push(self.assign(&length_or_end, - Rvalue::BinaryOp(BinOp::Offset, - Operand::Copy(cur), Operand::Move(length) - ))); + vec![ + self.assign(&tmp, Rvalue::Ref( + tcx.lifetimes.re_erased, + BorrowKind::Mut { allow_two_phase_borrow: false }, + self.place.clone() + )), + self.assign( + &cur, + Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty), + ), + self.assign( + &length_or_end, + Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length) + )), + ] } else { - // index = 0 (length already pushed) - drop_block_stmts.push(self.assign(&cur, Rvalue::Use(zero))); - } + // cur = 0 (length already pushed) + let zero = self.constant_usize(0); + vec![self.assign(&cur, Rvalue::Use(zero))] + }; let drop_block = self.elaborator.patch().new_block(BasicBlockData { statements: drop_block_stmts, is_cleanup: unwind.is_cleanup(), @@ -768,7 +776,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> // FIXME(#34708): handle partially-dropped array/slice elements. let reset_block = self.drop_flag_reset_block(DropFlagMode::Deep, drop_block, unwind); - self.drop_flag_test_block(reset_block, succ, unwind) + self.drop_flag_test_block(reset_block, self.succ, unwind) } /// The slow-path - create an "open", elaborated drop for a type diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs index f558ec18ba9..754fad51b21 100644 --- a/src/test/mir-opt/slice-drop-shim.rs +++ b/src/test/mir-opt/slice-drop-shim.rs @@ -6,21 +6,19 @@ fn main() { // START rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir // let mut _2: usize; -// let mut _3: bool; +// let mut _3: usize; // let mut _4: usize; -// let mut _5: usize; -// let mut _6: &mut std::string::String; -// let mut _7: bool; -// let mut _8: &mut std::string::String; -// let mut _9: bool; +// let mut _5: &mut std::string::String; +// let mut _6: bool; +// let mut _7: &mut std::string::String; +// let mut _8: bool; +// let mut _9: *mut std::string::String; // let mut _10: *mut std::string::String; -// let mut _11: usize; -// let mut _12: *mut std::string::String; +// let mut _11: &mut std::string::String; +// let mut _12: bool; // let mut _13: &mut std::string::String; // let mut _14: bool; -// let mut _15: &mut std::string::String; -// let mut _16: bool; -// let mut _17: *mut [std::string::String]; +// let mut _15: *mut [std::string::String]; // bb0: { // goto -> bb15; // } @@ -31,25 +29,24 @@ fn main() { // resume; // } // bb3 (cleanup): { -// _6 = &mut (*_1)[_4]; -// _4 = Add(_4, const 1usize); -// drop((*_6)) -> bb4; +// _5 = &mut (*_1)[_4]; +// _4 = Add(move _4, const 1usize); +// drop((*_5)) -> bb4; // } // bb4 (cleanup): { -// _7 = Eq(_4, _5); -// switchInt(move _7) -> [false: bb3, otherwise: bb2]; +// _6 = Eq(_4, _3); +// switchInt(move _6) -> [false: bb3, otherwise: bb2]; // } // bb5: { -// _8 = &mut (*_1)[_4]; -// _4 = Add(_4, const 1usize); -// drop((*_8)) -> [return: bb6, unwind: bb4]; +// _7 = &mut (*_1)[_4]; +// _4 = Add(move _4, const 1usize); +// drop((*_7)) -> [return: bb6, unwind: bb4]; // } // bb6: { -// _9 = Eq(_4, _5); -// switchInt(move _9) -> [false: bb5, otherwise: bb1]; +// _8 = Eq(_4, _3); +// switchInt(move _8) -> [false: bb5, otherwise: bb1]; // } // bb7: { -// _5 = Len((*_1)); // _4 = const 0usize; // goto -> bb6; // } @@ -57,28 +54,27 @@ fn main() { // goto -> bb7; // } // bb9 (cleanup): { -// _13 = &mut (*_10); -// _10 = Offset(_10, const 1usize); -// drop((*_13)) -> bb10; +// _11 = &mut (*_9); +// _9 = Offset(move _9, const 1usize); +// drop((*_11)) -> bb10; // } // bb10 (cleanup): { -// _14 = Eq(_10, _12); -// switchInt(move _14) -> [false: bb9, otherwise: bb2]; +// _12 = Eq(_9, _10); +// switchInt(move _12) -> [false: bb9, otherwise: bb2]; // } // bb11: { -// _15 = &mut (*_10); -// _10 = Offset(_10, const 1usize); -// drop((*_15)) -> [return: bb12, unwind: bb10]; +// _13 = &mut (*_9); +// _9 = Offset(move _9, const 1usize); +// drop((*_13)) -> [return: bb12, unwind: bb10]; // } // bb12: { -// _16 = Eq(_10, _12); -// switchInt(move _16) -> [false: bb11, otherwise: bb1]; +// _14 = Eq(_9, _10); +// switchInt(move _14) -> [false: bb11, otherwise: bb1]; // } // bb13: { -// _11 = Len((*_1)); -// _17 = &mut (*_1); -// _10 = move _17 as *mut std::string::String (Misc); -// _12 = Offset(_10, move _11); +// _15 = &mut (*_1); +// _9 = move _15 as *mut std::string::String (Misc); +// _10 = Offset(_9, move _3); // goto -> bb12; // } // bb14: { @@ -86,7 +82,7 @@ fn main() { // } // bb15: { // _2 = SizeOf(std::string::String); -// _3 = Eq(move _2, const 0usize); -// switchInt(move _3) -> [false: bb14, otherwise: bb8]; +// _3 = Len((*_1)); +// switchInt(move _2) -> [0usize: bb8, otherwise: bb14]; // } // END rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir From e0cef5cf406016d5c1685a164a27571d182fa873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 2 May 2019 15:53:09 -0700 Subject: [PATCH 07/19] fix typo --- src/librustc_typeck/check/mod.rs | 2 +- src/libsyntax/parse/parser.rs | 8 ++++---- src/test/ui/error-codes/E0423.stderr | 4 ++-- src/test/ui/parser/expr-as-stmt.stderr | 12 ++++++------ .../ui/parser/match-arrows-block-then-binop.stderr | 2 +- src/test/ui/parser/struct-literal-in-for.stderr | 2 +- src/test/ui/parser/struct-literal-in-if.stderr | 2 +- .../struct-literal-in-match-discriminant.stderr | 2 +- src/test/ui/parser/struct-literal-in-while.stderr | 2 +- .../struct-literal-restrictions-in-lamda.stderr | 2 +- src/test/ui/struct-literal-variant-in-if.stderr | 8 ++++---- 11 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 61270716dfc..a0050b13596 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4182,7 +4182,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { { err.span_suggestion( *sp, - "parenthesis are required to parse this \ + "parentheses are required to parse this \ as an expression", format!("({})", snippet), Applicability::MachineApplicable, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fbd1203dec9..02e6c5e1c8d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2934,7 +2934,7 @@ impl<'a> Parser<'a> { if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { err.span_suggestion( *sp, - "parenthesis are required to parse this as an expression", + "parentheses are required to parse this as an expression", format!("({})", snippet), Applicability::MachineApplicable, ); @@ -2979,7 +2979,7 @@ impl<'a> Parser<'a> { "struct literals are not allowed here", ); err.multipart_suggestion( - "surround the struct literal with parenthesis", + "surround the struct literal with parentheses", vec![ (lo.shrink_to_lo(), "(".to_string()), (expr.span.shrink_to_hi(), ")".to_string()), @@ -3661,7 +3661,7 @@ impl<'a> Parser<'a> { .unwrap_or_else(|_| pprust::expr_to_string(&lhs)); err.span_suggestion( lhs.span, - "parenthesis are required to parse this as an expression", + "parentheses are required to parse this as an expression", format!("({})", snippet), Applicability::MachineApplicable, ); @@ -4982,7 +4982,7 @@ impl<'a> Parser<'a> { if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { err.span_suggestion( *sp, - "parenthesis are required to parse this as an expression", + "parentheses are required to parse this as an expression", format!("({})", snippet), Applicability::MachineApplicable, ); diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr index 5cb7121a0d1..ec240003f91 100644 --- a/src/test/ui/error-codes/E0423.stderr +++ b/src/test/ui/error-codes/E0423.stderr @@ -3,7 +3,7 @@ error: struct literals are not allowed here | LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); } | ^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if let S { x: _x, y: 2 } = (S { x: 1, y: 2 }) { println!("Ok"); } | ^ ^ @@ -19,7 +19,7 @@ error: struct literals are not allowed here | LL | for _ in std::ops::Range { start: 0, end: 10 } {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | for _ in (std::ops::Range { start: 0, end: 10 }) {} | ^ ^ diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index 1725ba944c5..a11209998a7 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -4,7 +4,7 @@ error: expected expression, found `+` LL | {2} + {2} | --- ^ expected expression | | - | help: parenthesis are required to parse this as an expression: `({2})` + | help: parentheses are required to parse this as an expression: `({2})` error: expected expression, found `+` --> $DIR/expr-as-stmt.rs:12:9 @@ -12,7 +12,7 @@ error: expected expression, found `+` LL | {2} + 2 | --- ^ expected expression | | - | help: parenthesis are required to parse this as an expression: `({2})` + | help: parentheses are required to parse this as an expression: `({2})` error: expected expression, found `+` --> $DIR/expr-as-stmt.rs:18:12 @@ -20,13 +20,13 @@ error: expected expression, found `+` LL | { 42 } + foo; | ------ ^ expected expression | | - | help: parenthesis are required to parse this as an expression: `({ 42 })` + | help: parentheses are required to parse this as an expression: `({ 42 })` error: expected expression, found `&&` --> $DIR/expr-as-stmt.rs:30:5 | LL | if let Some(x) = a { true } else { false } - | ------------------------------------------ help: parenthesis are required to parse this as an expression: `(if let Some(x) = a { true } else { false })` + | ------------------------------------------ help: parentheses are required to parse this as an expression: `(if let Some(x) = a { true } else { false })` LL | && | ^^ expected expression @@ -35,7 +35,7 @@ error: expected expression, found `>` | LL | } > 0 | ^ expected expression -help: parenthesis are required to parse this as an expression +help: parentheses are required to parse this as an expression | LL | (match x { LL | _ => 1, @@ -84,7 +84,7 @@ error[E0614]: type `{integer}` cannot be dereferenced LL | { 3 } * 3 | ----- ^^^ | | - | help: parenthesis are required to parse this as an expression: `({ 3 })` + | help: parentheses are required to parse this as an expression: `({ 3 })` error: aborting due to 10 previous errors diff --git a/src/test/ui/parser/match-arrows-block-then-binop.stderr b/src/test/ui/parser/match-arrows-block-then-binop.stderr index 0d7f81645b4..bb7df30783a 100644 --- a/src/test/ui/parser/match-arrows-block-then-binop.stderr +++ b/src/test/ui/parser/match-arrows-block-then-binop.stderr @@ -3,7 +3,7 @@ error: expected pattern, found `+` | LL | } + 5 | ^ expected pattern -help: parenthesis are required to parse this as an expression +help: parentheses are required to parse this as an expression | LL | 0 => ({ LL | 0 diff --git a/src/test/ui/parser/struct-literal-in-for.stderr b/src/test/ui/parser/struct-literal-in-for.stderr index 3c3f6e7f032..29af72a5d23 100644 --- a/src/test/ui/parser/struct-literal-in-for.stderr +++ b/src/test/ui/parser/struct-literal-in-for.stderr @@ -6,7 +6,7 @@ LL | for x in Foo { LL | | x: 3 LL | | }.hi() { | |_____^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | for x in (Foo { LL | x: 3 diff --git a/src/test/ui/parser/struct-literal-in-if.stderr b/src/test/ui/parser/struct-literal-in-if.stderr index 851c495abb4..e76c1cb45dd 100644 --- a/src/test/ui/parser/struct-literal-in-if.stderr +++ b/src/test/ui/parser/struct-literal-in-if.stderr @@ -6,7 +6,7 @@ LL | if Foo { LL | | x: 3 LL | | }.hi() { | |_____^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if (Foo { LL | x: 3 diff --git a/src/test/ui/parser/struct-literal-in-match-discriminant.stderr b/src/test/ui/parser/struct-literal-in-match-discriminant.stderr index 0058e8981cd..95b0882b7ae 100644 --- a/src/test/ui/parser/struct-literal-in-match-discriminant.stderr +++ b/src/test/ui/parser/struct-literal-in-match-discriminant.stderr @@ -6,7 +6,7 @@ LL | match Foo { LL | | x: 3 LL | | } { | |_____^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | match (Foo { LL | x: 3 diff --git a/src/test/ui/parser/struct-literal-in-while.stderr b/src/test/ui/parser/struct-literal-in-while.stderr index 9959a57be85..acd31b477dc 100644 --- a/src/test/ui/parser/struct-literal-in-while.stderr +++ b/src/test/ui/parser/struct-literal-in-while.stderr @@ -6,7 +6,7 @@ LL | while Foo { LL | | x: 3 LL | | }.hi() { | |_____^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | while (Foo { LL | x: 3 diff --git a/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr index 81f7a91ddb3..24078074161 100644 --- a/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr +++ b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr @@ -6,7 +6,7 @@ LL | while || Foo { LL | | x: 3 LL | | }.hi() { | |_____^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | while || (Foo { LL | x: 3 diff --git a/src/test/ui/struct-literal-variant-in-if.stderr b/src/test/ui/struct-literal-variant-in-if.stderr index 55f23baea7a..f91b9d7dce6 100644 --- a/src/test/ui/struct-literal-variant-in-if.stderr +++ b/src/test/ui/struct-literal-variant-in-if.stderr @@ -3,7 +3,7 @@ error: struct literals are not allowed here | LL | if x == E::I { field1: true, field2: 42 } {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if x == (E::I { field1: true, field2: 42 }) {} | ^ ^ @@ -13,7 +13,7 @@ error: struct literals are not allowed here | LL | if x == E::V { field: false } {} | ^^^^^^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if x == (E::V { field: false }) {} | ^ ^ @@ -23,7 +23,7 @@ error: struct literals are not allowed here | LL | if x == E::J { field: -42 } {} | ^^^^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if x == (E::J { field: -42 }) {} | ^ ^ @@ -33,7 +33,7 @@ error: struct literals are not allowed here | LL | if x == E::K { field: "" } {} | ^^^^^^^^^^^^^^^^^^ -help: surround the struct literal with parenthesis +help: surround the struct literal with parentheses | LL | if x == (E::K { field: "" }) {} | ^ ^ From f6a4b5270a0007e950546828a7f6fc7c54354b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 2 May 2019 16:13:28 -0700 Subject: [PATCH 08/19] Deduplicate needed parentheses suggestion code --- src/librustc_typeck/check/mod.rs | 16 +++++----------- src/libsyntax/parse/mod.rs | 23 ++++++++++++++++++++++- src/libsyntax/parse/parser.rs | 29 ++++++----------------------- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a0050b13596..763d6b898a4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4177,17 +4177,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(sp) = tcx.sess.parse_sess.abiguous_block_expr_parse .borrow().get(&sp) { - if let Ok(snippet) = tcx.sess.source_map() - .span_to_snippet(*sp) - { - err.span_suggestion( - *sp, - "parentheses are required to parse this \ - as an expression", - format!("({})", snippet), - Applicability::MachineApplicable, - ); - } + tcx.sess.parse_sess.expr_parentheses_needed( + &mut err, + *sp, + None, + ); } err.emit(); oprnd_t = tcx.types.err; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 94bbd5ba2f7..0d41a1ff849 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -11,7 +11,7 @@ use crate::tokenstream::{TokenStream, TokenTree}; use crate::diagnostics::plugin::ErrorMap; use crate::print::pprust::token_to_string; -use errors::{FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; +use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; use rustc_data_structures::sync::{Lrc, Lock}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; use log::debug; @@ -47,6 +47,9 @@ pub struct ParseSess { included_mod_stack: Lock>, source_map: Lrc, pub buffered_lints: Lock>, + /// Contains the spans of block expressions that could have been incomplete based on the + /// operation token that followed it, but that the parser cannot identify without further + /// analysis. pub abiguous_block_expr_parse: Lock>, } @@ -95,6 +98,24 @@ impl ParseSess { }); }); } + + /// Extend an error with a suggestion to wrap an expression with parentheses to allow the + /// parser to continue parsing the following operation as part of the same expression. + pub fn expr_parentheses_needed( + &self, + err: &mut DiagnosticBuilder<'_>, + span: Span, + alt_snippet: Option, + ) { + if let Some(snippet) = self.source_map().span_to_snippet(span).ok().or(alt_snippet) { + err.span_suggestion( + span, + "parentheses are required to parse this as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + } + } } #[derive(Clone)] diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 02e6c5e1c8d..66d45f799d9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2931,14 +2931,7 @@ impl<'a> Parser<'a> { if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow() .get(&sp) { - if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { - err.span_suggestion( - *sp, - "parentheses are required to parse this as an expression", - format!("({})", snippet), - Applicability::MachineApplicable, - ); - } + self.sess.expr_parentheses_needed(&mut err, *sp, None); } err.span_label(self.span, "expected expression"); return Err(err); @@ -3657,14 +3650,11 @@ impl<'a> Parser<'a> { pprust::token_to_string(&self.token), )); err.span_label(self.span, "expected expression"); - let snippet = self.sess.source_map().span_to_snippet(lhs.span) - .unwrap_or_else(|_| pprust::expr_to_string(&lhs)); - err.span_suggestion( + self.sess.expr_parentheses_needed( + &mut err, lhs.span, - "parentheses are required to parse this as an expression", - format!("({})", snippet), - Applicability::MachineApplicable, - ); + Some(pprust::expr_to_string(&lhs), + )); err.emit(); } } @@ -4979,14 +4969,7 @@ impl<'a> Parser<'a> { err.span_label(self.span, format!("expected {}", expected)); let sp = self.sess.source_map().start_point(self.span); if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow().get(&sp) { - if let Ok(snippet) = self.sess.source_map().span_to_snippet(*sp) { - err.span_suggestion( - *sp, - "parentheses are required to parse this as an expression", - format!("({})", snippet), - Applicability::MachineApplicable, - ); - } + self.sess.expr_parentheses_needed(&mut err, *sp, None); } return Err(err); } From 6d26c5f73ca1c6d1615c141b181374e152cab61a Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 6 May 2019 13:42:15 -0500 Subject: [PATCH 09/19] rustfmt --- src/libsyntax/ext/tt/transcribe.rs | 100 ++++++++++++++--------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index bd2adb5ac13..5eb5475b2a9 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -1,10 +1,10 @@ use crate::ast::Ident; use crate::ext::base::ExtCtxt; use crate::ext::expand::Marker; -use crate::ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; +use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; use crate::ext::tt::quoted; use crate::mut_visit::noop_visit_tt; -use crate::parse::token::{self, Token, NtTT}; +use crate::parse::token::{self, NtTT, Token}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; use smallvec::{smallvec, SmallVec}; @@ -16,18 +16,10 @@ use std::mem; use std::ops::Add; use std::rc::Rc; -// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). +/// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). enum Frame { - Delimited { - forest: Lrc, - idx: usize, - span: DelimSpan, - }, - Sequence { - forest: Lrc, - idx: usize, - sep: Option, - }, + Delimited { forest: Lrc, idx: usize, span: DelimSpan }, + Sequence { forest: Lrc, idx: usize, sep: Option }, } impl Frame { @@ -54,13 +46,13 @@ impl Iterator for Frame { } } -/// This can do Macro-By-Example transcription. On the other hand, if -/// `src` contains no `TokenTree::{Sequence, MetaVar, MetaVarDecl}`s, `interp` can -/// (and should) be None. -pub fn transcribe(cx: &ExtCtxt<'_>, - interp: Option>>, - src: Vec) - -> TokenStream { +/// This can do Macro-By-Example transcription. On the other hand, if `src` contains no +/// `TokenTree::{Sequence, MetaVar, MetaVarDecl}`s, `interp` can (and should) be `None`. +pub fn transcribe( + cx: &ExtCtxt<'_>, + interp: Option>>, + src: Vec, +) -> TokenStream { let mut stack: SmallVec<[Frame; 1]> = smallvec![Frame::new(src)]; let interpolations = interp.unwrap_or_else(FxHashMap::default); /* just a convenience */ let mut repeats = Vec::new(); @@ -84,7 +76,7 @@ pub fn transcribe(cx: &ExtCtxt<'_>, }; result.push(TokenTree::Token(prev_span, sep).into()); } - continue + continue; } } @@ -96,29 +88,30 @@ pub fn transcribe(cx: &ExtCtxt<'_>, if result_stack.is_empty() { return TokenStream::new(result); } - let tree = TokenTree::Delimited( - span, - forest.delim, - TokenStream::new(result).into(), - ); + let tree = + TokenTree::Delimited(span, forest.delim, TokenStream::new(result).into()); result = result_stack.pop().unwrap(); result.push(tree.into()); } } - continue + continue; }; match tree { quoted::TokenTree::Sequence(sp, seq) => { // FIXME(pcwalton): Bad copy. - match lockstep_iter_size("ed::TokenTree::Sequence(sp, seq.clone()), - &interpolations, - &repeats) { + match lockstep_iter_size( + "ed::TokenTree::Sequence(sp, seq.clone()), + &interpolations, + &repeats, + ) { LockstepIterSize::Unconstrained => { - cx.span_fatal(sp.entire(), /* blame macro writer */ + cx.span_fatal( + sp.entire(), /* blame macro writer */ "attempted to repeat an expression \ containing no syntax \ - variables matched as repeating at this depth"); + variables matched as repeating at this depth", + ); } LockstepIterSize::Contradiction(ref msg) => { // FIXME #2887 blame macro invoker instead @@ -153,8 +146,10 @@ pub fn transcribe(cx: &ExtCtxt<'_>, result.push(token.into()); } } else { - cx.span_fatal(sp, /* blame the macro writer */ - &format!("variable '{}' is still repeating at this depth", ident)); + cx.span_fatal( + sp, /* blame the macro writer */ + &format!("variable '{}' is still repeating at this depth", ident), + ); } } else { let ident = @@ -180,10 +175,11 @@ pub fn transcribe(cx: &ExtCtxt<'_>, } } -fn lookup_cur_matched(ident: Ident, - interpolations: &FxHashMap>, - repeats: &[(usize, usize)]) - -> Option> { +fn lookup_cur_matched( + ident: Ident, + interpolations: &FxHashMap>, + repeats: &[(usize, usize)], +) -> Option> { interpolations.get(&ident).map(|matched| { let mut matched = matched.clone(); for &(idx, _) in repeats { @@ -217,9 +213,11 @@ impl Add for LockstepIterSize { LockstepIterSize::Contradiction(_) => other, LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self, LockstepIterSize::Constraint(r_len, r_id) => { - let msg = format!("inconsistent lockstep iteration: \ - '{}' has {} items, but '{}' has {}", - l_id, l_len, r_id, r_len); + let msg = format!( + "inconsistent lockstep iteration: \ + '{}' has {} items, but '{}' has {}", + l_id, l_len, r_id, r_len + ); LockstepIterSize::Contradiction(msg) } }, @@ -227,30 +225,32 @@ impl Add for LockstepIterSize { } } -fn lockstep_iter_size(tree: "ed::TokenTree, - interpolations: &FxHashMap>, - repeats: &[(usize, usize)]) - -> LockstepIterSize { +fn lockstep_iter_size( + tree: "ed::TokenTree, + interpolations: &FxHashMap>, + repeats: &[(usize, usize)], +) -> LockstepIterSize { use quoted::TokenTree; match *tree { TokenTree::Delimited(_, ref delimed) => { delimed.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { size + lockstep_iter_size(tt, interpolations, repeats) }) - }, + } TokenTree::Sequence(_, ref seq) => { seq.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { size + lockstep_iter_size(tt, interpolations, repeats) }) - }, - TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => + } + TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => { match lookup_cur_matched(name, interpolations, repeats) { Some(matched) => match *matched { MatchedNonterminal(_) => LockstepIterSize::Unconstrained, MatchedSeq(ref ads, _) => LockstepIterSize::Constraint(ads.len(), name), }, - _ => LockstepIterSize::Unconstrained - }, + _ => LockstepIterSize::Unconstrained, + } + } TokenTree::Token(..) => LockstepIterSize::Unconstrained, } } From 54430ad53ab00bf86090a8d11844db1c40b2ca24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 6 May 2019 16:00:21 -0700 Subject: [PATCH 10/19] review comments: fix typo and add comments --- src/librustc_typeck/check/mod.rs | 2 +- src/libsyntax/parse/lexer/mod.rs | 2 +- src/libsyntax/parse/mod.rs | 4 ++-- src/libsyntax/parse/parser.rs | 11 +++++++---- src/libsyntax/util/parser.rs | 5 ++++- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 763d6b898a4..cc73e1753d4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4174,7 +4174,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { oprnd_t, ); let sp = tcx.sess.source_map().start_point(expr.span); - if let Some(sp) = tcx.sess.parse_sess.abiguous_block_expr_parse + if let Some(sp) = tcx.sess.parse_sess.ambiguous_block_expr_parse .borrow().get(&sp) { tcx.sess.parse_sess.expr_parentheses_needed( diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index e7d79a647d3..4e5a51bdd9a 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1918,7 +1918,7 @@ mod tests { raw_identifier_spans: Lock::new(Vec::new()), registered_diagnostics: Lock::new(ErrorMap::new()), buffered_lints: Lock::new(vec![]), - abiguous_block_expr_parse: Lock::new(FxHashMap::default()), + ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 0d41a1ff849..0ad60369422 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -50,7 +50,7 @@ pub struct ParseSess { /// Contains the spans of block expressions that could have been incomplete based on the /// operation token that followed it, but that the parser cannot identify without further /// analysis. - pub abiguous_block_expr_parse: Lock>, + pub ambiguous_block_expr_parse: Lock>, } impl ParseSess { @@ -74,7 +74,7 @@ impl ParseSess { included_mod_stack: Lock::new(vec![]), source_map, buffered_lints: Lock::new(vec![]), - abiguous_block_expr_parse: Lock::new(FxHashMap::default()), + ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 66d45f799d9..460d829fc06 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2928,7 +2928,7 @@ impl<'a> Parser<'a> { self.this_token_descr()); let mut err = self.fatal(&msg); let sp = self.sess.source_map().start_point(self.span); - if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow() + if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow() .get(&sp) { self.sess.expr_parentheses_needed(&mut err, *sp, None); @@ -3630,12 +3630,15 @@ impl<'a> Parser<'a> { return Ok(lhs); } (false, _) => {} // continue parsing the expression - (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` + // An exhaustive check is done in the following block, but these are checked first + // because they *are* ambiguous but also reasonable looking incorrect syntax, so we + // want to keep their span info to improve diagnostics in these cases in a later stage. + (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3` (true, Some(AssocOp::Subtract)) | // `{ 42 } -5` (true, Some(AssocOp::Add)) => { // `{ 42 } + 42 // These cases are ambiguous and can't be identified in the parser alone let sp = self.sess.source_map().start_point(self.span); - self.sess.abiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); + self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); return Ok(lhs); } (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => { @@ -4968,7 +4971,7 @@ impl<'a> Parser<'a> { let mut err = self.fatal(&msg); err.span_label(self.span, format!("expected {}", expected)); let sp = self.sess.source_map().start_point(self.span); - if let Some(sp) = self.sess.abiguous_block_expr_parse.borrow().get(&sp) { + if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { self.sess.expr_parentheses_needed(&mut err, *sp, None); } return Err(err); diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index d76dede8155..828fbaef985 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -208,6 +208,10 @@ impl AssocOp { } } + /// This operator could be used to follow a block unambiguously. + /// + /// This is used for error recovery at the moment, providing a suggestion to wrap blocks with + /// parentheses while having a high degree of confidence on the correctness of the suggestion. pub fn can_continue_expr_unambiguously(&self) -> bool { use AssocOp::*; match self { @@ -227,7 +231,6 @@ impl AssocOp { Colon => true, // `{ 42 }: usize` _ => false, } - } } From 606bb6f6fe4cfb6e3054e90cc400553f280ad94a Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 6 May 2019 16:31:59 -0500 Subject: [PATCH 11/19] avoid extra copy --- src/libsyntax/ext/tt/transcribe.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 5eb5475b2a9..424b94173a7 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -98,16 +98,11 @@ pub fn transcribe( }; match tree { - quoted::TokenTree::Sequence(sp, seq) => { - // FIXME(pcwalton): Bad copy. - match lockstep_iter_size( - "ed::TokenTree::Sequence(sp, seq.clone()), - &interpolations, - &repeats, - ) { + seq @ quoted::TokenTree::Sequence(..) => { + match lockstep_iter_size(&seq, interp, &repeats) { LockstepIterSize::Unconstrained => { cx.span_fatal( - sp.entire(), /* blame macro writer */ + seq.span(), /* blame macro writer */ "attempted to repeat an expression \ containing no syntax \ variables matched as repeating at this depth", @@ -115,9 +110,15 @@ pub fn transcribe( } LockstepIterSize::Contradiction(ref msg) => { // FIXME #2887 blame macro invoker instead - cx.span_fatal(sp.entire(), &msg[..]); + cx.span_fatal(seq.span(), &msg[..]); } LockstepIterSize::Constraint(len, _) => { + let (sp, seq) = if let quoted::TokenTree::Sequence(sp, seq) = seq { + (sp, seq) + } else { + unreachable!() + }; + if len == 0 { if seq.op == quoted::KleeneOp::OneOrMore { // FIXME #2887 blame invoker @@ -201,10 +202,8 @@ enum LockstepIterSize { Contradiction(String), } -impl Add for LockstepIterSize { - type Output = LockstepIterSize; - - fn add(self, other: LockstepIterSize) -> LockstepIterSize { +impl LockstepIterSize { + fn with(self, other: LockstepIterSize) -> LockstepIterSize { match self { LockstepIterSize::Unconstrained => other, LockstepIterSize::Contradiction(_) => self, From 5db665b972f7c9578fe0fd2bdb9c7aef6f6db3db Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 6 May 2019 16:16:23 -0500 Subject: [PATCH 12/19] lots of comments + minor cleanup --- src/libsyntax/ext/tt/macro_parser.rs | 5 +- src/libsyntax/ext/tt/macro_rules.rs | 2 +- src/libsyntax/ext/tt/quoted.rs | 1 + src/libsyntax/ext/tt/transcribe.rs | 147 ++++++++++++++++++++++++--- 4 files changed, 139 insertions(+), 16 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index ab5823eaca5..084a69f4cda 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -554,7 +554,10 @@ fn inner_parse_loop<'root, 'tt>( match item.top_elts.get_tt(idx) { // Need to descend into a sequence TokenTree::Sequence(sp, seq) => { - // Examine the case where there are 0 matches of this sequence + // Examine the case where there are 0 matches of this sequence. We are + // implicitly disallowing OneOrMore from having 0 matches here. Thus, that will + // result in a "no rules expected token" error by virtue of this matcher not + // working. if seq.op == quoted::KleeneOp::ZeroOrMore || seq.op == quoted::KleeneOp::ZeroOrOne { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index b1b9d25b3d5..a53cc2fe661 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -151,7 +151,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt<'_>, let rhs_spans = rhs.iter().map(|t| t.span()).collect::>(); // rhs has holes ( `$id` and `$(...)` that need filled) - let mut tts = transcribe(cx, Some(named_matches), rhs); + let mut tts = transcribe(cx, &named_matches, rhs); // Replace all the tokens for the corresponding positions in the macro, to maintain // proper positions in error reporting, while maintaining the macro_backtrace. diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index b24edb57e52..ed8395f11ad 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -73,6 +73,7 @@ pub enum KleeneOp { ZeroOrMore, /// Kleene plus (`+`) for one or more repetitions OneOrMore, + /// Kleene optional (`?`) for zero or one reptitions ZeroOrOne, } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 424b94173a7..3a40e8403cc 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -13,7 +13,6 @@ use syntax_pos::DUMMY_SP; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use std::mem; -use std::ops::Add; use std::rc::Rc; /// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). @@ -23,6 +22,7 @@ enum Frame { } impl Frame { + /// Construct a new frame around the delimited set of tokens. fn new(tts: Vec) -> Frame { let forest = Lrc::new(quoted::Delimited { delim: token::NoDelim, tts: tts }); Frame::Delimited { forest: forest, idx: 0, span: DelimSpan::dummy() } @@ -46,30 +46,72 @@ impl Iterator for Frame { } } -/// This can do Macro-By-Example transcription. On the other hand, if `src` contains no -/// `TokenTree::{Sequence, MetaVar, MetaVarDecl}`s, `interp` can (and should) be `None`. +/// This can do Macro-By-Example transcription. +/// - `interp` is a map of meta-variables to the tokens (non-terminals) they matched in the +/// invocation. We are assuming we already know there is a match. +/// - `src` is the RHS of the MBE, that is, the "example" we are filling in. +/// +/// For example, +/// +/// ```rust +/// macro_rules! foo { +/// ($id:ident) => { println!("{}", stringify!($id)); } +/// } +/// +/// foo!(bar); +/// ``` +/// +/// `interp` would contain `$id => bar` and `src` would contain `println!("{}", stringify!($id));`. +/// +/// `transcribe` would return a `TokenStream` containing `println!("{}", stringify!(bar));`. +/// +/// Along the way, we do some additional error checking. pub fn transcribe( cx: &ExtCtxt<'_>, - interp: Option>>, + interp: &FxHashMap>, src: Vec, ) -> TokenStream { + assert!(src.len() > 0); + + // We descend into the RHS (`src`), expanding things as we go. This stack contains the things + // we have yet to expand/are still expanding. We start the stack off with the whole RHS. let mut stack: SmallVec<[Frame; 1]> = smallvec![Frame::new(src)]; - let interpolations = interp.unwrap_or_else(FxHashMap::default); /* just a convenience */ + + // As we descend in the RHS, we will need to be able to match nested sequences of matchers. + // `repeats` keeps track of where we are in matching at each level, with the last element being + // the most deeply nested sequence. This is used as a stack. let mut repeats = Vec::new(); + + // `result` contains resulting token stream from the TokenTree we just finished processing. At + // the end, this will contain the full result of transcription, but at arbitrary points during + // `transcribe`, `result` will contain subsets of the final result. + // + // Specifically, as we descend into each TokenTree, we will push the existing results onto the + // `result_stack` and clear `results`. We will then produce the results of transcribing the + // TokenTree into `results`. Then, as we unwind back out of the `TokenTree`, we will pop the + // `result_stack` and append `results` too it to produce the new `results` up to that point. + // + // Thus, if we try to pop the `result_stack` and it is empty, we have reached the top-level + // again, and we are done transcribing. let mut result: Vec = Vec::new(); let mut result_stack = Vec::new(); loop { + // Look at the last frame on the stack. let tree = if let Some(tree) = stack.last_mut().unwrap().next() { + // If it still has a TokenTree we have not looked at yet, use that tree. tree - } else { + } + // The else-case never produces a value for `tree` (it `continue`s or `return`s). + else { + // Otherwise, if we have just reached the end of a sequence and we can keep repeating, + // go back to the beginning of the sequence. if let Frame::Sequence { ref mut idx, ref sep, .. } = *stack.last_mut().unwrap() { let (ref mut repeat_idx, repeat_len) = *repeats.last_mut().unwrap(); *repeat_idx += 1; if *repeat_idx < repeat_len { *idx = 0; if let Some(sep) = sep.clone() { - // repeat same span, I guess let prev_span = match result.last() { Some((tt, _)) => tt.span(), None => DUMMY_SP, @@ -80,14 +122,25 @@ pub fn transcribe( } } + // We are done with the top of the stack. Pop it. Depending on what it was, we do + // different things. Note that the outermost item must be the delimited, wrapped RHS + // that was passed in originally to `transcribe`. match stack.pop().unwrap() { + // Done with a sequence. Pop from repeats. Frame::Sequence { .. } => { repeats.pop(); } + + // We are done processing a Delimited. If this is the top-level delimited, we are + // done. Otherwise, we unwind the result_stack to append what we have produced to + // any previous results. Frame::Delimited { forest, span, .. } => { if result_stack.is_empty() { + // No results left to compute! We are back at the top-level. return TokenStream::new(result); } + + // Step back into the parent Delimited. let tree = TokenTree::Delimited(span, forest.delim, TokenStream::new(result).into()); result = result_stack.pop().unwrap(); @@ -97,35 +150,54 @@ pub fn transcribe( continue; }; + // At this point, we know we are in the middle of a TokenTree (the last one on `stack`). + // `tree` contains the next `TokenTree` to be processed. match tree { + // We are descending into a sequence. We first make sure that the matchers in the RHS + // and the matches in `interp` have the same shape. Otherwise, either the caller or the + // macro writer has made a mistake. seq @ quoted::TokenTree::Sequence(..) => { match lockstep_iter_size(&seq, interp, &repeats) { LockstepIterSize::Unconstrained => { cx.span_fatal( seq.span(), /* blame macro writer */ - "attempted to repeat an expression \ - containing no syntax \ - variables matched as repeating at this depth", + "attempted to repeat an expression containing no syntax variables \ + matched as repeating at this depth", ); } + LockstepIterSize::Contradiction(ref msg) => { + // FIXME: this should be impossible. I (mark-i-m) believe it would + // represent a bug in the macro_parser. // FIXME #2887 blame macro invoker instead cx.span_fatal(seq.span(), &msg[..]); } + LockstepIterSize::Constraint(len, _) => { + // We do this to avoid an extra clone above. We know that this is a + // sequence already. let (sp, seq) = if let quoted::TokenTree::Sequence(sp, seq) = seq { (sp, seq) } else { unreachable!() }; + // Is the repetition empty? if len == 0 { if seq.op == quoted::KleeneOp::OneOrMore { + // FIXME: this should be impossible because we check for this in + // macro_parser.rs // FIXME #2887 blame invoker cx.span_fatal(sp.entire(), "this must repeat at least once"); } } else { + // 0 is the initial counter (we have done 0 repretitions so far). `len` + // is the total number of reptitions we should generate. repeats.push((0, len)); + + // The first time we encounter the sequence we push it to the stack. It + // then gets reused (see the beginning of the loop) until we are done + // repeating. stack.push(Frame::Sequence { idx: 0, sep: seq.separator.clone(), @@ -135,10 +207,16 @@ pub fn transcribe( } } } - // FIXME #2887: think about span stuff here + + // Replace the meta-var with the matched token tree from the invocation. quoted::TokenTree::MetaVar(mut sp, ident) => { - if let Some(cur_matched) = lookup_cur_matched(ident, &interpolations, &repeats) { + // Find the matched nonterminal from the macro invocation, and use it to replace + // the meta-var. + if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { if let MatchedNonterminal(ref nt) = *cur_matched { + // FIXME #2887: why do we apply a mark when matching a token tree meta-var + // (e.g. `$x:tt`), but not when we are matching any other type of token + // tree? if let NtTT(ref tt) = **nt { result.push(tt.clone().into()); } else { @@ -147,12 +225,15 @@ pub fn transcribe( result.push(token.into()); } } else { + // We were unable to descend far enough. This is an error. cx.span_fatal( sp, /* blame the macro writer */ &format!("variable '{}' is still repeating at this depth", ident), ); } } else { + // If we aren't able to match the meta-var, we push it back into the result but + // with modified syntax context. (I believe this supports nested macros). let ident = Ident::new(ident.name, ident.span.apply_mark(cx.current_expansion.mark)); sp = sp.apply_mark(cx.current_expansion.mark); @@ -160,22 +241,39 @@ pub fn transcribe( result.push(TokenTree::Token(sp, token::Token::from_ast_ident(ident)).into()); } } + + // If we are entering a new delimiter, we push its contents to the `stack` to be + // processed, and we push all of the currently produced results to the `result_stack`. + // We will produce all of the results of the inside of the `Delimited` and then we will + // jump back out of the Delimited, pop the result_stack and add the new results back to + // the previous results (from outside the Delimited). quoted::TokenTree::Delimited(mut span, delimited) => { span = span.apply_mark(cx.current_expansion.mark); stack.push(Frame::Delimited { forest: delimited, idx: 0, span: span }); result_stack.push(mem::replace(&mut result, Vec::new())); } + + // Nothing much to do here. Just push the token to the result, being careful to + // preserve syntax context. quoted::TokenTree::Token(sp, tok) => { let mut marker = Marker(cx.current_expansion.mark); let mut tt = TokenTree::Token(sp, tok); noop_visit_tt(&mut tt, &mut marker); result.push(tt.into()); } + + // There should be no meta-var declarations in the invocation of a macro. quoted::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl"), } } } +/// Lookup the meta-var named `ident` and return the matched token tree from the invocation using +/// the set of matches `interpolations`. +/// +/// See the definition of `repeats` in the `transcribe` function. `repeats` is used to descend +/// into the right place in nested matchers. If we attempt to descend too far, the macro writer has +/// made a mistake, and we return `None`. fn lookup_cur_matched( ident: Ident, interpolations: &FxHashMap>, @@ -195,14 +293,29 @@ fn lookup_cur_matched( }) } +/// An accumulator over a TokenTree to be used with `fold`. During transcription, we need to make +/// sure that the size of each sequence and all of its nested sequences are the same as the sizes +/// of all the matched (nested) sequences in the macro invocation. If they don't match, somebody +/// has made a mistake (either the macro writer or caller). #[derive(Clone)] enum LockstepIterSize { + /// No constraints on length of matcher. This is true for any TokenTree variants except a + /// `MetaVar` with an actual `MatchedSeq` (as opposed to a `MatchedNonterminal`). Unconstrained, + + /// A `MetaVar` with an actual `MatchedSeq`. The length of the match and the name of the + /// meta-var are returned. Constraint(usize, Ident), + + /// Two `Constraint`s on the same sequence had different lengths. This is an error. Contradiction(String), } impl LockstepIterSize { + /// Find incompatibilities in matcher/invocation sizes. + /// - `Unconstrained` is compatible with everything. + /// - `Contradiction` is incompatible with everything. + /// - `Constraint(len)` is only compatible with other constraints of the same length. fn with(self, other: LockstepIterSize) -> LockstepIterSize { match self { LockstepIterSize::Unconstrained => other, @@ -224,6 +337,12 @@ impl LockstepIterSize { } } +/// Given a `tree`, make sure that all sequences have the same length as the matches for the +/// appropriate meta-vars in `interpolations`. +/// +/// Note that if `repeats` does not match the exact correct depth of a meta-var, +/// `lookup_cur_matched` will return `None`, which is why this still works even in the presnece of +/// multiple nested matcher sequences. fn lockstep_iter_size( tree: "ed::TokenTree, interpolations: &FxHashMap>, @@ -233,12 +352,12 @@ fn lockstep_iter_size( match *tree { TokenTree::Delimited(_, ref delimed) => { delimed.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { - size + lockstep_iter_size(tt, interpolations, repeats) + size.with(lockstep_iter_size(tt, interpolations, repeats)) }) } TokenTree::Sequence(_, ref seq) => { seq.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { - size + lockstep_iter_size(tt, interpolations, repeats) + size.with(lockstep_iter_size(tt, interpolations, repeats)) }) } TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => { From eb7d47cba90ac716c84fe720418e58c6eb84ac4e Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 8 May 2019 13:34:23 -0500 Subject: [PATCH 13/19] fix incorrect assert --- src/libsyntax/ext/tt/transcribe.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 3a40e8403cc..0cefcf1ce03 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -71,7 +71,10 @@ pub fn transcribe( interp: &FxHashMap>, src: Vec, ) -> TokenStream { - assert!(src.len() > 0); + // Nothing for us to transcribe... + if src.is_empty() { + return TokenStream::empty(); + } // We descend into the RHS (`src`), expanding things as we go. This stack contains the things // we have yet to expand/are still expanding. We start the stack off with the whole RHS. From d0ba8fe33f0eb426d01447b5159ce7e78afe7a74 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 9 May 2019 01:06:03 +0300 Subject: [PATCH 14/19] Skip codegen for one UI test with long file path --- .../region-lbr1-does-outlive-lbr2-because-implied-bound.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs index 66290f2ff23..5a008ad26b4 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs +++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs @@ -3,8 +3,7 @@ // compile-flags:-Zborrowck=mir -Zverbose // compile-pass - -#![allow(warnings)] +// skip-codegen fn foo<'a, 'b>(x: &'a &'b u32) -> &'a u32 { &**x From b2f71fb540faa4218de506c4d82bbcf237ea78d6 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Thu, 9 May 2019 12:03:13 -0400 Subject: [PATCH 15/19] remove unneeded `extern crate`s from build tools --- Cargo.lock | 76 +++++++++++++--------------- src/bootstrap/Cargo.toml | 5 +- src/bootstrap/builder.rs | 4 ++ src/bootstrap/cache.rs | 2 + src/bootstrap/clean.rs | 2 + src/bootstrap/compile.rs | 3 +- src/bootstrap/config.rs | 2 + src/bootstrap/dist.rs | 2 +- src/bootstrap/doc.rs | 2 +- src/bootstrap/install.rs | 2 + src/bootstrap/lib.rs | 15 ++---- src/bootstrap/metadata.rs | 1 + src/bootstrap/native.rs | 2 +- src/bootstrap/sanity.rs | 2 +- src/bootstrap/test.rs | 2 +- src/bootstrap/tool.rs | 2 + src/bootstrap/toolstate.rs | 2 + src/bootstrap/util.rs | 2 + src/tools/build-manifest/Cargo.toml | 1 - src/tools/compiletest/Cargo.toml | 3 +- src/tools/compiletest/src/errors.rs | 2 + src/tools/compiletest/src/header.rs | 2 + src/tools/compiletest/src/json.rs | 1 + src/tools/compiletest/src/main.rs | 9 +--- src/tools/compiletest/src/runtest.rs | 3 ++ src/tools/compiletest/src/util.rs | 2 + src/tools/tidy/Cargo.toml | 3 +- src/tools/tidy/src/deps.rs | 2 +- 28 files changed, 81 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff66b4a0372..a7c806ad481 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,7 +29,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "html5ever 0.22.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -170,13 +170,12 @@ dependencies = [ "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -192,7 +191,6 @@ name = "build-manifest" version = "0.1.0" dependencies = [ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -266,7 +264,7 @@ dependencies = [ "ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "im-rc 12.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -374,7 +372,7 @@ dependencies = [ "clippy_lints 0.0.212", "compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "rustc_tools_util 0.1.1", @@ -394,7 +392,7 @@ dependencies = [ "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -465,14 +463,13 @@ dependencies = [ "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -592,7 +589,7 @@ dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -606,7 +603,7 @@ dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -751,7 +748,7 @@ name = "elasticlunr-rs" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1032,7 +1029,7 @@ name = "handlebars" version = "0.32.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1047,7 +1044,7 @@ name = "handlebars" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1143,7 +1140,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1169,7 +1166,7 @@ dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1265,7 +1262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1354,7 +1351,7 @@ name = "log_settings" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1441,7 +1438,7 @@ dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1469,7 +1466,7 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1703,7 +1700,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1971,7 +1968,7 @@ dependencies = [ "bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2045,7 +2042,7 @@ dependencies = [ "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2141,7 +2138,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2243,7 +2240,7 @@ dependencies = [ "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-types 0.57.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2349,7 +2346,7 @@ dependencies = [ "fmt_macros 0.0.0", "graphviz 0.0.0", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "measureme 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2402,7 +2399,7 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-graphviz 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2532,7 +2529,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2543,7 +2540,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2702,7 +2699,7 @@ dependencies = [ "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3097,7 +3094,7 @@ dependencies = [ "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3143,7 +3140,7 @@ name = "schannel" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3313,7 +3310,7 @@ name = "string_cache" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3404,7 +3401,7 @@ name = "syntax" version = "0.0.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", @@ -3549,7 +3546,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3558,7 +3555,6 @@ version = "0.1.0" dependencies = [ "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3664,7 +3660,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3783,7 +3779,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3795,7 +3791,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4160,7 +4156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a5152c3fda235dfd68341b3edf4121bc4428642c93acbd6de88c26bf95fc5d7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" "checksum libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 3151b56d8e8..589ee9276a5 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -42,11 +42,10 @@ num_cpus = "1.0" getopts = "0.2.19" cc = "1.0.35" libc = "0.2" -serde = "1.0.8" -serde_derive = "1.0.8" +serde = { version = "1.0.8", features = ["derive"] } serde_json = "1.0.2" toml = "0.4" -lazy_static = "0.2" +lazy_static = "1.3.0" time = "0.1" petgraph = "0.4.13" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index c84eb6476e0..51663e93169 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -11,6 +11,8 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::{Duration, Instant}; +use build_helper::t; + use crate::cache::{Cache, Interned, INTERNER}; use crate::check; use crate::compile; @@ -1308,6 +1310,8 @@ mod __test { use crate::config::Config; use std::thread; + use pretty_assertions::assert_eq; + fn configure(host: &[&str], target: &[&str]) -> Config { let mut config = Config::default_opts(); // don't save toolstates diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 239959682cb..f137a7b8cc2 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -13,6 +13,8 @@ use std::path::{Path, PathBuf}; use std::sync::Mutex; use std::cmp::{PartialOrd, Ord, Ordering}; +use lazy_static::lazy_static; + use crate::builder::Step; pub struct Interned(usize, PhantomData<*const T>); diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index b52e1a7b0e6..73be8bfed8e 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -9,6 +9,8 @@ use std::fs; use std::io::{self, ErrorKind}; use std::path::Path; +use build_helper::t; + use crate::Build; pub fn clean(build: &Build, all: bool) { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 66443d472d3..9c4e856f0b8 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -15,8 +15,9 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio, exit}; use std::str; -use build_helper::{output, mtime, up_to_date}; +use build_helper::{output, mtime, t, up_to_date}; use filetime::FileTime; +use serde::Deserialize; use serde_json; use crate::dist; diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 0c31c41ceda..b1d009a6740 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -10,8 +10,10 @@ use std::path::{Path, PathBuf}; use std::process; use std::cmp; +use build_helper::t; use num_cpus; use toml; +use serde::Deserialize; use crate::cache::{INTERNER, Interned}; use crate::flags::Flags; pub use crate::flags::Subcommand; diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 57c06061c34..b0616ff6691 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -14,7 +14,7 @@ use std::io::Write; use std::path::{PathBuf, Path}; use std::process::{Command, Stdio}; -use build_helper::output; +use build_helper::{output, t}; use crate::{Compiler, Mode, LLVM_TOOLS}; use crate::channel; diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 330f66c1df0..9c3a17bff6b 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -13,7 +13,7 @@ use std::io; use std::path::{PathBuf, Path}; use crate::Mode; -use build_helper::up_to_date; +use build_helper::{t, up_to_date}; use crate::util::symlink_dir; use crate::builder::{Builder, Compiler, RunConfig, ShouldRun, Step}; diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 2d040d60e5f..deda30b6bbd 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -8,6 +8,8 @@ use std::fs; use std::path::{Path, PathBuf, Component}; use std::process::Command; +use build_helper::t; + use crate::dist::{self, pkgname, sanitize_sh, tmpdir}; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index f63aac0f0e2..ca4489655ca 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -108,17 +108,6 @@ #![feature(core_intrinsics)] #![feature(drain_filter)] -#[macro_use] -extern crate build_helper; -#[macro_use] -extern crate serde_derive; -#[macro_use] -extern crate lazy_static; - -#[cfg(test)] -#[macro_use] -extern crate pretty_assertions; - use std::cell::{RefCell, Cell}; use std::collections::{HashSet, HashMap}; use std::env; @@ -134,7 +123,9 @@ use std::os::unix::fs::symlink as symlink_file; #[cfg(windows)] use std::os::windows::fs::symlink_file; -use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime}; +use build_helper::{ + mtime, output, run_silent, run_suppressed, t, try_run_silent, try_run_suppressed, +}; use filetime::FileTime; use crate::util::{exe, libdir, OutputFolder, CiEnv}; diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index 7fa377f310b..4a71fd2ce0b 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -4,6 +4,7 @@ use std::path::PathBuf; use std::collections::HashSet; use build_helper::output; +use serde::Deserialize; use serde_json; use crate::{Build, Crate}; diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 285f9458c44..5777331b9bf 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -14,7 +14,7 @@ use std::fs::{self, File}; use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::output; +use build_helper::{output, t}; use cmake; use cc; diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index fa6857cdc11..dc65fb9b797 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -15,7 +15,7 @@ use std::fs; use std::path::PathBuf; use std::process::Command; -use build_helper::output; +use build_helper::{output, t}; use crate::Build; diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 38027aded9c..a3d96836aad 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -11,7 +11,7 @@ use std::iter; use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::{self, output}; +use build_helper::{self, output, t}; use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index c23ddbdbc68..edcd68d010e 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -4,6 +4,8 @@ use std::path::PathBuf; use std::process::{Command, exit}; use std::collections::HashSet; +use build_helper::t; + use crate::Mode; use crate::Compiler; use crate::builder::{Step, RunConfig, ShouldRun, Builder}; diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 8ff7c09fc29..e86209be91f 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -1,3 +1,5 @@ +use serde::{Deserialize, Serialize}; + #[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] /// Whether a tool can be compiled, tested or neither diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index bda1e56e1e7..a162c65672f 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -11,6 +11,8 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::{SystemTime, Instant}; +use build_helper::t; + use crate::config::Config; use crate::builder::Builder; diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index 93d0f61e1d9..63b6399bb90 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -7,4 +7,3 @@ edition = "2018" [dependencies] toml = "0.4" serde = { version = "1.0", features = ["derive"] } -serde_derive = "1.0" diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 00e1a53473c..336d7e32024 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -11,9 +11,8 @@ filetime = "0.2" getopts = "0.2" log = "0.4" regex = "1.0" -serde = "1.0" +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -serde_derive = "1.0" rustfix = "0.4.1" lazy_static = "1.0" walkdir = "2" diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 0329fb0db14..5b3936ffc1e 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -7,6 +7,8 @@ use std::io::BufReader; use std::path::Path; use std::str::FromStr; +use log::*; + #[derive(Clone, Debug, PartialEq)] pub enum ErrorKind { Help, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 54e9b76a21e..dbc477585cb 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -4,6 +4,8 @@ use std::io::prelude::*; use std::io::BufReader; use std::path::{Path, PathBuf}; +use log::*; + use crate::common::{self, CompareMode, Config, Mode}; use crate::util; diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index d651b9a92b6..02b09e21ff0 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -3,6 +3,7 @@ use crate::errors::{Error, ErrorKind}; use crate::runtest::ProcRes; +use serde::Deserialize; use serde_json; use std::path::{Path, PathBuf}; use std::str::FromStr; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index dc5d1b9a853..e253934e566 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -3,14 +3,6 @@ #![feature(vec_remove_item)] #![deny(warnings, rust_2018_idioms)] -#[cfg(unix)] -extern crate libc; -#[macro_use] -extern crate log; -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate serde_derive; extern crate test; use crate::common::CompareMode; @@ -30,6 +22,7 @@ use crate::util::logv; use walkdir::WalkDir; use env_logger; use getopts; +use log::*; use self::header::{EarlyProps, Ignore}; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index a11a4f17eb5..3689946c055 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -29,6 +29,9 @@ use std::path::{Path, PathBuf}; use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::str; +use lazy_static::lazy_static; +use log::*; + use crate::extract_gdb_version; use crate::is_android_gdb_target; diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 50dce4b55ae..adc1224bcd3 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -3,6 +3,8 @@ use std::env; use std::path::PathBuf; use crate::common::Config; +use log::*; + /// Conversion table from triple OS name to Rust SYSNAME const OS_TABLE: &'static [(&'static str, &'static str)] = &[ ("android", "android"), diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 433e9264dd1..eeac6cfbb30 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -6,6 +6,5 @@ edition = "2018" [dependencies] regex = "1" -serde = "1.0.8" -serde_derive = "1.0.8" +serde = { version = "1.0.8", features = ["derive"] } serde_json = "1.0.2" diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index e90737febd5..8626ba060bf 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -5,7 +5,7 @@ use std::fs; use std::path::Path; use std::process::Command; -use serde_derive::Deserialize; +use serde::Deserialize; use serde_json; const LICENSES: &[&str] = &[ From e57c7b859d3d60ee9c1ed63ac87234e83b088f82 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 9 May 2019 18:13:21 +0100 Subject: [PATCH 16/19] Add regression test for #60674. This commit adds a regression test (with current broken behaviour) that tests that `mut` patterns are not lost when provided as input to a proc macro. --- src/test/ui/async-await/auxiliary/issue-60674.rs | 12 ++++++++++++ src/test/ui/async-await/issue-60674.rs | 14 ++++++++++++++ src/test/ui/async-await/issue-60674.stdout | 1 + 3 files changed, 27 insertions(+) create mode 100644 src/test/ui/async-await/auxiliary/issue-60674.rs create mode 100644 src/test/ui/async-await/issue-60674.rs create mode 100644 src/test/ui/async-await/issue-60674.stdout diff --git a/src/test/ui/async-await/auxiliary/issue-60674.rs b/src/test/ui/async-await/auxiliary/issue-60674.rs new file mode 100644 index 00000000000..680c6e55e56 --- /dev/null +++ b/src/test/ui/async-await/auxiliary/issue-60674.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr(_args: TokenStream, input: TokenStream) -> TokenStream { + println!("{}", input); + TokenStream::new() +} diff --git a/src/test/ui/async-await/issue-60674.rs b/src/test/ui/async-await/issue-60674.rs new file mode 100644 index 00000000000..37e356e5baf --- /dev/null +++ b/src/test/ui/async-await/issue-60674.rs @@ -0,0 +1,14 @@ +// aux-build:issue-60674.rs +// compile-pass +// edition:2018 +#![feature(async_await)] + +// This is a regression test that ensures that `mut` patterns are not lost when provided as input +// to a proc macro. + +extern crate issue_60674; + +#[issue_60674::attr] +async fn f(mut x: u8) {} + +fn main() {} diff --git a/src/test/ui/async-await/issue-60674.stdout b/src/test/ui/async-await/issue-60674.stdout new file mode 100644 index 00000000000..f1dbcbaac0b --- /dev/null +++ b/src/test/ui/async-await/issue-60674.stdout @@ -0,0 +1 @@ +async fn f(x: u8) { } From df41e4f695a057fb14fdbc63b9009dafe4d7f681 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Thu, 9 May 2019 10:49:39 -0700 Subject: [PATCH 17/19] Remove the old await! macro This doesn't work anymore, and its continued presence is cause for confusion. --- src/libstd/macros.rs | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 9eba76cc04a..03aebeda47c 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -357,29 +357,6 @@ macro_rules! dbg { }; } -/// Awaits the completion of an async call. -#[macro_export] -#[unstable(feature = "await_macro", issue = "50547")] -#[allow_internal_unstable(gen_future, generators)] -#[allow_internal_unsafe] -macro_rules! r#await { - ($e:expr) => { { - let mut pinned = $e; - loop { - if let $crate::task::Poll::Ready(x) = - $crate::future::poll_with_tls_context(unsafe { - $crate::pin::Pin::new_unchecked(&mut pinned) - }) - { - break x; - } - // FIXME(cramertj) prior to stabilizing await, we have to ensure that this - // can't be used to create a generator on stable via `|| await!()`. - yield - } - } } -} - /// Selects the first successful receive event from a number of receivers. /// /// This macro is used to wait for the first event to occur on a number of From dcd3cf70177f5af115d4799fc7fff836b3bcf649 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 9 May 2019 19:10:27 +0100 Subject: [PATCH 18/19] Do not modify mutability of simple bindings. This commit removes the modification of the mutability of simple bindings. While the mutability isn't used, it is important that it is kept so that the input to procedural macros matches what the user wrote. This commit also modifies the span of the binding mode so that it is considered a compiler desugaring and won't be linted against for being unused.. --- src/librustc/hir/lowering.rs | 44 ++++++---------------- src/libsyntax/parse/parser.rs | 23 ++++++----- src/libsyntax/source_map.rs | 21 +++++++++++ src/test/ui/async-await/issue-60674.stdout | 2 +- 4 files changed, 46 insertions(+), 44 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 20e016b8b5b..2f1bb1475bf 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -50,7 +50,6 @@ use errors::Applicability; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::thin_vec::ThinVec; -use rustc_data_structures::sync::Lrc; use std::collections::{BTreeSet, BTreeMap}; use std::mem; @@ -59,10 +58,10 @@ use syntax::attr; use syntax::ast; use syntax::ast::*; use syntax::errors; -use syntax::ext::hygiene::{Mark, SyntaxContext}; +use syntax::ext::hygiene::Mark; use syntax::print::pprust; use syntax::ptr::P; -use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned}; +use syntax::source_map::{respan, CompilerDesugaringKind, Spanned}; use syntax::std_inject; use syntax::symbol::{keywords, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; @@ -855,27 +854,6 @@ impl<'a> LoweringContext<'a> { Ident::with_empty_ctxt(Symbol::gensym(s)) } - /// Reuses the span but adds information like the kind of the desugaring and features that are - /// allowed inside this span. - fn mark_span_with_reason( - &self, - reason: CompilerDesugaringKind, - span: Span, - allow_internal_unstable: Option>, - ) -> Span { - let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(source_map::ExpnInfo { - call_site: span, - def_site: Some(span), - format: source_map::CompilerDesugaring(reason), - allow_internal_unstable, - allow_internal_unsafe: false, - local_inner_macros: false, - edition: source_map::hygiene::default_edition(), - }); - span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) - } - fn with_anonymous_lifetime_mode( &mut self, anonymous_lifetime_mode: AnonymousLifetimeMode, @@ -1164,7 +1142,7 @@ impl<'a> LoweringContext<'a> { attrs: ThinVec::new(), }; - let unstable_span = self.mark_span_with_reason( + let unstable_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::Async, span, Some(vec![ @@ -1571,7 +1549,7 @@ impl<'a> LoweringContext<'a> { // desugaring that explicitly states that we don't want to track that. // Not tracking it makes lints in rustc and clippy very fragile as // frequently opened issues show. - let exist_ty_span = self.mark_span_with_reason( + let exist_ty_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::ExistentialReturnType, span, None, @@ -2446,7 +2424,7 @@ impl<'a> LoweringContext<'a> { ) -> hir::FunctionRetTy { let span = output.span(); - let exist_ty_span = self.mark_span_with_reason( + let exist_ty_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::Async, span, None, @@ -4182,7 +4160,7 @@ impl<'a> LoweringContext<'a> { }), ExprKind::TryBlock(ref body) => { self.with_catch_scope(body.id, |this| { - let unstable_span = this.mark_span_with_reason( + let unstable_span = this.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::TryBlock, body.span, Some(vec![ @@ -4615,7 +4593,7 @@ impl<'a> LoweringContext<'a> { // expand let mut head = self.lower_expr(head); let head_sp = head.span; - let desugared_span = self.mark_span_with_reason( + let desugared_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::ForLoop, head_sp, None, @@ -4776,7 +4754,7 @@ impl<'a> LoweringContext<'a> { // return Try::from_error(From::from(err)), // } - let unstable_span = self.mark_span_with_reason( + let unstable_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::QuestionMark, e.span, Some(vec![ @@ -4784,7 +4762,7 @@ impl<'a> LoweringContext<'a> { ].into()), ); let try_span = self.sess.source_map().end_point(e.span); - let try_span = self.mark_span_with_reason( + let try_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::QuestionMark, try_span, Some(vec![ @@ -5569,12 +5547,12 @@ impl<'a> LoweringContext<'a> { ); self.sess.abort_if_errors(); } - let span = self.mark_span_with_reason( + let span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::Await, await_span, None, ); - let gen_future_span = self.mark_span_with_reason( + let gen_future_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::Await, await_span, Some(vec![Symbol::intern("gen_future")].into()), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f3eac71ee77..ab4de4891a5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -50,7 +50,10 @@ use crate::symbol::{Symbol, keywords}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; -use syntax_pos::{Span, MultiSpan, BytePos, FileName}; +use syntax_pos::{ + Span, MultiSpan, BytePos, FileName, + hygiene::CompilerDesugaringKind, +}; use log::{debug, trace}; use std::borrow::Cow; @@ -8741,6 +8744,15 @@ impl<'a> Parser<'a> { // statement. let (binding_mode, ident, is_simple_pattern) = match input.pat.node { PatKind::Ident(binding_mode @ BindingMode::ByValue(_), ident, _) => { + // Simple patterns like this don't have a generated argument, but they are + // moved into the closure with a statement, so any `mut` bindings on the + // argument will be unused. This binding mode can't be removed, because + // this would affect the input to procedural macros, but they can have + // their span marked as being the result of a compiler desugaring so + // that they aren't linted against. + input.pat.span = self.sess.source_map().mark_span_with_reason( + CompilerDesugaringKind::Async, span, None); + (binding_mode, ident, true) } _ => (BindingMode::ByValue(Mutability::Mutable), ident, false), @@ -8810,15 +8822,6 @@ impl<'a> Parser<'a> { }) }; - // Remove mutability from arguments. If this is not a simple pattern, - // those arguments are replaced by `__argN`, so there is no need to do this. - if let PatKind::Ident(BindingMode::ByValue(mutability @ Mutability::Mutable), ..) = - &mut input.pat.node - { - assert!(is_simple_pattern); - *mutability = Mutability::Immutable; - } - let move_stmt = Stmt { id, node: StmtKind::Local(P(move_local)), span }; arguments.push(AsyncArgument { ident, arg, pat_stmt, move_stmt }); } diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index 08abbf5e8a4..215618bd09c 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -930,6 +930,27 @@ impl SourceMap { None } + + /// Reuses the span but adds information like the kind of the desugaring and features that are + /// allowed inside this span. + pub fn mark_span_with_reason( + &self, + reason: hygiene::CompilerDesugaringKind, + span: Span, + allow_internal_unstable: Option>, + ) -> Span { + let mark = Mark::fresh(Mark::root()); + mark.set_expn_info(ExpnInfo { + call_site: span, + def_site: Some(span), + format: CompilerDesugaring(reason), + allow_internal_unstable, + allow_internal_unsafe: false, + local_inner_macros: false, + edition: hygiene::default_edition(), + }); + span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) + } } impl SourceMapper for SourceMap { diff --git a/src/test/ui/async-await/issue-60674.stdout b/src/test/ui/async-await/issue-60674.stdout index f1dbcbaac0b..a93944db1c5 100644 --- a/src/test/ui/async-await/issue-60674.stdout +++ b/src/test/ui/async-await/issue-60674.stdout @@ -1 +1 @@ -async fn f(x: u8) { } +async fn f(mut x: u8) { } From d5e04067cb23df91070fea1a01aa6417afa714ed Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 9 May 2019 19:14:39 +0100 Subject: [PATCH 19/19] Add FIXME about `construct_async_arguments`. This is unrelated to the rest of this PR but it made sense to add a FIXME explaining that the function shouldn't really be in the parser. --- src/libsyntax/parse/parser.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ab4de4891a5..5fd6276a237 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -8730,6 +8730,10 @@ impl<'a> Parser<'a> { /// The arguments of the function are replaced in HIR lowering with the arguments created by /// this function and the statements created here are inserted at the top of the closure body. fn construct_async_arguments(&mut self, asyncness: &mut Spanned, decl: &mut FnDecl) { + // FIXME(davidtwco): This function should really live in the HIR lowering but because + // the types constructed here need to be used in parts of resolve so that the correct + // locals are considered upvars, it is currently easier for it to live here in the parser, + // where it can be constructed once. if let IsAsync::Async { ref mut arguments, .. } = asyncness.node { for (index, input) in decl.inputs.iter_mut().enumerate() { let id = ast::DUMMY_NODE_ID;