Skip to content

Commit 410c209

Browse files
authored
Merge pull request #11160 from CodaFi/youre-gonna-like-the-way-you-invoke
2 parents 37a3d85 + 3ae852c commit 410c209

File tree

4 files changed

+193
-20
lines changed

4 files changed

+193
-20
lines changed

lib/SIL/SILFunctionType.cpp

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -477,8 +477,8 @@ enum class ConventionsKind : uint8_t {
477477
}
478478
}
479479

480-
void visitSelfType(AbstractionPattern origType, CanType substType,
481-
SILFunctionTypeRepresentation rep) {
480+
void visitSharedType(AbstractionPattern origType, CanType substType,
481+
SILFunctionTypeRepresentation rep) {
482482
NextOrigParamIndex++;
483483

484484
auto &substTL =
@@ -548,16 +548,29 @@ enum class ConventionsKind : uint8_t {
548548
/*canonicalVararg*/true)
549549
->getCanonicalType();
550550
CanTupleType tty = dyn_cast<TupleType>(ty);
551-
if (!tty || (origType.isTypeParameter() && !tty->hasInOutElement())) {
552-
visit(origType, ty);
553-
return;
554-
}
555-
556551
// If the abstraction pattern is opaque, and the tuple type is
557552
// materializable -- if it doesn't contain an l-value type -- then it's
558553
// a valid target for substitution and we should not expand it.
554+
if (!tty || (origType.isTypeParameter() && !tty->hasInOutElement())) {
555+
auto flags = (params.size() == 1)
556+
? params.front().getParameterFlags()
557+
: ParameterTypeFlags();
558+
if (flags.isShared()) {
559+
visitSharedType(origType, ty, extInfo.getSILRepresentation());
560+
} else {
561+
visit(origType, ty);
562+
}
563+
return;
564+
}
565+
559566
for (auto i : indices(tty.getElementTypes())) {
560-
visit(origType.getTupleElementType(i), tty.getElementType(i));
567+
if (tty->getElement(i).getParameterFlags().isShared()) {
568+
visitSharedType(origType.getTupleElementType(i),
569+
tty.getElementType(i),
570+
extInfo.getSILRepresentation());
571+
} else {
572+
visit(origType.getTupleElementType(i), tty.getElementType(i));
573+
}
561574
}
562575
return;
563576
}
@@ -569,15 +582,19 @@ enum class ConventionsKind : uint8_t {
569582
CanType ty = params[i].getType();
570583
CanTupleType tty = dyn_cast<TupleType>(ty);
571584
AbstractionPattern eltPattern = origType.getTupleElementType(i);
585+
// If the abstraction pattern is opaque, and the tuple type is
586+
// materializable -- if it doesn't contain an l-value type -- then it's
587+
// a valid target for substitution and we should not expand it.
572588
if (!tty || (eltPattern.isTypeParameter() && !tty->hasInOutElement())) {
573-
visit(eltPattern, ty);
589+
if (params[i].getParameterFlags().isShared()) {
590+
visitSharedType(eltPattern, ty, extInfo.getSILRepresentation());
591+
} else {
592+
visit(eltPattern, ty);
593+
}
574594
continue;
575595
}
576596

577597
assert(eltPattern.isTuple());
578-
// If the abstraction pattern is opaque, and the tuple type is
579-
// materializable -- if it doesn't contain an l-value type -- then it's
580-
// a valid target for substitution and we should not expand it.
581598
for (unsigned j = 0; j < eltPattern.getNumTupleElements(); ++j) {
582599
visit(eltPattern.getTupleElementType(j), tty.getElementType(j));
583600
}
@@ -586,9 +603,9 @@ enum class ConventionsKind : uint8_t {
586603
// Process the self parameter. Note that we implicitly drop self
587604
// if this is a static foreign-self import.
588605
if (!Foreign.Self.isImportAsMember()) {
589-
visitSelfType(origType.getTupleElementType(numNonSelfParams),
590-
params[numNonSelfParams].getType(),
591-
extInfo.getSILRepresentation());
606+
visitSharedType(origType.getTupleElementType(numNonSelfParams),
607+
params[numNonSelfParams].getType(),
608+
extInfo.getSILRepresentation());
592609
}
593610

594611
// Clear the foreign-self handler for safety.

lib/SIL/TypeLowering.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,9 @@ CaptureKind TypeConverter::getDeclCaptureKind(CapturedValue capture) {
118118
// If this is a non-address-only stored 'let' constant, we can capture it
119119
// by value. If it is address-only, then we can't load it, so capture it
120120
// by its address (like a var) instead.
121-
if (var->isLet() && (!SILModuleConventions(M).useLoweredAddresses() ||
122-
!getTypeLowering(var->getType()).isAddressOnly()))
121+
if ((var->isLet() || var->isShared())
122+
&& (!SILModuleConventions(M).useLoweredAddresses() ||
123+
!getTypeLowering(var->getType()).isAddressOnly()))
123124
return CaptureKind::Constant;
124125

125126
// In-out parameters are captured by address.

test/Constraints/closures.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,25 @@ struct X2 {
2929

3030
_ = f0(X2(), {$0.g()})
3131

32+
// Closures with inout arguments and '__shared' conversions.
33+
34+
func inoutToSharedConversions() {
35+
func fooOW<T, U>(_ f : (__owned T) -> U) {}
36+
fooOW({ (x : Int) in return Int(5) }) // '__owned'-to-'__owned' allowed
37+
fooOW({ (x : __shared Int) in return Int(5) }) // '__shared'-to-'__owned' allowed
38+
fooOW({ (x : inout Int) in return Int(5) }) // expected-error {{cannot convert value of type '(inout Int) -> Int' to expected argument type '(_) -> _'}}
39+
40+
func fooIO<T, U>(_ f : (inout T) -> U) {}
41+
fooIO({ (x : inout Int) in return Int(5) }) // 'inout'-to-'inout' allowed
42+
fooIO({ (x : __shared Int) in return Int(5) }) // expected-error {{cannot convert value of type '(__shared Int) -> Int' to expected argument type '(inout _) -> _'}}
43+
fooIO({ (x : Int) in return Int(5) }) // expected-error {{cannot convert value of type '(inout Int) -> Int' to expected argument type '(inout _) -> _'}}
44+
45+
func fooSH<T, U>(_ f : (__shared T) -> U) {}
46+
fooSH({ (x : __shared Int) in return Int(5) }) // '__shared'-to-'__shared' allowed
47+
fooSH({ (x : inout Int) in return Int(5) }) // expected-error {{cannot convert value of type '(inout Int) -> Int' to expected argument type '(__shared _) -> _'}}
48+
fooSH({ (x : Int) in return Int(5) }) // '__owned'-to-'__shared' allowed
49+
}
50+
3251
// Autoclosure
3352
func f1(f: @autoclosure () -> Int) { }
3453
func f2() -> Int { }

0 commit comments

Comments
 (0)