@@ -2532,20 +2532,19 @@ namespace {
25322532
25332533 enum class RetainReleaseOperationKind {
25342534 notAfunction,
2535- doesntReturnVoid ,
2535+ doesntReturnVoidOrSelf ,
25362536 invalidParameters,
25372537 valid
25382538 };
25392539
25402540 auto getOperationValidity =
2541- [&](ValueDecl *operation) -> RetainReleaseOperationKind {
2541+ [&](ValueDecl *operation,
2542+ CustomRefCountingOperationKind operationKind)
2543+ -> RetainReleaseOperationKind {
25422544 auto operationFn = dyn_cast<FuncDecl>(operation);
25432545 if (!operationFn)
25442546 return RetainReleaseOperationKind::notAfunction;
25452547
2546- if (!operationFn->getResultInterfaceType ()->isVoid ())
2547- return RetainReleaseOperationKind::doesntReturnVoid;
2548-
25492548 if (operationFn->getParameters ()->size () != 1 )
25502549 return RetainReleaseOperationKind::invalidParameters;
25512550
@@ -2557,6 +2556,16 @@ namespace {
25572556 }
25582557
25592558 swift::NominalTypeDecl *paramDecl = paramType->getAnyNominal ();
2559+
2560+ // The return type should be void (for release functions), or void
2561+ // or the parameter type (for retain functions).
2562+ auto resultInterfaceType = operationFn->getResultInterfaceType ();
2563+ if (!resultInterfaceType->isVoid ()) {
2564+ if (operationKind == CustomRefCountingOperationKind::release ||
2565+ !resultInterfaceType->lookThroughSingleOptionalType ()->isEqual (paramType))
2566+ return RetainReleaseOperationKind::doesntReturnVoidOrSelf;
2567+ }
2568+
25602569 // The parameter of the retain/release function should be pointer to the
25612570 // same FRT or a base FRT.
25622571 if (paramDecl != classDecl) {
@@ -2570,6 +2579,7 @@ namespace {
25702579 }
25712580 return RetainReleaseOperationKind::invalidParameters;
25722581 }
2582+
25732583 return RetainReleaseOperationKind::valid;
25742584 };
25752585
@@ -2608,7 +2618,8 @@ namespace {
26082618 } else if (retainOperation.kind ==
26092619 CustomRefCountingOperationResult::foundOperation) {
26102620 RetainReleaseOperationKind operationKind =
2611- getOperationValidity (retainOperation.operation );
2621+ getOperationValidity (retainOperation.operation ,
2622+ CustomRefCountingOperationKind::retain);
26122623 HeaderLoc loc (decl->getLocation ());
26132624 switch (operationKind) {
26142625 case RetainReleaseOperationKind::notAfunction:
@@ -2617,11 +2628,11 @@ namespace {
26172628 diag::foreign_reference_types_retain_release_not_a_function_decl,
26182629 false , retainOperation.name );
26192630 break ;
2620- case RetainReleaseOperationKind::doesntReturnVoid :
2631+ case RetainReleaseOperationKind::doesntReturnVoidOrSelf :
26212632 Impl.diagnose (
26222633 loc,
2623- diag::foreign_reference_types_retain_release_non_void_return_type ,
2624- false , retainOperation.name );
2634+ diag::foreign_reference_types_retain_non_void_or_self_return_type ,
2635+ retainOperation.name );
26252636 break ;
26262637 case RetainReleaseOperationKind::invalidParameters:
26272638 Impl.diagnose (loc,
@@ -2672,7 +2683,8 @@ namespace {
26722683 } else if (releaseOperation.kind ==
26732684 CustomRefCountingOperationResult::foundOperation) {
26742685 RetainReleaseOperationKind operationKind =
2675- getOperationValidity (releaseOperation.operation );
2686+ getOperationValidity (releaseOperation.operation ,
2687+ CustomRefCountingOperationKind::release);
26762688 HeaderLoc loc (decl->getLocation ());
26772689 switch (operationKind) {
26782690 case RetainReleaseOperationKind::notAfunction:
@@ -2681,11 +2693,11 @@ namespace {
26812693 diag::foreign_reference_types_retain_release_not_a_function_decl,
26822694 true , releaseOperation.name );
26832695 break ;
2684- case RetainReleaseOperationKind::doesntReturnVoid :
2696+ case RetainReleaseOperationKind::doesntReturnVoidOrSelf :
26852697 Impl.diagnose (
26862698 loc,
2687- diag::foreign_reference_types_retain_release_non_void_return_type ,
2688- true , releaseOperation.name );
2699+ diag::foreign_reference_types_release_non_void_return_type ,
2700+ releaseOperation.name );
26892701 break ;
26902702 case RetainReleaseOperationKind::invalidParameters:
26912703 Impl.diagnose (loc,
0 commit comments