Skip to content

Commit 41f2504

Browse files
DougGregortshortli
authored andcommitted
Only emit error about missing import when we're missing the import
This eliminates some diagnostics that incorrectly refer to a missin `@_spi` import as an outright missing import, which is incorrect. The one test case changed here really is a case of a missing import that happens to be SPI.
1 parent 237ddb6 commit 41f2504

File tree

2 files changed

+48
-36
lines changed

2 files changed

+48
-36
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6188,49 +6188,60 @@ bool InaccessibleMemberFailure::diagnoseAsError() {
61886188
auto loc = nameLoc.isValid() ? nameLoc.getStartLoc() : ::getLoc(anchor);
61896189
auto accessLevel = Member->getFormalAccessScope().accessLevelForDiagnostics();
61906190
bool suppressDeclHereNote = false;
6191-
if (accessLevel == AccessLevel::Public) {
6191+
if (accessLevel == AccessLevel::Public &&
6192+
!Member->findImport(getDC())) {
61926193
auto definingModule = Member->getDeclContext()->getParentModule();
61936194
emitDiagnosticAt(loc, diag::candidate_from_missing_import,
61946195
Member->getDescriptiveKind(), Member->getName(),
61956196
definingModule->getName());
61966197

6197-
if (auto enclosingSF = getDC()->getParentSourceFile()) {
6198-
SourceLoc bestLoc;
6199-
SourceManager &srcMgr = Member->getASTContext().SourceMgr;
6200-
for (auto item : enclosingSF->getTopLevelItems()) {
6201-
// If we found an import declaration, we want to insert after it.
6202-
if (auto importDecl =
6203-
dyn_cast_or_null<ImportDecl>(item.dyn_cast<Decl *>())) {
6204-
SourceLoc loc = importDecl->getEndLoc();
6205-
if (loc.isValid()) {
6206-
bestLoc = Lexer::getLocForEndOfLine(srcMgr, loc);
6207-
}
6208-
6209-
// Keep looking for more import declarations.
6210-
continue;
6211-
}
6212-
6213-
// If we got a location based on import declarations, we're done.
6214-
if (bestLoc.isValid())
6215-
break;
6216-
6217-
// For any other item, we want to insert before it.
6218-
SourceLoc loc = item.getStartLoc();
6198+
auto enclosingSF = getDC()->getParentSourceFile();
6199+
SourceLoc bestLoc;
6200+
SourceManager &srcMgr = Member->getASTContext().SourceMgr;
6201+
for (auto item : enclosingSF->getTopLevelItems()) {
6202+
// If we found an import declaration, we want to insert after it.
6203+
if (auto importDecl =
6204+
dyn_cast_or_null<ImportDecl>(item.dyn_cast<Decl *>())) {
6205+
SourceLoc loc = importDecl->getEndLoc();
62196206
if (loc.isValid()) {
6220-
bestLoc = Lexer::getLocForStartOfLine(srcMgr, loc);
6221-
break;
6207+
bestLoc = Lexer::getLocForEndOfLine(srcMgr, loc);
62226208
}
6209+
6210+
// Keep looking for more import declarations.
6211+
continue;
6212+
}
6213+
6214+
// If we got a location based on import declarations, we're done.
6215+
if (bestLoc.isValid())
6216+
break;
6217+
6218+
// For any other item, we want to insert before it.
6219+
SourceLoc loc = item.getStartLoc();
6220+
if (loc.isValid()) {
6221+
bestLoc = Lexer::getLocForStartOfLine(srcMgr, loc);
6222+
break;
62236223
}
6224+
}
6225+
6226+
if (bestLoc.isValid()) {
6227+
llvm::SmallString<64> importText;
62246228

6225-
if (bestLoc.isValid()) {
6226-
llvm::SmallString<64> importText;
6227-
importText += "import ";
6228-
importText += definingModule->getName().str();
6229-
importText += "\n";
6230-
emitDiagnosticAt(bestLoc, diag::candidate_add_import,
6231-
definingModule->getName())
6232-
.fixItInsert(bestLoc, importText);
6229+
// @_spi imports.
6230+
if (Member->isSPI()) {
6231+
auto spiGroups = Member->getSPIGroups();
6232+
if (!spiGroups.empty()) {
6233+
importText += "@_spi(";
6234+
importText += spiGroups[0].str();
6235+
importText += ") ";
6236+
}
62336237
}
6238+
6239+
importText += "import ";
6240+
importText += definingModule->getName().str();
6241+
importText += "\n";
6242+
emitDiagnosticAt(bestLoc, diag::candidate_add_import,
6243+
definingModule->getName())
6244+
.fixItInsert(bestLoc, importText);
62346245
}
62356246

62366247
suppressDeclHereNote = true;
@@ -6244,7 +6255,8 @@ bool InaccessibleMemberFailure::diagnoseAsError() {
62446255
.highlight(nameLoc.getSourceRange());
62456256
}
62466257

6247-
emitDiagnosticAt(Member, diag::decl_declared_here, Member);
6258+
if (!suppressDeclHereNote)
6259+
emitDiagnosticAt(Member, diag::decl_declared_here, Member);
62486260
return true;
62496261
}
62506262

test/SPI/client_reuse_spi.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// RUN: %target-swift-frontend -typecheck -verify -verify-ignore-unknown -DLIB_C %s -I %t
77

88
#if LIB_A
9-
9+
// expected-note@-1{{add import of module 'A'}}{{1-1=@_spi(A) import A\n}}
1010
@_spi(A) public struct SecretStruct {
1111
@_spi(A) public func bar() {}
1212
}
@@ -22,7 +22,7 @@
2222
@_spi(B) import B
2323

2424
var a = foo() // OK
25-
a.bar() // expected-error{{'bar' is inaccessible due to '@_spi' protection level}}
25+
a.bar() // expected-error{{instance method 'bar()' is not available due to missing import of defining module 'A'}}
2626

2727
var b = SecretStruct() // expected-error{{cannot find 'SecretStruct' in scope}}
2828

0 commit comments

Comments
 (0)