-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Function builders] Use buildLimitedAvailability() for #available block #32994
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
[Function builders] Use buildLimitedAvailability() for #available block #32994
Conversation
The use of "if #available" in function builders can subvert availability checking if the function builder carries all type information for the values within the "then" block outside of the "else" block. Tighten up the model in two ways: * Check whether the type coming out of an "if #available" references any declarations that are not available in the outer context, to close up the model. * If the function builder provides a buildLimitedAvailability(_:) operation, call that on the result of the "then" block in an "if that it cannot leak out of the "if #available"; if it doesn't, the check above will still fire. Stage this in with a warning so function builders out there in the wild can adapt. We'll upgrade the warning to an error later. Fixes rdar://problem/65021017.
@swift-ci test |
@swift-ci test source compatibility |
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 just have some very minor suggestions
@@ -5127,6 +5127,10 @@ NOTE(function_builder_infer_add_return, none, | |||
NOTE(function_builder_infer_pick_specific, none, | |||
"apply function builder %0 (inferred from %select{protocol|dynamic replacement of}1 %2)", | |||
(Type, unsigned, DeclName)) | |||
WARNING(function_builder_missing_limited_availability, none, | |||
"function builder %0 does not implement `buildLimitedAvailability`; " |
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.
"function builder %0 does not implement `buildLimitedAvailability`; " | |
"function builder %0 does not implement 'buildLimitedAvailability'; " |
It would also be great to put this in the YAML diagnostic localization file :)
@@ -498,10 +517,20 @@ class BuilderClosureVisitor | |||
if (!cs || !thenVar || (elseChainVar && !*elseChainVar)) | |||
return nullptr; | |||
|
|||
// If there is a #available in the condition, the 'then' will need to | |||
// be wrapped in a call to buildAvailabilityErasure(_:), if available. |
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.
// be wrapped in a call to buildAvailabilityErasure(_:), if available. | |
// be wrapped in a call to buildLimitedAvailability(_:), if available. |
@@ -1175,6 +1204,35 @@ class BuilderClosureRewriter | |||
capturedThen.first, {capturedThen.second.front()})); | |||
ifStmt->setThenStmt(newThen); | |||
|
|||
// Look for a #available condition. If there is one, we need to check | |||
// that the resulting type of the "then" does refer to any types that |
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.
// that the resulting type of the "then" does refer to any types that | |
// that the resulting type of the "then" doesn’t refer to any types that |
// that the resulting type of the "then" does refer to any types that | ||
// are unavailable in the enclosing context. | ||
// | ||
// Note that this is for staging in support for |
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.
Nit: Incomplete sentence.
Looks good to me! For an added bit of paranoia, should we look at the availability of the |
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.
Approved for the short term.
// that the resulting type of the "then" does refer to any types that | ||
// are unavailable in the enclosing context. | ||
// | ||
// Note that this is for staging in support for |
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.
Incomplete sentence
nominal, loc, dc)) { | ||
// Note that the problem is with the function builder, not the body. | ||
// This is for staging only. We want to disable #available in | ||
// function builders that don't support this operation. |
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.
This doesn't seem reasonable in general; function builders which don't propagate types structurally are probably fine. Can we not diagnose that an unavailable type has escaped the context?
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.
We can, and you're right: I'll zap the comment when address the other comments in a follow-up PR. Later in 5.3, we'll turn this warning into an error.
The call to |
Cleanup PR over at #33046 |
The use of "if #available" in function builders can subvert availability
checking if the function builder carries all type information for the
values within the "then" block outside of the "else" block. Tighten up
the model in two ways:
any declarations that are not available in the outer context, to close
up the model.
operation, call that on the result of the "then" block in an "if
that it cannot leak out of the "if #available"; if it doesn't, the
check above will still fire.
Stage this in with a warning so function builders out there in the wild
can adapt. We'll upgrade the warning to an error later.
Fixes rdar://problem/65021017.