Skip to content

Commit 1b9d539

Browse files
committed
Sema: Diagnose when typealiases used in public declarations would desugar to types from non-public imports.
Resolves rdar://91447971
1 parent 8f9c533 commit 1b9d539

File tree

6 files changed

+218
-166
lines changed

6 files changed

+218
-166
lines changed

include/swift/AST/DiagnosticsSema.def

+19
Original file line numberDiff line numberDiff line change
@@ -2916,6 +2916,17 @@ WARNING(decl_from_hidden_module_warn,none,
29162916
"<<ERROR>>|<<ERROR>>|"
29172917
"%3 was not imported by this file}4",
29182918
(DescriptiveDeclKind, DeclName, unsigned, Identifier, unsigned))
2919+
ERROR(typealias_desugars_to_type_from_hidden_module,none,
2920+
"%0 aliases '%1.%2' and cannot be used %select{here|"
2921+
"as property wrapper here|"
2922+
"as result builder here|"
2923+
"in an extension with public or '@usableFromInline' members|"
2924+
"in an extension with conditional conformances}3 "
2925+
"because %select{%4 has been imported as implementation-only|"
2926+
"it is an SPI imported from %4|"
2927+
"<<ERROR>>|"
2928+
"%4 was not imported by this file}5",
2929+
(DeclName, StringRef, StringRef, unsigned, Identifier, unsigned))
29192930
ERROR(conformance_from_implementation_only_module,none,
29202931
"cannot use conformance of %0 to %1 %select{here|as property wrapper here|"
29212932
"as result builder here|"
@@ -5805,6 +5816,14 @@ WARNING(inlinable_decl_ref_from_hidden_module_warn,
58055816
"; this is an error in Swift 6",
58065817
(DescriptiveDeclKind, DeclName, unsigned, Identifier, unsigned))
58075818

5819+
ERROR(inlinable_typealias_desugars_to_type_from_hidden_module,
5820+
none, "%0 aliases '%1.%2' and cannot be used in " FRAGILE_FUNC_KIND "3 "
5821+
"because %select{%4 has been imported as implementation-only|"
5822+
"it is an SPI imported from %4|"
5823+
"<<ERROR>>|"
5824+
"%4 was not imported by this file}5",
5825+
(DeclName, StringRef, StringRef, unsigned, Identifier, unsigned))
5826+
58085827
ERROR(availability_macro_in_inlinable, none,
58095828
"availability macro cannot be used in " FRAGILE_FUNC_KIND "0",
58105829
(unsigned))

lib/Sema/ResilienceDiagnostics.cpp

+61-8
Original file line numberDiff line numberDiff line change
@@ -106,20 +106,52 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
106106
return (downgradeToWarning == DowngradeToWarning::No);
107107
}
108108

109-
bool
110-
TypeChecker::diagnoseDeclRefExportability(SourceLoc loc,
111-
const ValueDecl *D,
112-
const ExportContext &where) {
113-
// Accessors cannot have exportability that's different than the storage,
114-
// so skip them for now.
115-
if (isa<AccessorDecl>(D))
109+
static bool diagnoseTypeAliasDeclRefExportability(SourceLoc loc,
110+
const TypeAliasDecl *TAD,
111+
const ExportContext &where) {
112+
assert(where.mustOnlyReferenceExportedDecls());
113+
114+
auto *D = TAD->getUnderlyingType()->getAnyNominal();
115+
if (!D)
116116
return false;
117117

118-
if (!where.mustOnlyReferenceExportedDecls())
118+
auto ignoredDowngradeToWarning = DowngradeToWarning::No;
119+
auto originKind =
120+
getDisallowedOriginKind(D, where, ignoredDowngradeToWarning);
121+
if (originKind == DisallowedOriginKind::None)
119122
return false;
120123

121124
auto definingModule = D->getModuleContext();
125+
ASTContext &ctx = definingModule->getASTContext();
126+
auto fragileKind = where.getFragileFunctionKind();
127+
128+
if (fragileKind.kind == FragileFunctionKind::None) {
129+
auto reason = where.getExportabilityReason();
130+
ctx.Diags
131+
.diagnose(loc, diag::typealias_desugars_to_type_from_hidden_module,
132+
TAD->getName(), definingModule->getNameStr(), D->getNameStr(),
133+
static_cast<unsigned>(*reason), definingModule->getName(),
134+
static_cast<unsigned>(originKind))
135+
.warnUntilSwiftVersion(6);
136+
} else {
137+
ctx.Diags
138+
.diagnose(loc,
139+
diag::inlinable_typealias_desugars_to_type_from_hidden_module,
140+
TAD->getName(), definingModule->getNameStr(), D->getNameStr(),
141+
fragileKind.getSelector(), definingModule->getName(),
142+
static_cast<unsigned>(originKind))
143+
.warnUntilSwiftVersion(6);
144+
}
145+
D->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type);
146+
147+
return true;
148+
}
149+
150+
static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
151+
const ExportContext &where) {
152+
assert(where.mustOnlyReferenceExportedDecls());
122153

154+
auto definingModule = D->getModuleContext();
123155
auto downgradeToWarning = DowngradeToWarning::No;
124156

125157
auto originKind = getDisallowedOriginKind(
@@ -162,6 +194,27 @@ TypeChecker::diagnoseDeclRefExportability(SourceLoc loc,
162194
return true;
163195
}
164196

197+
bool TypeChecker::diagnoseDeclRefExportability(SourceLoc loc,
198+
const ValueDecl *D,
199+
const ExportContext &where) {
200+
// Accessors cannot have exportability that's different than the storage,
201+
// so skip them for now.
202+
if (isa<AccessorDecl>(D))
203+
return false;
204+
205+
if (!where.mustOnlyReferenceExportedDecls())
206+
return false;
207+
208+
if (diagnoseValueDeclRefExportability(loc, D, where))
209+
return true;
210+
211+
if (auto *TAD = dyn_cast<TypeAliasDecl>(D))
212+
if (diagnoseTypeAliasDeclRefExportability(loc, TAD, where))
213+
return true;
214+
215+
return false;
216+
}
217+
165218
bool
166219
TypeChecker::diagnoseConformanceExportability(SourceLoc loc,
167220
const RootProtocolConformance *rootConf,

lib/Sema/TypeCheckAccess.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,14 @@ class SourceFile;
3232
/// itself. Related checks may also be performed.
3333
void checkAccessControl(Decl *D);
3434

35-
// Problematic origin of an exported type.
36-
//
37-
// This enum must be kept in sync with
38-
// diag::inlinable_decl_ref_from_hidden_module,
39-
// diag::decl_from_hidden_module and
40-
// diag::conformance_from_implementation_only_module.
35+
/// Problematic origin of an exported type.
36+
///
37+
/// This enum must be kept in sync with a number of diagnostics:
38+
/// diag::inlinable_decl_ref_from_hidden_module
39+
/// diag::decl_from_hidden_module
40+
/// diag::conformance_from_implementation_only_module
41+
/// diag::typealias_desugars_to_type_from_hidden_module
42+
/// daig::inlinable_typealias_desugars_to_type_from_hidden_module
4143
enum class DisallowedOriginKind : uint8_t {
4244
ImplementationOnly,
4345
SPIImported,

test/ModuleInterface/cross-module-typealias.swift

-152
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// RUN: %target-swift-emit-module-interface(%t/Original.swiftinterface) %t/Original.swift
5+
// RUN: %target-swift-typecheck-module-from-interface(%t/Original.swiftinterface)
6+
7+
// RUN: %target-swift-emit-module-interface(%t/Aliases.swiftinterface) %t/Aliases.swift -I %t
8+
// RUN: %target-swift-typecheck-module-from-interface(%t/Aliases.swiftinterface) -I %t
9+
10+
// RUN: %target-swift-frontend -typecheck -verify %t/UsesAliasesNoImport.swift -I %t -swift-version 6
11+
12+
// REQUIRES: asserts
13+
14+
// This test is a simplified version of implicit-import-typealias.swift that
15+
// verifies errors are emitted instead of warnings in Swift 6.
16+
17+
//--- Original.swift
18+
19+
open class Clazz {}
20+
21+
22+
//--- Aliases.swift
23+
24+
import Original
25+
26+
public typealias ClazzAlias = Clazz
27+
28+
29+
//--- UsesAliasesNoImport.swift
30+
31+
import Aliases
32+
33+
// expected-error@+1 {{'ClazzAlias' aliases 'Original.Clazz' and cannot be used here because 'Original' was not imported by this file}}
34+
public class InheritsFromClazzAlias: ClazzAlias {}
35+

0 commit comments

Comments
 (0)