about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_parse/parser/expr.rs63
-rw-r--r--src/test/ui/parser/issue-35813-postfix-after-cast.rs171
-rw-r--r--src/test/ui/parser/issue-35813-postfix-after-cast.stderr392
-rw-r--r--src/test/ui/type/ascription/issue-54516.rs4
-rw-r--r--src/test/ui/type/ascription/issue-54516.stderr26
-rw-r--r--src/test/ui/type/ascription/issue-60933.rs4
-rw-r--r--src/test/ui/type/ascription/issue-60933.stderr26
7 files changed, 671 insertions, 15 deletions
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 18ddd23588e..e425ca6c4dd 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -544,8 +544,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();
-        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
@@ -599,17 +599,70 @@ 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);
                     }
                 }
             }
-        }
+        };
+
+        self.parse_and_disallow_postfix_after_cast(cast_expr)
+    }
+
+    /// 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<Expr>,
+    ) -> PResult<'a, P<Expr>> {
+        // 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;
+
+        // 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(_, _)) || changed {
+            let msg = format!(
+                "casts cannot be followed by {}",
+                match with_postfix.kind {
+                    ExprKind::Index(_, _) => "indexing",
+                    ExprKind::Try(_) => "?",
+                    ExprKind::Field(_, _) => "a field access",
+                    ExprKind::MethodCall(_, _) => "a method call",
+                    ExprKind::Call(_, _) => "a function call",
+                    ExprKind::Await(_) => "`.await`",
+                    _ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"),
+                }
+            );
+            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 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();
+        };
+        Ok(with_postfix)
     }
 
     fn parse_assoc_op_ascribe(&mut self, lhs: P<Expr>, lhs_span: Span) -> PResult<'a, P<Expr>> {
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 00000000000..e725aa5d73d
--- /dev/null
+++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs
@@ -0,0 +1,171 @@
+// edition:2018
+#![crate_type = "lib"]
+#![feature(type_ascription)]
+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<i32>[0];
+    //~^ ERROR: casts cannot be followed by indexing
+    vec![1, 2, 3]: Vec<i32>[0];
+    //~^ ERROR: casts cannot be followed by indexing
+}
+
+pub fn index_after_cast_to_index() {
+    (&[0]) as &[i32][0];
+    //~^ 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;
+}
+
+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
+}
+
+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<i32>[0];
+    //~^ 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!(
+        "{} 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 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 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 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<u64,u64> {
+    Err(0u64) as Result<u64,u64>?;
+    //~^ ERROR: casts cannot be followed by ?
+    Err(0u64): Result<u64,u64>?;
+    //~^ 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<Box<dyn Future<Output = ()>>>.await;
+    //~^ ERROR: casts cannot be followed by `.await`
+
+    Box::pin(noop()): Pin<Box<_>>.await;
+    //~^ ERROR: casts cannot be followed by `.await`
+}
+
+pub async fn noop() {}
+
+#[derive(Default)]
+pub struct Foo {
+    pub bar: u32,
+}
+
+pub fn struct_field() {
+    Foo::default() as Foo.bar;
+    //~^ 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
new file mode 100644
index 00000000000..255e9f40921
--- /dev/null
+++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr
@@ -0,0 +1,392 @@
+error: casts cannot be followed by indexing
+  --> $DIR/issue-35813-postfix-after-cast.rs:10:5
+   |
+LL |     vec![1, 2, 3] as Vec<i32>[0];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (vec![1, 2, 3] as Vec<i32>)[0];
+   |     ^                         ^
+
+error: casts cannot be followed by indexing
+  --> $DIR/issue-35813-postfix-after-cast.rs:12:5
+   |
+LL |     vec![1, 2, 3]: Vec<i32>[0];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (vec![1, 2, 3]: Vec<i32>)[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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+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
+   |
+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:70:18
+   |
+LL |     let x: i32 = &vec![1, 2, 3] as &Vec<i32>[0];
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     let x: i32 = (&vec![1, 2, 3] as &Vec<i32>)[0];
+   |                  ^                           ^
+
+error: casts cannot be followed by a method call
+  --> $DIR/issue-35813-postfix-after-cast.rs:75:5
+   |
+LL |     0 as i32.max(0);
+   |     ^^^^^^^^
+   |
+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:77:5
+   |
+LL |     0: i32.max(0);
+   |     ^^^^^^
+   |
+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:92:8
+   |
+LL |     if 5u64 as i32.max(0) == 0 {
+   |        ^^^^^^^^^^^
+   |
+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:95:8
+   |
+LL |     if 5u64: u64.max(0) == 0 {
+   |        ^^^^^^^^^
+   |
+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:102:9
+   |
+LL |         5u64 as u32.max(0) == 0
+   |         ^^^^^^^^^^^
+   |
+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:106:9
+   |
+LL |         5u64: u64.max(0) == 0
+   |         ^^^^^^^^^
+   |
+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:111:24
+   |
+LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]);
+   |                        ^^^^^^^^^^^^^^^^^^
+   |
+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:114:25
+   |
+LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+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:119:5
+   |
+LL |     Err(0u64) as Result<u64,u64>?;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (Err(0u64) as Result<u64,u64>)?;
+   |     ^                            ^
+
+error: casts cannot be followed by ?
+  --> $DIR/issue-35813-postfix-after-cast.rs:121:5
+   |
+LL |     Err(0u64): Result<u64,u64>?;
+   |     ^^^^^^^^^-^^^^^^^^^^^^^^^^
+   |              |
+   |              help: maybe write a path separator here: `::`
+   |
+   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+
+error: casts cannot be followed by a function call
+  --> $DIR/issue-35813-postfix-after-cast.rs:145:5
+   |
+LL |     drop as fn(u8)(0);
+   |     ^^^^^^^^^^^^^^
+   |
+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:147:5
+   |
+LL |     drop_ptr: fn(u8)(0);
+   |     ^^^^^^^^^^^^^^^^
+   |
+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:152:5
+   |
+LL |     Box::pin(noop()) as Pin<Box<dyn Future<Output = ()>>>.await;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try surrounding the expression in parentheses
+   |
+LL |     (Box::pin(noop()) as Pin<Box<dyn Future<Output = ()>>>).await;
+   |     ^                                                     ^
+
+error: casts cannot be followed by `.await`
+  --> $DIR/issue-35813-postfix-after-cast.rs:155:5
+   |
+LL |     Box::pin(noop()): Pin<Box<_>>.await;
+   |     ^^^^^^^^^^^^^^^^-^^^^^^^^^^^^
+   |                     |
+   |                     help: maybe write a path separator here: `::`
+   |
+   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+
+error: casts cannot be followed by a field access
+  --> $DIR/issue-35813-postfix-after-cast.rs:167:5
+   |
+LL |     Foo::default() as Foo.bar;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+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:169:5
+   |
+LL |     Foo::default(): Foo.bar;
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+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:84:9
+   |
+LL |         if true { 33 } else { 44 } as i32.max(0),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+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:86:9
+   |
+LL |         if true { 33 } else { 44 }: i32.max(0)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+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: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:133:15
+   |
+LL |     drop_ptr: F();
+   |               ^^^ only `Fn` traits may use parentheses
+
+error: aborting due to 36 previous errors
+
+For more information about this error, try `rustc --explain E0214`.
diff --git a/src/test/ui/type/ascription/issue-54516.rs b/src/test/ui/type/ascription/issue-54516.rs
index b53bfe5df03..8d6fd2abb6d 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::<BTreeMap<u32, u32>>());
-    //~^ 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 7127f67cd7d..fdf35700ef9 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::<BTreeMap<u32, u32>>());
-   |                            -                             ^ expected one of `!`, `,`, or `::`
+   |                    ^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                            |
    |                            help: maybe write a path separator here: `::`
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
    = note: see issue #23416 <https://github.com/rust-lang/rust/issues/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::<BTreeMap<u32, u32>>());
+   |                    ^^^^^^^^- 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::<BTreeMap<u32, u32>>());
+   |                            -^^^^^^^ 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 8fb06c887bd..bcf9f88cb41 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::<u32>();
-    //~^ 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 7130767b6c6..cd9ae8f49f4 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::<u32>();
-   |                            -              ^ expected one of `!`, `::`, or `;`
+   |                    ^^^^^^^^-^^^^^^^^^^^^^^
    |                            |
    |                            help: maybe write a path separator here: `::`
    |
    = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
    = note: see issue #23416 <https://github.com/rust-lang/rust/issues/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::<u32>();
+   |                    ^^^^^^^^- 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::<u32>();
+   |                            -^^^^^^^ 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`.