Skip to content

Commit c7cb8ef

Browse files
committed
AST/Sema: Make MemberImportVisibility a migratable feature.
The migration to `MemberImportVisibility` can be performed mechanically by adding missing import declarations, so offer automatic migration for the feature. Resolves rdar://151931597.
1 parent 956fcde commit c7cb8ef

13 files changed

+82
-21
lines changed

include/swift/AST/DiagnosticGroups.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ GROUP(ErrorInFutureSwiftVersion, "error-in-future-swift-version")
4949
GROUP(ExistentialAny, "existential-any")
5050
GROUP(ExistentialMemberAccess, "existential-member-access-limitations")
5151
GROUP(IsolatedConformances, "isolated-conformances")
52+
GROUP(MemberImportVisibility, "member-import-visibility")
5253
GROUP(MultipleInheritance, "multiple-inheritance")
5354
GROUP(MutableGlobalVariable, "mutable-global-variable")
5455
GROUP(NominalTypes, "nominal-types")

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,10 @@ ERROR(init_candidate_inaccessible,none,
167167
"'%select{private|fileprivate|internal|package|@_spi|@_spi}1' protection level",
168168
(Type, AccessLevel))
169169

170-
ERROR(candidate_from_missing_import,none,
170+
GROUPED_ERROR(member_from_missing_import,MemberImportVisibility,none,
171171
"%kind0 is not available due to missing import of defining module %1",
172172
(const ValueDecl *, const ModuleDecl *))
173-
ERROR(candidate_from_missing_imports_2_or_more,none,
173+
GROUPED_ERROR(member_from_missing_imports_2_or_more,MemberImportVisibility,none,
174174
"%kind0 is not available due to missing imports of defining modules "
175175
"%2%select{ and|, }1 %3%select{|, and others}1",
176176
(const ValueDecl *, bool, const ModuleDecl *, const ModuleDecl *))

include/swift/Basic/Features.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ UPCOMING_FEATURE(GlobalActorIsolatedTypesUsability, 0434, 6)
287287
// Swift 7
288288
MIGRATABLE_UPCOMING_FEATURE(ExistentialAny, 335, 7)
289289
UPCOMING_FEATURE(InternalImportsByDefault, 409, 7)
290-
UPCOMING_FEATURE(MemberImportVisibility, 444, 7)
290+
MIGRATABLE_UPCOMING_FEATURE(MemberImportVisibility, 444, 7)
291291
MIGRATABLE_UPCOMING_FEATURE(InferIsolatedConformances, 470, 7)
292292
MIGRATABLE_UPCOMING_FEATURE(NonisolatedNonsendingByDefault, 461, 7)
293293

lib/AST/NameLookup.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,7 +2371,9 @@ ObjCCategoryNameMap ClassDecl::getObjCCategoryNameMap() {
23712371
/// the given context.
23722372
static bool shouldRequireImportsInContext(const DeclContext *lookupContext) {
23732373
auto &ctx = lookupContext->getASTContext();
2374-
if (!ctx.LangOpts.hasFeature(Feature::MemberImportVisibility))
2374+
2375+
if (!ctx.LangOpts.hasFeature(Feature::MemberImportVisibility,
2376+
/*allowMigration=*/true))
23752377
return false;
23762378

23772379
// Code outside of the main module (which is often synthesized) isn't subject
@@ -3591,7 +3593,8 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator,
35913593
// inaccessible due to missing imports. The missing imports will be diagnosed
35923594
// elsewhere.
35933595
if (referenced.first.empty() &&
3594-
ctx.LangOpts.hasFeature(Feature::MemberImportVisibility)) {
3596+
ctx.LangOpts.hasFeature(Feature::MemberImportVisibility,
3597+
/*allowMigration=*/true)) {
35953598
options |= DirectlyReferencedTypeLookupFlags::IgnoreMissingImports;
35963599
referenced = directReferencesForTypeRepr(evaluator, ctx, typeRepr,
35973600
ext->getParent(), options);

lib/Basic/SupportedFeatures.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ static std::vector<DiagGroupID> migratableCategories(Feature feature) {
3535
return { DiagGroupID::ExistentialAny };
3636
case Feature::InnerKind::InferIsolatedConformances:
3737
return { DiagGroupID::IsolatedConformances };
38+
case Feature::InnerKind::MemberImportVisibility:
39+
return { DiagGroupID::MemberImportVisibility };
3840
case Feature::InnerKind::NonisolatedNonsendingByDefault:
3941
return { DiagGroupID::NonisolatedNonsendingByDefault };
4042
case Feature::InnerKind::StrictMemorySafety:

lib/Sema/MiscDiagnostics.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6322,7 +6322,8 @@ static void diagnoseMissingMemberImports(const Expr *E, const DeclContext *DC) {
63226322
};
63236323

63246324
auto &ctx = DC->getASTContext();
6325-
if (!ctx.LangOpts.hasFeature(Feature::MemberImportVisibility))
6325+
if (!ctx.LangOpts.hasFeature(Feature::MemberImportVisibility,
6326+
/*allowMigration=*/true))
63266327
return;
63276328

63286329
DiagnoseWalker walker(DC);

lib/Sema/ResilienceDiagnostics.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,9 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
279279
// Some diagnostics emitted with the `MemberImportVisibility` feature enabled
280280
// subsume these diagnostics.
281281
if (originKind == DisallowedOriginKind::MissingImport &&
282-
ctx.LangOpts.hasFeature(Feature::MemberImportVisibility) && SF)
282+
ctx.LangOpts.hasFeature(Feature::MemberImportVisibility,
283+
/*allowMigration=*/true) &&
284+
SF)
283285
return false;
284286

285287
if (auto accessor = dyn_cast<AccessorDecl>(D)) {

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,7 +1532,8 @@ bool swift::checkOverrides(ValueDecl *decl) {
15321532

15331533
auto &ctx = decl->getASTContext();
15341534
if (overridden.empty() &&
1535-
ctx.LangOpts.hasFeature(Feature::MemberImportVisibility)) {
1535+
ctx.LangOpts.hasFeature(Feature::MemberImportVisibility,
1536+
/*allowMigration=*/true)) {
15361537
// If we didn't find anything, try broadening the search by ignoring missing
15371538
// imports.
15381539
if (!checkPotentialOverrides(decl, overridden,
@@ -2528,7 +2529,8 @@ OverriddenDeclsRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
25282529
// If we didn't find anything, try broadening the search by ignoring missing
25292530
// imports.
25302531
if (overridden.empty() &&
2531-
ctx.LangOpts.hasFeature(Feature::MemberImportVisibility)) {
2532+
ctx.LangOpts.hasFeature(Feature::MemberImportVisibility,
2533+
/*allowMigration=*/true)) {
25322534
overridden = computeOverriddenDecls(decl, true);
25332535
if (!overridden.empty()) {
25342536
auto first = overridden.front();

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -920,22 +920,31 @@ class MissingImportFixItCache {
920920
}
921921
};
922922

923-
static void
923+
static bool
924924
diagnoseMissingImportsForMember(const ValueDecl *decl,
925925
SmallVectorImpl<ModuleDecl *> &modulesToImport,
926926
SourceFile *sf, SourceLoc loc) {
927927
auto &ctx = sf->getASTContext();
928928
auto count = modulesToImport.size();
929929
ASSERT(count > 0);
930930

931+
bool isMigrating =
932+
ctx.LangOpts.getFeatureState(Feature::MemberImportVisibility)
933+
.isEnabledForMigration();
934+
931935
if (count > 1) {
932-
ctx.Diags.diagnose(loc, diag::candidate_from_missing_imports_2_or_more,
933-
decl, bool(count > 2), modulesToImport[0],
934-
modulesToImport[1]);
936+
ctx.Diags
937+
.diagnose(loc, diag::member_from_missing_imports_2_or_more, decl,
938+
bool(count > 2), modulesToImport[0], modulesToImport[1])
939+
.limitBehaviorIf(isMigrating, DiagnosticBehavior::Warning);
935940
} else {
936-
ctx.Diags.diagnose(loc, diag::candidate_from_missing_import, decl,
937-
modulesToImport.front());
941+
ctx.Diags
942+
.diagnose(loc, diag::member_from_missing_import, decl,
943+
modulesToImport.front())
944+
.limitBehaviorIf(isMigrating, DiagnosticBehavior::Warning);
938945
}
946+
947+
return !isMigrating;
939948
}
940949

941950
static void emitMissingImportFixIt(SourceLoc loc,
@@ -1039,8 +1048,7 @@ bool swift::maybeDiagnoseMissingImportForMember(const ValueDecl *decl,
10391048
if (modulesToImport.empty())
10401049
return false;
10411050

1042-
diagnoseMissingImportsForMember(decl, modulesToImport, sf, loc);
1043-
return true;
1051+
return diagnoseMissingImportsForMember(decl, modulesToImport, sf, loc);
10441052
}
10451053

10461054
sf->addDelayedMissingImportForMemberDiagnostic(decl, loc);

lib/Sema/TypeCheckType.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,7 +1772,8 @@ resolveUnqualifiedIdentTypeRepr(const TypeResolution &resolution,
17721772
// If the look up did not yield any results, try again but allow members from
17731773
// modules that are not directly imported to be accessible.
17741774
bool didIgnoreMissingImports = false;
1775-
if (!globals && ctx.LangOpts.hasFeature(Feature::MemberImportVisibility)) {
1775+
if (!globals && ctx.LangOpts.hasFeature(Feature::MemberImportVisibility,
1776+
/*allowMigration=*/true)) {
17761777
lookupOptions |= NameLookupFlags::IgnoreMissingImports;
17771778
globals = TypeChecker::lookupUnqualifiedType(DC, id, repr->getLoc(),
17781779
lookupOptions);
@@ -2035,8 +2036,8 @@ static Type resolveQualifiedIdentTypeRepr(const TypeResolution &resolution,
20352036
DC, parentTy, repr->getNameRef(), repr->getLoc(), lookupOptions);
20362037

20372038
// If no members were found, try ignoring missing imports.
2038-
if (!memberTypes &&
2039-
ctx.LangOpts.hasFeature(Feature::MemberImportVisibility)) {
2039+
if (!memberTypes && ctx.LangOpts.hasFeature(Feature::MemberImportVisibility,
2040+
/*allowMigration=*/true)) {
20402041
lookupOptions |= NameLookupFlags::IgnoreMissingImports;
20412042
memberTypes = TypeChecker::lookupMemberType(
20422043
DC, parentTy, repr->getNameRef(), repr->getLoc(), lookupOptions);

lib/Sema/TypeOfReference.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2698,7 +2698,8 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
26982698
increaseScore(SK_Unavailable, locator);
26992699

27002700
// If the declaration is from a module that hasn't been imported, note that.
2701-
if (getASTContext().LangOpts.hasFeature(Feature::MemberImportVisibility)) {
2701+
if (getASTContext().LangOpts.hasFeature(Feature::MemberImportVisibility,
2702+
/*allowMigration=*/true)) {
27022703
if (!useDC->isDeclImported(decl))
27032704
increaseScore(SK_MissingImport, locator);
27042705
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/MemberImportVisibility/members_A.swift
3+
// RUN: %target-swift-frontend -emit-module -I %t -o %t -package-name TestPackage %S/Inputs/MemberImportVisibility/members_B.swift
4+
// RUN: %target-swift-frontend -emit-module -I %t -o %t %S/Inputs/MemberImportVisibility/members_C.swift
5+
// RUN: %target-swift-frontend -typecheck %s -I %t -verify -swift-version 5 -enable-upcoming-feature MemberImportVisibility:migrate
6+
7+
// REQUIRES: swift_feature_MemberImportVisibility
8+
9+
import members_C
10+
// expected-note 3 {{add import of module 'members_B'}}{{1-1=internal import members_B\n}}
11+
12+
13+
func testMigration(x: X, y: Y<Z>) {
14+
x.XinA()
15+
y.YinA()
16+
17+
x.XinB() // expected-warning {{instance method 'XinB()' is not available due to missing import of defining module 'members_B'}}
18+
y.YinB() // expected-warning{{instance method 'YinB()' is not available due to missing import of defining module 'members_B'}}
19+
20+
x.XinC()
21+
y.YinC()
22+
23+
_ = X(true)
24+
_ = X(1) // expected-warning {{initializer 'init(_:)' is not available due to missing import of defining module 'members_B'}}
25+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Member import visibility
2+
3+
4+
This diagnostic group includes the errors that are emitted when a member declaration cannot be accessed because the module defining that member has not been directly imported by the file containing the reference:
5+
6+
```
7+
func getFileContents() throws -> String {
8+
// error: initializer 'init(contentsOfFile:)' is not available due to missing import of defining module 'Foundation'
9+
return try String(contentsOfFile: "example.txt")
10+
}
11+
```
12+
13+
To resolve the error, you must add an import of the module that defines the member.
14+
15+
These errors are only emitted when the `MemberImportVisibility` language mode is enabled.

0 commit comments

Comments
 (0)