Skip to content

Sema: Fix requirement/witness disambiguation for subclass existentials [4.0] #11242

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

Conversation

slavapestov
Copy link
Contributor

@slavapestov slavapestov commented Jul 28, 2017

  • Description: If an imported Objective-C class C conforms to an Objective-C protocol Q with a requirement foo(), a member lookup of foo on a value of type C & P (where P is some unrelated protocol) would be incorrectly reported as ambiguous. This fixes the disambiguation logic that is used for such lookups on a concrete type C to also work for a subclass existential C & P.

  • Scope of the issue: This is a bug in a new feature, but in Swift 4.0 mode, we started importing Objective-C types like C <P> * as subclass existentials C & P, whereas previously we would import them as an existential type P, so code examples that worked in Swift 3.2 mode can now fail to type check.

  • Risk: Name lookup is a very tricky piece of code; hopefully the standard library, test suite and source compatibility test suite give us enough coverage here. I deliberately kept this patch for swift-4.0-branch as small as possible; there are other cleanups on master that hopefully make the logic here easier to follow and review.

  • Reviewed by: @DougGregor

  • Radar: rdar://problem/33291112.

When performing a lookup into a class C, we might find a member of
C that witnesses a requirement in a protocol Q that C conforms to.

In this case, AST name lookup returns both results.

There are two further levels of fitering which can eliminate the
ambiguity:

- Sema name lookup maps requirements to witnesses if the base type
  of the lookup is a nominal type or a class-constrained archetype.

  Imported conformances don't have this mapping recorded, but there's
  another hack in this code path where if a requirement maps to
  itself inside a conformance, it is dropped from the results
  altogether.

- If the duplicate results were not filtered out in Sema name lookup,
  there was another hack in CSRanking which would a witness higher
  than it's requirement when comparing solutions. This doesn't work
  for imported conformances, but usually name lookup filters out
  the duplicate results sooner, which also eliminates the exponential
  behavior from having multiple constraint system solutions.

However, if we have a subclass existential C & P where C conforms
to Q and we find a member of C that witnesses a requirement of Q,
then (C & P) does not conform to Q.

So if the conformance was imported, *both* of the above checks
would fail to disambiguate the witness and requirement, and the
member access would fail to type check.

To make this work with imported conformances, teach Sema name lookup
to extract the superclass from an existential before performing the
conformance check. If the conformance check fails, it means we
found the protocol member via the 'existential' part of the subclass
existential (eg, in our case, a member of P), and we proceed as
before.

Fixes <rdar://problem/33291112>.
@slavapestov slavapestov requested a review from DougGregor July 28, 2017 06:43
@slavapestov
Copy link
Contributor Author

@swift-ci Please test

@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

@slavapestov
Copy link
Contributor Author

@DougGregor Does this look OK for 4.0? Also see the cleaner LookupResultBuilder on master...

Copy link
Member

@DougGregor DougGregor left a comment

Choose a reason for hiding this comment

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

LGTM

@slavapestov slavapestov merged commit 7dc1e1e into swiftlang:swift-4.0-branch Jul 28, 2017
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.

2 participants