@@ -36,14 +36,30 @@ impl<H: CompilerHost> Resolver<'_, H> {
3636 let len = block. stmts . len ( ) ;
3737 let mut stmts = Vec :: new ( ) ;
3838 for ( i, s) in block. stmts . iter ( ) . enumerate ( ) {
39- // Propagate expected type to the last expression for coercion
40- if expected_type. is_some ( )
41- && i == len - 1
42- && let Stmt :: Expr ( expr_stmt) = s
43- {
44- let expr = self . resolve_expr ( & expr_stmt. expr , ctx, expected_type) ;
45- stmts. push ( TirStmt :: new ( TirStmtKind :: Expr ( expr) , expr_stmt. span ) ) ;
46- continue ;
39+ // Propagate expected type to the last expression/statement for coercion
40+ if expected_type. is_some ( ) && i == len - 1 {
41+ if let Stmt :: Expr ( expr_stmt) = s {
42+ let expr = self . resolve_expr ( & expr_stmt. expr , ctx, expected_type) ;
43+ stmts. push ( TirStmt :: new ( TirStmtKind :: Expr ( expr) , expr_stmt. span ) ) ;
44+ continue ;
45+ }
46+ if let Stmt :: If ( if_stmt) = s {
47+ stmts. extend ( self . resolve_if_stmt_with_expected ( if_stmt, ctx, expected_type) ) ;
48+ continue ;
49+ }
50+ if let Stmt :: Match ( match_expr) = s {
51+ let tir = self . resolve_match_expr ( match_expr, ctx, expected_type) ;
52+ stmts. push ( TirStmt :: new ( TirStmtKind :: Expr ( tir) , match_expr. span ) ) ;
53+ continue ;
54+ }
55+ if let Stmt :: LabeledBlock ( labeled_block) = s {
56+ stmts. push ( self . resolve_labeled_block_with_expected (
57+ labeled_block,
58+ ctx,
59+ expected_type,
60+ ) ) ;
61+ continue ;
62+ }
4763 }
4864 stmts. extend ( self . resolve_stmt ( s, ctx) ) ;
4965 }
@@ -85,10 +101,19 @@ impl<H: CompilerHost> Resolver<'_, H> {
85101 & mut self ,
86102 labeled_block : & ast:: LabeledBlockStmt ,
87103 ctx : & mut FunctionContext ,
104+ ) -> TirStmt {
105+ self . resolve_labeled_block_with_expected ( labeled_block, ctx, None )
106+ }
107+
108+ fn resolve_labeled_block_with_expected (
109+ & mut self ,
110+ labeled_block : & ast:: LabeledBlockStmt ,
111+ ctx : & mut FunctionContext ,
112+ expected_type : Option < TypeId > ,
88113 ) -> TirStmt {
89114 ctx. active_labels . push ( labeled_block. label . clone ( ) ) ;
90115 // resolve_block already handles scope entry/exit
91- let block = self . resolve_block ( & labeled_block. block , ctx, None ) ;
116+ let block = self . resolve_block ( & labeled_block. block , ctx, expected_type ) ;
92117 ctx. active_labels . pop ( ) ;
93118
94119 TirStmt :: new (
@@ -811,6 +836,54 @@ impl<H: CompilerHost> Resolver<'_, H> {
811836 }
812837 }
813838
839+ /// Like `resolve_if_stmt` but propagates `expected_type` to blocks for coercion.
840+ /// Used when an if statement is the last statement in a block that needs type coercion
841+ /// (e.g., match arm returning Array<T> from an if-else with tuple literals).
842+ fn resolve_if_stmt_with_expected (
843+ & mut self ,
844+ if_stmt : & IfStmt ,
845+ ctx : & mut FunctionContext ,
846+ expected_type : Option < TypeId > ,
847+ ) -> Vec < TirStmt > {
848+ match & if_stmt. condition {
849+ ast:: Condition :: Expr ( expr) => {
850+ let condition = self . resolve_expr ( expr, ctx, Some ( TypeTable :: BOOL ) ) ;
851+ let then_block = self . resolve_block ( & if_stmt. then_block , ctx, expected_type) ;
852+ let else_block = if_stmt
853+ . else_block
854+ . as_ref ( )
855+ . map ( |b| self . resolve_block ( b, ctx, expected_type) ) ;
856+ vec ! [ TirStmt :: new(
857+ TirStmtKind :: If {
858+ condition,
859+ then_block,
860+ else_block,
861+ } ,
862+ if_stmt. span,
863+ ) ]
864+ }
865+ ast:: Condition :: LetChain { elements, .. } => {
866+ let else_block = if_stmt
867+ . else_block
868+ . as_ref ( )
869+ . map ( |b| self . resolve_block ( b, ctx, expected_type) ) ;
870+
871+ ctx. enter_scope ( ) ;
872+ let stmts = self . resolve_let_chain_stmts (
873+ elements,
874+ & if_stmt. then_block ,
875+ else_block. as_ref ( ) ,
876+ ctx,
877+ expected_type,
878+ if_stmt. span ,
879+ ) ;
880+ ctx. exit_scope ( ) ;
881+
882+ stmts
883+ }
884+ }
885+ }
886+
814887 /// Resolve a let-chain condition into a nested sequence of IfLet/If TIR statements.
815888 ///
816889 /// Each element of the chain adds one nesting level: a `Let` element becomes an `IfLet`
0 commit comments