From 940f65782cc5df7fecad27b38cc25b6d1eeaf2e8 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 8 Feb 2020 21:34:38 -0800 Subject: [PATCH 01/23] Parse & reject postfix operators after casts This adds parsing for expressions like 'x as Ty[0]' which will immediately error out, but still give the rest of the parser a valid parse tree to continue. --- src/librustc_parse/parser/expr.rs | 41 +++++++++- .../parser/issue-35813-postfix-after-cast.rs | 63 ++++++++++++++++ .../issue-35813-postfix-after-cast.stderr | 74 +++++++++++++++++++ 3 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/parser/issue-35813-postfix-after-cast.rs create mode 100644 src/test/ui/parser/issue-35813-postfix-after-cast.stderr diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 20b9df0a2d9b6..d7d3145770ca1 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -551,7 +551,7 @@ impl<'a> Parser<'a> { // Save the state of the parser before parsing type normally, in case there is a // LessThan comparison after this cast. let parser_snapshot_before_type = self.clone(); - match self.parse_ty_no_plus() { + let type_result = match self.parse_ty_no_plus() { Ok(rhs) => Ok(mk_expr(self, rhs)), Err(mut type_err) => { // Rewind to before attempting to parse the type with generics, to recover @@ -616,7 +616,44 @@ impl<'a> Parser<'a> { } } } - } + }; + + // Disallow postfix operators such as `.`, `?` or index (`[]`) after casts. + // Parses the postfix operator and emits an error. + let expr = type_result?; + let span = expr.span; + + // The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`. + let with_postfix = self.parse_dot_or_call_expr_with_(expr, span)?; + if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) { + let expr_str = self.span_to_snippet(span); + + let msg = format!( + "casts followed by {} are not supported", + match with_postfix.kind { + ExprKind::Index(_, _) => "index operators", + ExprKind::Try(_) => "try operators", + ExprKind::Field(_, _) => "field access expressions", + ExprKind::MethodCall(_, _) => "method call expressions", + ExprKind::Await(_) => "awaits", + _ => "expressions", + } + ); + let mut err = self.struct_span_err(with_postfix.span, &msg); + let suggestion = "try surrounding the expression with parentheses"; + if let Ok(expr_str) = expr_str { + err.span_suggestion( + span, + suggestion, + format!("({})", expr_str), + Applicability::MachineApplicable, + ) + } else { + err.span_help(span, suggestion) + } + .emit(); + }; + Ok(with_postfix) } fn parse_assoc_op_ascribe(&mut self, lhs: P, lhs_span: Span) -> PResult<'a, P> { diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs new file mode 100644 index 0000000000000..dd608b263ec6c --- /dev/null +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs @@ -0,0 +1,63 @@ +// edition:2018 +#![crate_type = "lib"] +use std::future::Future; +use std::pin::Pin; + +// This tests the parser for "x as Y[z]". It errors, but we want to give useful +// errors and parse such that further code gives useful errors. +pub fn index_after_as_cast() { + vec![1, 2, 3] as Vec[0]; + //~^ ERROR: casts followed by index operators are not supported +} + +pub fn index_after_cast_to_index() { + (&[0]) as &[i32][0]; + //~^ ERROR: casts followed by index operators are not supported +} + +// this tests that the precedence for `!x as Y.Z` is still what we expect +pub fn precedence() { + let x: i32 = &vec![1, 2, 3] as &Vec[0]; + //~^ ERROR: casts followed by index operators are not supported +} + +pub fn complex() { + let _ = format!( + "{}", + if true { 33 } else { 44 } as i32.max(0) + //~^ ERROR: casts followed by method call expressions are not supported + ); +} + +pub fn in_condition() { + if 5u64 as i32.max(0) == 0 { + //~^ ERROR: casts followed by method call expressions are not supported + } +} + +pub fn inside_block() { + let _ = if true { + 5u64 as u32.max(0) == 0 + //~^ ERROR: casts followed by method call expressions are not supported + } else { false }; +} + +static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); +//~^ ERROR: casts followed by index operators are not supported + +pub async fn cast_then_await() { + Box::pin(noop()) as Pin>>.await; + //~^ ERROR: casts followed by awaits are not supported +} + +pub async fn noop() {} + +#[derive(Default)] +pub struct Foo { + pub bar: u32, +} + +pub fn struct_field() { + Foo::default() as Foo.bar; + //~^ ERROR: casts followed by field access expressions are not supported +} diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr new file mode 100644 index 0000000000000..9459e076ea0c5 --- /dev/null +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr @@ -0,0 +1,74 @@ +error: casts followed by index operators are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:9:5 + | +LL | vec![1, 2, 3] as Vec[0]; + | -------------------------^^^ + | | + | help: try surrounding the expression with parentheses: `(vec![1, 2, 3] as Vec)` + +error: casts followed by index operators are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:14:5 + | +LL | (&[0]) as &[i32][0]; + | ----------------^^^ + | | + | help: try surrounding the expression with parentheses: `((&[0]) as &[i32])` + +error: casts followed by index operators are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:20:18 + | +LL | let x: i32 = &vec![1, 2, 3] as &Vec[0]; + | ---------------------------^^^ + | | + | help: try surrounding the expression with parentheses: `(&vec![1, 2, 3] as &Vec)` + +error: casts followed by method call expressions are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:33:8 + | +LL | if 5u64 as i32.max(0) == 0 { + | -----------^^^^^^^ + | | + | help: try surrounding the expression with parentheses: `(5u64 as i32)` + +error: casts followed by method call expressions are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:40:9 + | +LL | 5u64 as u32.max(0) == 0 + | -----------^^^^^^^ + | | + | help: try surrounding the expression with parentheses: `(5u64 as u32)` + +error: casts followed by index operators are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:45:24 + | +LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); + | ------------------^^^^^^ + | | + | help: try surrounding the expression with parentheses: `(&[1,2,3] as &[i32])` + +error: casts followed by awaits are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:49:5 + | +LL | Box::pin(noop()) as Pin>>.await; + | -----------------------------------------------------^^^^^^ + | | + | help: try surrounding the expression with parentheses: `(Box::pin(noop()) as Pin>>)` + +error: casts followed by field access expressions are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:61:5 + | +LL | Foo::default() as Foo.bar; + | ---------------------^^^^ + | | + | help: try surrounding the expression with parentheses: `(Foo::default() as Foo)` + +error: casts followed by method call expressions are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:27:9 + | +LL | if true { 33 } else { 44 } as i32.max(0) + | ---------------------------------^^^^^^^ + | | + | help: try surrounding the expression with parentheses: `(if true { 33 } else { 44 } as i32)` + +error: aborting due to 9 previous errors + From 5ce9b80c0f93e54bc83f6cb15942ecdce31c3e6a Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 16:12:59 -0800 Subject: [PATCH 02/23] Refactor out error case & apply suggestions. This is almost entirely refactoring and message changing, with the single behavioral change of panicking for unexpected output. --- src/librustc_parse/parser/expr.rs | 62 +++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index d7d3145770ca1..76e4a80878f13 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -551,8 +551,8 @@ impl<'a> Parser<'a> { // Save the state of the parser before parsing type normally, in case there is a // LessThan comparison after this cast. let parser_snapshot_before_type = self.clone(); - let type_result = match self.parse_ty_no_plus() { - Ok(rhs) => Ok(mk_expr(self, rhs)), + let cast_expr = match self.parse_ty_no_plus() { + Ok(rhs) => mk_expr(self, rhs), Err(mut type_err) => { // Rewind to before attempting to parse the type with generics, to recover // from situations like `x as usize < y` in which we first tried to parse @@ -606,41 +606,63 @@ impl<'a> Parser<'a> { ) .emit(); - Ok(expr) + expr } Err(mut path_err) => { // Couldn't parse as a path, return original error and parser state. path_err.cancel(); mem::replace(self, parser_snapshot_after_type); - Err(type_err) + return Err(type_err); } } } }; - // Disallow postfix operators such as `.`, `?` or index (`[]`) after casts. - // Parses the postfix operator and emits an error. - let expr = type_result?; - let span = expr.span; + self.parse_and_disallow_postfix_after_cast(cast_expr) + } - // The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`. - let with_postfix = self.parse_dot_or_call_expr_with_(expr, span)?; - if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) { + /// Parses a postfix operators such as `.`, `?`, or index (`[]`) after a cast, + /// then emits an error and returns the newly parsed tree. + /// The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`. + fn parse_and_disallow_postfix_after_cast( + &mut self, + cast_expr: P, + ) -> PResult<'a, P> { + use std::collections::hash_map::DefaultHasher; + use std::hash::Hasher; + // Hash the memory location of expr before parsing any following postfix operators. + // This will be compared with the hash of the output expression. + // If they different we can assume we parsed another expression because the existing expression is not reallocated. + let mut before_hasher = DefaultHasher::new(); + std::ptr::hash(&*cast_expr, &mut before_hasher); + let before_hash = before_hasher.finish(); + let span = cast_expr.span; + let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?; + + let mut after_hasher = DefaultHasher::new(); + std::ptr::hash(&*with_postfix, &mut after_hasher); + let after_hash = after_hasher.finish(); + + // Check if an illegal postfix operator has been added after the cast. + // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator. + if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) || after_hash != before_hash { let expr_str = self.span_to_snippet(span); let msg = format!( - "casts followed by {} are not supported", + "casts cannot be followed by {}", match with_postfix.kind { - ExprKind::Index(_, _) => "index operators", - ExprKind::Try(_) => "try operators", - ExprKind::Field(_, _) => "field access expressions", - ExprKind::MethodCall(_, _) => "method call expressions", - ExprKind::Await(_) => "awaits", - _ => "expressions", + ExprKind::Index(_, _) => "indexing", + ExprKind::Try(_) => "?", + ExprKind::Field(_, _) => "a field access", + ExprKind::MethodCall(_, _) => "a method call", + ExprKind::Call(_, _) => "a function call", + ExprKind::Await(_) => "`.await`", + ref kind => + unreachable!("parse_dot_or_call_expr_with_ shouldn't produce a {:?}", kind), } ); - let mut err = self.struct_span_err(with_postfix.span, &msg); - let suggestion = "try surrounding the expression with parentheses"; + let mut err = self.struct_span_err(span, &msg); + let suggestion = "try surrounding the expression in parentheses"; if let Ok(expr_str) = expr_str { err.span_suggestion( span, From 4fc0532269f40c2870936faaebcdd14539613411 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 16:18:20 -0800 Subject: [PATCH 03/23] Type ascription outputs a Type, not Cast Previously this just errored out on all usages of type ascription, which isn't helpful. --- src/librustc_parse/parser/expr.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 76e4a80878f13..645e680d15f48 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -645,7 +645,9 @@ impl<'a> Parser<'a> { // Check if an illegal postfix operator has been added after the cast. // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator. - if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) || after_hash != before_hash { + if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) + || after_hash != before_hash + { let expr_str = self.span_to_snippet(span); let msg = format!( From 0cf204930a2ecaa5f7416602fca6054d4fd44b6b Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 16:18:50 -0800 Subject: [PATCH 04/23] Keep better fix suggestion if type ascription is likely unintended --- src/librustc_parse/parser/expr.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 645e680d15f48..fe5570f26abd5 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -665,17 +665,23 @@ impl<'a> Parser<'a> { ); let mut err = self.struct_span_err(span, &msg); let suggestion = "try surrounding the expression in parentheses"; - if let Ok(expr_str) = expr_str { - err.span_suggestion( - span, - suggestion, - format!("({})", expr_str), - Applicability::MachineApplicable, - ) + // if type ascription is "likely an error", the user will already be getting a useful + // help message, and doesn't need a second. + if self.last_type_ascription.map_or(false, |last_ascription| last_ascription.1) { + self.maybe_annotate_with_ascription(&mut err, false); } else { - err.span_help(span, suggestion) + if let Ok(expr_str) = expr_str { + err.span_suggestion( + span, + suggestion, + format!("({})", expr_str), + Applicability::MachineApplicable, + ); + } else { + err.span_help(span, suggestion); + } } - .emit(); + err.emit(); }; Ok(with_postfix) } From f82ca8b0efa64bc33ed811b34c83a21aeb2950d1 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 16:20:53 -0800 Subject: [PATCH 05/23] Add more error cases to issue 35813 tests --- .../parser/issue-35813-postfix-after-cast.rs | 100 ++++++++-- .../issue-35813-postfix-after-cast.stderr | 183 +++++++++++++----- 2 files changed, 225 insertions(+), 58 deletions(-) diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs index dd608b263ec6c..0083a475ddfba 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.rs +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs @@ -1,5 +1,6 @@ // edition:2018 #![crate_type = "lib"] +#![feature(type_ascription)] use std::future::Future; use std::pin::Pin; @@ -7,47 +8,122 @@ use std::pin::Pin; // errors and parse such that further code gives useful errors. pub fn index_after_as_cast() { vec![1, 2, 3] as Vec[0]; - //~^ ERROR: casts followed by index operators are not supported + //~^ ERROR: casts cannot be followed by indexing + vec![1, 2, 3]: Vec[0]; + //~^ ERROR: casts cannot be followed by indexing } pub fn index_after_cast_to_index() { (&[0]) as &[i32][0]; - //~^ ERROR: casts followed by index operators are not supported + //~^ ERROR: casts cannot be followed by indexing + (&[0i32]): &[i32; 1][0]; + //~^ ERROR: casts cannot be followed by indexing +} + +pub fn cast_after_cast() { + if 5u64 as i32 as u16 == 0u16 { + + } + if 5u64: u64: u64 == 0u64 { + + } + let _ = 5u64: u64: u64 as u8 as i8 == 9i8; + let _ = 0i32: i32: i32; + let _ = 0 as i32: i32; + let _ = 0i32: i32 as i32; + let _ = 0 as i32 as i32; + let _ = 0i32: i32: i32 as u32 as i32; } // this tests that the precedence for `!x as Y.Z` is still what we expect pub fn precedence() { let x: i32 = &vec![1, 2, 3] as &Vec[0]; - //~^ ERROR: casts followed by index operators are not supported + //~^ ERROR: casts cannot be followed by indexing +} + +pub fn method_calls() { + 0 as i32.max(0); + //~^ ERROR: casts cannot be followed by a method call + 0: i32.max(0); + //~^ ERROR: casts cannot be followed by a method call } pub fn complex() { let _ = format!( - "{}", - if true { 33 } else { 44 } as i32.max(0) - //~^ ERROR: casts followed by method call expressions are not supported + "{} and {}", + if true { 33 } else { 44 } as i32.max(0), + //~^ ERROR: casts cannot be followed by a method call + if true { 33 } else { 44 }: i32.max(0) + //~^ ERROR: casts cannot be followed by a method call ); } pub fn in_condition() { if 5u64 as i32.max(0) == 0 { - //~^ ERROR: casts followed by method call expressions are not supported + //~^ ERROR: casts cannot be followed by a method call + } + if 5u64: u64.max(0) == 0 { + //~^ ERROR: casts cannot be followed by a method call } } pub fn inside_block() { let _ = if true { 5u64 as u32.max(0) == 0 - //~^ ERROR: casts followed by method call expressions are not supported + //~^ ERROR: casts cannot be followed by a method call + } else { false }; + let _ = if true { + 5u64: u64.max(0) == 0 + //~^ ERROR: casts cannot be followed by a method call } else { false }; } static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); -//~^ ERROR: casts followed by index operators are not supported +//~^ ERROR: casts cannot be followed by indexing + +static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); +//~^ ERROR: casts cannot be followed by indexing + + +pub fn cast_then_try() -> Result { + Err(0u64) as Result?; + //~^ ERROR: casts cannot be followed by ? + Err(0u64): Result?; + //~^ ERROR: casts cannot be followed by ? + Ok(1) +} + + +pub fn cast_then_call() { + type F = fn(u8); + // type ascription won't actually do [unique drop fn type] -> fn(u8) casts. + let drop_ptr = drop as fn(u8); + drop as F(); + //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214] + drop_ptr: F(); + //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214] +} + +pub fn cast_to_fn_should_work() { + let drop_ptr = drop as fn(u8); + drop as fn(u8); + drop_ptr: fn(u8); +} + +pub fn parens_after_cast_error() { + let drop_ptr = drop as fn(u8); + drop as fn(u8)(0); + //~^ ERROR: casts cannot be followed by a function call + drop_ptr: fn(u8)(0); + //~^ ERROR: casts cannot be followed by a function call +} pub async fn cast_then_await() { Box::pin(noop()) as Pin>>.await; - //~^ ERROR: casts followed by awaits are not supported + //~^ ERROR: casts cannot be followed by `.await` + + Box::pin(noop()): Pin>.await; + //~^ ERROR: casts cannot be followed by `.await` } pub async fn noop() {} @@ -59,5 +135,7 @@ pub struct Foo { pub fn struct_field() { Foo::default() as Foo.bar; - //~^ ERROR: casts followed by field access expressions are not supported + //~^ ERROR: cannot be followed by a field access + Foo::default(): Foo.bar; + //~^ ERROR: cannot be followed by a field access } diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr index 9459e076ea0c5..ec6c4eb810737 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr @@ -1,74 +1,163 @@ -error: casts followed by index operators are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:9:5 +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:10:5 | LL | vec![1, 2, 3] as Vec[0]; - | -------------------------^^^ - | | - | help: try surrounding the expression with parentheses: `(vec![1, 2, 3] as Vec)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(vec![1, 2, 3] as Vec)` -error: casts followed by index operators are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:14:5 +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:12:5 + | +LL | vec![1, 2, 3]: Vec[0]; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(vec![1, 2, 3]: Vec)` + +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:17:5 | LL | (&[0]) as &[i32][0]; - | ----------------^^^ - | | - | help: try surrounding the expression with parentheses: `((&[0]) as &[i32])` + | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `((&[0]) as &[i32])` -error: casts followed by index operators are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:20:18 +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:19:5 + | +LL | (&[0i32]): &[i32; 1][0]; + | ^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `((&[0i32]): &[i32; 1])` + +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:40:18 | LL | let x: i32 = &vec![1, 2, 3] as &Vec[0]; - | ---------------------------^^^ - | | - | help: try surrounding the expression with parentheses: `(&vec![1, 2, 3] as &Vec)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&vec![1, 2, 3] as &Vec)` -error: casts followed by method call expressions are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:33:8 +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:45:5 + | +LL | 0 as i32.max(0); + | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:47:5 + | +LL | 0: i32.max(0); + | ^^^^^^ help: try surrounding the expression in parentheses: `(0: i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:62:8 | LL | if 5u64 as i32.max(0) == 0 { - | -----------^^^^^^^ - | | - | help: try surrounding the expression with parentheses: `(5u64 as i32)` + | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as i32)` -error: casts followed by method call expressions are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:40:9 +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:65:8 + | +LL | if 5u64: u64.max(0) == 0 { + | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:72:9 | LL | 5u64 as u32.max(0) == 0 - | -----------^^^^^^^ - | | - | help: try surrounding the expression with parentheses: `(5u64 as u32)` + | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as u32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:76:9 + | +LL | 5u64: u64.max(0) == 0 + | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` -error: casts followed by index operators are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:45:24 +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:81:24 | LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); - | ------------------^^^^^^ - | | - | help: try surrounding the expression with parentheses: `(&[1,2,3] as &[i32])` + | ^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1,2,3] as &[i32])` + +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:84:25 + | +LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1i32,2,3]: &[i32; 3])` + +error: casts cannot be followed by ? + --> $DIR/issue-35813-postfix-after-cast.rs:89:5 + | +LL | Err(0u64) as Result?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Err(0u64) as Result)` + +error: casts cannot be followed by ? + --> $DIR/issue-35813-postfix-after-cast.rs:91:5 + | +LL | Err(0u64): Result?; + | ^^^^^^^^^-^^^^^^^^^^^^^^^^ + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 -error: casts followed by awaits are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:49:5 +error: casts cannot be followed by a function call + --> $DIR/issue-35813-postfix-after-cast.rs:115:5 + | +LL | drop as fn(u8)(0); + | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop as fn(u8))` + +error: casts cannot be followed by a function call + --> $DIR/issue-35813-postfix-after-cast.rs:117:5 + | +LL | drop_ptr: fn(u8)(0); + | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop_ptr: fn(u8))` + +error: casts cannot be followed by `.await` + --> $DIR/issue-35813-postfix-after-cast.rs:122:5 | LL | Box::pin(noop()) as Pin>>.await; - | -----------------------------------------------------^^^^^^ - | | - | help: try surrounding the expression with parentheses: `(Box::pin(noop()) as Pin>>)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Box::pin(noop()) as Pin>>)` + +error: casts cannot be followed by `.await` + --> $DIR/issue-35813-postfix-after-cast.rs:125:5 + | +LL | Box::pin(noop()): Pin>.await; + | ^^^^^^^^^^^^^^^^-^^^^^^^^^^^^ + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 -error: casts followed by field access expressions are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:61:5 +error: casts cannot be followed by a field access + --> $DIR/issue-35813-postfix-after-cast.rs:137:5 | LL | Foo::default() as Foo.bar; - | ---------------------^^^^ - | | - | help: try surrounding the expression with parentheses: `(Foo::default() as Foo)` + | ^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default() as Foo)` + +error: casts cannot be followed by a field access + --> $DIR/issue-35813-postfix-after-cast.rs:139:5 + | +LL | Foo::default(): Foo.bar; + | ^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default(): Foo)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:54:9 + | +LL | if true { 33 } else { 44 } as i32.max(0), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 } as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:56:9 + | +LL | if true { 33 } else { 44 }: i32.max(0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 }: i32)` + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-35813-postfix-after-cast.rs:101:13 + | +LL | drop as F(); + | ^^^ only `Fn` traits may use parentheses -error: casts followed by method call expressions are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:27:9 +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-35813-postfix-after-cast.rs:103:15 | -LL | if true { 33 } else { 44 } as i32.max(0) - | ---------------------------------^^^^^^^ - | | - | help: try surrounding the expression with parentheses: `(if true { 33 } else { 44 } as i32)` +LL | drop_ptr: F(); + | ^^^ only `Fn` traits may use parentheses -error: aborting due to 9 previous errors +error: aborting due to 25 previous errors +For more information about this error, try `rustc --explain E0214`. From 5dd646435ba882574e677acf58113880a6570949 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 16:21:59 -0800 Subject: [PATCH 06/23] Fix related type ascription tests. --- src/test/ui/type/ascription/issue-54516.rs | 4 ++- .../ui/type/ascription/issue-54516.stderr | 26 ++++++++++++++++--- src/test/ui/type/ascription/issue-60933.rs | 4 ++- .../ui/type/ascription/issue-60933.stderr | 26 ++++++++++++++++--- 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/test/ui/type/ascription/issue-54516.rs b/src/test/ui/type/ascription/issue-54516.rs index b53bfe5df03f3..8d6fd2abb6d5f 100644 --- a/src/test/ui/type/ascription/issue-54516.rs +++ b/src/test/ui/type/ascription/issue-54516.rs @@ -2,5 +2,7 @@ use std::collections::BTreeMap; fn main() { println!("{}", std::mem:size_of::>()); - //~^ ERROR expected one of + //~^ ERROR casts cannot be followed by a function call + //~| ERROR expected value, found module `std::mem` [E0423] + //~| ERROR cannot find type `size_of` in this scope [E0412] } diff --git a/src/test/ui/type/ascription/issue-54516.stderr b/src/test/ui/type/ascription/issue-54516.stderr index 7127f67cd7dde..fdf35700ef94c 100644 --- a/src/test/ui/type/ascription/issue-54516.stderr +++ b/src/test/ui/type/ascription/issue-54516.stderr @@ -1,13 +1,31 @@ -error: expected one of `!`, `,`, or `::`, found `(` - --> $DIR/issue-54516.rs:4:58 +error: casts cannot be followed by a function call + --> $DIR/issue-54516.rs:4:20 | LL | println!("{}", std::mem:size_of::>()); - | - ^ expected one of `!`, `,`, or `::` + | ^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: maybe write a path separator here: `::` | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` = note: see issue #23416 for more information -error: aborting due to previous error +error[E0423]: expected value, found module `std::mem` + --> $DIR/issue-54516.rs:4:20 + | +LL | println!("{}", std::mem:size_of::>()); + | ^^^^^^^^- help: maybe you meant to write a path separator here: `::` + | | + | not a value + +error[E0412]: cannot find type `size_of` in this scope + --> $DIR/issue-54516.rs:4:29 + | +LL | println!("{}", std::mem:size_of::>()); + | -^^^^^^^ not found in this scope + | | + | help: maybe you meant to write a path separator here: `::` + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0412, E0423. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/type/ascription/issue-60933.rs b/src/test/ui/type/ascription/issue-60933.rs index 8fb06c887bd3e..bcf9f88cb414b 100644 --- a/src/test/ui/type/ascription/issue-60933.rs +++ b/src/test/ui/type/ascription/issue-60933.rs @@ -1,4 +1,6 @@ fn main() { let u: usize = std::mem:size_of::(); - //~^ ERROR expected one of + //~^ ERROR casts cannot be followed by a function call + //~| ERROR expected value, found module `std::mem` [E0423] + //~| ERROR cannot find type `size_of` in this scope [E0412] } diff --git a/src/test/ui/type/ascription/issue-60933.stderr b/src/test/ui/type/ascription/issue-60933.stderr index 7130767b6c6f3..cd9ae8f49f4f1 100644 --- a/src/test/ui/type/ascription/issue-60933.stderr +++ b/src/test/ui/type/ascription/issue-60933.stderr @@ -1,13 +1,31 @@ -error: expected one of `!`, `::`, or `;`, found `(` - --> $DIR/issue-60933.rs:2:43 +error: casts cannot be followed by a function call + --> $DIR/issue-60933.rs:2:20 | LL | let u: usize = std::mem:size_of::(); - | - ^ expected one of `!`, `::`, or `;` + | ^^^^^^^^-^^^^^^^^^^^^^^ | | | help: maybe write a path separator here: `::` | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` = note: see issue #23416 for more information -error: aborting due to previous error +error[E0423]: expected value, found module `std::mem` + --> $DIR/issue-60933.rs:2:20 + | +LL | let u: usize = std::mem:size_of::(); + | ^^^^^^^^- help: maybe you meant to write a path separator here: `::` + | | + | not a value + +error[E0412]: cannot find type `size_of` in this scope + --> $DIR/issue-60933.rs:2:29 + | +LL | let u: usize = std::mem:size_of::(); + | -^^^^^^^ not found in this scope + | | + | help: maybe you meant to write a path separator here: `::` + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0412, E0423. +For more information about an error, try `rustc --explain E0412`. From e3eefe266756449ebe3b2c1bb177f0130569b3b2 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 17:09:42 -0800 Subject: [PATCH 07/23] Remove extra debug print in unreachable! --- src/librustc_parse/parser/expr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index fe5570f26abd5..3d0f746d3955c 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -659,8 +659,7 @@ impl<'a> Parser<'a> { ExprKind::MethodCall(_, _) => "a method call", ExprKind::Call(_, _) => "a function call", ExprKind::Await(_) => "`.await`", - ref kind => - unreachable!("parse_dot_or_call_expr_with_ shouldn't produce a {:?}", kind), + _ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"), } ); let mut err = self.struct_span_err(span, &msg); From c2d7ffb8a9906f5c7b6a1cf6a739cf4d7d732c2b Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 17:17:09 -0800 Subject: [PATCH 08/23] Remove trailing whitespace --- src/test/ui/parser/issue-35813-postfix-after-cast.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs index 0083a475ddfba..d04a092e93b00 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.rs +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs @@ -22,10 +22,10 @@ pub fn index_after_cast_to_index() { pub fn cast_after_cast() { if 5u64 as i32 as u16 == 0u16 { - + } if 5u64: u64: u64 == 0u64 { - + } let _ = 5u64: u64: u64 as u8 as i8 == 9i8; let _ = 0i32: i32: i32; @@ -107,7 +107,7 @@ pub fn cast_then_call() { pub fn cast_to_fn_should_work() { let drop_ptr = drop as fn(u8); drop as fn(u8); - drop_ptr: fn(u8); + drop_ptr: fn(u8); } pub fn parens_after_cast_error() { From 8ef3da0858c5a76fd1756b9efcf82eeb9491fb64 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 22:08:29 -0800 Subject: [PATCH 09/23] Fix test stderr after rebasing on master. --- src/test/ui/parser/issue-35813-postfix-after-cast.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr index ec6c4eb810737..f96000ea0aa4d 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr @@ -91,7 +91,7 @@ LL | Err(0u64): Result?; | help: maybe write a path separator here: `::` | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` - = note: for more information, see https://github.com/rust-lang/rust/issues/23416 + = note: see issue #23416 for more information error: casts cannot be followed by a function call --> $DIR/issue-35813-postfix-after-cast.rs:115:5 @@ -120,7 +120,7 @@ LL | Box::pin(noop()): Pin>.await; | help: maybe write a path separator here: `::` | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` - = note: for more information, see https://github.com/rust-lang/rust/issues/23416 + = note: see issue #23416 for more information error: casts cannot be followed by a field access --> $DIR/issue-35813-postfix-after-cast.rs:137:5 From fa1f547f82d66f986af2c33220199b042fcb5f99 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 22 Feb 2020 11:36:09 -0800 Subject: [PATCH 10/23] Add more double cast + method call tests --- .../parser/issue-35813-postfix-after-cast.rs | 23 ++++ .../issue-35813-postfix-after-cast.stderr | 104 ++++++++++++++---- 2 files changed, 105 insertions(+), 22 deletions(-) diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs index d04a092e93b00..5c6e0ce5024d9 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.rs +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs @@ -35,6 +35,29 @@ pub fn cast_after_cast() { let _ = 0i32: i32: i32 as u32 as i32; } +pub fn cast_cast_method_call() { + let _ = 0i32: i32: i32.count_ones(); + //~^ ERROR: casts cannot be followed by a method call + let _ = 0 as i32: i32.count_ones(); + //~^ ERROR: casts cannot be followed by a method call + let _ = 0i32: i32 as i32.count_ones(); + //~^ ERROR: casts cannot be followed by a method call + let _ = 0 as i32 as i32.count_ones(); + //~^ ERROR: casts cannot be followed by a method call + let _ = 0i32: i32: i32 as u32 as i32.count_ones(); + //~^ ERROR: casts cannot be followed by a method call + let _ = 0i32: i32.count_ones(): u32; + //~^ ERROR: casts cannot be followed by a method call + let _ = 0 as i32.count_ones(): u32; + //~^ ERROR: casts cannot be followed by a method call + let _ = 0i32: i32.count_ones() as u32; + //~^ ERROR: casts cannot be followed by a method call + let _ = 0 as i32.count_ones() as u32; + //~^ ERROR: casts cannot be followed by a method call + let _ = 0i32: i32: i32.count_ones() as u32 as i32; + //~^ ERROR: casts cannot be followed by a method call +} + // this tests that the precedence for `!x as Y.Z` is still what we expect pub fn precedence() { let x: i32 = &vec![1, 2, 3] as &Vec[0]; diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr index f96000ea0aa4d..42b614edf7638 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr @@ -22,68 +22,128 @@ error: casts cannot be followed by indexing LL | (&[0i32]): &[i32; 1][0]; | ^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `((&[0i32]): &[i32; 1])` +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:39:13 + | +LL | let _ = 0i32: i32: i32.count_ones(); + | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:41:13 + | +LL | let _ = 0 as i32: i32.count_ones(); + | ^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32: i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:43:13 + | +LL | let _ = 0i32: i32 as i32.count_ones(); + | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:45:13 + | +LL | let _ = 0 as i32 as i32.count_ones(); + | ^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:47:13 + | +LL | let _ = 0i32: i32: i32 as u32 as i32.count_ones(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32 as u32 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:49:13 + | +LL | let _ = 0i32: i32.count_ones(): u32; + | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:51:13 + | +LL | let _ = 0 as i32.count_ones(): u32; + | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:53:13 + | +LL | let _ = 0i32: i32.count_ones() as u32; + | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:55:13 + | +LL | let _ = 0 as i32.count_ones() as u32; + | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:57:13 + | +LL | let _ = 0i32: i32: i32.count_ones() as u32 as i32; + | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32)` + error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:40:18 + --> $DIR/issue-35813-postfix-after-cast.rs:63:18 | LL | let x: i32 = &vec![1, 2, 3] as &Vec[0]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&vec![1, 2, 3] as &Vec)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:45:5 + --> $DIR/issue-35813-postfix-after-cast.rs:68:5 | LL | 0 as i32.max(0); | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:47:5 + --> $DIR/issue-35813-postfix-after-cast.rs:70:5 | LL | 0: i32.max(0); | ^^^^^^ help: try surrounding the expression in parentheses: `(0: i32)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:62:8 + --> $DIR/issue-35813-postfix-after-cast.rs:85:8 | LL | if 5u64 as i32.max(0) == 0 { | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as i32)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:65:8 + --> $DIR/issue-35813-postfix-after-cast.rs:88:8 | LL | if 5u64: u64.max(0) == 0 { | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:72:9 + --> $DIR/issue-35813-postfix-after-cast.rs:95:9 | LL | 5u64 as u32.max(0) == 0 | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as u32)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:76:9 + --> $DIR/issue-35813-postfix-after-cast.rs:99:9 | LL | 5u64: u64.max(0) == 0 | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:81:24 + --> $DIR/issue-35813-postfix-after-cast.rs:104:24 | LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); | ^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1,2,3] as &[i32])` error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:84:25 + --> $DIR/issue-35813-postfix-after-cast.rs:107:25 | LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); | ^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1i32,2,3]: &[i32; 3])` error: casts cannot be followed by ? - --> $DIR/issue-35813-postfix-after-cast.rs:89:5 + --> $DIR/issue-35813-postfix-after-cast.rs:112:5 | LL | Err(0u64) as Result?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Err(0u64) as Result)` error: casts cannot be followed by ? - --> $DIR/issue-35813-postfix-after-cast.rs:91:5 + --> $DIR/issue-35813-postfix-after-cast.rs:114:5 | LL | Err(0u64): Result?; | ^^^^^^^^^-^^^^^^^^^^^^^^^^ @@ -94,25 +154,25 @@ LL | Err(0u64): Result?; = note: see issue #23416 for more information error: casts cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:115:5 + --> $DIR/issue-35813-postfix-after-cast.rs:138:5 | LL | drop as fn(u8)(0); | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop as fn(u8))` error: casts cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:117:5 + --> $DIR/issue-35813-postfix-after-cast.rs:140:5 | LL | drop_ptr: fn(u8)(0); | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop_ptr: fn(u8))` error: casts cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:122:5 + --> $DIR/issue-35813-postfix-after-cast.rs:145:5 | LL | Box::pin(noop()) as Pin>>.await; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Box::pin(noop()) as Pin>>)` error: casts cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:125:5 + --> $DIR/issue-35813-postfix-after-cast.rs:148:5 | LL | Box::pin(noop()): Pin>.await; | ^^^^^^^^^^^^^^^^-^^^^^^^^^^^^ @@ -123,41 +183,41 @@ LL | Box::pin(noop()): Pin>.await; = note: see issue #23416 for more information error: casts cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:137:5 + --> $DIR/issue-35813-postfix-after-cast.rs:160:5 | LL | Foo::default() as Foo.bar; | ^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default() as Foo)` error: casts cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:139:5 + --> $DIR/issue-35813-postfix-after-cast.rs:162:5 | LL | Foo::default(): Foo.bar; | ^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default(): Foo)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:54:9 + --> $DIR/issue-35813-postfix-after-cast.rs:77:9 | LL | if true { 33 } else { 44 } as i32.max(0), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 } as i32)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:56:9 + --> $DIR/issue-35813-postfix-after-cast.rs:79:9 | LL | if true { 33 } else { 44 }: i32.max(0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 }: i32)` error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:101:13 + --> $DIR/issue-35813-postfix-after-cast.rs:124:13 | LL | drop as F(); | ^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:103:15 + --> $DIR/issue-35813-postfix-after-cast.rs:126:15 | LL | drop_ptr: F(); | ^^^ only `Fn` traits may use parentheses -error: aborting due to 25 previous errors +error: aborting due to 35 previous errors For more information about this error, try `rustc --explain E0214`. From f434c6e636eda6c6c4fe167eee5b2549f8524ec7 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 22 Feb 2020 12:33:06 -0800 Subject: [PATCH 11/23] Use multipart suggestion This is a modified version of estebank's suggestion, with a bit of extra cleanup now that we don't need the different cases for if we can turn a span into a string or not. --- src/librustc_parse/parser/expr.rs | 22 +- .../parser/issue-35813-postfix-after-cast.rs | 7 + .../issue-35813-postfix-after-cast.stderr | 275 ++++++++++++++---- 3 files changed, 238 insertions(+), 66 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 3d0f746d3955c..12729019e9bdc 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -648,8 +648,6 @@ impl<'a> Parser<'a> { if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) || after_hash != before_hash { - let expr_str = self.span_to_snippet(span); - let msg = format!( "casts cannot be followed by {}", match with_postfix.kind { @@ -663,22 +661,20 @@ impl<'a> Parser<'a> { } ); let mut err = self.struct_span_err(span, &msg); - let suggestion = "try surrounding the expression in parentheses"; // if type ascription is "likely an error", the user will already be getting a useful // help message, and doesn't need a second. if self.last_type_ascription.map_or(false, |last_ascription| last_ascription.1) { self.maybe_annotate_with_ascription(&mut err, false); } else { - if let Ok(expr_str) = expr_str { - err.span_suggestion( - span, - suggestion, - format!("({})", expr_str), - Applicability::MachineApplicable, - ); - } else { - err.span_help(span, suggestion); - } + let suggestions = vec![ + (span.shrink_to_lo(), "(".to_string()), + (span.shrink_to_hi(), ")".to_string()), + ]; + err.multipart_suggestion( + "try surrounding the expression in parentheses", + suggestions, + Applicability::MachineApplicable, + ); } err.emit(); }; diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs index 5c6e0ce5024d9..e725aa5d73d1f 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.rs +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs @@ -58,6 +58,13 @@ pub fn cast_cast_method_call() { //~^ ERROR: casts cannot be followed by a method call } +pub fn multiline_error() { + let _ = 0 + as i32 + .count_ones(); + //~^^^ ERROR: casts cannot be followed by a method call +} + // this tests that the precedence for `!x as Y.Z` is still what we expect pub fn precedence() { let x: i32 = &vec![1, 2, 3] as &Vec[0]; diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr index 42b614edf7638..255e9f409218b 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr @@ -2,148 +2,282 @@ error: casts cannot be followed by indexing --> $DIR/issue-35813-postfix-after-cast.rs:10:5 | LL | vec![1, 2, 3] as Vec[0]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(vec![1, 2, 3] as Vec)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (vec![1, 2, 3] as Vec)[0]; + | ^ ^ error: casts cannot be followed by indexing --> $DIR/issue-35813-postfix-after-cast.rs:12:5 | LL | vec![1, 2, 3]: Vec[0]; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(vec![1, 2, 3]: Vec)` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (vec![1, 2, 3]: Vec)[0]; + | ^ ^ error: casts cannot be followed by indexing --> $DIR/issue-35813-postfix-after-cast.rs:17:5 | LL | (&[0]) as &[i32][0]; - | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `((&[0]) as &[i32])` + | ^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | ((&[0]) as &[i32])[0]; + | ^ ^ error: casts cannot be followed by indexing --> $DIR/issue-35813-postfix-after-cast.rs:19:5 | LL | (&[0i32]): &[i32; 1][0]; - | ^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `((&[0i32]): &[i32; 1])` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | ((&[0i32]): &[i32; 1])[0]; + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:39:13 | LL | let _ = 0i32: i32: i32.count_ones(); - | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32)` + | ^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32: i32).count_ones(); + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:41:13 | LL | let _ = 0 as i32: i32.count_ones(); - | ^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32: i32)` + | ^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32: i32).count_ones(); + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:43:13 | LL | let _ = 0i32: i32 as i32.count_ones(); - | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32 as i32)` + | ^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32 as i32).count_ones(); + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:45:13 | LL | let _ = 0 as i32 as i32.count_ones(); - | ^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32 as i32)` + | ^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32 as i32).count_ones(); + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:47:13 | LL | let _ = 0i32: i32: i32 as u32 as i32.count_ones(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32 as u32 as i32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32: i32 as u32 as i32).count_ones(); + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:49:13 | LL | let _ = 0i32: i32.count_ones(): u32; - | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32)` + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32).count_ones(): u32; + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:51:13 | LL | let _ = 0 as i32.count_ones(): u32; - | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + | ^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32).count_ones(): u32; + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:53:13 | LL | let _ = 0i32: i32.count_ones() as u32; - | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32)` + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32).count_ones() as u32; + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:55:13 | LL | let _ = 0 as i32.count_ones() as u32; - | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + | ^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32).count_ones() as u32; + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:57:13 | LL | let _ = 0i32: i32: i32.count_ones() as u32 as i32; - | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32)` + | ^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32: i32).count_ones() as u32 as i32; + | ^ ^ + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:62:13 + | +LL | let _ = 0 + | _____________^ +LL | | as i32 + | |______________^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 +LL | as i32) + | error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:63:18 + --> $DIR/issue-35813-postfix-after-cast.rs:70:18 | LL | let x: i32 = &vec![1, 2, 3] as &Vec[0]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&vec![1, 2, 3] as &Vec)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let x: i32 = (&vec![1, 2, 3] as &Vec)[0]; + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:68:5 + --> $DIR/issue-35813-postfix-after-cast.rs:75:5 | LL | 0 as i32.max(0); - | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + | ^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (0 as i32).max(0); + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:70:5 + --> $DIR/issue-35813-postfix-after-cast.rs:77:5 | LL | 0: i32.max(0); - | ^^^^^^ help: try surrounding the expression in parentheses: `(0: i32)` + | ^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (0: i32).max(0); + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:85:8 + --> $DIR/issue-35813-postfix-after-cast.rs:92:8 | LL | if 5u64 as i32.max(0) == 0 { - | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as i32)` + | ^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | if (5u64 as i32).max(0) == 0 { + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:88:8 + --> $DIR/issue-35813-postfix-after-cast.rs:95:8 | LL | if 5u64: u64.max(0) == 0 { - | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | if (5u64: u64).max(0) == 0 { + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:95:9 + --> $DIR/issue-35813-postfix-after-cast.rs:102:9 | LL | 5u64 as u32.max(0) == 0 - | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as u32)` + | ^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (5u64 as u32).max(0) == 0 + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:99:9 + --> $DIR/issue-35813-postfix-after-cast.rs:106:9 | LL | 5u64: u64.max(0) == 0 - | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (5u64: u64).max(0) == 0 + | ^ ^ error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:104:24 + --> $DIR/issue-35813-postfix-after-cast.rs:111:24 | LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); - | ^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1,2,3] as &[i32])` + | ^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | static bar: &[i32] = &((&[1,2,3] as &[i32])[0..1]); + | ^ ^ error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:107:25 + --> $DIR/issue-35813-postfix-after-cast.rs:114:25 | LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1i32,2,3]: &[i32; 3])` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | static bar2: &[i32] = &((&[1i32,2,3]: &[i32; 3])[0..1]); + | ^ ^ error: casts cannot be followed by ? - --> $DIR/issue-35813-postfix-after-cast.rs:112:5 + --> $DIR/issue-35813-postfix-after-cast.rs:119:5 | LL | Err(0u64) as Result?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Err(0u64) as Result)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Err(0u64) as Result)?; + | ^ ^ error: casts cannot be followed by ? - --> $DIR/issue-35813-postfix-after-cast.rs:114:5 + --> $DIR/issue-35813-postfix-after-cast.rs:121:5 | LL | Err(0u64): Result?; | ^^^^^^^^^-^^^^^^^^^^^^^^^^ @@ -154,25 +288,40 @@ LL | Err(0u64): Result?; = note: see issue #23416 for more information error: casts cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:138:5 + --> $DIR/issue-35813-postfix-after-cast.rs:145:5 | LL | drop as fn(u8)(0); - | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop as fn(u8))` + | ^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (drop as fn(u8))(0); + | ^ ^ error: casts cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:140:5 + --> $DIR/issue-35813-postfix-after-cast.rs:147:5 | LL | drop_ptr: fn(u8)(0); - | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop_ptr: fn(u8))` + | ^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (drop_ptr: fn(u8))(0); + | ^ ^ error: casts cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:145:5 + --> $DIR/issue-35813-postfix-after-cast.rs:152:5 | LL | Box::pin(noop()) as Pin>>.await; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Box::pin(noop()) as Pin>>)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Box::pin(noop()) as Pin>>).await; + | ^ ^ error: casts cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:148:5 + --> $DIR/issue-35813-postfix-after-cast.rs:155:5 | LL | Box::pin(noop()): Pin>.await; | ^^^^^^^^^^^^^^^^-^^^^^^^^^^^^ @@ -183,41 +332,61 @@ LL | Box::pin(noop()): Pin>.await; = note: see issue #23416 for more information error: casts cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:160:5 + --> $DIR/issue-35813-postfix-after-cast.rs:167:5 | LL | Foo::default() as Foo.bar; - | ^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default() as Foo)` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Foo::default() as Foo).bar; + | ^ ^ error: casts cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:162:5 + --> $DIR/issue-35813-postfix-after-cast.rs:169:5 | LL | Foo::default(): Foo.bar; - | ^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default(): Foo)` + | ^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Foo::default(): Foo).bar; + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:77:9 + --> $DIR/issue-35813-postfix-after-cast.rs:84:9 | LL | if true { 33 } else { 44 } as i32.max(0), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 } as i32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (if true { 33 } else { 44 } as i32).max(0), + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:79:9 + --> $DIR/issue-35813-postfix-after-cast.rs:86:9 | LL | if true { 33 } else { 44 }: i32.max(0) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 }: i32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (if true { 33 } else { 44 }: i32).max(0) + | ^ ^ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:124:13 + --> $DIR/issue-35813-postfix-after-cast.rs:131:13 | LL | drop as F(); | ^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:126:15 + --> $DIR/issue-35813-postfix-after-cast.rs:133:15 | LL | drop_ptr: F(); | ^^^ only `Fn` traits may use parentheses -error: aborting due to 35 previous errors +error: aborting due to 36 previous errors For more information about this error, try `rustc --explain E0214`. From 453c5051476fab4d09f6d16bdbf37043c5c26a27 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 24 Feb 2020 22:11:15 -0800 Subject: [PATCH 12/23] Replace ptr hashing with ptr casting Implementes suggeseted changes by Centril. This checks whether the memory location of the cast remains the same after atttempting to parse a postfix operator after a cast has been parsed. If the address is not the same, an illegal postfix operator was parsed. Previously the code generated a hash of the pointer, which was overly complex and inefficent. Casting the pointers and comparing them is simpler and more effcient. --- src/librustc_parse/parser/expr.rs | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 12729019e9bdc..36ed075cebd2f 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -628,26 +628,17 @@ impl<'a> Parser<'a> { &mut self, cast_expr: P, ) -> PResult<'a, P> { - use std::collections::hash_map::DefaultHasher; - use std::hash::Hasher; - // Hash the memory location of expr before parsing any following postfix operators. - // This will be compared with the hash of the output expression. + // Save the memory location of expr before parsing any following postfix operators. + // This will be compared with the memory location of the output expression. // If they different we can assume we parsed another expression because the existing expression is not reallocated. - let mut before_hasher = DefaultHasher::new(); - std::ptr::hash(&*cast_expr, &mut before_hasher); - let before_hash = before_hasher.finish(); + let addr_before = &*cast_expr as *const _ as usize; let span = cast_expr.span; let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?; - - let mut after_hasher = DefaultHasher::new(); - std::ptr::hash(&*with_postfix, &mut after_hasher); - let after_hash = after_hasher.finish(); + let changed = addr_before != &*with_postfix as *const _ as usize; // Check if an illegal postfix operator has been added after the cast. // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator. - if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) - || after_hash != before_hash - { + if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) || changed { let msg = format!( "casts cannot be followed by {}", match with_postfix.kind { @@ -661,7 +652,7 @@ impl<'a> Parser<'a> { } ); let mut err = self.struct_span_err(span, &msg); - // if type ascription is "likely an error", the user will already be getting a useful + // If type ascription is "likely an error", the user will already be getting a useful // help message, and doesn't need a second. if self.last_type_ascription.map_or(false, |last_ascription| last_ascription.1) { self.maybe_annotate_with_ascription(&mut err, false); From d3e5177f816d723cbce31ae7a7779feca8a69724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 3 Mar 2020 01:19:00 +0100 Subject: [PATCH 13/23] Use .next() instead of .nth(0) on iterators. --- src/librustc/mir/mod.rs | 2 +- src/librustc/ty/util.rs | 2 +- src/librustc_mir/transform/simplify.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_mir_build/hair/pattern/_match.rs | 2 +- src/librustc_parse/parser/expr.rs | 2 +- src/librustc_parse/parser/pat.rs | 2 +- src/librustc_parse/parser/ty.rs | 2 +- src/librustc_span/source_map.rs | 6 +++--- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/tools/unicode-table-generator/src/main.rs | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 668240ab42b4c..bb2d57c856d4b 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1446,7 +1446,7 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { match successor_count { 0 => Ok(()), - 1 => write!(fmt, " -> {:?}", self.successors().nth(0).unwrap()), + 1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()), _ => { write!(fmt, " -> [")?; diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 7b1f821877baa..87dcc617fa289 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -357,7 +357,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut dtor_did = None; let ty = self.type_of(adt_did); self.for_each_relevant_impl(drop_trait, ty, |impl_did| { - if let Some(item) = self.associated_items(impl_did).in_definition_order().nth(0) { + if let Some(item) = self.associated_items(impl_did).in_definition_order().next() { if validate(self, impl_did).is_ok() { dtor_did = Some(item.def_id); } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index ddf8d73e5481f..597d3f0237a71 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -230,7 +230,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { }; let first_succ = { - if let Some(&first_succ) = terminator.successors().nth(0) { + if let Some(&first_succ) = terminator.successors().next() { if terminator.successors().all(|s| *s == first_succ) { let count = terminator.successors().count(); self.pred_count[first_succ] -= (count - 1) as u32; diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index f7239ae55faa2..a928ab6a00979 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -549,7 +549,7 @@ where debug!("destructor_call_block({:?}, {:?})", self, succ); let tcx = self.tcx(); let drop_trait = tcx.lang_items().drop_trait().unwrap(); - let drop_fn = tcx.associated_items(drop_trait).in_definition_order().nth(0).unwrap(); + let drop_fn = tcx.associated_items(drop_trait).in_definition_order().next().unwrap(); let ty = self.place_ty(self.place); let substs = tcx.mk_substs_trait(ty, &[]); diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 90e4f53647846..64960a0da9cde 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -1000,7 +1000,7 @@ impl<'tcx> Constructor<'tcx> { PatKind::Leaf { subpatterns } } } - ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.nth(0).unwrap() }, + ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.next().unwrap() }, ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty), _ => PatKind::Wild, }, diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 18ddd23588e48..14366eb4e8748 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -955,7 +955,7 @@ impl<'a> Parser<'a> { }; let kind = if es.len() == 1 && !trailing_comma { // `(e)` is parenthesized `e`. - ExprKind::Paren(es.into_iter().nth(0).unwrap()) + ExprKind::Paren(es.into_iter().next().unwrap()) } else { // `(e,)` is a tuple with only one field, `e`. ExprKind::Tup(es) diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index 45d1aacdd3cc6..4c041fd669d67 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -479,7 +479,7 @@ impl<'a> Parser<'a> { // Here, `(pat,)` is a tuple pattern. // For backward compatibility, `(..)` is a tuple pattern as well. Ok(if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) { - PatKind::Paren(fields.into_iter().nth(0).unwrap()) + PatKind::Paren(fields.into_iter().next().unwrap()) } else { PatKind::Tuple(fields) }) diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 3d2b0c014ac49..c4469331b6669 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -198,7 +198,7 @@ impl<'a> Parser<'a> { })?; if ts.len() == 1 && !trailing { - let ty = ts.into_iter().nth(0).unwrap().into_inner(); + let ty = ts.into_iter().next().unwrap().into_inner(); let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus(); match ty.kind { // `(TY_BOUND_NOPAREN) + BOUND + ...`. diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index 39601ad76222c..798600fc68275 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -620,7 +620,7 @@ impl SourceMap { /// if no character could be found or if an error occurred while retrieving the code snippet. pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span { if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(c).nth(0).unwrap_or("").trim_start(); + let prev_source = prev_source.rsplit(c).next().unwrap_or("").trim_start(); if !prev_source.is_empty() && !prev_source.contains('\n') { return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); } @@ -640,7 +640,7 @@ impl SourceMap { for ws in &[" ", "\t", "\n"] { let pat = pat.to_owned() + ws; if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(&pat).nth(0).unwrap_or("").trim_start(); + let prev_source = prev_source.rsplit(&pat).next().unwrap_or("").trim_start(); if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) { return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); } @@ -655,7 +655,7 @@ impl SourceMap { pub fn span_until_char(&self, sp: Span, c: char) -> Span { match self.span_to_snippet(sp) { Ok(snippet) => { - let snippet = snippet.split(c).nth(0).unwrap_or("").trim_end(); + let snippet = snippet.split(c).next().unwrap_or("").trim_end(); if !snippet.is_empty() && !snippet.contains('\n') { sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32)) } else { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 816de5dadbc15..8689db1b1eb56 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -675,7 +675,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The `Future` trait has only one associted item, `Output`, // so check that this is what we see. let output_assoc_item = - self.tcx.associated_items(future_trait).in_definition_order().nth(0).unwrap().def_id; + self.tcx.associated_items(future_trait).in_definition_order().next().unwrap().def_id; if output_assoc_item != predicate.projection_ty.item_def_id { span_bug!( cause_span, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b7353c6af267a..f00476fb991f2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5244,7 +5244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .associated_items(future_trait) .in_definition_order() - .nth(0) + .next() .unwrap() .def_id; let predicate = diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index be8508e3973a2..839d914baa954 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -147,7 +147,7 @@ fn main() { eprintln!("Must provide path to write unicode tables to"); eprintln!( "e.g. {} src/libcore/unicode/unicode_data.rs", - std::env::args().nth(0).unwrap_or_default() + std::env::args().next().unwrap_or_default() ); std::process::exit(1); }); From 54561148581f002793ab42893de4e3f7c26bd7ed Mon Sep 17 00:00:00 2001 From: Matthew Kuo Date: Wed, 4 Mar 2020 01:09:53 -0600 Subject: [PATCH 14/23] test(pattern): add tests for combinations of pattern features Reference issue #67311 Tests combinations of the following pattern features: - bindings_after_at - or_patterns - slice_patterns - box_patterns --- src/test/ui/or-patterns/box-patterns.rs | 37 +++++++++++++++ src/test/ui/or-patterns/slice-patterns.rs | 42 +++++++++++++++++ .../pattern/bindings-after-at/box-patterns.rs | 36 +++++++++++++++ .../or-patterns-box-patterns.rs | 45 +++++++++++++++++++ .../or-patterns-slice-patterns.rs | 43 ++++++++++++++++++ .../pattern/bindings-after-at/or-patterns.rs | 40 +++++++++++++++++ .../bindings-after-at/slice-patterns.rs | 40 +++++++++++++++++ 7 files changed, 283 insertions(+) create mode 100644 src/test/ui/or-patterns/box-patterns.rs create mode 100644 src/test/ui/or-patterns/slice-patterns.rs create mode 100644 src/test/ui/pattern/bindings-after-at/box-patterns.rs create mode 100644 src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs create mode 100644 src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs create mode 100644 src/test/ui/pattern/bindings-after-at/or-patterns.rs create mode 100644 src/test/ui/pattern/bindings-after-at/slice-patterns.rs diff --git a/src/test/ui/or-patterns/box-patterns.rs b/src/test/ui/or-patterns/box-patterns.rs new file mode 100644 index 0000000000000..aafd47993836c --- /dev/null +++ b/src/test/ui/or-patterns/box-patterns.rs @@ -0,0 +1,37 @@ +// Test or-patterns with box-patterns + +// run-pass + +#![feature(or_patterns)] +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(x: Option>) -> MatchArm { + match x { + Some(box Test::Foo | box Test::Bar) => MatchArm::Arm(0), + Some(box Test::Baz) => MatchArm::Arm(1), + Some(_) => MatchArm::Arm(2), + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Box::new(Test::Foo))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Bar))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Baz))), MatchArm::Arm(1)); + assert_eq!(test(Some(Box::new(Test::Qux))), MatchArm::Arm(2)); + assert_eq!(test(None), MatchArm::Wild); +} diff --git a/src/test/ui/or-patterns/slice-patterns.rs b/src/test/ui/or-patterns/slice-patterns.rs new file mode 100644 index 0000000000000..2f2e865d98528 --- /dev/null +++ b/src/test/ui/or-patterns/slice-patterns.rs @@ -0,0 +1,42 @@ +// Test or-patterns with slice-patterns + +// run-pass + +#![feature(or_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: &[Option]) -> MatchArm { + match foo { + [.., Some(Test::Foo | Test::Qux)] => MatchArm::Arm(0), + [Some(Test::Foo), .., Some(Test::Bar | Test::Baz)] => MatchArm::Arm(1), + [.., Some(Test::Bar | Test::Baz), _] => MatchArm::Arm(2), + _ => MatchArm::Wild, + } +} + +fn main() { + let foo = vec![ + Some(Test::Foo), + Some(Test::Bar), + Some(Test::Baz), + Some(Test::Qux), + ]; + + assert_eq!(test(&foo), MatchArm::Arm(0)); + assert_eq!(test(&foo[..3]), MatchArm::Arm(1)); + assert_eq!(test(&foo[1..3]), MatchArm::Arm(2)); + assert_eq!(test(&foo[4..]), MatchArm::Wild); +} diff --git a/src/test/ui/pattern/bindings-after-at/box-patterns.rs b/src/test/ui/pattern/bindings-after-at/box-patterns.rs new file mode 100644 index 0000000000000..ef9669a6b9e5a --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/box-patterns.rs @@ -0,0 +1,36 @@ +// Test bindings-after-at with box-patterns + +// run-pass + +#![feature(bindings_after_at)] +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +fn test(x: Option>) -> MatchArm { + match x { + ref bar @ Some(box n) if n > 0 => { + // bar is a &Option> + assert_eq!(bar, &x); + + MatchArm::Arm(0) + }, + Some(ref bar @ box n) if n < 0 => { + // bar is a &Box here + assert_eq!(**bar, n); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Box::new(2))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(-1))), MatchArm::Arm(1)); + assert_eq!(test(Some(Box::new(0))), MatchArm::Wild); +} diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs new file mode 100644 index 0000000000000..ca8826f03f1ad --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs @@ -0,0 +1,45 @@ +// Test bindings-after-at with or-patterns and box-patterns + +// run-pass + +#![feature(bindings_after_at)] +#![feature(or_patterns)] +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: Option>) -> MatchArm { + match foo { + ref bar @ Some(box Test::Foo | box Test::Bar) => { + assert_eq!(bar, &foo); + + MatchArm::Arm(0) + }, + Some(ref bar @ box Test::Baz | ref bar @ box Test::Qux) => { + assert!(**bar == Test::Baz || **bar == Test::Qux); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Box::new(Test::Foo))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Bar))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Baz))), MatchArm::Arm(1)); + assert_eq!(test(Some(Box::new(Test::Qux))), MatchArm::Arm(1)); + assert_eq!(test(None), MatchArm::Wild); +} diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs new file mode 100644 index 0000000000000..154df74cc33d8 --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs @@ -0,0 +1,43 @@ +// Test bindings-after-at with or-patterns and slice-patterns + +// run-pass + +#![feature(bindings_after_at)] +#![feature(or_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: &[Option]) -> MatchArm { + match foo { + bar @ [Some(Test::Foo), .., Some(Test::Foo | Test::Qux)] => { + assert_eq!(bar, foo); + + MatchArm::Arm(0) + }, + [.., bar @ Some(Test::Bar | Test::Qux), _] => { + assert!(bar == &Some(Test::Bar) || bar == &Some(Test::Qux)); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + let foo = vec![Some(Test::Foo), Some(Test::Bar), Some(Test::Baz), Some(Test::Qux)]; + assert_eq!(test(&foo), MatchArm::Arm(0)); + assert_eq!(test(&foo[..3]), MatchArm::Arm(1)); + assert_eq!(test(&foo[1..2]), MatchArm::Wild); +} diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns.rs new file mode 100644 index 0000000000000..a0e14004ab1b0 --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/or-patterns.rs @@ -0,0 +1,40 @@ +// Test bindings-after-at with or-patterns + +// run-pass + +#![feature(bindings_after_at)] +#![feature(or_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: Option) -> MatchArm { + match foo { + bar @ Some(Test::Foo | Test::Bar) => { + assert!(bar == Some(Test::Foo) || bar == Some(Test::Bar)); + + MatchArm::Arm(0) + }, + Some(_) => MatchArm::Arm(1), + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Test::Foo)), MatchArm::Arm(0)); + assert_eq!(test(Some(Test::Bar)), MatchArm::Arm(0)); + assert_eq!(test(Some(Test::Baz)), MatchArm::Arm(1)); + assert_eq!(test(Some(Test::Qux)), MatchArm::Arm(1)); + assert_eq!(test(None), MatchArm::Wild); +} diff --git a/src/test/ui/pattern/bindings-after-at/slice-patterns.rs b/src/test/ui/pattern/bindings-after-at/slice-patterns.rs new file mode 100644 index 0000000000000..7e50527af0b97 --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/slice-patterns.rs @@ -0,0 +1,40 @@ +// Test bindings-after-at with slice-patterns + +// run-pass + +#![feature(bindings_after_at)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +fn test(foo: &[i32]) -> MatchArm { + match foo { + [bar @ .., n] if n == &5 => { + for i in bar { + assert!(i < &5); + } + + MatchArm::Arm(0) + }, + bar @ [x0, .., xn] => { + assert_eq!(x0, &1); + assert_eq!(x0, &1); + assert_eq!(xn, &4); + assert_eq!(bar, &[1, 2, 3, 4]); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + let foo = vec![1, 2, 3, 4, 5]; + + assert_eq!(test(&foo), MatchArm::Arm(0)); + assert_eq!(test(&foo[..4]), MatchArm::Arm(1)); + assert_eq!(test(&foo[0..1]), MatchArm::Wild); +} From b4788a739b5dd040a969135bf46dc633c39fce16 Mon Sep 17 00:00:00 2001 From: Matthew Kuo Date: Wed, 4 Mar 2020 01:33:32 -0600 Subject: [PATCH 15/23] test(pattern): harden tests for or-patterns with slice-patterns Some of the nested OR paths were being missed --- src/test/ui/or-patterns/slice-patterns.rs | 14 ++++++++++++-- .../or-patterns-slice-patterns.rs | 17 +++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/test/ui/or-patterns/slice-patterns.rs b/src/test/ui/or-patterns/slice-patterns.rs index 2f2e865d98528..2526f048655ae 100644 --- a/src/test/ui/or-patterns/slice-patterns.rs +++ b/src/test/ui/or-patterns/slice-patterns.rs @@ -20,8 +20,8 @@ enum Test { fn test(foo: &[Option]) -> MatchArm { match foo { - [.., Some(Test::Foo | Test::Qux)] => MatchArm::Arm(0), - [Some(Test::Foo), .., Some(Test::Bar | Test::Baz)] => MatchArm::Arm(1), + [.., Some(Test::Qux | Test::Foo)] => MatchArm::Arm(0), + [Some(Test::Foo), .., Some(Test::Baz | Test::Bar)] => MatchArm::Arm(1), [.., Some(Test::Bar | Test::Baz), _] => MatchArm::Arm(2), _ => MatchArm::Wild, } @@ -35,8 +35,18 @@ fn main() { Some(Test::Qux), ]; + // path 1a assert_eq!(test(&foo), MatchArm::Arm(0)); + // path 1b + assert_eq!(test(&[Some(Test::Bar), Some(Test::Foo)]), MatchArm::Arm(0)); + // path 2a assert_eq!(test(&foo[..3]), MatchArm::Arm(1)); + // path 2b + assert_eq!(test(&[Some(Test::Foo), Some(Test::Foo), Some(Test::Bar)]), MatchArm::Arm(1)); + // path 3a assert_eq!(test(&foo[1..3]), MatchArm::Arm(2)); + // path 3b + assert_eq!(test(&[Some(Test::Bar), Some(Test::Baz), Some(Test::Baz), Some(Test::Bar)]), MatchArm::Arm(2)); + // path 4 assert_eq!(test(&foo[4..]), MatchArm::Wild); } diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs index 154df74cc33d8..65c2b3741b3e3 100644 --- a/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs +++ b/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs @@ -21,7 +21,7 @@ enum Test { fn test(foo: &[Option]) -> MatchArm { match foo { - bar @ [Some(Test::Foo), .., Some(Test::Foo | Test::Qux)] => { + bar @ [Some(Test::Foo), .., Some(Test::Qux | Test::Foo)] => { assert_eq!(bar, foo); MatchArm::Arm(0) @@ -36,8 +36,21 @@ fn test(foo: &[Option]) -> MatchArm { } fn main() { - let foo = vec![Some(Test::Foo), Some(Test::Bar), Some(Test::Baz), Some(Test::Qux)]; + let foo = vec![ + Some(Test::Foo), + Some(Test::Bar), + Some(Test::Baz), + Some(Test::Qux), + ]; + + // path 1a assert_eq!(test(&foo), MatchArm::Arm(0)); + // path 1b + assert_eq!(test(&[Some(Test::Foo), Some(Test::Bar), Some(Test::Foo)]), MatchArm::Arm(0)); + // path 2a assert_eq!(test(&foo[..3]), MatchArm::Arm(1)); + // path 2b + assert_eq!(test(&[Some(Test::Bar), Some(Test::Qux), Some(Test::Baz)]), MatchArm::Arm(1)); + // path 3 assert_eq!(test(&foo[1..2]), MatchArm::Wild); } From ea7b3c3c7bfbde2fc900f686b2dcd6ef03fcc510 Mon Sep 17 00:00:00 2001 From: Matthew Kuo Date: Wed, 4 Mar 2020 02:05:23 -0600 Subject: [PATCH 16/23] fix tidy error --- src/test/ui/or-patterns/slice-patterns.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/or-patterns/slice-patterns.rs b/src/test/ui/or-patterns/slice-patterns.rs index 2526f048655ae..05c907e824679 100644 --- a/src/test/ui/or-patterns/slice-patterns.rs +++ b/src/test/ui/or-patterns/slice-patterns.rs @@ -46,7 +46,8 @@ fn main() { // path 3a assert_eq!(test(&foo[1..3]), MatchArm::Arm(2)); // path 3b - assert_eq!(test(&[Some(Test::Bar), Some(Test::Baz), Some(Test::Baz), Some(Test::Bar)]), MatchArm::Arm(2)); + assert_eq!(test(&[Some(Test::Bar), Some(Test::Baz), Some(Test::Baz), Some(Test::Bar)]), + MatchArm::Arm(2)); // path 4 assert_eq!(test(&foo[4..]), MatchArm::Wild); } From 53be0ccbc913f05c81f1762fd60512e3f57ab5c7 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 4 Mar 2020 10:34:24 -0800 Subject: [PATCH 17/23] Use subslice patterns in slice methods For all of the methods that pick off the first or last element, we can use subslice patterns to implement them directly, rather than relying on deeper indexing function calls. At a minimum, this means the generated code will rely less on inlining for performance, but in some cases it also optimizes better. --- src/libcore/slice/mod.rs | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 1670c8418421f..0e12e6360da95 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -103,7 +103,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn first(&self) -> Option<&T> { - self.get(0) + if let [first, ..] = self { Some(first) } else { None } } /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty. @@ -121,7 +121,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn first_mut(&mut self) -> Option<&mut T> { - self.get_mut(0) + if let [first, ..] = self { Some(first) } else { None } } /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. @@ -139,7 +139,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[inline] pub fn split_first(&self) -> Option<(&T, &[T])> { - if self.is_empty() { None } else { Some((&self[0], &self[1..])) } + if let [first, tail @ ..] = self { Some((first, tail)) } else { None } } /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. @@ -159,12 +159,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[inline] pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { - if self.is_empty() { - None - } else { - let split = self.split_at_mut(1); - Some((&mut split.0[0], split.1)) - } + if let [first, tail @ ..] = self { Some((first, tail)) } else { None } } /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. @@ -182,8 +177,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[inline] pub fn split_last(&self) -> Option<(&T, &[T])> { - let len = self.len(); - if len == 0 { None } else { Some((&self[len - 1], &self[..(len - 1)])) } + if let [init @ .., last] = self { Some((last, init)) } else { None } } /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. @@ -203,13 +197,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[inline] pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { - let len = self.len(); - if len == 0 { - None - } else { - let split = self.split_at_mut(len - 1); - Some((&mut split.1[0], split.0)) - } + if let [init @ .., last] = self { Some((last, init)) } else { None } } /// Returns the last element of the slice, or `None` if it is empty. @@ -226,8 +214,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn last(&self) -> Option<&T> { - let last_idx = self.len().checked_sub(1)?; - self.get(last_idx) + if let [.., last] = self { Some(last) } else { None } } /// Returns a mutable pointer to the last item in the slice. @@ -245,8 +232,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn last_mut(&mut self) -> Option<&mut T> { - let last_idx = self.len().checked_sub(1)?; - self.get_mut(last_idx) + if let [.., last] = self { Some(last) } else { None } } /// Returns a reference to an element or subslice depending on the type of From 9afbf28ef607b769dc666d93f371459aa727f1d7 Mon Sep 17 00:00:00 2001 From: Dylan Nugent Date: Thu, 5 Mar 2020 21:55:36 -0500 Subject: [PATCH 18/23] Update deprecation version to 1.42 for Error::description Error::description is deprecated as of version 1.42, as the commit was not in the release for 1.41. --- src/libstd/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index b480581e21ba9..3f6501bc7b4f6 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -135,7 +135,7 @@ pub trait Error: Debug + Display { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.41.0", reason = "use the Display impl or to_string()")] + #[rustc_deprecated(since = "1.42.0", reason = "use the Display impl or to_string()")] fn description(&self) -> &str { "description() is deprecated; use Display" } From 2d0c5b4337ff24ef12b3ed7242a6bbf9f7567ce1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 3 Mar 2020 23:22:32 +0300 Subject: [PATCH 19/23] rustc_expand: Factor out `Annotatable::into_tokens` to a separate method --- src/librustc_expand/base.rs | 27 ++++++++++++++++++++++++- src/librustc_expand/expand.rs | 37 ++++++----------------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index 9258b59f79be8..f15e626c2783b 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::{self, Attribute, Name, NodeId, PatKind}; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token; -use rustc_ast::tokenstream::{self, TokenStream}; +use rustc_ast::tokenstream::{self, TokenStream, TokenTree}; use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability}; use rustc_data_structures::fx::FxHashMap; @@ -118,6 +118,31 @@ impl Annotatable { } } + crate fn into_tokens(self) -> TokenStream { + // `Annotatable` can be converted into tokens directly, but we + // are packing it into a nonterminal as a piece of AST to make + // the produced token stream look nicer in pretty-printed form. + let nt = match self { + Annotatable::Item(item) => token::NtItem(item), + Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => { + token::NtItem(P(item.and_then(ast::AssocItem::into_item))) + } + Annotatable::ForeignItem(item) => { + token::NtItem(P(item.and_then(ast::ForeignItem::into_item))) + } + Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), + Annotatable::Expr(expr) => token::NtExpr(expr), + Annotatable::Arm(..) + | Annotatable::Field(..) + | Annotatable::FieldPat(..) + | Annotatable::GenericParam(..) + | Annotatable::Param(..) + | Annotatable::StructField(..) + | Annotatable::Variant(..) => panic!("unexpected annotatable"), + }; + TokenTree::token(token::Interpolated(Lrc::new(nt)), DUMMY_SP).into() + } + pub fn expect_item(self) -> P { match self { Annotatable::Item(i) => i, diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index b16659725db73..effa89e8bfb21 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -10,12 +10,11 @@ use rustc_ast::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind}; use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::token; -use rustc_ast::tokenstream::{TokenStream, TokenTree}; +use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::map_in_place::MapInPlace; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; -use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; use rustc_parse::configure; @@ -668,38 +667,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); - // `Annotatable` can be converted into tokens directly, but we are packing it - // into a nonterminal as a piece of AST to make the produced token stream - // look nicer in pretty-printed form. This may be no longer necessary. - let item_tok = TokenTree::token( - token::Interpolated(Lrc::new(match item { - Annotatable::Item(item) => token::NtItem(item), - Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => { - token::NtItem(P(item.and_then(ast::AssocItem::into_item))) - } - Annotatable::ForeignItem(item) => { - token::NtItem(P(item.and_then(ast::ForeignItem::into_item))) - } - Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), - Annotatable::Expr(expr) => token::NtExpr(expr), - Annotatable::Arm(..) - | Annotatable::Field(..) - | Annotatable::FieldPat(..) - | Annotatable::GenericParam(..) - | Annotatable::Param(..) - | Annotatable::StructField(..) - | Annotatable::Variant(..) => panic!("unexpected annotatable"), - })), - DUMMY_SP, - ) - .into(); - let item = attr.unwrap_normal_item(); - if let MacArgs::Eq(..) = item.args { + let tokens = item.into_tokens(); + let attr_item = attr.unwrap_normal_item(); + if let MacArgs::Eq(..) = attr_item.args { self.cx.span_err(span, "key-value macro attributes are not supported"); } let tok_result = - expander.expand(self.cx, span, item.args.inner_tokens(), item_tok); - self.parse_ast_fragment(tok_result, fragment_kind, &item.path, span) + expander.expand(self.cx, span, attr_item.args.inner_tokens(), tokens); + self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span) } SyntaxExtensionKind::LegacyAttr(expander) => { match validate_attr::parse_meta(self.cx.parse_sess, &attr) { From 83980aca2086e5c4dca5aae9a92a065a9ff4ac56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 6 Mar 2020 19:28:44 +0100 Subject: [PATCH 20/23] Don't redundantly repeat field names (clippy::redundant_field_names) --- src/liballoc/collections/linked_list.rs | 2 +- src/liballoc/vec.rs | 2 +- src/libproc_macro/diagnostic.rs | 17 +++++++---------- src/librustc/hir/map/definitions.rs | 2 +- src/librustc/mir/mono.rs | 2 +- src/librustc/traits/structural_impls.rs | 6 +++--- src/librustc/ty/context.rs | 10 +++++----- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/mod.rs | 4 ++-- src/librustc/ty/normalize_erasing_regions.rs | 5 +---- src/librustc/ty/relate.rs | 4 ++-- src/librustc/ty/sty.rs | 2 +- .../deriving/generic/mod.rs | 2 +- src/librustc_codegen_llvm/abi.rs | 2 +- src/librustc_infer/infer/at.rs | 2 +- src/librustc_infer/infer/equate.rs | 2 +- .../error_reporting/nice_region_error/util.rs | 8 ++++---- src/librustc_infer/infer/glb.rs | 2 +- src/librustc_infer/infer/lub.rs | 2 +- .../infer/region_constraints/leak_check.rs | 2 +- .../infer/region_constraints/mod.rs | 2 +- src/librustc_infer/infer/resolve.rs | 2 +- src/librustc_infer/infer/sub.rs | 2 +- src/librustc_infer/traits/mod.rs | 2 +- src/librustc_infer/traits/project.rs | 4 ++-- src/librustc_infer/traits/select.rs | 2 +- src/librustc_infer/traits/util.rs | 2 +- src/librustc_lint/levels.rs | 4 ++-- src/librustc_metadata/rmeta/encoder.rs | 2 +- .../borrow_check/diagnostics/mod.rs | 2 +- .../borrow_check/region_infer/values.rs | 2 +- .../borrow_check/universal_regions.rs | 2 +- src/librustc_mir/dataflow/graphviz.rs | 2 +- src/librustc_mir/dataflow/move_paths/builder.rs | 2 +- src/librustc_mir/interpret/place.rs | 2 +- src/librustc_mir/monomorphize/mod.rs | 2 +- src/librustc_mir/transform/add_retag.rs | 4 ++-- src/librustc_mir/transform/generator.rs | 2 +- src/librustc_mir/transform/rustc_peek.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 4 ++-- src/librustc_mir/util/pretty.rs | 2 +- .../build/matches/simplify.rs | 2 +- src/librustc_mir_build/build/matches/test.rs | 5 +---- src/librustc_mir_build/build/mod.rs | 2 +- src/librustc_mir_build/hair/cx/block.rs | 2 +- src/librustc_resolve/late.rs | 2 +- src/librustc_resolve/late/lifetimes.rs | 8 ++++---- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_save_analysis/sig.rs | 2 +- src/librustc_session/code_stats.rs | 2 +- src/librustc_span/def_id.rs | 2 +- src/librustc_ty/instance.rs | 2 +- src/librustc_typeck/check/expr.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/outlives/implicit_infer.rs | 4 ++-- src/librustdoc/doctree.rs | 2 +- src/libstd/collections/hash/map.rs | 2 +- src/libstd/io/cursor.rs | 2 +- src/libstd/io/mod.rs | 4 ++-- src/libstd/sync/mutex.rs | 2 +- src/libstd/sync/rwlock.rs | 7 ++----- 61 files changed, 88 insertions(+), 100 deletions(-) diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index a9b4e3e4706b8..8efacf108fc2f 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -959,7 +959,7 @@ impl LinkedList { let it = self.head; let old_len = self.len; - DrainFilter { list: self, it: it, pred: filter, idx: 0, old_len: old_len } + DrainFilter { list: self, it, pred: filter, idx: 0, old_len } } } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 3fd7be06fd4fc..7523d9c5ba3b1 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1659,7 +1659,7 @@ struct SetLenOnDrop<'a> { impl<'a> SetLenOnDrop<'a> { #[inline] fn new(len: &'a mut usize) -> Self { - SetLenOnDrop { local_len: *len, len: len } + SetLenOnDrop { local_len: *len, len } } #[inline] diff --git a/src/libproc_macro/diagnostic.rs b/src/libproc_macro/diagnostic.rs index fdf252e53387e..7495468a05b6c 100644 --- a/src/libproc_macro/diagnostic.rs +++ b/src/libproc_macro/diagnostic.rs @@ -55,13 +55,15 @@ pub struct Diagnostic { } macro_rules! diagnostic_child_methods { - ($spanned:ident, $regular:ident, $level:expr) => ( + ($spanned:ident, $regular:ident, $level:expr) => { /// Adds a new child diagnostic message to `self` with the level /// identified by this method's name with the given `spans` and /// `message`. #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn $spanned(mut self, spans: S, message: T) -> Diagnostic - where S: MultiSpan, T: Into + where + S: MultiSpan, + T: Into, { self.children.push(Diagnostic::spanned(spans, $level, message)); self @@ -74,7 +76,7 @@ macro_rules! diagnostic_child_methods { self.children.push(Diagnostic::new($level, message)); self } - ) + }; } /// Iterator over the children diagnostics of a `Diagnostic`. @@ -96,7 +98,7 @@ impl Diagnostic { /// Creates a new diagnostic with the given `level` and `message`. #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn new>(level: Level, message: T) -> Diagnostic { - Diagnostic { level: level, message: message.into(), spans: vec![], children: vec![] } + Diagnostic { level, message: message.into(), spans: vec![], children: vec![] } } /// Creates a new diagnostic with the given `level` and `message` pointing to @@ -107,12 +109,7 @@ impl Diagnostic { S: MultiSpan, T: Into, { - Diagnostic { - level: level, - message: message.into(), - spans: spans.into_spans(), - children: vec![], - } + Diagnostic { level, message: message.into(), spans: spans.into_spans(), children: vec![] } } diagnostic_child_methods!(span_error, error, Level::Error); diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 047ce8b8445fd..e1b5ec041db06 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -192,7 +192,7 @@ impl DefPath { } } data.reverse(); - DefPath { data: data, krate: krate } + DefPath { data, krate } } /// Returns a string representation of the `DefPath` without diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 9a3ddfb0e82c9..4f8efc1607eaa 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -258,7 +258,7 @@ pub enum Visibility { impl<'tcx> CodegenUnit<'tcx> { pub fn new(name: Symbol) -> CodegenUnit<'tcx> { - CodegenUnit { name: name, items: Default::default(), size_estimate: None } + CodegenUnit { name, items: Default::default(), size_estimate: None } } pub fn name(&self) -> Symbol { diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 63d7124ee91f9..a5efea9e5fa4d 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -532,9 +532,9 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> { nested, }) => tcx.lift(&substs).map(|substs| { traits::VtableGenerator(traits::VtableGeneratorData { - generator_def_id: generator_def_id, - substs: substs, - nested: nested, + generator_def_id, + substs, + nested, }) }), traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested }) => { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 20736b50831bb..48ef81c1d5bf7 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2256,22 +2256,22 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut { ty: ty, mutbl: hir::Mutability::Mut }) + self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Mut }) } #[inline] pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut { ty: ty, mutbl: hir::Mutability::Not }) + self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Not }) } #[inline] pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut { ty: ty, mutbl: hir::Mutability::Mut }) + self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Mut }) } #[inline] pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut { ty: ty, mutbl: hir::Mutability::Not }) + self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not }) } #[inline] @@ -2393,7 +2393,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> { - self.mk_ty(Param(ParamTy { index, name: name })) + self.mk_ty(Param(ParamTy { index, name })) } #[inline] diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 4014d1d8ae250..445df76cd32be 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -241,7 +241,7 @@ impl<'tcx> Instance<'tcx> { def_id, substs ); - Instance { def: InstanceDef::Item(def_id), substs: substs } + Instance { def: InstanceDef::Item(def_id), substs } } pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index b25fd3c61fd5d..7bcd63b965534 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -370,7 +370,7 @@ pub trait DefIdTree: Copy { impl<'tcx> DefIdTree for TyCtxt<'tcx> { fn parent(self, id: DefId) -> Option { - self.def_key(id).parent.map(|index| DefId { index: index, ..id }) + self.def_key(id).parent.map(|index| DefId { index, ..id }) } } @@ -2227,7 +2227,7 @@ impl ReprOptions { if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) { flags.insert(ReprFlags::IS_LINEAR); } - ReprOptions { int: size, align: max_align, pack: min_pack, flags: flags } + ReprOptions { int: size, align: max_align, pack: min_pack, flags } } #[inline] diff --git a/src/librustc/ty/normalize_erasing_regions.rs b/src/librustc/ty/normalize_erasing_regions.rs index dc64482907f75..cbaabd8e1f137 100644 --- a/src/librustc/ty/normalize_erasing_regions.rs +++ b/src/librustc/ty/normalize_erasing_regions.rs @@ -34,10 +34,7 @@ impl<'tcx> TyCtxt<'tcx> { if !value.has_projections() { value } else { - value.fold_with(&mut NormalizeAfterErasingRegionsFolder { - tcx: self, - param_env: param_env, - }) + value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env }) } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 3b9df72266f09..10f27bf66f383 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -287,7 +287,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { let substs = relate_substs(relation, None, a.substs, b.substs)?; - Ok(ty::TraitRef { def_id: a.def_id, substs: substs }) + Ok(ty::TraitRef { def_id: a.def_id, substs }) } } } @@ -303,7 +303,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { let substs = relate_substs(relation, None, a.substs, b.substs)?; - Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs }) + Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs }) } } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index ab2c98c89b4e6..47bf7822b1f55 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1193,7 +1193,7 @@ pub struct ParamTy { impl<'tcx> ParamTy { pub fn new(index: u32, name: Symbol) -> ParamTy { - ParamTy { index, name: name } + ParamTy { index, name } } pub fn for_self() -> ParamTy { diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index 311298c0f4083..e0c619fcbd378 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -482,7 +482,7 @@ impl<'a> TraitDef<'a> { }) .cloned(), ); - push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() }))) + push(Annotatable::Item(P(ast::Item { attrs, ..(*newitem).clone() }))) } _ => { // Non-Item derive is an error, but it should have been diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index c79d9f77e654e..470a2bb8e1ea5 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -148,7 +148,7 @@ impl LlvmType for CastTarget { .prefix .iter() .flat_map(|option_kind| { - option_kind.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx)) + option_kind.map(|kind| Reg { kind, size: self.prefix_chunk }.llvm_type(cx)) }) .chain((0..rest_count).map(|_| rest_ll_unit)) .collect(); diff --git a/src/librustc_infer/infer/at.rs b/src/librustc_infer/infer/at.rs index 156b5a8b0b50b..04f5b03c0e15c 100644 --- a/src/librustc_infer/infer/at.rs +++ b/src/librustc_infer/infer/at.rs @@ -179,7 +179,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { T: ToTrace<'tcx>, { let trace = ToTrace::to_trace(self.cause, a_is_expected, a, b); - Trace { at: self, trace: trace, a_is_expected } + Trace { at: self, trace, a_is_expected } } } diff --git a/src/librustc_infer/infer/equate.rs b/src/librustc_infer/infer/equate.rs index c1eec6832b826..bb0c124a1892d 100644 --- a/src/librustc_infer/infer/equate.rs +++ b/src/librustc_infer/infer/equate.rs @@ -19,7 +19,7 @@ impl<'combine, 'infcx, 'tcx> Equate<'combine, 'infcx, 'tcx> { fields: &'combine mut CombineFields<'infcx, 'tcx>, a_is_expected: bool, ) -> Equate<'combine, 'infcx, 'tcx> { - Equate { fields: fields, a_is_expected: a_is_expected } + Equate { fields, a_is_expected } } } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs index 4dc9096533b84..cab632935fd8e 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs @@ -77,11 +77,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if found_anon_region { let is_first = index == 0; Some(AnonymousParamInfo { - param: param, + param, param_ty: new_param_ty, - param_ty_span: param_ty_span, - bound_region: bound_region, - is_first: is_first, + param_ty_span, + bound_region, + is_first, }) } else { None diff --git a/src/librustc_infer/infer/glb.rs b/src/librustc_infer/infer/glb.rs index 2634d9cac3e99..8b26bcef57304 100644 --- a/src/librustc_infer/infer/glb.rs +++ b/src/librustc_infer/infer/glb.rs @@ -18,7 +18,7 @@ impl<'combine, 'infcx, 'tcx> Glb<'combine, 'infcx, 'tcx> { fields: &'combine mut CombineFields<'infcx, 'tcx>, a_is_expected: bool, ) -> Glb<'combine, 'infcx, 'tcx> { - Glb { fields: fields, a_is_expected: a_is_expected } + Glb { fields, a_is_expected } } } diff --git a/src/librustc_infer/infer/lub.rs b/src/librustc_infer/infer/lub.rs index b6d20ba1f3f12..20ddeec68503a 100644 --- a/src/librustc_infer/infer/lub.rs +++ b/src/librustc_infer/infer/lub.rs @@ -18,7 +18,7 @@ impl<'combine, 'infcx, 'tcx> Lub<'combine, 'infcx, 'tcx> { fields: &'combine mut CombineFields<'infcx, 'tcx>, a_is_expected: bool, ) -> Lub<'combine, 'infcx, 'tcx> { - Lub { fields: fields, a_is_expected: a_is_expected } + Lub { fields, a_is_expected } } } diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs index bbd4f3b35508e..6ebe3f5759760 100644 --- a/src/librustc_infer/infer/region_constraints/leak_check.rs +++ b/src/librustc_infer/infer/region_constraints/leak_check.rs @@ -85,7 +85,7 @@ impl<'tcx> TaintSet<'tcx> { fn new(directions: TaintDirections, initial_region: ty::Region<'tcx>) -> Self { let mut regions = FxHashSet::default(); regions.insert(initial_region); - TaintSet { directions: directions, regions: regions } + TaintSet { directions, regions } } fn fixed_point( diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs index 3f9fa6459b37f..868b95043796b 100644 --- a/src/librustc_infer/infer/region_constraints/mod.rs +++ b/src/librustc_infer/infer/region_constraints/mod.rs @@ -766,7 +766,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { b: Region<'tcx>, origin: SubregionOrigin<'tcx>, ) -> Region<'tcx> { - let vars = TwoRegions { a: a, b: b }; + let vars = TwoRegions { a, b }; if let Some(&c) = self.combine_map(t).get(&vars) { return tcx.mk_region(ReVar(c)); } diff --git a/src/librustc_infer/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs index e2207d08ee61b..562fbc246f7ee 100644 --- a/src/librustc_infer/infer/resolve.rs +++ b/src/librustc_infer/infer/resolve.rs @@ -160,7 +160,7 @@ pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: &T) -> Fix where T: TypeFoldable<'tcx>, { - let mut full_resolver = FullTypeResolver { infcx: infcx, err: None }; + let mut full_resolver = FullTypeResolver { infcx, err: None }; let result = value.fold_with(&mut full_resolver); match full_resolver.err { None => Ok(result), diff --git a/src/librustc_infer/infer/sub.rs b/src/librustc_infer/infer/sub.rs index 2b770ced42a55..f6fc38b535887 100644 --- a/src/librustc_infer/infer/sub.rs +++ b/src/librustc_infer/infer/sub.rs @@ -19,7 +19,7 @@ impl<'combine, 'infcx, 'tcx> Sub<'combine, 'infcx, 'tcx> { f: &'combine mut CombineFields<'infcx, 'tcx>, a_is_expected: bool, ) -> Sub<'combine, 'infcx, 'tcx> { - Sub { fields: f, a_is_expected: a_is_expected } + Sub { fields: f, a_is_expected } } fn with_expected_switched R>(&mut self, f: F) -> R { diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index 61702d74f1a91..800f8e91a7801 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -619,7 +619,7 @@ impl<'tcx> FulfillmentError<'tcx> { obligation: PredicateObligation<'tcx>, code: FulfillmentErrorCode<'tcx>, ) -> FulfillmentError<'tcx> { - FulfillmentError { obligation: obligation, code: code, points_at_arg_span: false } + FulfillmentError { obligation, code, points_at_arg_span: false } } } diff --git a/src/librustc_infer/traits/project.rs b/src/librustc_infer/traits/project.rs index 34889c6984bb0..78483cf6577de 100644 --- a/src/librustc_infer/traits/project.rs +++ b/src/librustc_infer/traits/project.rs @@ -403,7 +403,7 @@ pub type NormalizedTy<'tcx> = Normalized<'tcx, Ty<'tcx>>; impl<'tcx, T> Normalized<'tcx, T> { pub fn with(self, value: U) -> Normalized<'tcx, U> { - Normalized { value: value, obligations: self.obligations } + Normalized { value, obligations: self.obligations } } } @@ -1291,7 +1291,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( substs: trait_ref.substs, item_def_id: obligation.predicate.item_def_id, }, - ty: ty, + ty, } }); diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs index fd94e3b69940c..c0d8f3cfd4f86 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_infer/traits/select.rs @@ -2923,7 +2923,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Predicate::ClosureKind(closure_def_id, substs, kind), )); - Ok(VtableClosureData { closure_def_id, substs: substs, nested: obligations }) + Ok(VtableClosureData { closure_def_id, substs, nested: obligations }) } /// In the case of closure types and fn pointers, diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index 1dca01b3468ae..cd4595e76ccec 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -55,7 +55,7 @@ struct PredicateSet<'tcx> { impl PredicateSet<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> Self { - Self { tcx: tcx, set: Default::default() } + Self { tcx, set: Default::default() } } fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool { diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs index 7da69f3ed26f2..e0db2ae64ff21 100644 --- a/src/librustc_lint/levels.rs +++ b/src/librustc_lint/levels.rs @@ -377,10 +377,10 @@ impl<'s> LintLevelsBuilder<'s> { let prev = self.cur; if !specs.is_empty() { self.cur = self.sets.list.len() as u32; - self.sets.list.push(LintSet::Node { specs: specs, parent: prev }); + self.sets.list.push(LintSet::Node { specs, parent: prev }); } - BuilderPush { prev: prev, changed: prev != self.cur } + BuilderPush { prev, changed: prev != self.cur } } /// Called after `push` when the scope of a set of attributes are exited. diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index ea0cc2f0c8bf2..7624b1d562f08 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -493,7 +493,7 @@ impl<'tcx> EncodeContext<'tcx> { edition: tcx.sess.edition(), has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), - has_default_lib_allocator: has_default_lib_allocator, + has_default_lib_allocator, plugin_registrar_fn: tcx.plugin_registrar_fn(LOCAL_CRATE).map(|id| id.index), proc_macro_decls_static: if is_proc_macro { let id = tcx.proc_macro_decls_static(LOCAL_CRATE).unwrap(); diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index cd6834a5a4d00..fefef69d63cbd 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -175,7 +175,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if self.body.local_decls[local].is_ref_for_guard() => { self.append_place_to_string( - PlaceRef { local: local, projection: &[] }, + PlaceRef { local, projection: &[] }, buf, autoderef, &including_downcast, diff --git a/src/librustc_mir/borrow_check/region_infer/values.rs b/src/librustc_mir/borrow_check/region_infer/values.rs index 3126d44014b4e..675463cb1c1f9 100644 --- a/src/librustc_mir/borrow_check/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/region_infer/values.rs @@ -140,7 +140,7 @@ impl LivenessValues { /// Each of the regions in num_region_variables will be initialized with an /// empty set of points and no causal information. crate fn new(elements: Rc) -> Self { - Self { points: SparseBitMatrix::new(elements.num_points), elements: elements } + Self { points: SparseBitMatrix::new(elements.num_points), elements } } /// Iterate through each region that has a value in this set. diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs index af4ea759f4f8b..67b00e9ffdd5f 100644 --- a/src/librustc_mir/borrow_check/universal_regions.rs +++ b/src/librustc_mir/borrow_check/universal_regions.rs @@ -486,7 +486,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { defining_ty, unnormalized_output_ty, unnormalized_input_tys, - yield_ty: yield_ty, + yield_ty, } } diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs index 45d2b1a71f0f2..a9ef7ef6c528a 100644 --- a/src/librustc_mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -72,7 +72,7 @@ pub struct Edge { fn outgoing(body: &Body<'_>, bb: BasicBlock) -> Vec { (0..body[bb].terminator().successors().count()) - .map(|index| Edge { source: bb, index: index }) + .map(|index| Edge { source: bb, index }) .collect() } diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 57aa5de7f7a31..7e36a3cf2bfec 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -474,7 +474,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } fn record_move(&mut self, place: &Place<'tcx>, path: MovePathIndex) { - let move_out = self.builder.data.moves.push(MoveOut { path: path, source: self.loc }); + let move_out = self.builder.data.moves.push(MoveOut { path, source: self.loc }); debug!( "gather_move({:?}, {:?}): adding move {:?} of {:?}", self.loc, place, move_out, path diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 4f96cb698915d..4cf179f5fcecf 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -647,7 +647,7 @@ where } local => PlaceTy { // This works even for dead/uninitialized locals; we check further when writing - place: Place::Local { frame: self.cur_frame(), local: local }, + place: Place::Local { frame: self.cur_frame(), local }, layout: self.layout_of_local(self.frame(), local, None)?, }, }; diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index 3dff06967e50e..7177bf726d403 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -13,7 +13,7 @@ pub fn custom_coerce_unsize_info<'tcx>( let def_id = tcx.lang_items().coerce_unsized_trait().unwrap(); let trait_ref = ty::Binder::bind(ty::TraitRef { - def_id: def_id, + def_id, substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]), }); diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index a5b467c1e101f..45cecc1b125d8 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -75,8 +75,8 @@ impl<'tcx> MirPass<'tcx> for AddRetag { { let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, - span: span, // FIXME: Consider using just the span covering the function - // argument declaration. + span, // FIXME: Consider using just the span covering the function + // argument declaration. }; // Gather all arguments, skip return value. let places = local_decls diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 3107be1b62207..d060a0eab3db0 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -506,7 +506,7 @@ fn locals_live_across_suspend_points( for (block, data) in body.basic_blocks().iter_enumerated() { if let TerminatorKind::Yield { .. } = data.terminator().kind { - let loc = Location { block: block, statement_index: data.statements.len() }; + let loc = Location { block, statement_index: data.statements.len() }; if !movable { // The `liveness` variable contains the liveness of MIR locals ignoring borrows. diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 2ae7bd4d72729..22ac3410a75ab 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -34,7 +34,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); let move_data = MoveData::gather_moves(body, tcx, param_env).unwrap(); - let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; + let mdpe = MoveDataParamEnv { move_data, param_env }; let flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) .into_engine(tcx, body, def_id) diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index f7239ae55faa2..4531b91e53769 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -872,7 +872,7 @@ where debug!("drop_flag_reset_block({:?},{:?})", self, mode); let block = self.new_block(unwind, TerminatorKind::Goto { target: succ }); - let block_start = Location { block: block, statement_index: 0 }; + let block_start = Location { block, statement_index: 0 }; self.elaborator.clear_drop_flag(block_start, self.path, mode); block } @@ -921,7 +921,7 @@ where let call = TerminatorKind::Call { func: Operand::function_handle(tcx, free_func, substs, self.source_info.span), - args: args, + args, destination: Some((unit_temp, target)), cleanup: None, from_hir_call: false, diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 6fd8f06fe8f25..1fd5f3c439587 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -297,7 +297,7 @@ where writeln!(w, "{}{:?}{}: {{", INDENT, block, cleanup_text)?; // List of statements in the middle. - let mut current_location = Location { block: block, statement_index: 0 }; + let mut current_location = Location { block, statement_index: 0 }; for statement in &data.statements { extra_data(PassWhere::BeforeLocation(current_location), w)?; let indented_body = format!("{0}{0}{1:?};", INDENT, statement); diff --git a/src/librustc_mir_build/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs index 56aa150dd37d2..80fa0c44860e4 100644 --- a/src/librustc_mir_build/build/matches/simplify.rs +++ b/src/librustc_mir_build/build/matches/simplify.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // value being matched, taking the variance field into account. candidate.ascriptions.push(Ascription { span: user_ty_span, - user_ty: user_ty, + user_ty, source: match_pair.place, variance, }); diff --git a/src/librustc_mir_build/build/matches/test.rs b/src/librustc_mir_build/build/matches/test.rs index 9f450f8fc7b77..d23a2708dc478 100644 --- a/src/librustc_mir_build/build/matches/test.rs +++ b/src/librustc_mir_build/build/matches/test.rs @@ -64,10 +64,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Slice { ref prefix, ref slice, ref suffix } => { let len = prefix.len() + suffix.len(); let op = if slice.is_some() { BinOp::Ge } else { BinOp::Eq }; - Test { - span: match_pair.pattern.span, - kind: TestKind::Len { len: len as u64, op: op }, - } + Test { span: match_pair.pattern.span, kind: TestKind::Len { len: len as u64, op } } } PatKind::Or { .. } => bug!("or-patterns should have already been handled"), diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index 830877f713e4b..b60a637471e13 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -418,7 +418,7 @@ struct GuardFrameLocal { impl GuardFrameLocal { fn new(id: hir::HirId, _binding_mode: BindingMode) -> Self { - GuardFrameLocal { id: id } + GuardFrameLocal { id } } } diff --git a/src/librustc_mir_build/hair/cx/block.rs b/src/librustc_mir_build/hair/cx/block.rs index a883b84f8fe2f..8d7225c8c7b51 100644 --- a/src/librustc_mir_build/hair/cx/block.rs +++ b/src/librustc_mir_build/hair/cx/block.rs @@ -84,7 +84,7 @@ fn mirror_stmts<'a, 'tcx>( result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Let { - remainder_scope: remainder_scope, + remainder_scope, init_scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node, diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index a3554ea2ee0a3..6b5e927214f5a 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -2102,7 +2102,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { .is_ok() { let def_id = module.def_id().unwrap(); - found_traits.push(TraitCandidate { def_id: def_id, import_ids: smallvec![] }); + found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] }); } } diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 193b6d75935b2..7281173e9db78 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -1032,13 +1032,13 @@ struct Shadower { } fn original_label(span: Span) -> Original { - Original { kind: ShadowKind::Label, span: span } + Original { kind: ShadowKind::Label, span } } fn shadower_label(span: Span) -> Shadower { - Shadower { kind: ShadowKind::Label, span: span } + Shadower { kind: ShadowKind::Label, span } } fn original_lifetime(span: Span) -> Original { - Original { kind: ShadowKind::Lifetime, span: span } + Original { kind: ShadowKind::Lifetime, span } } fn shadower_lifetime(param: &hir::GenericParam<'_>) -> Shadower { Shadower { kind: ShadowKind::Lifetime, span: param.span } @@ -1347,7 +1347,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let missing_named_lifetime_spots = take(&mut self.missing_named_lifetime_spots); let mut this = LifetimeContext { tcx: *tcx, - map: map, + map, scope: &wrap_scope, trait_ref_hack: self.trait_ref_hack, is_in_fn_syntax: self.is_in_fn_syntax, diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 9da8ee548fddd..ec251c224b690 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -334,7 +334,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { Some(_) => ImplKind::Direct, None => ImplKind::Inherent, }, - span: span, + span, value: String::new(), parent: None, children: items diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index a295e1637aa4c..2005366f83986 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -793,7 +793,7 @@ impl Sig for ast::ForeignItem { text.push_str(&name); text.push(';'); - Ok(Signature { text: text, defs: defs, refs: vec![] }) + Ok(Signature { text, defs, refs: vec![] }) } ast::ForeignItemKind::Macro(..) => Err("macro"), } diff --git a/src/librustc_session/code_stats.rs b/src/librustc_session/code_stats.rs index 9b89c7ae32abc..c263da69c3521 100644 --- a/src/librustc_session/code_stats.rs +++ b/src/librustc_session/code_stats.rs @@ -70,7 +70,7 @@ impl CodeStats { type_description: type_desc.to_string(), align: align.bytes(), overall_size: overall_size.bytes(), - packed: packed, + packed, opt_discr_size: opt_discr_size.map(|s| s.bytes()), variants, }; diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs index 6cdfd0500ca84..66cdf46bd4e5f 100644 --- a/src/librustc_span/def_id.rs +++ b/src/librustc_span/def_id.rs @@ -130,7 +130,7 @@ impl DefId { /// Makes a local `DefId` from the given `DefIndex`. #[inline] pub fn local(index: DefIndex) -> DefId { - DefId { krate: LOCAL_CRATE, index: index } + DefId { krate: LOCAL_CRATE, index } } #[inline] diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index c2b2196e74c61..8b1ba57e81945 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -47,7 +47,7 @@ pub fn resolve_instance<'tcx>( } } }; - Some(Instance { def: def, substs: substs }) + Some(Instance { def, substs }) }; debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result); result diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index ff9fec004bbb5..7570d9d4b28ac 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let needs = Needs::maybe_mut_place(mutbl); let ty = self.check_expr_with_expectation_and_needs(&oprnd, hint, needs); - let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl }; + let tm = ty::TypeAndMut { ty, mutbl }; match kind { _ if tm.ty.references_error() => self.tcx.types.err, hir::BorrowKind::Raw => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d8b23998e727f..d2f9f4e068a09 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4234,7 +4234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let substs = self.fresh_substs_for_item(span, did); let substd_ty = self.instantiate_type_scheme(span, &substs, &ity); - TypeAndSubsts { substs: substs, ty: substd_ty } + TypeAndSubsts { substs, ty: substd_ty } } /// Unifies the output type with the expected type early, for more coercions diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index fcbeb5b210dec..44473fee643c6 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -31,10 +31,10 @@ pub fn infer_predicates<'tcx>( predicates_added = false; let mut visitor = InferVisitor { - tcx: tcx, + tcx, global_inferred_outlives: &mut global_inferred_outlives, predicates_added: &mut predicates_added, - explicit_map: explicit_map, + explicit_map, }; // Visit all the crates and infer predicates diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index becdeaba50f78..41b8e66d26592 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -44,7 +44,7 @@ impl Module<'hir> { vis: &'hir hir::Visibility<'hir>, ) -> Module<'hir> { Module { - name: name, + name, id: hir::CRATE_HIR_ID, vis, where_outer: rustc_span::DUMMY_SP, diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index d0e1a01b00654..44f8e8bd1717a 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -2461,7 +2461,7 @@ impl RandomState { KEYS.with(|keys| { let (k0, k1) = keys.get(); keys.set((k0.wrapping_add(1), k1)); - RandomState { k0: k0, k1: k1 } + RandomState { k0, k1 } }) } } diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 9787cbb556bd2..f36aa1846a16c 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -96,7 +96,7 @@ impl Cursor { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: T) -> Cursor { - Cursor { pos: 0, inner: inner } + Cursor { pos: 0, inner } } /// Consumes this cursor, returning the underlying value. diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index a50dd9575de32..0103e4bd628d7 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -371,7 +371,7 @@ where F: FnMut(&R) -> usize, { let start_len = buf.len(); - let mut g = Guard { len: buf.len(), buf: buf }; + let mut g = Guard { len: buf.len(), buf }; let ret; loop { if g.len == g.buf.len() { @@ -939,7 +939,7 @@ pub trait Read { where Self: Sized, { - Take { inner: self, limit: limit } + Take { inner: self, limit } } } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 6eeddc28512d9..0cb16b19d7326 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -416,7 +416,7 @@ impl fmt::Debug for Mutex { impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> { unsafe fn new(lock: &'mutex Mutex) -> LockResult> { - poison::map_result(lock.poison.borrow(), |guard| MutexGuard { lock: lock, poison: guard }) + poison::map_result(lock.poison.borrow(), |guard| MutexGuard { lock, poison: guard }) } } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index fdd29af858185..50f54dbf14306 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -465,16 +465,13 @@ impl From for RwLock { impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { unsafe fn new(lock: &'rwlock RwLock) -> LockResult> { - poison::map_result(lock.poison.borrow(), |_| RwLockReadGuard { lock: lock }) + poison::map_result(lock.poison.borrow(), |_| RwLockReadGuard { lock }) } } impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { unsafe fn new(lock: &'rwlock RwLock) -> LockResult> { - poison::map_result(lock.poison.borrow(), |guard| RwLockWriteGuard { - lock: lock, - poison: guard, - }) + poison::map_result(lock.poison.borrow(), |guard| RwLockWriteGuard { lock, poison: guard }) } } From 1631b4de1c951034654cc0684b38dcbd0708c902 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 5 Mar 2020 15:24:53 +0900 Subject: [PATCH 21/23] Avoid using `unwrap()` in suggestions --- src/librustc_typeck/check/method/suggest.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 95faa353e9b65..084601fbde1d4 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -547,10 +547,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (&self_ty.kind, parent_pred) { if let ty::Adt(def, _) = p.skip_binder().trait_ref.self_ty().kind { - let id = self.tcx.hir().as_local_hir_id(def.did).unwrap(); - let node = self.tcx.hir().get(id); + let node = self + .tcx + .hir() + .as_local_hir_id(def.did) + .map(|id| self.tcx.hir().get(id)); match node { - hir::Node::Item(hir::Item { kind, .. }) => { + Some(hir::Node::Item(hir::Item { kind, .. })) => { if let Some(g) = kind.generics() { let key = match &g.where_clause.predicates[..] { [.., pred] => { From 3d676492872d5e464e811a8f8d5afcd7122db089 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 7 Mar 2020 04:38:50 +0900 Subject: [PATCH 22/23] Add a regression test --- src/test/ui/issues/auxiliary/issue-69725.rs | 8 ++++++++ src/test/ui/issues/issue-69725.rs | 11 +++++++++++ src/test/ui/issues/issue-69725.stderr | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 src/test/ui/issues/auxiliary/issue-69725.rs create mode 100644 src/test/ui/issues/issue-69725.rs create mode 100644 src/test/ui/issues/issue-69725.stderr diff --git a/src/test/ui/issues/auxiliary/issue-69725.rs b/src/test/ui/issues/auxiliary/issue-69725.rs new file mode 100644 index 0000000000000..13606e498ef7d --- /dev/null +++ b/src/test/ui/issues/auxiliary/issue-69725.rs @@ -0,0 +1,8 @@ +#[derive(Clone)] +pub struct Struct(A); + +impl Struct { + pub fn new() -> Self { + todo!() + } +} diff --git a/src/test/ui/issues/issue-69725.rs b/src/test/ui/issues/issue-69725.rs new file mode 100644 index 0000000000000..b8130b41f2167 --- /dev/null +++ b/src/test/ui/issues/issue-69725.rs @@ -0,0 +1,11 @@ +// aux-build:issue-69725.rs + +extern crate issue_69725; +use issue_69725::Struct; + +fn crash() { + let _ = Struct::::new().clone(); + //~^ ERROR: no method named `clone` found +} + +fn main() {} diff --git a/src/test/ui/issues/issue-69725.stderr b/src/test/ui/issues/issue-69725.stderr new file mode 100644 index 0000000000000..667383e072a54 --- /dev/null +++ b/src/test/ui/issues/issue-69725.stderr @@ -0,0 +1,18 @@ +error[E0599]: no method named `clone` found for struct `issue_69725::Struct` in the current scope + --> $DIR/issue-69725.rs:7:32 + | +LL | let _ = Struct::::new().clone(); + | ^^^^^ method not found in `issue_69725::Struct` + | + ::: $DIR/auxiliary/issue-69725.rs:2:1 + | +LL | pub struct Struct(A); + | ------------------------ doesn't satisfy `issue_69725::Struct: std::clone::Clone` + | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `A: std::clone::Clone` + which is required by `issue_69725::Struct: std::clone::Clone` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From 125159f30a7a97b0b4d4bc36b11846a3f6dd4a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Dec 2019 15:46:31 -0800 Subject: [PATCH 23/23] When encountering an Item in a pat context, point at the item def --- src/librustc_typeck/check/pat.rs | 103 ++++++++++++++---- .../ui/blind/blind-item-block-middle.stderr | 9 +- src/test/ui/issues/issue-33504.stderr | 9 +- src/test/ui/issues/issue-4968.stderr | 9 +- src/test/ui/issues/issue-5100.stderr | 3 + src/test/ui/issues/issue-7867.stderr | 3 + src/test/ui/match/match-tag-nullary.stderr | 3 + .../const.stderr | 9 +- .../ui/suggestions/const-in-struct-pat.rs | 11 ++ .../ui/suggestions/const-in-struct-pat.stderr | 16 +++ 10 files changed, 147 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/suggestions/const-in-struct-pat.rs create mode 100644 src/test/ui/suggestions/const-in-struct-pat.stderr diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index b7aac707a9838..dd4b407ac52cb 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -63,6 +63,22 @@ struct TopInfo<'tcx> { /// found type `std::result::Result<_, _>` /// ``` span: Option, + /// This refers to the parent pattern. Used to provide extra diagnostic information on errors. + /// ```text + /// error[E0308]: mismatched types + /// --> $DIR/const-in-struct-pat.rs:8:17 + /// | + /// L | struct f; + /// | --------- unit struct defined here + /// ... + /// L | let Thing { f } = t; + /// | ^ + /// | | + /// | expected struct `std::string::String`, found struct `f` + /// | `f` is interpreted as a unit struct, not a new binding + /// | help: bind the struct field to a different name instead: `f: other_f` + /// ``` + parent_pat: Option<&'tcx Pat<'tcx>>, } impl<'tcx> FnCtxt<'_, 'tcx> { @@ -120,7 +136,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Option, origin_expr: bool, ) { - self.check_pat(pat, expected, INITIAL_BM, TopInfo { expected, origin_expr, span }); + let info = TopInfo { expected, origin_expr, span, parent_pat: None }; + self.check_pat(pat, expected, INITIAL_BM, info); } /// Type check the given `pat` against the `expected` type @@ -161,8 +178,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, ti) } PatKind::Or(pats) => { + let parent_pat = Some(pat); for pat in pats { - self.check_pat(pat, expected, def_bm, ti); + self.check_pat(pat, expected, def_bm, TopInfo { parent_pat, ..ti }); } expected } @@ -501,7 +519,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_ident( &self, - pat: &Pat<'_>, + pat: &'tcx Pat<'tcx>, ba: hir::BindingAnnotation, var_id: HirId, sub: Option<&'tcx Pat<'tcx>>, @@ -546,7 +564,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(p) = sub { - self.check_pat(&p, expected, def_bm, ti); + self.check_pat(&p, expected, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); } local_ty @@ -647,6 +665,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant_ty } else { for field in fields { + let ti = TopInfo { parent_pat: Some(&pat), ..ti }; self.check_pat(&field.pat, self.tcx.types.err, def_bm, ti); } return self.tcx.types.err; @@ -656,9 +675,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_eqtype_pat(pat.span, expected, pat_ty, ti); // Type-check subpatterns. - if self - .check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm, ti) - { + if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, etc, def_bm, ti) { pat_ty } else { self.tcx.types.err @@ -696,18 +713,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Type-check the path. - let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0; - if let Some(mut err) = + let (pat_ty, pat_res) = + self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id); + if let Some(err) = self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty) { - err.emit(); + self.emit_bad_pat_path(err, pat.span, res, pat_res, segments, ti.parent_pat); } pat_ty } + fn emit_bad_pat_path( + &self, + mut e: DiagnosticBuilder<'_>, + pat_span: Span, + res: Res, + pat_res: Res, + segments: &'b [hir::PathSegment<'b>], + parent_pat: Option<&Pat<'_>>, + ) { + if let Some(span) = self.tcx.hir().res_span(pat_res) { + e.span_label(span, &format!("{} defined here", res.descr())); + if let [hir::PathSegment { ident, .. }] = &*segments { + e.span_label( + pat_span, + &format!( + "`{}` is interpreted as {} {}, not a new binding", + ident, + res.article(), + res.descr(), + ), + ); + let (msg, sugg) = match parent_pat { + Some(Pat { kind: hir::PatKind::Struct(..), .. }) => ( + "bind the struct field to a different name instead", + format!("{}: other_{}", ident, ident.as_str().to_lowercase()), + ), + _ => ( + "introduce a new binding instead", + format!("other_{}", ident.as_str().to_lowercase()), + ), + }; + e.span_suggestion(ident.span, msg, sugg, Applicability::HasPlaceholders); + } + } + e.emit(); + } + fn check_pat_tuple_struct( &self, - pat: &Pat<'_>, + pat: &'tcx Pat<'tcx>, qpath: &hir::QPath<'_>, subpats: &'tcx [&'tcx Pat<'tcx>], ddpos: Option, @@ -717,8 +772,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; let on_error = || { + let parent_pat = Some(pat); for pat in subpats { - self.check_pat(&pat, tcx.types.err, def_bm, ti); + self.check_pat(&pat, tcx.types.err, def_bm, TopInfo { parent_pat, ..ti }); } }; let report_unexpected_res = |res: Res| { @@ -793,7 +849,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs); - self.check_pat(&subpat, field_ty, def_bm, ti); + self.check_pat(&subpat, field_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span); } @@ -938,8 +994,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_struct_pat_fields( &self, adt_ty: Ty<'tcx>, - pat_id: HirId, - span: Span, + pat: &'tcx Pat<'tcx>, variant: &'tcx ty::VariantDef, fields: &'tcx [hir::FieldPat<'tcx>], etc: bool, @@ -950,7 +1005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (substs, adt) = match adt_ty.kind { ty::Adt(adt, substs) => (substs, adt), - _ => span_bug!(span, "struct pattern is not an ADT"), + _ => span_bug!(pat.span, "struct pattern is not an ADT"), }; let kind_name = adt.variant_descr(); @@ -983,7 +1038,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .get(&ident) .map(|(i, f)| { self.write_field_index(field.hir_id, *i); - self.tcx.check_stability(f.did, Some(pat_id), span); + self.tcx.check_stability(f.did, Some(pat.hir_id), span); self.field_ty(span, f, substs) }) .unwrap_or_else(|| { @@ -994,7 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - self.check_pat(&field.pat, field_ty, def_bm, ti); + self.check_pat(&field.pat, field_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); } let mut unmentioned_fields = variant @@ -1017,7 +1072,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc { struct_span_err!( tcx.sess, - span, + pat.span, E0638, "`..` required with {} marked as non-exhaustive", kind_name @@ -1029,14 +1084,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if kind_name == "union" { if fields.len() != 1 { tcx.sess - .struct_span_err(span, "union patterns should have exactly one field") + .struct_span_err(pat.span, "union patterns should have exactly one field") .emit(); } if etc { - tcx.sess.struct_span_err(span, "`..` cannot be used in union patterns").emit(); + tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit(); } } else if !etc && !unmentioned_fields.is_empty() { - self.error_unmentioned_fields(span, &unmentioned_fields, variant); + self.error_unmentioned_fields(pat.span, &unmentioned_fields, variant); } no_field_errors } @@ -1196,7 +1251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_ref( &self, - pat: &Pat<'_>, + pat: &'tcx Pat<'tcx>, inner: &'tcx Pat<'tcx>, mutbl: hir::Mutability, expected: Ty<'tcx>, @@ -1236,7 +1291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (tcx.types.err, tcx.types.err) }; - self.check_pat(&inner, inner_ty, def_bm, ti); + self.check_pat(&inner, inner_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); rptr_ty } diff --git a/src/test/ui/blind/blind-item-block-middle.stderr b/src/test/ui/blind/blind-item-block-middle.stderr index 264e7fc8e73a2..d8d15615d7c33 100644 --- a/src/test/ui/blind/blind-item-block-middle.stderr +++ b/src/test/ui/blind/blind-item-block-middle.stderr @@ -1,8 +1,15 @@ error[E0308]: mismatched types --> $DIR/blind-item-block-middle.rs:6:9 | +LL | mod foo { pub struct bar; } + | --------------- unit struct defined here +... LL | let bar = 5; - | ^^^ expected integer, found struct `foo::bar` + | ^^^ + | | + | expected integer, found struct `foo::bar` + | `bar` is interpreted as a unit struct, not a new binding + | help: introduce a new binding instead: `other_bar` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-33504.stderr b/src/test/ui/issues/issue-33504.stderr index 522df6a07c2c6..1e61178f42edb 100644 --- a/src/test/ui/issues/issue-33504.stderr +++ b/src/test/ui/issues/issue-33504.stderr @@ -1,8 +1,15 @@ error[E0308]: mismatched types --> $DIR/issue-33504.rs:7:13 | +LL | struct Test; + | ------------ unit struct defined here +... LL | let Test = 1; - | ^^^^ expected integer, found struct `Test` + | ^^^^ + | | + | expected integer, found struct `Test` + | `Test` is interpreted as a unit struct, not a new binding + | help: introduce a new binding instead: `other_test` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-4968.stderr b/src/test/ui/issues/issue-4968.stderr index 35435d0e61819..5451cf423559e 100644 --- a/src/test/ui/issues/issue-4968.stderr +++ b/src/test/ui/issues/issue-4968.stderr @@ -1,8 +1,15 @@ error[E0308]: mismatched types --> $DIR/issue-4968.rs:5:16 | +LL | const A: (isize,isize) = (4,2); + | ------------------------------- constant defined here +LL | fn main() { LL | match 42 { A => () } - | ^ expected integer, found tuple + | ^ + | | + | expected integer, found tuple + | `A` is interpreted as a constant, not a new binding + | help: introduce a new binding instead: `other_a` | = note: expected type `{integer}` found tuple `(isize, isize)` diff --git a/src/test/ui/issues/issue-5100.stderr b/src/test/ui/issues/issue-5100.stderr index c81d6dcaf0217..a89980964ca0a 100644 --- a/src/test/ui/issues/issue-5100.stderr +++ b/src/test/ui/issues/issue-5100.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/issue-5100.rs:8:9 | +LL | enum A { B, C } + | - unit variant defined here +... LL | match (true, false) { | ------------- this expression has type `(bool, bool)` LL | A::B => (), diff --git a/src/test/ui/issues/issue-7867.stderr b/src/test/ui/issues/issue-7867.stderr index 4a29464aebd2b..0d3121d60455d 100644 --- a/src/test/ui/issues/issue-7867.stderr +++ b/src/test/ui/issues/issue-7867.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/issue-7867.rs:7:9 | +LL | enum A { B, C } + | - unit variant defined here +... LL | match (true, false) { | ------------- this expression has type `(bool, bool)` LL | A::B => (), diff --git a/src/test/ui/match/match-tag-nullary.stderr b/src/test/ui/match/match-tag-nullary.stderr index 3703a59edb836..723c7fa92b10d 100644 --- a/src/test/ui/match/match-tag-nullary.stderr +++ b/src/test/ui/match/match-tag-nullary.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/match-tag-nullary.rs:4:40 | +LL | enum B { B } + | - unit variant defined here +LL | LL | fn main() { let x: A = A::A; match x { B::B => { } } } | - ^^^^ expected enum `A`, found enum `B` | | diff --git a/src/test/ui/rfc-2005-default-binding-mode/const.stderr b/src/test/ui/rfc-2005-default-binding-mode/const.stderr index 27efd450b9471..10d30ec1a1b18 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/const.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/const.stderr @@ -1,10 +1,17 @@ error[E0308]: mismatched types --> $DIR/const.rs:14:9 | +LL | const FOO: Foo = Foo{bar: 5}; + | ----------------------------- constant defined here +... LL | match &f { | -- this expression has type `&Foo` LL | FOO => {}, - | ^^^ expected `&Foo`, found struct `Foo` + | ^^^ + | | + | expected `&Foo`, found struct `Foo` + | `FOO` is interpreted as a constant, not a new binding + | help: introduce a new binding instead: `other_foo` error: aborting due to previous error diff --git a/src/test/ui/suggestions/const-in-struct-pat.rs b/src/test/ui/suggestions/const-in-struct-pat.rs new file mode 100644 index 0000000000000..1cbba935402a9 --- /dev/null +++ b/src/test/ui/suggestions/const-in-struct-pat.rs @@ -0,0 +1,11 @@ +#[allow(non_camel_case_types)] +struct foo; +struct Thing { + foo: String, +} + +fn example(t: Thing) { + let Thing { foo } = t; //~ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/suggestions/const-in-struct-pat.stderr b/src/test/ui/suggestions/const-in-struct-pat.stderr new file mode 100644 index 0000000000000..0a010dcab4c26 --- /dev/null +++ b/src/test/ui/suggestions/const-in-struct-pat.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/const-in-struct-pat.rs:8:17 + | +LL | struct foo; + | ----------- unit struct defined here +... +LL | let Thing { foo } = t; + | ^^^ - this expression has type `Thing` + | | + | expected struct `std::string::String`, found struct `foo` + | `foo` is interpreted as a unit struct, not a new binding + | help: bind the struct field to a different name instead: `foo: other_foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.