11use std:: cmp;
22
3+ use rustc_index:: vec:: IndexVec ;
34use rustc_middle:: ty:: error:: TypeError ;
45
6+ rustc_index:: newtype_index! {
7+ pub ( crate ) struct ExpectedIdx {
8+ DEBUG_FORMAT = "ExpectedIdx({})" ,
9+ }
10+ }
11+
12+ rustc_index:: newtype_index! {
13+ pub ( crate ) struct ProvidedIdx {
14+ DEBUG_FORMAT = "ProvidedIdx({})" ,
15+ }
16+ }
17+
18+ impl ExpectedIdx {
19+ pub fn to_provided_idx ( self ) -> ProvidedIdx {
20+ ProvidedIdx :: from_usize ( self . as_usize ( ) )
21+ }
22+ }
23+
524// An issue that might be found in the compatibility matrix
625#[ derive( Debug ) ]
726enum Issue {
@@ -27,87 +46,89 @@ pub(crate) enum Compatibility<'tcx> {
2746#[ derive( Debug ) ]
2847pub ( crate ) enum Error < ' tcx > {
2948 /// The provided argument is the invalid type for the expected input
30- Invalid ( usize , usize , Compatibility < ' tcx > ) , // provided, expected
49+ Invalid ( ProvidedIdx , ExpectedIdx , Compatibility < ' tcx > ) ,
3150 /// There is a missing input
32- Missing ( usize ) ,
51+ Missing ( ExpectedIdx ) ,
3352 /// There's a superfluous argument
34- Extra ( usize ) ,
53+ Extra ( ProvidedIdx ) ,
3554 /// Two arguments should be swapped
36- Swap ( usize , usize , usize , usize ) ,
55+ Swap ( ProvidedIdx , ProvidedIdx , ExpectedIdx , ExpectedIdx ) ,
3756 /// Several arguments should be reordered
38- Permutation ( Vec < ( usize , usize ) > ) , // dest_arg, dest_input
57+ Permutation ( Vec < ( ExpectedIdx , ProvidedIdx ) > ) ,
3958}
4059
4160pub ( crate ) struct ArgMatrix < ' tcx > {
4261 /// Maps the indices in the `compatibility_matrix` rows to the indices of
4362 /// the *user provided* inputs
44- input_indexes : Vec < usize > ,
63+ provided_indices : Vec < ProvidedIdx > ,
4564 /// Maps the indices in the `compatibility_matrix` columns to the indices
4665 /// of the *expected* args
47- arg_indexes : Vec < usize > ,
66+ expected_indices : Vec < ExpectedIdx > ,
4867 /// The first dimension (rows) are the remaining user provided inputs to
4968 /// match and the second dimension (cols) are the remaining expected args
5069 /// to match
5170 compatibility_matrix : Vec < Vec < Compatibility < ' tcx > > > ,
5271}
5372
5473impl < ' tcx > ArgMatrix < ' tcx > {
55- pub ( crate ) fn new < F : FnMut ( usize , usize ) -> Compatibility < ' tcx > > (
56- minimum_input_count : usize ,
57- provided_arg_count : usize ,
74+ pub ( crate ) fn new < F : FnMut ( ProvidedIdx , ExpectedIdx ) -> Compatibility < ' tcx > > (
75+ provided_count : usize ,
76+ expected_input_count : usize ,
5877 mut is_compatible : F ,
5978 ) -> Self {
60- let compatibility_matrix = ( 0 ..provided_arg_count)
61- . map ( |i| ( 0 ..minimum_input_count) . map ( |j| is_compatible ( i, j) ) . collect ( ) )
79+ let compatibility_matrix = ( 0 ..provided_count)
80+ . map ( |i| {
81+ ( 0 ..expected_input_count)
82+ . map ( |j| is_compatible ( ProvidedIdx :: from_usize ( i) , ExpectedIdx :: from_usize ( j) ) )
83+ . collect ( )
84+ } )
6285 . collect ( ) ;
6386 ArgMatrix {
64- input_indexes : ( 0 ..provided_arg_count ) . collect ( ) ,
65- arg_indexes : ( 0 ..minimum_input_count ) . collect ( ) ,
87+ provided_indices : ( 0 ..provided_count ) . map ( ProvidedIdx :: from_usize ) . collect ( ) ,
88+ expected_indices : ( 0 ..expected_input_count ) . map ( ExpectedIdx :: from_usize ) . collect ( ) ,
6689 compatibility_matrix,
6790 }
6891 }
6992
7093 /// Remove a given input from consideration
71- fn eliminate_input ( & mut self , idx : usize ) {
72- self . input_indexes . remove ( idx) ;
94+ fn eliminate_provided ( & mut self , idx : usize ) {
95+ self . provided_indices . remove ( idx) ;
7396 self . compatibility_matrix . remove ( idx) ;
7497 }
7598
7699 /// Remove a given argument from consideration
77- fn eliminate_arg ( & mut self , idx : usize ) {
78- self . arg_indexes . remove ( idx) ;
100+ fn eliminate_expected ( & mut self , idx : usize ) {
101+ self . expected_indices . remove ( idx) ;
79102 for row in & mut self . compatibility_matrix {
80103 row. remove ( idx) ;
81104 }
82105 }
83106
84107 /// "satisfy" an input with a given arg, removing both from consideration
85- fn satisfy_input ( & mut self , input_idx : usize , arg_idx : usize ) {
86- self . eliminate_input ( input_idx ) ;
87- self . eliminate_arg ( arg_idx ) ;
108+ fn satisfy_input ( & mut self , provided_idx : usize , expected_idx : usize ) {
109+ self . eliminate_provided ( provided_idx ) ;
110+ self . eliminate_expected ( expected_idx ) ;
88111 }
89112
90113 // Returns a `Vec` of (user input, expected arg) of matched arguments. These
91114 // are inputs on the remaining diagonal that match.
92- fn eliminate_satisfied ( & mut self ) -> Vec < ( usize , usize ) > {
93- let mut i = cmp:: min ( self . input_indexes . len ( ) , self . arg_indexes . len ( ) ) ;
115+ fn eliminate_satisfied ( & mut self ) -> Vec < ( ProvidedIdx , ExpectedIdx ) > {
116+ let num_args = cmp:: min ( self . provided_indices . len ( ) , self . expected_indices . len ( ) ) ;
94117 let mut eliminated = vec ! [ ] ;
95- while i > 0 {
96- let idx = i - 1 ;
97- if matches ! ( self . compatibility_matrix[ idx] [ idx] , Compatibility :: Compatible ) {
98- eliminated. push ( ( self . input_indexes [ idx] , self . arg_indexes [ idx] ) ) ;
99- self . satisfy_input ( idx, idx) ;
118+ for i in ( 0 ..num_args) . rev ( ) {
119+ if matches ! ( self . compatibility_matrix[ i] [ i] , Compatibility :: Compatible ) {
120+ eliminated. push ( ( self . provided_indices [ i] , self . expected_indices [ i] ) ) ;
121+ self . satisfy_input ( i, i) ;
100122 }
101- i -= 1 ;
102123 }
103- return eliminated;
124+ eliminated
104125 }
105126
106127 // Find some issue in the compatibility matrix
107128 fn find_issue ( & self ) -> Option < Issue > {
108129 let mat = & self . compatibility_matrix ;
109- let ai = & self . arg_indexes ;
110- let ii = & self . input_indexes ;
130+ let ai = & self . expected_indices ;
131+ let ii = & self . provided_indices ;
111132
112133 for i in 0 ..cmp:: max ( ai. len ( ) , ii. len ( ) ) {
113134 // If we eliminate the last row, any left-over inputs are considered missing
@@ -264,12 +285,15 @@ impl<'tcx> ArgMatrix<'tcx> {
264285 //
265286 // We'll want to know which arguments and inputs these rows and columns correspond to
266287 // even after we delete them.
267- pub ( crate ) fn find_errors ( mut self ) -> ( Vec < Error < ' tcx > > , Vec < Option < usize > > ) {
268- let provided_arg_count = self . input_indexes . len ( ) ;
288+ pub ( crate ) fn find_errors (
289+ mut self ,
290+ ) -> ( Vec < Error < ' tcx > > , IndexVec < ExpectedIdx , Option < ProvidedIdx > > ) {
291+ let provided_arg_count = self . provided_indices . len ( ) ;
269292
270293 let mut errors: Vec < Error < ' tcx > > = vec ! [ ] ;
271294 // For each expected argument, the matched *actual* input
272- let mut matched_inputs: Vec < Option < usize > > = vec ! [ None ; self . arg_indexes. len( ) ] ;
295+ let mut matched_inputs: IndexVec < ExpectedIdx , Option < ProvidedIdx > > =
296+ IndexVec :: from_elem_n ( None , self . expected_indices . len ( ) ) ;
273297
274298 // Before we start looking for issues, eliminate any arguments that are already satisfied,
275299 // so that an argument which is already spoken for by the input it's in doesn't
@@ -280,34 +304,34 @@ impl<'tcx> ArgMatrix<'tcx> {
280304 // Without this elimination, the first argument causes the second argument
281305 // to show up as both a missing input and extra argument, rather than
282306 // just an invalid type.
283- for ( inp , arg ) in self . eliminate_satisfied ( ) {
284- matched_inputs[ arg ] = Some ( inp ) ;
307+ for ( provided , expected ) in self . eliminate_satisfied ( ) {
308+ matched_inputs[ expected ] = Some ( provided ) ;
285309 }
286310
287- while self . input_indexes . len ( ) > 0 || self . arg_indexes . len ( ) > 0 {
311+ while ! self . provided_indices . is_empty ( ) || ! self . expected_indices . is_empty ( ) {
288312 match self . find_issue ( ) {
289313 Some ( Issue :: Invalid ( idx) ) => {
290314 let compatibility = self . compatibility_matrix [ idx] [ idx] . clone ( ) ;
291- let input_idx = self . input_indexes [ idx] ;
292- let arg_idx = self . arg_indexes [ idx] ;
315+ let input_idx = self . provided_indices [ idx] ;
316+ let arg_idx = self . expected_indices [ idx] ;
293317 self . satisfy_input ( idx, idx) ;
294318 errors. push ( Error :: Invalid ( input_idx, arg_idx, compatibility) ) ;
295319 }
296320 Some ( Issue :: Extra ( idx) ) => {
297- let input_idx = self . input_indexes [ idx] ;
298- self . eliminate_input ( idx) ;
321+ let input_idx = self . provided_indices [ idx] ;
322+ self . eliminate_provided ( idx) ;
299323 errors. push ( Error :: Extra ( input_idx) ) ;
300324 }
301325 Some ( Issue :: Missing ( idx) ) => {
302- let arg_idx = self . arg_indexes [ idx] ;
303- self . eliminate_arg ( idx) ;
326+ let arg_idx = self . expected_indices [ idx] ;
327+ self . eliminate_expected ( idx) ;
304328 errors. push ( Error :: Missing ( arg_idx) ) ;
305329 }
306330 Some ( Issue :: Swap ( idx, other) ) => {
307- let input_idx = self . input_indexes [ idx] ;
308- let other_input_idx = self . input_indexes [ other] ;
309- let arg_idx = self . arg_indexes [ idx] ;
310- let other_arg_idx = self . arg_indexes [ other] ;
331+ let input_idx = self . provided_indices [ idx] ;
332+ let other_input_idx = self . provided_indices [ other] ;
333+ let arg_idx = self . expected_indices [ idx] ;
334+ let other_arg_idx = self . expected_indices [ other] ;
311335 let ( min, max) = ( cmp:: min ( idx, other) , cmp:: max ( idx, other) ) ;
312336 self . satisfy_input ( min, max) ;
313337 // Subtract 1 because we already removed the "min" row
@@ -319,13 +343,14 @@ impl<'tcx> ArgMatrix<'tcx> {
319343 Some ( Issue :: Permutation ( args) ) => {
320344 let mut idxs: Vec < usize > = args. iter ( ) . filter_map ( |& a| a) . collect ( ) ;
321345
322- let mut real_idxs = vec ! [ None ; provided_arg_count] ;
346+ let mut real_idxs: IndexVec < ProvidedIdx , Option < ( ExpectedIdx , ProvidedIdx ) > > =
347+ IndexVec :: from_elem_n ( None , provided_arg_count) ;
323348 for ( src, dst) in
324349 args. iter ( ) . enumerate ( ) . filter_map ( |( src, dst) | dst. map ( |dst| ( src, dst) ) )
325350 {
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] ;
351+ let src_input_idx = self . provided_indices [ src] ;
352+ let dst_input_idx = self . provided_indices [ dst] ;
353+ let dest_arg_idx = self . expected_indices [ dst] ;
329354 real_idxs[ src_input_idx] = Some ( ( dest_arg_idx, dst_input_idx) ) ;
330355 matched_inputs[ dest_arg_idx] = Some ( src_input_idx) ;
331356 }
0 commit comments