@@ -222,6 +222,17 @@ ExportContext ExportContext::forFunctionBody(DeclContext *DC, SourceLoc loc) {
222222 unavailablePlatformKind);
223223}
224224
225+ ExportContext ExportContext::forConformance (DeclContext *DC,
226+ ProtocolDecl *proto) {
227+ assert (isa<ExtensionDecl>(DC) || isa<NominalTypeDecl>(DC));
228+ auto where = forDeclSignature (DC->getInnermostDeclarationDeclContext ());
229+
230+ where.Exported &= proto->getFormalAccessScope (
231+ DC, /* usableFromInlineAsPublic*/ true ).isPublic ();
232+
233+ return where;
234+ }
235+
225236ExportContext ExportContext::withReason (ExportabilityReason reason) const {
226237 auto copy = *this ;
227238 copy.Reason = unsigned (reason);
@@ -1226,7 +1237,8 @@ static const Decl *ancestorMemberLevelDeclForAvailabilityFixit(const Decl *D) {
12261237 while (D) {
12271238 D = relatedDeclForAvailabilityFixit (D);
12281239
1229- if (D->getDeclContext ()->isTypeContext () &&
1240+ if (!D->isImplicit () &&
1241+ D->getDeclContext ()->isTypeContext () &&
12301242 DeclAttribute::canAttributeAppearOnDecl (DeclAttrKind::DAK_Available,
12311243 D)) {
12321244 break ;
@@ -2172,20 +2184,19 @@ void TypeChecker::diagnoseIfDeprecated(SourceRange ReferenceRange,
21722184 }
21732185}
21742186
2175- void TypeChecker::diagnoseIfDeprecated (
2176- SourceLoc loc,
2177- const RootProtocolConformance *rootConf,
2178- const ExtensionDecl *ext,
2179- const ExportContext &where) {
2187+ bool TypeChecker::diagnoseIfDeprecated (SourceLoc loc,
2188+ const RootProtocolConformance *rootConf,
2189+ const ExtensionDecl *ext,
2190+ const ExportContext &where) {
21802191 const AvailableAttr *attr = TypeChecker::getDeprecated (ext);
21812192 if (!attr)
2182- return ;
2193+ return false ;
21832194
21842195 // We match the behavior of clang to not report deprecation warnings
21852196 // inside declarations that are themselves deprecated on all deployment
21862197 // targets.
21872198 if (where.isDeprecated ()) {
2188- return ;
2199+ return false ;
21892200 }
21902201
21912202 auto *dc = where.getDeclContext ();
@@ -2196,7 +2207,7 @@ void TypeChecker::diagnoseIfDeprecated(
21962207 // Suppress a deprecation warning if the availability checking machinery
21972208 // thinks the reference program location will not execute on any
21982209 // deployment target for the current platform.
2199- return ;
2210+ return false ;
22002211 }
22012212 }
22022213
@@ -2215,7 +2226,7 @@ void TypeChecker::diagnoseIfDeprecated(
22152226 attr->Deprecated .hasValue (), deprecatedVersion,
22162227 /* message*/ StringRef ())
22172228 .highlight (attr->getRange ());
2218- return ;
2229+ return true ;
22192230 }
22202231
22212232 EncodedDiagnosticMessage encodedMessage (attr->Message );
@@ -2225,6 +2236,7 @@ void TypeChecker::diagnoseIfDeprecated(
22252236 attr->Deprecated .hasValue (), deprecatedVersion,
22262237 encodedMessage.Message )
22272238 .highlight (attr->getRange ());
2239+ return true ;
22282240}
22292241
22302242void swift::diagnoseUnavailableOverride (ValueDecl *override ,
@@ -3374,7 +3386,8 @@ void swift::diagnoseTypeAvailability(const TypeRepr *TR, Type T, SourceLoc loc,
33743386bool
33753387swift::diagnoseConformanceAvailability (SourceLoc loc,
33763388 ProtocolConformanceRef conformance,
3377- const ExportContext &where) {
3389+ const ExportContext &where,
3390+ Type depTy, Type replacementTy) {
33783391 assert (!where.isImplicit ());
33793392
33803393 if (!conformance.isConcrete ())
@@ -3385,29 +3398,55 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
33853398
33863399 auto *DC = where.getDeclContext ();
33873400
3401+ auto maybeEmitAssociatedTypeNote = [&]() {
3402+ if (!depTy && !replacementTy)
3403+ return ;
3404+
3405+ Type selfTy = rootConf->getProtocol ()->getProtocolSelfType ();
3406+ if (!depTy->isEqual (selfTy)) {
3407+ auto &ctx = DC->getASTContext ();
3408+ ctx.Diags .diagnose (
3409+ loc,
3410+ diag::assoc_conformance_from_implementation_only_module,
3411+ depTy, replacementTy->getCanonicalType ());
3412+ }
3413+ };
3414+
33883415 if (auto *ext = dyn_cast<ExtensionDecl>(rootConf->getDeclContext ())) {
3389- if (TypeChecker::diagnoseConformanceExportability (loc, rootConf, ext, where))
3416+ if (TypeChecker::diagnoseConformanceExportability (loc, rootConf, ext, where)) {
3417+ maybeEmitAssociatedTypeNote ();
33903418 return true ;
3419+ }
33913420
3392- if (diagnoseExplicitUnavailability (loc, rootConf, ext, where))
3421+ if (diagnoseExplicitUnavailability (loc, rootConf, ext, where)) {
3422+ maybeEmitAssociatedTypeNote ();
33933423 return true ;
3394-
3395- // Diagnose for deprecation
3396- TypeChecker::diagnoseIfDeprecated (loc, rootConf, ext, where);
3424+ }
33973425
33983426 // Diagnose (and possibly signal) for potential unavailability
33993427 auto maybeUnavail = TypeChecker::checkConformanceAvailability (
34003428 rootConf, ext, where);
34013429 if (maybeUnavail.hasValue ()) {
34023430 TypeChecker::diagnosePotentialUnavailability (rootConf, ext, loc, DC,
34033431 maybeUnavail.getValue ());
3432+ maybeEmitAssociatedTypeNote ();
3433+ return true ;
3434+ }
3435+
3436+ // Diagnose for deprecation
3437+ if (TypeChecker::diagnoseIfDeprecated (loc, rootConf, ext, where)) {
3438+ maybeEmitAssociatedTypeNote ();
3439+
3440+ // Deprecation is just a warning, so keep going with checking the
3441+ // substitution map below.
34043442 }
34053443 }
34063444
34073445 // Now, check associated conformances.
34083446 SubstitutionMap subConformanceSubs =
34093447 concreteConf->getSubstitutions (DC->getParentModule ());
3410- if (diagnoseSubstitutionMapAvailability (loc, subConformanceSubs, where))
3448+ if (diagnoseSubstitutionMapAvailability (loc, subConformanceSubs, where,
3449+ depTy, replacementTy))
34113450 return true ;
34123451
34133452 return false ;
@@ -3416,10 +3455,12 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
34163455bool
34173456swift::diagnoseSubstitutionMapAvailability (SourceLoc loc,
34183457 SubstitutionMap subs,
3419- const ExportContext &where) {
3458+ const ExportContext &where,
3459+ Type depTy, Type replacementTy) {
34203460 bool hadAnyIssues = false ;
34213461 for (ProtocolConformanceRef conformance : subs.getConformances ()) {
3422- if (diagnoseConformanceAvailability (loc, conformance, where))
3462+ if (diagnoseConformanceAvailability (loc, conformance, where,
3463+ depTy, replacementTy))
34233464 hadAnyIssues = true ;
34243465 }
34253466 return hadAnyIssues;
0 commit comments