Skip to content

Print proper error message when the swiftmodule for architecture not found #17092

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 10 commits into from
Jun 19, 2018

Conversation

tapthaker
Copy link
Contributor

This PR adds a diagnostic message when a .swiftmodule is found but doesn't have the same cpu architecture as the target module. It would emit message such as:
could not find module '<module_name>' for architecture 'x86_64'

Resolves SR-7160.

@tapthaker
Copy link
Contributor Author

@jrose-apple : Trying to fix the SR-7160 as we discussed in #TrySwift

// RUN: touch %t/new_module.swiftmodule/arm64.swiftmodule
// RUN: %target-swift-frontend %s -typecheck -I %t -verify -show-diagnostics-after-fatal

import new_module // expected-error {{no such module 'new_module'}} expected-error {{could not find module 'new_module' for architecture 'x86_64'}}
Copy link
Contributor

Choose a reason for hiding this comment

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

So this one statement will emit two different errors? I don't think that's usually how we do things. Maybe the statement identifying the architecture should be a note instead, or maybe the generic "no such module" error should be omitted and only the architecture one should be shown.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@brentdax : First off, nice meeting you @ tryswift :)
Makes sense to not emit 2 errors, however the way code is currently structured it is difficult to not emit the no such module 'new_module' error. That would need some level of refactoring.

Will try emitting note instead.

@@ -122,6 +124,13 @@ findModule(ASTContext &ctx, AccessPathElem moduleID,
archFile.str(), archDocFile.str(),
moduleBuffer, moduleDocBuffer,
scratch);

if(err == std::errc::no_such_file_or_directory) {
ctx.Diags.diagnose(moduleID.second, diag::sema_no_import_arch,
Copy link
Contributor

Choose a reason for hiding this comment

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

Possibly a pie-in-the-sky request, but is there some way we could identify and list the architectures which are available? That might help someone go "Oh, duh, I built the iOS one, not the Mac one".

Copy link
Contributor

Choose a reason for hiding this comment

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

You could enumerate the files under the swiftmodule's directory and do a bit of string processing to emit some notes. The cost of the enumeration should be fairly low, but the results should be cached so we keep the failure path zippy.

for (; directoryIterator != endIterator; directoryIterator.increment(errorCode)) {
auto entry = *directoryIterator;
llvm::StringRef filePath(entry.path());
foundArchs = foundArchs + (foundArchs.length() > 0 ? ", " : "")
Copy link
Contributor

Choose a reason for hiding this comment

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

A swift module contains swiftdoc files as well. This will pick those up and double-diagnose.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True. Let me add a check for that !! And update the test accordingly.


ctx.Diags.diagnose(sourceLocation, diag::sema_no_import_arch,
moduleName, archName, foundArchs);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@brentdax @CodaFi : I see 2 problems with the current implementation:

foundArchs = foundArchs + (foundArchs.length() > 0 ? ", " : "")
                        + llvm::sys::path::stem(filePath).str();

might not be the most optimal was of appending strings

  1. How do I cached the foundArchs for a module ?

Pretty new to the codebase, so any suggestions will be helpful.

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.

This is a great start, Tapan! I have a bunch of comments that hopefully aren't too burdensome. I do share the concern about emitting two separate messages, but that's something that already happens today with Clang modules that can't be loaded, so I think it's okay to deal with that in a separate SR. This is still an improvement over what's there today.

currPath);
}

return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this was supposed to go inside your new if statement, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

actually I don't need the return false; statement.

The following line should suffice

if (!err)
  return true;

@@ -562,6 +562,9 @@ ERROR(cannot_return_value_from_void_func,none,

ERROR(sema_no_import,Fatal,
"no such module '%0'", (StringRef))
NOTE(sema_no_import_arch,Fatal,
"could not find module '%0' for architecture '%1' "
"found: %2", (StringRef, StringRef, StringRef))
Copy link
Contributor

Choose a reason for hiding this comment

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

I like this touch of including the architectures that are present! Good thinking.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@brentdax's suggestion 😄

@@ -562,6 +562,9 @@ ERROR(cannot_return_value_from_void_func,none,

ERROR(sema_no_import,Fatal,
"no such module '%0'", (StringRef))
NOTE(sema_no_import_arch,Fatal,
Copy link
Contributor

Choose a reason for hiding this comment

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

This part isn't going to work, unfortunately. Notes always have to be attached to an error or warning, but one hasn't been emitted yet in this case. You'll have to make this an error on its own.

SourceLoc sourceLocation,
llvm::SmallString<64> moduleName,
llvm::SmallString<16> archName,
llvm::SmallString<128> directoryPath) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Style notes:

  • For parameters that would break the 80-column rule, please double-indent them from the left, rather than right-aligning them. (You can also use clang-format on the code you changed to match our style if you want to set that up.)
  • Since you aren't planning to modify any of these strings, the StringRef type is probably a better choice. There's an implicit conversion from SmallString and then the strings wouldn't get copied when you call the function.

true);
llvm::sys::fs::directory_iterator endIterator;

if(errorCode) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Style nitpick: please put a space after if, and check the indentation of the following lines!

}

std::string foundArchs;
for (; directoryIterator != endIterator; directoryIterator.increment(errorCode)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

You should probably stop the loop if there's ever an error, too, even if it means having to emit a more generic diagnostic.

auto entry = *directoryIterator;
llvm::StringRef filePath(entry.path());
llvm::StringRef extension = llvm::sys::path::extension(filePath);
if(extension.startswith(".") &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: Space after if again.

for (; directoryIterator != endIterator; directoryIterator.increment(errorCode)) {
auto entry = *directoryIterator;
llvm::StringRef filePath(entry.path());
llvm::StringRef extension = llvm::sys::path::extension(filePath);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: StringRef and a handful of other types from the LLVM namespace are so common that it's conventional not to use llvm:: with them in Swift code. You can see the list of such types in the "swift/Basic/LLVM.h" header.

(You'll notice SmallString is in this list too, so clearly we're not perfectly consistent about it ourselves. But StringRef is super common.)

if(extension.startswith(".") &&
extension.drop_front() == SERIALIZED_MODULE_EXTENSION) {
foundArchs = foundArchs + (foundArchs.length() > 0 ? ", " : "")
+ llvm::sys::path::stem(filePath).str();
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's okay that this isn't very efficient. It's not a diagnostic we expect people to hit very often, and failing to import something means compilation stops early anyway.

// RUN: touch %t/new_module.swiftmodule/powerpc64.swiftmodule
// RUN: touch %t/new_module.swiftmodule/arm64.swiftdoc
// RUN: touch %t/new_module.swiftmodule/powerpc64.swiftdoc
// RUN: %target-swift-frontend %s -typecheck -I %t -verify -show-diagnostics-after-fatal

This comment was marked as resolved.

@jrose-apple
Copy link
Contributor

(In particular, I still think the right answer in this case is for SerializedModuleLoader to realize it found something it couldn't load and return an empty ModuleDecl, like it does for invalid modules later on.)

@tapthaker
Copy link
Contributor Author

(In particular, I still think the right answer in this case is for SerializedModuleLoader to realize it found something it couldn't load and return an empty ModuleDecl, like it does for invalid modules later on.)

I agree, just confirming that we can implement this feature as a separate PR, right ?

// RUN: mkdir -p %t/new_module.framework/Modules/new_module.swiftmodule/
// RUN: touch %t/new_module.framework/Modules/new_module.swiftmodule/powerpc64.swiftmodule
// RUN: touch %t/new_module.framework/Modules/new_module.swiftmodule/arm64.swiftmodule
// RUN: %target-swift-frontend %s -F %t -typecheck -I %t -verify -show-diagnostics-after-fatal
Copy link
Contributor

Choose a reason for hiding this comment

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

You can drop the -I %t here.

}

return false;
if(err == std::errc::no_such_file_or_directory) {
Copy link
Contributor

Choose a reason for hiding this comment

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

(still missing a space here)

return false;
if(err == std::errc::no_such_file_or_directory) {
addDiagnosticInfoForArchitectureMismatch(
ctx, moduleID.second, moduleName, archName, currPath);
Copy link
Contributor

@jrose-apple jrose-apple Jun 12, 2018

Choose a reason for hiding this comment

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

Hm. I think we still do need to exit early, though (here and below). Otherwise we could go on to a different search path and find a different module with the same name.

(Yes, it's still possible for a different module loader to find another module with the same name right now, but I think it's okay not to worry about that at the moment.)

@tapthaker
Copy link
Contributor Author

@jrose-apple : Made the required changes.

Also, is there a linter that we could use for our cpp code ? Don't want you folks to spend time in pointing out the obvious styling issues.

@jrose-apple
Copy link
Contributor

No one's set up a linter but running your changes through clang-format would get the right style. It's a good idea, though.

@jrose-apple
Copy link
Contributor

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - ea3a9f4

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - ea3a9f4

@tapthaker
Copy link
Contributor Author

tapthaker commented Jun 13, 2018

Got the reason why the load-invalid-arch.swift test failed:
Expected:
could not find module 'new_module' for architecture 'x86_64' found: powerpc64, arm64
Got:
could not find module 'new_module' for architecture 'i386' found: powerpc64, arm64

I hardcoded the assertion for my computer. Will see if there is a template string for this.

@tapthaker
Copy link
Contributor Author

Feels like a bit indirect though

// RUN: %gyb -DTARGET_ARCHITECTURE=%target-cpu %s -o %t/load-invalid-arc.swift
// RUN: %target-swift-frontend %t/load-invalid-arc.swift -F %t -typecheck -verify -show-diagnostics-after-fatal

import new_module // expected-error {{no such module 'new_module'}} expected-error {{could not find module 'new_module' for architecture '${TARGET_ARCHITECTURE}' found: powerpc64, arm64}}
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems reasonable. Another approach would be to give up on -verify diagnostics and instead pipe the output into %FileCheck.

One note, though: we actually do run these tests for arm64 targets too, and someone could try to run them for powerpc64. It might be better to use obviously invalid architecture names instead.

@@ -562,6 +562,9 @@ ERROR(cannot_return_value_from_void_func,none,

ERROR(sema_no_import,Fatal,
"no such module '%0'", (StringRef))
ERROR(sema_no_import_arch,Fatal,
"could not find module '%0' for architecture '%1' "
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: can you add a semicolon after the '%1' here?

@tapthaker
Copy link
Contributor Author

Makes sense, adding non-existing arch : i387 & ppc65

// RUN: %gyb -DTARGET_ARCHITECTURE=%target-cpu %s -o %t/load-invalid-arc.swift
// RUN: %target-swift-frontend %t/load-invalid-arc.swift -F %t -typecheck -verify -show-diagnostics-after-fatal

import new_module // expected-error {{no such module 'new_module'}} expected-error {{could not find module 'new_module' for architecture '${TARGET_ARCHITECTURE}'; found: ppc65, i387}}
Copy link
Contributor

Choose a reason for hiding this comment

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

Ooh, just thought of another issue: the order of files returned by directory_iterator probably isn't guaranteed. We might need to switch to FileCheck and a regex match after all.

(Alternately, you could collect the names in a SmallVector and then llvm::sort them.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doesn't make sense in sorting them. Will switch to FileCheck instead.

@tapthaker
Copy link
Contributor Author

Learnt a lot about testing in Swift Complier with this PR

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.

All right, this is pretty good. Let's take it! Thanks for sticking with this through all the unexpected pitfalls and detours. :-)

@jrose-apple
Copy link
Contributor

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 4b9262e

@tapthaker
Copy link
Contributor Author

Thank you for helping me out along the way. Standby for more PRs :-)

Last question: Why do we get Build failed even when the tests are still running ?
Super confusing to me !!

@jrose-apple
Copy link
Contributor

There's a GitHub/Jenkins plugin bug where it presents the wrong commit after a force-push. We've added code to check for that circumstance and automatically restart the build in that case. You can see that if you click through into the failed build log, but it's long been on @shahmishal's queue to expose that more visibly.

@tapthaker
Copy link
Contributor Author

@jrose-apple: I think we can now merge this to master

@jrose-apple
Copy link
Contributor

Oops, sorry I let this slip! Thanks so much for working on this!

@jrose-apple jrose-apple merged commit 359385b into swiftlang:master Jun 19, 2018
@jrose-apple
Copy link
Contributor

Ah, I didn't exactly mean to do Squash and Merge, but it shouldn't harm anything.

@tapthaker
Copy link
Contributor Author

I was expecting you to Squash it 😄 . Thanks.

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.

5 participants