@@ -1270,6 +1270,12 @@ impl<'a> PatternLowerer<'a> {
12701270 // Literal/Enum patterns don't bind anything, just evaluate for side effects
12711271 out. push ( TirStmt :: new ( TirStmtKind :: Expr ( value) , span) ) ;
12721272 }
1273+ TirPattern :: Or ( alternatives) => {
1274+ // Or patterns in let-destructure: use first alternative's bindings
1275+ if let Some ( first) = alternatives. first ( ) {
1276+ self . lower_pattern_to_lets ( first, is_mut, value, span, out, type_table) ;
1277+ }
1278+ }
12731279 }
12741280 }
12751281
@@ -1522,6 +1528,12 @@ impl<'a> PatternLowerer<'a> {
15221528 // Just evaluate for side effects (no bindings)
15231529 out. push ( TirStmt :: new ( TirStmtKind :: Expr ( value) , span) ) ;
15241530 }
1531+ TirPattern :: Or ( alternatives) => {
1532+ // Or patterns in lets: use first alternative's bindings
1533+ if let Some ( first) = alternatives. first ( ) {
1534+ self . lower_pattern_to_lets ( first, is_mut, value, span, out, type_table) ;
1535+ }
1536+ }
15251537 }
15261538 }
15271539
@@ -2058,6 +2070,42 @@ impl<'a> PatternLowerer<'a> {
20582070 binding_stmts,
20592071 )
20602072 }
2073+ TirPattern :: Or ( alternatives) => {
2074+ // Or pattern: combine conditions with logical OR, use first alternative's bindings
2075+ let mut or_conditions: Vec < TirExpr > = Vec :: new ( ) ;
2076+ for alt in alternatives {
2077+ let ( cond, _) = self . pattern_to_condition_and_bindings (
2078+ alt,
2079+ scrutinee. clone ( ) ,
2080+ span,
2081+ type_table,
2082+ ) ;
2083+ or_conditions. push ( cond) ;
2084+ }
2085+ // Emit bindings from the first alternative (all alternatives bind the same names)
2086+ if let Some ( first) = alternatives. first ( ) {
2087+ let ( _, first_bindings) =
2088+ self . pattern_to_condition_and_bindings ( first, scrutinee, span, type_table) ;
2089+ binding_stmts. extend ( first_bindings) ;
2090+ }
2091+ let combined = or_conditions
2092+ . into_iter ( )
2093+ . reduce ( |acc, cond| {
2094+ TirExpr :: new (
2095+ TirExprKind :: Binary {
2096+ op : TirBinaryOp :: Or ,
2097+ left : Box :: new ( acc) ,
2098+ right : Box :: new ( cond) ,
2099+ } ,
2100+ TypeTable :: BOOL ,
2101+ span,
2102+ )
2103+ } )
2104+ . unwrap_or_else ( || {
2105+ TirExpr :: new ( TirExprKind :: BoolLiteral ( false ) , TypeTable :: BOOL , span)
2106+ } ) ;
2107+ ( combined, binding_stmts)
2108+ }
20612109 }
20622110 }
20632111
@@ -2091,6 +2139,24 @@ impl<'a> PatternLowerer<'a> {
20912139 self . lower_expr ( & mut arm. body , type_table) ;
20922140 }
20932141
2142+ // Expand or-patterns: `A | B => body` becomes `A => body, B => body`
2143+ let mut expanded_arms = Vec :: new ( ) ;
2144+ for arm in arms. drain ( ..) {
2145+ if let TirPattern :: Or ( alternatives) = arm. pattern {
2146+ for alt in alternatives {
2147+ expanded_arms. push ( TirMatchArm {
2148+ pattern : alt,
2149+ guard : arm. guard . clone ( ) ,
2150+ body : arm. body . clone ( ) ,
2151+ span : arm. span ,
2152+ } ) ;
2153+ }
2154+ } else {
2155+ expanded_arms. push ( arm) ;
2156+ }
2157+ }
2158+ * arms = expanded_arms;
2159+
20942160 // Match ergonomics: insert deref if scrutinee is Ref/MutRef
20952161 while let ResolvedType :: Ref ( inner) | ResolvedType :: MutRef ( inner) =
20962162 type_table. get ( scrutinee. type_id )
0 commit comments