@@ -12,6 +12,7 @@ use ruff_python_ast::AtomicNodeIndex;
1212use ruff_python_ast:: Expr ;
1313use ruff_python_ast:: ExprNumberLiteral ;
1414use ruff_python_ast:: ExprStringLiteral ;
15+ use ruff_python_ast:: ExprTuple ;
1516use ruff_python_ast:: Int ;
1617use ruff_python_ast:: MatchCase ;
1718use ruff_python_ast:: Number ;
@@ -43,6 +44,47 @@ use crate::error::context::ErrorInfo;
4344use crate :: export:: special:: SpecialExport ;
4445use crate :: types:: facet:: UnresolvedFacetKind ;
4546
47+ fn sequence_pattern_is_syntactically_exhaustive ( subjects : & [ Expr ] , patterns : & [ Pattern ] ) -> bool {
48+ let Some ( star_idx) = patterns
49+ . iter ( )
50+ . position ( |pattern| matches ! ( pattern, Pattern :: MatchStar ( _) ) )
51+ else {
52+ return subjects. len ( ) == patterns. len ( )
53+ && subjects. iter ( ) . zip ( patterns) . all ( |( subject, pattern) | {
54+ pattern_is_syntactically_exhaustive_for_subject ( subject, pattern)
55+ } ) ;
56+ } ;
57+ let suffix_len = patterns. len ( ) - star_idx - 1 ;
58+ if subjects. len ( ) + 1 < patterns. len ( ) {
59+ return false ;
60+ }
61+ patterns[ ..star_idx]
62+ . iter ( )
63+ . zip ( & subjects[ ..star_idx] )
64+ . all ( |( pattern, subject) | pattern_is_syntactically_exhaustive_for_subject ( subject, pattern) )
65+ && patterns[ star_idx + 1 ..]
66+ . iter ( )
67+ . zip ( & subjects[ subjects. len ( ) - suffix_len..] )
68+ . all ( |( pattern, subject) | {
69+ pattern_is_syntactically_exhaustive_for_subject ( subject, pattern)
70+ } )
71+ }
72+
73+ pub ( crate ) fn pattern_is_syntactically_exhaustive_for_subject (
74+ subject : & Expr ,
75+ pattern : & Pattern ,
76+ ) -> bool {
77+ if pattern. is_wildcard ( ) || pattern. is_irrefutable ( ) {
78+ return true ;
79+ }
80+ match ( subject, pattern) {
81+ ( Expr :: Tuple ( ExprTuple { elts, .. } ) , Pattern :: MatchSequence ( x) ) => {
82+ sequence_pattern_is_syntactically_exhaustive ( elts, & x. patterns )
83+ }
84+ _ => false ,
85+ }
86+ }
87+
4688#[ derive( Clone , Debug ) ]
4789enum MatchSubject {
4890 /// No narrowing subject available.
@@ -538,7 +580,8 @@ impl<'a> BindingsBuilder<'a> {
538580 ..
539581 } = case;
540582 self . start_branch ( ) ;
541- let case_is_irrefutable = pattern. is_wildcard ( ) || pattern. is_irrefutable ( ) ;
583+ let case_is_irrefutable =
584+ pattern_is_syntactically_exhaustive_for_subject ( & subject_expr, & pattern) ;
542585 if case_is_irrefutable {
543586 exhaustive = true ;
544587 }
0 commit comments