Skip to content

Commit 56e7678

Browse files
committedSep 12, 2022
Auto merge of #100502 - chenyukang:fix-100478, r=jackh726
Avoid infinite loop in function arguments checking Fixes #100478 Fixes #101097
2 parents 3194958 + 7e7dfb8 commit 56e7678

File tree

5 files changed

+330
-9
lines changed

5 files changed

+330
-9
lines changed
 

‎compiler/rustc_typeck/src/check/fn_ctxt/arg_matrix.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -130,21 +130,25 @@ impl<'tcx> ArgMatrix<'tcx> {
130130
let ai = &self.expected_indices;
131131
let ii = &self.provided_indices;
132132

133+
// Issue: 100478, when we end the iteration,
134+
// `next_unmatched_idx` will point to the index of the first unmatched
135+
let mut next_unmatched_idx = 0;
133136
for i in 0..cmp::max(ai.len(), ii.len()) {
134-
// If we eliminate the last row, any left-over inputs are considered missing
137+
// If we eliminate the last row, any left-over arguments are considered missing
135138
if i >= mat.len() {
136-
return Some(Issue::Missing(i));
139+
return Some(Issue::Missing(next_unmatched_idx));
137140
}
138-
// If we eliminate the last column, any left-over arguments are extra
141+
// If we eliminate the last column, any left-over inputs are extra
139142
if mat[i].len() == 0 {
140-
return Some(Issue::Extra(i));
143+
return Some(Issue::Extra(next_unmatched_idx));
141144
}
142145

143146
// Make sure we don't pass the bounds of our matrix
144147
let is_arg = i < ai.len();
145148
let is_input = i < ii.len();
146149
if is_arg && is_input && matches!(mat[i][i], Compatibility::Compatible) {
147150
// This is a satisfied input, so move along
151+
next_unmatched_idx += 1;
148152
continue;
149153
}
150154

@@ -163,7 +167,7 @@ impl<'tcx> ArgMatrix<'tcx> {
163167
if is_input {
164168
for j in 0..ai.len() {
165169
// If we find at least one argument that could satisfy this input
166-
// this argument isn't useless
170+
// this input isn't useless
167171
if matches!(mat[i][j], Compatibility::Compatible) {
168172
useless = false;
169173
break;
@@ -232,8 +236,8 @@ impl<'tcx> ArgMatrix<'tcx> {
232236
if matches!(c, Compatibility::Compatible) { Some(i) } else { None }
233237
})
234238
.collect();
235-
if compat.len() != 1 {
236-
// this could go into multiple slots, don't bother exploring both
239+
if compat.len() < 1 {
240+
// try to find a cycle even when this could go into multiple slots, see #101097
237241
is_cycle = false;
238242
break;
239243
}
@@ -309,7 +313,8 @@ impl<'tcx> ArgMatrix<'tcx> {
309313
}
310314

311315
while !self.provided_indices.is_empty() || !self.expected_indices.is_empty() {
312-
match self.find_issue() {
316+
let res = self.find_issue();
317+
match res {
313318
Some(Issue::Invalid(idx)) => {
314319
let compatibility = self.compatibility_matrix[idx][idx].clone();
315320
let input_idx = self.provided_indices[idx];
@@ -364,7 +369,9 @@ impl<'tcx> ArgMatrix<'tcx> {
364369
None => {
365370
// We didn't find any issues, so we need to push the algorithm forward
366371
// First, eliminate any arguments that currently satisfy their inputs
367-
for (inp, arg) in self.eliminate_satisfied() {
372+
let eliminated = self.eliminate_satisfied();
373+
assert!(!eliminated.is_empty(), "didn't eliminated any indice in this round");
374+
for (inp, arg) in eliminated {
368375
matched_inputs[arg] = Some(inp);
369376
}
370377
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use std::sync::Arc;
2+
macro_rules! GenT {
3+
($name:tt) => {
4+
#[derive(Default, Debug)]
5+
struct $name {
6+
#[allow(unused)]
7+
val: i32,
8+
}
9+
10+
impl $name {
11+
#[allow(unused)]
12+
fn new(val: i32) -> Self {
13+
$name { val }
14+
}
15+
}
16+
};
17+
}
18+
19+
GenT!(T1);
20+
GenT!(T2);
21+
GenT!(T3);
22+
GenT!(T4);
23+
GenT!(T5);
24+
GenT!(T6);
25+
GenT!(T7);
26+
GenT!(T8);
27+
28+
#[allow(unused)]
29+
fn foo(p1: T1, p2: Arc<T2>, p3: T3, p4: Arc<T4>, p5: T5, p6: T6, p7: T7, p8: Arc<T8>) {}
30+
fn three_diff(_a: T1, _b: T2, _c: T3) {}
31+
fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {}
32+
33+
fn main() {
34+
three_diff(T2::new(0)); //~ ERROR this function takes
35+
four_shuffle(T3::default(), T4::default(), T1::default(), T2::default()); //~ ERROR 35:5: 35:17: arguments to this function are incorrect [E0308]
36+
four_shuffle(T3::default(), T2::default(), T1::default(), T3::default()); //~ ERROR 36:5: 36:17: arguments to this function are incorrect [E0308]
37+
38+
let p1 = T1::new(0);
39+
let p2 = Arc::new(T2::new(0));
40+
let p3 = T3::new(0);
41+
let p4 = Arc::new(T4::new(1));
42+
let p5 = T5::new(0);
43+
let p6 = T6::new(0);
44+
let p7 = T7::new(0);
45+
let p8 = Arc::default();
46+
47+
foo(
48+
//~^ 47:5: 47:8: this function takes 8 arguments but 7 arguments were supplied [E0061]
49+
p1, //p2,
50+
p3, p4, p5, p6, p7, p8,
51+
);
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
error[E0061]: this function takes 3 arguments but 1 argument was supplied
2+
--> $DIR/issue-100478.rs:34:5
3+
|
4+
LL | three_diff(T2::new(0));
5+
| ^^^^^^^^^^------------
6+
| ||
7+
| |an argument of type `T1` is missing
8+
| an argument of type `T3` is missing
9+
|
10+
note: function defined here
11+
--> $DIR/issue-100478.rs:30:4
12+
|
13+
LL | fn three_diff(_a: T1, _b: T2, _c: T3) {}
14+
| ^^^^^^^^^^ ------ ------ ------
15+
help: provide the arguments
16+
|
17+
LL | three_diff(/* T1 */, T2::new(0), /* T3 */);
18+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19+
20+
error[E0308]: arguments to this function are incorrect
21+
--> $DIR/issue-100478.rs:35:5
22+
|
23+
LL | four_shuffle(T3::default(), T4::default(), T1::default(), T2::default());
24+
| ^^^^^^^^^^^^ ------------- ------------- ------------- ------------- expected `T4`, found `T2`
25+
| | | |
26+
| | | expected `T3`, found `T1`
27+
| | expected `T2`, found `T4`
28+
| expected `T1`, found `T3`
29+
|
30+
note: function defined here
31+
--> $DIR/issue-100478.rs:31:4
32+
|
33+
LL | fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {}
34+
| ^^^^^^^^^^^^ ------ ------ ------ ------
35+
help: did you mean
36+
|
37+
LL | four_shuffle(T1::default(), T2::default(), T3::default(), T4::default());
38+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39+
40+
error[E0308]: arguments to this function are incorrect
41+
--> $DIR/issue-100478.rs:36:5
42+
|
43+
LL | four_shuffle(T3::default(), T2::default(), T1::default(), T3::default());
44+
| ^^^^^^^^^^^^ ------------- ------------- ------------- expected struct `T4`, found struct `T3`
45+
| | |
46+
| | expected `T3`, found `T1`
47+
| expected `T1`, found `T3`
48+
|
49+
note: function defined here
50+
--> $DIR/issue-100478.rs:31:4
51+
|
52+
LL | fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {}
53+
| ^^^^^^^^^^^^ ------ ------ ------ ------
54+
help: swap these arguments
55+
|
56+
LL | four_shuffle(T1::default(), T2::default(), T3::default(), /* T4 */);
57+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
58+
59+
error[E0061]: this function takes 8 arguments but 7 arguments were supplied
60+
--> $DIR/issue-100478.rs:47:5
61+
|
62+
LL | foo(
63+
| ^^^
64+
...
65+
LL | p3, p4, p5, p6, p7, p8,
66+
| -- an argument of type `Arc<T2>` is missing
67+
|
68+
note: function defined here
69+
--> $DIR/issue-100478.rs:29:4
70+
|
71+
LL | fn foo(p1: T1, p2: Arc<T2>, p3: T3, p4: Arc<T4>, p5: T5, p6: T6, p7: T7, p8: Arc<T8>) {}
72+
| ^^^ ------ ----------- ------ ----------- ------ ------ ------ -----------
73+
help: provide the argument
74+
|
75+
LL | foo(p1, /* Arc<T2> */, p3, p4, p5, p6, p7, p8);
76+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
77+
78+
error: aborting due to 4 previous errors
79+
80+
Some errors have detailed explanations: E0061, E0308.
81+
For more information about an error, try `rustc --explain E0061`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
struct A;
2+
struct B;
3+
struct C;
4+
struct D;
5+
6+
fn f(
7+
a1: A,
8+
a2: A,
9+
b1: B,
10+
b2: B,
11+
c1: C,
12+
c2: C,
13+
) {}
14+
15+
fn main() {
16+
f(C, A, A, A, B, B, C); //~ ERROR this function takes 6 arguments but 7 arguments were supplied [E0061]
17+
f(C, C, A, A, B, B); //~ ERROR arguments to this function are incorrect [E0308]
18+
f(A, A, D, D, B, B); //~ arguments to this function are incorrect [E0308]
19+
f(C, C, B, B, A, A); //~ arguments to this function are incorrect [E0308]
20+
f(C, C, A, B, A, A); //~ arguments to this function are incorrect [E0308]
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
error[E0061]: this function takes 6 arguments but 7 arguments were supplied
2+
--> $DIR/issue-101097.rs:16:5
3+
|
4+
LL | f(C, A, A, A, B, B, C);
5+
| ^ - - - - expected `C`, found `B`
6+
| | | |
7+
| | | argument of type `A` unexpected
8+
| | expected `B`, found `A`
9+
| expected `A`, found `C`
10+
|
11+
note: function defined here
12+
--> $DIR/issue-101097.rs:6:4
13+
|
14+
LL | fn f(
15+
| ^
16+
LL | a1: A,
17+
| -----
18+
LL | a2: A,
19+
| -----
20+
LL | b1: B,
21+
| -----
22+
LL | b2: B,
23+
| -----
24+
LL | c1: C,
25+
| -----
26+
LL | c2: C,
27+
| -----
28+
help: did you mean
29+
|
30+
LL | f(A, A, B, B, C, C);
31+
| ~~~~~~~~~~~~~~~~~~
32+
33+
error[E0308]: arguments to this function are incorrect
34+
--> $DIR/issue-101097.rs:17:5
35+
|
36+
LL | f(C, C, A, A, B, B);
37+
| ^
38+
|
39+
note: function defined here
40+
--> $DIR/issue-101097.rs:6:4
41+
|
42+
LL | fn f(
43+
| ^
44+
LL | a1: A,
45+
| -----
46+
LL | a2: A,
47+
| -----
48+
LL | b1: B,
49+
| -----
50+
LL | b2: B,
51+
| -----
52+
LL | c1: C,
53+
| -----
54+
LL | c2: C,
55+
| -----
56+
help: did you mean
57+
|
58+
LL | f(A, A, B, B, C, C);
59+
| ~~~~~~~~~~~~~~~~~~
60+
61+
error[E0308]: arguments to this function are incorrect
62+
--> $DIR/issue-101097.rs:18:5
63+
|
64+
LL | f(A, A, D, D, B, B);
65+
| ^ - - ---- two arguments of type `C` and `C` are missing
66+
| | |
67+
| | argument of type `D` unexpected
68+
| argument of type `D` unexpected
69+
|
70+
note: function defined here
71+
--> $DIR/issue-101097.rs:6:4
72+
|
73+
LL | fn f(
74+
| ^
75+
LL | a1: A,
76+
| -----
77+
LL | a2: A,
78+
| -----
79+
LL | b1: B,
80+
| -----
81+
LL | b2: B,
82+
| -----
83+
LL | c1: C,
84+
| -----
85+
LL | c2: C,
86+
| -----
87+
help: did you mean
88+
|
89+
LL | f(A, A, B, B, /* C */, /* C */);
90+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
91+
92+
error[E0308]: arguments to this function are incorrect
93+
--> $DIR/issue-101097.rs:19:5
94+
|
95+
LL | f(C, C, B, B, A, A);
96+
| ^ - - - - expected `C`, found `A`
97+
| | | |
98+
| | | expected `C`, found `A`
99+
| | expected `A`, found `C`
100+
| expected `A`, found `C`
101+
|
102+
note: function defined here
103+
--> $DIR/issue-101097.rs:6:4
104+
|
105+
LL | fn f(
106+
| ^
107+
LL | a1: A,
108+
| -----
109+
LL | a2: A,
110+
| -----
111+
LL | b1: B,
112+
| -----
113+
LL | b2: B,
114+
| -----
115+
LL | c1: C,
116+
| -----
117+
LL | c2: C,
118+
| -----
119+
help: did you mean
120+
|
121+
LL | f(A, A, B, B, C, C);
122+
| ~~~~~~~~~~~~~~~~~~
123+
124+
error[E0308]: arguments to this function are incorrect
125+
--> $DIR/issue-101097.rs:20:5
126+
|
127+
LL | f(C, C, A, B, A, A);
128+
| ^ - - - - - expected `C`, found `A`
129+
| | | | |
130+
| | | | expected `C`, found `A`
131+
| | | expected struct `B`, found struct `A`
132+
| | expected `A`, found `C`
133+
| expected `A`, found `C`
134+
|
135+
note: function defined here
136+
--> $DIR/issue-101097.rs:6:4
137+
|
138+
LL | fn f(
139+
| ^
140+
LL | a1: A,
141+
| -----
142+
LL | a2: A,
143+
| -----
144+
LL | b1: B,
145+
| -----
146+
LL | b2: B,
147+
| -----
148+
LL | c1: C,
149+
| -----
150+
LL | c2: C,
151+
| -----
152+
help: did you mean
153+
|
154+
LL | f(A, A, /* B */, B, C, C);
155+
| ~~~~~~~~~~~~~~~~~~~~~~~~
156+
157+
error: aborting due to 5 previous errors
158+
159+
Some errors have detailed explanations: E0061, E0308.
160+
For more information about an error, try `rustc --explain E0061`.

0 commit comments

Comments
 (0)
Please sign in to comment.