Skip to content

[CSGen] Don't walk into ?? in LinkedExprAnalyzer. #40078

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

Merged
merged 1 commit into from
Nov 6, 2021

Conversation

hborla
Copy link
Member

@hborla hborla commented Nov 6, 2021

Attempting to favor the type of this expression based on operand types is wrong, because this operator attempts to unwrap its operand types.

Resolves: rdar://85045881

Attempting to favor the type of this expression based on operand
types is wrong, because this operator attempts to unwrap its
operand types.
@hborla hborla requested a review from DougGregor November 6, 2021 04:24
@hborla
Copy link
Member Author

hborla commented Nov 6, 2021

@swift-ci please smoke test

@hborla hborla requested a review from xedin November 6, 2021 04:29
Copy link
Contributor

@xedin xedin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hamishknight I suspect this change is caused by the PR that removed function input constraint.

@xedin
Copy link
Contributor

xedin commented Nov 6, 2021

@hamishknight Since I referenced you, here is an explanation of what is going on here precisely. It's a regression cased by #39543, here - https://github.com/apple/swift/pull/39543/files#diff-5fffd7ce67aca13059738c34fbc714dcbaf3f6fe83daff7ca75836bc88304c20L1511-L1520. Constructor used to have a type variable for an argument type and now it doesn't, which means that type could flow up while generating constraints. That means that we could prefer wrong initializer if argument expression has a "common" result type. I think the PR I mentioned is correct, it's LinkedExprAnalyzer what is to blame here because it's too greedy once again...

@hborla hborla merged commit d584153 into swiftlang:main Nov 6, 2021
@hborla hborla deleted the wrong-nil-coalescing-favoring branch November 6, 2021 20:31
@hamishknight
Copy link
Contributor

I'm not sure this was caused by #39543, from what I can tell it appears to be fallout from #38836. Reverting the former didn't appear to fix the issue, but reverting the latter did.

It seems in computeFavoredTypeForExpr we can assign a favored type to a function argument, but we don't propagate it to any ParenExprs that wrap it. Therefore when walking with ConstraintOptimizer, we would previously not pick up that favored type in favorMatchingOverloadExprs, as for a unary unlabeled arg there'd be an intermediate ParenExpr. With the elimination of ParenExpr and TupleExpr argument lists however, there's no longer an intermediate ParenExpr, so we pick up the favored type.

Interestingly, there is logic in ConstraintOptimizer to propagate favored types across parens, but it happens after favorMatchingOverloadExprs. However, this means that the short-form constructor favoring logic in performMemberLookup has always been affected by this issue, for example on 5.5 this calls the optional init:

struct S {
  init(_ x: Int) { print("non-optional") }
  init(_ x: Int?) { print("optional") }
}

func foo(_ x: Int?) {
  let x = S(x ?? 0)
}

The argument list refactoring however opened this up to any unlabeled unary function call through favorMatchingOverloadExprs, not just for short-form constructor X(y) calls.

This patch fixes the above example for the ?? operator, but I wonder if there's more we should do here to mitigate the impact for user-defined operators? If we want to try and preserve the previous behavior, I guess we'd need to find a way not to run favorMatchingOverloadExprs for favored types computed by computeFavoredTypeForExpr. In general though it seems pretty worrying that computeFavoredTypeForExpr is run for arbitrary operators, maybe it should be limited to the stdlib's arithmetic operators? I'm not sure what kind of impact that would have tho.

@xedin
Copy link
Contributor

xedin commented Nov 8, 2021

@hamishknight Running this only for stdlib ones might be a good idea. We should remove the favoring from performMeberLookup too, it's not the right place for it anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants