| ... | ... | @@ -38590,7 +38590,7 @@ pub fn resolveNavPtrModifiers( |
| 38590 | 38590 | }; |
| 38591 | 38591 | } |
| 38592 | 38592 | |
| 38593 | | pub fn analyzeMemoizedState(sema: *Sema, block: *Block, src: LazySrcLoc, builtin_namespace: InternPool.NamespaceIndex, stage: InternPool.MemoizedStateStage) CompileError!bool { |
| 38593 | pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, builtin_namespace: InternPool.NamespaceIndex, stage: InternPool.MemoizedStateStage) CompileError!bool { |
| 38594 | 38594 | const pt = sema.pt; |
| 38595 | 38595 | const zcu = pt.zcu; |
| 38596 | 38596 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -38605,38 +38605,47 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, src: LazySrcLoc, builtin |
| 38605 | 38605 | .nested => |nested| access: { |
| 38606 | 38606 | const parent_ty: Type = .fromInterned(zcu.builtin_decl_values.get(nested[0])); |
| 38607 | 38607 | const parent_ns = parent_ty.getNamespace(zcu).unwrap() orelse { |
| 38608 | | return sema.fail(block, src, "std.builtin.{s} is not a container type", .{@tagName(nested[0])}); |
| 38608 | return sema.fail(block, simple_src, "std.builtin.{s} is not a container type", .{@tagName(nested[0])}); |
| 38609 | 38609 | }; |
| 38610 | 38610 | break :access .{ parent_ns, "std.builtin." ++ @tagName(nested[0]), nested[1] }; |
| 38611 | 38611 | }, |
| 38612 | 38612 | }; |
| 38613 | 38613 | |
| 38614 | 38614 | const name_nts = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls); |
| 38615 | | const result = try sema.namespaceLookupVal(block, src, parent_ns, name_nts) orelse |
| 38616 | | return sema.fail(block, src, "{s} missing {s}", .{ parent_name, name }); |
| 38615 | const nav = try sema.namespaceLookup(block, simple_src, parent_ns, name_nts) orelse |
| 38616 | return sema.fail(block, simple_src, "{s} missing {s}", .{ parent_name, name }); |
| 38617 | 38617 | |
| 38618 | | const val = try sema.resolveConstDefinedValue(block, src, result, null); |
| 38618 | const src: LazySrcLoc = .{ |
| 38619 | .base_node_inst = ip.getNav(nav).srcInst(ip), |
| 38620 | .offset = .nodeOffset(0), |
| 38621 | }; |
| 38619 | 38622 | |
| 38620 | | switch (builtin_decl.kind()) { |
| 38621 | | .type => if (val.typeOf(zcu).zigTypeTag(zcu) != .type) { |
| 38623 | const result = try sema.analyzeNavVal(block, src, nav); |
| 38624 | |
| 38625 | const uncoerced_val = try sema.resolveConstDefinedValue(block, src, result, null); |
| 38626 | const maybe_lazy_val: Value = switch (builtin_decl.kind()) { |
| 38627 | .type => if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .type) { |
| 38622 | 38628 | return sema.fail(block, src, "{s}.{s} is not a type", .{ parent_name, name }); |
| 38623 | | } else { |
| 38624 | | try val.toType().resolveFully(pt); |
| 38629 | } else val: { |
| 38630 | try uncoerced_val.toType().resolveFully(pt); |
| 38631 | break :val uncoerced_val; |
| 38625 | 38632 | }, |
| 38626 | | .func => if (val.typeOf(zcu).zigTypeTag(zcu) != .@"fn") { |
| 38627 | | return sema.fail(block, src, "{s}.{s} is not a function", .{ parent_name, name }); |
| 38628 | | }, |
| 38629 | | .string => { |
| 38630 | | const ty = val.typeOf(zcu); |
| 38631 | | if (!ty.isSinglePointer(zcu) or |
| 38632 | | !ty.isConstPtr(zcu) or |
| 38633 | | ty.childType(zcu).zigTypeTag(zcu) != .array or |
| 38634 | | ty.childType(zcu).childType(zcu).toIntern() != .u8_type) |
| 38635 | | { |
| 38636 | | return sema.fail(block, src, "{s}.{s} is not a valid string", .{ parent_name, name }); |
| 38633 | .func => val: { |
| 38634 | if (try sema.getExpectedBuiltinFnType(src, builtin_decl)) |func_ty| { |
| 38635 | const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src); |
| 38636 | break :val .fromInterned(coerced.toInterned().?); |
| 38637 | 38637 | } |
| 38638 | if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .@"fn") { |
| 38639 | return sema.fail(block, src, "{s}.{s} is not a function", .{ parent_name, name }); |
| 38640 | } |
| 38641 | break :val uncoerced_val; |
| 38638 | 38642 | }, |
| 38639 | | } |
| 38643 | .string => val: { |
| 38644 | const coerced = try sema.coerce(block, .slice_const_u8, Air.internedToRef(uncoerced_val.toIntern()), src); |
| 38645 | break :val .fromInterned(coerced.toInterned().?); |
| 38646 | }, |
| 38647 | }; |
| 38648 | const val = try sema.resolveLazyValue(maybe_lazy_val); |
| 38640 | 38649 | |
| 38641 | 38650 | const prev = zcu.builtin_decl_values.get(builtin_decl); |
| 38642 | 38651 | if (val.toIntern() != prev) { |
| ... | ... | @@ -38648,7 +38657,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, src: LazySrcLoc, builtin |
| 38648 | 38657 | |
| 38649 | 38658 | if (stage == .panic) { |
| 38650 | 38659 | // We use `getBuiltinType` because this is from an earlier stage. |
| 38651 | | const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace); |
| 38660 | const stack_trace_ty = try sema.getBuiltinType(simple_src, .StackTrace); |
| 38652 | 38661 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); |
| 38653 | 38662 | const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern()); |
| 38654 | 38663 | const null_stack_trace = try pt.intern(.{ .opt = .{ |
| ... | ... | @@ -38663,3 +38672,59 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, src: LazySrcLoc, builtin |
| 38663 | 38672 | |
| 38664 | 38673 | return any_changed; |
| 38665 | 38674 | } |
| 38675 | |
| 38676 | /// Given that `decl.kind() == .func`, get the type expected of the function if necessary. |
| 38677 | /// If this will be type checked by `Sema` anyway, this function may return `null`. In |
| 38678 | /// particular, generic functions should return `null`, as `Sema` will necessarily check |
| 38679 | /// them at instantiation time. Returning non-null is necessary only when backends can emit |
| 38680 | /// calls to the function, as is the case with the panic handler. |
| 38681 | fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!?Type { |
| 38682 | const pt = sema.pt; |
| 38683 | return switch (decl) { |
| 38684 | // `fn ([]const u8, ?*StackTrace, ?usize) noreturn` |
| 38685 | .@"Panic.call" => try pt.funcType(.{ |
| 38686 | .param_types = &.{ |
| 38687 | .slice_const_u8_type, |
| 38688 | (try pt.optionalType( |
| 38689 | (try pt.singleMutPtrType( |
| 38690 | try sema.getBuiltinType(src, .StackTrace), |
| 38691 | )).toIntern(), |
| 38692 | )).toIntern(), |
| 38693 | (try pt.optionalType(.usize_type)).toIntern(), |
| 38694 | }, |
| 38695 | .return_type = .noreturn_type, |
| 38696 | }), |
| 38697 | |
| 38698 | // `fn (?*StackTrace, anyerror) noreturn` |
| 38699 | .@"Panic.unwrapError" => try pt.funcType(.{ |
| 38700 | .param_types = &.{ |
| 38701 | (try pt.optionalType( |
| 38702 | (try pt.singleMutPtrType( |
| 38703 | try sema.getBuiltinType(src, .StackTrace), |
| 38704 | )).toIntern(), |
| 38705 | )).toIntern(), |
| 38706 | .anyerror_type, |
| 38707 | }, |
| 38708 | .return_type = .noreturn_type, |
| 38709 | }), |
| 38710 | |
| 38711 | // `fn (usize, usize) noreturn` |
| 38712 | .@"Panic.outOfBounds", |
| 38713 | .@"Panic.startGreaterThanEnd", |
| 38714 | => try pt.funcType(.{ |
| 38715 | .param_types = &.{ .usize_type, .usize_type }, |
| 38716 | .return_type = .noreturn_type, |
| 38717 | }), |
| 38718 | |
| 38719 | // Generic functions, so calls are necessarily validated by Sema |
| 38720 | .@"Panic.sentinelMismatch", |
| 38721 | .@"Panic.inactiveUnionField", |
| 38722 | => null, |
| 38723 | |
| 38724 | // Other functions called exclusively by Sema |
| 38725 | .returnError, |
| 38726 | => null, |
| 38727 | |
| 38728 | else => unreachable, |
| 38729 | }; |
| 38730 | } |