Skip to content

Conversation

chenyukang
Copy link
Member

@chenyukang chenyukang commented Aug 13, 2022

Fixes #100478
Fixes #101097

@rust-highfive
Copy link
Contributor

r? @lcnr

(rust-highfive has picked a reviewer for you, use r? to override)

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Aug 13, 2022
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 13, 2022
@chenyukang
Copy link
Member Author

chenyukang commented Aug 13, 2022

@jackh726
My fix maybe not the best solution, feel free give other solutions.

If you would like to have a debug, here is a log for you to inspect:
check.log

@compiler-errors
Copy link
Member

compiler-errors commented Aug 13, 2022

Thanks for finding this @chenyukang.

Also remember to use "fixes" instead of "fixing" :)

@chenyukang
Copy link
Member Author

Thanks for finding this @chenyukang.

Also remember to use "fixes" instead of "fixing" :)

Aha, seems it's my habit😁
I found we also can link issues with Fixing, but fixing seems not work.

@jackh726
Copy link
Member

@chenyukang thanks for the PR. This indeed doesn't seem like the correct fix. I think this masks a different problem. There's an unstated assertion that if find_issue returns None, then we can eliminate at least some provided/expected args. The fact that this isn't the case seems like there is a discrepancy between find_issue and eliminate_satisfied.

Is the log that you provided for the test you added? The test seems to have 11 args and the log has 15/16?

@jackh726
Copy link
Member

Just looking at the log and comparing it to the what would happen. There's actually a couple things we could change.

But let's look going backwards at "most straightforward" fix.
Last cycle:

x|  0  1  2  3  4  5  -  -  -  -  -  - 
0|  0  1  0  0  0  0 
1|  0  0  1  0  0  0 
2|  0  0  0  1  0  0 
3|  0  0  0  0  1  0 
4|  0  0  0  0  0  1 
5|  1  0  1  0  0  0

We should detect this as a permutation, I think. Or that column 1 is extra, followed by row 5 extra. This suggests there's a bug in our permutation detection.

Actually though, all the back towards the beginning, first call to find_issue:

x|  0  1  2  3  4  5  6  7  8  9  -  -  -  -  -  -  -  -  -  - 
0|  0  1  0  0  0  0  0  0  0  0 
1|  0  0  1  0  0  0  0  0  0  0 
2|  0  0  0  1  0  0  0  0  0  0 
3|  0  0  0  0  1  0  0  0  0  0 
4|  0  0  0  0  0  1  0  0  0  0 
5|  1  0  1  0  0  0  1  0  0  0 
6|  0  0  0  0  0  0  0  1  0  0 
7|  0  0  0  0  0  0  0  0  1  0 
8|  0  0  0  0  0  0  0  0  0  1 

It would be nice to identify that column 1 is "extra", rather than that row 9 is "missing".

@chenyukang
Copy link
Member Author

chenyukang commented Aug 14, 2022

It would be nice to identify that column 1 is "extra", rather than that row 9 is "missing".

I guess what you mean should be: column 0 is "missing", rather than that col 9 is "missing" ?since we lack an argument for a input.

Yes, the first iteration is not good.
I also tried this idea, actually my first try is fix this line https://github.com/rust-lang/rust/blob/master/compiler/rustc_typeck/src/check/fn_ctxt/arg_matrix.rs#L136

 // If we eliminate the last row, any left-over inputs are considered missing
 if i >= mat.len() {
    return Some(Issue::Missing(i));   // Fix to Issue::Missing(0)
 }

But this fix will broke another testcase, for function call in testcase https://github.com/rust-lang/rust/blob/master/src/test/ui/argument-suggestions/missing_arguments.rs#L30, this fix print the wrong type for missing arguments:

--- a/src/test/ui/argument-suggestions/missing_arguments.stderr
+++ b/src/test/ui/argument-suggestions/missing_arguments.stderr
@@ -210,10 +210,7 @@ error[E0061]: this function takes 3 arguments but 1 argument was supplied
   --> $DIR/missing_arguments.rs:30:3
    |
 LL |   three_diff(          1.0          );
-   |   ^^^^^^^^^^-------------------------
-   |             |          |
-   |             |          an argument of type `i32` is missing
-   |             an argument of type `&str` is missing
+   |   ^^^^^^^^^^------------------------- two arguments of type `i32` and `f32` are missing
    |
 note: function defined here
   --> $DIR/missing_arguments.rs:5:4
@@ -222,8 +219,8 @@ LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
    |    ^^^^^^^^^^ -------  -------  --------
 help: provide the arguments
    |
-LL |   three_diff(/* i32 */, 1.0, /* &str */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |   three_diff(/* i32 */, /* f32 */, /* &str */);
+   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@chenyukang
Copy link
Member Author

chenyukang commented Aug 14, 2022

@chenyukang thanks for the PR. This indeed doesn't seem like the correct fix. I think this masks a different problem. There's an unstated assertion that if find_issue returns None, then we can eliminate at least some provided/expected args. The fact that this isn't the case seems like there is a discrepancy between find_issue and eliminate_satisfied.

Is the log that you provided for the test you added? The test seems to have 11 args and the log has 15/16?

oh, sorry, I minilized the test case later, droping some several extra parameters at the beginning.

@chenyukang
Copy link
Member Author

chenyukang commented Aug 14, 2022

@jackh726
The root cause is by the special Arc::default(), which could satisfy multiple arguments, and this will introduce we can not eliminate the col 0 as Missing.

This part of checking will not find out the missing 0.

x| 0 1 2 3 4 5 6 7 8 9 - - - - - - - - - -
0| 0 1 0 0 0 0 0 0 0 0
1| 0 0 1 0 0 0 0 0 0 0
2| 0 0 0 1 0 0 0 0 0 0
3| 0 0 0 0 1 0 0 0 0 0
4| 0 0 0 0 0 1 0 0 0 0
5| 1 0 1 0 0 0 1 0 0 0
6| 0 0 0 0 0 0 0 1 0 0
7| 0 0 0 0 0 0 0 0 1 0
8| 0 0 0 0 0 0 0 0 0 1

I worked out another solution, next_unmatched_idx used to tracking the next unmatched indexes, when broke from the for loop, it's a suitable index to return, this will also return the right index for the case three_diff I mentioned above.

By the way, I fixed some comments which didn't get right between the arguments and input. I found in code, input means the user's input and arguments means the function's expected parameter list.

This is how the compatibility_matrix is constructed:

let compatibility_matrix = (0..provided_count)
            .map(|i| {
                (0..expected_input_count)
                    .map(|j| is_compatible(ProvidedIdx::from_usize(i), ExpectedIdx::from_usize(j)))
                    .collect()
            })
            .collect();
        ArgMatrix {
            provided_indices: (0..provided_count).map(ProvidedIdx::from_usize).collect(),
            expected_indices: (0..expected_input_count).map(ExpectedIdx::from_usize).collect(),
            compatibility_matrix,
        }

...

let ai = &self.expected_indices;
let ii = &self.provided_indices;

This is not match with the comments in b6c87c5:

It helps to understand this argument by paying special attention to terminology: "inputs" refers to the inputs being expected by the function, and "arguments" refers to what has been provided at the call site.
...

  • Construct a boolean grid, with a row for each argument, and a column for each input. The cell [i, j] is true if the i'th argument could satisfy the j'th input.

Anyway, I think we'd better keep the naming choice in the code now.

@lcnr
Copy link
Contributor

lcnr commented Aug 17, 2022

r? @jackh726 it seems like you're already familiar with this code

@rust-highfive rust-highfive assigned jackh726 and unassigned lcnr Aug 17, 2022
@rust-log-analyzer

This comment has been minimized.

@chenyukang
Copy link
Member Author

@jackh726
#101097, there is another case will cause infinite loop in arguments checking, the algorithm didn't cover the case that there are multiple inputs compatiable with each other.

Debugging code FYI: https://github.com/chenyukang/rust/pull/1/files

struct A;
struct B;
struct C;
struct D;

fn f(
    a1: A,
    a2: A,
    b1: B,
    b2: B,
    c1: C,
    c2: C,
) {}

fn main() {
    f(C, C, A, A, B, B);
}

The debug log is:

ai: [ExpectedIdx(0), ExpectedIdx(1), ExpectedIdx(2), ExpectedIdx(3), ExpectedIdx(4), ExpectedIdx(5)]
ii: [ProvidedIdx(0), ProvidedIdx(1), ProvidedIdx(2), ProvidedIdx(3), ProvidedIdx(4), ProvidedIdx(5)]
================== find_issue: ==================
x|  0  1  2  3  4  5
-|  -  -  -  -  -  -
0|  0  0  0  0  1  1
1|  0  0  0  0  1  1
2|  1  1  0  0  0  0
3|  1  1  0  0  0  0
4|  0  0  1  1  0  0
5|  0  0  1  1  0  0
i: 0, is_input: true, is_arg: true, useless: false, unsatisfiable: false
i: 1, is_input: true, is_arg: true, useless: false, unsatisfiable: false
i: 2, is_input: true, is_arg: true, useless: false, unsatisfiable: false
i: 3, is_input: true, is_arg: true, useless: false, unsatisfiable: false
i: 4, is_input: true, is_arg: true, useless: false, unsatisfiable: false
i: 5, is_input: true, is_arg: true, useless: false, unsatisfiable: false
loop i: 0 j: 0 compat: [4, 5]
permutation_found: false
now permutation: [Some(None), None, None, None, None, None]
loop i: 1 j: 1 compat: [4, 5]
permutation_found: false
now permutation: [Some(None), Some(None), None, None, None, None]
loop i: 2 j: 2 compat: [0, 1]
permutation_found: false
now permutation: [Some(None), Some(None), Some(None), None, None, None]
loop i: 3 j: 3 compat: [0, 1]
permutation_found: false
now permutation: [Some(None), Some(None), Some(None), Some(None), None, None]
loop i: 4 j: 4 compat: [2, 3]
permutation_found: false
now permutation: [Some(None), Some(None), Some(None), Some(None), Some(None), None]
loop i: 5 j: 5 compat: [2, 3]
permutation_found: false
now permutation: [Some(None), Some(None), Some(None), Some(None), Some(None), Some(None)]
res: None
thread 'rustc' panicked at 'didn't eliminated any indice in this round', compiler/rustc_typeck/src/check/fn_ctxt/arg_matrix.rs:412:21

@chenyukang
Copy link
Member Author

b9bdc01
will fix this issue.

@chenyukang
Copy link
Member Author

Another similar case is:

struct A;
struct B;
struct C;
struct D;

fn f(
    a1: A,
    a2: A,
    b1: B,
    b2: B,
    c1: C,
    c2: C,
) {}

fn main() {
    f(C, A, A, A, B, B, C);
}

with log:

ai: [ExpectedIdx(0), ExpectedIdx(2), ExpectedIdx(3), ExpectedIdx(4), ExpectedIdx(5)]
ii: [ProvidedIdx(0), ProvidedIdx(2), ProvidedIdx(3), ProvidedIdx(4), ProvidedIdx(5), ProvidedIdx(6)]
================== find_issue: ==================
x|  0  1  2  3  4
-|  -  -  -  -  -
0|  0  0  0  1  1
1|  1  0  0  0  0
2|  1  0  0  0  0
3|  0  1  1  0  0
4|  0  1  1  0  0
5|  0  0  0  1  1
i: 0, is_input: true, is_arg: true, useless: false, unsatisfiable: false
i: 1, is_input: true, is_arg: true, useless: false, unsatisfiable: false
i: 2, is_input: true, is_arg: true, useless: false, unsatisfiable: false
i: 3, is_input: true, is_arg: true, useless: false, unsatisfiable: false
i: 4, is_input: true, is_arg: true, useless: false, unsatisfiable: false
i: 5, is_input: true, is_arg: false, useless: false, unsatisfiable: true
loop i: 0 j: 0 compat: [3, 4]
permutation_found: false
now permutation: [Some(None), None, None, None, None, None]
loop i: 1 j: 1 compat: [0]
loop i: 1 j: 0 compat: [3, 4]
permutation_found: false
now permutation: [Some(None), None, None, None, None, None]
now permutation: [Some(None), Some(None), None, None, None, None]
loop i: 2 j: 2 compat: [0]
loop i: 2 j: 0 compat: [3, 4]
permutation_found: false
now permutation: [Some(None), Some(None), None, None, None, None]
now permutation: [Some(None), Some(None), Some(None), None, None, None]
loop i: 3 j: 3 compat: [1, 2]
permutation_found: false
now permutation: [Some(None), Some(None), Some(None), Some(None), None, None]
loop i: 4 j: 4 compat: [1, 2]
permutation_found: false
now permutation: [Some(None), Some(None), Some(None), Some(None), Some(None), None]
loop i: 5 j: 5 compat: [3, 4]
permutation_found: false
now permutation: [Some(None), Some(None), Some(None), Some(None), Some(None), Some(None)]
res: None
thread 'rustc' panicked at 'didn't eliminated any indice in this round', compiler/rustc_typeck/src/check/fn_ctxt/arg_matrix.rs:412:21

@rust-log-analyzer

This comment has been minimized.

@jackh726
Copy link
Member

@bors r+

@bors
Copy link
Collaborator

bors commented Sep 12, 2022

📌 Commit 7e7dfb8 has been approved by jackh726

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 12, 2022
@bors
Copy link
Collaborator

bors commented Sep 12, 2022

⌛ Testing commit 7e7dfb8 with merge 56e7678...

@bors
Copy link
Collaborator

bors commented Sep 12, 2022

☀️ Test successful - checks-actions
Approved by: jackh726
Pushing 56e7678 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Sep 12, 2022
@bors bors merged commit 56e7678 into rust-lang:master Sep 12, 2022
@rustbot rustbot added this to the 1.65.0 milestone Sep 12, 2022
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (56e7678): comparison URL.

Overall result: ❌ regressions - no action needed

@rustbot label: -perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
5.0% [5.0%, 5.0%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
3.6% [2.6%, 4.6%] 2
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-4.9% [-4.9%, -4.9%] 1
Improvements ✅
(secondary)
-0.9% [-0.9%, -0.9%] 1
All ❌✅ (primary) 0.8% [-4.9%, 4.6%] 3

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
3.4% [3.4%, 3.4%] 1
Regressions ❌
(secondary)
2.9% [2.9%, 2.9%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 3.4% [3.4%, 3.4%] 1

Footnotes

  1. the arithmetic mean of the percent change 2 3

  2. number of relevant changes 2 3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

infinite loop during function argument check rustc enters an infinite loop when doing cargo check
9 participants