Skip to content

Commit 4afa371

Browse files
committed
Introduce subtyping rule for functions with "isolated" parameters.
With isolated parameters being part of a function's type, check to ensure that isolated and non-isolated parameters aren't incorrectly matched. Specifically, it is okay to add `isolated` to a parameter when there is a subtyping relationship, but not remove it: ```swift actor A { } func f(_: isolated A) { } func g(_: A) { } func test() { let _: (isolated A) -> Void = g // okay to add 'isolated' let _: (A) -> Void = f // error when removing 'isolated' } ```
1 parent 5004a54 commit 4afa371

File tree

3 files changed

+43
-10
lines changed

3 files changed

+43
-10
lines changed

lib/Parse/ParsePattern.cpp

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -574,16 +574,33 @@ mapParsedParameters(Parser &parser,
574574

575575
param->setTypeRepr(type);
576576

577-
// If there is `@autoclosure` attribute associated with the type
578-
// let's mark that in the declaration as well, because it
579-
// belongs to both type flags and declaration.
580-
if (auto *ATR = dyn_cast<AttributedTypeRepr>(type)) {
581-
auto &attrs = ATR->getAttrs();
582-
// At this point we actually don't know if that's valid to mark
583-
// this parameter declaration as `autoclosure` because type has
584-
// not been resolved yet - it should either be a function type
585-
// or typealias with underlying function type.
586-
param->setAutoClosure(attrs.has(TypeAttrKind::TAK_autoclosure));
577+
// Dig through the type to find any attributes or modifiers that are
578+
// associated with the type but should also be reflected on the
579+
// declaration.
580+
{
581+
auto unwrappedType = type;
582+
while (true) {
583+
if (auto *ATR = dyn_cast<AttributedTypeRepr>(unwrappedType)) {
584+
auto &attrs = ATR->getAttrs();
585+
// At this point we actually don't know if that's valid to mark
586+
// this parameter declaration as `autoclosure` because type has
587+
// not been resolved yet - it should either be a function type
588+
// or typealias with underlying function type.
589+
param->setAutoClosure(attrs.has(TypeAttrKind::TAK_autoclosure));
590+
591+
unwrappedType = ATR->getTypeRepr();
592+
continue;
593+
}
594+
595+
if (auto *STR = dyn_cast<SpecifierTypeRepr>(unwrappedType)) {
596+
if (isa<IsolatedTypeRepr>(STR))
597+
param->setIsolated(true);
598+
unwrappedType = STR->getBase();
599+
continue;;
600+
}
601+
602+
break;
603+
}
587604
}
588605
} else if (paramInfo.SpecifierLoc.isValid()) {
589606
StringRef specifier;

lib/Sema/CSSimplify.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2461,6 +2461,12 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
24612461
hasLabelingFailures = true;
24622462
}
24632463

2464+
// "isolated" can be added as a subtype relation, but otherwise must match.
2465+
if (func1Param.isIsolated() != func2Param.isIsolated() &&
2466+
!(func2Param.isIsolated() && subKind >= ConstraintKind::Subtype)) {
2467+
return getTypeMatchFailure(argumentLocator);
2468+
}
2469+
24642470
// FIXME: We should check value ownership too, but it's not completely
24652471
// trivial because of inout-to-pointer conversions.
24662472

test/Concurrency/isolated_parameters.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,13 @@ func testA<T: Actor>(
2424

2525
@available(SwiftStdlib 5.5, *)
2626
typealias Fn = (isolated A) -> Void
27+
28+
@available(SwiftStdlib 5.5, *)
29+
func globalFunc(_: A) { }
30+
31+
@available(SwiftStdlib 5.5, *)
32+
func globalFuncIsolated(_: isolated A) {
33+
let _: Int = globalFuncIsolated // expected-error{{cannot convert value of type '(isolated A) -> ()' to specified type 'Int'}}
34+
let _: (A) -> Void = globalFuncIsolated // expected-error{{cannot convert value of type '(isolated A) -> ()' to specified type '(A) -> Void'}}
35+
let _: Fn = globalFunc // okay
36+
}

0 commit comments

Comments
 (0)