Skip to content

[ClangImporter] Add direct access for import-as-member types. #10956

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 5 commits into from
Jul 17, 2017

Conversation

jrose-apple
Copy link
Contributor

This avoids having to bring in all members (and extensions!) for an outer type just to look up a nested type. In the test case attached (reduced from the project in SR-5284), this actually led to a circular dependency between deserialization and the importer, which resulted in a compiler crash.

This is not a new problem, but it's more important with the release of Swift 4, where a number of Apple SDK types are now newly imported as member types. (The one in the original bug was NSView.AutoresizingMask, formerly NSAutoresizingMaskOptions.) Since we always use the Swift 4 name for cross-references, this affected everyone, even those still compiling in Swift 3 mode.

SR-5284 / rdar://problem/32926560

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test source compatibility

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 6dcd4542c8be3be857a53f39ec0c1b0edcb6ce3a
Test requested by - @jrose-apple

We use this to avoid circularity issues in serialization; we'd like to
extend that to the Clang importer. This is only necessary because we
can't look up a single member at a time, but it can still fix issues
in the short term.

This commit should have no effect on functionality.
@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 6dcd4542c8be3be857a53f39ec0c1b0edcb6ce3a
Test requested by - @jrose-apple

This avoids having to bring in all members (and extensions!) for an
outer type just to look up a nested type. In the test case attached
(reduced from the project in SR-5284), this actually led to a circular
dependency between deserialization and the importer, which resulted in
a compiler crash.

This is not a new problem, but it's more important with the release of
Swift 4, where a number of Apple SDK types are now newly imported as
member types. (The one in the original bug was
NSView.AutoresizingMask, formerly NSAutoresizingMaskOptions.) Since we
always use the Swift 4 name for cross-references, this affected
everyone, even those still compiling in Swift 3 mode.

https://bugs.swift.org/browse/SR-5284
@jrose-apple jrose-apple force-pushed the lookupNestedType-for-Clang branch from 6dcd454 to 6faac2a Compare July 14, 2017 01:01
@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test source compatibility

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 6dcd4542c8be3be857a53f39ec0c1b0edcb6ce3a
Test requested by - @jrose-apple

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 6dcd4542c8be3be857a53f39ec0c1b0edcb6ce3a
Test requested by - @jrose-apple

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test source compatibility

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test Linux

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 6faac2a3beb2b517480d4784d0d7eeae77876a99
Test requested by - @jrose-apple

@jrose-apple
Copy link
Contributor Author

I've gotten this twice now but I didn't change anything there. Very confused.

19:58:26 
lib/libswiftSema.a(TypeCheckDecl.cpp.o):/home/buildnode/jenkins/workspace/swift-PR-Linux/branch-master/swift/lib/Sema/TypeCheckDecl.cpp:function (anonymous namespace)::DeclChecker::visitClassDecl(swift::ClassDecl*): error: undefined reference to 'swift::SerializedASTFile::getLanguageVersionBuiltWith() const'
19:58:26 
lib/libswiftSema.a(TypeCheckDecl.cpp.o):/home/buildnode/jenkins/workspace/swift-PR-Linux/branch-master/swift/lib/Sema/TypeCheckDecl.cpp:function (anonymous namespace)::DeclChecker::visitClassDecl(swift::ClassDecl*): error: undefined reference to 'swift::SerializedASTFile::getLanguageVersionBuiltWith() const'

@swift-ci Please clean test Linux

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 6faac2a3beb2b517480d4784d0d7eeae77876a99
Test requested by - @jrose-apple

@jrose-apple
Copy link
Contributor Author

*sigh* #10968, though I don't know why my PR is revealing the issue.

Copy link
Member

@milseman milseman left a comment

Choose a reason for hiding this comment

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

I'm a little out of my depth reviewing this, so hopefully Doug can provide feedback as well. I do have some questions.

///
/// This is a fast-path hack to avoid circular dependencies in deserialization
/// and the Clang importer.
///
Copy link
Member

Choose a reason for hiding this comment

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

Is this used as a failable fast path? That is, if this succeeds we're fast and if it returns nullptr we go through slower lookups?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's correct. It could probably be non-failable but since the eventual goal is to remove it altogether…no reason not to be cautious.

auto *containingFile =
dyn_cast<FileUnit>(dc->getModuleScopeContext());
if (containingFile) {
nestedType = containingFile->lookupNestedType(memberName, baseType);
}
Copy link
Member

Choose a reason for hiding this comment

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

Can any of this logic be factored out into a separate function with early returns? Perhaps return when the nested type is actually found? I'm having a hard time understanding the logic here. I realized that refactoring this method is probably outside the scope of this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That would certainly be reasonable; resolveCrossReference is getting huge. But yeah, this part is supposed to be a small tweak to what's already there.

// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t -import-objc-header %t/NestedClangTypes.h -pch-output-dir %t/PCHCache %s -module-name Lib -DNO_MODULE
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -I %t -pch-output-dir %t/PCHCache -import-objc-header %t/NestedClangTypes.h %s -DCLIENT -verify

#if CLIENT
Copy link
Member

Choose a reason for hiding this comment

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

If this PR is about fast paths, then should you be testing the value of the stats like NumNestedTypeShortcuts? Or is this a correctness test?

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's a correctness test in this case; master will crash with circular dependencies without the "fast path". Maybe I should call it a "direct path".

@jrose-apple
Copy link
Contributor Author

Doug's well away on vacation by this point, so I'm unlikely to get a review from him. I'm not too worried about the serialization parts, though, and I trust you on the importer parts.

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test Linux

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 6faac2a3beb2b517480d4784d0d7eeae77876a99
Test requested by - @jrose-apple

Copy link
Member

@milseman milseman left a comment

Choose a reason for hiding this comment

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

Alright, in that case I have more questions ;-)

auto codeEnum = mutableBase->lookupDirect(name,/*ignoreNewExtensions*/true);
if (codeEnum.size() == 1 && isa<TypeDecl>(codeEnum.front()))
return cast<TypeDecl>(codeEnum.front());
if (codeEnum.size() > 1)
Copy link
Member

Choose a reason for hiding this comment

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

I'm not familiar with the role of Code in the importer. What does it mean for there to be multiple lookup results?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, so this is about how we import error enums, which come out something like this:

struct MyError : _BridgedStoredNSError {
  static let _domain: String
  var rawValue: NSError

  @objc enum Code: Int {
    case bad
    case worse
  }

  static var bad: MyError { return NSError(domain: _domain, code: Code.bad.rawValue) }
  static var worse: MyError { return NSError(domain: _domain, code: Code.worse.rawValue) }
}

However, it's possible we've just imported a struct that looks like an error enum struct (given the imperfect checks above), and that it's been extended with members named Code, possibly more than one. In that case we can't be sure this lookup is doing the right thing, and so give up on the "fast path".


if (results.size() == 1)
return results.front();
return nullptr;
Copy link
Member

Choose a reason for hiding this comment

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

Could you add a comment here? What does it mean for there to be multiple results, and why should that trigger an import failure? Would this be a mismatch between what forEachDistinctName considers distinct and what this function is looking for?

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's probably impossible for this part of the code to come back with multiple results unless the developer screwed up, but if two types in the same module were both SwiftName'd into "Outer.Inner", you'd end up in this situation. It's always better to Not Crash.

I guess that's worth a comment.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, if not also a test

Copy link
Member

@milseman milseman left a comment

Choose a reason for hiding this comment

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

LGTM, with a request for a couple comments for future-reader clarity

These are also imported as local types, so they can have the same
issues as the previous commit.
(both precompiled and non-precompiled)
Unrelated to the previous commits, but good to Not Crash.
@jrose-apple jrose-apple force-pushed the lookupNestedType-for-Clang branch from 6faac2a to 3d42828 Compare July 17, 2017 18:53
@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 6faac2a3beb2b517480d4784d0d7eeae77876a99
Test requested by - @jrose-apple

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 6faac2a3beb2b517480d4784d0d7eeae77876a99
Test requested by - @jrose-apple

@jrose-apple jrose-apple merged commit 2dbae8e into swiftlang:master Jul 17, 2017
@jrose-apple jrose-apple deleted the lookupNestedType-for-Clang branch July 17, 2017 21:02
jrose-apple added a commit to jrose-apple/swift that referenced this pull request Jul 17, 2017
…for-Clang

[ClangImporter] Add direct access for import-as-member types.
Copy link
Member

@DougGregor DougGregor left a comment

Choose a reason for hiding this comment

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

Late to the party, but LGTM

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