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,
3831 ConcreteDeclRef declRef,
3932 const DeclContext *DC,
@@ -55,16 +48,17 @@ bool TypeChecker::diagnoseInlinableDeclRef(SourceLoc loc,
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, declRef, DC,
52+ None, Kind))
5953 return true ;
6054
6155 return false ;
6256}
6357
6458bool 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) {
6862 assert (Kind.kind != FragileFunctionKind::None);
6963
7064 // Local declarations are OK.
@@ -150,96 +144,87 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
150144static bool diagnoseDeclExportability (SourceLoc loc, const ValueDecl *D,
151145 const SourceFile &userSF,
152146 const DeclContext *userDC,
147+ Optional<ExportabilityReason> reason,
153148 FragileFunctionKind fragileKind) {
154- assert (fragileKind.kind != FragileFunctionKind::None);
149+ if (fragileKind.kind == FragileFunctionKind::None && !reason.hasValue ())
150+ return false ;
155151
156152 auto definingModule = D->getModuleContext ();
157153
154+ auto downgradeToWarning = DowngradeToWarning::No;
158155 auto originKind = getDisallowedOriginKind (
159- D, userSF, userDC->getInnermostDeclarationDeclContext ());
156+ D, userSF, userDC->getInnermostDeclarationDeclContext (),
157+ downgradeToWarning);
160158 if (originKind == DisallowedOriginKind::None)
161159 return false ;
162160
163- // TODO: different diagnostics
164161 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- }
172162
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 (),
202180 static_cast <unsigned >(originKind));
203- hadAnyIssues = true ;
204181 }
205- return hadAnyIssues ;
182+ return true ;
206183}
207184
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 ;
225213}
226214
227215bool
228216TypeChecker::diagnoseDeclRefExportability (SourceLoc loc,
229217 ConcreteDeclRef declRef,
230218 const DeclContext *DC,
219+ Optional<ExportabilityReason> reason,
231220 FragileFunctionKind fragileKind) {
232221 // We're only interested in diagnosing uses from source files.
233222 auto userSF = DC->getParentSourceFile ();
234223 if (!userSF)
235224 return false ;
236225
237226 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))
242228 return true ;
243- }
244229 return false ;
245230}
0 commit comments