authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-26 20:34:22-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-26 20:34:22-05:00
log1b86a628acef7bc180ea6cbe6e4930710e5dff97
tree36d24de2b50eabdb9588c8c82f03f84448f6ac49
parentb0cd24f90ef159cc60c9607e9cc37af8b5bd147a
parent81443fcde84879782f38fde33510e56d2faaaa21
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #14015 from Vexu/recursive-inline

Sema: add error for recursive inline call

9 files changed, 130 insertions(+), 60 deletions(-)

doc/langref.html.in+41-22
...@@ -12062,24 +12062,24 @@ ContainerMembers <- ContainerDeclarations (ContainerField COMMA)* (ContainerFiel...@@ -12062,24 +12062,24 @@ ContainerMembers <- ContainerDeclarations (ContainerField COMMA)* (ContainerFiel
1206212062
12063ContainerDeclarations12063ContainerDeclarations
12064 <- TestDecl ContainerDeclarations12064 <- TestDecl ContainerDeclarations
12065 / TopLevelComptime ContainerDeclarations12065 / ComptimeDecl ContainerDeclarations
12066 / doc_comment? KEYWORD_pub? TopLevelDecl ContainerDeclarations12066 / doc_comment? KEYWORD_pub? Decl ContainerDeclarations
12067 /12067 /
1206812068
12069TestDecl <- doc_comment? KEYWORD_test STRINGLITERALSINGLE? Block12069TestDecl <- KEYWORD_test STRINGLITERALSINGLE? Block
1207012070
12071TopLevelComptime <- doc_comment? KEYWORD_comptime BlockExpr12071ComptimeDecl <- KEYWORD_comptime Block
1207212072
12073TopLevelDecl12073Decl
12074 <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block)12074 <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block)
12075 / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl12075 / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl
12076 / KEYWORD_usingnamespace Expr SEMICOLON12076 / KEYWORD_usingnamespace Expr SEMICOLON
1207712077
12078FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr12078FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr
1207912079
12080VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON12080VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection? (EQUAL Expr)? SEMICOLON
1208112081
12082ContainerField <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON (KEYWORD_anytype / TypeExpr) ByteAlign?)? (EQUAL Expr)?12082ContainerField <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
1208312083
12084# *** Block Level ***12084# *** Block Level ***
12085Statement12085Statement
...@@ -12240,6 +12240,8 @@ WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN...@@ -12240,6 +12240,8 @@ WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
1224012240
12241LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN12241LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
1224212242
12243AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN
12244
12243# Fn specific12245# Fn specific
12244CallConv <- KEYWORD_callconv LPAREN Expr RPAREN12246CallConv <- KEYWORD_callconv LPAREN Expr RPAREN
1224512247
...@@ -12267,7 +12269,7 @@ PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE...@@ -12267,7 +12269,7 @@ PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
1226712269
1226812270
12269# Switch specific12271# Switch specific
12270SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr12272SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr
1227112273
12272SwitchCase12274SwitchCase
12273 <- SwitchItem (COMMA SwitchItem)* COMMA?12275 <- SwitchItem (COMMA SwitchItem)* COMMA?
...@@ -12278,11 +12280,15 @@ SwitchItem <- Expr (DOT3 Expr)?...@@ -12278,11 +12280,15 @@ SwitchItem <- Expr (DOT3 Expr)?
12278# Operators12280# Operators
12279AssignOp12281AssignOp
12280 <- ASTERISKEQUAL12282 <- ASTERISKEQUAL
12283 / ASTERISKPIPEEQUAL
12281 / SLASHEQUAL12284 / SLASHEQUAL
12282 / PERCENTEQUAL12285 / PERCENTEQUAL
12283 / PLUSEQUAL12286 / PLUSEQUAL
12287 / PLUSPIPEEQUAL
12284 / MINUSEQUAL12288 / MINUSEQUAL
12289 / MINUSPIPEEQUAL
12285 / LARROW2EQUAL12290 / LARROW2EQUAL
12291 / LARROW2PIPEEQUAL
12286 / RARROW2EQUAL12292 / RARROW2EQUAL
12287 / AMPERSANDEQUAL12293 / AMPERSANDEQUAL
12288 / CARETEQUAL12294 / CARETEQUAL
...@@ -12310,6 +12316,7 @@ BitwiseOp...@@ -12310,6 +12316,7 @@ BitwiseOp
12310BitShiftOp12316BitShiftOp
12311 <- LARROW212317 <- LARROW2
12312 / RARROW212318 / RARROW2
12319 / LARROW2PIPE
1231312320
12314AdditionOp12321AdditionOp
12315 <- PLUS12322 <- PLUS
...@@ -12317,6 +12324,8 @@ AdditionOp...@@ -12317,6 +12324,8 @@ AdditionOp
12317 / PLUS212324 / PLUS2
12318 / PLUSPERCENT12325 / PLUSPERCENT
12319 / MINUSPERCENT12326 / MINUSPERCENT
12327 / PLUSPIPE
12328 / MINUSPIPE
1232012329
12321MultiplyOp12330MultiplyOp
12322 <- PIPE212331 <- PIPE2
...@@ -12325,6 +12334,7 @@ MultiplyOp...@@ -12325,6 +12334,7 @@ MultiplyOp
12325 / PERCENT12334 / PERCENT
12326 / ASTERISK212335 / ASTERISK2
12327 / ASTERISKPERCENT12336 / ASTERISKPERCENT
12337 / ASTERISKPIPE
1232812338
12329PrefixOp12339PrefixOp
12330 <- EXCLAMATIONMARK12340 <- EXCLAMATIONMARK
...@@ -12338,8 +12348,8 @@ PrefixOp...@@ -12338,8 +12348,8 @@ PrefixOp
12338PrefixTypeOp12348PrefixTypeOp
12339 <- QUESTIONMARK12349 <- QUESTIONMARK
12340 / KEYWORD_anyframe MINUSRARROW12350 / KEYWORD_anyframe MINUSRARROW
12341 / SliceTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*12351 / SliceTypeStart (ByteAlign / AddrSpace / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
12342 / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*12352 / PtrTypeStart (AddrSpace / KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
12343 / ArrayTypeStart12353 / ArrayTypeStart
1234412354
12345SuffixOp12355SuffixOp
...@@ -12364,7 +12374,7 @@ ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET...@@ -12364,7 +12374,7 @@ ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET
12364ContainerDeclAuto <- ContainerDeclType LBRACE container_doc_comment? ContainerMembers RBRACE12374ContainerDeclAuto <- ContainerDeclType LBRACE container_doc_comment? ContainerMembers RBRACE
1236512375
12366ContainerDeclType12376ContainerDeclType
12367 <- KEYWORD_struct12377 <- KEYWORD_struct (LPAREN Expr RPAREN)?
12368 / KEYWORD_opaque12378 / KEYWORD_opaque
12369 / KEYWORD_enum (LPAREN Expr RPAREN)?12379 / KEYWORD_enum (LPAREN Expr RPAREN)?
12370 / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?12380 / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
...@@ -12455,7 +12465,7 @@ string_char...@@ -12455,7 +12465,7 @@ string_char
12455 / [^\\"\n]12465 / [^\\"\n]
1245612466
12457container_doc_comment <- ('//!' [^\n]* [ \n]*)+12467container_doc_comment <- ('//!' [^\n]* [ \n]*)+
12458doc_comment <- ('///' [^\n]* [ \n]*)+12468doc_comment <- ('///' [^\n]* [ \n]*)+ skip
12459line_comment <- '//' ![!/][^\n]* / '////' [^\n]*12469line_comment <- '//' ![!/][^\n]* / '////' [^\n]*
12460line_string <- ("\\\\" [^\n]* [ \n]*)+12470line_string <- ("\\\\" [^\n]* [ \n]*)+
12461skip <- ([ \n] / line_comment)*12471skip <- ([ \n] / line_comment)*
...@@ -12483,11 +12493,13 @@ BUILTINIDENTIFIER <- "@"[A-Za-z_][A-Za-z0-9_]* skip...@@ -12483,11 +12493,13 @@ BUILTINIDENTIFIER <- "@"[A-Za-z_][A-Za-z0-9_]* skip
1248312493
12484AMPERSAND <- '&' ![=] skip12494AMPERSAND <- '&' ![=] skip
12485AMPERSANDEQUAL <- '&=' skip12495AMPERSANDEQUAL <- '&=' skip
12486ASTERISK <- '*' ![*%=] skip12496ASTERISK <- '*' ![*%=|] skip
12487ASTERISK2 <- '**' skip12497ASTERISK2 <- '**' skip
12488ASTERISKEQUAL <- '*=' skip12498ASTERISKEQUAL <- '*=' skip
12489ASTERISKPERCENT <- '*%' ![=] skip12499ASTERISKPERCENT <- '*%' ![=] skip
12490ASTERISKPERCENTEQUAL <- '*%=' skip12500ASTERISKPERCENTEQUAL <- '*%=' skip
12501ASTERISKPIPE <- '*|' ![=] skip
12502ASTERISKPIPEEQUAL <- '*|=' skip
12491CARET <- '^' ![=] skip12503CARET <- '^' ![=] skip
12492CARETEQUAL <- '^=' skip12504CARETEQUAL <- '^=' skip
12493COLON <- ':' skip12505COLON <- ':' skip
...@@ -12503,27 +12515,33 @@ EQUALRARROW <- '=>' skip...@@ -12503,27 +12515,33 @@ EQUALRARROW <- '=>' skip
12503EXCLAMATIONMARK <- '!' ![=] skip12515EXCLAMATIONMARK <- '!' ![=] skip
12504EXCLAMATIONMARKEQUAL <- '!=' skip12516EXCLAMATIONMARKEQUAL <- '!=' skip
12505LARROW <- '<' ![<=] skip12517LARROW <- '<' ![<=] skip
12506LARROW2 <- '<<' ![=] skip12518LARROW2 <- '<<' ![=|] skip
12507LARROW2EQUAL <- '<<=' skip12519LARROW2EQUAL <- '<<=' skip
12520LARROW2PIPE <- '<<|' ![=] skip
12521LARROW2PIPEEQUAL <- '<<|=' skip
12508LARROWEQUAL <- '<=' skip12522LARROWEQUAL <- '<=' skip
12509LBRACE <- '{' skip12523LBRACE <- '{' skip
12510LBRACKET <- '[' skip12524LBRACKET <- '[' skip
12511LPAREN <- '(' skip12525LPAREN <- '(' skip
12512MINUS <- '-' ![%=>] skip12526MINUS <- '-' ![%=>|] skip
12513MINUSEQUAL <- '-=' skip12527MINUSEQUAL <- '-=' skip
12514MINUSPERCENT <- '-%' ![=] skip12528MINUSPERCENT <- '-%' ![=] skip
12515MINUSPERCENTEQUAL <- '-%=' skip12529MINUSPERCENTEQUAL <- '-%=' skip
12530MINUSPIPE <- '-|' ![=] skip
12531MINUSPIPEEQUAL <- '-|=' skip
12516MINUSRARROW <- '->' skip12532MINUSRARROW <- '->' skip
12517PERCENT <- '%' ![=] skip12533PERCENT <- '%' ![=] skip
12518PERCENTEQUAL <- '%=' skip12534PERCENTEQUAL <- '%=' skip
12519PIPE <- '|' ![|=] skip12535PIPE <- '|' ![|=] skip
12520PIPE2 <- '||' skip12536PIPE2 <- '||' skip
12521PIPEEQUAL <- '|=' skip12537PIPEEQUAL <- '|=' skip
12522PLUS <- '+' ![%+=] skip12538PLUS <- '+' ![%+=|] skip
12523PLUS2 <- '++' skip12539PLUS2 <- '++' skip
12524PLUSEQUAL <- '+=' skip12540PLUSEQUAL <- '+=' skip
12525PLUSPERCENT <- '+%' ![=] skip12541PLUSPERCENT <- '+%' ![=] skip
12526PLUSPERCENTEQUAL <- '+%=' skip12542PLUSPERCENTEQUAL <- '+%=' skip
12543PLUSPIPE <- '+|' ![=] skip
12544PLUSPIPEEQUAL <- '+|=' skip
12527LETTERC <- 'c' skip12545LETTERC <- 'c' skip
12528QUESTIONMARK <- '?' skip12546QUESTIONMARK <- '?' skip
12529RARROW <- '>' ![>=] skip12547RARROW <- '>' ![>=] skip
...@@ -12539,6 +12557,7 @@ SLASHEQUAL <- '/=' skip...@@ -12539,6 +12557,7 @@ SLASHEQUAL <- '/=' skip
12539TILDE <- '~' skip12557TILDE <- '~' skip
1254012558
12541end_of_word <- ![a-zA-Z0-9_] skip12559end_of_word <- ![a-zA-Z0-9_] skip
12560KEYWORD_addrspace <- 'addrspace' end_of_word
12542KEYWORD_align <- 'align' end_of_word12561KEYWORD_align <- 'align' end_of_word
12543KEYWORD_allowzero <- 'allowzero' end_of_word12562KEYWORD_allowzero <- 'allowzero' end_of_word
12544KEYWORD_and <- 'and' end_of_word12563KEYWORD_and <- 'and' end_of_word
...@@ -12588,11 +12607,11 @@ KEYWORD_var <- 'var' end_of_word...@@ -12588,11 +12607,11 @@ KEYWORD_var <- 'var' end_of_word
12588KEYWORD_volatile <- 'volatile' end_of_word12607KEYWORD_volatile <- 'volatile' end_of_word
12589KEYWORD_while <- 'while' end_of_word12608KEYWORD_while <- 'while' end_of_word
1259012609
12591keyword <- KEYWORD_align / KEYWORD_allowzero / KEYWORD_and / KEYWORD_anyframe12610keyword <- KEYWORD_addrspace / KEYWORD_align / KEYWORD_allowzero / KEYWORD_and
12592 / KEYWORD_anytype / KEYWORD_asm / KEYWORD_async / KEYWORD_await12611 / KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_asm / KEYWORD_async
12593 / KEYWORD_break / KEYWORD_callconv / KEYWORD_catch / KEYWORD_comptime12612 / KEYWORD_await / KEYWORD_break / KEYWORD_callconv / KEYWORD_catch
12594 / KEYWORD_const / KEYWORD_continue / KEYWORD_defer / KEYWORD_else12613 / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue / KEYWORD_defer
12595 / KEYWORD_enum / KEYWORD_errdefer / KEYWORD_error / KEYWORD_export12614 / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer / KEYWORD_error / KEYWORD_export
12596 / KEYWORD_extern / KEYWORD_fn / KEYWORD_for / KEYWORD_if12615 / KEYWORD_extern / KEYWORD_fn / KEYWORD_for / KEYWORD_if
12597 / KEYWORD_inline / KEYWORD_noalias / KEYWORD_nosuspend / KEYWORD_noinline12616 / KEYWORD_inline / KEYWORD_noalias / KEYWORD_nosuspend / KEYWORD_noinline
12598 / KEYWORD_opaque / KEYWORD_or / KEYWORD_orelse / KEYWORD_packed12617 / KEYWORD_opaque / KEYWORD_or / KEYWORD_orelse / KEYWORD_packed
lib/std/zig/parse.zig+4-4
...@@ -240,10 +240,10 @@ const Parser = struct {...@@ -240,10 +240,10 @@ const Parser = struct {
240 /// ContainerMembers <- ContainerDeclarations (ContainerField COMMA)* (ContainerField / ContainerDeclarations)240 /// ContainerMembers <- ContainerDeclarations (ContainerField COMMA)* (ContainerField / ContainerDeclarations)
241 /// ContainerDeclarations241 /// ContainerDeclarations
242 /// <- TestDecl ContainerDeclarations242 /// <- TestDecl ContainerDeclarations
243 /// / TopLevelComptime ContainerDeclarations243 /// / ComptimeDecl ContainerDeclarations
244 /// / KEYWORD_pub? TopLevelDecl ContainerDeclarations244 /// / doc_comment? KEYWORD_pub? Decl ContainerDeclarations
245 /// /245 /// /
246 /// TopLevelComptime <- KEYWORD_comptime Block246 /// ComptimeDecl <- KEYWORD_comptime Block
247 fn parseContainerMembers(p: *Parser) !Members {247 fn parseContainerMembers(p: *Parser) !Members {
248 const scratch_top = p.scratch.items.len;248 const scratch_top = p.scratch.items.len;
249 defer p.scratch.shrinkRetainingCapacity(scratch_top);249 defer p.scratch.shrinkRetainingCapacity(scratch_top);
...@@ -622,7 +622,7 @@ const Parser = struct {...@@ -622,7 +622,7 @@ const Parser = struct {
622 };622 };
623 }623 }
624624
625 /// TopLevelDecl625 /// Decl
626 /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block)626 /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block)
627 /// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl627 /// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl
628 /// / KEYWORD_usingnamespace Expr SEMICOLON628 /// / KEYWORD_usingnamespace Expr SEMICOLON
src/Sema.zig+33-15
...@@ -335,6 +335,7 @@ pub const Block = struct {...@@ -335,6 +335,7 @@ pub const Block = struct {
335 /// It is shared among all the blocks in an inline or comptime called335 /// It is shared among all the blocks in an inline or comptime called
336 /// function.336 /// function.
337 pub const Inlining = struct {337 pub const Inlining = struct {
338 func: ?*Module.Fn,
338 comptime_result: Air.Inst.Ref,339 comptime_result: Air.Inst.Ref,
339 merges: Merges,340 merges: Merges,
340 };341 };
...@@ -6428,7 +6429,6 @@ fn analyzeCall(...@@ -6428,7 +6429,6 @@ fn analyzeCall(
6428 }),6429 }),
6429 else => unreachable,6430 else => unreachable,
6430 };6431 };
6431 if (!is_comptime_call and module_fn.state == .sema_failure) return error.AnalysisFail;
6432 if (func_ty_info.is_var_args) {6432 if (func_ty_info.is_var_args) {
6433 return sema.fail(block, call_src, "{s} call of variadic function", .{6433 return sema.fail(block, call_src, "{s} call of variadic function", .{
6434 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),6434 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
...@@ -6448,6 +6448,7 @@ fn analyzeCall(...@@ -6448,6 +6448,7 @@ fn analyzeCall(
6448 // This one is shared among sub-blocks within the same callee, but not6448 // This one is shared among sub-blocks within the same callee, but not
6449 // shared among the entire inline/comptime call stack.6449 // shared among the entire inline/comptime call stack.
6450 var inlining: Block.Inlining = .{6450 var inlining: Block.Inlining = .{
6451 .func = null,
6451 .comptime_result = undefined,6452 .comptime_result = undefined,
6452 .merges = .{6453 .merges = .{
6453 .results = .{},6454 .results = .{},
...@@ -6534,6 +6535,7 @@ fn analyzeCall(...@@ -6534,6 +6535,7 @@ fn analyzeCall(
6534 const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst);6535 const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst);
6535 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body);6536 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body);
65366537
6538 var has_comptime_args = false;
6537 var arg_i: usize = 0;6539 var arg_i: usize = 0;
6538 for (fn_info.param_body) |inst| {6540 for (fn_info.param_body) |inst| {
6539 sema.analyzeInlineCallArg(6541 sema.analyzeInlineCallArg(
...@@ -6549,6 +6551,7 @@ fn analyzeCall(...@@ -6549,6 +6551,7 @@ fn analyzeCall(
6549 memoized_call_key,6551 memoized_call_key,
6550 func_ty_info.param_types,6552 func_ty_info.param_types,
6551 func,6553 func,
6554 &has_comptime_args,
6552 ) catch |err| switch (err) {6555 ) catch |err| switch (err) {
6553 error.NeededSourceLocation => {6556 error.NeededSourceLocation => {
6554 _ = sema.inst_map.remove(inst);6557 _ = sema.inst_map.remove(inst);
...@@ -6566,6 +6569,7 @@ fn analyzeCall(...@@ -6566,6 +6569,7 @@ fn analyzeCall(
6566 memoized_call_key,6569 memoized_call_key,
6567 func_ty_info.param_types,6570 func_ty_info.param_types,
6568 func,6571 func,
6572 &has_comptime_args,
6569 );6573 );
6570 unreachable;6574 unreachable;
6571 },6575 },
...@@ -6573,6 +6577,19 @@ fn analyzeCall(...@@ -6573,6 +6577,19 @@ fn analyzeCall(
6573 };6577 };
6574 }6578 }
65756579
6580 if (!has_comptime_args and module_fn.state == .sema_failure) return error.AnalysisFail;
6581
6582 const recursive_msg = "inline call is recursive";
6583 var head = if (!has_comptime_args) block else null;
6584 while (head) |some| {
6585 const parent_inlining = some.inlining orelse break;
6586 if (parent_inlining.func == module_fn) {
6587 return sema.fail(block, call_src, recursive_msg, .{});
6588 }
6589 head = some.parent;
6590 }
6591 if (!has_comptime_args) inlining.func = module_fn;
6592
6576 // In case it is a generic function with an expression for the return type that depends6593 // In case it is a generic function with an expression for the return type that depends
6577 // on parameters, we must now do the same for the return type as we just did with6594 // on parameters, we must now do the same for the return type as we just did with
6578 // each of the parameters, resolving the return type and providing it to the child6595 // each of the parameters, resolving the return type and providing it to the child
...@@ -6657,6 +6674,7 @@ fn analyzeCall(...@@ -6657,6 +6674,7 @@ fn analyzeCall(
6657 error.ComptimeReturn => break :result inlining.comptime_result,6674 error.ComptimeReturn => break :result inlining.comptime_result,
6658 error.AnalysisFail => {6675 error.AnalysisFail => {
6659 const err_msg = sema.err orelse return err;6676 const err_msg = sema.err orelse return err;
6677 if (std.mem.eql(u8, err_msg.msg, recursive_msg)) return err;
6660 try sema.errNote(block, call_src, err_msg, "called from here", .{});6678 try sema.errNote(block, call_src, err_msg, "called from here", .{});
6661 err_msg.clearTrace(sema.gpa);6679 err_msg.clearTrace(sema.gpa);
6662 return err;6680 return err;
...@@ -6814,8 +6832,13 @@ fn analyzeInlineCallArg(...@@ -6814,8 +6832,13 @@ fn analyzeInlineCallArg(
6814 memoized_call_key: Module.MemoizedCall.Key,6832 memoized_call_key: Module.MemoizedCall.Key,
6815 raw_param_types: []const Type,6833 raw_param_types: []const Type,
6816 func_inst: Air.Inst.Ref,6834 func_inst: Air.Inst.Ref,
6835 has_comptime_args: *bool,
6817) !void {6836) !void {
6818 const zir_tags = sema.code.instructions.items(.tag);6837 const zir_tags = sema.code.instructions.items(.tag);
6838 switch (zir_tags[inst]) {
6839 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,
6840 else => {},
6841 }
6819 switch (zir_tags[inst]) {6842 switch (zir_tags[inst]) {
6820 .param, .param_comptime => {6843 .param, .param_comptime => {
6821 // Evaluate the parameter type expression now that previous ones have6844 // Evaluate the parameter type expression now that previous ones have
...@@ -6870,23 +6893,20 @@ fn analyzeInlineCallArg(...@@ -6870,23 +6893,20 @@ fn analyzeInlineCallArg(
6870 .ty = param_ty,6893 .ty = param_ty,
6871 .val = arg_val,6894 .val = arg_val,
6872 };6895 };
6873 } else if (zir_tags[inst] == .param_comptime or try sema.typeRequiresComptime(param_ty)) {
6874 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);
6875 } else if (try sema.resolveMaybeUndefVal(casted_arg)) |val| {
6876 // We have a comptime value but we need a runtime value to preserve inlining semantics,
6877 const wrapped = try sema.addConstant(param_ty, try Value.Tag.runtime_value.create(sema.arena, val));
6878 sema.inst_map.putAssumeCapacityNoClobber(inst, wrapped);
6879 } else {6896 } else {
6880 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);6897 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);
6881 }6898 }
68826899
6900 if (try sema.resolveMaybeUndefVal(casted_arg)) |_| {
6901 has_comptime_args.* = true;
6902 }
6903
6883 arg_i.* += 1;6904 arg_i.* += 1;
6884 },6905 },
6885 .param_anytype, .param_anytype_comptime => {6906 .param_anytype, .param_anytype_comptime => {
6886 // No coercion needed.6907 // No coercion needed.
6887 const uncasted_arg = uncasted_args[arg_i.*];6908 const uncasted_arg = uncasted_args[arg_i.*];
6888 new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg);6909 new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg);
6889 const param_ty = sema.typeOf(uncasted_arg);
68906910
6891 if (is_comptime_call) {6911 if (is_comptime_call) {
6892 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);6912 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
...@@ -6912,16 +6932,14 @@ fn analyzeInlineCallArg(...@@ -6912,16 +6932,14 @@ fn analyzeInlineCallArg(
6912 .ty = sema.typeOf(uncasted_arg),6932 .ty = sema.typeOf(uncasted_arg),
6913 .val = arg_val,6933 .val = arg_val,
6914 };6934 };
6915 } else if (zir_tags[inst] == .param_anytype_comptime or try sema.typeRequiresComptime(param_ty)) {
6916 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
6917 } else if (try sema.resolveMaybeUndefVal(uncasted_arg)) |val| {
6918 // We have a comptime value but we need a runtime value to preserve inlining semantics,
6919 const wrapped = try sema.addConstant(param_ty, try Value.Tag.runtime_value.create(sema.arena, val));
6920 sema.inst_map.putAssumeCapacityNoClobber(inst, wrapped);
6921 } else {6935 } else {
6922 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);6936 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
6923 }6937 }
69246938
6939 if (try sema.resolveMaybeUndefVal(uncasted_arg)) |_| {
6940 has_comptime_args.* = true;
6941 }
6942
6925 arg_i.* += 1;6943 arg_i.* += 1;
6926 },6944 },
6927 else => {},6945 else => {},
...@@ -33075,7 +33093,7 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {...@@ -33075,7 +33093,7 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
33075 host_size: u16 = 0,33093 host_size: u16 = 0,
33076 alignment: u32 = 0,33094 alignment: u32 = 0,
33077 vector_index: VI = .none,33095 vector_index: VI = .none,
33078 } = if (parent_ty.tag() == .vector) blk: {33096 } = if (parent_ty.tag() == .vector and ptr_info.size == .One) blk: {
33079 const elem_bits = elem_ty.bitSize(target);33097 const elem_bits = elem_ty.bitSize(target);
33080 if (elem_bits == 0) break :blk .{};33098 if (elem_bits == 0) break :blk .{};
33081 const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits);33099 const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits);
src/codegen/llvm.zig+4
...@@ -3361,6 +3361,10 @@ pub const DeclGen = struct {...@@ -3361,6 +3361,10 @@ pub const DeclGen = struct {
3361 const llvm_type = try dg.lowerType(tv.ty);3361 const llvm_type = try dg.lowerType(tv.ty);
3362 return llvm_type.constNull();3362 return llvm_type.constNull();
3363 },3363 },
3364 .opt_payload => {
3365 const payload = tv.val.castTag(.opt_payload).?.data;
3366 return dg.lowerParentPtr(payload, tv.ty);
3367 },
3364 else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{3368 else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{
3365 tv.ty.fmtDebug(), tag,3369 tv.ty.fmtDebug(), tag,
3366 }),3370 }),
test/behavior.zig-1
...@@ -133,7 +133,6 @@ test {...@@ -133,7 +133,6 @@ test {
133 _ = @import("behavior/bugs/13113.zig");133 _ = @import("behavior/bugs/13113.zig");
134 _ = @import("behavior/bugs/13128.zig");134 _ = @import("behavior/bugs/13128.zig");
135 _ = @import("behavior/bugs/13159.zig");135 _ = @import("behavior/bugs/13159.zig");
136 _ = @import("behavior/bugs/13164.zig");
137 _ = @import("behavior/bugs/13171.zig");136 _ = @import("behavior/bugs/13171.zig");
138 _ = @import("behavior/bugs/13209.zig");137 _ = @import("behavior/bugs/13209.zig");
139 _ = @import("behavior/bugs/13285.zig");138 _ = @import("behavior/bugs/13285.zig");
test/behavior/bugs/13164.zig deleted-18
...@@ -1,18 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4inline fn setLimits(min: ?u32, max: ?u32) !void {
5 if (min != null and max != null) {
6 try std.testing.expect(min.? <= max.?);
7 }
8}
9
10test {
11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15
16 var x: u32 = 42;
17 try setLimits(x, null);
18}
test/behavior/call.zig+14
...@@ -381,3 +381,17 @@ test "generic function with generic function parameter" {...@@ -381,3 +381,17 @@ test "generic function with generic function parameter" {
381 };381 };
382 try S.f(S.g, 123);382 try S.f(S.g, 123);
383}383}
384
385test "recursive inline call with comptime known argument" {
386 const S = struct {
387 inline fn foo(x: i32) i32 {
388 if (x <= 0) {
389 return 0;
390 } else {
391 return x * 2 + foo(x - 1);
392 }
393 }
394 };
395
396 try expect(S.foo(4) == 20);
397}
test/behavior/vector.zig+16
...@@ -1261,3 +1261,19 @@ test "store packed vector element" {...@@ -1261,3 +1261,19 @@ test "store packed vector element" {
1261 v[0] = 0;1261 v[0] = 0;
1262 try expectEqual(@Vector(4, u1){ 0, 1, 1, 1 }, v);1262 try expectEqual(@Vector(4, u1){ 0, 1, 1, 1 }, v);
1263}1263}
1264
1265test "store to vector in slice" {
1266 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1267 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1268 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1269 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1270
1271 var v = [_]@Vector(3, f32){
1272 .{ 1, 1, 1 },
1273 .{ 0, 0, 0 },
1274 };
1275 var s: []@Vector(3, f32) = &v;
1276 var i: usize = 1;
1277 s[i] = s[0];
1278 try expectEqual(v[1], v[0]);
1279}
test/cases/compile_errors/recursive_inline_fn.zig created+18
...@@ -0,0 +1,18 @@
1inline fn foo(x: i32) i32 {
2 if (x <= 0) {
3 return 0;
4 } else {
5 return x * 2 + foo(x - 1);
6 }
7}
8
9pub export fn entry() void {
10 var x: i32 = 4;
11 _ = foo(x) == 20;
12}
13
14// error
15// backend=stage2
16// target=native
17//
18// :5:27: error: inline call is recursive