test(ir): cover Obj-C protocol pointers in isObjcClassPointer/objcPropertyKind (A6.1 scaffolding review fix)

Codex review of 0012228 noted isObjcClassPointer's contract is
`fcd.runtime == .objc_class or fcd.runtime == .objc_protocol`, but the new tests
only exercised the class case. Test-only fix (no visibility/behavior change —
still exactly the two pub widenings from the parent commit):

- isObjcClassPointer: add a *NSCopying case where NSCopying is a registered
  .objc_protocol foreign class -> true (alongside the .objc_class *NSString case).
- objcPropertyKind: add a *NSCoding protocol-pointer field -> strong default
  assertion, since it uses the same class/protocol object-pointer predicate.

Gate: zig build, zig build test, bash tests/run_examples.sh -> 361/0.
This commit is contained in:
agra
2026-06-03 07:45:10 +03:00
parent 0012228796
commit b5119e8587

View File

@@ -680,6 +680,22 @@ test "lower: isObjcClassPointer recognises pointer-to-foreign-Obj-C-class" {
try lowering.program_index.foreign_class_map.put("NSString", &ns_fcd);
try std.testing.expect(lowering.isObjcClassPointer(ns_ptr));
// *NSCopying where NSCopying is a registered Obj-C *protocol* → also true
// (the predicate accepts .objc_class OR .objc_protocol).
const proto_name = module.types.internString("NSCopying");
const proto_struct = module.types.intern(.{ .@"struct" = .{ .name = proto_name, .fields = &.{} } });
const proto_ptr = module.types.ptrTo(proto_struct);
var proto_fcd = ast.ForeignClassDecl{
.name = "NSCopying",
.foreign_path = "NSCopying",
.runtime = .objc_protocol,
.members = &.{},
.is_foreign = true,
.is_main = false,
};
try lowering.program_index.foreign_class_map.put("NSCopying", &proto_fcd);
try std.testing.expect(lowering.isObjcClassPointer(proto_ptr));
// *Plain where Plain is a non-foreign struct → false.
const plain_name = module.types.internString("Plain");
const plain_struct = module.types.intern(.{ .@"struct" = .{ .name = plain_name, .fields = &.{} } });
@@ -720,6 +736,24 @@ test "lower: objcPropertyKind defaults + explicit ARC modifiers" {
const obj_default = ast.ForeignFieldDecl{ .name = "title", .field_type = obj_ty, .is_property = true };
try std.testing.expect(lowering.objcPropertyKind(obj_default) == .strong);
// Protocol-pointer field → also strong by default (same object-pointer
// predicate accepts .objc_protocol).
const proto_name = module.types.internString("NSCoding");
_ = module.types.intern(.{ .@"struct" = .{ .name = proto_name, .fields = &.{} } });
var proto_fcd = ast.ForeignClassDecl{
.name = "NSCoding",
.foreign_path = "NSCoding",
.runtime = .objc_protocol,
.members = &.{},
.is_foreign = true,
.is_main = false,
};
try lowering.program_index.foreign_class_map.put("NSCoding", &proto_fcd);
const proto_ty = typeKeyword(alloc, "*NSCoding");
defer alloc.destroy(proto_ty);
const proto_default = ast.ForeignFieldDecl{ .name = "coder", .field_type = proto_ty, .is_property = true };
try std.testing.expect(lowering.objcPropertyKind(proto_default) == .strong);
// Explicit modifiers on an object pointer win over the default.
const weak_mods = [_][]const u8{"weak"};
try std.testing.expect(lowering.objcPropertyKind(.{ .name = "delegate", .field_type = obj_ty, .is_property = true, .property_modifiers = &weak_mods }) == .weak);