-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Type substitution eliminates dependencies with Escapable targets. #80438
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
Type substitution eliminates dependencies with Escapable targets. #80438
Conversation
@swift-ci Please test |
@swift-ci Please test Windows |
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.
Just some nitpicks
include/swift/AST/TypeTransform.h
Outdated
/// Returns true if the set of output lifetime dependencies is different from | ||
/// the set of input lifetime dependencies, false if there was no change. | ||
inline bool | ||
filterEscapableLifetimeDependencies(GenericSignature sig, |
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.
Maybe this belongs in LifetimeDependenceInfo.h?
include/swift/AST/TypeTransform.h
Outdated
} else { | ||
// The last lifetime dependency targets the result at the end | ||
// of the curried chain. | ||
assert(targetIndex == params.size() |
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.
Let's use ASSERT in new code
include/swift/AST/TypeTransform.h
Outdated
auto extInfo = fnTy->getExtInfo(); | ||
SmallVector<LifetimeDependenceInfo, 2> substDependenceInfos; | ||
bool didRemoveLifetimeDependencies | ||
= filterEscapableLifetimeDependencies(GenericSignature(), |
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.
Type::transform() is a very hot code path. Can you think of a way to skip all of this new work if the function type does not have lifetime dependencies?
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 misunderstood your code; if there are no lifetime dependencies in the function type it does appear everything is skipped.
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.
filterEscapableLifetimeDependencies
doesn't do anything if the input list is empty, since it just runs in a for
loop. I can hoist that check out at each use point if you think it'll make a difference.
@@ -916,3 +916,11 @@ bool TypeBase::isEscapable() { | |||
auto canType = preprocessTypeForInvertibleQuery(this); | |||
return conformsToInvertible(canType, InvertibleProtocolKind::Escapable); | |||
} | |||
|
|||
bool TypeBase::isEscapable(GenericSignature sig) { |
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.
Is this new utility method really necessary? If you know type
is an interface type, this will work whether sig is null or not:
GenericEnvironment::mapTypeIntoContext(sig.getGenericEnvironment(), type)->isEscapable()
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.
To me, it seems like having only the version that takes a GenericSignature
would be more robust, since that would lead to call sites passing a GenericSignature proactively. As is it's easy to reach for isEscapable
and write code that crashes as soon as it's used in a generic context.
@swift-ci Please test macOS |
When a generic function has potentially Escapable outputs, those outputs declare lifetime dependencies, which have no effect when substitution leads to those types becoming `Escapable` in a concrete context. This means that type substitution should canonically eliminate lifetime dependencies targeting Escapable parameters or returns, and that type checking should allow a function value with potentially-Escapable lifetime dependencies to bind to a function type without those dependencies when the target of the dependencies is Escapable. Fixes rdar://147533059.
54f195f
to
6b605f4
Compare
@swift-ci Please test |
Comments in PR swiftlang#80438, where this code comes from, already suggest using ASSERT() instead of assert().
Comments in PR swiftlang#80438, where this code comes from, already suggest using ASSERT() instead of assert().
Comments in PR swiftlang#80438, where this code comes from, already suggest using ASSERT() instead of assert().
When a generic function has potentially Escapable outputs, those outputs declare lifetime dependencies, which have no effect when substitution leads to those types becoming
Escapable
in a concrete context. This means that type substitution should canonically eliminate lifetime dependencies targeting Escapable parameters or returns, and that type checking should allow a function value with potentially-Escapable lifetime dependencies to bind to a function type without those dependencies when the target of the dependencies is Escapable.Fixes rdar://147533059.