Skip to content

Commit ba62465

Browse files
authored
Merge pull request #84259 from tshortli/member-import-visibility-migrate-crash
Sema: Fix a crash in migrate mode for `MemberImportVisibility`
2 parents 255c460 + d8fac32 commit ba62465

File tree

3 files changed

+65
-22
lines changed

3 files changed

+65
-22
lines changed

lib/Sema/PreCheckTarget.cpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
568568
// chance to diagnose name shadowing which requires explicit
569569
// name/module qualifier to access top-level name.
570570
lookupOptions |= NameLookupFlags::IncludeOuterResults;
571+
lookupOptions |= NameLookupFlags::IgnoreMissingImports;
571572

572573
LookupResult Lookup;
573574

@@ -662,19 +663,6 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
662663
return errorResult();
663664
}
664665

665-
// Try ignoring missing imports.
666-
relookupOptions |= NameLookupFlags::IgnoreMissingImports;
667-
auto nonImportedResults =
668-
TypeChecker::lookupUnqualified(DC, LookupName, Loc, relookupOptions);
669-
if (nonImportedResults) {
670-
const ValueDecl *first = nonImportedResults.front().getValueDecl();
671-
maybeDiagnoseMissingImportForMember(first, DC, Loc);
672-
673-
// Don't try to recover here; we'll get more access-related diagnostics
674-
// downstream if the type of the inaccessible decl is also inaccessible.
675-
return errorResult();
676-
}
677-
678666
// TODO: Name will be a compound name if it was written explicitly as
679667
// one, but we should also try to propagate labels into this.
680668
DeclNameLoc nameLoc = UDRE->getNameLoc();
@@ -791,14 +779,21 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
791779
// FIXME: Need to refactor the way we build an AST node from a lookup result!
792780

793781
auto buildTypeExpr = [&](TypeDecl *D) -> Expr * {
782+
auto *LookupDC = Lookup[0].getDeclContext();
783+
784+
// If the type decl is a member that wasn't imported, diagnose it now when
785+
// MemberImportVisibility is enabled.
786+
if (!UDRE->isImplicit() && LookupDC)
787+
maybeDiagnoseMissingImportForMember(D, LookupDC,
788+
UDRE->getNameLoc().getStartLoc());
789+
794790
// FIXME: This is odd.
795791
if (isa<ModuleDecl>(D)) {
796792
return new (Context) DeclRefExpr(
797793
D, UDRE->getNameLoc(),
798794
/*Implicit=*/false, AccessSemantics::Ordinary, D->getInterfaceType());
799795
}
800796

801-
auto *LookupDC = Lookup[0].getDeclContext();
802797
bool makeTypeValue = false;
803798

804799
if (isa<GenericTypeParamDecl>(D) &&
@@ -890,6 +885,13 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
890885
DC, UDRE->getNameLoc().getBaseNameLoc(), ResultValues);
891886
}
892887

888+
// If there is a single result and it's a member that wasn't imported,
889+
// diagnose it now when MemberImportVisibility is enabled.
890+
if (ResultValues.size() == 1) {
891+
maybeDiagnoseMissingImportForMember(ResultValues.front(), DC,
892+
UDRE->getNameLoc().getStartLoc());
893+
}
894+
893895
return buildRefExpr(ResultValues, DC, UDRE->getNameLoc(),
894896
UDRE->isImplicit(), UDRE->getFunctionRefInfo());
895897
}

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,11 +1013,26 @@ bool swift::maybeDiagnoseMissingImportForMember(const ValueDecl *decl,
10131013
const DeclContext *dc,
10141014
SourceLoc loc,
10151015
DiagnosticBehavior limit) {
1016+
// Only diagnose references in source files.
1017+
auto sf = dc->getParentSourceFile();
1018+
if (!sf)
1019+
return false;
1020+
1021+
auto &ctx = dc->getASTContext();
1022+
if (!ctx.LangOpts.hasFeature(Feature::MemberImportVisibility,
1023+
/*allowMigration=*/true))
1024+
return false;
1025+
1026+
// Only diagnose members.
1027+
if (!decl->getDeclContext()->isTypeContext())
1028+
return false;
1029+
1030+
// Only diagnose declarations that haven't been imported.
10161031
if (dc->isDeclImported(decl))
10171032
return false;
10181033

10191034
auto definingModule = decl->getModuleContextForNameLookup();
1020-
if (dc->getASTContext().LangOpts.EnableCXXInterop) {
1035+
if (ctx.LangOpts.EnableCXXInterop) {
10211036
// With Cxx interop enabled, there are some declarations that always belong
10221037
// to the Clang header import module which should always be implicitly
10231038
// visible. However, that module is not implicitly imported in source files
@@ -1026,12 +1041,6 @@ bool swift::maybeDiagnoseMissingImportForMember(const ValueDecl *decl,
10261041
return false;
10271042
}
10281043

1029-
auto sf = dc->getParentSourceFile();
1030-
if (!sf)
1031-
return false;
1032-
1033-
auto &ctx = dc->getASTContext();
1034-
10351044
// In lazy typechecking mode just emit the diagnostic immediately without a
10361045
// fix-it since there won't be an opportunity to emit delayed diagnostics.
10371046
if (ctx.TypeCheckerOpts.EnableLazyTypecheck) {

test/NameLookup/member_import_visibility_migrate.swift

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// RUN: %target-swift-frontend -emit-module -o %t %t/InternalUsesOnlyDefaultedImportSPIOnly.swift -I %t
1515
// RUN: %target-swift-frontend -emit-module -o %t %t/PublicUsesOnlySPIOnly.swift -I %t
1616

17-
// RUN: %target-swift-frontend -typecheck -verify -swift-version 5 \
17+
// RUN: %target-swift-frontend -emit-silgen -verify -swift-version 5 \
1818
// RUN: -primary-file %t/main.swift \
1919
// RUN: %t/imports.swift \
2020
// RUN: -I %t -package-name Package \
@@ -81,6 +81,31 @@ extension Int {
8181
internal func usesTypealiasInMixedUses_Internal(x: TypealiasInMixedUses) {} // expected-note {{type alias 'TypealiasInMixedUses' from 'MixedUses' used here}}
8282
}
8383

84+
struct GenericType<T> { }
85+
86+
extension Int {
87+
var referencesMemberInInternalUsesOnly: Int { memberInInternalUsesOnly } // expected-note {{property 'memberInInternalUsesOnly' from 'InternalUsesOnly' used here}}
88+
89+
func testTypes<T: ProtocolInInternalUsesOnly>(_ t: T) -> TypealiasInInternalUsesOnly? {
90+
// expected-note@-1 {{protocol 'ProtocolInInternalUsesOnly' from 'InternalUsesOnly' used here}}
91+
// expected-note@-2 {{type alias 'TypealiasInInternalUsesOnly' from 'InternalUsesOnly' used here}}
92+
93+
let _: TypealiasInInternalUsesOnly = 0 // expected-note {{type alias 'TypealiasInInternalUsesOnly' from 'InternalUsesOnly' used here}}
94+
_ = TypealiasInInternalUsesOnly.self // expected-note {{type alias 'TypealiasInInternalUsesOnly' from 'InternalUsesOnly' used here}}
95+
_ = (TypealiasInInternalUsesOnly).self // expected-note {{type alias 'TypealiasInInternalUsesOnly' from 'InternalUsesOnly' used here}}
96+
_ = (Int, TypealiasInInternalUsesOnly).self // expected-note {{type alias 'TypealiasInInternalUsesOnly' from 'InternalUsesOnly' used here}}
97+
_ = GenericType<TypealiasInInternalUsesOnly>.self // expected-note {{type alias 'TypealiasInInternalUsesOnly' from 'InternalUsesOnly' used here}}
98+
return t as? TypealiasInInternalUsesOnly // expected-note {{type alias 'TypealiasInInternalUsesOnly' from 'InternalUsesOnly' used here}}
99+
}
100+
101+
func testLeadingDotSyntax() {
102+
func takesP<T: ProtocolInInternalUsesOnly>(_: T) { } // expected-note {{protocol 'ProtocolInInternalUsesOnly' from 'InternalUsesOnly' used here}}
103+
takesP(.staticDefaultMemberInInternalUsesOnly) // expected-note {{static property 'staticDefaultMemberInInternalUsesOnly' from 'InternalUsesOnly' used here}}
104+
}
105+
}
106+
107+
extension Int.TypealiasInInternalUsesOnly { } // expected-note {{type alias 'TypealiasInInternalUsesOnly' from 'InternalUsesOnly' used here}}
108+
84109
//--- imports.swift
85110

86111
internal import InternalUsesOnly
@@ -97,10 +122,17 @@ internal import ImportsOtherModules
97122
//--- InternalUsesOnly.swift
98123

99124
extension Int {
125+
public protocol ProtocolInInternalUsesOnly { }
100126
public typealias TypealiasInInternalUsesOnly = Self
101127
public var memberInInternalUsesOnly: Int { return self }
102128
}
103129

130+
extension Int: Int.ProtocolInInternalUsesOnly { }
131+
132+
extension Int.ProtocolInInternalUsesOnly where Self == Int {
133+
public static var staticDefaultMemberInInternalUsesOnly: Int { 0 }
134+
}
135+
104136
//--- InternalUsesOnlyDefaultedImport.swift
105137

106138
extension Int {

0 commit comments

Comments
 (0)