| ... | @@ -3930,6 +3930,23 @@ fn analyzeBlockBody( | ... | @@ -3930,6 +3930,23 @@ fn analyzeBlockBody( |
| 3930 | // to emit a jump instruction to after the block when it encounters the break. | 3930 | // to emit a jump instruction to after the block when it encounters the break. |
| 3931 | try parent_block.instructions.append(gpa, merges.block_inst); | 3931 | try parent_block.instructions.append(gpa, merges.block_inst); |
| 3932 | const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .none); | 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 | const ty_inst = try sema.addType(resolved_ty); | 3950 | const ty_inst = try sema.addType(resolved_ty); |
| 3934 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + | 3951 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + |
| 3935 | child_block.instructions.items.len); | 3952 | child_block.instructions.items.len); |
| ... | @@ -4191,6 +4208,11 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -4191,6 +4208,11 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError |
| 4191 | const br_ref = try start_block.addBr(label.merges.block_inst, operand); | 4208 | const br_ref = try start_block.addBr(label.merges.block_inst, operand); |
| 4192 | try label.merges.results.append(sema.gpa, operand); | 4209 | try label.merges.results.append(sema.gpa, operand); |
| 4193 | try label.merges.br_list.append(sema.gpa, Air.refToIndex(br_ref).?); | 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 | return inst; | 4216 | return inst; |
| 4195 | } | 4217 | } |
| 4196 | } | 4218 | } |
| ... | @@ -15447,6 +15469,26 @@ fn validateVarType( | ... | @@ -15447,6 +15469,26 @@ fn validateVarType( |
| 15447 | var_ty: Type, | 15469 | var_ty: Type, |
| 15448 | is_extern: bool, | 15470 | is_extern: bool, |
| 15449 | ) CompileError!void { | 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 | var ty = var_ty; | 15492 | var ty = var_ty; |
| 15451 | while (true) switch (ty.zigTypeTag()) { | 15493 | while (true) switch (ty.zigTypeTag()) { |
| 15452 | .Bool, | 15494 | .Bool, |
| ... | @@ -15457,7 +15499,7 @@ fn validateVarType( | ... | @@ -15457,7 +15499,7 @@ fn validateVarType( |
| 15457 | .Frame, | 15499 | .Frame, |
| 15458 | .AnyFrame, | 15500 | .AnyFrame, |
| 15459 | .Void, | 15501 | .Void, |
| 15460 | => return, | 15502 | => return true, |
| 15461 | | 15503 | |
| 15462 | .BoundFn, | 15504 | .BoundFn, |
| 15463 | .ComptimeFloat, | 15505 | .ComptimeFloat, |
| ... | @@ -15468,21 +15510,21 @@ fn validateVarType( | ... | @@ -15468,21 +15510,21 @@ fn validateVarType( |
| 15468 | .Undefined, | 15510 | .Undefined, |
| 15469 | .Null, | 15511 | .Null, |
| 15470 | .Fn, | 15512 | .Fn, |
| 15471 | => break, | 15513 | => return false, |
| 15472 | | 15514 | |
| 15473 | .Pointer => { | 15515 | .Pointer => { |
| 15474 | const elem_ty = ty.childType(); | 15516 | const elem_ty = ty.childType(); |
| 15475 | switch (elem_ty.zigTypeTag()) { | 15517 | switch (elem_ty.zigTypeTag()) { |
| 15476 | .Opaque, .Fn => return, | 15518 | .Opaque, .Fn => return true, |
| 15477 | else => ty = elem_ty, | 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 | .Optional => { | 15524 | .Optional => { |
| 15483 | var buf: Type.Payload.ElemType = undefined; | 15525 | var buf: Type.Payload.ElemType = undefined; |
| 15484 | const child_ty = ty.optionalChild(&buf); | 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 | .Array, .Vector => ty = ty.elemType(), | 15529 | .Array, .Vector => ty = ty.elemType(), |
| 15488 | | 15530 | |
| ... | @@ -15490,23 +15532,10 @@ fn validateVarType( | ... | @@ -15490,23 +15532,10 @@ fn validateVarType( |
| 15490 | | 15532 | |
| 15491 | .Struct, .Union => { | 15533 | .Struct, .Union => { |
| 15492 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); | 15534 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 15493 | if (try sema.typeRequiresComptime(block, src, resolved_ty)) { | 15535 | const needs_comptime = try sema.typeRequiresComptime(block, src, resolved_ty); |
| 15494 | break; | 15536 | return !needs_comptime; |
| 15495 | } else { | | |
| 15496 | return; | | |
| 15497 | } | | |
| 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 | fn explainWhyTypeIsComptime( | 15541 | fn explainWhyTypeIsComptime( |
| ... | @@ -20351,6 +20380,20 @@ pub fn resolveTypeFully( | ... | @@ -20351,6 +20380,20 @@ pub fn resolveTypeFully( |
| 20351 | return resolveTypeFully(sema, block, src, ty.optionalChild(&buf)); | 20380 | return resolveTypeFully(sema, block, src, ty.optionalChild(&buf)); |
| 20352 | }, | 20381 | }, |
| 20353 | .ErrorUnion => return resolveTypeFully(sema, block, src, ty.errorUnionPayload()), | 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 | else => {}, | 20397 | else => {}, |
| 20355 | } | 20398 | } |
| 20356 | } | 20399 | } |