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

Update to Xcode 16 #629

Merged
merged 6 commits into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ jobs:
- lint

env:
DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer
DEVELOPER_DIR: /Applications/Xcode_16.0.app/Contents/Developer

steps:
- uses: actions/checkout@v4
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion crates/header-translator/src/availability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ impl Availability {
if let Some(m) = availability.message {
if let Some(message) = message.as_deref() {
if m != message {
error!(m, message, "message availability attributes were not equal");
// TODO: Either use `cfg_attr` on the `deprecated`
// attributes, or merge it into a single string.
warn!(m, message, "message availability attributes were not equal");
}
}
message = Some(m);
Expand Down
36 changes: 27 additions & 9 deletions crates/header-translator/src/expr.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use std::collections::BTreeMap;
use std::collections::{BTreeMap, HashSet};
use std::fmt;

use clang::token::TokenKind;
use clang::{Entity, EntityKind, EntityVisitResult, EvaluationResult};

use crate::rust_type::Ty;
use crate::stmt::{enum_constant_name, new_enum_id};
use crate::{Context, ItemIdentifier};
use crate::unexposed_attr::UnexposedAttr;
use crate::{immediate_children, Context, ItemIdentifier};

#[derive(Clone, Debug, PartialEq)]
pub enum Token {
Expand All @@ -27,7 +28,7 @@ pub enum Expr {
Enum {
id: ItemIdentifier,
variant: String,
// TODO: Type
attrs: HashSet<UnexposedAttr>,
},
Const(ItemIdentifier), // TODO: Type
Var {
Expand Down Expand Up @@ -180,9 +181,18 @@ impl Expr {
let parent_id = new_enum_id(&parent, context);
let name = entity.get_name().expect("EnumConstantDecl name");
if parent_id.name.is_some() {
let mut attrs = HashSet::new();
immediate_children(&parent, |entity, _span| {
if let EntityKind::UnexposedAttr = entity.get_kind() {
if let Some(attr) = UnexposedAttr::parse(&entity, context) {
attrs.insert(attr);
}
}
});
Self::Enum {
id: parent_id.map_name(|name| name.unwrap()),
variant: name,
attrs,
}
} else {
Self::Const(parent_id.map_name(|_| name))
Expand Down Expand Up @@ -256,17 +266,25 @@ impl fmt::Display for Expr {
write!(f, "{}", id.path())
}
}
Self::Enum { id, variant } => {
Self::Enum { id, variant, attrs } => {
let pretty_name = enum_constant_name(&id.name, variant);
// Note: Even if we had the enum kind available here, we would
// not be able to avoid the `.0` here, as the expression must
// be `const`.
write!(f, "{}::{pretty_name}.0", id.name)
if attrs.contains(&UnexposedAttr::ClosedEnum) {
// Close enums are actual Rust `enum`s, so to get their
// value, we use an `as` cast.
// Using `usize` here is a hack, we should be using the
// actual enum type.
write!(f, "{}::{pretty_name} as usize", id.name)
} else {
// Note: Even though we have the enum kind available here,
// we cannot avoid the `.0` here, as the expression must
// be `const`.
write!(f, "{}::{pretty_name}.0", id.name)
}
}
Self::Const(id) => write!(f, "{}", id.name),
Self::Var { id, ty } => {
if ty.is_enum_through_typedef() {
write!(f, "{}.0", id.name)
write!(f, "{}.xxx", id.name)
} else {
write!(f, "{}", id.name)
}
Expand Down
8 changes: 7 additions & 1 deletion crates/header-translator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,19 @@ fn parse_sdk(
if let Some(location) = context.get_location(&entity) {
let library_name = location.library_name();
if library_span.as_ref().map(|(_, s)| &**s) != Some(library_name) {
// Drop old entered spans
library_span.take();
file_span.take();
// Enter new span
library_span = Some((
debug_span!("library", name = library_name).entered(),
library_name.to_string(),
));
file_span.take();
}
if file_span.as_ref().map(|(_, l)| l) != Some(&location) {
// Drop old entered span
file_span.take();
// Enter new span
file_span = Some((debug_span!("file", ?location).entered(), location.clone()));
}

Expand Down
50 changes: 30 additions & 20 deletions crates/header-translator/src/rust_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,22 +424,29 @@ pub enum Ty {

impl Ty {
fn parse(attributed_ty: Type<'_>, mut lifetime: Lifetime, context: &Context<'_>) -> Self {
let _span = debug_span!("ty", ?attributed_ty, ?lifetime).entered();

let mut ty = attributed_ty;
while let TypeKind::Attributed = ty.get_kind() {
ty = ty
.get_modified_type()
.expect("attributed type to have modified type");
}

let _span = debug_span!("ty2", ?ty).entered();
let _span = debug_span!("ty", ?ty, ?lifetime).entered();

let mut attributed_name = attributed_ty.get_display_name();
let mut name = ty.get_display_name();
let mut unexposed_nullability = None;

while let TypeKind::Unexposed | TypeKind::Attributed = ty.get_kind() {
if let TypeKind::Attributed = ty.get_kind() {
ty = ty
.get_modified_type()
.expect("attributed type to have modified type");
name = ty.get_display_name();
continue;
}

if let Some(nullability) = ty.get_nullability() {
if unexposed_nullability.is_some() {
error!("unexposed nullability already set");
}
unexposed_nullability = Some(nullability);
}

let unexposed_nullability = if let TypeKind::Unexposed = ty.get_kind() {
let nullability = ty.get_nullability();
let (new_attributed_name, attributed_attr) = parse_unexposed_tokens(&attributed_name);
// Also parse the expected name to ensure that the formatting that
// TokenStream does is the same on both.
Expand All @@ -453,7 +460,12 @@ impl Ty {
}

match attr {
Some(UnexposedAttr::NonIsolated | UnexposedAttr::UIActor) => {
Some(
UnexposedAttr::NonIsolated
| UnexposedAttr::UIActor
| UnexposedAttr::Sendable
| UnexposedAttr::NonSendable,
) => {
// Ignored for now; these are usually also emitted on the method/property,
// which is where they will be useful in any case.
}
Expand All @@ -467,22 +479,19 @@ impl Ty {
if let Some(modified) = ty.get_modified_type() {
ty = modified;
} else {
error!("expected unexposed type to have modified type");
error!("expected unexposed / attributed type to have modified type");
}
nullability
} else {
None
};
}

let _span = debug_span!("ty3", ?ty).entered();
let _span = debug_span!("ty after unexposed/attributed", ?ty).entered();

let elaborated_ty = ty;

if let Some(true) = ty.is_elaborated() {
ty = ty.get_elaborated_type().expect("elaborated");
}

let _span = debug_span!("ty4", ?ty).entered();
let _span = debug_span!("ty after elaborated", ?ty).entered();

let get_is_const = |new: bool| {
if new {
Expand Down Expand Up @@ -722,10 +731,11 @@ impl Ty {

let is_const = get_is_const(parser.is_const(ParsePosition::Suffix));
lifetime.update(parser.lifetime(ParsePosition::Suffix));
let nullability = parser.nullability(ParsePosition::Suffix);
let nullability = if let Some(nullability) = unexposed_nullability {
nullability
} else {
check_nullability(&attributed_ty, parser.nullability(ParsePosition::Suffix))
check_nullability(&attributed_ty, nullability)
};

let ty = ty.get_pointee_type().expect("pointer type to have pointee");
Expand Down
27 changes: 22 additions & 5 deletions crates/header-translator/src/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1019,7 +1019,8 @@ impl Stmt {
}
match attr {
// TODO
UnexposedAttr::Sendable => warn!("sendable on typedef"),
UnexposedAttr::Sendable => warn!("sendable typedef"),
UnexposedAttr::UIActor => warn!("main-thread-only typedef"),
_ => kind = Some(attr),
}
}
Expand Down Expand Up @@ -1290,7 +1291,15 @@ impl Stmt {
immediate_children(entity, |entity, _span| match entity.get_kind() {
EntityKind::UnexposedAttr => {
if let Some(attr) = UnexposedAttr::parse(&entity, context) {
error!(?attr, "unknown attribute");
match attr {
// Swift makes some statics associated with a
// certain type, which means it needs this to
// allow accessing them from any thread. We
// don't generally restrict statics in this
// fashion, so it shouldn't matter for us.
UnexposedAttr::NonIsolated => {}
attr => error!(?attr, "unknown attribute"),
}
}
}
EntityKind::VisibilityAttr => {}
Expand Down Expand Up @@ -1344,7 +1353,13 @@ impl Stmt {
immediate_children(entity, |entity, _span| match entity.get_kind() {
EntityKind::UnexposedAttr => {
if let Some(attr) = UnexposedAttr::parse(&entity, context) {
error!(?attr, "unknown attribute");
match attr {
// TODO
UnexposedAttr::UIActor => {
warn!("unhandled UIActor on function declaration")
}
_ => error!(?attr, "unknown attribute"),
}
}
}
EntityKind::ObjCClassRef
Expand Down Expand Up @@ -2443,12 +2458,14 @@ impl Stmt {
write!(f, "{}", self.cfg_gate_ln(config))?;
writeln!(f, "pub type {} = {};", id.name, ty.typedef())?;
}
None | Some(UnexposedAttr::BridgedTypedef) => {
kind => {
if !matches!(kind, None | Some(UnexposedAttr::BridgedTypedef)) {
error!("invalid alias kind {kind:?} for {ty:?}");
}
// "bridged" typedefs should use a normal type alias.
write!(f, "{}", self.cfg_gate_ln(config))?;
writeln!(f, "pub type {} = {};", id.name, ty.typedef())?;
}
kind => panic!("invalid alias kind {kind:?} for {ty:?}"),
}
}
};
Expand Down
4 changes: 3 additions & 1 deletion crates/header-translator/src/unexposed_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl UnexposedAttr {
}
"NS_SWIFT_SENDABLE" | "AS_SWIFT_SENDABLE" => Some(Self::Sendable),
"NS_SWIFT_NONSENDABLE" => Some(Self::NonSendable),
"NS_SWIFT_UI_ACTOR" => Some(Self::UIActor),
"NS_SWIFT_UI_ACTOR" | "WK_SWIFT_UI_ACTOR" => Some(Self::UIActor),
"NS_SWIFT_NONISOLATED" | "UIKIT_SWIFT_ACTOR_INDEPENDENT" => Some(Self::NonIsolated),
// TODO
"NS_FORMAT_FUNCTION" | "NS_FORMAT_ARGUMENT" => {
Expand Down Expand Up @@ -125,11 +125,13 @@ impl UnexposedAttr {
| "CI_GL_DEPRECATED_MAC"
| "CIKL_DEPRECATED"
| "CK_UNAVAILABLE"
| "CK_NEWLY_UNAVAILABLE"
| "FPUI_AVAILABLE"
| "MLCOMPUTE_AVAILABLE_STARTING"
| "MLCOMPUTE_AVAILABLE_STARTING_BUT_DEPRECATED_MACOS14"
| "MLCOMPUTE_CLASS_AVAILABLE_STARTING"
| "MLCOMPUTE_ENUM_AVAILABLE_STARTING"
| "MODELCOLLECTION_SUNSET"
| "MP_API"
| "MP_DEPRECATED"
| "MP_DEPRECATED_WITH_REPLACEMENT"
Expand Down
60 changes: 60 additions & 0 deletions crates/objc2/src/topics/about_generated/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* **BREAKING**: Renamed `from_id_slice` to `from_retained_slice`.
* **BREAKING**: Renamed `NSString::as_str` to `to_str`, and made it `unsafe`,
since we cannot ensure that the given pool is actually the innermost pool.
* Updated SDK from Xcode 15.4 to 16.0.

View the release notes to learn more details:
- [16.0](https://developer.apple.com/documentation/xcode-release-notes/xcode-16-release-notes)

Breaking changes are noted elsewhere in this changelog entry.
* **BREAKING**: `NSWindowSharingReadWrite` was deprecated, and moved from
`NSWindowSharingType` to a separate static.
* **BREAKING**: Moved a few methods on AppKit `NSAttributedString` categories.
- `NSAttributedStringKitAdditions` moved to
`NSAttributedStringAppKitAdditions`.
- `NSMutableAttributedStringKitAdditions` moved to
`NSMutableAttributedStringAppKitAdditions`.
- `NSAttributedStringDocumentFormats` moved to
`NSAttributedStringAppKitDocumentFormats`.
- `NSAttributedStringAppKitAttributeFixing` moved to
* **BREAKING**: Make `"MTLResource"` a sub-protocol of the new `MTLAllocation`.
This makes a bunch of things cfg-gated behind `"MTLAllocation"`.
* **BREAKING**: Cfg-gated `LABiometryType` behind `"LABiometryType"` instead
of `"LAContext"`.
* **BREAKING**: Cfg-gated `HKAudiogramSensitivityPoint` behind
`"HKAudiogramSensitivityPoint"` instead of `"HKAudiogramSample"`.

### Deprecated
* Moved `MainThreadMarker` from `objc2-foundation` to `objc2`.
Expand All @@ -66,10 +88,48 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- `UIDocumentProperties::initWithMetadata`
- `UIDocumentProperties::metadata`
- `UIDocumentProperties::setMetadata`
* **BREAKING**: Removed a bunch of deprecated methods in CloudKit:
- `CKFetchNotificationChangesOperation::initWithPreviousServerChangeToken`
- `CKFetchNotificationChangesOperation::previousServerChangeToken`
- `CKFetchNotificationChangesOperation::resultsLimit`
- `CKFetchNotificationChangesOperation::moreComing`
- `CKFetchNotificationChangesOperation::notificationChangedBlock`
- `CKMarkNotificationsReadOperation::initWithNotificationIDsToMarkRead`
- `CKMarkNotificationsReadOperation::notificationIDs`
- `CKMarkNotificationsReadOperation::markNotificationsReadCompletionBlock`
- `CKModifyBadgeOperation::initWithBadgeValue`
- `CKModifyBadgeOperation::initWithBadgeValue`
- `CKModifyBadgeOperation::badgeValue`
- `CKModifyBadgeOperation::modifyBadgeCompletionBlock`
- `CKModifyBadgeOperation::initWithBadgeValue`
* **BREAKING**: Removed `SCStreamDelegate::userDidStopStream`.
- **BREAKING**: Removed `BGContinuedProcessingTaskRequest`.

### Fixed
* **BREAKING**: Converted function signatures into using `extern "C-unwind"`.
This allows Rust and Objective-C unwinding to interoperate.
* Removed incorrectly declared `BGTask::new` method.
* **BREAKING**: Marked the following classes and protocols as `MainThreadOnly`:
- `ASAuthorizationControllerPresentationContextProviding`,
- `ASAuthorizationControllerDelegate`
- `ASAuthorizationProviderExtensionAuthorizationRequestHandler`
- `ASAccountAuthenticationModificationControllerPresentationContextProviding`
- `ASWebAuthenticationPresentationContextProviding`
- `EXHostViewControllerDelegate`
- `MKMapViewDelegate`
- `MTKViewDelegate`
- `UIToolTipConfiguration`
- `UIToolTipInteractionDelegate`
- `UITraitListEnvironment`
- `NSOutlineViewDelegate`
- `MEComposeSessionHandler`
- `MEExtension`
- `MEMessageSecurityHandler`
- `PHContentEditingController`
- `PHLivePhotoViewDelegate`
- A bunch of things in `WebKit`.
* **BREAKING**: Marked methods on the `NSObjectUIAccessibility` category as
`MainThreadOnly`.


## 0.2.2 - 2024-05-21
Expand Down
12 changes: 6 additions & 6 deletions crates/objc2/src/topics/about_generated/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ for the [`block2`] crate for how to call such methods using a closure.

## Currently supported versions

- macOS: `10.12-14.5`
- iOS/iPadOS: `10.0-17.5` (WIP)
- tvOS: `10.0-17.5` (WIP)
- watchOS: `5.0-10.5` (WIP)
- visionOS: `1.0-1.2` (WIP)
- macOS: `10.12-15.0`
- iOS/iPadOS: `10.0-18.0` (WIP)
- tvOS: `10.0-18.0` (WIP)
- watchOS: `5.0-11.0` (WIP)
- visionOS: `1.0-2.0` (WIP)

These bindings are currently generated from the SDKs in Xcode 15.4.
These bindings are currently generated from the SDKs in Xcode 16.0.
The Xcode version will be periodically updated.
Loading