| ... | ... | @@ -3930,6 +3930,23 @@ fn analyzeBlockBody( |
| 3930 | 3930 | // to emit a jump instruction to after the block when it encounters the break. |
| 3931 | 3931 | try parent_block.instructions.append(gpa, merges.block_inst); |
| 3932 | 3932 | const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .none); |
| 3933 | |
| 3934 | const type_src = src; // TODO: better source location |
| 3935 | const valid_rt = try sema.validateRunTimeType(child_block, type_src, resolved_ty, false); |
| 3936 | if (!valid_rt) { |
| 3937 | const msg = msg: { |
| 3938 | const msg = try sema.errMsg(child_block, type_src, "value with comptime only type '{}' depends on runtime control flow", .{resolved_ty}); |
| 3939 | errdefer msg.destroy(sema.gpa); |
| 3940 | |
| 3941 | const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?; |
| 3942 | try sema.errNote(child_block, runtime_src, msg, "runtime control flow here", .{}); |
| 3943 | |
| 3944 | try sema.explainWhyTypeIsComptime(child_block, type_src, msg, type_src.toSrcLoc(child_block.src_decl), resolved_ty); |
| 3945 | |
| 3946 | break :msg msg; |
| 3947 | }; |
| 3948 | return sema.failWithOwnedErrorMsg(child_block, msg); |
| 3949 | } |
| 3933 | 3950 | const ty_inst = try sema.addType(resolved_ty); |
| 3934 | 3951 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + |
| 3935 | 3952 | child_block.instructions.items.len); |
| ... | ... | @@ -4191,6 +4208,11 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError |
| 4191 | 4208 | const br_ref = try start_block.addBr(label.merges.block_inst, operand); |
| 4192 | 4209 | try label.merges.results.append(sema.gpa, operand); |
| 4193 | 4210 | try label.merges.br_list.append(sema.gpa, Air.refToIndex(br_ref).?); |
| 4211 | block.runtime_index += 1; |
| 4212 | if (block.runtime_cond == null and block.runtime_loop == null) { |
| 4213 | block.runtime_cond = start_block.runtime_cond orelse start_block.runtime_loop; |
| 4214 | block.runtime_loop = start_block.runtime_loop; |
| 4215 | } |
| 4194 | 4216 | return inst; |
| 4195 | 4217 | } |
| 4196 | 4218 | } |
| ... | ... | @@ -15447,6 +15469,26 @@ fn validateVarType( |
| 15447 | 15469 | var_ty: Type, |
| 15448 | 15470 | is_extern: bool, |
| 15449 | 15471 | ) CompileError!void { |
| 15472 | if (try sema.validateRunTimeType(block, src, var_ty, is_extern)) return; |
| 15473 | |
| 15474 | const msg = msg: { |
| 15475 | const msg = try sema.errMsg(block, src, "variable of type '{}' must be const or comptime", .{var_ty}); |
| 15476 | errdefer msg.destroy(sema.gpa); |
| 15477 | |
| 15478 | try sema.explainWhyTypeIsComptime(block, src, msg, src.toSrcLoc(block.src_decl), var_ty); |
| 15479 | |
| 15480 | break :msg msg; |
| 15481 | }; |
| 15482 | return sema.failWithOwnedErrorMsg(block, msg); |
| 15483 | } |
| 15484 | |
| 15485 | fn validateRunTimeType( |
| 15486 | sema: *Sema, |
| 15487 | block: *Block, |
| 15488 | src: LazySrcLoc, |
| 15489 | var_ty: Type, |
| 15490 | is_extern: bool, |
| 15491 | ) CompileError!bool { |
| 15450 | 15492 | var ty = var_ty; |
| 15451 | 15493 | while (true) switch (ty.zigTypeTag()) { |
| 15452 | 15494 | .Bool, |
| ... | ... | @@ -15457,7 +15499,7 @@ fn validateVarType( |
| 15457 | 15499 | .Frame, |
| 15458 | 15500 | .AnyFrame, |
| 15459 | 15501 | .Void, |
| 15460 | | => return, |
| 15502 | => return true, |
| 15461 | 15503 | |
| 15462 | 15504 | .BoundFn, |
| 15463 | 15505 | .ComptimeFloat, |
| ... | ... | @@ -15468,21 +15510,21 @@ fn validateVarType( |
| 15468 | 15510 | .Undefined, |
| 15469 | 15511 | .Null, |
| 15470 | 15512 | .Fn, |
| 15471 | | => break, |
| 15513 | => return false, |
| 15472 | 15514 | |
| 15473 | 15515 | .Pointer => { |
| 15474 | 15516 | const elem_ty = ty.childType(); |
| 15475 | 15517 | switch (elem_ty.zigTypeTag()) { |
| 15476 | | .Opaque, .Fn => return, |
| 15518 | .Opaque, .Fn => return true, |
| 15477 | 15519 | else => ty = elem_ty, |
| 15478 | 15520 | } |
| 15479 | 15521 | }, |
| 15480 | | .Opaque => if (is_extern) return else break, |
| 15522 | .Opaque => return is_extern, |
| 15481 | 15523 | |
| 15482 | 15524 | .Optional => { |
| 15483 | 15525 | var buf: Type.Payload.ElemType = undefined; |
| 15484 | 15526 | const child_ty = ty.optionalChild(&buf); |
| 15485 | | return validateVarType(sema, block, src, child_ty, is_extern); |
| 15527 | return validateRunTimeType(sema, block, src, child_ty, is_extern); |
| 15486 | 15528 | }, |
| 15487 | 15529 | .Array, .Vector => ty = ty.elemType(), |
| 15488 | 15530 | |
| ... | ... | @@ -15490,23 +15532,10 @@ fn validateVarType( |
| 15490 | 15532 | |
| 15491 | 15533 | .Struct, .Union => { |
| 15492 | 15534 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 15493 | | if (try sema.typeRequiresComptime(block, src, resolved_ty)) { |
| 15494 | | break; |
| 15495 | | } else { |
| 15496 | | return; |
| 15497 | | } |
| 15535 | const needs_comptime = try sema.typeRequiresComptime(block, src, resolved_ty); |
| 15536 | return !needs_comptime; |
| 15498 | 15537 | }, |
| 15499 | | } else unreachable; // TODO should not need else unreachable |
| 15500 | | |
| 15501 | | const msg = msg: { |
| 15502 | | const msg = try sema.errMsg(block, src, "variable of type '{}' must be const or comptime", .{var_ty}); |
| 15503 | | errdefer msg.destroy(sema.gpa); |
| 15504 | | |
| 15505 | | try sema.explainWhyTypeIsComptime(block, src, msg, src.toSrcLoc(block.src_decl), var_ty); |
| 15506 | | |
| 15507 | | break :msg msg; |
| 15508 | 15538 | }; |
| 15509 | | return sema.failWithOwnedErrorMsg(block, msg); |
| 15510 | 15539 | } |
| 15511 | 15540 | |
| 15512 | 15541 | fn explainWhyTypeIsComptime( |
| ... | ... | @@ -20351,6 +20380,20 @@ pub fn resolveTypeFully( |
| 20351 | 20380 | return resolveTypeFully(sema, block, src, ty.optionalChild(&buf)); |
| 20352 | 20381 | }, |
| 20353 | 20382 | .ErrorUnion => return resolveTypeFully(sema, block, src, ty.errorUnionPayload()), |
| 20383 | .Fn => { |
| 20384 | const info = ty.fnInfo(); |
| 20385 | if (info.is_generic) { |
| 20386 | // Resolving of generic function types is defeerred to when |
| 20387 | // the function is instantiated. |
| 20388 | return; |
| 20389 | } |
| 20390 | for (info.param_types) |param_ty| { |
| 20391 | const param_ty_src = src; // TODO better source location |
| 20392 | try sema.resolveTypeFully(block, param_ty_src, param_ty); |
| 20393 | } |
| 20394 | const return_ty_src = src; // TODO better source location |
| 20395 | try sema.resolveTypeFully(block, return_ty_src, info.return_type); |
| 20396 | }, |
| 20354 | 20397 | else => {}, |
| 20355 | 20398 | } |
| 20356 | 20399 | } |