-
Notifications
You must be signed in to change notification settings - Fork 10.5k
SILGen: Fix crash when a stored property with an initial value has a reabstractable type #34255
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
SILGen: Fix crash when a stored property with an initial value has a reabstractable type #34255
Conversation
@swift-ci Please test source compatibility |
4197ef2
to
2ad7f2c
Compare
@swift-ci Please smoke test |
@swift-ci Please test source compatibility |
2ad7f2c
to
1ec2e7b
Compare
@swift-ci Please test source compatibility |
@swift-ci Please benchmark |
Performance: -O
Code size: -O
Performance: -Osize
Code size: -Osize
Performance: -Onone
Code size: -swiftlibsHow to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
…ertyInitializer()
Instead of constructing an LValue and storing the result of the stored property initializer to the lvalue, let's emit the call of the stored property initializer directly into an initialization pointing at the stored properties named by the pattern.
…reabstractable type A constructor can constrain generic parameters more than the type itself, either because there is a 'where' clause on the constructor, or because the constructor is defined inside an extension with a 'where' clause. In this case, when the constructor calls a stored property initializer to implicitly initialize a stored property with an initial value, we must apply substitutions to get the correct result type for the call. If the original type of the stored property lowers differently based on the abstraction pattern, for example if it is a function type, then emitApply() would by default re-abstract the result to the most specific abstraction pattern possible. However, this was wrong because we store the result value into the stored property, and a stored property's type should always be lowered with the most generic abstraction pattern. In practice, this meant if you have a stored property of type (T) -> (), and an initializer with 'where T == String' for example, we would call the initializer, to produce a value with lowered type (@in_guaranteed String) -> (), then thunk it to a (@guaranteed String) -> (), and try to store the thunk into the stored property -- which has type (@in_guaranteed String) -> (). This would either miscompile or trigger an assertion. To get around this, we want to bypass the orig-to-subst conversion performed in emitApply(). My chosen solution is to have emitApply() emit the result into a ConvertingInitialization set up to perform a subst-to-orig conversion. Now that ConvertingInitialization is smart enough to peephole away matched pairs of orig-to-subst and subst-to-orig conversions, this always reduces to a no-op, and the emitApply() call produces and stores a value with the correct abstraction pattern. Fixes <rdar://problem/67419937>.
1ec2e7b
to
7fd4615
Compare
@swift-ci Please smoke test |
@swift-ci Please test Windows platform |
A constructor can constrain generic parameters more than the
type itself, either because there is a 'where' clause on the
constructor, or because the constructor is defined inside an
extension with a 'where' clause.
In this case, when the constructor calls a stored property
initializer to implicitly initialize a stored property with
an initial value, we must apply substitutions to get the
correct result type for the call.
If the original type of the stored property lowers differently
based on the abstraction pattern, for example if it is a
function type, then emitApply() would by default re-abstract
the result to the most specific abstraction pattern possible.
However, this was wrong because we store the result value into
the stored property, and a stored property's type should
always be lowered with the most generic abstraction pattern.
In practice, this meant if you have a stored property of type
(T) -> ()
, and an initializer withwhere T == String
forexample, we would call the initializer, to produce a value with
lowered type
(@in_guaranteed String) -> ()
, then thunk it to a(@guaranteed String) -> ()
, and try to store the thunk intothe stored property -- which has type
(@in_guaranteed String) -> ()
.This would either miscompile or trigger an assertion.
To get around this, we want to bypass the orig-to-subst
conversion performed in emitApply(). My chosen solution is
to have emitApply() emit the result into a
ConvertingInitialization set up to perform a subst-to-orig
conversion.
Now that ConvertingInitialization is smart enough to
peephole away matched pairs of orig-to-subst and subst-to-orig
conversions, this always reduces to a no-op, and the
emitApply() call produces and stores a value with the
correct abstraction pattern.
Fixes rdar://problem/67419937.