@@ -22,6 +22,7 @@ use syntax::ast_util::{variant_def_ids, dummy_sp, unguarded_pat, walk_pat};
22
22
use syntax:: codemap:: span;
23
23
use syntax:: print:: pprust:: pat_to_str;
24
24
use syntax:: visit;
25
+ use std:: sort;
25
26
26
27
struct AltCheckCtxt {
27
28
tcx : ty:: ctxt ,
@@ -146,6 +147,12 @@ fn check_exhaustive(cx: @AltCheckCtxt, sp: span, pats: ~[@pat]) {
146
147
None => fail ~"check_exhaustive: bad variant in ctor"
147
148
}
148
149
}
150
+ ty:: ty_unboxed_vec( * ) | ty:: ty_evec( * ) => {
151
+ match ( * ctor) {
152
+ vec( n) => Some ( fmt ! ( "vectors of length %u" , n) ) ,
153
+ _ => None
154
+ }
155
+ }
149
156
_ => None
150
157
}
151
158
}
@@ -166,6 +173,8 @@ enum ctor {
166
173
variant( def_id ) ,
167
174
val( const_val ) ,
168
175
range( const_val , const_val ) ,
176
+ vec( uint ) ,
177
+ vec_with_tail( uint )
169
178
}
170
179
171
180
impl ctor : cmp:: Eq {
@@ -179,7 +188,12 @@ impl ctor : cmp::Eq {
179
188
range( ref cv0_other, ref cv1_other) ) => {
180
189
( * cv0_self) == ( * cv0_other) && ( * cv1_self) == ( * cv1_other)
181
190
}
182
- ( single, _) | ( variant( _) , _) | ( val( _) , _) | ( range( * ) , _) => {
191
+ ( vec( n_self) , vec( n_other) ) => n_self == n_other,
192
+ ( vec_with_tail( n_self) , vec_with_tail( n_other) ) => {
193
+ n_self == n_other
194
+ }
195
+ ( single, _) | ( variant( _) , _) | ( val( _) , _) |
196
+ ( range( * ) , _) | ( vec( * ) , _) | ( vec_with_tail( * ) , _) => {
183
197
false
184
198
}
185
199
}
@@ -236,6 +250,21 @@ fn is_useful(cx: @AltCheckCtxt, m: matrix, v: ~[@pat]) -> useful {
236
250
}
237
251
not_useful
238
252
}
253
+ ty:: ty_unboxed_vec( * ) | ty:: ty_evec( * ) => {
254
+ let max_len = do m. foldr ( 0 ) |r, max_len| {
255
+ match r[ 0 ] . node {
256
+ pat_vec( elems, _) => uint:: max ( elems. len ( ) , max_len) ,
257
+ _ => max_len
258
+ }
259
+ } ;
260
+ for uint:: range( 0 , max_len + 1 ) |n| {
261
+ match is_useful_specialized( cx, m, v, vec( n) , n, left_ty) {
262
+ not_useful => ( ) ,
263
+ ref u => return ( * u)
264
+ }
265
+ }
266
+ not_useful
267
+ }
239
268
_ => {
240
269
let arity = ctor_arity ( cx, single, left_ty) ;
241
270
is_useful_specialized ( cx, m, v, single, arity, left_ty)
@@ -297,6 +326,12 @@ fn pat_ctor_id(cx: @AltCheckCtxt, p: @pat) -> Option<ctor> {
297
326
pat_region( * ) => {
298
327
Some ( single)
299
328
}
329
+ pat_vec( elems, tail) => {
330
+ match tail {
331
+ Some ( _) => Some ( vec_with_tail ( elems. len ( ) ) ) ,
332
+ None => Some ( vec ( elems. len ( ) ) )
333
+ }
334
+ }
300
335
}
301
336
}
302
337
@@ -360,6 +395,56 @@ fn missing_ctor(cx: @AltCheckCtxt,
360
395
else if true_found { Some ( val ( const_bool ( false ) ) ) }
361
396
else { Some ( val ( const_bool ( true ) ) ) }
362
397
}
398
+ ty:: ty_unboxed_vec ( * ) | ty:: ty_evec ( * ) => {
399
+ let max_len = do m. foldr ( 0 ) |r, max_len| {
400
+ match r[ 0 ] . node {
401
+ pat_vec( elems, _) => uint:: max ( elems. len ( ) , max_len) ,
402
+ _ => max_len
403
+ }
404
+ } ;
405
+ let min_len_with_tail = do m. foldr ( max_len + 1 ) |r, min_len| {
406
+ match r[ 0 ] . node {
407
+ pat_vec( elems, tail) => {
408
+ if tail. is_some ( ) && elems. len ( ) < min_len {
409
+ elems. len ( )
410
+ } else {
411
+ min_len
412
+ }
413
+ }
414
+ _ => min_len
415
+ }
416
+ } ;
417
+ let vec_lens = do m. filter_map |r| {
418
+ match r[ 0 ] . node {
419
+ pat_vec( elems, tail) => {
420
+ match tail {
421
+ None if elems. len ( ) < min_len_with_tail => Some ( elems. len ( ) ) ,
422
+ _ => None
423
+ }
424
+ }
425
+ _ => None
426
+ }
427
+ } ;
428
+ let mut sorted_vec_lens = do sort:: merge_sort ( vec_lens) |a, b| {
429
+ a < b
430
+ } ;
431
+ vec:: dedup ( & mut sorted_vec_lens) ;
432
+
433
+ let mut missing = None ;
434
+ for uint:: range( 0 , min_len_with_tail) |i| {
435
+ if i >= sorted_vec_lens. len ( ) || i != sorted_vec_lens[ i] {
436
+ missing = Some ( i) ;
437
+ break ;
438
+ }
439
+ } ;
440
+ if missing. is_none ( ) && min_len_with_tail > max_len {
441
+ missing = Some ( min_len_with_tail) ;
442
+ }
443
+ match missing {
444
+ Some ( k) => Some ( vec ( k) ) ,
445
+ None => None
446
+ }
447
+ }
363
448
_ => Some ( single)
364
449
}
365
450
}
@@ -378,6 +463,12 @@ fn ctor_arity(cx: @AltCheckCtxt, ctor: ctor, ty: ty::t) -> uint {
378
463
}
379
464
}
380
465
ty:: ty_struct ( cid, _) => ty:: lookup_struct_fields ( cx. tcx , cid) . len ( ) ,
466
+ ty:: ty_unboxed_vec ( * ) | ty:: ty_evec ( * ) => {
467
+ match ctor {
468
+ vec( n) | vec_with_tail( n) => n,
469
+ _ => 0 u
470
+ }
471
+ }
381
472
_ => 0 u
382
473
}
383
474
}
@@ -521,6 +612,32 @@ fn specialize(cx: @AltCheckCtxt, r: ~[@pat], ctor_id: ctor, arity: uint,
521
612
compare_const_vals ( c_hi, v_hi) <= 0 ;
522
613
if match_ { Some ( vec:: tail ( r) ) } else { None }
523
614
}
615
+ pat_vec( elems, tail) => {
616
+ match ctor_id {
617
+ vec_with_tail( _) => {
618
+ if elems. len ( ) >= arity {
619
+ Some ( vec:: append ( elems. slice ( 0 , arity) , vec:: tail ( r) ) )
620
+ } else {
621
+ None
622
+ }
623
+ }
624
+ vec( _) => {
625
+ if elems. len ( ) < arity && tail. is_some ( ) {
626
+ Some ( vec:: append (
627
+ vec:: append ( elems, vec:: from_elem (
628
+ arity - elems. len ( ) , wild ( ) )
629
+ ) ,
630
+ vec:: tail ( r)
631
+ ) )
632
+ } else if elems. len ( ) == arity {
633
+ Some ( vec:: append ( elems, vec:: tail ( r) ) )
634
+ } else {
635
+ None
636
+ }
637
+ }
638
+ _ => None
639
+ }
640
+ }
524
641
}
525
642
}
526
643
@@ -593,6 +710,7 @@ fn is_refutable(cx: @AltCheckCtxt, pat: &pat) -> bool {
593
710
args. any ( |a| is_refutable ( cx, * a) )
594
711
}
595
712
pat_enum( _, _) => { false }
713
+ pat_vec( * ) => { true }
596
714
}
597
715
}
598
716
0 commit comments