@@ -2092,7 +2092,7 @@ static Type getRequirementTypeForDisplay(ModuleDecl *module,
2092
2092
return FunctionType::get (params, result, fnTy->getExtInfo ());
2093
2093
}
2094
2094
2095
- return substType (type, /* result*/ false );
2095
+ return substType (type, /* result*/ true );
2096
2096
}
2097
2097
2098
2098
diag::RequirementKind
@@ -3361,41 +3361,36 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement,
3361
3361
emitDeclaredHereIfNeeded (diags, diagLoc, witness);
3362
3362
});
3363
3363
} else if (selfKind.result ) {
3364
- // The reference to Self occurs in the result type. A non-final class
3365
- // can satisfy this requirement with a method that returns Self.
3364
+ // The reference to Self occurs in the result type of a method/subscript
3365
+ // or the type of a property. A non-final class can satisfy this requirement
3366
+ // by holding onto Self accordingly.
3367
+ if (witness->getDeclContext ()->getSelfClassDecl ()) {
3368
+ const bool hasDynamicSelfResult = [&] {
3369
+ if (auto func = dyn_cast<AbstractFunctionDecl>(witness)) {
3370
+ return func->hasDynamicSelfResult ();
3371
+ } else if (auto var = dyn_cast<VarDecl>(witness)) {
3372
+ return var->getInterfaceType ()->hasDynamicSelfType ();
3373
+ }
3366
3374
3367
- // If the function has a dynamic Self, it's okay.
3368
- if (auto func = dyn_cast<FuncDecl>(witness)) {
3369
- if (func->getDeclContext ()->getSelfClassDecl () &&
3370
- !func->hasDynamicSelfResult ()) {
3375
+ return cast<SubscriptDecl>(witness)
3376
+ ->getElementInterfaceType ()
3377
+ ->hasDynamicSelfType ();
3378
+ }();
3379
+
3380
+ if (!hasDynamicSelfResult) {
3371
3381
diagnoseOrDefer (requirement, false ,
3372
3382
[witness, requirement](NormalProtocolConformance *conformance) {
3373
3383
auto proto = conformance->getProtocol ();
3374
3384
auto &diags = proto->getASTContext ().Diags ;
3375
3385
SourceLoc diagLoc = getLocForDiagnosingWitness (conformance,witness);
3376
- diags.diagnose (diagLoc,
3377
- diag::witness_requires_dynamic_self ,
3386
+ diags.diagnose (diagLoc, diag::witness_requires_dynamic_self,
3387
+ getProtocolRequirementKind (requirement) ,
3378
3388
requirement->getName (),
3379
3389
conformance->getType (),
3380
3390
proto->getDeclaredInterfaceType ());
3381
3391
emitDeclaredHereIfNeeded (diags, diagLoc, witness);
3382
3392
});
3383
3393
}
3384
-
3385
- // Constructors conceptually also have a dynamic Self
3386
- // return type, so they're okay.
3387
- } else if (!isa<ConstructorDecl>(witness)) {
3388
- diagnoseOrDefer (requirement, false ,
3389
- [witness, requirement](NormalProtocolConformance *conformance) {
3390
- auto proto = conformance->getProtocol ();
3391
- auto &diags = proto->getASTContext ().Diags ;
3392
- SourceLoc diagLoc = getLocForDiagnosingWitness (conformance, witness);
3393
- diags.diagnose (diagLoc, diag::witness_self_non_subtype,
3394
- proto->getDeclaredInterfaceType (),
3395
- requirement->getName (),
3396
- conformance->getType ());
3397
- emitDeclaredHereIfNeeded (diags, diagLoc, witness);
3398
- });
3399
3394
}
3400
3395
} else if (selfKind.requirement ) {
3401
3396
if (auto targetPair = getAdopteeSelfSameTypeConstraint (classDecl,
@@ -3431,8 +3426,8 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement,
3431
3426
// constraint that either the requirement not produce 'Self' in a
3432
3427
// covariant position, or the type of the requirement does not involve
3433
3428
// associated types.
3434
- if (auto func = dyn_cast<FuncDecl >(witness)) {
3435
- if (func ->getDeclContext ()->getExtendedProtocolDecl ()) {
3429
+ if (isa<FuncDecl>(witness) || isa<SubscriptDecl >(witness)) {
3430
+ if (witness ->getDeclContext ()->getExtendedProtocolDecl ()) {
3436
3431
auto selfKindWithAssocTypes = Proto->findProtocolSelfReferences (
3437
3432
requirement,
3438
3433
/* allowCovariantParameters=*/ false ,
@@ -3445,6 +3440,7 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement,
3445
3440
auto &diags = proto->getASTContext ().Diags ;
3446
3441
diags.diagnose (conformance->getLoc (),
3447
3442
diag::witness_requires_class_implementation,
3443
+ getProtocolRequirementKind (requirement),
3448
3444
requirement->getName (),
3449
3445
conformance->getType ());
3450
3446
diags.diagnose (witness, diag::decl_declared_here,
0 commit comments