@@ -1452,7 +1452,11 @@ fn stmt_to_c(
14521452 w ! ( p, "{} {} = " , c_ty( rhs_ty) , rhs_temp) ;
14531453 expr_to_c ( & rhs. node , & rhs. loc , locals, cg, p) ;
14541454 wln ! ( p, "; // {}" , loc_display( & rhs. loc) ) ;
1455- wln ! ( p, "{};" , pat_to_cond( & lhs. node, & rhs_temp, locals, cg) ) ;
1455+ wln ! (
1456+ p,
1457+ "{};" ,
1458+ pat_to_cond( & lhs. node, & rhs_temp, None , locals, cg)
1459+ ) ;
14561460 if let Some ( result_var) = result_var {
14571461 wln ! (
14581462 p,
@@ -1795,7 +1799,7 @@ fn expr_to_c(expr: &Expr, loc: &Loc, locals: &[LocalInfo], cg: &mut Cg, p: &mut
17951799 w ! ( p, " else " ) ;
17961800 }
17971801 // Generate pattern match condition
1798- let cond = pat_to_cond ( & alt. pat . node , & scrut_temp, locals, cg) ;
1802+ let cond = pat_to_cond ( & alt. pat . node , & scrut_temp, None , locals, cg) ;
17991803 w ! ( p, "if ({}" , cond) ;
18001804
18011805 // Add guard if present
@@ -1974,7 +1978,7 @@ fn expr_to_c(expr: &Expr, loc: &Loc, locals: &[LocalInfo], cg: &mut Cg, p: &mut
19741978 w ! (
19751979 p,
19761980 "if ({}) {{" ,
1977- pat_to_cond( & pat. node, & expr_temp, locals, cg)
1981+ pat_to_cond( & pat. node, & expr_temp, None , locals, cg)
19781982 ) ;
19791983 p. indent ( ) ;
19801984 p. nl ( ) ;
@@ -2189,13 +2193,24 @@ fn gen_variant_conversion(
21892193}
21902194
21912195/// Generate a C condition expression for pattern matching.
2192- fn pat_to_cond ( pat : & Pat , scrutinee : & str , locals : & [ LocalInfo ] , cg : & mut Cg ) -> String {
2196+ ///
2197+ /// - `scrutinee` is the expression being matched against.
2198+ ///
2199+ /// - `tag_expr` is an optional override for how to get the tag. When `Some`, use that expression
2200+ /// directly (e.g., for variant patterns where we check the variant's `_tag` field). When `None`,
2201+ /// derive the tag from the scrutinee using `get_tag(scrutinee)`.
2202+ fn pat_to_cond (
2203+ pat : & Pat ,
2204+ scrutinee : & str ,
2205+ tag_expr : Option < & str > ,
2206+ locals : & [ LocalInfo ] ,
2207+ cg : & mut Cg ,
2208+ ) -> String {
21932209 match pat {
21942210 Pat :: Ignore => "1" . to_string ( ) ,
21952211
21962212 Pat :: Var ( VarPat { idx, original_ty } ) => {
21972213 let refined_ty = & locals[ idx. as_usize ( ) ] . ty ;
2198-
21992214 if needs_variant_conversion ( original_ty, refined_ty) {
22002215 let conversion = gen_variant_conversion ( scrutinee, original_ty, refined_ty, cg) ;
22012216 format ! ( "({{ _{} = {}; 1; }})" , idx. as_usize( ) , conversion)
@@ -2207,12 +2222,15 @@ fn pat_to_cond(pat: &Pat, scrutinee: &str, locals: &[LocalInfo], cg: &mut Cg) ->
22072222 Pat :: Con ( ConPat { con, fields } ) => {
22082223 let struct_name = heap_obj_struct_name ( cg. pgm , * con) ;
22092224 let tag_name = heap_obj_tag_name ( cg. pgm , * con) ;
2210- // let get_tag_expr = gen_get_tag(&cg.pgm, scrutinee, ty); TODO
2211- let mut cond = format ! ( "(get_tag({}) == {})" , scrutinee, tag_name) ;
2225+ let tag_check = match tag_expr {
2226+ Some ( expr) => format ! ( "({expr} == {tag_name})" ) ,
2227+ None => format ! ( "(get_tag({scrutinee}) == {tag_name})" ) ,
2228+ } ;
2229+ let mut cond = tag_check;
22122230 for ( i, field_pat) in fields. iter ( ) . enumerate ( ) {
22132231 let field_expr = format ! ( "(({struct_name}*){scrutinee})->_{i}" ) ;
2214- let field_cond = pat_to_cond ( & field_pat. node , & field_expr, locals, cg) ;
2215- cond = format ! ( "({} && {})" , cond , field_cond ) ;
2232+ let field_cond = pat_to_cond ( & field_pat. node , & field_expr, None , locals, cg) ;
2233+ cond = format ! ( "({cond } && {field_cond })" ) ;
22162234 }
22172235 cond
22182236 }
@@ -2221,36 +2239,34 @@ fn pat_to_cond(pat: &Pat, scrutinee: &str, locals: &[LocalInfo], cg: &mut Cg) ->
22212239 let mut escaped = String :: new ( ) ;
22222240 for byte in s. bytes ( ) {
22232241 if byte == b'"' || byte == b'\\' || !( 32 ..=126 ) . contains ( & byte) {
2224- // Same as `Expr::Str`, use octal escape here instead of hex.
22252242 escaped. push_str ( & format ! ( "\\ {:03o}" , byte) ) ;
22262243 } else {
22272244 escaped. push ( byte as char ) ;
22282245 }
22292246 }
2230- // Note: the type cast below is to handle strings in variants. Variants are currently
2231- // `Variant*` so they need to be cast.
2247+ let tag_check = match tag_expr {
2248+ Some ( expr) => format ! ( "({expr} == {})" , cg. pgm. str_con_idx. 0 ) ,
2249+ None => format ! ( "(get_tag({scrutinee}) == {})" , cg. pgm. str_con_idx. 0 ) ,
2250+ } ;
22322251 format ! (
2233- "(get_tag({}) == {} && str_eq((Str*){}, \" {}\" , {}))" ,
2234- scrutinee,
2235- cg. pgm. str_con_idx. 0 ,
2236- scrutinee,
2237- escaped,
2252+ "({tag_check} && str_eq((Str*){scrutinee}, \" {escaped}\" , {}))" ,
22382253 s. len( )
22392254 )
22402255 }
22412256
22422257 Pat :: Char ( c) => {
22432258 let tag_name = heap_obj_tag_name ( cg. pgm , cg. pgm . char_con_idx ) ;
2244- format ! (
2245- "(get_tag({}) == {} && ((Char*){})->_0 == {})" ,
2246- scrutinee, tag_name, scrutinee, * c as u32
2247- )
2259+ let tag_check = match tag_expr {
2260+ Some ( expr) => format ! ( "({expr} == {tag_name})" ) ,
2261+ None => format ! ( "(get_tag({scrutinee}) == {tag_name})" ) ,
2262+ } ;
2263+ format ! ( "({tag_check} && ((Char*){scrutinee})->_0 == {})" , * c as u32 )
22482264 }
22492265
22502266 Pat :: Or ( p1, p2) => {
2251- let c1 = pat_to_cond ( & p1. node , scrutinee, locals, cg) ;
2252- let c2 = pat_to_cond ( & p2. node , scrutinee, locals, cg) ;
2253- format ! ( "({} || {})" , c1 , c2 )
2267+ let c1 = pat_to_cond ( & p1. node , scrutinee, tag_expr , locals, cg) ;
2268+ let c2 = pat_to_cond ( & p2. node , scrutinee, tag_expr , locals, cg) ;
2269+ format ! ( "({c1 } || {c2 })" )
22542270 }
22552271
22562272 Pat :: Variant {
@@ -2260,10 +2276,8 @@ fn pat_to_cond(pat: &Pat, scrutinee: &str, locals: &[LocalInfo], cg: &mut Cg) ->
22602276 } => {
22612277 let alt_idx = find_variant_alt_index ( pat_ty, variant_ty) ;
22622278 let inner_expr = format ! ( "({scrutinee})._alt._{alt_idx}" ) ;
2263- let expected_tag = gen_get_tag ( cg. pgm , & inner_expr, pat_ty) ;
2264- let tag_check = format ! ( "(({scrutinee})._tag == {expected_tag})" ) ;
2265- let inner_cond = pat_to_cond ( & pat. node , & inner_expr, locals, cg) ;
2266- format ! ( "({tag_check} && {inner_cond})" )
2279+ let variant_tag_expr = format ! ( "({scrutinee})._tag" ) ;
2280+ pat_to_cond ( & pat. node , & inner_expr, Some ( & variant_tag_expr) , locals, cg)
22672281 }
22682282 }
22692283}
0 commit comments