bind: annotate ObjC types with nullability annotations

This highly improves interop with Swift. It would map all
pointers as implicitly unwrapped optionals, which skip all
null safety checks. Adding `_Nullable` to pointer types
makes swift map them as optionals.

Also constructors are now nullable since it's valid to return nil from
Go code.

Change-Id: If0506bb80f31bf36f11522c16a1e66d77be935f8
GitHub-Last-Rev: bd6c30f7f50ef5ea5797b07073f0a4a70d545025
GitHub-Pull-Request: golang/mobile#26
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/159477
Run-TryBot: Elias Naur <mail@eliasnaur.com>
Reviewed-by: Elias Naur <mail@eliasnaur.com>
diff --git a/bind/genobjc.go b/bind/genobjc.go
index 573dffc..a928989 100644
--- a/bind/genobjc.go
+++ b/bind/genobjc.go
@@ -538,7 +538,7 @@
 func (s *funcSummary) asFunc(g *ObjcGen) string {
 	var params []string
 	for _, p := range s.params {
-		params = append(params, g.objcType(p.typ)+" "+p.name)
+		params = append(params, g.objcParamType(p.typ)+" "+p.name)
 	}
 	skip := 0
 	if s.returnsVal() {
@@ -569,7 +569,7 @@
 		if i != 0 {
 			key = p.name
 		}
-		params = append(params, fmt.Sprintf("%s:(%s)%s", key, g.objcType(p.typ), p.name))
+		params = append(params, fmt.Sprintf("%s:(%s)%s", key, g.objcParamType(p.typ), p.name))
 	}
 	skip = 0
 	if s.returnsVal() {
@@ -592,7 +592,7 @@
 		if i > 0 {
 			key = p.name
 		}
-		params = append(params, fmt.Sprintf("%s:(%s)%s", key, g.objcType(p.typ), p.name))
+		params = append(params, fmt.Sprintf("%s:(%s)%s", key, g.objcParamType(p.typ), p.name))
 	}
 	return strings.Join(params, " ")
 }
@@ -1099,7 +1099,7 @@
 	g.Printf("}\n")
 	g.Printf("@property(strong, readonly) id _ref;\n")
 	g.Printf("\n")
-	g.Printf("- (instancetype)initWithRef:(id)ref;\n")
+	g.Printf("- (nonnull instancetype)initWithRef:(id)ref;\n")
 	cons := g.constructors[obj]
 	if oinf == nil {
 		for _, f := range cons {
@@ -1111,7 +1111,8 @@
 		}
 	}
 	if oinf != nil || len(cons) == 0 {
-		g.Printf("- (instancetype)init;\n")
+		// default constructor won't return nil
+		g.Printf("- (nonnull instancetype)init;\n")
 	}
 
 	// accessors to exported fields.
@@ -1120,7 +1121,7 @@
 			g.Printf("// skipped field %s.%s with unsupported type: %s\n\n", obj.Name(), f.Name(), t)
 			continue
 		}
-		name, typ := f.Name(), g.objcFieldType(f.Type())
+		name, typ := f.Name(), g.objcType(f.Type())
 		g.objcdoc(doc.Member(f.Name()))
 
 		// properties are atomic by default so explicitly say otherwise
@@ -1214,7 +1215,9 @@
 	s := g.funcSummary(obj, f)
 	doc := g.docs[f.Name()]
 	g.objcdoc(doc.Doc())
-	g.Printf("- (instancetype)%s%s;\n", s.initName, s.asInitSignature(g))
+
+	// custom inits can return nil in Go so make them nullable
+	g.Printf("- (nullable instancetype)%s%s;\n", s.initName, s.asInitSignature(g))
 }
 
 func (g *ObjcGen) genInitM(obj *types.TypeName, f *types.Func) {
@@ -1284,16 +1287,24 @@
 	return g.objcType(typ)
 }
 
-func (g *ObjcGen) objcFieldType(t types.Type) string {
-	if isErrorType(t) {
-		return "NSError*"
+func (g *ObjcGen) objcParamType(t types.Type) string {
+
+	switch typ := t.(type) {
+	case *types.Basic:
+		switch typ.Kind() {
+		case types.String, types.UntypedString:
+			return "NSString* _Nullable"
+		}
 	}
+
 	return g.objcType(t)
+
 }
 
 func (g *ObjcGen) objcType(typ types.Type) string {
+
 	if isErrorType(typ) {
-		return "NSError*"
+		return "NSError* _Nullable"
 	}
 
 	switch typ := typ.(type) {
@@ -1325,7 +1336,7 @@
 		case types.Float64, types.UntypedFloat:
 			return "double"
 		case types.String, types.UntypedString:
-			return "NSString*"
+			return "NSString* _Nonnull"
 		default:
 			g.errorf("unsupported type: %s", typ)
 			return "TODO"
@@ -1334,7 +1345,7 @@
 		elem := g.objcType(typ.Elem())
 		// Special case: NSData seems to be a better option for byte slice.
 		if elem == "byte" {
-			return "NSData*"
+			return "NSData* _Nullable"
 		}
 		// TODO(hyangah): support other slice types: NSArray or CFArrayRef.
 		// Investigate the performance implication.
@@ -1342,7 +1353,7 @@
 		return "TODO"
 	case *types.Pointer:
 		if _, ok := typ.Elem().(*types.Named); ok {
-			return g.objcType(typ.Elem()) + "*"
+			return g.objcType(typ.Elem()) + "* _Nullable"
 		}
 		g.errorf("unsupported pointer to type: %s", typ)
 		return "TODO"
@@ -1359,9 +1370,9 @@
 		switch t := typ.Underlying().(type) {
 		case *types.Interface:
 			if makeIfaceSummary(t).implementable {
-				return "id<" + g.namePrefixOf(n.Pkg()) + n.Name() + ">"
+				return "id<" + g.namePrefixOf(n.Pkg()) + n.Name() + "> _Nullable"
 			} else {
-				return g.namePrefixOf(n.Pkg()) + n.Name() + "*"
+				return g.namePrefixOf(n.Pkg()) + n.Name() + "* _Nullable"
 			}
 		case *types.Struct:
 			return g.namePrefixOf(n.Pkg()) + n.Name()
diff --git a/bind/testdata/basictypes.objc.h.golden b/bind/testdata/basictypes.objc.h.golden
index eaffdb2..134bbcf 100644
--- a/bind/testdata/basictypes.objc.h.golden
+++ b/bind/testdata/basictypes.objc.h.golden
@@ -21,11 +21,11 @@
 
 FOUNDATION_EXPORT BOOL BasictypesBool(BOOL p0);
 
-FOUNDATION_EXPORT NSData* BasictypesByteArrays(NSData* x);
+FOUNDATION_EXPORT NSData* _Nullable BasictypesByteArrays(NSData* _Nullable x);
 
-FOUNDATION_EXPORT BOOL BasictypesError(NSError** error);
+FOUNDATION_EXPORT BOOL BasictypesError(NSError* _Nullable* error);
 
-FOUNDATION_EXPORT BOOL BasictypesErrorPair(long* ret0_, NSError** error);
+FOUNDATION_EXPORT BOOL BasictypesErrorPair(long* ret0_, NSError* _Nullable* error);
 
 FOUNDATION_EXPORT void BasictypesInts(int8_t x, int16_t y, int32_t z, int64_t t, long u);
 
diff --git a/bind/testdata/basictypes.objc.m.golden b/bind/testdata/basictypes.objc.m.golden
index 665fcef..9e907ed 100644
--- a/bind/testdata/basictypes.objc.m.golden
+++ b/bind/testdata/basictypes.objc.m.golden
@@ -24,7 +24,7 @@
 	return _ret0_;
 }
 
-NSData* BasictypesByteArrays(NSData* x) {
+NSData* _Nullable BasictypesByteArrays(NSData* _Nullable x) {
 	nbyteslice _x = go_seq_from_objc_bytearray(x, 0);
 	nbyteslice r0 = proxybasictypes__ByteArrays(_x);
 	if (![x isKindOfClass:[NSMutableData class]]) {
@@ -34,7 +34,7 @@
 	return _ret0_;
 }
 
-BOOL BasictypesError(NSError** error) {
+BOOL BasictypesError(NSError* _Nullable* error) {
 	int32_t r0 = proxybasictypes__Error();
 	Universeerror* _error = nil;
 	GoSeqRef* _error_ref = go_seq_from_refnum(r0);
@@ -50,7 +50,7 @@
 	return (_error == nil);
 }
 
-BOOL BasictypesErrorPair(long* ret0_, NSError** error) {
+BOOL BasictypesErrorPair(long* ret0_, NSError* _Nullable* error) {
 	struct proxybasictypes__ErrorPair_return res = proxybasictypes__ErrorPair();
 	long _ret0_ = (long)res.r0;
 	Universeerror* _error = nil;
diff --git a/bind/testdata/doc.objc.h.golden b/bind/testdata/doc.objc.h.golden
index 11d01a7..0754847 100644
--- a/bind/testdata/doc.objc.h.golden
+++ b/bind/testdata/doc.objc.h.golden
@@ -28,8 +28,8 @@
 }
 @property(strong, readonly) id _ref;
 
-- (instancetype)initWithRef:(id)ref;
-- (instancetype)init;
+- (nonnull instancetype)initWithRef:(id)ref;
+- (nonnull instancetype)init;
 @end
 
 /**
@@ -39,27 +39,27 @@
 }
 @property(strong, readonly) id _ref;
 
-- (instancetype)initWithRef:(id)ref;
+- (nonnull instancetype)initWithRef:(id)ref;
 /**
  * NewS is a constructor.
  */
-- (instancetype)init;
+- (nullable instancetype)init;
 /**
  * SF is a field.
  */
-@property (nonatomic) NSString* sf;
+@property (nonatomic) NSString* _Nonnull sf;
 /**
  * Anonymous field.
  */
-@property (nonatomic) DocS2* s2;
+@property (nonatomic) DocS2* _Nullable s2;
 /**
  * Multiple fields.
  */
-@property (nonatomic) NSString* f1;
+@property (nonatomic) NSString* _Nonnull f1;
 /**
  * Multiple fields.
  */
-@property (nonatomic) NSString* f2;
+@property (nonatomic) NSString* _Nonnull f2;
 /**
  * After is another method.
  */
@@ -74,8 +74,8 @@
 }
 @property(strong, readonly) id _ref;
 
-- (instancetype)initWithRef:(id)ref;
-- (instancetype)init;
+- (nonnull instancetype)initWithRef:(id)ref;
+- (nonnull instancetype)init;
 @end
 
 /**
@@ -93,14 +93,14 @@
 /**
  * A specific var.
  */
-+ (NSString*) specific;
-+ (void) setSpecific:(NSString*)v;
++ (NSString* _Nonnull) specific;
++ (void) setSpecific:(NSString* _Nonnull)v;
 
 /**
  * V is a var.
  */
-+ (NSString*) v;
-+ (void) setV:(NSString*)v;
++ (NSString* _Nonnull) v;
++ (void) setV:(NSString* _Nonnull)v;
 
 @end
 
@@ -112,7 +112,7 @@
 /**
  * NewS is a constructor.
  */
-FOUNDATION_EXPORT DocS* DocNewS(void);
+FOUNDATION_EXPORT DocS* _Nullable DocNewS(void);
 
 @class DocI;
 
diff --git a/bind/testdata/doc.objc.m.golden b/bind/testdata/doc.objc.m.golden
index 9d6dd5d..ebb201a 100644
--- a/bind/testdata/doc.objc.m.golden
+++ b/bind/testdata/doc.objc.m.golden
@@ -47,20 +47,20 @@
 	return self;
 }
 
-- (NSString*)sf {
+- (NSString* _Nonnull)sf {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring r0 = proxydoc_S_SF_Get(refnum);
 	NSString *_r0 = go_seq_to_objc_string(r0);
 	return _r0;
 }
 
-- (void)setSF:(NSString*)v {
+- (void)setSF:(NSString* _Nonnull)v {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring _v = go_seq_from_objc_string(v);
 	proxydoc_S_SF_Set(refnum, _v);
 }
 
-- (DocS2*)s2 {
+- (DocS2* _Nullable)s2 {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	int32_t r0 = proxydoc_S_S2_Get(refnum);
 	DocS2* _r0 = nil;
@@ -74,7 +74,7 @@
 	return _r0;
 }
 
-- (void)setS2:(DocS2*)v {
+- (void)setS2:(DocS2* _Nullable)v {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	int32_t _v;
 	if ([v conformsToProtocol:@protocol(goSeqRefInterface)]) {
@@ -86,27 +86,27 @@
 	proxydoc_S_S2_Set(refnum, _v);
 }
 
-- (NSString*)f1 {
+- (NSString* _Nonnull)f1 {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring r0 = proxydoc_S_F1_Get(refnum);
 	NSString *_r0 = go_seq_to_objc_string(r0);
 	return _r0;
 }
 
-- (void)setF1:(NSString*)v {
+- (void)setF1:(NSString* _Nonnull)v {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring _v = go_seq_from_objc_string(v);
 	proxydoc_S_F1_Set(refnum, _v);
 }
 
-- (NSString*)f2 {
+- (NSString* _Nonnull)f2 {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring r0 = proxydoc_S_F2_Get(refnum);
 	NSString *_r0 = go_seq_to_objc_string(r0);
 	return _r0;
 }
 
-- (void)setF2:(NSString*)v {
+- (void)setF2:(NSString* _Nonnull)v {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring _v = go_seq_from_objc_string(v);
 	proxydoc_S_F2_Set(refnum, _v);
@@ -177,23 +177,23 @@
 	return _r0;
 }
 
-+ (void) setSpecific:(NSString*)v {
++ (void) setSpecific:(NSString* _Nonnull)v {
 	nstring _v = go_seq_from_objc_string(v);
 	var_setdoc_Specific(_v);
 }
 
-+ (NSString*) specific {
++ (NSString* _Nonnull) specific {
 	nstring r0 = var_getdoc_Specific();
 	NSString *_r0 = go_seq_to_objc_string(r0);
 	return _r0;
 }
 
-+ (void) setV:(NSString*)v {
++ (void) setV:(NSString* _Nonnull)v {
 	nstring _v = go_seq_from_objc_string(v);
 	var_setdoc_V(_v);
 }
 
-+ (NSString*) v {
++ (NSString* _Nonnull) v {
 	nstring r0 = var_getdoc_V();
 	NSString *_r0 = go_seq_to_objc_string(r0);
 	return _r0;
@@ -206,7 +206,7 @@
 	proxydoc__F();
 }
 
-DocS* DocNewS(void) {
+DocS* _Nullable DocNewS(void) {
 	int32_t r0 = proxydoc__NewS();
 	DocS* _ret0_ = nil;
 	GoSeqRef* _ret0__ref = go_seq_from_refnum(r0);
diff --git a/bind/testdata/ignore.objc.h.golden b/bind/testdata/ignore.objc.h.golden
index 98df76c..b4b23d7 100644
--- a/bind/testdata/ignore.objc.h.golden
+++ b/bind/testdata/ignore.objc.h.golden
@@ -26,8 +26,8 @@
 }
 @property(strong, readonly) id _ref;
 
-- (instancetype)initWithRef:(id)ref;
-- (instancetype)init;
+- (nonnull instancetype)initWithRef:(id)ref;
+- (nonnull instancetype)init;
 // skipped field S.F with unsupported type: interface{}
 
 // skipped method S.Argument with unsupported parameter or return types
diff --git a/bind/testdata/interfaces.objc.h.golden b/bind/testdata/interfaces.objc.h.golden
index f78b482..a25f498 100644
--- a/bind/testdata/interfaces.objc.h.golden
+++ b/bind/testdata/interfaces.objc.h.golden
@@ -29,7 +29,7 @@
 @class InterfacesWithParam;
 
 @protocol InterfacesError <NSObject>
-- (BOOL)err:(NSError**)error;
+- (BOOL)err:(NSError* _Nullable*)error;
 @end
 
 @protocol InterfacesI <NSObject>
@@ -59,7 +59,7 @@
 @end
 
 @protocol InterfacesI3 <NSObject>
-- (InterfacesI1*)f;
+- (InterfacesI1* _Nullable)f;
 @end
 
 @protocol InterfacesInterfaces <NSObject>
@@ -79,11 +79,11 @@
 - (void)hasParam:(BOOL)p0;
 @end
 
-FOUNDATION_EXPORT int32_t InterfacesAdd3(id<InterfacesI> r);
+FOUNDATION_EXPORT int32_t InterfacesAdd3(id<InterfacesI> _Nullable r);
 
-FOUNDATION_EXPORT BOOL InterfacesCallErr(id<InterfacesError> e, NSError** error);
+FOUNDATION_EXPORT BOOL InterfacesCallErr(id<InterfacesError> _Nullable e, NSError* _Nullable* error);
 
-FOUNDATION_EXPORT id<InterfacesI> InterfacesSeven(void);
+FOUNDATION_EXPORT id<InterfacesI> _Nullable InterfacesSeven(void);
 
 @class InterfacesError;
 
@@ -104,7 +104,7 @@
 @property(strong, readonly) id _ref;
 
 - (instancetype)initWithRef:(id)ref;
-- (BOOL)err:(NSError**)error;
+- (BOOL)err:(NSError* _Nullable*)error;
 @end
 
 @interface InterfacesI : NSObject <goSeqRefInterface, InterfacesI> {
@@ -124,7 +124,7 @@
 @property(strong, readonly) id _ref;
 
 - (instancetype)initWithRef:(id)ref;
-- (InterfacesI1*)f;
+- (InterfacesI1* _Nullable)f;
 @end
 
 /**
diff --git a/bind/testdata/interfaces.objc.m.golden b/bind/testdata/interfaces.objc.m.golden
index 54383df..da83529 100644
--- a/bind/testdata/interfaces.objc.m.golden
+++ b/bind/testdata/interfaces.objc.m.golden
@@ -17,7 +17,7 @@
 	return self;
 }
 
-- (BOOL)err:(NSError**)error {
+- (BOOL)err:(NSError* _Nullable*)error {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	int32_t r0 = proxyinterfaces_Error_Err(refnum);
 	Universeerror* _error = nil;
@@ -99,7 +99,7 @@
 	return self;
 }
 
-- (InterfacesI1*)f {
+- (InterfacesI1* _Nullable)f {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	int32_t r0 = proxyinterfaces_I3_F(refnum);
 	InterfacesI1* _ret0_ = nil;
@@ -195,7 +195,7 @@
 
 
 
-int32_t InterfacesAdd3(id<InterfacesI> r) {
+int32_t InterfacesAdd3(id<InterfacesI> _Nullable r) {
 	int32_t _r;
 	if ([r conformsToProtocol:@protocol(goSeqRefInterface)]) {
 		id<goSeqRefInterface> r_proxy = (id<goSeqRefInterface>)(r);
@@ -208,7 +208,7 @@
 	return _ret0_;
 }
 
-BOOL InterfacesCallErr(id<InterfacesError> e, NSError** error) {
+BOOL InterfacesCallErr(id<InterfacesError> _Nullable e, NSError* _Nullable* error) {
 	int32_t _e;
 	if ([e conformsToProtocol:@protocol(goSeqRefInterface)]) {
 		id<goSeqRefInterface> e_proxy = (id<goSeqRefInterface>)(e);
@@ -231,7 +231,7 @@
 	return (_error == nil);
 }
 
-id<InterfacesI> InterfacesSeven(void) {
+id<InterfacesI> _Nullable InterfacesSeven(void) {
 	int32_t r0 = proxyinterfaces__Seven();
 	InterfacesI* _ret0_ = nil;
 	GoSeqRef* _ret0__ref = go_seq_from_refnum(r0);
@@ -291,7 +291,7 @@
 int32_t cproxyinterfaces_I3_F(int32_t refnum) {
 	@autoreleasepool {
 		InterfacesI3* o = go_seq_objc_from_refnum(refnum);
-		InterfacesI1* ret0_;
+		InterfacesI1* _Nullable ret0_;
 		ret0_ = [o f];
 		int32_t _ret0_;
 		if ([ret0_ conformsToProtocol:@protocol(goSeqRefInterface)]) {
diff --git a/bind/testdata/issue10788.objc.h.golden b/bind/testdata/issue10788.objc.h.golden
index 751e5d9..fed5085 100644
--- a/bind/testdata/issue10788.objc.h.golden
+++ b/bind/testdata/issue10788.objc.h.golden
@@ -16,17 +16,17 @@
 @class Issue10788TestInterface;
 
 @protocol Issue10788TestInterface <NSObject>
-- (void)doSomeWork:(Issue10788TestStruct*)s;
-- (void)multipleUnnamedParams:(long)p0 p1:(NSString*)p1 日本:(int64_t)日本;
+- (void)doSomeWork:(Issue10788TestStruct* _Nullable)s;
+- (void)multipleUnnamedParams:(long)p0 p1:(NSString* _Nullable)p1 日本:(int64_t)日本;
 @end
 
 @interface Issue10788TestStruct : NSObject <goSeqRefInterface> {
 }
 @property(strong, readonly) id _ref;
 
-- (instancetype)initWithRef:(id)ref;
-- (instancetype)init;
-@property (nonatomic) NSString* value;
+- (nonnull instancetype)initWithRef:(id)ref;
+- (nonnull instancetype)init;
+@property (nonatomic) NSString* _Nonnull value;
 @end
 
 @class Issue10788TestInterface;
@@ -36,8 +36,8 @@
 @property(strong, readonly) id _ref;
 
 - (instancetype)initWithRef:(id)ref;
-- (void)doSomeWork:(Issue10788TestStruct*)s;
-- (void)multipleUnnamedParams:(long)p0 p1:(NSString*)p1 日本:(int64_t)日本;
+- (void)doSomeWork:(Issue10788TestStruct* _Nullable)s;
+- (void)multipleUnnamedParams:(long)p0 p1:(NSString* _Nullable)p1 日本:(int64_t)日本;
 @end
 
 #endif
diff --git a/bind/testdata/issue10788.objc.m.golden b/bind/testdata/issue10788.objc.m.golden
index e8f6ba3..c218e33 100644
--- a/bind/testdata/issue10788.objc.m.golden
+++ b/bind/testdata/issue10788.objc.m.golden
@@ -26,14 +26,14 @@
 	return self;
 }
 
-- (NSString*)value {
+- (NSString* _Nonnull)value {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring r0 = proxyissue10788_TestStruct_Value_Get(refnum);
 	NSString *_r0 = go_seq_to_objc_string(r0);
 	return _r0;
 }
 
-- (void)setValue:(NSString*)v {
+- (void)setValue:(NSString* _Nonnull)v {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring _v = go_seq_from_objc_string(v);
 	proxyissue10788_TestStruct_Value_Set(refnum, _v);
@@ -51,7 +51,7 @@
 	return self;
 }
 
-- (void)doSomeWork:(Issue10788TestStruct*)s {
+- (void)doSomeWork:(Issue10788TestStruct* _Nullable)s {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	int32_t _s;
 	if ([s conformsToProtocol:@protocol(goSeqRefInterface)]) {
@@ -63,7 +63,7 @@
 	proxyissue10788_TestInterface_DoSomeWork(refnum, _s);
 }
 
-- (void)multipleUnnamedParams:(long)p0 p1:(NSString*)p1 日本:(int64_t)日本 {
+- (void)multipleUnnamedParams:(long)p0 p1:(NSString* _Nullable)p1 日本:(int64_t)日本 {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nint _p0 = (nint)p0;
 	nstring _p1 = go_seq_from_objc_string(p1);
diff --git a/bind/testdata/issue12328.objc.h.golden b/bind/testdata/issue12328.objc.h.golden
index cf77c41..3fb9333 100644
--- a/bind/testdata/issue12328.objc.h.golden
+++ b/bind/testdata/issue12328.objc.h.golden
@@ -17,9 +17,9 @@
 }
 @property(strong, readonly) id _ref;
 
-- (instancetype)initWithRef:(id)ref;
-- (instancetype)init;
-@property (nonatomic) NSError* err;
+- (nonnull instancetype)initWithRef:(id)ref;
+- (nonnull instancetype)init;
+@property (nonatomic) NSError* _Nullable err;
 @end
 
 #endif
diff --git a/bind/testdata/issue12328.objc.m.golden b/bind/testdata/issue12328.objc.m.golden
index e46f6ac..6f2c9b7 100644
--- a/bind/testdata/issue12328.objc.m.golden
+++ b/bind/testdata/issue12328.objc.m.golden
@@ -26,7 +26,7 @@
 	return self;
 }
 
-- (NSError*)err {
+- (NSError* _Nullable)err {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	int32_t r0 = proxyissue12328_T_Err_Get(refnum);
 	Universeerror* _r0 = nil;
@@ -40,7 +40,7 @@
 	return _r0;
 }
 
-- (void)setErr:(NSError*)v {
+- (void)setErr:(NSError* _Nullable)v {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	int32_t _v;
 	if ([v conformsToProtocol:@protocol(goSeqRefInterface)]) {
diff --git a/bind/testdata/issue12403.objc.h.golden b/bind/testdata/issue12403.objc.h.golden
index b617237..bfc6d04 100644
--- a/bind/testdata/issue12403.objc.h.golden
+++ b/bind/testdata/issue12403.objc.h.golden
@@ -15,8 +15,8 @@
 @class Issue12403Parsable;
 
 @protocol Issue12403Parsable <NSObject>
-- (NSString*)fromJSON:(NSString*)jstr;
-- (NSString*)toJSON:(NSError**)error;
+- (NSString* _Nonnull)fromJSON:(NSString* _Nullable)jstr;
+- (NSString* _Nonnull)toJSON:(NSError* _Nullable*)error;
 @end
 
 @class Issue12403Parsable;
@@ -26,8 +26,8 @@
 @property(strong, readonly) id _ref;
 
 - (instancetype)initWithRef:(id)ref;
-- (NSString*)fromJSON:(NSString*)jstr;
-- (NSString*)toJSON:(NSError**)error;
+- (NSString* _Nonnull)fromJSON:(NSString* _Nullable)jstr;
+- (NSString* _Nonnull)toJSON:(NSError* _Nullable*)error;
 @end
 
 #endif
diff --git a/bind/testdata/issue12403.objc.m.golden b/bind/testdata/issue12403.objc.m.golden
index 4b732f1..8d62c88 100644
--- a/bind/testdata/issue12403.objc.m.golden
+++ b/bind/testdata/issue12403.objc.m.golden
@@ -17,7 +17,7 @@
 	return self;
 }
 
-- (NSString*)fromJSON:(NSString*)jstr {
+- (NSString* _Nonnull)fromJSON:(NSString* _Nullable)jstr {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring _jstr = go_seq_from_objc_string(jstr);
 	nstring r0 = proxyissue12403_Parsable_FromJSON(refnum, _jstr);
@@ -25,7 +25,7 @@
 	return _ret0_;
 }
 
-- (NSString*)toJSON:(NSError**)error {
+- (NSString* _Nonnull)toJSON:(NSError* _Nullable*)error {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	struct proxyissue12403_Parsable_ToJSON_return res = proxyissue12403_Parsable_ToJSON(refnum);
 	NSString *_ret0_ = go_seq_to_objc_string(res.r0);
@@ -54,7 +54,7 @@
 	@autoreleasepool {
 		Issue12403Parsable* o = go_seq_objc_from_refnum(refnum);
 		NSString *_jstr = go_seq_to_objc_string(jstr);
-		NSString* ret0_;
+		NSString* _Nonnull ret0_;
 		ret0_ = [o fromJSON:_jstr];
 		nstring _ret0_ = go_seq_from_objc_string(ret0_);
 		return _ret0_;
@@ -64,7 +64,7 @@
 struct cproxyissue12403_Parsable_ToJSON_return cproxyissue12403_Parsable_ToJSON(int32_t refnum) {
 	@autoreleasepool {
 		Issue12403Parsable* o = go_seq_objc_from_refnum(refnum);
-		NSString* ret0_;
+		NSString* _Nonnull ret0_;
 		NSError* error = nil;
 		ret0_ = [o toJSON:&error];
 		nstring _ret0_ = go_seq_from_objc_string(ret0_);
diff --git a/bind/testdata/issue29559.objc.h.golden b/bind/testdata/issue29559.objc.h.golden
index 0ce3cf8..6638e14 100644
--- a/bind/testdata/issue29559.objc.h.golden
+++ b/bind/testdata/issue29559.objc.h.golden
@@ -11,6 +11,6 @@
 #include "Universe.objc.h"
 
 
-FOUNDATION_EXPORT void Issue29559TakesAString(NSString* s);
+FOUNDATION_EXPORT void Issue29559TakesAString(NSString* _Nullable s);
 
 #endif
diff --git a/bind/testdata/issue29559.objc.m.golden b/bind/testdata/issue29559.objc.m.golden
index c01628c..83a9b8d 100644
--- a/bind/testdata/issue29559.objc.m.golden
+++ b/bind/testdata/issue29559.objc.m.golden
@@ -9,7 +9,7 @@
 #include "Issue29559.objc.h"
 
 
-void Issue29559TakesAString(NSString* s) {
+void Issue29559TakesAString(NSString* _Nullable s) {
 	nstring _s = go_seq_from_objc_string(s);
 	proxyissue29559__TakesAString(_s);
 }
diff --git a/bind/testdata/keywords.objc.h.golden b/bind/testdata/keywords.objc.h.golden
index 8ebd53d..4fa7864 100644
--- a/bind/testdata/keywords.objc.h.golden
+++ b/bind/testdata/keywords.objc.h.golden
@@ -72,9 +72,9 @@
 - (void)while;
 @end
 
-FOUNDATION_EXPORT void KeywordsConst(NSString* id_);
+FOUNDATION_EXPORT void KeywordsConst(NSString* _Nullable id_);
 
-FOUNDATION_EXPORT void KeywordsStatic(NSString* strictfp);
+FOUNDATION_EXPORT void KeywordsStatic(NSString* _Nullable strictfp);
 
 @class KeywordsKeywordCaller;
 
diff --git a/bind/testdata/keywords.objc.m.golden b/bind/testdata/keywords.objc.m.golden
index 1ccbdb3..21dbdb1 100644
--- a/bind/testdata/keywords.objc.m.golden
+++ b/bind/testdata/keywords.objc.m.golden
@@ -296,12 +296,12 @@
 
 
 
-void KeywordsConst(NSString* id_) {
+void KeywordsConst(NSString* _Nullable id_) {
 	nstring _id_ = go_seq_from_objc_string(id_);
 	proxykeywords__Const(_id_);
 }
 
-void KeywordsStatic(NSString* strictfp) {
+void KeywordsStatic(NSString* _Nullable strictfp) {
 	nstring _strictfp = go_seq_from_objc_string(strictfp);
 	proxykeywords__Static(_strictfp);
 }
diff --git a/bind/testdata/structs.objc.h.golden b/bind/testdata/structs.objc.h.golden
index f53802c..244cfd3 100644
--- a/bind/testdata/structs.objc.h.golden
+++ b/bind/testdata/structs.objc.h.golden
@@ -25,11 +25,11 @@
 }
 @property(strong, readonly) id _ref;
 
-- (instancetype)initWithRef:(id)ref;
-- (instancetype)init;
+- (nonnull instancetype)initWithRef:(id)ref;
+- (nonnull instancetype)init;
 @property (nonatomic) double x;
 @property (nonatomic) double y;
-- (StructsS*)identity:(NSError**)error;
+- (StructsS* _Nullable)identity:(NSError* _Nullable*)error;
 - (double)sum;
 @end
 
@@ -37,10 +37,10 @@
 }
 @property(strong, readonly) id _ref;
 
-- (instancetype)initWithRef:(id)ref;
-- (instancetype)init;
+- (nonnull instancetype)initWithRef:(id)ref;
+- (nonnull instancetype)init;
 - (void)m;
-- (NSString*)string;
+- (NSString* _Nonnull)string;
 @end
 
 /**
@@ -50,14 +50,14 @@
 }
 @property(strong, readonly) id _ref;
 
-- (instancetype)initWithRef:(id)ref;
-- (instancetype)init;
+- (nonnull instancetype)initWithRef:(id)ref;
+- (nonnull instancetype)init;
 - (void)m;
 @end
 
-FOUNDATION_EXPORT StructsS* StructsIdentity(StructsS* s);
+FOUNDATION_EXPORT StructsS* _Nullable StructsIdentity(StructsS* _Nullable s);
 
-FOUNDATION_EXPORT StructsS* StructsIdentityWithError(StructsS* s, NSError** error);
+FOUNDATION_EXPORT StructsS* _Nullable StructsIdentityWithError(StructsS* _Nullable s, NSError* _Nullable* error);
 
 @class StructsI;
 
diff --git a/bind/testdata/structs.objc.m.golden b/bind/testdata/structs.objc.m.golden
index 87b1da8..dec7196 100644
--- a/bind/testdata/structs.objc.m.golden
+++ b/bind/testdata/structs.objc.m.golden
@@ -52,7 +52,7 @@
 	proxystructs_S_Y_Set(refnum, _v);
 }
 
-- (StructsS*)identity:(NSError**)error {
+- (StructsS* _Nullable)identity:(NSError* _Nullable*)error {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	struct proxystructs_S_Identity_return res = proxystructs_S_Identity(refnum);
 	StructsS* _ret0_ = nil;
@@ -113,7 +113,7 @@
 	proxystructs_S2_M(refnum);
 }
 
-- (NSString*)string {
+- (NSString* _Nonnull)string {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring r0 = proxystructs_S2_String(refnum);
 	NSString *_ret0_ = go_seq_to_objc_string(r0);
@@ -167,7 +167,7 @@
 
 
 
-StructsS* StructsIdentity(StructsS* s) {
+StructsS* _Nullable StructsIdentity(StructsS* _Nullable s) {
 	int32_t _s;
 	if ([s conformsToProtocol:@protocol(goSeqRefInterface)]) {
 		id<goSeqRefInterface> s_proxy = (id<goSeqRefInterface>)(s);
@@ -187,7 +187,7 @@
 	return _ret0_;
 }
 
-StructsS* StructsIdentityWithError(StructsS* s, NSError** error) {
+StructsS* _Nullable StructsIdentityWithError(StructsS* _Nullable s, NSError* _Nullable* error) {
 	int32_t _s;
 	if ([s conformsToProtocol:@protocol(goSeqRefInterface)]) {
 		id<goSeqRefInterface> s_proxy = (id<goSeqRefInterface>)(s);
diff --git a/bind/testdata/try.objc.h.golden b/bind/testdata/try.objc.h.golden
index 7045c6b..f72f7cc 100644
--- a/bind/testdata/try.objc.h.golden
+++ b/bind/testdata/try.objc.h.golden
@@ -11,6 +11,6 @@
 #include "Universe.objc.h"
 
 
-FOUNDATION_EXPORT NSString* TryThis(void);
+FOUNDATION_EXPORT NSString* _Nonnull TryThis(void);
 
 #endif
diff --git a/bind/testdata/try.objc.m.golden b/bind/testdata/try.objc.m.golden
index 8c6d281..a8d6392 100644
--- a/bind/testdata/try.objc.m.golden
+++ b/bind/testdata/try.objc.m.golden
@@ -9,7 +9,7 @@
 #include "Try.objc.h"
 
 
-NSString* TryThis(void) {
+NSString* _Nonnull TryThis(void) {
 	nstring r0 = proxytry__This();
 	NSString *_ret0_ = go_seq_to_objc_string(r0);
 	return _ret0_;
diff --git a/bind/testdata/underscores.objc.h.golden b/bind/testdata/underscores.objc.h.golden
index 302b30f..56e922b 100644
--- a/bind/testdata/underscores.objc.h.golden
+++ b/bind/testdata/underscores.objc.h.golden
@@ -17,9 +17,9 @@
 }
 @property(strong, readonly) id _ref;
 
-- (instancetype)initWithRef:(id)ref;
-- (instancetype)init;
-@property (nonatomic) NSString* underscore_field;
+- (nonnull instancetype)initWithRef:(id)ref;
+- (nonnull instancetype)init;
+@property (nonatomic) NSString* _Nonnull underscore_field;
 @end
 
 @interface Underscore_pkg : NSObject
diff --git a/bind/testdata/underscores.objc.m.golden b/bind/testdata/underscores.objc.m.golden
index 4cac5a5..116b28b 100644
--- a/bind/testdata/underscores.objc.m.golden
+++ b/bind/testdata/underscores.objc.m.golden
@@ -26,14 +26,14 @@
 	return self;
 }
 
-- (NSString*)underscore_field {
+- (NSString* _Nonnull)underscore_field {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring r0 = proxyunderscore_pkg_Underscore_struct_Underscore_field_Get(refnum);
 	NSString *_r0 = go_seq_to_objc_string(r0);
 	return _r0;
 }
 
-- (void)setUnderscore_field:(NSString*)v {
+- (void)setUnderscore_field:(NSString* _Nonnull)v {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring _v = go_seq_from_objc_string(v);
 	proxyunderscore_pkg_Underscore_struct_Underscore_field_Set(refnum, _v);
diff --git a/bind/testdata/universe.objc.h.golden b/bind/testdata/universe.objc.h.golden
index ce2b08c..d0ee3dc 100644
--- a/bind/testdata/universe.objc.h.golden
+++ b/bind/testdata/universe.objc.h.golden
@@ -13,7 +13,7 @@
 @class Universeerror;
 
 @protocol Universeerror <NSObject>
-- (NSString*)error;
+- (NSString* _Nonnull)error;
 @end
 
 @class Universeerror;
@@ -23,7 +23,7 @@
 @property(strong, readonly) id _ref;
 
 - (instancetype)initWithRef:(id)ref;
-- (NSString*)error;
+- (NSString* _Nonnull)error;
 @end
 
 #endif
diff --git a/bind/testdata/universe.objc.m.golden b/bind/testdata/universe.objc.m.golden
index 4e42757..0bfa3a2 100644
--- a/bind/testdata/universe.objc.m.golden
+++ b/bind/testdata/universe.objc.m.golden
@@ -19,7 +19,7 @@
 	return self;
 }
 
-- (NSString*)error {
+- (NSString* _Nonnull)error {
 	int32_t refnum = go_seq_go_to_refnum(self._ref);
 	nstring r0 = proxy_error_Error(refnum);
 	NSString *_ret0_ = go_seq_to_objc_string(r0);
@@ -33,7 +33,7 @@
 nstring cproxy_error_Error(int32_t refnum) {
 	@autoreleasepool {
 		Universeerror* o = go_seq_objc_from_refnum(refnum);
-		NSString* ret0_;
+		NSString* _Nonnull ret0_;
 		ret0_ = [o localizedDescription];
 		nstring _ret0_ = go_seq_from_objc_string(ret0_);
 		return _ret0_;
diff --git a/bind/testdata/vars.objc.h.golden b/bind/testdata/vars.objc.h.golden
index d5964a8..d1586de 100644
--- a/bind/testdata/vars.objc.h.golden
+++ b/bind/testdata/vars.objc.h.golden
@@ -22,8 +22,8 @@
 }
 @property(strong, readonly) id _ref;
 
-- (instancetype)initWithRef:(id)ref;
-- (instancetype)init;
+- (nonnull instancetype)initWithRef:(id)ref;
+- (nonnull instancetype)init;
 @end
 
 @interface Vars : NSObject
@@ -39,11 +39,11 @@
 + (double) aFloat64;
 + (void) setAFloat64:(double)v;
 
-+ (NSString*) aString;
-+ (void) setAString:(NSString*)v;
++ (NSString* _Nonnull) aString;
++ (void) setAString:(NSString* _Nonnull)v;
 
-+ (VarsS*) aStructPtr;
-+ (void) setAStructPtr:(VarsS*)v;
++ (VarsS* _Nullable) aStructPtr;
++ (void) setAStructPtr:(VarsS* _Nullable)v;
 
 + (long) anInt;
 + (void) setAnInt:(long)v;
@@ -60,8 +60,8 @@
 + (int8_t) anInt8;
 + (void) setAnInt8:(int8_t)v;
 
-+ (id<VarsI>) anInterface;
-+ (void) setAnInterface:(id<VarsI>)v;
++ (id<VarsI> _Nullable) anInterface;
++ (void) setAnInterface:(id<VarsI> _Nullable)v;
 
 @end
 
diff --git a/bind/testdata/vars.objc.m.golden b/bind/testdata/vars.objc.m.golden
index 6e5cb3c..9bc4f98 100644
--- a/bind/testdata/vars.objc.m.golden
+++ b/bind/testdata/vars.objc.m.golden
@@ -86,18 +86,18 @@
 	return _r0;
 }
 
-+ (void) setAString:(NSString*)v {
++ (void) setAString:(NSString* _Nonnull)v {
 	nstring _v = go_seq_from_objc_string(v);
 	var_setvars_AString(_v);
 }
 
-+ (NSString*) aString {
++ (NSString* _Nonnull) aString {
 	nstring r0 = var_getvars_AString();
 	NSString *_r0 = go_seq_to_objc_string(r0);
 	return _r0;
 }
 
-+ (void) setAStructPtr:(VarsS*)v {
++ (void) setAStructPtr:(VarsS* _Nullable)v {
 	int32_t _v;
 	if ([v conformsToProtocol:@protocol(goSeqRefInterface)]) {
 		id<goSeqRefInterface> v_proxy = (id<goSeqRefInterface>)(v);
@@ -108,7 +108,7 @@
 	var_setvars_AStructPtr(_v);
 }
 
-+ (VarsS*) aStructPtr {
++ (VarsS* _Nullable) aStructPtr {
 	int32_t r0 = var_getvars_AStructPtr();
 	VarsS* _r0 = nil;
 	GoSeqRef* _r0_ref = go_seq_from_refnum(r0);
@@ -176,7 +176,7 @@
 	return _r0;
 }
 
-+ (void) setAnInterface:(id<VarsI>)v {
++ (void) setAnInterface:(id<VarsI> _Nullable)v {
 	int32_t _v;
 	if ([v conformsToProtocol:@protocol(goSeqRefInterface)]) {
 		id<goSeqRefInterface> v_proxy = (id<goSeqRefInterface>)(v);
@@ -187,7 +187,7 @@
 	var_setvars_AnInterface(_v);
 }
 
-+ (id<VarsI>) anInterface {
++ (id<VarsI> _Nullable) anInterface {
 	int32_t r0 = var_getvars_AnInterface();
 	VarsI* _r0 = nil;
 	GoSeqRef* _r0_ref = go_seq_from_refnum(r0);