-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Allow dynamic replacement initializers to be non delegating #22691
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
Allow dynamic replacement initializers to be non delegating #22691
Conversation
rdar://48125765
@swift-ci Please test |
@@ -6342,8 +6342,10 @@ ConstructorDecl::getDelegatingOrChainedInitKind(DiagnosticEngine *diags, | |||
// Prior to Swift 5, cross-module initializers were permitted to be | |||
// non-delegating. However, if the struct isn't fixed-layout, we have to | |||
// be delegating because, well, we don't know the layout. | |||
if (NTD->isResilient() || | |||
containingModule->getASTContext().isSwiftVersionAtLeast(5)) { | |||
// A dynamic replacement is permitted to be non-delegating. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if the type is resilient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I think you should be able to replace resilient constructors via dynamic replacement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the dynamic replacement module have visibility past the resilience boundary? It seems like that would require additional code, or building it with the IRGenOptions::EnableResilienceBypass flag set. Did you test this scenario?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is what I have tested:
$ cat ModuleA.swift
struct S {
let i: Int
init(i: Int) {
self.i = i
}
init(y: Int) {
self.init(i: y)
}
}
$ bin/swiftc -emit-library -Xfrontend -enable-private-imports -Xfrontend -enable-implicit-dynamic ModuleA.swift -emit-module -enable-resilience
$ cat ModuleB.swift
@_private(sourceFile: "ModuleA.swift") import ModuleA
extension S {
@_dynamicReplacement(for: init(i:))
private init(__preview_i: Int) {
self.i = __preview_i
}
@_dynamicReplacement(for: init(y:))
private init(__preview_y: Int) {
self.init(i: __preview_y)
}
}
$ bin/swiftc -emit-library -Xfrontend -enable-private-imports -Xfrontend -enable-implicit-dynamic ModuleB.swift -I. -L. -lModuleA -Xfrontend -enable-resilience -emit-sil
// S.init(__preview_i:)
sil [dynamic_replacement_for "$s7ModuleA1SV1iACSi_tcfC"] @$s7ModuleA1SV0A1BE11__preview_iACSi_tc33_261761554CC3BA78F2BD69544DB6E8C4LlfC : $@convention(method) (Int, @thin S.Type) -> S {
// %0 // users: %8, %6, %3
bb0(%0 : $Int, %1 : $@thin S.Type):
%2 = alloc_stack $S, var, name "self" // users: %4, %9
debug_value %0 : $Int, let, name "__preview_i", argno 1 // id: %3
%4 = begin_access [modify] [static] %2 : $*S // users: %7, %5
%5 = struct_element_addr %4 : $*S, #S.i // user: %6
store %0 to %5 : $*Int // id: %6
end_access %4 : $*S // id: %7
%8 = struct $S (%0 : $Int) // user: %10
dealloc_stack %2 : $*S // id: %9
return %8 : $S // id: %10
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if S and S.init are both public?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, that just crashes the compiler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could make it work, if the dynamic replacement module is built with EnableResilienceBypass on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It crashes in SILGen. There are more dragons. I will deal with that later.
@swift-ci Please test |
rdar://48125765