Skip to content

Tighten NSFileHandle retained NSError annotations#605

Open
danjboyd wants to merge 10 commits into
gnustep:masterfrom
danjboyd:phase-15i-nsfilehandle-nserror-annotations
Open

Tighten NSFileHandle retained NSError annotations#605
danjboyd wants to merge 10 commits into
gnustep:masterfrom
danjboyd:phase-15i-nsfilehandle-nserror-annotations

Conversation

@danjboyd

@danjboyd danjboyd commented May 4, 2026

Copy link
Copy Markdown

Summary

  • Annotate the three NSFileHandle URL factory NSError out-parameters as nullable storage.
  • Keep the change scoped to the retained URL factory family.

Validation

  • scripts/run-phase15i-nsfilehandle-import-shape-audit.sh
  • scripts/run-phase15i-nsfilehandle-nserror-runtime-gate.sh
  • scripts/run-phase15i-nsfilehandle-promotion-validation.sh
  • PATH=/usr/GNUstep/System/Tools:$PATH make check testobj=NSFileHandle/general.m

@danjboyd
danjboyd requested a review from rfm as a code owner May 4, 2026 19:22
dboyd-invitoep and others added 10 commits May 4, 2026 15:55
Add narrow nullability annotations for the first Phase 4B core Foundation tranche without touching collection headers, module maps, or non-core surfaces.

Keep the remaining judgment-call annotations conservative:
- NSString legacy C-string decoding entry points stay nullable where decoding can return nil even though NULL C string inputs still raise.
- NSURL initWithScheme:host:path: stays nullable because it funnels through initWithString:relativeToURL:, which can still fail for constructed non-ASCII URL text.
- NSData bytes and mutableBytes stay nullable because zero-length concrete storage may legitimately expose a NULL backing pointer.
@danjboyd
danjboyd force-pushed the phase-15i-nsfilehandle-nserror-annotations branch from f44b01d to fc37667 Compare May 4, 2026 20:59
@fredkiefer

Copy link
Copy Markdown
Member

Hi @danjboyd
you opened three PR that seem to build on top of each other. It would be easier to review if you stated this in the comments or even better waited for the first to get merged and then provided the second and so on.

@danjboyd

danjboyd commented May 5, 2026

Copy link
Copy Markdown
Author

Thanks, agreed. These three PRs are stacked and intended for review/merge in order:\n\n1. #605 Phase 15I NSFileHandle NSError annotation slice\n2. #606 Phase 15J invalid keyed-unarchive runtime repair\n3. #607 Phase 15J NSKeyedArchiver/NSKeyedUnarchiver NSError annotation slice\n\nI opened them together to keep the current GNUstep Swift validation stack visible, but #606 and #607 can wait until #605 lands if that is easier for review.

@rfm rfm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a long review for this a few days ago, but it seems that it somehow got lost (perhaps I failed to notice an error response when I submitted it).

In short, the basic changes look good, but don't compile on even the limited set of test systems we use on github. It's a key requirement for GNUstep as a framework that it is portable code which makes it easier for developers to write portable code.

In this case it looks like the issue is compiler compatibility, and I think it's because the compatibility macros for nullability are in NSObjCRuntime.h (I don't know why, it probably seemed a good idea at the time). A quick fix would probably be to ensure that all the files which fail to compile import that header. A better fix might be to move those compatibility macros to a more commonly imported header file. Given that GSConfig.h is supposed to encapsulate portability issues found at configure time, perhaps we should put these (and other) portability macros dealing with compiler compatibility in GSConfig.h.in?

@DTW-Thalion

DTW-Thalion commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

As I have been playing with portability between clang and GCC lately, this might help:

The two GCC jobs (Ubuntu x64 GCC, Windows x64 MinGW GCC) fail to compile while the clang jobs pass:

NSData.h:109:4: error: unknown type name 'nonnull'
NSData.h:109:11: error: expected ')' before 'id'

_Nullable, _Nonnull and NS_ASSUME_NONNULL_BEGIN are guarded on __has_feature(nullability) in NSObjCRuntime.h and expand to nothing under gcc, so those annotations build fine. The bare nonnull keyword has no such fallback and gcc's Objective-C front end does not recognise it, so it reads nonnull as a type name. GSObjCRuntime.m includes NSData.h first, so the Additions subproject aborts there.

Three declarations use the bare form:

NSData.h  + (nonnull instancetype) dataWithBytes: ...
NSData.h  - (nonnull instancetype) initWithBytes: ...
NSURL.h   - (nonnull instancetype) init;

NS_ASSUME_NONNULL_BEGIN is already in effect at those points, so an unannotated instancetype return is implicitly nonnull. Dropping the bare nonnull (or spelling it _Nonnull) keeps the annotation on clang and builds on gcc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

5 participants