mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 02:33:55 +00:00
Avoid infinite loop in function arguments checking
This commit is contained in:
parent
3c72788461
commit
50e5d03e16
@ -130,14 +130,17 @@ impl<'tcx> ArgMatrix<'tcx> {
|
||||
let ai = &self.expected_indices;
|
||||
let ii = &self.provided_indices;
|
||||
|
||||
// Issue: 100478, when we end the iteration,
|
||||
// `next_unmatched_idx` will point to the index of the first unmatched
|
||||
let mut next_unmatched_idx = 0;
|
||||
for i in 0..cmp::max(ai.len(), ii.len()) {
|
||||
// If we eliminate the last row, any left-over inputs are considered missing
|
||||
// If we eliminate the last row, any left-over arguments are considered missing
|
||||
if i >= mat.len() {
|
||||
return Some(Issue::Missing(i));
|
||||
return Some(Issue::Missing(next_unmatched_idx));
|
||||
}
|
||||
// If we eliminate the last column, any left-over arguments are extra
|
||||
// If we eliminate the last column, any left-over inputs are extra
|
||||
if mat[i].len() == 0 {
|
||||
return Some(Issue::Extra(i));
|
||||
return Some(Issue::Extra(next_unmatched_idx));
|
||||
}
|
||||
|
||||
// Make sure we don't pass the bounds of our matrix
|
||||
@ -145,6 +148,7 @@ impl<'tcx> ArgMatrix<'tcx> {
|
||||
let is_input = i < ii.len();
|
||||
if is_arg && is_input && matches!(mat[i][i], Compatibility::Compatible) {
|
||||
// This is a satisfied input, so move along
|
||||
next_unmatched_idx += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -163,7 +167,7 @@ impl<'tcx> ArgMatrix<'tcx> {
|
||||
if is_input {
|
||||
for j in 0..ai.len() {
|
||||
// If we find at least one argument that could satisfy this input
|
||||
// this argument isn't useless
|
||||
// this input isn't useless
|
||||
if matches!(mat[i][j], Compatibility::Compatible) {
|
||||
useless = false;
|
||||
break;
|
||||
@ -309,7 +313,8 @@ impl<'tcx> ArgMatrix<'tcx> {
|
||||
}
|
||||
|
||||
while !self.provided_indices.is_empty() || !self.expected_indices.is_empty() {
|
||||
match self.find_issue() {
|
||||
let res = self.find_issue();
|
||||
match res {
|
||||
Some(Issue::Invalid(idx)) => {
|
||||
let compatibility = self.compatibility_matrix[idx][idx].clone();
|
||||
let input_idx = self.provided_indices[idx];
|
||||
@ -364,7 +369,9 @@ impl<'tcx> ArgMatrix<'tcx> {
|
||||
None => {
|
||||
// We didn't find any issues, so we need to push the algorithm forward
|
||||
// First, eliminate any arguments that currently satisfy their inputs
|
||||
for (inp, arg) in self.eliminate_satisfied() {
|
||||
let eliminated = self.eliminate_satisfied();
|
||||
assert!(!eliminated.is_empty(), "didn't eliminated any indice in this round");
|
||||
for (inp, arg) in eliminated {
|
||||
matched_inputs[arg] = Some(inp);
|
||||
}
|
||||
}
|
||||
|
52
src/test/ui/argument-suggestions/issue-100478.rs
Normal file
52
src/test/ui/argument-suggestions/issue-100478.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use std::sync::Arc;
|
||||
macro_rules! GenT {
|
||||
($name:tt) => {
|
||||
#[derive(Default, Debug)]
|
||||
struct $name {
|
||||
#[allow(unused)]
|
||||
val: i32,
|
||||
}
|
||||
|
||||
impl $name {
|
||||
#[allow(unused)]
|
||||
fn new(val: i32) -> Self {
|
||||
$name { val }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
GenT!(T1);
|
||||
GenT!(T2);
|
||||
GenT!(T3);
|
||||
GenT!(T4);
|
||||
GenT!(T5);
|
||||
GenT!(T6);
|
||||
GenT!(T7);
|
||||
GenT!(T8);
|
||||
|
||||
#[allow(unused)]
|
||||
fn foo(p1: T1, p2: Arc<T2>, p3: T3, p4: Arc<T4>, p5: T5, p6: T6, p7: T7, p8: Arc<T8>) {}
|
||||
fn three_diff(_a: T1, _b: T2, _c: T3) {}
|
||||
fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {}
|
||||
|
||||
fn main() {
|
||||
three_diff(T2::new(0)); //~ ERROR this function takes
|
||||
four_shuffle(T3::default(), T4::default(), T1::default(), T2::default()); //~ ERROR 35:5: 35:17: arguments to this function are incorrect [E0308]
|
||||
four_shuffle(T3::default(), T2::default(), T1::default(), T3::default()); //~ ERROR 36:5: 36:17: arguments to this function are incorrect [E0308]
|
||||
|
||||
let p1 = T1::new(0);
|
||||
let p2 = Arc::new(T2::new(0));
|
||||
let p3 = T3::new(0);
|
||||
let p4 = Arc::new(T4::new(1));
|
||||
let p5 = T5::new(0);
|
||||
let p6 = T6::new(0);
|
||||
let p7 = T7::new(0);
|
||||
let p8 = Arc::default();
|
||||
|
||||
foo(
|
||||
//~^ 47:5: 47:8: this function takes 8 arguments but 7 arguments were supplied [E0061]
|
||||
p1, //p2,
|
||||
p3, p4, p5, p6, p7, p8,
|
||||
);
|
||||
}
|
81
src/test/ui/argument-suggestions/issue-100478.stderr
Normal file
81
src/test/ui/argument-suggestions/issue-100478.stderr
Normal file
@ -0,0 +1,81 @@
|
||||
error[E0061]: this function takes 3 arguments but 1 argument was supplied
|
||||
--> $DIR/issue-100478.rs:34:5
|
||||
|
|
||||
LL | three_diff(T2::new(0));
|
||||
| ^^^^^^^^^^------------
|
||||
| ||
|
||||
| |an argument of type `T1` is missing
|
||||
| an argument of type `T3` is missing
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/issue-100478.rs:30:4
|
||||
|
|
||||
LL | fn three_diff(_a: T1, _b: T2, _c: T3) {}
|
||||
| ^^^^^^^^^^ ------ ------ ------
|
||||
help: provide the arguments
|
||||
|
|
||||
LL | three_diff(/* T1 */, T2::new(0), /* T3 */);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0308]: arguments to this function are incorrect
|
||||
--> $DIR/issue-100478.rs:35:5
|
||||
|
|
||||
LL | four_shuffle(T3::default(), T4::default(), T1::default(), T2::default());
|
||||
| ^^^^^^^^^^^^ ------------- ------------- ------------- ------------- expected `T4`, found `T2`
|
||||
| | | |
|
||||
| | | expected `T3`, found `T1`
|
||||
| | expected `T2`, found `T4`
|
||||
| expected `T1`, found `T3`
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/issue-100478.rs:31:4
|
||||
|
|
||||
LL | fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {}
|
||||
| ^^^^^^^^^^^^ ------ ------ ------ ------
|
||||
help: did you mean
|
||||
|
|
||||
LL | four_shuffle(T1::default(), T2::default(), T3::default(), T4::default());
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0308]: arguments to this function are incorrect
|
||||
--> $DIR/issue-100478.rs:36:5
|
||||
|
|
||||
LL | four_shuffle(T3::default(), T2::default(), T1::default(), T3::default());
|
||||
| ^^^^^^^^^^^^ ------------- ------------- ------------- expected struct `T4`, found struct `T3`
|
||||
| | |
|
||||
| | expected `T3`, found `T1`
|
||||
| expected `T1`, found `T3`
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/issue-100478.rs:31:4
|
||||
|
|
||||
LL | fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {}
|
||||
| ^^^^^^^^^^^^ ------ ------ ------ ------
|
||||
help: swap these arguments
|
||||
|
|
||||
LL | four_shuffle(T1::default(), T2::default(), T3::default(), /* T4 */);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0061]: this function takes 8 arguments but 7 arguments were supplied
|
||||
--> $DIR/issue-100478.rs:47:5
|
||||
|
|
||||
LL | foo(
|
||||
| ^^^
|
||||
...
|
||||
LL | p3, p4, p5, p6, p7, p8,
|
||||
| -- an argument of type `Arc<T2>` is missing
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/issue-100478.rs:29:4
|
||||
|
|
||||
LL | fn foo(p1: T1, p2: Arc<T2>, p3: T3, p4: Arc<T4>, p5: T5, p6: T6, p7: T7, p8: Arc<T8>) {}
|
||||
| ^^^ ------ ----------- ------ ----------- ------ ------ ------ -----------
|
||||
help: provide the argument
|
||||
|
|
||||
LL | foo(p1, /* Arc<T2> */, p3, p4, p5, p6, p7, p8);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0061, E0308.
|
||||
For more information about an error, try `rustc --explain E0061`.
|
Loading…
Reference in New Issue
Block a user