-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[IRGen] Fix crasher in emitPartialApplicationForwarder
when the result type is a struct.
#22401
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
Conversation
…urn type is a tuple that contains a closure. In `emitPartialApplicationForwarder`, when we handle result types that have a type parameter, the lowered result type could be a struct. This happens when we have a function result, for instance: ```swift %0 = function_ref @returns_closure : $@convention(thin) <τ_0_0> (Empty<τ_0_0>) -> (@owned Empty<τ_0_0>, @owned @callee_guaranteed (Empty<τ_0_0>) -> @owned Empty<τ_0_0>) %1 = partial_apply [callee_guaranteed] %0<S>() : $@convention(thin) <τ_0_0> (Empty<τ_0_0>) -> (@owned Empty<τ_0_0>, @owned @callee_guaranteed (Empty<τ_0_0>) -> @owned Empty<τ_0_0>) ``` In this case, we emit code that casts the struct memberwise. Resolves [SR-9709](https://bugs.swift.org/browse/SR-9709).
lib/IRGen/GenFunc.cpp
Outdated
for (auto i : range(structType->getStructNumElements())) { | ||
auto desiredEltTy = structType->getElementType(i); | ||
auto elt = subIGF.Builder.CreateExtractValue(callResult, {i}); | ||
auto castElt = subIGF.Builder.CreateBitCast(elt, desiredEltTy); |
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.
Don't you need a recursion here?
Maybe emitCastToSubstSchema() can be used here?
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 don't know enough IRGen. Can any element be a nested struct? I assumed everything has been exploded at this stage.
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.
Everything is going to be exploded. When we form a direct return value we call getScalarResultType (among other things) which makes this assumption.
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.
You could use IRGenFunction::coerceValue
instead.
// If the result type is dependent on a type parameter we might have to
// cast to the result type - it could be substituted.
if (origConv.getSILResultType().hasTypeParameter()) {
auto ResType = fwd->getReturnType();
if (ResType != callResult->getType())
callResult =
subIGF.coerceValue(callResult, ResType, subIGF.IGM.DataLayout);
}
subIGF.Builder.CreateRet(callResult);
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.
coerceValue() looks much cleaner, thanks Arnold!
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.
Done. This is much nicer :)
@swift-ci please smoke test |
@swift-ci please smoke test and merge |
In
emitPartialApplicationForwarder
, when we handle result types that have a type parameter, the lowered result type could be a struct. This happens when we have a function result, for instance:In this case, we emit code that casts the struct memberwise.
Resolves SR-9709.