@@ -2536,20 +2536,19 @@ namespace {
2536
2536
2537
2537
enum class RetainReleaseOperationKind {
2538
2538
notAfunction,
2539
- doesntReturnVoid ,
2539
+ doesntReturnVoidOrSelf ,
2540
2540
invalidParameters,
2541
2541
valid
2542
2542
};
2543
2543
2544
2544
auto getOperationValidity =
2545
- [&](ValueDecl *operation) -> RetainReleaseOperationKind {
2545
+ [&](ValueDecl *operation,
2546
+ CustomRefCountingOperationKind operationKind)
2547
+ -> RetainReleaseOperationKind {
2546
2548
auto operationFn = dyn_cast<FuncDecl>(operation);
2547
2549
if (!operationFn)
2548
2550
return RetainReleaseOperationKind::notAfunction;
2549
2551
2550
- if (!operationFn->getResultInterfaceType ()->isVoid ())
2551
- return RetainReleaseOperationKind::doesntReturnVoid;
2552
-
2553
2552
if (operationFn->getParameters ()->size () != 1 )
2554
2553
return RetainReleaseOperationKind::invalidParameters;
2555
2554
@@ -2561,6 +2560,16 @@ namespace {
2561
2560
}
2562
2561
2563
2562
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->getAnyNominal () != paramDecl)
2570
+ return RetainReleaseOperationKind::doesntReturnVoidOrSelf;
2571
+ }
2572
+
2564
2573
// The parameter of the retain/release function should be pointer to the
2565
2574
// same FRT or a base FRT.
2566
2575
if (paramDecl != classDecl) {
@@ -2574,6 +2583,7 @@ namespace {
2574
2583
}
2575
2584
return RetainReleaseOperationKind::invalidParameters;
2576
2585
}
2586
+
2577
2587
return RetainReleaseOperationKind::valid;
2578
2588
};
2579
2589
@@ -2612,7 +2622,8 @@ namespace {
2612
2622
} else if (retainOperation.kind ==
2613
2623
CustomRefCountingOperationResult::foundOperation) {
2614
2624
RetainReleaseOperationKind operationKind =
2615
- getOperationValidity (retainOperation.operation );
2625
+ getOperationValidity (retainOperation.operation ,
2626
+ CustomRefCountingOperationKind::retain);
2616
2627
HeaderLoc loc (decl->getLocation ());
2617
2628
switch (operationKind) {
2618
2629
case RetainReleaseOperationKind::notAfunction:
@@ -2621,10 +2632,10 @@ namespace {
2621
2632
diag::foreign_reference_types_retain_release_not_a_function_decl,
2622
2633
false , retainOperation.name );
2623
2634
break ;
2624
- case RetainReleaseOperationKind::doesntReturnVoid :
2635
+ case RetainReleaseOperationKind::doesntReturnVoidOrSelf :
2625
2636
Impl.diagnose (
2626
2637
loc,
2627
- diag::foreign_reference_types_retain_release_non_void_return_type ,
2638
+ diag::foreign_reference_types_retain_non_void_or_self_return_type ,
2628
2639
false , retainOperation.name );
2629
2640
break ;
2630
2641
case RetainReleaseOperationKind::invalidParameters:
@@ -2676,7 +2687,8 @@ namespace {
2676
2687
} else if (releaseOperation.kind ==
2677
2688
CustomRefCountingOperationResult::foundOperation) {
2678
2689
RetainReleaseOperationKind operationKind =
2679
- getOperationValidity (releaseOperation.operation );
2690
+ getOperationValidity (releaseOperation.operation ,
2691
+ CustomRefCountingOperationKind::release);
2680
2692
HeaderLoc loc (decl->getLocation ());
2681
2693
switch (operationKind) {
2682
2694
case RetainReleaseOperationKind::notAfunction:
@@ -2685,10 +2697,10 @@ namespace {
2685
2697
diag::foreign_reference_types_retain_release_not_a_function_decl,
2686
2698
true , releaseOperation.name );
2687
2699
break ;
2688
- case RetainReleaseOperationKind::doesntReturnVoid :
2700
+ case RetainReleaseOperationKind::doesntReturnVoidOrSelf :
2689
2701
Impl.diagnose (
2690
2702
loc,
2691
- diag::foreign_reference_types_retain_release_non_void_return_type ,
2703
+ diag::foreign_reference_types_release_non_void_return_type ,
2692
2704
true , releaseOperation.name );
2693
2705
break ;
2694
2706
case RetainReleaseOperationKind::invalidParameters:
0 commit comments