Skip to content

Commit 17e64f5

Browse files
Merge pull request #22691 from aschwaighofer/allow_dynamic_replacement_init_non_delegating
Allow dynamic replacement initializers to be non delegating
2 parents 802f0bd + d5b33ba commit 17e64f5

File tree

4 files changed

+78
-2
lines changed

4 files changed

+78
-2
lines changed

lib/AST/Decl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6344,8 +6344,10 @@ ConstructorDecl::getDelegatingOrChainedInitKind(DiagnosticEngine *diags,
63446344
// Prior to Swift 5, cross-module initializers were permitted to be
63456345
// non-delegating. However, if the struct isn't fixed-layout, we have to
63466346
// be delegating because, well, we don't know the layout.
6347+
// A dynamic replacement is permitted to be non-delegating.
63476348
if (NTD->isResilient() ||
6348-
containingModule->getASTContext().isSwiftVersionAtLeast(5)) {
6349+
(containingModule->getASTContext().isSwiftVersionAtLeast(5) &&
6350+
!getAttrs().getAttribute<DynamicReplacementAttr>())) {
63496351
if (containingModule != NTD->getParentModule())
63506352
Kind = BodyInitKind::Delegating;
63516353
}

lib/Sema/TypeCheckDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4047,7 +4047,8 @@ void TypeChecker::validateDecl(ValueDecl *D) {
40474047
// (or the same file) to add vtable entries, we can re-evaluate this
40484048
// restriction.
40494049
if (extType->getClassOrBoundGenericClass() &&
4050-
isa<ExtensionDecl>(CD->getDeclContext())) {
4050+
isa<ExtensionDecl>(CD->getDeclContext()) &&
4051+
!(CD->getAttrs().hasAttribute<DynamicReplacementAttr>())) {
40514052
diagnose(CD->getLoc(), diag::designated_init_in_extension, extType)
40524053
.fixItInsert(CD->getLoc(), "convenience ");
40534054
CD->setInitKind(CtorInitializerKind::Convenience);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
struct S {
2+
let i: Int
3+
init(i: Int) {
4+
self.i = i
5+
}
6+
7+
init(y: Int) {
8+
self.init(i: y)
9+
}
10+
}
11+
12+
class A {
13+
let i: Int
14+
init(i: Int) {
15+
self.i = i
16+
}
17+
convenience init(c: Int) {
18+
self.init(i: c)
19+
}
20+
}
21+
22+
class B : A {
23+
let b: Int
24+
init(b: Int, i: Int) {
25+
self.b = b
26+
super.init(i: i)
27+
}
28+
29+
convenience init(x: Int) {
30+
self.init(b: x, i: x)
31+
}
32+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -swift-version 5 -enable-implicit-dynamic -enable-private-imports -emit-module -primary-file %S/Inputs/dynamic_replacements_init_A.swift -emit-module -module-name ModuleA -emit-module-path %t/ModuleA.swiftmodule
3+
// RUN: %target-swift-frontend -swift-version 5 -typecheck -verify %s -I %t
4+
5+
@_private(sourceFile: "dynamic_replacements_init_A.swift") import ModuleA
6+
7+
extension S {
8+
@_dynamicReplacement(for: init(i:))
9+
private init(_i: Int) {
10+
self.i = _i
11+
}
12+
@_dynamicReplacement(for: init(y:))
13+
private init(_y: Int) {
14+
self.init(i: _y)
15+
}
16+
}
17+
18+
extension A {
19+
@_dynamicReplacement(for: init(i:))
20+
private init(_i: Int) {
21+
self.i = _i
22+
}
23+
24+
@_dynamicReplacement(for: init(c:))
25+
private convenience init(_y: Int) {
26+
self.init(i: _y)
27+
}
28+
}
29+
30+
extension B {
31+
@_dynamicReplacement(for: init(b:i:))
32+
private init(_i: Int, _b: Int) {
33+
self.b = _b
34+
super.init(i: _i)
35+
}
36+
37+
@_dynamicReplacement(for: init(x:))
38+
private convenience init(_i: Int) {
39+
self.init(b: _i, i: _i)
40+
}
41+
}

0 commit comments

Comments
 (0)