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
[ConstraintSystem] Deplay opening generic requirements until after co… #25053
Conversation
…ntextual self has been applied While computing a type of member via `getTypeOfMemberReference` let's delay opening generic requirements associated with function type until after self constraint has been created, that would give a chance for contextual types to get propagated and make mismatch originated in generic requirements much easier to diagnose. Consider following example: ```swift struct S<T> {} extension S where T == Int { func foo() {} } func test(_ s: S<String>) { s.foo() } ``` `foo` would get opened as `(S<$T>) -> () -> Void` and contextual `self` type is going to be `S<String>`, so applying that before generic requirement `$T == Int` would make sure that `$T` gets bound to a contextual type of `String` and later fails requirement constraint `$T == Int`. This is much easier to diagnose comparing to `$T` being bound to `Int` right away due to same-type generic requirement and then failing an attempt to convert `S<String>` to `S<Int>` while simplifying self constraint. Resolves: rdar://problem/46427500 Resolves: rdar://problem/34770265
@@ -1110,7 +1112,8 @@ void ConstraintSystem::openGeneric( | |||
GenericSignature *sig, | |||
bool skipProtocolSelfConstraint, | |||
ConstraintLocatorBuilder locator, | |||
OpenedTypeMap &replacements) { | |||
OpenedTypeMap &replacements, | |||
bool skipGenericRequirements) { |
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.
Instead of adding a new boolean parameter here, how about removing the openGenericRequirements() call below, and then changing all callers to either call it or not? It would be clearer than yet another boolean. This allows you to remove the skipProtocolSelfConstraint parameter from openGeneric() as well, since its only used by openGenericRequirements().
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 have considered doing that, but I didn't go that route because it means that we'd have to do duplicate direct calls everywhere when it's only useful in this special case. I think it makes this whole setup more error-prone. Other places like CRanking/getTypeOfReference shouldn't have to do anything special besides a call to openFunctionType/openGeneric.
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.
But there aren't that many calls overall are there? I'm just not a fan of boolean flags as parameters to functions.
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 also factor into three functions, openGeneric() that does both, openGenericParams() creating the type variables and binding the outer archetypes only, and openGenericRequirements()
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.
There aren't many calls at the moment, but I want to make sure that openGeneric
/openFunctionType
still does the right thing by default. I can absolutely look into refactoring this some more though.
@swift-ci please smoke test compiler performance |
@swift-ci please test |
@swift-ci please test source compatibility |
Build failed |
Looks like this also fixed LLDB crash |
Align test error message which apple/swift#25053 which improves diagnostics related to generic requirements.
@swift-ci Please test macOS platform |
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 looks correct and is an improvement, although that set of bool
parameters is starting to make me a bit twitchy.
@DougGregor I talked to @slavapestov about this offline as well. Going to get this merged and refactor separately as I wanted to get this into 5.1 with minimal changes. |
Align test error message which apple/swift#25053 which improves diagnostics related to generic requirements. (cherry picked from commit bbe2050)
…ntextual self has been applied
While computing a type of member via
getTypeOfMemberReference
let's delay opening generic requirements associated with function
type until after self constraint has been created, that would give
a chance for contextual types to get propagated and make mismatch
originated in generic requirements much easier to diagnose.
Consider following example:
foo
would get opened as(S<$T>) -> () -> Void
and contextualself
type is going to be
S<String>
, so applying that before generic requirement$T == Int
would make sure that$T
gets bound to a contextualtype of
String
and later fails requirement constraint$T == Int
.This is much easier to diagnose comparing to
$T
being bound toInt
right away due to same-type generic requirement and thenfailing an attempt to convert
S<String>
toS<Int>
while simplifyingself constraint.
Resolves: rdar://problem/46427500
Resolves: rdar://problem/34770265