@@ -706,9 +706,12 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
706706 debug ! ( "is_useful - pat_constructors = {:?} left_ty = {:?}" , constructors,
707707 left_ty) ;
708708 if constructors. is_empty ( ) {
709+ // v[0] is a wildcard pattern - `pat_constructors` should really be returning
710+ // an Option.
709711 let constructors = missing_constructors ( cx, matrix, left_ty, max_slice_length) ;
710712 debug ! ( "is_useful - missing_constructors = {:?}" , constructors) ;
711713 if constructors. is_empty ( ) {
714+ // all constructors are covered - must check them all.
712715 all_constructors ( cx, left_ty, max_slice_length) . into_iter ( ) . map ( |c| {
713716 match is_useful_specialized ( cx, matrix, v, c. clone ( ) , left_ty, witness) {
714717 UsefulWithWitness ( pats) => UsefulWithWitness ( {
@@ -727,6 +730,7 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
727730 }
728731 } ) . find ( |result| result != & NotUseful ) . unwrap_or ( NotUseful )
729732 } else {
733+ // some constructor is only covered by wildcards - pick it.
730734 let matrix = rows. iter ( ) . filter_map ( |r| {
731735 match raw_pat ( r[ 0 ] . 0 ) . node {
732736 PatKind :: Binding ( ..) | PatKind :: Wild => Some ( r[ 1 ..] . to_vec ( ) ) ,
@@ -747,12 +751,41 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
747751 }
748752 }
749753 } else {
754+ // `v` is not a wildcard
750755 constructors. into_iter ( ) . map ( |c|
751756 is_useful_specialized ( cx, matrix, v, c. clone ( ) , left_ty, witness)
752757 ) . find ( |result| result != & NotUseful ) . unwrap_or ( NotUseful )
753758 }
754759}
755760
761+ fn check_for_ref_splitting < ' s , ' a , ' tcx , I > ( cx : & MatchCheckCtxt < ' a , ' tcx > , data : I )
762+ where I : Iterator < Item =( & ' s Pat , Option < Ty < ' tcx > > ) >
763+ {
764+ let mut ref_pattern = None ;
765+ let mut lit_pattern = None ;
766+
767+ for ( pat, _ty) in data {
768+ match pat. node {
769+ PatKind :: Lit ( ..) => {
770+ lit_pattern = Some ( pat) ;
771+ }
772+ PatKind :: Ref ( ..) => {
773+ ref_pattern = Some ( pat) ;
774+ }
775+ _ => { }
776+ } ;
777+ if let ( Some ( lit_pattern) , Some ( ref_pattern) ) = ( lit_pattern, ref_pattern) {
778+ cx. tcx . sess . struct_span_err (
779+ ref_pattern. span ,
780+ & format ! ( "as a temporary restriction, literal patterns can't be split \
781+ - see issue #35044")
782+ ) . span_note ( lit_pattern. span , & format ! ( "split literal here" ) )
783+ . emit ( ) ;
784+ cx. tcx . sess . abort_if_errors ( ) ;
785+ }
786+ }
787+ }
788+
756789fn is_useful_specialized < ' a , ' tcx > (
757790 cx : & MatchCheckCtxt < ' a , ' tcx > ,
758791 & Matrix ( ref m) : & Matrix < ' a , ' tcx > ,
@@ -762,6 +795,10 @@ fn is_useful_specialized<'a, 'tcx>(
762795 witness : WitnessPreference ) -> Usefulness
763796{
764797 let arity = constructor_arity ( cx, & ctor, lty) ;
798+ check_for_ref_splitting (
799+ cx,
800+ m. iter ( ) . map ( |r| r[ 0 ] ) . chain ( Some ( v[ 0 ] ) )
801+ ) ;
765802 let matrix = Matrix ( m. iter ( ) . filter_map ( |r| {
766803 specialize ( cx, & r[ ..] , & ctor, 0 , arity)
767804 } ) . collect ( ) ) ;
@@ -781,7 +818,8 @@ fn is_useful_specialized<'a, 'tcx>(
781818/// On the other hand, a wild pattern and an identifier pattern cannot be
782819/// specialized in any way.
783820fn pat_constructors ( cx : & MatchCheckCtxt , p : & Pat ,
784- left_ty : Ty , max_slice_length : usize ) -> Vec < Constructor > {
821+ left_ty : Ty , max_slice_length : usize )
822+ -> Vec < Constructor > {
785823 let pat = raw_pat ( p) ;
786824 match pat. node {
787825 PatKind :: Struct ( ..) | PatKind :: TupleStruct ( ..) | PatKind :: Path ( ..) =>
0 commit comments