about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-03-18 20:45:15 -0700
committerMichael Goulet <michael@errs.io>2022-03-18 21:22:26 -0700
commit3516a16eebc93c2ebcf049ce9bb83748f365a57d (patch)
tree3e6fbce55b5d61f86395d8bd453ed436ddb6527a
parent1bfe40d11c3630254504fb73eeccfca28d50df52 (diff)
downloadrust-3516a16eebc93c2ebcf049ce9bb83748f365a57d.tar.gz
rust-3516a16eebc93c2ebcf049ce9bb83748f365a57d.zip
suggest removing type ascription in bad position
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs41
-rw-r--r--src/test/ui/parser/issues/issue-35813-postfix-after-cast.stderr80
2 files changed, 115 insertions, 6 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index a907f50a11b..148e0a24ec3 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -800,11 +800,17 @@ impl<'a> Parser<'a> {
         &mut self,
         cast_expr: P<Expr>,
     ) -> PResult<'a, P<Expr>> {
+        let span = cast_expr.span;
+        let maybe_ascription_span = if let ExprKind::Type(ascripted_expr, _) = &cast_expr.kind {
+            Some(ascripted_expr.span.shrink_to_hi().with_hi(span.hi()))
+        } else {
+            None
+        };
+
         // 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 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 changed = addr_before != &*with_postfix as *const _ as usize;
 
@@ -825,11 +831,8 @@ 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
-            // 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 {
+
+            let suggest_parens = |err: &mut DiagnosticBuilder<'_, _>| {
                 let suggestions = vec![
                     (span.shrink_to_lo(), "(".to_string()),
                     (span.shrink_to_hi(), ")".to_string()),
@@ -839,6 +842,32 @@ impl<'a> Parser<'a> {
                     suggestions,
                     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 if let Some(ascription_span) = maybe_ascription_span {
+                let is_nightly = self.sess.unstable_features.is_nightly_build();
+                if is_nightly {
+                    suggest_parens(&mut err);
+                }
+                err.span_suggestion(
+                    ascription_span,
+                    &format!(
+                        "{}remove the type ascription",
+                        if is_nightly { "alternatively, " } else { "" }
+                    ),
+                    String::new(),
+                    if is_nightly {
+                        Applicability::MaybeIncorrect
+                    } else {
+                        Applicability::MachineApplicable
+                    },
+                );
+            } else {
+                suggest_parens(&mut err);
             }
             err.emit();
         };
diff --git a/src/test/ui/parser/issues/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issues/issue-35813-postfix-after-cast.stderr
index e96b67da336..6823a426823 100644
--- a/src/test/ui/parser/issues/issue-35813-postfix-after-cast.stderr
+++ b/src/test/ui/parser/issues/issue-35813-postfix-after-cast.stderr
@@ -19,6 +19,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     (vec![1, 2, 3]: Vec<i32>)[0];
    |     +                       +
+help: alternatively, remove the type ascription
+   |
+LL -     vec![1, 2, 3]: Vec<i32>[0];
+LL +     vec![1, 2, 3][0];
+   | 
 
 error: casts cannot be followed by indexing
   --> $DIR/issue-35813-postfix-after-cast.rs:17:5
@@ -41,6 +46,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     ((&[0i32]): &[i32; 1])[0];
    |     +                    +
+help: alternatively, remove the type ascription
+   |
+LL -     (&[0i32]): &[i32; 1][0];
+LL +     (&[0i32])[0];
+   | 
 
 error: casts cannot be followed by a method call
   --> $DIR/issue-35813-postfix-after-cast.rs:39:13
@@ -52,6 +62,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     let _ = (0i32: i32: i32).count_ones();
    |             +              +
+help: alternatively, remove the type ascription
+   |
+LL -     let _ = 0i32: i32: i32.count_ones();
+LL +     let _ = 0i32: i32.count_ones();
+   | 
 
 error: casts cannot be followed by a method call
   --> $DIR/issue-35813-postfix-after-cast.rs:41:13
@@ -63,6 +78,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     let _ = (0 as i32: i32).count_ones();
    |             +             +
+help: alternatively, remove the type ascription
+   |
+LL -     let _ = 0 as i32: i32.count_ones();
+LL +     let _ = 0 as i32.count_ones();
+   | 
 
 error: casts cannot be followed by a method call
   --> $DIR/issue-35813-postfix-after-cast.rs:43:13
@@ -107,6 +127,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     let _ = (0i32: i32).count_ones(): u32;
    |             +         +
+help: alternatively, remove the type ascription
+   |
+LL -     let _ = 0i32: i32.count_ones(): u32;
+LL +     let _ = 0i32.count_ones(): u32;
+   | 
 
 error: casts cannot be followed by a method call
   --> $DIR/issue-35813-postfix-after-cast.rs:51:13
@@ -129,6 +154,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     let _ = (0i32: i32).count_ones() as u32;
    |             +         +
+help: alternatively, remove the type ascription
+   |
+LL -     let _ = 0i32: i32.count_ones() as u32;
+LL +     let _ = 0i32.count_ones() as u32;
+   | 
 
 error: casts cannot be followed by a method call
   --> $DIR/issue-35813-postfix-after-cast.rs:55:13
@@ -151,6 +181,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     let _ = (0i32: i32: i32).count_ones() as u32 as i32;
    |             +              +
+help: alternatively, remove the type ascription
+   |
+LL -     let _ = 0i32: i32: i32.count_ones() as u32 as i32;
+LL +     let _ = 0i32: 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
@@ -198,6 +233,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     (0: i32).max(0);
    |     +      +
+help: alternatively, remove the type ascription
+   |
+LL -     0: i32.max(0);
+LL +     0.max(0);
+   | 
 
 error: casts cannot be followed by a method call
   --> $DIR/issue-35813-postfix-after-cast.rs:92:8
@@ -220,6 +260,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     if (5u64: u64).max(0) == 0 {
    |        +         +
+help: alternatively, remove the type ascription
+   |
+LL -     if 5u64: u64.max(0) == 0 {
+LL +     if 5u64.max(0) == 0 {
+   | 
 
 error: casts cannot be followed by a method call
   --> $DIR/issue-35813-postfix-after-cast.rs:102:9
@@ -242,6 +287,11 @@ help: try surrounding the expression in parentheses
    |
 LL |         (5u64: u64).max(0) == 0
    |         +         +
+help: alternatively, remove the type ascription
+   |
+LL -         5u64: u64.max(0) == 0
+LL +         5u64.max(0) == 0
+   | 
 
 error: casts cannot be followed by indexing
   --> $DIR/issue-35813-postfix-after-cast.rs:111:24
@@ -264,6 +314,11 @@ help: try surrounding the expression in parentheses
    |
 LL | static bar2: &[i32] = &((&[1i32,2,3]: &[i32; 3])[0..1]);
    |                         +                      +
+help: alternatively, remove the type ascription
+   |
+LL - static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]);
+LL + static bar2: &[i32] = &(&[1i32,2,3][0..1]);
+   | 
 
 error: casts cannot be followed by `?`
   --> $DIR/issue-35813-postfix-after-cast.rs:119:5
@@ -286,6 +341,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     (Err(0u64): Result<u64,u64>)?;
    |     +                          +
+help: alternatively, remove the type ascription
+   |
+LL -     Err(0u64): Result<u64,u64>?;
+LL +     Err(0u64)?;
+   | 
 
 error: casts cannot be followed by a function call
   --> $DIR/issue-35813-postfix-after-cast.rs:145:5
@@ -308,6 +368,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     (drop_ptr: fn(u8))(0);
    |     +                +
+help: alternatively, remove the type ascription
+   |
+LL -     drop_ptr: fn(u8)(0);
+LL +     drop_ptr(0);
+   | 
 
 error: casts cannot be followed by `.await`
   --> $DIR/issue-35813-postfix-after-cast.rs:152:5
@@ -330,6 +395,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     (Box::pin(noop()): Pin<Box<_>>).await;
    |     +                             +
+help: alternatively, remove the type ascription
+   |
+LL -     Box::pin(noop()): Pin<Box<_>>.await;
+LL +     Box::pin(noop()).await;
+   | 
 
 error: casts cannot be followed by a field access
   --> $DIR/issue-35813-postfix-after-cast.rs:167:5
@@ -352,6 +422,11 @@ help: try surrounding the expression in parentheses
    |
 LL |     (Foo::default(): Foo).bar;
    |     +                   +
+help: alternatively, remove the type ascription
+   |
+LL -     Foo::default(): Foo.bar;
+LL +     Foo::default().bar;
+   | 
 
 error: casts cannot be followed by a method call
   --> $DIR/issue-35813-postfix-after-cast.rs:84:9
@@ -374,6 +449,11 @@ help: try surrounding the expression in parentheses
    |
 LL |         (if true { 33 } else { 44 }: i32).max(0)
    |         +                               +
+help: alternatively, remove the type ascription
+   |
+LL -         if true { 33 } else { 44 }: i32.max(0)
+LL +         if true { 33 } else { 44 }.max(0)
+   | 
 
 error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/issue-35813-postfix-after-cast.rs:131:13