@@ -3,6 +3,7 @@ use std::cmp;
33use rustc_middle:: ty:: error:: TypeError ;
44
55// An issue that might be found in the compatibility matrix
6+ #[ derive( Debug ) ]
67enum Issue {
78 /// The given argument is the invalid type for the input
89 Invalid ( usize ) ,
@@ -23,9 +24,10 @@ pub(crate) enum Compatibility<'tcx> {
2324}
2425
2526/// Similar to `Issue`, but contains some extra information
27+ #[ derive( Debug ) ]
2628pub ( crate ) enum Error < ' tcx > {
27- /// The given argument is the invalid type for the input
28- Invalid ( usize , Compatibility < ' tcx > ) ,
29+ /// The provided argument is the invalid type for the expected input
30+ Invalid ( usize , usize , Compatibility < ' tcx > ) , // provided, expected
2931 /// There is a missing input
3032 Missing ( usize ) ,
3133 /// There's a superfluous argument
@@ -37,8 +39,15 @@ pub(crate) enum Error<'tcx> {
3739}
3840
3941pub ( crate ) struct ArgMatrix < ' tcx > {
42+ /// Maps the indices in the `compatibility_matrix` rows to the indices of
43+ /// the *user provided* inputs
4044 input_indexes : Vec < usize > ,
45+ /// Maps the indices in the `compatibility_matrix` columns to the indices
46+ /// of the *expected* args
4147 arg_indexes : Vec < usize > ,
48+ /// The first dimension (rows) are the remaining user provided inputs to
49+ /// match and the second dimension (cols) are the remaining expected args
50+ /// to match
4251 compatibility_matrix : Vec < Vec < Compatibility < ' tcx > > > ,
4352}
4453
@@ -52,24 +61,24 @@ impl<'tcx> ArgMatrix<'tcx> {
5261 . map ( |i| ( 0 ..minimum_input_count) . map ( |j| is_compatible ( i, j) ) . collect ( ) )
5362 . collect ( ) ;
5463 ArgMatrix {
55- input_indexes : ( 0 ..minimum_input_count ) . collect ( ) ,
56- arg_indexes : ( 0 ..provided_arg_count ) . collect ( ) ,
64+ input_indexes : ( 0 ..provided_arg_count ) . collect ( ) ,
65+ arg_indexes : ( 0 ..minimum_input_count ) . collect ( ) ,
5766 compatibility_matrix,
5867 }
5968 }
6069
6170 /// Remove a given input from consideration
6271 fn eliminate_input ( & mut self , idx : usize ) {
6372 self . input_indexes . remove ( idx) ;
64- for row in & mut self . compatibility_matrix {
65- row. remove ( idx) ;
66- }
73+ self . compatibility_matrix . remove ( idx) ;
6774 }
6875
6976 /// Remove a given argument from consideration
7077 fn eliminate_arg ( & mut self , idx : usize ) {
7178 self . arg_indexes . remove ( idx) ;
72- self . compatibility_matrix . remove ( idx) ;
79+ for row in & mut self . compatibility_matrix {
80+ row. remove ( idx) ;
81+ }
7382 }
7483
7584 /// "satisfy" an input with a given arg, removing both from consideration
@@ -78,21 +87,23 @@ impl<'tcx> ArgMatrix<'tcx> {
7887 self . eliminate_arg ( arg_idx) ;
7988 }
8089
90+ // Returns a `Vec` of (user input, expected arg) of matched arguments. These
91+ // are inputs on the remaining diagonal that match.
8192 fn eliminate_satisfied ( & mut self ) -> Vec < ( usize , usize ) > {
8293 let mut i = cmp:: min ( self . input_indexes . len ( ) , self . arg_indexes . len ( ) ) ;
8394 let mut eliminated = vec ! [ ] ;
8495 while i > 0 {
8596 let idx = i - 1 ;
8697 if matches ! ( self . compatibility_matrix[ idx] [ idx] , Compatibility :: Compatible ) {
87- eliminated. push ( ( self . arg_indexes [ idx] , self . input_indexes [ idx] ) ) ;
98+ eliminated. push ( ( self . input_indexes [ idx] , self . arg_indexes [ idx] ) ) ;
8899 self . satisfy_input ( idx, idx) ;
89100 }
90101 i -= 1 ;
91102 }
92103 return eliminated;
93104 }
94105
95- // Check for the above mismatch cases
106+ // Find some issue in the compatibility matrix
96107 fn find_issue ( & self ) -> Option < Issue > {
97108 let mat = & self . compatibility_matrix ;
98109 let ai = & self . arg_indexes ;
@@ -121,26 +132,26 @@ impl<'tcx> ArgMatrix<'tcx> {
121132 if is_arg {
122133 for j in 0 ..ii. len ( ) {
123134 // If we find at least one input this argument could satisfy
124- // this argument isn't completely useless
125- if matches ! ( mat[ i ] [ j ] , Compatibility :: Compatible ) {
126- useless = false ;
135+ // this argument isn't unsatisfiable
136+ if matches ! ( mat[ j ] [ i ] , Compatibility :: Compatible ) {
137+ unsatisfiable = false ;
127138 break ;
128139 }
129140 }
130141 }
131142 if is_input {
132143 for j in 0 ..ai. len ( ) {
133144 // If we find at least one argument that could satisfy this input
134- // this argument isn't unsatisfiable
135- if matches ! ( mat[ j ] [ i ] , Compatibility :: Compatible ) {
136- unsatisfiable = false ;
145+ // this argument isn't useless
146+ if matches ! ( mat[ i ] [ j ] , Compatibility :: Compatible ) {
147+ useless = false ;
137148 break ;
138149 }
139150 }
140151 }
141152
142- match ( is_arg , is_input , useless, unsatisfiable) {
143- // If an input is unsatisfied, and the argument in its position is useless
153+ match ( is_input , is_arg , useless, unsatisfiable) {
154+ // If an argument is unsatisfied, and the input in its position is useless
144155 // then the most likely explanation is that we just got the types wrong
145156 ( true , true , true , true ) => return Some ( Issue :: Invalid ( i) ) ,
146157 // Otherwise, if an input is useless, then indicate that this is an extra argument
@@ -167,7 +178,7 @@ impl<'tcx> ArgMatrix<'tcx> {
167178 _ => {
168179 continue ;
169180 }
170- } ;
181+ }
171182 }
172183
173184 // We didn't find any of the individual issues above, but
@@ -254,11 +265,11 @@ impl<'tcx> ArgMatrix<'tcx> {
254265 // We'll want to know which arguments and inputs these rows and columns correspond to
255266 // even after we delete them.
256267 pub ( crate ) fn find_errors ( mut self ) -> ( Vec < Error < ' tcx > > , Vec < Option < usize > > ) {
257- let provided_arg_count = self . arg_indexes . len ( ) ;
268+ let provided_arg_count = self . input_indexes . len ( ) ;
258269
259270 let mut errors: Vec < Error < ' tcx > > = vec ! [ ] ;
260271 // For each expected argument, the matched *actual* input
261- let mut matched_inputs: Vec < Option < usize > > = vec ! [ None ; self . input_indexes . len( ) ] ;
272+ let mut matched_inputs: Vec < Option < usize > > = vec ! [ None ; self . arg_indexes . len( ) ] ;
262273
263274 // Before we start looking for issues, eliminate any arguments that are already satisfied,
264275 // so that an argument which is already spoken for by the input it's in doesn't
@@ -269,28 +280,28 @@ impl<'tcx> ArgMatrix<'tcx> {
269280 // Without this elimination, the first argument causes the second argument
270281 // to show up as both a missing input and extra argument, rather than
271282 // just an invalid type.
272- for ( arg , inp ) in self . eliminate_satisfied ( ) {
273- matched_inputs[ inp ] = Some ( arg ) ;
283+ for ( inp , arg ) in self . eliminate_satisfied ( ) {
284+ matched_inputs[ arg ] = Some ( inp ) ;
274285 }
275286
276287 while self . input_indexes . len ( ) > 0 || self . arg_indexes . len ( ) > 0 {
277- // Check for the first relevant issue
278288 match self . find_issue ( ) {
279289 Some ( Issue :: Invalid ( idx) ) => {
280290 let compatibility = self . compatibility_matrix [ idx] [ idx] . clone ( ) ;
281291 let input_idx = self . input_indexes [ idx] ;
292+ let arg_idx = self . arg_indexes [ idx] ;
282293 self . satisfy_input ( idx, idx) ;
283- errors. push ( Error :: Invalid ( input_idx, compatibility) ) ;
294+ errors. push ( Error :: Invalid ( input_idx, arg_idx , compatibility) ) ;
284295 }
285296 Some ( Issue :: Extra ( idx) ) => {
286- let arg_idx = self . arg_indexes [ idx] ;
287- self . eliminate_arg ( idx) ;
288- errors. push ( Error :: Extra ( arg_idx) ) ;
289- }
290- Some ( Issue :: Missing ( idx) ) => {
291297 let input_idx = self . input_indexes [ idx] ;
292298 self . eliminate_input ( idx) ;
293- errors. push ( Error :: Missing ( input_idx) ) ;
299+ errors. push ( Error :: Extra ( input_idx) ) ;
300+ }
301+ Some ( Issue :: Missing ( idx) ) => {
302+ let arg_idx = self . arg_indexes [ idx] ;
303+ self . eliminate_arg ( idx) ;
304+ errors. push ( Error :: Missing ( arg_idx) ) ;
294305 }
295306 Some ( Issue :: Swap ( idx, other) ) => {
296307 let input_idx = self . input_indexes [ idx] ;
@@ -302,24 +313,21 @@ impl<'tcx> ArgMatrix<'tcx> {
302313 // Subtract 1 because we already removed the "min" row
303314 self . satisfy_input ( max - 1 , min) ;
304315 errors. push ( Error :: Swap ( input_idx, other_input_idx, arg_idx, other_arg_idx) ) ;
305- matched_inputs[ input_idx ] = Some ( other_arg_idx ) ;
306- matched_inputs[ other_input_idx ] = Some ( arg_idx ) ;
316+ matched_inputs[ other_arg_idx ] = Some ( input_idx ) ;
317+ matched_inputs[ arg_idx ] = Some ( other_input_idx ) ;
307318 }
308319 Some ( Issue :: Permutation ( args) ) => {
309- // FIXME: If satisfy_input ever did anything non-trivial (emit obligations to help type checking, for example)
310- // we'd want to call this function with the correct arg/input pairs, but for now, we just throw them in a bucket.
311- // This works because they force a cycle, so each row is guaranteed to also be a column
312320 let mut idxs: Vec < usize > = args. iter ( ) . filter_map ( |& a| a) . collect ( ) ;
313321
314322 let mut real_idxs = vec ! [ None ; provided_arg_count] ;
315323 for ( src, dst) in
316324 args. iter ( ) . enumerate ( ) . filter_map ( |( src, dst) | dst. map ( |dst| ( src, dst) ) )
317325 {
318- let src_arg = self . arg_indexes [ src] ;
319- let dst_arg = self . arg_indexes [ dst] ;
320- let dest_input = self . input_indexes [ dst] ;
321- real_idxs[ src_arg ] = Some ( ( dst_arg , dest_input ) ) ;
322- matched_inputs[ dest_input ] = Some ( src_arg ) ;
326+ let src_input_idx = self . input_indexes [ src] ;
327+ let dst_input_idx = self . input_indexes [ dst] ;
328+ let dest_arg_idx = self . arg_indexes [ dst] ;
329+ real_idxs[ src_input_idx ] = Some ( ( dest_arg_idx , dst_input_idx ) ) ;
330+ matched_inputs[ dest_arg_idx ] = Some ( src_input_idx ) ;
323331 }
324332 idxs. sort ( ) ;
325333 idxs. reverse ( ) ;
@@ -331,8 +339,8 @@ impl<'tcx> ArgMatrix<'tcx> {
331339 None => {
332340 // We didn't find any issues, so we need to push the algorithm forward
333341 // First, eliminate any arguments that currently satisfy their inputs
334- for ( arg , inp ) in self . eliminate_satisfied ( ) {
335- matched_inputs[ inp ] = Some ( arg ) ;
342+ for ( inp , arg ) in self . eliminate_satisfied ( ) {
343+ matched_inputs[ arg ] = Some ( inp ) ;
336344 }
337345 }
338346 } ;
0 commit comments