Skip to content

Commit 178315e

Browse files
committed
Sema: Look through missing imports during qualified type lookup.
To improve knock-on diagnostics, resolve qualified types to their matching member type declarations regardless of whether an import is missing when the `MemberImportVisibility` features is enabled. Part of rdar://126637855.
1 parent 3d0cf98 commit 178315e

File tree

2 files changed

+78
-16
lines changed

2 files changed

+78
-16
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,19 +1472,6 @@ static Type diagnoseUnknownType(const TypeResolution &resolution,
14721472
return ErrorType::get(ctx);
14731473
}
14741474

1475-
// Try ignoring missing imports.
1476-
relookupOptions |= NameLookupFlags::IgnoreMissingImports;
1477-
auto nonImportedMembers = TypeChecker::lookupMemberType(
1478-
dc, parentType, repr->getNameRef(), repr->getLoc(), relookupOptions);
1479-
if (nonImportedMembers) {
1480-
const TypeDecl *first = nonImportedMembers.front().Member;
1481-
auto nameLoc = repr->getNameLoc();
1482-
maybeDiagnoseMissingImportForMember(first, dc, nameLoc.getStartLoc());
1483-
// Don't try to recover here; we'll get more access-related diagnostics
1484-
// downstream if we do.
1485-
return ErrorType::get(ctx);
1486-
}
1487-
14881475
// FIXME: Typo correction!
14891476

14901477
// Lookup into a type.
@@ -1902,10 +1889,25 @@ static Type resolveQualifiedIdentTypeRepr(const TypeResolution &resolution,
19021889
if (options.contains(TypeResolutionFlags::AllowUsableFromInline))
19031890
lookupOptions |= NameLookupFlags::IncludeUsableFromInline;
19041891
LookupTypeResult memberTypes;
1905-
if (parentTy->mayHaveMembers())
1892+
if (parentTy->mayHaveMembers()) {
19061893
memberTypes = TypeChecker::lookupMemberType(
19071894
DC, parentTy, repr->getNameRef(), repr->getLoc(), lookupOptions);
19081895

1896+
// If no members were found, try ignoring missing imports.
1897+
if (!memberTypes &&
1898+
ctx.LangOpts.hasFeature(Feature::MemberImportVisibility)) {
1899+
lookupOptions |= NameLookupFlags::IgnoreMissingImports;
1900+
memberTypes = TypeChecker::lookupMemberType(
1901+
DC, parentTy, repr->getNameRef(), repr->getLoc(), lookupOptions);
1902+
1903+
if (memberTypes.size() == 1) {
1904+
if (maybeDiagnoseMissingImportForMember(memberTypes.back().Member, DC,
1905+
repr->getLoc()))
1906+
return ErrorType::get(ctx);
1907+
}
1908+
}
1909+
}
1910+
19091911
// Name lookup was ambiguous. Complain.
19101912
// FIXME: Could try to apply generic arguments first, and see whether
19111913
// that resolves things. But do we really want that to succeed?

test/NameLookup/members_transitive_multifile_access_level.swift

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
// RUN: %target-swift-frontend -emit-module -o %t %t/Exports.swift -I %t
1111
// RUN: %target-swift-frontend -typecheck -verify -swift-version 5 \
1212
// RUN: -primary-file %t/function_bodies.swift \
13-
// RUN: -primary-file %t/function_signatures.swift \
13+
// RUN: -primary-file %t/function_signatures_unqualified.swift \
14+
// RUN: -primary-file %t/function_signatures_qualified.swift \
15+
// RUN: -primary-file %t/extensions.swift \
1416
// RUN: %t/imports.swift \
1517
// RUN: -I %t -package-name Package \
1618
// RUN: -enable-experimental-feature MemberImportVisibility
@@ -45,7 +47,7 @@ func internalFunc(_ x: Int) {
4547
_ = x.memberInMixedUses // expected-error {{property 'memberInMixedUses' is not available due to missing import of defining module 'MixedUses'}}
4648
}
4749

48-
//--- function_signatures.swift
50+
//--- function_signatures_unqualified.swift
4951

5052
import Swift // Just here to anchor the fix-its
5153
// expected-note 2 {{add import of module 'InternalUsesOnly'}}{{1-1=internal import InternalUsesOnly\n}}
@@ -64,6 +66,57 @@ extension Int {
6466
internal func usesTypealiasInMixedUses_Internal(x: TypealiasInMixedUses) {} // expected-error {{type alias 'TypealiasInMixedUses' is not available due to missing import of defining module 'MixedUses'}}
6567
}
6668

69+
//--- function_signatures_qualified.swift
70+
71+
import Swift // Just here to anchor the fix-its
72+
// expected-note 2 {{add import of module 'InternalUsesOnly'}}{{1-1=internal import InternalUsesOnly\n}}
73+
// expected-note@-1 {{add import of module 'PackageUsesOnly'}}{{1-1=package import PackageUsesOnly\n}}
74+
// expected-note@-2 {{add import of module 'PublicUsesOnly'}}{{1-1=public import PublicUsesOnly\n}}
75+
// expected-note@-3 2 {{add import of module 'MixedUses'}}{{1-1=public import MixedUses\n}}
76+
77+
private func usesTypealiasInInternalUsesOnly_Private(x: Int.TypealiasInInternalUsesOnly) {} // expected-error {{type alias 'TypealiasInInternalUsesOnly' is not available due to missing import of defining module 'InternalUsesOnly'}}
78+
internal func usesTypealiasInInternalUsesOnly(x: Int.TypealiasInInternalUsesOnly) {} // expected-error {{type alias 'TypealiasInInternalUsesOnly' is not available due to missing import of defining module 'InternalUsesOnly'}}
79+
package func usesTypealiasInPackageUsesOnly(x: Int.TypealiasInPackageUsesOnly) {} // expected-error {{type alias 'TypealiasInPackageUsesOnly' is not available due to missing import of defining module 'PackageUsesOnly'}}
80+
public func usesTypealiasInPublicUsesOnly(x: Int.TypealiasInPublicUsesOnly) {} // expected-error {{type alias 'TypealiasInPublicUsesOnly' is not available due to missing import of defining module 'PublicUsesOnly'}}
81+
// expected-warning@-1 {{cannot use type alias 'TypealiasInPublicUsesOnly' here; 'PublicUsesOnly' was not imported by this file}}
82+
public func usesTypealiasInMixedUses(x: Int.TypealiasInMixedUses) {} // expected-error {{type alias 'TypealiasInMixedUses' is not available due to missing import of defining module 'MixedUses'}}
83+
// expected-warning@-1 {{cannot use type alias 'TypealiasInMixedUses' here; 'MixedUses' was not imported by this file}}
84+
internal func usesTypealiasInMixedUses_Internal(x: Int.TypealiasInMixedUses) {} // expected-error {{type alias 'TypealiasInMixedUses' is not available due to missing import of defining module 'MixedUses'}}
85+
86+
//--- extensions.swift
87+
88+
import Swift // Just here to anchor the fix-its
89+
// expected-note 2 {{add import of module 'InternalUsesOnly'}}{{1-1=internal import InternalUsesOnly\n}}
90+
// expected-note@-1 {{add import of module 'PackageUsesOnly'}}{{1-1=package import PackageUsesOnly\n}}
91+
// expected-note@-2 {{add import of module 'PublicUsesOnly'}}{{1-1=public import PublicUsesOnly\n}}
92+
// expected-note@-3 2 {{add import of module 'MixedUses'}}{{1-1=public import MixedUses\n}}
93+
94+
extension Int.NestedInInternalUsesOnly { // expected-error {{struct 'NestedInInternalUsesOnly' is not available due to missing import of defining module 'InternalUsesOnly'}}
95+
private func privateMethod() {}
96+
}
97+
98+
extension Int.NestedInInternalUsesOnly { // expected-error {{struct 'NestedInInternalUsesOnly' is not available due to missing import of defining module 'InternalUsesOnly'}}
99+
internal func internalMethod() {}
100+
}
101+
102+
extension Int.NestedInPackageUsesOnly { // expected-error {{struct 'NestedInPackageUsesOnly' is not available due to missing import of defining module 'PackageUsesOnly'}}
103+
package func packageMethod() {}
104+
}
105+
106+
extension Int.NestedInPublicUsesOnly { // expected-error {{struct 'NestedInPublicUsesOnly' is not available due to missing import of defining module 'PublicUsesOnly'}}
107+
// expected-warning@-1 {{cannot use struct 'NestedInPublicUsesOnly' in an extension with public or '@usableFromInline' members; 'PublicUsesOnly' was not imported by this file}}
108+
public func publicMethod() {}
109+
}
110+
111+
extension Int.NestedInMixedUses { // expected-error {{struct 'NestedInMixedUses' is not available due to missing import of defining module 'MixedUses'}}
112+
// expected-warning@-1 {{cannot use struct 'NestedInMixedUses' in an extension with public or '@usableFromInline' members; 'MixedUses' was not imported by this file}}
113+
public func publicMethod() {}
114+
}
115+
116+
extension Int.NestedInMixedUses { // expected-error {{struct 'NestedInMixedUses' is not available due to missing import of defining module 'MixedUses'}}
117+
internal func internalMethod() {}
118+
}
119+
67120
//--- imports.swift
68121

69122
internal import InternalUsesOnly
@@ -78,48 +131,55 @@ internal import Exports
78131

79132
extension Int {
80133
public typealias TypealiasInInternalUsesOnly = Self
134+
public struct NestedInInternalUsesOnly {}
81135
public var memberInInternalUsesOnly: Int { return self }
82136
}
83137

84138
//--- InternalUsesOnlyDefaultedImport.swift
85139

86140
extension Int {
87141
public typealias TypealiasInInternalUsesOnlyDefaultedImport = Self
142+
public struct NestedInInternalUsesOnlyDefaultedImport {}
88143
public var memberInInternalUsesOnlyDefaultedImport: Int { return self }
89144
}
90145

91146
//--- PackageUsesOnly.swift
92147

93148
extension Int {
94149
public typealias TypealiasInPackageUsesOnly = Self
150+
public struct NestedInPackageUsesOnly {}
95151
public var memberInPackageUsesOnly: Int { return self }
96152
}
97153

98154
//--- PublicUsesOnly.swift
99155

100156
extension Int {
101157
public typealias TypealiasInPublicUsesOnly = Self
158+
public struct NestedInPublicUsesOnly {}
102159
public var memberInPublicUsesOnly: Int { return self }
103160
}
104161

105162
//--- PublicUsesOnlyDefaultedImport.swift
106163

107164
extension Int {
108165
public typealias TypealiasInPublicUsesOnlyDefaultedImport = Self
166+
public struct NestedInPublicUsesOnlyDefaultedImport {}
109167
public var memberInPublicUsesOnlyDefaultedImport: Int { return self }
110168
}
111169

112170
//--- MixedUses.swift
113171

114172
extension Int {
115173
public typealias TypealiasInMixedUses = Self
174+
public struct NestedInMixedUses {}
116175
public var memberInMixedUses: Int { return self }
117176
}
118177

119178
//--- InternalUsesOnlyTransitivelyImported.swift
120179

121180
extension Int {
122181
public typealias TypealiasInInternalUsesOnlyTransitivelyImported = Self
182+
public struct NestedInInternalUsesOnlyTransitivelyImported {}
123183
public var memberInInternalUsesOnlyTransitivelyImported: Int { return self }
124184
}
125185

0 commit comments

Comments
 (0)