@@ -2536,20 +2536,19 @@ namespace {
25362536
25372537 enum class RetainReleaseOperationKind {
25382538 notAfunction,
2539- doesntReturnVoid ,
2539+ doesntReturnVoidOrSelf ,
25402540 invalidParameters,
25412541 valid
25422542 };
25432543
25442544 auto getOperationValidity =
2545- [&](ValueDecl *operation) -> RetainReleaseOperationKind {
2545+ [&](ValueDecl *operation,
2546+ CustomRefCountingOperationKind operationKind)
2547+ -> RetainReleaseOperationKind {
25462548 auto operationFn = dyn_cast<FuncDecl>(operation);
25472549 if (!operationFn)
25482550 return RetainReleaseOperationKind::notAfunction;
25492551
2550- if (!operationFn->getResultInterfaceType ()->isVoid ())
2551- return RetainReleaseOperationKind::doesntReturnVoid;
2552-
25532552 if (operationFn->getParameters ()->size () != 1 )
25542553 return RetainReleaseOperationKind::invalidParameters;
25552554
@@ -2561,6 +2560,16 @@ namespace {
25612560 }
25622561
25632562 swift::NominalTypeDecl *paramDecl = paramType->getAnyNominal ();
2563+
2564+ // The return type should be void (for release functions), or void
2565+ // or the parameter type (for retain functions).
2566+ auto resultInterfaceType = operationFn->getResultInterfaceType ();
2567+ if (!resultInterfaceType->isVoid ()) {
2568+ if (operationKind == CustomRefCountingOperationKind::release ||
2569+ !resultInterfaceType->lookThroughSingleOptionalType ()->isEqual (paramType))
2570+ return RetainReleaseOperationKind::doesntReturnVoidOrSelf;
2571+ }
2572+
25642573 // The parameter of the retain/release function should be pointer to the
25652574 // same FRT or a base FRT.
25662575 if (paramDecl != classDecl) {
@@ -2574,6 +2583,7 @@ namespace {
25742583 }
25752584 return RetainReleaseOperationKind::invalidParameters;
25762585 }
2586+
25772587 return RetainReleaseOperationKind::valid;
25782588 };
25792589
@@ -2612,7 +2622,8 @@ namespace {
26122622 } else if (retainOperation.kind ==
26132623 CustomRefCountingOperationResult::foundOperation) {
26142624 RetainReleaseOperationKind operationKind =
2615- getOperationValidity (retainOperation.operation );
2625+ getOperationValidity (retainOperation.operation ,
2626+ CustomRefCountingOperationKind::retain);
26162627 HeaderLoc loc (decl->getLocation ());
26172628 switch (operationKind) {
26182629 case RetainReleaseOperationKind::notAfunction:
@@ -2621,11 +2632,11 @@ namespace {
26212632 diag::foreign_reference_types_retain_release_not_a_function_decl,
26222633 false , retainOperation.name );
26232634 break ;
2624- case RetainReleaseOperationKind::doesntReturnVoid :
2635+ case RetainReleaseOperationKind::doesntReturnVoidOrSelf :
26252636 Impl.diagnose (
26262637 loc,
2627- diag::foreign_reference_types_retain_release_non_void_return_type ,
2628- false , retainOperation.name );
2638+ diag::foreign_reference_types_retain_non_void_or_self_return_type ,
2639+ retainOperation.name );
26292640 break ;
26302641 case RetainReleaseOperationKind::invalidParameters:
26312642 Impl.diagnose (loc,
@@ -2676,7 +2687,8 @@ namespace {
26762687 } else if (releaseOperation.kind ==
26772688 CustomRefCountingOperationResult::foundOperation) {
26782689 RetainReleaseOperationKind operationKind =
2679- getOperationValidity (releaseOperation.operation );
2690+ getOperationValidity (releaseOperation.operation ,
2691+ CustomRefCountingOperationKind::release);
26802692 HeaderLoc loc (decl->getLocation ());
26812693 switch (operationKind) {
26822694 case RetainReleaseOperationKind::notAfunction:
@@ -2685,11 +2697,11 @@ namespace {
26852697 diag::foreign_reference_types_retain_release_not_a_function_decl,
26862698 true , releaseOperation.name );
26872699 break ;
2688- case RetainReleaseOperationKind::doesntReturnVoid :
2700+ case RetainReleaseOperationKind::doesntReturnVoidOrSelf :
26892701 Impl.diagnose (
26902702 loc,
2691- diag::foreign_reference_types_retain_release_non_void_return_type ,
2692- true , releaseOperation.name );
2703+ diag::foreign_reference_types_release_non_void_return_type ,
2704+ releaseOperation.name );
26932705 break ;
26942706 case RetainReleaseOperationKind::invalidParameters:
26952707 Impl.diagnose (loc,
0 commit comments