@@ -2193,10 +2193,17 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, node_handle: NodeWithHandle) e
21932193 if (std .mem .eql (u8 , call_name , "@src" )) {
21942194 return analyser .instanceStdBuiltinType ("SourceLocation" );
21952195 }
2196+
21962197 if (std .mem .eql (u8 , call_name , "@compileError" )) {
21972198 return .{ .data = .{ .compile_error = node_handle }, .is_type_val = false };
21982199 }
21992200
2201+ if (std .mem .eql (u8 , call_name , "@panic" ) or
2202+ std .mem .eql (u8 , call_name , "@trap" ))
2203+ {
2204+ return Type .fromIP (analyser , .noreturn_type , null );
2205+ }
2206+
22002207 if (std .mem .eql (u8 , call_name , "@Vector" )) {
22012208 if (params .len != 2 ) return null ;
22022209
@@ -2414,16 +2421,21 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, node_handle: NodeWithHandle) e
24142421 .block_two ,
24152422 .block_two_semicolon ,
24162423 = > {
2417- const has_zero_statements = switch (tree .nodeTag (node )) {
2418- .block_two , .block_two_semicolon = > tree .nodeData (node ).opt_node_and_opt_node [0 ] == .none ,
2419- .block , .block_semicolon = > false ,
2420- else = > unreachable ,
2421- };
2422- if (has_zero_statements ) {
2424+ var buffer : [2 ]Ast.Node.Index = undefined ;
2425+ const statements = tree .blockStatements (& buffer , node ).? ;
2426+ if (statements .len == 0 ) {
24232427 return Type .fromIP (analyser , .void_type , .void_value );
24242428 }
24252429
2426- const label_token = ast .blockLabel (tree , node ) orelse return null ;
2430+ const label_token = ast .blockLabel (tree , node ) orelse {
2431+ const last_statement = statements [statements .len - 1 ];
2432+ if (try analyser .resolveTypeOfNodeInternal (.of (last_statement , handle ))) | ty | {
2433+ if (ty .typeOf (analyser ).isNoreturnType ()) {
2434+ return Type .fromIP (analyser , .noreturn_type , null );
2435+ }
2436+ }
2437+ return Type .fromIP (analyser , .void_type , .void_value );
2438+ };
24272439 const block_label = offsets .identifierTokenToNameSlice (tree , label_token );
24282440
24292441 // TODO: peer type resolution based on all `break` statements
@@ -3381,6 +3393,15 @@ pub const Type = struct {
33813393 };
33823394 }
33833395
3396+ pub fn isNoreturnType (self : Type ) bool {
3397+ if (! self .is_type_val ) return false ;
3398+ return switch (self .data ) {
3399+ .compile_error = > true ,
3400+ .ip_index = > | payload | payload .index == .noreturn_type ,
3401+ else = > false ,
3402+ };
3403+ }
3404+
33843405 pub fn typeDefinitionToken (self : Type ) ! ? TokenWithHandle {
33853406 return switch (self .data ) {
33863407 .container = > | scope_handle | .{
0 commit comments