Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

don't call type ascription "cast" #99895

Merged
merged 1 commit into from
Jul 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -827,11 +827,12 @@ impl<'a> Parser<'a> {
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
};
let (cast_kind, maybe_ascription_span) =
if let ExprKind::Type(ascripted_expr, _) = &cast_expr.kind {
("type ascription", Some(ascripted_expr.span.shrink_to_hi().with_hi(span.hi())))
} else {
("cast", 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.
Expand All @@ -844,7 +845,7 @@ impl<'a> Parser<'a> {
// 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 {}",
"{cast_kind} cannot be followed by {}",
match with_postfix.kind {
ExprKind::Index(_, _) => "indexing",
ExprKind::Try(_) => "`?`",
Expand Down
66 changes: 33 additions & 33 deletions src/test/ui/parser/issues/issue-35813-postfix-after-cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ 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<i32>[0];
//~^ ERROR: casts cannot be followed by indexing
//~^ ERROR: cast cannot be followed by indexing
vec![1, 2, 3]: Vec<i32>[0];
//~^ ERROR: casts cannot be followed by indexing
//~^ ERROR: type ascription cannot be followed by indexing
}

pub fn index_after_cast_to_index() {
(&[0]) as &[i32][0];
//~^ ERROR: casts cannot be followed by indexing
//~^ ERROR: cast cannot be followed by indexing
(&[0i32]): &[i32; 1][0];
//~^ ERROR: casts cannot be followed by indexing
//~^ ERROR: type ascription cannot be followed by indexing
}

pub fn cast_after_cast() {
Expand All @@ -37,89 +37,89 @@ pub fn cast_after_cast() {

pub fn cast_cast_method_call() {
let _ = 0i32: i32: i32.count_ones();
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: type ascription cannot be followed by a method call
let _ = 0 as i32: i32.count_ones();
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: type ascription cannot be followed by a method call
let _ = 0i32: i32 as i32.count_ones();
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: cast cannot be followed by a method call
let _ = 0 as i32 as i32.count_ones();
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: cast 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
//~^ ERROR: cast cannot be followed by a method call
let _ = 0i32: i32.count_ones(): u32;
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: type ascription cannot be followed by a method call
let _ = 0 as i32.count_ones(): u32;
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: cast cannot be followed by a method call
let _ = 0i32: i32.count_ones() as u32;
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: type ascription cannot be followed by a method call
let _ = 0 as i32.count_ones() as u32;
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: cast 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
//~^ ERROR: type ascription 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
//~^^^ ERROR: cast 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
//~^ ERROR: cast cannot be followed by indexing
}

pub fn method_calls() {
0 as i32.max(0);
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: cast cannot be followed by a method call
0: i32.max(0);
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: type ascription 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
//~^ ERROR: cast cannot be followed by a method call
if true { 33 } else { 44 }: i32.max(0)
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: type ascription 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
//~^ ERROR: cast cannot be followed by a method call
}
if 5u64: u64.max(0) == 0 {
//~^ ERROR: casts cannot be followed by a method call
//~^ ERROR: type ascription 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
//~^ ERROR: cast 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
//~^ ERROR: type ascription 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
//~^ ERROR: cast cannot be followed by indexing

static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]);
//~^ ERROR: casts cannot be followed by indexing
//~^ ERROR: type ascription 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 `?`
//~^ ERROR: cast cannot be followed by `?`
Err(0u64): Result<u64,u64>?;
//~^ ERROR: casts cannot be followed by `?`
//~^ ERROR: type ascription cannot be followed by `?`
Ok(1)
}

Expand All @@ -143,17 +143,17 @@ pub fn cast_to_fn_should_work() {
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
//~^ ERROR: cast cannot be followed by a function call
drop_ptr: fn(u8)(0);
//~^ ERROR: casts cannot be followed by a function call
//~^ ERROR: type ascription 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`
//~^ ERROR: cast cannot be followed by `.await`

Box::pin(noop()): Pin<Box<_>>.await;
//~^ ERROR: casts cannot be followed by `.await`
//~^ ERROR: type ascription cannot be followed by `.await`
}

pub async fn noop() {}
Expand All @@ -167,5 +167,5 @@ 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
//~^ ERROR: type ascription cannot be followed by a field access
}
Loading