@@ -218,6 +218,7 @@ use util::ppaux::{Repr, vec_map_to_string};
218
218
219
219
use std;
220
220
use std:: collections:: HashMap ;
221
+ use std:: iter:: AdditiveIterator ;
221
222
use std:: rc:: Rc ;
222
223
use syntax:: ast;
223
224
use syntax:: ast:: { DUMMY_NODE_ID , Ident } ;
@@ -754,33 +755,41 @@ impl FailureHandler {
754
755
}
755
756
}
756
757
757
- fn pick_col ( m : & [ Match ] ) -> uint {
758
- fn score ( p : & ast:: Pat ) -> uint {
759
- match p . node {
760
- ast :: PatLit ( _ ) | ast:: PatEnum ( _, _) | ast :: PatRange ( _ , _ ) => 1 u ,
761
- ast :: PatIdent ( _ , _ , Some ( ref p ) ) => score ( & * * p ) ,
762
- _ => 0 u
758
+ fn pick_column_to_specialize ( def_map : & DefMap , m : & [ Match ] ) -> Option < uint > {
759
+ fn pat_score ( def_map : & DefMap , pat : & ast:: Pat ) -> uint {
760
+ match pat . node {
761
+ ast:: PatIdent ( _, _, Some ( ref inner ) ) => pat_score ( def_map , & * * inner ) ,
762
+ _ if pat_is_refutable ( def_map , pat ) => 1 u ,
763
+ _ => 0 u
763
764
}
764
765
}
765
- let mut scores = Vec :: from_elem ( m[ 0 ] . pats . len ( ) , 0 u) ;
766
- for br in m. iter ( ) {
767
- for ( i, ref p) in br. pats . iter ( ) . enumerate ( ) {
768
- * scores. get_mut ( i) += score ( & * * * p) ;
766
+
767
+ let column_score: |& [ Match ] , uint| -> uint = |m, col| {
768
+ let total_score = m. iter ( )
769
+ . map ( |row| row. pats [ col] )
770
+ . map ( |pat| pat_score ( def_map, pat) )
771
+ . sum ( ) ;
772
+
773
+ // Irrefutable columns always go first, they'd only be duplicated in the branches.
774
+ if total_score == 0 {
775
+ std:: uint:: MAX
776
+ } else {
777
+ total_score
769
778
}
770
- }
771
- let mut max_score = 0 u ;
772
- let mut best_col = 0 u ;
773
- for ( i , score ) in scores . iter ( ) . enumerate ( ) {
774
- let score = * score ;
775
-
776
- // Irrefutable columns always go first, they'd only be duplicated in
777
- // the branches.
778
- if score == 0 u { return i ; }
779
- // If no irrefutable ones are found, we pick the one with the biggest
780
- // branching factor.
781
- if score > max_score { max_score = score ; best_col = i ; }
782
- }
783
- return best_col ;
779
+ } ;
780
+
781
+ let column_contains_any_nonwild_patterns : | & uint| -> bool = | & col| {
782
+ m . iter ( ) . any ( |row| match row . pats [ col ] . node {
783
+ ast :: PatWild ( _ ) => false ,
784
+ _ => true
785
+ } )
786
+ } ;
787
+
788
+ range ( 0 , m [ 0 ] . pats . len ( ) )
789
+ . filter ( column_contains_any_nonwild_patterns )
790
+ . map ( |col| ( col , column_score ( m , col ) ) )
791
+ . max_by ( | & ( _ , score ) | score )
792
+ . map ( | ( col , _ ) | col )
784
793
}
785
794
786
795
// Compiles a comparison between two things.
@@ -951,44 +960,45 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
951
960
return ;
952
961
}
953
962
954
- let col_count = m[ 0 ] . pats . len ( ) ;
955
- if col_count == 0 u {
956
- let data = & m[ 0 ] . data ;
957
- for & ( ref ident, ref value_ptr) in m[ 0 ] . bound_ptrs . iter ( ) {
958
- let llmatch = data. bindings_map . get ( ident) . llmatch ;
959
- call_lifetime_start ( bcx, llmatch) ;
960
- Store ( bcx, * value_ptr, llmatch) ;
963
+ let tcx = bcx. tcx ( ) ;
964
+ let def_map = & tcx. def_map ;
965
+ match pick_column_to_specialize ( def_map, m) {
966
+ Some ( col) => {
967
+ let val = vals[ col] ;
968
+ if has_nested_bindings ( m, col) {
969
+ let expanded = expand_nested_bindings ( bcx, m, col, val) ;
970
+ compile_submatch_continue ( bcx,
971
+ expanded. as_slice ( ) ,
972
+ vals,
973
+ chk,
974
+ col,
975
+ val,
976
+ has_genuine_default)
977
+ } else {
978
+ compile_submatch_continue ( bcx, m, vals, chk, col, val, has_genuine_default)
979
+ }
961
980
}
962
- match data. arm . guard {
963
- Some ( ref guard_expr) => {
964
- bcx = compile_guard ( bcx,
965
- & * * guard_expr,
966
- m[ 0 ] . data ,
967
- m[ 1 ..m. len ( ) ] ,
968
- vals,
969
- chk,
970
- has_genuine_default) ;
981
+ None => {
982
+ let data = & m[ 0 ] . data ;
983
+ for & ( ref ident, ref value_ptr) in m[ 0 ] . bound_ptrs . iter ( ) {
984
+ let llmatch = data. bindings_map . get ( ident) . llmatch ;
985
+ call_lifetime_start ( bcx, llmatch) ;
986
+ Store ( bcx, * value_ptr, llmatch) ;
971
987
}
972
- _ => ( )
988
+ match data. arm . guard {
989
+ Some ( ref guard_expr) => {
990
+ bcx = compile_guard ( bcx,
991
+ & * * guard_expr,
992
+ m[ 0 ] . data ,
993
+ m[ 1 ..m. len ( ) ] ,
994
+ vals,
995
+ chk,
996
+ has_genuine_default) ;
997
+ }
998
+ _ => ( )
999
+ }
1000
+ Br ( bcx, data. bodycx . llbb ) ;
973
1001
}
974
- Br ( bcx, data. bodycx . llbb ) ;
975
- return ;
976
- }
977
-
978
- let col = pick_col ( m) ;
979
- let val = vals[ col] ;
980
-
981
- if has_nested_bindings ( m, col) {
982
- let expanded = expand_nested_bindings ( bcx, m, col, val) ;
983
- compile_submatch_continue ( bcx,
984
- expanded. as_slice ( ) ,
985
- vals,
986
- chk,
987
- col,
988
- val,
989
- has_genuine_default)
990
- } else {
991
- compile_submatch_continue ( bcx, m, vals, chk, col, val, has_genuine_default)
992
1002
}
993
1003
}
994
1004
0 commit comments