@@ -2532,20 +2532,19 @@ namespace {
2532
2532
2533
2533
enum class RetainReleaseOperationKind {
2534
2534
notAfunction,
2535
- doesntReturnVoid ,
2535
+ doesntReturnVoidOrSelf ,
2536
2536
invalidParameters,
2537
2537
valid
2538
2538
};
2539
2539
2540
2540
auto getOperationValidity =
2541
- [&](ValueDecl *operation) -> RetainReleaseOperationKind {
2541
+ [&](ValueDecl *operation,
2542
+ CustomRefCountingOperationKind operationKind)
2543
+ -> RetainReleaseOperationKind {
2542
2544
auto operationFn = dyn_cast<FuncDecl>(operation);
2543
2545
if (!operationFn)
2544
2546
return RetainReleaseOperationKind::notAfunction;
2545
2547
2546
- if (!operationFn->getResultInterfaceType ()->isVoid ())
2547
- return RetainReleaseOperationKind::doesntReturnVoid;
2548
-
2549
2548
if (operationFn->getParameters ()->size () != 1 )
2550
2549
return RetainReleaseOperationKind::invalidParameters;
2551
2550
@@ -2557,6 +2556,16 @@ namespace {
2557
2556
}
2558
2557
2559
2558
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
+
2560
2569
// The parameter of the retain/release function should be pointer to the
2561
2570
// same FRT or a base FRT.
2562
2571
if (paramDecl != classDecl) {
@@ -2570,6 +2579,7 @@ namespace {
2570
2579
}
2571
2580
return RetainReleaseOperationKind::invalidParameters;
2572
2581
}
2582
+
2573
2583
return RetainReleaseOperationKind::valid;
2574
2584
};
2575
2585
@@ -2608,7 +2618,8 @@ namespace {
2608
2618
} else if (retainOperation.kind ==
2609
2619
CustomRefCountingOperationResult::foundOperation) {
2610
2620
RetainReleaseOperationKind operationKind =
2611
- getOperationValidity (retainOperation.operation );
2621
+ getOperationValidity (retainOperation.operation ,
2622
+ CustomRefCountingOperationKind::retain);
2612
2623
HeaderLoc loc (decl->getLocation ());
2613
2624
switch (operationKind) {
2614
2625
case RetainReleaseOperationKind::notAfunction:
@@ -2617,11 +2628,11 @@ namespace {
2617
2628
diag::foreign_reference_types_retain_release_not_a_function_decl,
2618
2629
false , retainOperation.name );
2619
2630
break ;
2620
- case RetainReleaseOperationKind::doesntReturnVoid :
2631
+ case RetainReleaseOperationKind::doesntReturnVoidOrSelf :
2621
2632
Impl.diagnose (
2622
2633
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 );
2625
2636
break ;
2626
2637
case RetainReleaseOperationKind::invalidParameters:
2627
2638
Impl.diagnose (loc,
@@ -2672,7 +2683,8 @@ namespace {
2672
2683
} else if (releaseOperation.kind ==
2673
2684
CustomRefCountingOperationResult::foundOperation) {
2674
2685
RetainReleaseOperationKind operationKind =
2675
- getOperationValidity (releaseOperation.operation );
2686
+ getOperationValidity (releaseOperation.operation ,
2687
+ CustomRefCountingOperationKind::release);
2676
2688
HeaderLoc loc (decl->getLocation ());
2677
2689
switch (operationKind) {
2678
2690
case RetainReleaseOperationKind::notAfunction:
@@ -2681,11 +2693,11 @@ namespace {
2681
2693
diag::foreign_reference_types_retain_release_not_a_function_decl,
2682
2694
true , releaseOperation.name );
2683
2695
break ;
2684
- case RetainReleaseOperationKind::doesntReturnVoid :
2696
+ case RetainReleaseOperationKind::doesntReturnVoidOrSelf :
2685
2697
Impl.diagnose (
2686
2698
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 );
2689
2701
break ;
2690
2702
case RetainReleaseOperationKind::invalidParameters:
2691
2703
Impl.diagnose (loc,
0 commit comments