@@ -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);
@@ -2172,20 +2183,19 @@ void TypeChecker::diagnoseIfDeprecated(SourceRange ReferenceRange,
2172
2183
}
2173
2184
}
2174
2185
2175
- void TypeChecker::diagnoseIfDeprecated (
2176
- SourceLoc loc,
2177
- const RootProtocolConformance *rootConf,
2178
- const ExtensionDecl *ext,
2179
- const ExportContext &where) {
2186
+ bool TypeChecker::diagnoseIfDeprecated (SourceLoc loc,
2187
+ const RootProtocolConformance *rootConf,
2188
+ const ExtensionDecl *ext,
2189
+ const ExportContext &where) {
2180
2190
const AvailableAttr *attr = TypeChecker::getDeprecated (ext);
2181
2191
if (!attr)
2182
- return ;
2192
+ return false ;
2183
2193
2184
2194
// We match the behavior of clang to not report deprecation warnings
2185
2195
// inside declarations that are themselves deprecated on all deployment
2186
2196
// targets.
2187
2197
if (where.isDeprecated ()) {
2188
- return ;
2198
+ return false ;
2189
2199
}
2190
2200
2191
2201
auto *dc = where.getDeclContext ();
@@ -2196,7 +2206,7 @@ void TypeChecker::diagnoseIfDeprecated(
2196
2206
// Suppress a deprecation warning if the availability checking machinery
2197
2207
// thinks the reference program location will not execute on any
2198
2208
// deployment target for the current platform.
2199
- return ;
2209
+ return false ;
2200
2210
}
2201
2211
}
2202
2212
@@ -2215,7 +2225,7 @@ void TypeChecker::diagnoseIfDeprecated(
2215
2225
attr->Deprecated .hasValue (), deprecatedVersion,
2216
2226
/* message*/ StringRef ())
2217
2227
.highlight (attr->getRange ());
2218
- return ;
2228
+ return true ;
2219
2229
}
2220
2230
2221
2231
EncodedDiagnosticMessage encodedMessage (attr->Message );
@@ -2225,6 +2235,7 @@ void TypeChecker::diagnoseIfDeprecated(
2225
2235
attr->Deprecated .hasValue (), deprecatedVersion,
2226
2236
encodedMessage.Message )
2227
2237
.highlight (attr->getRange ());
2238
+ return true ;
2228
2239
}
2229
2240
2230
2241
void swift::diagnoseUnavailableOverride (ValueDecl *override ,
@@ -3374,7 +3385,8 @@ void swift::diagnoseTypeAvailability(const TypeRepr *TR, Type T, SourceLoc loc,
3374
3385
bool
3375
3386
swift::diagnoseConformanceAvailability (SourceLoc loc,
3376
3387
ProtocolConformanceRef conformance,
3377
- const ExportContext &where) {
3388
+ const ExportContext &where,
3389
+ Type depTy, Type replacementTy) {
3378
3390
assert (!where.isImplicit ());
3379
3391
3380
3392
if (!conformance.isConcrete ())
@@ -3385,29 +3397,55 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
3385
3397
3386
3398
auto *DC = where.getDeclContext ();
3387
3399
3400
+ auto maybeEmitAssociatedTypeNote = [&]() {
3401
+ if (!depTy && !replacementTy)
3402
+ return ;
3403
+
3404
+ Type selfTy = rootConf->getProtocol ()->getProtocolSelfType ();
3405
+ if (!depTy->isEqual (selfTy)) {
3406
+ auto &ctx = DC->getASTContext ();
3407
+ ctx.Diags .diagnose (
3408
+ loc,
3409
+ diag::assoc_conformance_from_implementation_only_module,
3410
+ depTy, replacementTy->getCanonicalType ());
3411
+ }
3412
+ };
3413
+
3388
3414
if (auto *ext = dyn_cast<ExtensionDecl>(rootConf->getDeclContext ())) {
3389
- if (TypeChecker::diagnoseConformanceExportability (loc, rootConf, ext, where))
3415
+ if (TypeChecker::diagnoseConformanceExportability (loc, rootConf, ext, where)) {
3416
+ maybeEmitAssociatedTypeNote ();
3390
3417
return true ;
3418
+ }
3391
3419
3392
- if (diagnoseExplicitUnavailability (loc, rootConf, ext, where))
3420
+ if (diagnoseExplicitUnavailability (loc, rootConf, ext, where)) {
3421
+ maybeEmitAssociatedTypeNote ();
3393
3422
return true ;
3394
-
3395
- // Diagnose for deprecation
3396
- TypeChecker::diagnoseIfDeprecated (loc, rootConf, ext, where);
3423
+ }
3397
3424
3398
3425
// Diagnose (and possibly signal) for potential unavailability
3399
3426
auto maybeUnavail = TypeChecker::checkConformanceAvailability (
3400
3427
rootConf, ext, where);
3401
3428
if (maybeUnavail.hasValue ()) {
3402
3429
TypeChecker::diagnosePotentialUnavailability (rootConf, ext, loc, DC,
3403
3430
maybeUnavail.getValue ());
3431
+ maybeEmitAssociatedTypeNote ();
3432
+ return true ;
3433
+ }
3434
+
3435
+ // Diagnose for deprecation
3436
+ if (TypeChecker::diagnoseIfDeprecated (loc, rootConf, ext, where)) {
3437
+ maybeEmitAssociatedTypeNote ();
3438
+
3439
+ // Deprecation is just a warning, so keep going with checking the
3440
+ // substitution map below.
3404
3441
}
3405
3442
}
3406
3443
3407
3444
// Now, check associated conformances.
3408
3445
SubstitutionMap subConformanceSubs =
3409
3446
concreteConf->getSubstitutions (DC->getParentModule ());
3410
- if (diagnoseSubstitutionMapAvailability (loc, subConformanceSubs, where))
3447
+ if (diagnoseSubstitutionMapAvailability (loc, subConformanceSubs, where,
3448
+ depTy, replacementTy))
3411
3449
return true ;
3412
3450
3413
3451
return false ;
@@ -3416,10 +3454,12 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
3416
3454
bool
3417
3455
swift::diagnoseSubstitutionMapAvailability (SourceLoc loc,
3418
3456
SubstitutionMap subs,
3419
- const ExportContext &where) {
3457
+ const ExportContext &where,
3458
+ Type depTy, Type replacementTy) {
3420
3459
bool hadAnyIssues = false ;
3421
3460
for (ProtocolConformanceRef conformance : subs.getConformances ()) {
3422
- if (diagnoseConformanceAvailability (loc, conformance, where))
3461
+ if (diagnoseConformanceAvailability (loc, conformance, where,
3462
+ depTy, replacementTy))
3423
3463
hadAnyIssues = true ;
3424
3464
}
3425
3465
return hadAnyIssues;
0 commit comments