Skip to content

Commit c0d664d

Browse files
authored
Merge pull request #34329 from slavapestov/nuke-exportability-checker
Fold exportability checking into availability checking
2 parents 7e16e3b + a824e5a commit c0d664d

14 files changed

+615
-847
lines changed

lib/Sema/ResilienceDiagnostics.cpp

Lines changed: 68 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -27,53 +27,47 @@
2727

2828
using namespace swift;
2929

30-
/// A uniquely-typed boolean to reduce the chances of accidentally inverting
31-
/// a check.
32-
enum class DowngradeToWarning: bool {
33-
No,
34-
Yes
35-
};
36-
3730
bool TypeChecker::diagnoseInlinableDeclRef(SourceLoc loc,
38-
ConcreteDeclRef declRef,
39-
const DeclContext *DC,
40-
FragileFunctionKind Kind) {
41-
assert(Kind.kind != FragileFunctionKind::None);
31+
const ValueDecl *D,
32+
ExportContext where) {
33+
auto fragileKind = where.getFragileFunctionKind();
34+
if (fragileKind.kind == FragileFunctionKind::None)
35+
return false;
4236

43-
const ValueDecl *D = declRef.getDecl();
4437
// Do some important fast-path checks that apply to all cases.
4538

4639
// Type parameters are OK.
4740
if (isa<AbstractTypeParamDecl>(D))
4841
return false;
4942

5043
// Check whether the declaration is accessible.
51-
if (diagnoseInlinableDeclRefAccess(loc, D, DC, Kind))
44+
if (diagnoseInlinableDeclRefAccess(loc, D, where))
5245
return true;
5346

5447
// Check whether the declaration comes from a publically-imported module.
5548
// Skip this check for accessors because the associated property or subscript
5649
// will also be checked, and will provide a better error message.
5750
if (!isa<AccessorDecl>(D))
58-
if (diagnoseDeclRefExportability(loc, declRef, DC, Kind))
51+
if (diagnoseDeclRefExportability(loc, D, where))
5952
return true;
6053

6154
return false;
6255
}
6356

6457
bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
65-
const ValueDecl *D,
66-
const DeclContext *DC,
67-
FragileFunctionKind Kind) {
68-
assert(Kind.kind != FragileFunctionKind::None);
58+
const ValueDecl *D,
59+
ExportContext where) {
60+
auto *DC = where.getDeclContext();
61+
auto fragileKind = where.getFragileFunctionKind();
62+
assert(fragileKind.kind != FragileFunctionKind::None);
6963

7064
// Local declarations are OK.
7165
if (D->getDeclContext()->isLocalContext())
7266
return false;
7367

7468
// Public declarations or SPI used from SPI are OK.
7569
if (D->getFormalAccessScope(/*useDC=*/nullptr,
76-
Kind.allowUsableFromInline).isPublic() &&
70+
fragileKind.allowUsableFromInline).isPublic() &&
7771
!(D->isSPI() && !DC->getInnermostDeclarationDeclContext()->isSPI()))
7872
return false;
7973

@@ -133,10 +127,10 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
133127
loc, diagID,
134128
D->getDescriptiveKind(), diagName,
135129
D->getFormalAccessScope().accessLevelForDiagnostics(),
136-
static_cast<unsigned>(Kind.kind),
130+
static_cast<unsigned>(fragileKind.kind),
137131
isAccessor);
138132

139-
if (Kind.allowUsableFromInline) {
133+
if (fragileKind.allowUsableFromInline) {
140134
Context.Diags.diagnose(D, diag::resilience_decl_declared_here,
141135
D->getDescriptiveKind(), diagName, isAccessor);
142136
} else {
@@ -147,99 +141,74 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
147141
return (downgradeToWarning == DowngradeToWarning::No);
148142
}
149143

150-
static bool diagnoseDeclExportability(SourceLoc loc, const ValueDecl *D,
151-
const SourceFile &userSF,
152-
const DeclContext *userDC,
153-
FragileFunctionKind fragileKind) {
154-
assert(fragileKind.kind != FragileFunctionKind::None);
144+
bool
145+
TypeChecker::diagnoseDeclRefExportability(SourceLoc loc,
146+
const ValueDecl *D,
147+
ExportContext where) {
148+
if (!where.mustOnlyReferenceExportedDecls())
149+
return false;
155150

156151
auto definingModule = D->getModuleContext();
157152

153+
auto downgradeToWarning = DowngradeToWarning::No;
154+
158155
auto originKind = getDisallowedOriginKind(
159-
D, userSF, userDC->getInnermostDeclarationDeclContext());
156+
D, where, downgradeToWarning);
160157
if (originKind == DisallowedOriginKind::None)
161158
return false;
162159

163-
// TODO: different diagnostics
164160
ASTContext &ctx = definingModule->getASTContext();
165-
ctx.Diags.diagnose(loc, diag::inlinable_decl_ref_from_hidden_module,
166-
D->getDescriptiveKind(), D->getName(),
167-
static_cast<unsigned>(fragileKind.kind),
168-
definingModule->getName(),
169-
static_cast<unsigned>(originKind));
170-
return true;
171-
}
172161

173-
static bool
174-
diagnoseGenericArgumentsExportability(SourceLoc loc,
175-
SubstitutionMap subs,
176-
const SourceFile &userSF,
177-
const DeclContext *userDC) {
178-
bool hadAnyIssues = false;
179-
for (ProtocolConformanceRef conformance : subs.getConformances()) {
180-
if (!conformance.isConcrete())
181-
continue;
182-
const ProtocolConformance *concreteConf = conformance.getConcrete();
183-
184-
SubstitutionMap subConformanceSubs =
185-
concreteConf->getSubstitutions(userSF.getParentModule());
186-
diagnoseGenericArgumentsExportability(loc, subConformanceSubs, userSF, userDC);
187-
188-
const RootProtocolConformance *rootConf =
189-
concreteConf->getRootConformance();
190-
ModuleDecl *M = rootConf->getDeclContext()->getParentModule();
191-
192-
auto originKind = getDisallowedOriginKind(
193-
rootConf->getDeclContext()->getAsDecl(),
194-
userSF, userDC->getInnermostDeclarationDeclContext());
195-
if (originKind == DisallowedOriginKind::None)
196-
continue;
197-
198-
ASTContext &ctx = M->getASTContext();
199-
ctx.Diags.diagnose(loc, diag::conformance_from_implementation_only_module,
200-
rootConf->getType(),
201-
rootConf->getProtocol()->getName(), 0, M->getName(),
162+
auto fragileKind = where.getFragileFunctionKind();
163+
auto reason = where.getExportabilityReason();
164+
165+
if (fragileKind.kind == FragileFunctionKind::None) {
166+
auto errorOrWarning = downgradeToWarning == DowngradeToWarning::Yes?
167+
diag::decl_from_hidden_module_warn:
168+
diag::decl_from_hidden_module;
169+
ctx.Diags.diagnose(loc, errorOrWarning,
170+
D->getDescriptiveKind(),
171+
D->getName(),
172+
static_cast<unsigned>(*reason),
173+
definingModule->getName(),
202174
static_cast<unsigned>(originKind));
203-
hadAnyIssues = true;
204-
}
205-
return hadAnyIssues;
206-
}
207175

208-
void TypeChecker::diagnoseGenericTypeExportability(SourceLoc Loc, Type T,
209-
const DeclContext *DC) {
210-
const SourceFile *SF = DC->getParentSourceFile();
211-
if (!SF)
212-
return;
213-
214-
// FIXME: It would be nice to highlight just the part of the type that's
215-
// problematic, but unfortunately the TypeRepr doesn't have the
216-
// information we need and the Type doesn't easily map back to it.
217-
if (auto *BGT = dyn_cast<BoundGenericType>(T.getPointer())) {
218-
ModuleDecl *useModule = SF->getParentModule();
219-
auto subs = T->getContextSubstitutionMap(useModule, BGT->getDecl());
220-
(void)diagnoseGenericArgumentsExportability(Loc, subs, *SF, DC);
221-
} else if (auto *TAT = dyn_cast<TypeAliasType>(T.getPointer())) {
222-
auto subs = TAT->getSubstitutionMap();
223-
(void)diagnoseGenericArgumentsExportability(Loc, subs, *SF, DC);
176+
D->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type);
177+
} else {
178+
ctx.Diags.diagnose(loc, diag::inlinable_decl_ref_from_hidden_module,
179+
D->getDescriptiveKind(), D->getName(),
180+
static_cast<unsigned>(fragileKind.kind),
181+
definingModule->getName(),
182+
static_cast<unsigned>(originKind));
224183
}
184+
return true;
225185
}
226186

227187
bool
228-
TypeChecker::diagnoseDeclRefExportability(SourceLoc loc,
229-
ConcreteDeclRef declRef,
230-
const DeclContext *DC,
231-
FragileFunctionKind fragileKind) {
232-
// We're only interested in diagnosing uses from source files.
233-
auto userSF = DC->getParentSourceFile();
234-
if (!userSF)
188+
TypeChecker::diagnoseConformanceExportability(SourceLoc loc,
189+
const RootProtocolConformance *rootConf,
190+
ExportContext where) {
191+
if (!where.mustOnlyReferenceExportedDecls())
235192
return false;
236193

237-
const ValueDecl *D = declRef.getDecl();
238-
if (diagnoseDeclExportability(loc, D, *userSF, DC, fragileKind))
239-
return true;
240-
if (diagnoseGenericArgumentsExportability(loc, declRef.getSubstitutions(),
241-
*userSF, DC)) {
242-
return true;
243-
}
244-
return false;
194+
auto originKind = getDisallowedOriginKind(
195+
rootConf->getDeclContext()->getAsDecl(),
196+
where);
197+
if (originKind == DisallowedOriginKind::None)
198+
return false;
199+
200+
ModuleDecl *M = rootConf->getDeclContext()->getParentModule();
201+
ASTContext &ctx = M->getASTContext();
202+
203+
auto reason = where.getExportabilityReason();
204+
if (!reason.hasValue())
205+
reason = ExportabilityReason::General;
206+
207+
ctx.Diags.diagnose(loc, diag::conformance_from_implementation_only_module,
208+
rootConf->getType(),
209+
rootConf->getProtocol()->getName(),
210+
static_cast<unsigned>(*reason),
211+
M->getName(),
212+
static_cast<unsigned>(originKind));
213+
return true;
245214
}

0 commit comments

Comments
 (0)