Skip to content

Commit 40cfc45

Browse files
authored
Fix synthesis of 'override' and 'required' on initializers (swiftlang#20548)
This is actually two separate problems: - 'override' wasn't getting added to initializers in deserialization - 'override' was getting added when inheriting a 'required' initializer, even though it's normally an error to write that Needed for parseable interfaces.
1 parent a21a71d commit 40cfc45

File tree

4 files changed

+54
-9
lines changed

4 files changed

+54
-9
lines changed

lib/Sema/CodeSynthesis.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2473,11 +2473,12 @@ configureInheritedDesignatedInitAttributes(TypeChecker &tc,
24732473
}
24742474

24752475
// Wire up the overrides.
2476-
ctor->getAttrs().add(new (ctx) OverrideAttr(/*IsImplicit=*/true));
24772476
ctor->setOverriddenDecl(superclassCtor);
24782477

24792478
if (superclassCtor->isRequired())
2480-
ctor->getAttrs().add(new (ctx) RequiredAttr(/*IsImplicit=*/true));
2479+
ctor->getAttrs().add(new (ctx) RequiredAttr(/*IsImplicit=*/false));
2480+
else
2481+
ctor->getAttrs().add(new (ctx) OverrideAttr(/*IsImplicit=*/false));
24812482

24822483
// If the superclass constructor is @objc but the subclass constructor is
24832484
// not representable in Objective-C, add @nonobjc implicitly.

lib/Serialization/Deserialization.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2222,6 +2222,15 @@ ModuleFile::getDeclChecked(DeclID DID) {
22222222
return deserialized;
22232223
}
22242224

2225+
template <typename DERIVED>
2226+
static bool attributeChainContains(DeclAttribute *attr) {
2227+
DeclAttributes tempAttrs;
2228+
tempAttrs.setRawAttributeChain(attr);
2229+
static_assert(std::is_trivially_destructible<DeclAttributes>::value,
2230+
"must not try to destroy the attribute chain");
2231+
return tempAttrs.hasAttribute<DERIVED>();
2232+
}
2233+
22252234
Expected<Decl *>
22262235
ModuleFile::getDeclCheckedImpl(DeclID DID) {
22272236
if (DID == 0)
@@ -2892,9 +2901,16 @@ ModuleFile::getDeclCheckedImpl(DeclID DID) {
28922901
ctor->setStubImplementation(true);
28932902
if (initKind.hasValue())
28942903
ctor->setInitKind(initKind.getValue());
2895-
ctor->setOverriddenDecl(cast_or_null<ConstructorDecl>(overridden.get()));
28962904
ctor->setNeedsNewVTableEntry(needsNewVTableEntry);
28972905

2906+
ctor->setOverriddenDecl(cast_or_null<ConstructorDecl>(overridden.get()));
2907+
if (auto *overridden = ctor->getOverriddenDecl()) {
2908+
if (!attributeChainContains<RequiredAttr>(DAttrs) ||
2909+
!overridden->isRequired()) {
2910+
AddAttribute(new (ctx) OverrideAttr(SourceLoc()));
2911+
}
2912+
}
2913+
28982914
if (auto defaultArgumentResilienceExpansion = getActualResilienceExpansion(
28992915
rawDefaultArgumentResilienceExpansion)) {
29002916
ctor->setDefaultArgumentResilienceExpansion(

test/ParseableInterface/modifiers.swift

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: %FileCheck %s < %t/Test.swiftinterface
44
// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -disable-objc-attr-requires-foundation-module -emit-parseable-module-interface-path - -module-name Test -enable-objc-interop | %FileCheck %s
55

6-
// CHECK: final public class FinalClass {
6+
// CHECK-LABEL: final public class FinalClass {
77
public final class FinalClass {
88
// CHECK: @inlinable final public class var a: [[INT:(Swift.)?Int]] {
99
// CHECK-NEXT: {{^}} get {
@@ -53,7 +53,35 @@ public final class FinalClass {
5353
}
5454
}
5555

56-
// CHECK: public struct MyStruct {
56+
// CHECK-LABEL: public class Base {
57+
public class Base {
58+
// CHECK-NEXT: @objc public init(){{$}}
59+
@objc public init() {}
60+
// CHECK-NEXT: @objc required public init(x: [[INT]]){{$}}
61+
@objc public required init(x: Int) {}
62+
// CHECK-NEXT: @objc deinit{{$}}
63+
} // CHECK-NEXT: {{^}$}}
64+
65+
66+
// CHECK-LABEL: public class SubImplicit : {{(Test[.])?Base}} {
67+
public class SubImplicit: Base {
68+
// CHECK-NEXT: @objc override public init(){{$}}
69+
// CHECK-NEXT: @objc required public init(x: [[INT]]){{$}}
70+
// CHECK-NEXT: @objc deinit{{$}}
71+
} // CHECK-NEXT: {{^}$}}
72+
73+
74+
// CHECK-LABEL: public class SubExplicit : {{(Test[.])?Base}} {
75+
public class SubExplicit: Base {
76+
// Make sure adding "required" preserves both "required" and "override".
77+
// CHECK-NEXT: @objc override required public init(){{$}}
78+
public override required init() { super.init() }
79+
// CHECK-NEXT: @objc required public init(x: [[INT]]){{$}}
80+
public required init(x: Int) { super.init() }
81+
// CHECK-NEXT: @objc deinit{{$}}
82+
} // CHECK-NEXT: {{^}$}}
83+
84+
// CHECK-LABEL: public struct MyStruct {
5785
public struct MyStruct {
5886
// CHECK: public var e: [[INT]] {
5987
// CHECK-NEXT: {{^}} mutating get{{$}}

test/attr/accessibility_print.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -365,12 +365,12 @@ public class PublicInitBase {
365365

366366
// CHECK-LABEL: public{{(\*/)?}} class PublicInitInheritor : PublicInitBase {
367367
public class PublicInitInheritor : PublicInitBase {
368-
// CHECK: {{^}} public init()
369-
// CHECK: {{^}} fileprivate init(other: PublicInitBase)
368+
// CHECK: {{^}} override public init()
369+
// CHECK: {{^}} override fileprivate init(other: PublicInitBase)
370370
} // CHECK: {{^[}]}}
371371

372372
// CHECK-LABEL: {{(/\*)?private(\*/)?}} class PublicInitPrivateInheritor : PublicInitBase {
373373
private class PublicInitPrivateInheritor : PublicInitBase {
374-
// CHECK: {{^}} internal init()
375-
// CHECK: {{^}} fileprivate init(other: PublicInitBase)
374+
// CHECK: {{^}} override internal init()
375+
// CHECK: {{^}} override fileprivate init(other: PublicInitBase)
376376
} // CHECK: {{^[}]}}

0 commit comments

Comments
 (0)