Skip to content

[ConstraintSystem] Overhaul ambiguity diagnostics #31713

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 22 commits into from
Jun 16, 2020

Conversation

xedin
Copy link
Contributor

@xedin xedin commented May 11, 2020

  • Don't attempt to rank solutions based on overloads if they have fixes
  • Factor out overload ambiguity diagnostics
  • Switch to a different algorithm:
    • Aggregate all of the available fixes based on callee locator;
    • For each ambiguous overload match aggregated fixes and diagnose;
    • Discard all of the fixes which have been already considered
      as part of overload diagnostics;
    • Diagnose remaining (uniqued based on kind + locator) fixes
      iff they appear in all of the solutions.

Resolves: SR-12689
Resolves: rdar://problem/62481592

@xedin xedin requested a review from hborla May 11, 2020 20:57
@xedin
Copy link
Contributor Author

xedin commented May 11, 2020

/cc @LucianoPAlmeida

@xedin
Copy link
Contributor Author

xedin commented May 11, 2020

This is still a WIP because we need to implement diagnoseForAmbiguity for some of the fixes e.g. treat r-value as l-value and do other work, but I'd like to get some initial feedback on this to make sure that everybody on the same page.

auto aggregate = fixes->second;
diagnosed |= ::diagnoseAmbiguity(*this, ambiguity, aggregate, solutions);

consideredFixes.insert(aggregate.begin(), aggregate.end());
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if In the cases where diagnoseAmbiguity returns false(if there's any) ... since we are adding them independently it maybe is a problem since they would be dropped from fixes undiagnosed? If there are such cases, maybe we should let them to attempt diagnose by kind?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reason why I did that is related to the fact that it could be a bunch of different fixes all related to the same callee e.g. 1 + "" would produce one fix for first argument and one for second. Even if we didn't produce ambiguity related to overload in such case keeping them around wouldn't help to diagnose anything later because there is going to be no intersection so it's better to produce "I don't know" diagnostic and figure out case by case what went wrong...

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah makes sense, I think I actually have seen situations like that too in SR-12689. I was just worried that it may end up discarding useful fixes in some way... but now I see the point :)

Copy link
Member

@hborla hborla left a comment

Choose a reason for hiding this comment

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

The new approach looks great!

xedin added 18 commits June 12, 2020 11:46
…r fix diagnostics have failed

If there are multiple solutions with fixes, let's not try to rank
them based on overload choices because doing so would filter out
viable candidates.
Refactor `diagnoseAmbiguityWithFixes` as follows:

- Aggregate all of the available fixes based on callee locator;
- For each ambiguous overload match aggregated fixes and diagnose;
- Discard all of the fixes which have been already considered
  as part of overload diagnostics;
- Diagnose remaining (uniqued based on kind + locator) fixes
  iff they appear in all of the solutions.
…irements

If there is a conditional requirement failure associated with
member/function reference used in a call let's increase a score
of a fix for such failure because it renders member/function
unreachable in current context or with a given set of arguments.
…t specially

If aggregate fix (based on callee locator) differs only in picked
overload choices, let's diagnose that via `diagnoseForAmbiguity`
associated with a particular fix kind all solutions share, that
would produce a tailored diagnostic instead of the most general one.
…pe before diagnosing ambiguity

Instead of requiring sub-classes of `ContextualMismatch` to implement
`diagnoseForAmbiguity` let's implement it directly on `ContextualMismatch`
itself and check whether all of the aggregated fixes have same types on
both sides and if so, diagnose as-if it was a single fix.
…Ambiguity`

For cases like this:

```swift
struct X {}
struct Y {}

func overloaded<T>(_ value: T) -> T { value }
func overloaded<T>(_ value: T) -> Int { 0 }

func test(x: inout X, y: Y) {
  x = overloaded(y)
}
```

Solver would record a `IgnoreAssignmentDestinationType` fix per overload,
`diagnoseForAmbiguity` could be used to properly diagnose ambiguity cases
like that.
…with a known foundation type

Just like we already do for stdlib types, extend impact of missing
conformances on _known_ foundation types because it's unlikely to
be a valid suggestion to extend a foundation type with a new conformance.
@xedin xedin force-pushed the no-ranking-with-ambiguous-with-fixes branch from a01984e to 82fcee7 Compare June 12, 2020 20:13
xedin added 3 commits June 12, 2020 14:59
…ment positions

If parameter has a function type and no argument overload choices
match let's diagnose that specifically.

Resolves: [SR-12689](https://bugs.swift.org/browse/SR-12689)
Resolves: rdar://problem/62481592
@xedin xedin marked this pull request as ready for review June 12, 2020 22:10
@xedin
Copy link
Contributor Author

xedin commented Jun 12, 2020

This PR is finally ready for review. @LucianoPAlmeida this PR incorporates a fix for SR-12689 which means that it supersedes #31359

@LucianoPAlmeida
Copy link
Contributor

This PR is finally ready for review. @LucianoPAlmeida this PR incorporates a fix for SR-12689 which means that it supersedes #31359

Awesome @xedin \o/
Not sure if you've seen, but I left a comment on that PR few days ago with another SR that I believe may be fixed by these changes too, so maybe you can take a look if thats the case and add the regression test as well :)

@xedin
Copy link
Contributor Author

xedin commented Jun 12, 2020

@LucianoPAlmeida I've seen it, thanks! I think it's a different problem those, we'd need to split LabelingFailure into one-per-mismatch, that way we could diagnose cases like that better...

@LucianoPAlmeida
Copy link
Contributor

@LucianoPAlmeida I've seen it, thanks! I think it's a different problem those, we'd need to split LabelingFailure into one-per-mismatch, that way we could diagnose cases like that better...

Ahh I see, but that's fine ... thanks for verifying :))

@@ -323,12 +323,12 @@ class TestOverloadSets {
self.init(5, 5) // expected-error{{extra argument in call}}
}

convenience init(a : Z0) { // expected-note{{candidate has partially matching parameter list (a: Z0)}}
convenience init(a : Z0) { // expected-note{{candidate expects value of type 'Z0' for parameter #1}}
Copy link
Contributor

Choose a reason for hiding this comment

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

From what I remember from the other PR, the calls that trigger those have also a relabel fix alongside the argument mismatch. I think this is fine, but do you think to mention that in some way could be valid in those situations?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't really know, this is something I was thinking about as well. I don't really like partially matching parameter list note because it's as un-actionable as it gets but I don't know how to also mention a label here. It would be very unfortunate to produce two diagnostics/notes - one for labeling and one for type because that would be confusing...

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I agree that show two notes wouldn't be ideal. But in the other PR I also thought that partially matching parameter list was not ideal, but I did choose to show the relabel diagnostic, but to be honest there was no particular reason other than is better than partially matching parameter list. But in fact neither correct the type or relabel the call would fix the problem by itself because both type and label are wrong in this situation.
I've been thinking about it and also not sure how to mention the label and also don't know how much we are loosing not showing one of them ... probably not much since as you mention both are actionable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we could re-visit this once it's possible to produce a fix per label mismatch, that way we could probably coalesce type and label mismatch for each argument and produce a much better note...

@xedin
Copy link
Contributor Author

xedin commented Jun 15, 2020

@swift-ci please smoke test

@xedin
Copy link
Contributor Author

xedin commented Jun 16, 2020

@swift-ci please smoke test Linux platform

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.

5 participants