| ... | @@ -38590,7 +38590,7 @@ pub fn resolveNavPtrModifiers( | ... | @@ -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 | const pt = sema.pt; | 38594 | const pt = sema.pt; |
| 38595 | const zcu = pt.zcu; | 38595 | const zcu = pt.zcu; |
| 38596 | const ip = &zcu.intern_pool; | 38596 | const ip = &zcu.intern_pool; |
| ... | @@ -38605,38 +38605,47 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, src: LazySrcLoc, builtin | ... | @@ -38605,38 +38605,47 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, src: LazySrcLoc, builtin |
| 38605 | .nested => |nested| access: { | 38605 | .nested => |nested| access: { |
| 38606 | const parent_ty: Type = .fromInterned(zcu.builtin_decl_values.get(nested[0])); | 38606 | const parent_ty: Type = .fromInterned(zcu.builtin_decl_values.get(nested[0])); |
| 38607 | const parent_ns = parent_ty.getNamespace(zcu).unwrap() orelse { | 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 | break :access .{ parent_ns, "std.builtin." ++ @tagName(nested[0]), nested[1] }; | 38610 | break :access .{ parent_ns, "std.builtin." ++ @tagName(nested[0]), nested[1] }; |
| 38611 | }, | 38611 | }, |
| 38612 | }; | 38612 | }; |
| 38613 | | 38613 | |
| 38614 | const name_nts = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls); | 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 | 38615 | const nav = try sema.namespaceLookup(block, simple_src, parent_ns, name_nts) orelse |
| 38616 | return sema.fail(block, src, "{s} missing {s}", .{ parent_name, name }); | 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()) { | 38623 | const result = try sema.analyzeNavVal(block, src, nav); |
| 38621 | .type => if (val.typeOf(zcu).zigTypeTag(zcu) != .type) { | 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 | return sema.fail(block, src, "{s}.{s} is not a type", .{ parent_name, name }); | 38628 | return sema.fail(block, src, "{s}.{s} is not a type", .{ parent_name, name }); |
| 38623 | } else { | 38629 | } else val: { |
| 38624 | try val.toType().resolveFully(pt); | 38630 | try uncoerced_val.toType().resolveFully(pt); |
| | 38631 | break :val uncoerced_val; |
| 38625 | }, | 38632 | }, |
| 38626 | .func => if (val.typeOf(zcu).zigTypeTag(zcu) != .@"fn") { | 38633 | .func => val: { |
| 38627 | return sema.fail(block, src, "{s}.{s} is not a function", .{ parent_name, name }); | 38634 | if (try sema.getExpectedBuiltinFnType(src, builtin_decl)) |func_ty| { |
| 38628 | }, | 38635 | const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src); |
| 38629 | .string => { | 38636 | break :val .fromInterned(coerced.toInterned().?); |
| 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 }); | | |
| 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 | const prev = zcu.builtin_decl_values.get(builtin_decl); | 38650 | const prev = zcu.builtin_decl_values.get(builtin_decl); |
| 38642 | if (val.toIntern() != prev) { | 38651 | if (val.toIntern() != prev) { |
| ... | @@ -38648,7 +38657,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, src: LazySrcLoc, builtin | ... | @@ -38648,7 +38657,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, src: LazySrcLoc, builtin |
| 38648 | | 38657 | |
| 38649 | if (stage == .panic) { | 38658 | if (stage == .panic) { |
| 38650 | // We use `getBuiltinType` because this is from an earlier stage. | 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 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); | 38661 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); |
| 38653 | const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern()); | 38662 | const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern()); |
| 38654 | const null_stack_trace = try pt.intern(.{ .opt = .{ | 38663 | const null_stack_trace = try pt.intern(.{ .opt = .{ |
| ... | @@ -38663,3 +38672,59 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, src: LazySrcLoc, builtin | ... | @@ -38663,3 +38672,59 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, src: LazySrcLoc, builtin |
| 38663 | | 38672 | |
| 38664 | return any_changed; | 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 | } |