-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Fix some SourceKit assertion hits #28226
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
@swift-ci please test |
The Ideally keep the existing behaviour, but restoring the older syntactic algorithm would be OK --- though there was some fallout for us when this last changed. @marcelofabri fyi |
@johnfairh The problem is that the result of this key would not have been stable. There wasn’t a previous syntactic algorithm, there was only a quasi-semantic algorithm that used to get silently bounced out of the type checker with a null answer and whatever fallback that path gave you. |
Right; I think the 'previous syntactic' version that Nathan mentioned is the |
16 SwiftLint rules use this, as well as Jazzy. Even though this key would not be stable, I don't remember ever seeing any false positives caused by this. cc @jpsim |
Ah ok, thanks @johnfairh! I'll see if @CodaFi's suggestion works because that will probably have less change in behavior and go back to the |
8b9506e
to
dd9e118
Compare
The type checker fixes in this round of changers LGTM |
@swift-ci please test |
Build failed |
Build failed |
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.
Formalizing this: TypeChecker parts LGTM. Can't speak for the syntax model.
It was being used purely to get the name of the type context for a diagnostic message. SourceKit's syntactic-only requests were hitting an assertion when this diagnostic was triggered because they don't set up a type checker.
SourceKit doesn't install a typechecker for its syntactic requests so was hitting assertions in these methods if any typechecking was triggered.
dd9e118
to
e8616dc
Compare
Ok, so after thinking about this a bit more I don't think we can keep using The newest commit stops binding extensions and restores the equivalent of the old @slavapestov are you ok with this? Or should I try to parameterize |
@swift-ci please test |
Build failed |
Build failed |
It looks like we recently started binding extensions to their nominals in order to continue to compute access levels via ValueDecl::getFormalAccess() after an assertion was added to enforce that bindExtensions had been called before anything tried to call ExtensionDecl::getBoundNominal() - which getFormalAccess() depends on. Sourcekitd's syntactic requests are made on every keypress in the editor though, so we shouldn't do any name binding (which may require module loading) to keep them as fast as possible. This patch restores the old inferAccessLevel() functions we used prior to the switch to ValueDecl::getFormalAccess() (plus a few fixes) that does as much as it can syntactically, without any name binding, and simply doesn't report the access level in cases where it couldn't be computed without name-binding. This also fixes an assertion hit we were getting trying to bind extensions in inactive ifconfig clauses, which ASTScope doesn't support. Resolves rdar://problem/57202584
e8616dc
to
11d20b8
Compare
@swift-ci please test |
Build failed |
Build failed |
if (D->getKind() == DeclKind::Destructor || | ||
D->getKind() == DeclKind::EnumElement) { | ||
if (auto container = dyn_cast<NominalTypeDecl>(D->getDeclContext())) | ||
return std::max(container->getFormalAccess(), AccessLevel::Internal); |
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.
Should this be calling inferAccessSyntactically()
again instead of getFormalAccess()
?
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.
Yes! Thanks – I'll add a test case and fix.
It should have been recursing into inferAccessSyntactically() to avoid any chance of triggering name lookup.
@swift-ci please test |
Build failed |
Build failed |
Going to go ahead and merge this to let SourceKit stress tester CI job progress a little further, but if there are any further comments let me know and I'll address them in a follow-up PR. |
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 think this is fine in principle, but I'm wondering why do you need the access level at all for 'syntactic' requests?
Ideally we wouldn't. I'd like to remove it, and did in an earlier version of this PR but it's been in the SourceKit response since Swift was open sourced and from what others have said earlier in the comments several open source tools like SwiftLint and Jazzy currently rely on it. Longer term I think it'd be good if we could remove these syntactic requests completely in favor of using SwiftSyntax. |
Those open source tools can certainly evolve and use preferred mechanisms to access that information. That migration path isn't completely clear to me, especially as SwiftSyntax grows its capabilities to match everything SourceKit's syntactic requests can provide. |
SourceKit's purely syntactic requests don't install a type-checker and so were hitting the below assertion in
ValueDecl::getInterfaceType()
when they inadvertently invoked some logic that required a type-checker:This was happening in calls to:
FuncDecl::isStatic()
, which was callinggetInterfaceType()
unnecessarily in order to print it in a diagnostic message.ASTVerifier::verifyParsed()
for initializers and deinitializers which both callisInvalid()
when theinit
/deinit
isn't contained in a type/class decl. I just removed these checks since they're already being checked inASTVerifier::verifyChecked()
as well.ValueDecl::getFormalAccess()
to provide the access level in the document structure response.We could avoid this by approximating the access level syntactically, and actually used to do this before getFormalAccess was requestified, but the access level info doesn't seem like it's being used anywhere (at least not in Xcode or Swift Playgrounds) so I just removed it.This method was callingThis method callsisInvalid()
too (which I've replaced with what is hopefully an equivalent check), and also hit problems in inactive ifconfig clauses. It asserts that extensions are already bound and they're not in inactive ifconfig clauses (ASTScope doesn't support this at the moment).isInvalid()
too (though doesn't need to) but also triggers a different assertion if extensions aren't bound, and we don't want to do that here for performance reasons (these requests run on every keypress in the editor). I've resurrected the oldinferAccessLevel()
logic we used to use prior togetFormalAccess()
.Resolves rdar://problem/57202584