27
27
28
28
using namespace swift ;
29
29
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
-
37
30
bool TypeChecker::diagnoseInlinableDeclRef (SourceLoc loc,
38
31
ConcreteDeclRef declRef,
39
32
const DeclContext *DC,
@@ -55,16 +48,17 @@ bool TypeChecker::diagnoseInlinableDeclRef(SourceLoc loc,
55
48
// Skip this check for accessors because the associated property or subscript
56
49
// will also be checked, and will provide a better error message.
57
50
if (!isa<AccessorDecl>(D))
58
- if (diagnoseDeclRefExportability (loc, declRef, DC, Kind))
51
+ if (diagnoseDeclRefExportability (loc, declRef, DC,
52
+ None, Kind))
59
53
return true ;
60
54
61
55
return false ;
62
56
}
63
57
64
58
bool TypeChecker::diagnoseInlinableDeclRefAccess (SourceLoc loc,
65
- const ValueDecl *D,
66
- const DeclContext *DC,
67
- FragileFunctionKind Kind) {
59
+ const ValueDecl *D,
60
+ const DeclContext *DC,
61
+ FragileFunctionKind Kind) {
68
62
assert (Kind.kind != FragileFunctionKind::None);
69
63
70
64
// Local declarations are OK.
@@ -150,96 +144,87 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
150
144
static bool diagnoseDeclExportability (SourceLoc loc, const ValueDecl *D,
151
145
const SourceFile &userSF,
152
146
const DeclContext *userDC,
147
+ Optional<ExportabilityReason> reason,
153
148
FragileFunctionKind fragileKind) {
154
- assert (fragileKind.kind != FragileFunctionKind::None);
149
+ if (fragileKind.kind == FragileFunctionKind::None && !reason.hasValue ())
150
+ return false ;
155
151
156
152
auto definingModule = D->getModuleContext ();
157
153
154
+ auto downgradeToWarning = DowngradeToWarning::No;
158
155
auto originKind = getDisallowedOriginKind (
159
- D, userSF, userDC->getInnermostDeclarationDeclContext ());
156
+ D, userSF, userDC->getInnermostDeclarationDeclContext (),
157
+ downgradeToWarning);
160
158
if (originKind == DisallowedOriginKind::None)
161
159
return false ;
162
160
163
- // TODO: different diagnostics
164
161
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
- }
172
162
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 (),
163
+ if (fragileKind.kind == FragileFunctionKind::None) {
164
+ auto errorOrWarning = downgradeToWarning == DowngradeToWarning::Yes?
165
+ diag::decl_from_hidden_module_warn:
166
+ diag::decl_from_hidden_module;
167
+ ctx.Diags .diagnose (loc, errorOrWarning,
168
+ D->getDescriptiveKind (),
169
+ D->getName (),
170
+ static_cast <unsigned >(*reason),
171
+ definingModule->getName (),
172
+ static_cast <unsigned >(originKind));
173
+
174
+ D->diagnose (diag::kind_declared_here, DescriptiveDeclKind::Type);
175
+ } else {
176
+ ctx.Diags .diagnose (loc, diag::inlinable_decl_ref_from_hidden_module,
177
+ D->getDescriptiveKind (), D->getName (),
178
+ static_cast <unsigned >(fragileKind.kind ),
179
+ definingModule->getName (),
202
180
static_cast <unsigned >(originKind));
203
- hadAnyIssues = true ;
204
181
}
205
- return hadAnyIssues ;
182
+ return true ;
206
183
}
207
184
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);
224
- }
185
+ bool
186
+ TypeChecker::diagnoseConformanceExportability (SourceLoc loc,
187
+ const RootProtocolConformance *rootConf,
188
+ const SourceFile &userSF,
189
+ const DeclContext *userDC,
190
+ Optional<ExportabilityReason> reason,
191
+ FragileFunctionKind fragileKind) {
192
+ if (fragileKind.kind == FragileFunctionKind::None && !reason.hasValue ())
193
+ return false ;
194
+
195
+ auto originKind = getDisallowedOriginKind (
196
+ rootConf->getDeclContext ()->getAsDecl (),
197
+ userSF, userDC->getInnermostDeclarationDeclContext ());
198
+ if (originKind == DisallowedOriginKind::None)
199
+ return false ;
200
+
201
+ if (!reason.hasValue ())
202
+ reason = ExportabilityReason::General;
203
+
204
+ ModuleDecl *M = rootConf->getDeclContext ()->getParentModule ();
205
+ ASTContext &ctx = M->getASTContext ();
206
+ ctx.Diags .diagnose (loc, diag::conformance_from_implementation_only_module,
207
+ rootConf->getType (),
208
+ rootConf->getProtocol ()->getName (),
209
+ static_cast <unsigned >(*reason),
210
+ M->getName (),
211
+ static_cast <unsigned >(originKind));
212
+ return true ;
225
213
}
226
214
227
215
bool
228
216
TypeChecker::diagnoseDeclRefExportability (SourceLoc loc,
229
217
ConcreteDeclRef declRef,
230
218
const DeclContext *DC,
219
+ Optional<ExportabilityReason> reason,
231
220
FragileFunctionKind fragileKind) {
232
221
// We're only interested in diagnosing uses from source files.
233
222
auto userSF = DC->getParentSourceFile ();
234
223
if (!userSF)
235
224
return false ;
236
225
237
226
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)) {
227
+ if (diagnoseDeclExportability (loc, D, *userSF, DC, reason, fragileKind))
242
228
return true ;
243
- }
244
229
return false ;
245
230
}
0 commit comments