@@ -222,6 +222,17 @@ ExportContext ExportContext::forFunctionBody(DeclContext *DC, SourceLoc loc) {
222
222
unavailablePlatformKind);
223
223
}
224
224
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
+
225
236
ExportContext ExportContext::withReason (ExportabilityReason reason) const {
226
237
auto copy = *this ;
227
238
copy.Reason = unsigned (reason);
@@ -1226,7 +1237,8 @@ static const Decl *ancestorMemberLevelDeclForAvailabilityFixit(const Decl *D) {
1226
1237
while (D) {
1227
1238
D = relatedDeclForAvailabilityFixit (D);
1228
1239
1229
- if (D->getDeclContext ()->isTypeContext () &&
1240
+ if (!D->isImplicit () &&
1241
+ D->getDeclContext ()->isTypeContext () &&
1230
1242
DeclAttribute::canAttributeAppearOnDecl (DeclAttrKind::DAK_Available,
1231
1243
D)) {
1232
1244
break ;
@@ -2172,20 +2184,19 @@ void TypeChecker::diagnoseIfDeprecated(SourceRange ReferenceRange,
2172
2184
}
2173
2185
}
2174
2186
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) {
2180
2191
const AvailableAttr *attr = TypeChecker::getDeprecated (ext);
2181
2192
if (!attr)
2182
- return ;
2193
+ return false ;
2183
2194
2184
2195
// We match the behavior of clang to not report deprecation warnings
2185
2196
// inside declarations that are themselves deprecated on all deployment
2186
2197
// targets.
2187
2198
if (where.isDeprecated ()) {
2188
- return ;
2199
+ return false ;
2189
2200
}
2190
2201
2191
2202
auto *dc = where.getDeclContext ();
@@ -2196,7 +2207,7 @@ void TypeChecker::diagnoseIfDeprecated(
2196
2207
// Suppress a deprecation warning if the availability checking machinery
2197
2208
// thinks the reference program location will not execute on any
2198
2209
// deployment target for the current platform.
2199
- return ;
2210
+ return false ;
2200
2211
}
2201
2212
}
2202
2213
@@ -2215,7 +2226,7 @@ void TypeChecker::diagnoseIfDeprecated(
2215
2226
attr->Deprecated .hasValue (), deprecatedVersion,
2216
2227
/* message*/ StringRef ())
2217
2228
.highlight (attr->getRange ());
2218
- return ;
2229
+ return true ;
2219
2230
}
2220
2231
2221
2232
EncodedDiagnosticMessage encodedMessage (attr->Message );
@@ -2225,6 +2236,7 @@ void TypeChecker::diagnoseIfDeprecated(
2225
2236
attr->Deprecated .hasValue (), deprecatedVersion,
2226
2237
encodedMessage.Message )
2227
2238
.highlight (attr->getRange ());
2239
+ return true ;
2228
2240
}
2229
2241
2230
2242
void swift::diagnoseUnavailableOverride (ValueDecl *override ,
@@ -3374,7 +3386,8 @@ void swift::diagnoseTypeAvailability(const TypeRepr *TR, Type T, SourceLoc loc,
3374
3386
bool
3375
3387
swift::diagnoseConformanceAvailability (SourceLoc loc,
3376
3388
ProtocolConformanceRef conformance,
3377
- const ExportContext &where) {
3389
+ const ExportContext &where,
3390
+ Type depTy, Type replacementTy) {
3378
3391
assert (!where.isImplicit ());
3379
3392
3380
3393
if (!conformance.isConcrete ())
@@ -3385,29 +3398,55 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
3385
3398
3386
3399
auto *DC = where.getDeclContext ();
3387
3400
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
+
3388
3415
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 ();
3390
3418
return true ;
3419
+ }
3391
3420
3392
- if (diagnoseExplicitUnavailability (loc, rootConf, ext, where))
3421
+ if (diagnoseExplicitUnavailability (loc, rootConf, ext, where)) {
3422
+ maybeEmitAssociatedTypeNote ();
3393
3423
return true ;
3394
-
3395
- // Diagnose for deprecation
3396
- TypeChecker::diagnoseIfDeprecated (loc, rootConf, ext, where);
3424
+ }
3397
3425
3398
3426
// Diagnose (and possibly signal) for potential unavailability
3399
3427
auto maybeUnavail = TypeChecker::checkConformanceAvailability (
3400
3428
rootConf, ext, where);
3401
3429
if (maybeUnavail.hasValue ()) {
3402
3430
TypeChecker::diagnosePotentialUnavailability (rootConf, ext, loc, DC,
3403
3431
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.
3404
3442
}
3405
3443
}
3406
3444
3407
3445
// Now, check associated conformances.
3408
3446
SubstitutionMap subConformanceSubs =
3409
3447
concreteConf->getSubstitutions (DC->getParentModule ());
3410
- if (diagnoseSubstitutionMapAvailability (loc, subConformanceSubs, where))
3448
+ if (diagnoseSubstitutionMapAvailability (loc, subConformanceSubs, where,
3449
+ depTy, replacementTy))
3411
3450
return true ;
3412
3451
3413
3452
return false ;
@@ -3416,10 +3455,12 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
3416
3455
bool
3417
3456
swift::diagnoseSubstitutionMapAvailability (SourceLoc loc,
3418
3457
SubstitutionMap subs,
3419
- const ExportContext &where) {
3458
+ const ExportContext &where,
3459
+ Type depTy, Type replacementTy) {
3420
3460
bool hadAnyIssues = false ;
3421
3461
for (ProtocolConformanceRef conformance : subs.getConformances ()) {
3422
- if (diagnoseConformanceAvailability (loc, conformance, where))
3462
+ if (diagnoseConformanceAvailability (loc, conformance, where,
3463
+ depTy, replacementTy))
3423
3464
hadAnyIssues = true ;
3424
3465
}
3425
3466
return hadAnyIssues;
0 commit comments