-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Parse & reject postfix operators after casts #68985
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
940f657
Parse & reject postfix operators after casts
daboross 5ce9b80
Refactor out error case & apply suggestions.
daboross 4fc0532
Type ascription outputs a Type, not Cast
daboross 0cf2049
Keep better fix suggestion if type ascription is likely unintended
daboross f82ca8b
Add more error cases to issue 35813 tests
daboross 5dd6464
Fix related type ascription tests.
daboross e3eefe2
Remove extra debug print in unreachable!
daboross c2d7ffb
Remove trailing whitespace
daboross 8ef3da0
Fix test stderr after rebasing on master.
daboross fa1f547
Add more double cast + method call tests
daboross f434c6e
Use multipart suggestion
daboross 453c505
Replace ptr hashing with ptr casting
daboross File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
// edition:2018 | ||
daboross marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#![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; | ||
Centril marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
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 | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels weird to me to use the memory addresses for this, but I don't see a reason for it to ever fail...