2727
2828using 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-
3730bool 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
6457bool 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
227187bool
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