Skip to content

[Clang Importer] Defer module imports to end of bridging-header parse. #7705

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

graydon
Copy link
Contributor

@graydon graydon commented Feb 23, 2017

There is a subtle incompatibility between the way bridging headers handle
module imports and the way clang's normal module-loading works (as done
by -emit-pch in bridging PCH, in particular).

When importing a submodule, Swift implicitly imports its supermodule. This
is part of Swift's treatment of modules and fine, we're not changing it
here.

But if client code imports a submodule, then tries to use a type that is
only defined in its supermodule, not the submodule, this should cause
a parse error (and does in clang alone, or when generating a PCH).
Unfortunately Swift's "implicit parent import" currently happens
eagerly, so the supermodule is imported and its type is defined as soon
as the submodule is imported, which in turn suppresses the error.

This in turn means that client code thinks their code "works" and then
"breaks" when they turn on bridging PCH. What should happen here is
that the (actually broken) client code should not be accepted in the first
place, neither bridging PCH nor textual bridging-header import.

This commit merely changes textual bridging-header import from eager
import to deferred parent-import, like bridging PCH does. This reconciles
the difference in behaviour between the two, at the cost of a source-compat
break.

rdar://30615193

@graydon graydon requested a review from jrose-apple February 23, 2017 02:38
@graydon
Copy link
Contributor Author

graydon commented Feb 23, 2017

Remaining to deal with:

  • A narrow test illustrating the problem & solution
  • A decision on whether and how to take the source-compat break (possibly put behind swift-4 mode?)

@@ -275,6 +275,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation

bool IsReadingBridgingPCH;
llvm::SmallVector<clang::serialization::SubmoduleID, 2> PCHImportedSubmodules;
llvm::SmallVector<const clang::Module*, 2> ImportedModules;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you name this DeferredHeaderImports or something? ImportedModules makes it sound like something that stays valid and makes sense to ask for for the lifetime of the ClangImporter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, will do.

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

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

Seems reasonable to me.

There is a subtle incompatibility between the way bridging headers handle
module imports and the way clang's normal module-loading works (as done
by -emit-pch in bridging PCH, in particular).

When importing a submodule, Swift implicitly imports its supermodule. This
is part of Swift's treatment of modules and fine, we're not changing it
here.

But if client code imports a submodule, then tries to use a type that is
only defined in its supermodule, not the submodule, this _should_ cause
a parse error (and does in clang alone, or when generating a PCH).
Unfortunately Swift's "implicit parent import" currently happens
eagerly, so the supermodule is imported and its type is defined as soon
as the submodule is imported, which in turn suppresses the error.

This in turn means that client code thinks their code "works" and then
"breaks" when they turn on bridging PCH. What _should_ happen here is
that the (actually broken) client code should not be accepted in the first
place, neither bridging PCH nor textual bridging-header import.

This commit merely changes textual bridging-header import from eager
import to deferred parent-import, like bridging PCH does. This reconciles
the difference in behaviour between the two, at the cost of a source-compat
break.

rdar://30615193
@graydon graydon force-pushed the rdar-30615193-defer-module-import-from-bridging-header-until-finished-parse branch from 845ae28 to 416a12e Compare February 27, 2017 23:49
@graydon
Copy link
Contributor Author

graydon commented Feb 28, 2017

Decision was to land this for swift 4 timeframe, not swift 3.1, but consider it just a bug fix (with release note), not a behaviour to preserve under compat flag.

@graydon
Copy link
Contributor Author

graydon commented Feb 28, 2017

@swift-ci please test and merge

@graydon graydon changed the title DO NOT MERGE YET: [Clang Importer] Defer module imports to end of bridging-header parse. [Clang Importer] Defer module imports to end of bridging-header parse. Feb 28, 2017
@graydon graydon merged commit 94f30aa into swiftlang:master Feb 28, 2017
@graydon graydon deleted the rdar-30615193-defer-module-import-from-bridging-header-until-finished-parse branch September 13, 2017 16:42
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