Skip to content

Commit d002da0

Browse files
committed
AST: Add a IgnoreMissingImports option to name lookup.
Control enforcement of member import visibility requirements via a new option, instead of piggy-backing on the existing IgnoreAccessControl option. Adopt the option when doing fallback lookups for unviable members so that the compiler can diagnose the reason that a member is inaccessible more reliably. Previously, with MemberImportVisibility enabled decls with the package access level could be mis-diagnosed as inaccessible due to their access level when really they were inaccessible due to a missing import. Resolves rdar://131501862.
1 parent 10a2cde commit d002da0

18 files changed

+148
-65
lines changed

include/swift/AST/LookupKinds.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ enum NLOptions : unsigned {
6060
/// This lookup should only return macro declarations.
6161
NL_OnlyMacros = 1 << 8,
6262

63+
/// Include members that would otherwise be filtered out because they come
64+
/// from a module that has not been imported.
65+
NL_IgnoreMissingImports = 1 << 9,
66+
6367
/// The default set of options used for qualified name lookup.
6468
///
6569
/// FIXME: Eventually, add NL_ProtocolMembers to this, once all of the

include/swift/AST/NameLookup.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,10 @@ enum class UnqualifiedLookupFlags {
249249
ModuleLookup = 1 << 8,
250250
/// This lookup should discard 'Self' requirements in protocol extension
251251
/// 'where' clauses.
252-
DisregardSelfBounds = 1 << 9
252+
DisregardSelfBounds = 1 << 9,
253+
/// This lookup should include members that would otherwise be filtered out
254+
/// because they come from a module that has not been imported.
255+
IgnoreMissingImports = 1 << 10,
253256
};
254257

255258
using UnqualifiedLookupOptions = OptionSet<UnqualifiedLookupFlags>;

include/swift/Sema/CSFix.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1923,11 +1923,14 @@ class MoveOutOfOrderArgument final : public ConstraintFix {
19231923
};
19241924

19251925
class AllowInaccessibleMember final : public AllowInvalidMemberRef {
1926+
bool IsMissingImport;
1927+
19261928
AllowInaccessibleMember(ConstraintSystem &cs, Type baseType,
19271929
ValueDecl *member, DeclNameRef name,
1928-
ConstraintLocator *locator)
1930+
ConstraintLocator *locator, bool isMissingImport)
19291931
: AllowInvalidMemberRef(cs, FixKind::AllowInaccessibleMember, baseType,
1930-
member, name, locator) {}
1932+
member, name, locator),
1933+
IsMissingImport(isMissingImport) {}
19311934

19321935
public:
19331936
std::string getName() const override {
@@ -1942,7 +1945,8 @@ class AllowInaccessibleMember final : public AllowInvalidMemberRef {
19421945

19431946
static AllowInaccessibleMember *create(ConstraintSystem &cs, Type baseType,
19441947
ValueDecl *member, DeclNameRef name,
1945-
ConstraintLocator *locator);
1948+
ConstraintLocator *locator,
1949+
bool isMissingImport);
19461950

19471951
static bool classof(const ConstraintFix *fix) {
19481952
return fix->getKind() == FixKind::AllowInaccessibleMember;

include/swift/Sema/ConstraintSystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,6 +1975,10 @@ struct MemberLookupResult {
19751975
/// The member is inaccessible (e.g. a private member in another file).
19761976
UR_Inaccessible,
19771977

1978+
/// The member is not visible because it comes from a module that was not
1979+
/// imported.
1980+
UR_MissingImport,
1981+
19781982
/// This is a `WritableKeyPath` being used to look up read-only member,
19791983
/// used in situations involving dynamic member lookup via keypath,
19801984
/// because it's not known upfront what access capability would the

lib/AST/NameLookup.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2363,9 +2363,11 @@ static bool isAcceptableLookupResult(const DeclContext *dc,
23632363
if (!decl->isAccessibleFrom(dc, /*forConformance*/ false,
23642364
allowUsableFromInline))
23652365
return false;
2366+
}
23662367

2367-
// Check that there is some import in the originating context that
2368-
// makes this decl visible.
2368+
// Check that there is some import in the originating context that makes this
2369+
// decl visible.
2370+
if (!(options & NL_IgnoreMissingImports)) {
23692371
if (missingExplicitImportForMemberDecl(dc, decl))
23702372
return false;
23712373
}
@@ -3983,7 +3985,8 @@ bool IsCallAsFunctionNominalRequest::evaluate(Evaluator &evaluator,
39833985
// that will be checked when we actually try to solve with a `callAsFunction`
39843986
// member access.
39853987
SmallVector<ValueDecl *, 4> results;
3986-
auto opts = NL_QualifiedDefault | NL_ProtocolMembers | NL_IgnoreAccessControl;
3988+
auto opts = NL_QualifiedDefault | NL_ProtocolMembers |
3989+
NL_IgnoreAccessControl | NL_IgnoreMissingImports;
39873990
dc->lookupQualified(decl, DeclNameRef(ctx.Id_callAsFunction),
39883991
decl->getLoc(), opts, results);
39893992

@@ -4138,8 +4141,11 @@ void swift::simple_display(llvm::raw_ostream &out, NLOptions options) {
41384141
FLAG(NL_RemoveOverridden)
41394142
FLAG(NL_IgnoreAccessControl)
41404143
FLAG(NL_OnlyTypes)
4141-
FLAG(NL_OnlyMacros)
41424144
FLAG(NL_IncludeAttributeImplements)
4145+
FLAG(NL_IncludeUsableFromInline)
4146+
FLAG(NL_ExcludeMacroExpansions)
4147+
FLAG(NL_OnlyMacros)
4148+
FLAG(NL_IgnoreMissingImports)
41434149
#undef FLAG
41444150
};
41454151

lib/AST/UnqualifiedLookup.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,8 @@ NLOptions UnqualifiedLookupFactory::computeBaseNLOptions(
596596
baseNLOptions |= NL_OnlyMacros;
597597
if (options.contains(Flags::IgnoreAccessControl))
598598
baseNLOptions |= NL_IgnoreAccessControl;
599+
if (options.contains(Flags::IgnoreMissingImports))
600+
baseNLOptions |= NL_IgnoreMissingImports;
599601
return baseNLOptions;
600602
}
601603

lib/ClangImporter/ClangImporter.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6068,14 +6068,15 @@ static void lookupRelatedFuncs(AbstractFunctionDecl *func,
60686068
else
60696069
swiftName = func->getName();
60706070

6071+
NLOptions options = NL_IgnoreAccessControl | NL_IgnoreMissingImports;
60716072
if (auto ty = func->getDeclContext()->getSelfNominalTypeDecl()) {
60726073
ty->lookupQualified({ ty }, DeclNameRef(swiftName), func->getLoc(),
6073-
NL_QualifiedDefault | NL_IgnoreAccessControl, results);
6074+
NL_QualifiedDefault | options, results);
60746075
}
60756076
else {
60766077
auto mod = func->getDeclContext()->getParentModule();
60776078
mod->lookupQualified(mod, DeclNameRef(swiftName), func->getLoc(),
6078-
NL_RemoveOverridden | NL_IgnoreAccessControl, results);
6079+
NL_RemoveOverridden | options, results);
60796080
}
60806081
}
60816082

lib/Sema/CSDiagnostics.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6187,11 +6187,12 @@ bool InaccessibleMemberFailure::diagnoseAsError() {
61876187
}
61886188

61896189
auto loc = nameLoc.isValid() ? nameLoc.getStartLoc() : ::getLoc(anchor);
6190-
auto accessLevel = Member->getFormalAccessScope().accessLevelForDiagnostics();
6191-
if (accessLevel == AccessLevel::Public &&
6192-
diagnoseMissingImportForMember(Member, getDC(), loc))
6190+
if (IsMissingImport) {
6191+
diagnoseMissingImportForMember(Member, getDC(), loc);
61936192
return true;
6193+
}
61946194

6195+
auto accessLevel = Member->getFormalAccessScope().accessLevelForDiagnostics();
61956196
if (auto *CD = dyn_cast<ConstructorDecl>(Member)) {
61966197
emitDiagnosticAt(loc, diag::init_candidate_inaccessible,
61976198
CD->getResultInterfaceType(), accessLevel)

lib/Sema/CSDiagnostics.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,11 +1638,13 @@ class ClosureParamDestructuringFailure final : public FailureDiagnostic {
16381638
/// ```
16391639
class InaccessibleMemberFailure final : public FailureDiagnostic {
16401640
ValueDecl *Member;
1641+
bool IsMissingImport;
16411642

16421643
public:
16431644
InaccessibleMemberFailure(const Solution &solution, ValueDecl *member,
1644-
ConstraintLocator *locator)
1645-
: FailureDiagnostic(solution, locator), Member(member) {}
1645+
ConstraintLocator *locator, bool isMissingImport)
1646+
: FailureDiagnostic(solution, locator), Member(member),
1647+
IsMissingImport(isMissingImport) {}
16461648

16471649
bool diagnoseAsError() override;
16481650
};

lib/Sema/CSFix.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,16 +1152,16 @@ MoveOutOfOrderArgument *MoveOutOfOrderArgument::create(
11521152

11531153
bool AllowInaccessibleMember::diagnose(const Solution &solution,
11541154
bool asNote) const {
1155-
InaccessibleMemberFailure failure(solution, getMember(), getLocator());
1155+
InaccessibleMemberFailure failure(solution, getMember(), getLocator(),
1156+
IsMissingImport);
11561157
return failure.diagnose(asNote);
11571158
}
11581159

1159-
AllowInaccessibleMember *
1160-
AllowInaccessibleMember::create(ConstraintSystem &cs, Type baseType,
1161-
ValueDecl *member, DeclNameRef name,
1162-
ConstraintLocator *locator) {
1163-
return new (cs.getAllocator())
1164-
AllowInaccessibleMember(cs, baseType, member, name, locator);
1160+
AllowInaccessibleMember *AllowInaccessibleMember::create(
1161+
ConstraintSystem &cs, Type baseType, ValueDecl *member, DeclNameRef name,
1162+
ConstraintLocator *locator, bool isMissingImport) {
1163+
return new (cs.getAllocator()) AllowInaccessibleMember(
1164+
cs, baseType, member, name, locator, isMissingImport);
11651165
}
11661166

11671167
bool AllowAnyObjectKeyPathRoot::diagnose(const Solution &solution,

0 commit comments

Comments
 (0)