Rust: Add CFG test for early return in `async` block

Also made the test comply with `cargo check`.
This commit is contained in:
Tom Hvitved 2024-11-19 10:22:08 +01:00
Родитель ef9f3835e5
Коммит b6103e1ef4
6 изменённых файлов: 1176 добавлений и 1063 удалений

Просмотреть файл

@ -0,0 +1,53 @@
edges
| test.rs:5:5:11:5 | enter test_and_if_let | test.rs:5:24:5:24 | a | |
| test.rs:5:5:11:5 | exit test_and_if_let (normal) | test.rs:5:5:11:5 | exit test_and_if_let | |
| test.rs:5:24:5:24 | a | test.rs:5:24:5:30 | Param | match |
| test.rs:5:24:5:30 | Param | test.rs:5:33:5:33 | b | |
| test.rs:5:33:5:33 | b | test.rs:5:33:5:47 | Param | match |
| test.rs:5:33:5:47 | Param | test.rs:5:50:5:50 | c | |
| test.rs:5:50:5:50 | c | test.rs:5:50:5:56 | Param | match |
| test.rs:5:50:5:56 | Param | test.rs:6:12:6:12 | a | |
| test.rs:5:67:11:5 | BlockExpr | test.rs:5:5:11:5 | exit test_and_if_let (normal) | |
| test.rs:6:9:10:9 | IfExpr | test.rs:5:67:11:5 | BlockExpr | |
| test.rs:6:12:6:12 | a | test.rs:6:12:6:31 | [boolean(false)] ... && ... | false |
| test.rs:6:12:6:12 | a | test.rs:6:17:6:31 | LetExpr | true |
| test.rs:6:12:6:31 | [boolean(false)] ... && ... | test.rs:9:13:9:17 | false | false |
| test.rs:6:12:6:31 | [boolean(true)] ... && ... | test.rs:7:13:7:13 | d | true |
| test.rs:6:17:6:31 | LetExpr | test.rs:6:31:6:31 | b | |
| test.rs:6:21:6:27 | TupleStructPat | test.rs:6:12:6:31 | [boolean(false)] ... && ... | no-match |
| test.rs:6:21:6:27 | TupleStructPat | test.rs:6:26:6:26 | d | match |
| test.rs:6:26:6:26 | d | test.rs:6:12:6:31 | [boolean(true)] ... && ... | match |
| test.rs:6:31:6:31 | b | test.rs:6:21:6:27 | TupleStructPat | |
| test.rs:6:33:8:9 | BlockExpr | test.rs:6:9:10:9 | IfExpr | |
| test.rs:7:13:7:13 | d | test.rs:6:33:8:9 | BlockExpr | |
| test.rs:8:16:10:9 | BlockExpr | test.rs:6:9:10:9 | IfExpr | |
| test.rs:9:13:9:17 | false | test.rs:8:16:10:9 | BlockExpr | |
| test.rs:13:5:21:5 | enter test_and_if_let2 | test.rs:13:25:13:25 | a | |
| test.rs:13:5:21:5 | exit test_and_if_let2 (normal) | test.rs:13:5:21:5 | exit test_and_if_let2 | |
| test.rs:13:25:13:25 | a | test.rs:13:25:13:31 | Param | match |
| test.rs:13:25:13:31 | Param | test.rs:13:34:13:34 | b | |
| test.rs:13:34:13:34 | b | test.rs:13:34:13:39 | Param | match |
| test.rs:13:34:13:39 | Param | test.rs:13:42:13:42 | c | |
| test.rs:13:42:13:42 | c | test.rs:13:42:13:48 | Param | match |
| test.rs:13:42:13:48 | Param | test.rs:14:12:14:12 | a | |
| test.rs:13:59:21:5 | BlockExpr | test.rs:13:5:21:5 | exit test_and_if_let2 (normal) | |
| test.rs:14:9:20:9 | IfExpr | test.rs:13:59:21:5 | BlockExpr | |
| test.rs:14:12:14:12 | a | test.rs:14:12:14:25 | [boolean(false)] ... && ... | false |
| test.rs:14:12:14:12 | a | test.rs:14:17:14:25 | LetExpr | true |
| test.rs:14:12:14:25 | [boolean(false)] ... && ... | test.rs:14:12:15:16 | [boolean(false)] ... && ... | false |
| test.rs:14:12:14:25 | [boolean(true)] ... && ... | test.rs:15:16:15:16 | c | true |
| test.rs:14:12:15:16 | [boolean(false)] ... && ... | test.rs:19:13:19:17 | false | false |
| test.rs:14:12:15:16 | [boolean(true)] ... && ... | test.rs:17:13:17:13 | d | true |
| test.rs:14:17:14:25 | LetExpr | test.rs:14:25:14:25 | b | |
| test.rs:14:21:14:21 | d | test.rs:14:12:14:25 | [boolean(true)] ... && ... | match |
| test.rs:14:25:14:25 | b | test.rs:14:21:14:21 | d | |
| test.rs:15:16:15:16 | c | test.rs:14:12:15:16 | [boolean(false)] ... && ... | false |
| test.rs:15:16:15:16 | c | test.rs:14:12:15:16 | [boolean(true)] ... && ... | true |
| test.rs:16:9:18:9 | BlockExpr | test.rs:14:9:20:9 | IfExpr | |
| test.rs:17:13:17:13 | d | test.rs:17:17:17:17 | 0 | |
| test.rs:17:13:17:17 | ... > ... | test.rs:16:9:18:9 | BlockExpr | |
| test.rs:17:17:17:17 | 0 | test.rs:17:13:17:17 | ... > ... | |
| test.rs:18:16:20:9 | BlockExpr | test.rs:14:9:20:9 | IfExpr | |
| test.rs:19:13:19:17 | false | test.rs:18:16:20:9 | BlockExpr | |
breakTarget
continueTarget

Просмотреть файл

@ -0,0 +1 @@
query: utils/Cfg.ql

Просмотреть файл

@ -0,0 +1,22 @@
// TODO: Move these tests into `controlflow` when they become stable features
mod if_expression {
fn test_and_if_let(a: bool, b: Option<bool>, c: bool) -> bool {
if a && let Some(d) = b {
d
} else {
false
}
}
fn test_and_if_let2(a: bool, b: i64, c: bool) -> bool {
if a && let d = b
&& c
{
d > 0
} else {
false
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,10 +1,10 @@
use std::collections::HashMap;
use std::convert::Infallible;
mod calls {
use crate::test::logical_operators;
use std::collections::HashMap;
fn function_call() {
test_and_operator(true, false, true);
foo::<u32, u64>(42);
logical_operators::test_and_operator(true, false, true);
method_call();
}
fn method_call() {
@ -15,6 +15,14 @@ mod calls {
mod loop_expression {
fn next(n: i64) -> i64 {
if n % 2 == 0 {
n / 2
} else {
3 * n + 1
}
}
fn test_break_and_continue(n: i64) -> bool {
let mut i = n;
loop {
@ -89,7 +97,7 @@ mod loop_expression {
fn test_while_let() {
let mut iter = 1..10;
while let Some(x) = iter.next() {
if (i = 5) {
if (x == 5) {
break;
}
}
@ -136,29 +144,11 @@ mod if_expression {
fn test_if_let(a: Option<i64>) -> i64 {
if let Some(n) = a {
n
return n;
}
0
}
fn test_and_if_let(a: bool, b: Option<bool>, c: bool) -> bool {
if a && let Some(d) = b {
d
} else {
false
}
}
fn test_and_if_let2(a: bool, b: i64, c: bool) -> bool {
if a && let d = b
&& c
{
d > 0
} else {
false
}
}
fn test_nested_if(a: i64) -> i64 {
if (if a < 0 { a < -10 } else { a > 10 }) {
1
@ -191,7 +181,10 @@ mod if_expression {
fn test_if_assignment(a: i64) -> i64 {
let mut x = false;
if x = true {
if {
x = true;
x
} {
1
} else {
0
@ -237,7 +230,7 @@ mod if_expression {
mod logical_operators {
fn test_and_operator(a: bool, b: bool, c: bool) -> bool {
pub fn test_and_operator(a: bool, b: bool, c: bool) -> bool {
let d = a && b && c;
d
}
@ -257,7 +250,7 @@ mod logical_operators {
d
}
fn test_if_and_operator(a: bool, b: i64, c: bool) -> bool {
fn test_if_and_operator(a: bool, b: bool, c: bool) -> bool {
if a && b && c {
true
} else {
@ -265,7 +258,7 @@ mod logical_operators {
}
}
fn test_if_or_operator(a: bool, b: i64, c: bool) -> bool {
fn test_if_or_operator(a: bool, b: bool, c: bool) -> bool {
if a || b || c {
true
} else {
@ -287,9 +280,10 @@ mod logical_operators {
}
mod question_mark_operator {
use std::num;
fn test_question_mark_operator_1(s: &str) -> Option<i32> {
str.parse::<u32>()? + 4
fn test_question_mark_operator_1(s: &str) -> Result<u32, std::num::ParseIntError> {
Ok(s.parse::<u32>()? + 4)
}
fn test_question_mark_operator_2(b: Option<bool>) -> Option<bool> {
@ -301,6 +295,7 @@ mod question_mark_operator {
}
mod match_expression {
use std::convert::Infallible;
fn test_match(maybe_digit: Option<i64>) -> i64 {
match maybe_digit {
@ -321,7 +316,7 @@ mod match_expression {
}
}
fn test_match_and(cond: bool, r: Opton<bool>) -> bool {
fn test_match_and(cond: bool, r: Option<bool>) -> bool {
(match r {
Some(a) => a,
_ => false,
@ -338,12 +333,12 @@ mod match_expression {
mod let_statement {
fn test_let_match(a: Option<i64>) {
let Some(n) = a else { "Expected some" };
fn test_let_match(a: Option<i64>) -> i64 {
let Some(n) = a else { panic!("Expected some") };
n
}
fn test_let_with_return(m: Option<i64>) {
fn test_let_with_return(m: Option<i64>) -> bool {
let ret = match m {
Some(ret) => ret,
None => return false,
@ -354,7 +349,7 @@ mod let_statement {
mod patterns {
fn empty_tuple_pattern(unit: ()) -> void {
fn empty_tuple_pattern(unit: ()) -> () {
let () = unit;
return;
}
@ -363,7 +358,7 @@ mod patterns {
fn empty_struct_pattern(st: MyStruct) -> i64 {
match st {
MyStruct {} => 1,
MyStruct { .. } => 1,
}
}
@ -372,7 +367,7 @@ mod patterns {
..0 => 1,
1..2 => 2,
5.. => 3,
.. => 4,
_ => 4,
}
}
}
@ -380,7 +375,7 @@ mod patterns {
mod divergence {
fn test_infinite_loop() -> &'static str {
loop {
1
()
}
"never reached"
}
@ -391,7 +386,7 @@ mod async_await {
println!("hello, world!");
}
async fn async_block() {
async fn async_block(b: bool) {
let say_godbye = async {
println!("godbye, everyone!");
};
@ -403,17 +398,24 @@ mod async_await {
say_how_are_you.await;
say_godbye.await;
noop.await;
let lambda = |foo| async {
if b {
return async_block(true);
};
foo
};
}
}
mod const_evaluation {
const PI: i64 = 3.14159;
const PI: f64 = 3.14159;
const fn add_two(n: i64) -> i64 {
n + 2
}
const A_NUMBER: i64 = if add_two(2) + 2 == 4 { PI } else { 0 };
const A_NUMBER: f64 = if add_two(2) + 2 == 4 { PI } else { 0.0 };
fn const_block_assert<T>() -> usize {
// If this code ever gets executed, then the assertion has definitely
@ -444,6 +446,16 @@ fn dead_code() -> i64 {
return 1;
}
fn do_thing() {}
fn condition_not_met() -> bool {
false
}
fn do_next_thing() {}
fn do_last_thing() {}
fn labelled_block1() -> i64 {
let result = 'block: {
do_thing();
@ -457,19 +469,20 @@ fn labelled_block1() -> i64 {
do_last_thing();
3
};
result
}
fn labelled_block2() -> i64 {
fn labelled_block2() {
let result = 'block: {
let x: Option<i64> = None;
let Some(y) = x else {
break 'block 1;
};
x
0
};
}
fn test_nested_function() {
fn test_nested_function2() {
let mut x = 0;
fn nested(x: &mut i64) {
*x += 1;