| ... | @@ -5643,6 +5643,37 @@ const GenericCallAdapter = struct { | ... | @@ -5643,6 +5643,37 @@ const GenericCallAdapter = struct { |
| 5643 | } | 5643 | } |
| 5644 | }; | 5644 | }; |
| 5645 | | 5645 | |
| | 5646 | fn addComptimeReturnTypeNote( |
| | 5647 | sema: *Sema, |
| | 5648 | block: *Block, |
| | 5649 | func: Air.Inst.Ref, |
| | 5650 | func_src: LazySrcLoc, |
| | 5651 | return_ty: Type, |
| | 5652 | parent: *Module.ErrorMsg, |
| | 5653 | requires_comptime: bool, |
| | 5654 | ) !void { |
| | 5655 | if (!requires_comptime) return; |
| | 5656 | |
| | 5657 | const src_loc = if (try sema.funcDeclSrc(block, func_src, func)) |capture| blk: { |
| | 5658 | var src_loc = capture; |
| | 5659 | src_loc.lazy = .{ .node_offset_fn_type_ret_ty = 0 }; |
| | 5660 | break :blk src_loc; |
| | 5661 | } else blk: { |
| | 5662 | const src_decl = sema.mod.declPtr(block.src_decl); |
| | 5663 | break :blk func_src.toSrcLoc(src_decl); |
| | 5664 | }; |
| | 5665 | if (return_ty.tag() == .generic_poison) { |
| | 5666 | return sema.mod.errNoteNonLazy(src_loc, parent, "generic function is instantiated with a comptime only return type", .{}); |
| | 5667 | } |
| | 5668 | try sema.mod.errNoteNonLazy( |
| | 5669 | src_loc, |
| | 5670 | parent, |
| | 5671 | "function is being called at comptime because it returns a comptime only type '{}'", |
| | 5672 | .{return_ty.fmt(sema.mod)}, |
| | 5673 | ); |
| | 5674 | try sema.explainWhyTypeIsComptime(block, func_src, parent, src_loc, return_ty); |
| | 5675 | } |
| | 5676 | |
| 5646 | fn analyzeCall( | 5677 | fn analyzeCall( |
| 5647 | sema: *Sema, | 5678 | sema: *Sema, |
| 5648 | block: *Block, | 5679 | block: *Block, |
| ... | @@ -5733,9 +5764,11 @@ fn analyzeCall( | ... | @@ -5733,9 +5764,11 @@ fn analyzeCall( |
| 5733 | | 5764 | |
| 5734 | var is_generic_call = func_ty_info.is_generic; | 5765 | var is_generic_call = func_ty_info.is_generic; |
| 5735 | var is_comptime_call = block.is_comptime or modifier == .compile_time; | 5766 | var is_comptime_call = block.is_comptime or modifier == .compile_time; |
| | 5767 | var comptime_only_ret_ty = false; |
| 5736 | if (!is_comptime_call) { | 5768 | if (!is_comptime_call) { |
| 5737 | if (sema.typeRequiresComptime(block, func_src, func_ty_info.return_type)) |ct| { | 5769 | if (sema.typeRequiresComptime(block, func_src, func_ty_info.return_type)) |ct| { |
| 5738 | is_comptime_call = ct; | 5770 | is_comptime_call = ct; |
| | 5771 | comptime_only_ret_ty = ct; |
| 5739 | } else |err| switch (err) { | 5772 | } else |err| switch (err) { |
| 5740 | error.GenericPoison => is_generic_call = true, | 5773 | error.GenericPoison => is_generic_call = true, |
| 5741 | else => |e| return e, | 5774 | else => |e| return e, |
| ... | @@ -5764,6 +5797,7 @@ fn analyzeCall( | ... | @@ -5764,6 +5797,7 @@ fn analyzeCall( |
| 5764 | error.ComptimeReturn => { | 5797 | error.ComptimeReturn => { |
| 5765 | is_inline_call = true; | 5798 | is_inline_call = true; |
| 5766 | is_comptime_call = true; | 5799 | is_comptime_call = true; |
| | 5800 | comptime_only_ret_ty = true; |
| 5767 | }, | 5801 | }, |
| 5768 | else => |e| return e, | 5802 | else => |e| return e, |
| 5769 | } | 5803 | } |
| ... | @@ -5774,8 +5808,12 @@ fn analyzeCall( | ... | @@ -5774,8 +5808,12 @@ fn analyzeCall( |
| 5774 | } | 5808 | } |
| 5775 | | 5809 | |
| 5776 | const result: Air.Inst.Ref = if (is_inline_call) res: { | 5810 | const result: Air.Inst.Ref = if (is_inline_call) res: { |
| 5777 | // TODO explain why function is being called at comptime | 5811 | const func_val = sema.resolveConstValue(block, func_src, func, "function being called at comptime must be comptime known") catch |err| { |
| 5778 | const func_val = try sema.resolveConstValue(block, func_src, func, "function being called at comptime must be comptime known"); | 5812 | if (err == error.AnalysisFail and sema.err != null) { |
| | 5813 | try sema.addComptimeReturnTypeNote(block, func, func_src, func_ty_info.return_type, sema.err.?, comptime_only_ret_ty); |
| | 5814 | } |
| | 5815 | return err; |
| | 5816 | }; |
| 5779 | const module_fn = switch (func_val.tag()) { | 5817 | const module_fn = switch (func_val.tag()) { |
| 5780 | .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data, | 5818 | .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data, |
| 5781 | .function => func_val.castTag(.function).?.data, | 5819 | .function => func_val.castTag(.function).?.data, |
| ... | @@ -5887,6 +5925,11 @@ fn analyzeCall( | ... | @@ -5887,6 +5925,11 @@ fn analyzeCall( |
| 5887 | is_comptime_call, | 5925 | is_comptime_call, |
| 5888 | &should_memoize, | 5926 | &should_memoize, |
| 5889 | memoized_call_key, | 5927 | memoized_call_key, |
| | 5928 | // last 4 arguments are only used when reporting errors |
| | 5929 | undefined, |
| | 5930 | undefined, |
| | 5931 | undefined, |
| | 5932 | undefined, |
| 5890 | ) catch |err| switch (err) { | 5933 | ) catch |err| switch (err) { |
| 5891 | error.NeededSourceLocation => { | 5934 | error.NeededSourceLocation => { |
| 5892 | sema.inst_map.clearRetainingCapacity(); | 5935 | sema.inst_map.clearRetainingCapacity(); |
| ... | @@ -5904,6 +5947,10 @@ fn analyzeCall( | ... | @@ -5904,6 +5947,10 @@ fn analyzeCall( |
| 5904 | is_comptime_call, | 5947 | is_comptime_call, |
| 5905 | &should_memoize, | 5948 | &should_memoize, |
| 5906 | memoized_call_key, | 5949 | memoized_call_key, |
| | 5950 | func, |
| | 5951 | func_src, |
| | 5952 | func_ty_info.return_type, |
| | 5953 | comptime_only_ret_ty, |
| 5907 | ); | 5954 | ); |
| 5908 | return error.AnalysisFail; | 5955 | return error.AnalysisFail; |
| 5909 | }, | 5956 | }, |
| ... | @@ -6119,6 +6166,10 @@ fn analyzeInlineCallArg( | ... | @@ -6119,6 +6166,10 @@ fn analyzeInlineCallArg( |
| 6119 | is_comptime_call: bool, | 6166 | is_comptime_call: bool, |
| 6120 | should_memoize: *bool, | 6167 | should_memoize: *bool, |
| 6121 | memoized_call_key: Module.MemoizedCall.Key, | 6168 | memoized_call_key: Module.MemoizedCall.Key, |
| | 6169 | func: Air.Inst.Ref, |
| | 6170 | func_src: LazySrcLoc, |
| | 6171 | ret_ty: Type, |
| | 6172 | comptime_only_ret_ty: bool, |
| 6122 | ) !void { | 6173 | ) !void { |
| 6123 | const zir_tags = sema.code.instructions.items(.tag); | 6174 | const zir_tags = sema.code.instructions.items(.tag); |
| 6124 | switch (zir_tags[inst]) { | 6175 | switch (zir_tags[inst]) { |
| ... | @@ -6134,14 +6185,23 @@ fn analyzeInlineCallArg( | ... | @@ -6134,14 +6185,23 @@ fn analyzeInlineCallArg( |
| 6134 | new_fn_info.param_types[arg_i.*] = param_ty; | 6185 | new_fn_info.param_types[arg_i.*] = param_ty; |
| 6135 | const uncasted_arg = uncasted_args[arg_i.*]; | 6186 | const uncasted_arg = uncasted_args[arg_i.*]; |
| 6136 | if (try sema.typeRequiresComptime(arg_block, arg_src, param_ty)) { | 6187 | if (try sema.typeRequiresComptime(arg_block, arg_src, param_ty)) { |
| 6137 | _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime only type must be comptime known"); | 6188 | _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime only type must be comptime known") catch |err| { |
| | 6189 | if (err == error.AnalysisFail and sema.err != null) { |
| | 6190 | try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty); |
| | 6191 | } |
| | 6192 | return err; |
| | 6193 | }; |
| 6138 | } | 6194 | } |
| 6139 | const casted_arg = try sema.coerce(arg_block, param_ty, uncasted_arg, arg_src); | 6195 | const casted_arg = try sema.coerce(arg_block, param_ty, uncasted_arg, arg_src); |
| 6140 | try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg); | 6196 | try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg); |
| 6141 | | 6197 | |
| 6142 | if (is_comptime_call) { | 6198 | if (is_comptime_call) { |
| 6143 | // TODO explain why function is being called at comptime | 6199 | const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime known") catch |err| { |
| 6144 | const arg_val = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime known"); | 6200 | if (err == error.AnalysisFail and sema.err != null) { |
| | 6201 | try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty); |
| | 6202 | } |
| | 6203 | return err; |
| | 6204 | }; |
| 6145 | switch (arg_val.tag()) { | 6205 | switch (arg_val.tag()) { |
| 6146 | .generic_poison, .generic_poison_type => { | 6206 | .generic_poison, .generic_poison_type => { |
| 6147 | // This function is currently evaluated as part of an as-of-yet unresolvable | 6207 | // This function is currently evaluated as part of an as-of-yet unresolvable |
| ... | @@ -6171,8 +6231,12 @@ fn analyzeInlineCallArg( | ... | @@ -6171,8 +6231,12 @@ fn analyzeInlineCallArg( |
| 6171 | try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg); | 6231 | try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg); |
| 6172 | | 6232 | |
| 6173 | if (is_comptime_call) { | 6233 | if (is_comptime_call) { |
| 6174 | // TODO explain why function is being called at comptime | 6234 | const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime known") catch |err| { |
| 6175 | const arg_val = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime known"); | 6235 | if (err == error.AnalysisFail and sema.err != null) { |
| | 6236 | try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty); |
| | 6237 | } |
| | 6238 | return err; |
| | 6239 | }; |
| 6176 | switch (arg_val.tag()) { | 6240 | switch (arg_val.tag()) { |
| 6177 | .generic_poison, .generic_poison_type => { | 6241 | .generic_poison, .generic_poison_type => { |
| 6178 | // This function is currently evaluated as part of an as-of-yet unresolvable | 6242 | // This function is currently evaluated as part of an as-of-yet unresolvable |