Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-583] Add clang attribute to import NSUInteger in C/Objective-C APIs as Int (like Foundation) #43200

Open
marcomasser opened this issue Jan 19, 2016 · 7 comments

Comments

@marcomasser
Copy link

marcomasser commented Jan 19, 2016

Previous ID SR-583
Radar None
Original Reporter @marcomasser
Type Improvement
Additional Detail from JIRA
Votes 1
Component/s Compiler
Labels Improvement, ClangImporter
Assignee dmc (JIRA)
Priority Medium

md5: db8884fb8ef5fb1f54938b9fbc305b14

Issue Description:

When C and Objective-C APIs use NSUInteger as parameter types or return types, they get imported to Swift as Int instead of UInt, but only for Apple’s frameworks like Foundation or AppKit.
This is documented behavior and is fine by me, but it would be nice if there were a way to get the same behavior for my C and Objective-C code.

This would improve consistency in the code base. For example, if a Foundation class uses NSUInteger – like NSData does – it would be nice if my Objective-C categories or subclasses could use the same types as the framework class does: that is, NSUInteger in Objective-C and Int in Swift.

This would probably be an attribute on each single parameter/return type of a method/function declaration.
Maybe something similar to NS_ASSUME_NONNULL_BEGIN/END could be added that can be used to bracket parts of a header to import every NSUInteger occurrence as Int. OTOH, this is by far less common of a problem compared to nullable pointers, so maybe it’s not worth it.

I asked about this on the Swift Users mailing list and @lattner responded by writing that it would be reasonable to introduce a clang attribute for that. Here’s the link to the start of the thread:
https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20160111/000848.html

@swift-ci
Copy link
Collaborator

swift-ci commented Sep 5, 2017

Comment by Daniel Martín (JIRA)

I agree this would be a nice addition to have better Swift<->Objective-C APIs. I'll have a look and implement it.

@belkadan
Copy link
Contributor

belkadan commented Sep 5, 2017

We kind of have this (in heavyweight form) via API notes, and within Apple we still have a bug (rdar://problem/20347922) to consider whether we should just do this everywhere in Swift 5 mode. The most helpful thing that could be done there is an investigation of how modern third-party Objective-C projects are using NSUInteger.

See https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170130/031327.html (from Feb 2017) for more information.

@swift-ci
Copy link
Collaborator

swift-ci commented Sep 5, 2017

Comment by Daniel Martín (JIRA)

Interesting. Is there any documentation about how to accomplish this using API notes?

What I can do is, as an experiment, compile a custom version of ClangImporter that considers user and system frameworks the same regarding `NSUInteger`, check that against some mixed-source projects with old CocoaPods dependencies and report conclusions to the mailing list. Would that make sense?

@belkadan
Copy link
Contributor

belkadan commented Sep 5, 2017

We had Apple-internal documentation and I'm maybe 40% of the way through reformatting it and stripping out the pieces that are Apple-internal. (I keep setting it down and not getting back to it.) Meanwhile you can check out our tests. The general idea is to just replace the entire type with 'NSInteger' instead.

I think there's honestly not much to do with Swift in this investigation. It's more "in existing, well-known and/or well-used Objective-C frameworks from the last four years, how are people using NSUInteger?"

@zienag
Copy link

zienag commented Mar 29, 2019

@belkadan, is there any news on this issue? Just spent bunch of time figuring out what's wrong to finally get here 🙁

@belkadan
Copy link
Contributor

belkadan commented Mar 29, 2019

At this point it would be too source-breaking to change the default behavior, but API notes are also well-established by now. You can use the "Type" API note to adjust individual APIs in a framework you own. It's still not a solution for APIs brought in through a bridging header, though.

@zienag
Copy link

zienag commented Mar 29, 2019

Thanks! Looks good, but I didn't found a way to redefine type of method argument. Am I missing something, or it is not supported yet?

Also, main concern is not about behavior, but about non-obviousness of it. Given the fact that now it is really hard to figuring out different things when modules, objc and swift meeting together, good diagnostic message is crucial here. It wold be nice to see not just type conversion error, but also why it happened:

system_header.h:
  @interface SystemClass
  - (void)method:(NSUInteger)arg;
  @end
module.modulemap:
  framework module SystemModule [system] {
    umbrella header "system_header.h" 
  }
code.swift:
  import SystemModule
  let i: UInt = 32
  SystemClass().method(i)

Error:

obj.method(i)  // <- error about type conversion in code.swift
- (void)method:(NSUInteger)arg;  // <- declared here in system_header.h
framework module SystemModule [system] {  // <- imported as Int because of system header tag in module.modulemap

The problem is actually arise when third party headers emitting warnings when imported to swift. With warning as errors enabled, there is no way other than put a [system] tag to modulemap. The tricky part is when another third party swift code is importing it, and produce errors about type conversion. As there is no control over both of them, I can't think of a way other than creating two separate module maps.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants