Skip to content

[AST] scan @_exported import modules of source files for display decls #40810

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
Jan 13, 2022

Conversation

QuietMisdreavus
Copy link
Contributor

Resolves rdar://85230067

When collecting decls for SourceFile modules, decls from @_exported import modules (including those added with -import-underlying-module) are not collected. This causes SymbolGraphGen to miss Clang symbols when building in -emit-module mode. This PR adds an override for SourceFile::getDisplayDecls (called indirectly by SymbolGraphGen) that also collects symbols from these exported modules.

@QuietMisdreavus
Copy link
Contributor Author

@swift-ci Please test

@QuietMisdreavus
Copy link
Contributor Author

@swift-ci Please build toolchain macOS platform

@QuietMisdreavus
Copy link
Contributor Author

This PR builds on top of #40696 so that i can use its test.

@QuietMisdreavus
Copy link
Contributor Author

@swift-ci Please test windows

@belkadan
Copy link
Contributor

:-/ I realize I'm well away from being a compiler contributor by now, and that getDisplayDecls was always intended to be "do the right thing for Xcode", but won't this splat all of the declarations from the ObjC half of a framework into every file of the Swift half of the framework?

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 7a9c7bd

@QuietMisdreavus
Copy link
Contributor Author

@belkadan My assumption is that because i'm pulling the imports directly from the file, it will only pull when a file has the @_exported import declaration.

...however, i'll need to double-check about the imports added by -import-underlying-module. 😅 I didn't confirm whether they're added to each file.

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 7a9c7bd

void SourceFile::getDisplayDecls(SmallVectorImpl<Decl*> &Results) const {
if (Imports.hasValue()) {
for (auto import : *Imports) {
if (import.options.contains(ImportFlags::Exported)) {
Copy link
Contributor

@slavapestov slavapestov Jan 12, 2022

Choose a reason for hiding this comment

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

Will this potentially include the same decl more than once if it's imported via two different paths, eg

// C.swift:
public class Class {}

// A.swift:
@_exported import C

// B.swift
@_exported import C

// Foo.swift
import A
import B

// does this visit 'C.Class' twice?

Perhaps a better way is to get the 'flat' list of transitively-imported modules from the ImportCache, and then just get the top-level decls of each one?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks like it will, based on how the -import-underlying-module case works (it currently crawls those modules for each file). I'll work on an alternative method to collect these modules ahead of time.

Copy link
Contributor

Choose a reason for hiding this comment

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

Try something like this

auto &importCache = sf.getASTContext().getImportCache();
auto &importSet = importCache.getImportSet(sf);
auto modules = importSet.getTransitiveImports();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are the transitive imports what we want? I'm concerned about collecting decls that aren't actually part of the file/module, since they wouldn't be @_exported.

Copy link
Contributor

Choose a reason for hiding this comment

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

The transitive imports are the @_exported ones only, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks like that includes much more than the @_exported imports; the framework from the test case seems to be including all of Foundation.

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 i have a solution, but i'm not sure where/how to test it. The symbol graph deduplicated these symbols anyway, and i'm not sure where else uses getDisplayDecls() that we could slot a test into.

Copy link
Contributor

Choose a reason for hiding this comment

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

What about something like this in getDisplayDecls():

#ifndef NDEBUG
llvm::DenseSet<Decl *> visited;
for (auto *decl : decls) {
  auto inserted = visited.insert(decl).second;
  assert(inserted);
}
#endif

Copy link
Contributor Author

@QuietMisdreavus QuietMisdreavus Jan 12, 2022

Choose a reason for hiding this comment

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

That seemed to work! I've pushed a commit with my implementation and this assertion. I've updated the test to use two Swift files, which previously caused the underlying Clang module to be scanned twice.

Copy link
Contributor

Choose a reason for hiding this comment

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

Excellent, thanks. The PR looks good to me.

@QuietMisdreavus QuietMisdreavus force-pushed the QuietMisdreavus/sourcefile-export branch from 7a9c7bd to 8a896a7 Compare January 12, 2022 23:24
@QuietMisdreavus QuietMisdreavus changed the base branch from QuietMisdreavus/symgraph-accesscontrol to main January 12, 2022 23:24
@QuietMisdreavus
Copy link
Contributor Author

@swift-ci Please test

@QuietMisdreavus
Copy link
Contributor Author

@swift-ci Please build toolchain macOS platform

@QuietMisdreavus QuietMisdreavus changed the title [AST] add a SourceFile::getDisplayDecls override that also walks @_exported imports [AST] scan @_exported import modules of source files Jan 12, 2022
@QuietMisdreavus QuietMisdreavus changed the title [AST] scan @_exported import modules of source files [AST] scan @_exported import modules of source files for display decls Jan 12, 2022
@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 8a896a7

@QuietMisdreavus
Copy link
Contributor Author

@swift-ci Please test Linux

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 8a896a7

@swift-ci
Copy link
Contributor

macOS Toolchain
Download Toolchain
Git Sha - 8a896a7

Install command
tar -zxf swift-PR-40810-1282-osx.tar.gz --directory ~/

@QuietMisdreavus QuietMisdreavus force-pushed the QuietMisdreavus/sourcefile-export branch from 8a896a7 to e04092d Compare January 13, 2022 16:02
@QuietMisdreavus
Copy link
Contributor Author

@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