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

Don’t serialize objcImpl members #76191

Closed
wants to merge 1 commit into from
Closed
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
4 changes: 4 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2535,6 +2535,10 @@ class PatternBindingDecl final : public Decl,
/// Does this binding declare something that requires storage?
bool hasStorage() const;

/// Does this binding have at least one VarDecl that's an ObjC member
/// implementation?
bool hasAnyObjCMemberImplementations() const;

/// Determines whether this binding either has an initializer expression, or is
/// default initialized, without performing any type checking on it.
bool isDefaultInitializable() const {
Expand Down
10 changes: 10 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4620,6 +4620,16 @@ bool ValueDecl::isObjCMemberImplementation() const {
this, [&]() { return this->getFormalAccess(); });
}

bool PatternBindingDecl::hasAnyObjCMemberImplementations() const {
bool foundAny = false;
for (auto i : range(getNumPatternEntries())) {
getPattern(i)->forEachVariable([&](VarDecl *VD) {
foundAny |= VD->isObjCMemberImplementation();
});
}
return foundAny;
}

/// Checks if \p VD may be used from \p useDC, taking \@testable and \@_spi
/// imports into account.
///
Expand Down
6 changes: 4 additions & 2 deletions lib/Serialization/Serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2024,7 +2024,6 @@ static bool shouldSerializeMember(Decl *D) {
case DeclKind::Protocol:
case DeclKind::Constructor:
case DeclKind::Destructor:
case DeclKind::PatternBinding:
case DeclKind::Subscript:
case DeclKind::TypeAlias:
case DeclKind::GenericTypeParam:
Expand All @@ -2036,7 +2035,10 @@ static bool shouldSerializeMember(Decl *D) {
case DeclKind::Param:
case DeclKind::Func:
case DeclKind::Accessor:
return true;
return !cast<ValueDecl>(D)->isObjCMemberImplementation();

case DeclKind::PatternBinding:
return !cast<PatternBindingDecl>(D)->hasAnyObjCMemberImplementations();
}

llvm_unreachable("Unhandled DeclKind in switch.");
Expand Down
4 changes: 4 additions & 0 deletions test/Serialization/Inputs/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ module CLibrary {
module RawLayoutCXX {
header "raw_layout_cxx.h"
}

module objc_implementation {
header "objc_implementation.h"
}
20 changes: 20 additions & 0 deletions test/Serialization/Inputs/objc_implementation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface ObjCImpl : NSObject

- (instancetype)initWithNonSerialized:(int)value NS_SWIFT_NAME(init(nonSerialized:));
- (void)nonSerializedMethod;
@property (assign) int nonSerializedProperty;

@end

@interface ObjCImpl (CategoryMembers)

- (void)nonSerializedCategoryMethod;
@property (assign) int nonSerializedCategoryProperty;

@end

NS_ASSUME_NONNULL_END
68 changes: 68 additions & 0 deletions test/Serialization/objc_implementation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -module-name main -o %t -I %S/Inputs %s
// RUN: llvm-bcanalyzer %t/main.swiftmodule > %t/main.swiftmodule.txt
// RUN: %target-swift-ide-test -print-module -module-to-print=main -I %t -source-filename=%s >%t/main.txt
// RUN: %FileCheck %s --check-prefixes POSITIVE,CHECK --input-file=%t/main.txt
// RUN: %FileCheck %s --check-prefixes NEGATIVE,CHECK --input-file=%t/main.txt

// REQUIRES: objc_interop

import Foundation
import objc_implementation

// CHECK-LABEL: @objc @implementation extension ObjCImpl
@objc @implementation extension ObjCImpl {
// These should not appear in the serialized output.

// NEGATIVE-NOT: init(nonSerialized value
@objc(initWithNonSerialized:)
public init(nonSerialized value: Int32) {
super.init()
}

// NEGATIVE-NOT: func nonSerializedMethod
@objc public func nonSerializedMethod() {}

// NEGATIVE-NOT: var nonSerializedProperty
@objc public var nonSerializedProperty: Int32 = 0

// NEGATIVE-NOT: deinit
deinit {}

// These should appear in the serialized output.

// POSITIVE: func serializedMethod
final public func serializedMethod() {}
// POSITIVE: var serializedProperty
final public var serializedProperty: Int32 = 0

// POSITIVE: init(serialized value
@nonobjc public convenience init(serialized value: Int32) {
self.init(nonSerialized: value)
}
}

// CHECK-LABEL: @objc(CategoryMembers) @implementation extension ObjCImpl
@objc(CategoryMembers) @implementation extension ObjCImpl {
// These should not appear in the serialized output.

// NEGATIVE-NOT: func nonSerializedCategoryMethod
@objc public func nonSerializedCategoryMethod() {}

// NEGATIVE-NOT: var nonSerializedCategoryProperty
@objc public var nonSerializedCategoryProperty: Int32 {
get { nonSerializedProperty }
set { nonSerializedProperty = newValue }
}

// These should appear in the serialized output.

// POSITIVE: func serializedCategoryMethod()
final public func serializedCategoryMethod() {}

// POSITIVE: var serializedCategoryProperty
final public var serializedCategoryProperty: Int32 {
get { serializedProperty }
set { serializedProperty = newValue }
}
}