Skip to content

Index synthesized wrapper refs by substituting the Clang decl. #80074

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 3 commits into from
Mar 25, 2025

Conversation

dylansturg
Copy link
Contributor

@dylansturg dylansturg commented Mar 18, 2025

The goal of this change is replace the references to synthesized declarations, whose definitions are never contained in the indexstore, with references to the underlying declarations which are contained in the indexstore. The current behavior prevents code navigation from the references to the declaration.

Reference: #79912

  • I added the EnumElementDecl generated from the underlying Clang EnumConstantDecl to the imported decl cache for ClangImporter.
  • I took the effective Clang node and corresponding imported decl to substitute for "synthesized wrapper decls".

This has a weird outcome, where a reference to the Code enum inside of the synthesized struct can emit 2 references to the underlying enum. There's an example in the test case, where TestError.Code is referenced.

Fixes #79912

Copy link
Contributor

@bnbarham bnbarham left a comment

Choose a reason for hiding this comment

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

As I was looking at this I was wondering how/if cursor info handles this case. That then brought me to https://github.com/swiftlang/swift/blob/main/lib/AST/USRGeneration.cpp#L187 (added in 62f30d5).

We've apparently run into this before, where previously both the static variable and the enumerator had the same USR and that causes other issues (as then there's no way to uniquely identify the struct/enum and property/enumerator). I need to think about this a bit more - the USR returned from cursor info for these has to match the USR we add to the index.

@dylansturg
Copy link
Contributor Author

I had also considered emitting index data for the synthesized declarations. It became complex because the Swift indexing components don't emit ideal data from the Module with the Clang decls. For example, file references are disabled when indexing a module without Swift source files.

I think it could make sense to emit the synthesized declarations. I previously enabled that for decls synthesized from Swift (e.g. the synthesized Codable conformance).

@bnbarham
Copy link
Contributor

I think my preference here would just be to move that USR adjustment logic into initDocEntityInfo only. Then everything else should just work the way you'd expect?

@dylansturg
Copy link
Contributor Author

I think my preference here would just be to move that USR adjustment logic into initDocEntityInfo only.

Is the intent for the USR for the synthesized struct type and its static accessors use the USRs of the Clang enum and enum constants (respectively), for the index data and cursor info? And in the doc info output, the struct and accessors have unique USRs that are different from the underlying Clang enum and enum constants?

That seems feasible but I'm not sure how to move that USR adjustment. After I remove the adjustment logic from USRGenerationRequest, then requests will use the underlying Clang node to generate a USR for the static accessors. Which is reasonable when generating index data. When initDocEntityInfo needs the Swift USR for the static accessors and wants to ignore the Clang node, does it need to generate the USR in a different way because USRGenerationRequest is going to use the underlying Clang node?

@bnbarham
Copy link
Contributor

Is the intent for the USR for the synthesized struct type and its static accessors use the USRs of the Clang enum and enum constants (respectively), for the index data and cursor info?

Yeah, for anything that doesn't specifically need the synthesized Swift declarations, which is just documentation I believe (so doc info + symbol graph).

That seems feasible but I'm not sure how to move that USR adjustment

I don't have much better of an idea here other than passing a flag through (and then we could keep it there). Pretty ugly though :( Any other ideas @hamishknight?

@dylansturg
Copy link
Contributor Author

Yeah, for anything that doesn't specifically need the synthesized Swift declarations, which is just documentation I believe (so doc info + symbol graph).

That sounds reasonable to me. I added a flag and, I think, got it working in those places. I noticed that symbol graph wasn't specifically testing for the USR of the synthesized declarations, so I updated the relevant test to check that.

I wrote the USRGenerationOptions to try have a single point of documentation for the emit_synthesized_decls flag plus allow for some flexibility in the future. But using it in the various print*USR APIs proved fairly painful so I just kept the simple bool. I'm open to other approaches there.

@bnbarham Can you take another look and let me know what you think? Thanks!

@hamishknight
Copy link
Contributor

I don't have much better of an idea here other than passing a flag through (and then we could keep it there). Pretty ugly though :( Any other ideas @hamishknight?

Yeah, I'm okay with passing a flag through

…equesting the Swift USR.

The Error enum synthesized declarations, e.g. the struct and its static accessors, should generally appear to be identical to the underlying Clang definitions. There are some specific use cases where the synthesized declarations are necessary though.

I've added an option for USR generation to override the Clang node and emit the USR of the synthesized Swift declaration. This is used by SwiftDocSupport so that the USRs of the synthesized declarations are emitted.

Fixes 79912
@dylansturg
Copy link
Contributor Author

I think I have everything updated. Please take another look. Thanks!

Copy link
Contributor

@hamishknight hamishknight left a comment

Choose a reason for hiding this comment

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

One last comment, but otherwise this LGTM, thanks!

Comment on lines +21 to +25
// MyError
// CHECK-DAG: "precise": "s:SC11MyErrorCodeLeV"

// MyError.errFirst
// CHECK-DAG: "precise": "s:SC11MyErrorCodeLeV8errFirstSoAAVvpZ"
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for updating this test! This would have been my only concern with this PR, but it looks like that's settled.

Copy link
Contributor

@bnbarham bnbarham left a comment

Choose a reason for hiding this comment

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

One tiny fix-up, otherwise LGTM. Thanks @dylansturg!

@hamishknight
Copy link
Contributor

@swift-ci please test

@drexin
Copy link
Contributor

drexin commented Mar 24, 2025

@swift-ci test

@hamishknight hamishknight merged commit 2c8e337 into swiftlang:main Mar 25, 2025
5 checks passed
@dylansturg dylansturg deleted the objc_enum_refs branch March 25, 2025 20:23
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.

Index data is missing a definition for NS_ERROR_ENUM synthesized accessors
5 participants