Skip to content

Commit 7ce4f15

Browse files
author
Nathan Hawes
authored
Merge pull request #24250 from nathawes/module-interface-cherry-picks-5.1
[5.1] Cherry-pick module interface fixes to 5.1
2 parents f7261e8 + 9738713 commit 7ce4f15

File tree

4 files changed

+80
-3
lines changed

4 files changed

+80
-3
lines changed

lib/Sema/TypeCheckAttr.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,13 @@ void AttributeEarlyChecker::visitIBOutletAttr(IBOutletAttr *attr) {
415415
if (!VD->getDeclContext()->getSelfClassDecl() || VD->isStatic())
416416
diagnoseAndRemoveAttr(attr, diag::invalid_iboutlet);
417417

418-
if (!VD->isSettable(nullptr))
419-
diagnoseAndRemoveAttr(attr, diag::iboutlet_only_mutable);
418+
if (!VD->isSettable(nullptr)) {
419+
// Allow non-mutable IBOutlet properties in module interfaces,
420+
// as they may have been private(set)
421+
SourceFile *Parent = VD->getDeclContext()->getParentSourceFile();
422+
if (!Parent || Parent->Kind != SourceFileKind::Interface)
423+
diagnoseAndRemoveAttr(attr, diag::iboutlet_only_mutable);
424+
}
420425

421426
// Verify that the field type is valid as an outlet.
422427
auto type = VD->getType();

lib/Serialization/Deserialization.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2613,7 +2613,10 @@ class swift::DeclDeserializer {
26132613
if (auto *overridden = ctor->getOverriddenDecl()) {
26142614
if (!attributeChainContains<RequiredAttr>(DAttrs) ||
26152615
!overridden->isRequired()) {
2616-
AddAttribute(new (ctx) OverrideAttr(SourceLoc()));
2616+
// FIXME: why is a convenience init considered overridden when the
2617+
// overriding init can't be marked overriding in source?
2618+
if (!overridden->isConvenienceInit())
2619+
AddAttribute(new (ctx) OverrideAttr(SourceLoc()));
26172620
}
26182621
}
26192622

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// Generate the parseable interface of the current file via the merge-modules step
4+
// RUN: %target-build-swift -emit-module -o %t/Test.swiftmodule -emit-parseable-module-interface-path %t/TestMerge.swiftinterface -module-name Test %s
5+
6+
// Generate the parseable interface of the current file via a single frontend invocation
7+
// RUN: %target-swift-frontend -typecheck -enable-objc-interop -emit-parseable-module-interface-path %t/TestSingle.swiftinterface -module-name Test %s
8+
9+
// Make sure both don't add override for inits shadowing convenience initializers
10+
// RUN: %FileCheck --check-prefixes=CHECK,SINGLE %s < %t/TestSingle.swiftinterface
11+
// RUN: %FileCheck --check-prefixes=CHECK,MERGE %s < %t/TestMerge.swiftinterface
12+
13+
// Check we can consume the interface without issue
14+
// RUN: %target-swift-frontend -swift-version 5 -build-module-from-parseable-interface -o %t/Test.swiftmodule %t/TestSingle.swiftinterface
15+
// RUN: %target-swift-frontend -swift-version 5 -build-module-from-parseable-interface -o %t/Test.swiftmodule %t/TestMerge.swiftinterface
16+
17+
public class Base {
18+
let x: Int
19+
public init(x: Int) {
20+
self.x = x
21+
}
22+
convenience public init() {
23+
self.init(x: 1)
24+
}
25+
}
26+
27+
public class Derived: Base {
28+
// MERGE: {{^}} public init(z: Swift.Int)
29+
// SINGLE: {{^}} public init(z: Int)
30+
public init(z: Int) {
31+
super.init(x: z)
32+
}
33+
// MERGE: {{^}} public convenience init()
34+
// SINGLE: {{^}} convenience public init()
35+
convenience public init() {
36+
self.init(z: 1)
37+
}
38+
}
39+
40+
public class Derived2: Base {
41+
// CHECK: {{^}} public init()
42+
public init() {
43+
super.init(x: 1)
44+
}
45+
46+
// MERGE: {{^}} override public convenience init(x: Swift.Int)
47+
// SINGLE: {{^}} override convenience public init(x: Int)
48+
override convenience public init(x: Int) {
49+
self.init()
50+
}
51+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// REQUIRES: objc_interop
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: %target-swift-frontend -typecheck -enable-library-evolution -disable-objc-attr-requires-foundation-module -emit-parseable-module-interface-path %t/Foo.swiftinterface %s
5+
// RUN: %FileCheck %s -input-file %t/Foo.swiftinterface
6+
// RUN: %target-swift-frontend -build-module-from-parseable-interface %t/Foo.swiftinterface -o %t/Foo.swiftmodule
7+
8+
// Test the interface we generate for @IBOutlet private(set) properties is
9+
// consumable.
10+
11+
@objc public class MyType {}
12+
13+
open class Bar {
14+
// CHECK: @objc @IBOutlet weak public var foo: MyType! {
15+
// CHECK-NEXT: get
16+
// CHECK-NEXT: }
17+
@IBOutlet public private(set) weak var foo: MyType!
18+
}

0 commit comments

Comments
 (0)