Skip to content

[CodeCompletion] Ensure synthesized members are available before lookup #41735

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
Apr 15, 2022

Conversation

rintaro
Copy link
Member

@rintaro rintaro commented Mar 8, 2022

In ExprContextAnalyzer, when looking up members, some implicit members weren't populated. Ensure all implicit members available by calling 'gelAllMembers()' on the nominal type.

rdar://89773376

@rintaro
Copy link
Member Author

rintaro commented Mar 8, 2022

@swift-ci Please smoke test

@rintaro
Copy link
Member Author

rintaro commented Mar 8, 2022

@ahoppen Maybe this is not needed after we migrate PostfixExprParen to solver based (which can probably be unified with CallArg), but having a test case is a good thing.

@rintaro rintaro requested review from ahoppen and bnbarham March 8, 2022 23:23
Comment on lines 418 to 422
auto *baseNominal = baseInstanceTy->getAnyNominal();
if (baseNominal) {
// Force all implicit members synthesized before lookup.
(void)baseNominal->getAllMembers();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I found it a bit odd this wasn't already handled in the lookup. Is there a bug there? Ie. it does call NominalTypeDecl::prepareLookupTable. Is it intentional that calls getMembers rather than getAlllMembers? getMembers calls loadAllMembers but that doesn't get synthesized implicit members... How confusing

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree this is odd. I believe what is happening is that when LookupVisibleDecls does a walk over the members of a nominal it uses getMembers() and not getAllMembers(). Perhaps it should use getAllMembers() if we wish to see all possible synthesized declarations, and not just those that have been synthesized up until now.

Rintaro, do you mind investigating and pushing this down into the appropriate part of LookupVisibleDecls?

Copy link
Member Author

@rintaro rintaro Mar 14, 2022

Choose a reason for hiding this comment

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

@slavapestov FWIW, this PR is not about LookupVisibleDecls, but DeclContext::lookupQualified().

But before I opened this PR, I tested getAllMembers() in LookupVisibleDecls and eliminating our own logic force triggering synthesizing implicit members. In general, that works, but it caused circular dependency errors.

struct S {
  var value = undefined
}

When resolving undefined , the lookup fails and tries to perform typo correction (in test cases which we still do typo correction). When typo correction lookups visible decls, StructDecl("S")->getAllMembers() tries to

  • Synthesize member wise initializer which requires the type of value
  • Check automatic @Sendable conformance which requires the type of value
  • etc.

Do you have a good idea to resolve this circular dependency?

Copy link
Member Author

Choose a reason for hiding this comment

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

@bnbarham We talked about this offline, but qualified lookup (prepareLookupTable) uses getMembers() because it doesn't want synthesize all implicit members. It wants only members with the specified name. TypeChecker::lookupMember has the trick installSemanticMembersIfNeeded() which trigger the synthesis of those named members. Probably we should do similar things here instead of calling getAllMembers() which does unnecessary works.

Or, maybe we should pursue sinking this logic inside DeclContext::lookupQualified()

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, re-using installSemanticMembersIfNeeded() sounds like the correct approach. Sinking the logic down into DeclContext::lookupQualified() will probably take a lot of work to fix all the cycles.

@ahoppen
Copy link
Member

ahoppen commented Mar 14, 2022

@ahoppen Maybe this is not needed after we migrate PostfixExprParen to solver based (which can probably be unified with CallArg), but having a test case is a good thing.

Yes, I hope that we can remove ExprContextAnalysis altogether in the near future.

In ExprContextAnalyzer, when looking up members, some implicit
members weren't populated. Ensure all implicit members available by
force synthesizing them.

rdar://89773376
@rintaro rintaro force-pushed the ide-completion-rdar89773376 branch from 9ada69c to 4e62140 Compare April 15, 2022 18:48
@@ -1271,6 +1271,7 @@ func testSkippedCallArgInInvalidResultBuilderBody() {
Other(action: 2) {
MyImage(systemName: "", #^INVALID_RESULTBUILDER_ARG^#
struct Invalid
}
Copy link
Member Author

Choose a reason for hiding this comment

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

This missing } caused a test failure because extension is not allowed in a local context.

@rintaro
Copy link
Member Author

rintaro commented Apr 15, 2022

@swift-ci Please smoke test

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