Skip to content

Commit a245391

Browse files
authored
Merge pull request #72265 from eeckstein/fix-mandatory-inlining
MandatoryInlining and ConstExpr: look through sendable function conversions
2 parents 11d7d53 + 3c76464 commit a245391

34 files changed

+101
-83
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,7 @@ class TargetFunctionTypeFlags {
11191119
}
11201120

11211121
constexpr TargetFunctionTypeFlags<int_type>
1122-
withConcurrent(bool isSendable) const {
1122+
withSendable(bool isSendable) const {
11231123
return TargetFunctionTypeFlags<int_type>(
11241124
(Data & ~SendableMask) |
11251125
(isSendable ? SendableMask : 0));

include/swift/AST/ASTSynthesis.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ ASTExtInfo synthesizeExtInfo(SynthesisContext &SC,
490490
template <class S>
491491
ASTExtInfo synthesizeExtInfo(SynthesisContext &SC,
492492
const SendableModSynthesizer<S> &s) {
493-
return synthesizeExtInfo(SC, s.sub).withConcurrent();
493+
return synthesizeExtInfo(SC, s.sub).withSendable();
494494
}
495495

496496
/// Synthesize a function type.

include/swift/AST/ExtInfo.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ class ASTExtInfoBuilder {
620620
clangTypeInfo, globalActor, thrownError, lifetimeDependenceInfo);
621621
}
622622
[[nodiscard]]
623-
ASTExtInfoBuilder withConcurrent(bool concurrent = true) const {
623+
ASTExtInfoBuilder withSendable(bool concurrent = true) const {
624624
return ASTExtInfoBuilder(
625625
concurrent ? (bits | SendableMask) : (bits & ~SendableMask),
626626
clangTypeInfo, globalActor, thrownError, lifetimeDependenceInfo);
@@ -808,10 +808,10 @@ class ASTExtInfo {
808808

809809
/// Helper method for changing only the concurrent field.
810810
///
811-
/// Prefer using \c ASTExtInfoBuilder::withConcurrent for chaining.
811+
/// Prefer using \c ASTExtInfoBuilder::withSendable for chaining.
812812
[[nodiscard]]
813-
ASTExtInfo withConcurrent(bool concurrent = true) const {
814-
return builder.withConcurrent(concurrent).build();
813+
ASTExtInfo withSendable(bool isSendable = true) const {
814+
return builder.withSendable(isSendable).build();
815815
}
816816

817817
/// Helper method for changing only the throws field.
@@ -1122,7 +1122,7 @@ class SILExtInfoBuilder {
11221122
clangTypeInfo, lifetimeDependenceInfo);
11231123
}
11241124
[[nodiscard]]
1125-
SILExtInfoBuilder withConcurrent(bool isSendable = true) const {
1125+
SILExtInfoBuilder withSendable(bool isSendable = true) const {
11261126
return SILExtInfoBuilder(isSendable ? (bits | SendableMask)
11271127
: (bits & ~SendableMask),
11281128
clangTypeInfo, lifetimeDependenceInfo);
@@ -1294,8 +1294,8 @@ class SILExtInfo {
12941294
return builder.withNoEscape(noEscape).build();
12951295
}
12961296

1297-
SILExtInfo withConcurrent(bool isSendable = true) const {
1298-
return builder.withConcurrent(isSendable).build();
1297+
SILExtInfo withSendable(bool isSendable = true) const {
1298+
return builder.withSendable(isSendable).build();
12991299
}
13001300

13011301
SILExtInfo withAsync(bool isAsync = true) const {

include/swift/Demangling/TypeDecoder.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ class ImplFunctionTypeFlags {
311311
}
312312

313313
ImplFunctionTypeFlags
314-
withConcurrent() const {
314+
withSendable() const {
315315
return ImplFunctionTypeFlags(
316316
ImplFunctionRepresentation(Rep), Pseudogeneric, Escaping, true, Async,
317317
ErasedIsolation,
@@ -967,7 +967,7 @@ class TypeDecoder {
967967
++firstChildIdx;
968968
}
969969

970-
flags = flags.withConcurrent(isSendable)
970+
flags = flags.withSendable(isSendable)
971971
.withAsync(isAsync).withThrows(isThrow)
972972
.withDifferentiable(diffKind.isDifferentiable());
973973

@@ -1046,7 +1046,7 @@ class TypeDecoder {
10461046
if (!child->hasText())
10471047
return MAKE_NODE_TYPE_ERROR0(child, "expected text");
10481048
if (child->getText() == "@Sendable") {
1049-
flags = flags.withConcurrent();
1049+
flags = flags.withSendable();
10501050
} else if (child->getText() == "@async") {
10511051
flags = flags.withAsync();
10521052
}

include/swift/RemoteInspection/TypeRefBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,7 @@ class TypeRefBuilder {
11621162
break;
11631163
}
11641164

1165-
funcFlags = funcFlags.withConcurrent(flags.isSendable());
1165+
funcFlags = funcFlags.withSendable(flags.isSendable());
11661166
funcFlags = funcFlags.withAsync(flags.isAsync());
11671167
funcFlags = funcFlags.withDifferentiable(flags.isDifferentiable());
11681168
extFuncFlags =

include/swift/SIL/SILInstruction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5740,6 +5740,9 @@ class ConvertFunctionInst final
57405740
/// argument and return types, as well as all other attributes, after substitution,
57415741
/// such as converting `$<A, B> in (A) -> B for <Int, String>` to `(Int) -> String`.
57425742
bool onlyConvertsSubstitutions() const;
5743+
5744+
/// Returns true if the source and destination types only differ by `@Sendable`.
5745+
bool onlyConvertsSendable() const;
57435746
};
57445747

57455748
/// ConvertEscapeToNoEscapeInst - Change the type of a escaping function value

lib/AST/ASTDemangler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ Type ASTBuilder::createFunctionType(
475475
resultDiffKind, clangFunctionType, isolation,
476476
LifetimeDependenceInfo(), extFlags.hasTransferringResult())
477477
.withAsync(flags.isAsync())
478-
.withConcurrent(flags.isSendable())
478+
.withSendable(flags.isSendable())
479479
.build();
480480

481481
return FunctionType::get(funcParams, output, einfo);

lib/AST/Builtins.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1565,7 +1565,7 @@ static ValueDecl *getCreateAsyncTask(ASTContext &ctx, Identifier id,
15651565
builder.addParameter(makeConcrete(ctx.TheExecutorType)); // executor
15661566
}
15671567
auto extInfo = ASTExtInfoBuilder().withAsync().withThrows()
1568-
.withConcurrent(true).build();
1568+
.withSendable(true).build();
15691569
Type operationResultType;
15701570
if (isDiscarding) {
15711571
operationResultType = TupleType::getEmpty(ctx); // ()

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3377,7 +3377,7 @@ mapSignatureExtInfo(AnyFunctionType::ExtInfo info,
33773377
return AnyFunctionType::ExtInfo();
33783378
return AnyFunctionType::ExtInfoBuilder()
33793379
.withRepresentation(info.getRepresentation())
3380-
.withConcurrent(info.isSendable())
3380+
.withSendable(info.isSendable())
33813381
.withAsync(info.isAsync())
33823382
.withThrows(info.isThrowing(), info.getThrownError())
33833383
.withClangFunctionType(info.getClangTypeInfo().getType())

lib/AST/Type.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,7 @@ Type TypeBase::stripConcurrency(bool recurse, bool dropGlobalActor) {
920920
// Strip off Sendable and (possibly) the global actor.
921921
ASTExtInfo extInfo =
922922
fnType->hasExtInfo() ? fnType->getExtInfo() : ASTExtInfo();
923-
extInfo = extInfo.withConcurrent(false);
923+
extInfo = extInfo.withSendable(false);
924924
if (dropGlobalActor)
925925
extInfo = extInfo.withoutIsolation();
926926

@@ -3156,12 +3156,12 @@ static bool matchesFunctionType(CanAnyFunctionType fn1, CanAnyFunctionType fn2,
31563156
// Removing '@Sendable' is ABI-compatible because there's nothing wrong with
31573157
// a function being sendable when it doesn't need to be.
31583158
if (!ext2.isSendable())
3159-
ext1 = ext1.withConcurrent(false);
3159+
ext1 = ext1.withSendable(false);
31603160
}
31613161

31623162
if (matchMode.contains(TypeMatchFlags::IgnoreFunctionSendability)) {
3163-
ext1 = ext1.withConcurrent(false);
3164-
ext2 = ext2.withConcurrent(false);
3163+
ext1 = ext1.withSendable(false);
3164+
ext2 = ext2.withSendable(false);
31653165
}
31663166

31673167
// If specified, allow an escaping function parameter to override a

lib/ClangImporter/ImportType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2005,7 +2005,7 @@ class GetSendableType :
20052005

20062006
Result visitAnyFunctionType(AnyFunctionType *ty) {
20072007
auto newFn = applyToFunctionType(ty, [](ASTExtInfo extInfo) {
2008-
return extInfo.withConcurrent();
2008+
return extInfo.withSendable();
20092009
});
20102010
return { newFn, true };
20112011
}

lib/IRGen/MetadataRequest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1428,7 +1428,7 @@ getFunctionTypeFlags(CanFunctionType type) {
14281428
auto flags = FunctionTypeFlags()
14291429
.withConvention(metadataConvention)
14301430
.withAsync(type->isAsync())
1431-
.withConcurrent(type->isSendable())
1431+
.withSendable(type->isSendable())
14321432
.withThrows(type->isThrowing())
14331433
.withParameterFlags(hasParameterFlags)
14341434
.withEscaping(isEscaping)

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,7 +2407,7 @@ static CanSILFunctionType getSILFunctionType(
24072407
}
24082408
auto silExtInfo = extInfoBuilder.withClangFunctionType(clangType)
24092409
.withIsPseudogeneric(pseudogeneric)
2410-
.withConcurrent(isSendable)
2410+
.withSendable(isSendable)
24112411
.withAsync(isAsync)
24122412
.withUnimplementable(unimplementable)
24132413
.withLifetimeDependenceInfo(
@@ -2493,7 +2493,7 @@ static CanSILFunctionType getSILFunctionTypeForInitAccessor(
24932493
auto silExtInfo =
24942494
SILExtInfoBuilder()
24952495
.withRepresentation(SILFunctionTypeRepresentation::Thin)
2496-
.withConcurrent(substAccessorType->getExtInfo().isSendable())
2496+
.withSendable(substAccessorType->getExtInfo().isSendable())
24972497
.build();
24982498

24992499
return SILFunctionType::get(

lib/SIL/IR/SILInstructions.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2744,6 +2744,16 @@ bool ConvertFunctionInst::onlyConvertsSubstitutions() const {
27442744
return fromType->getUnsubstitutedType(M) == toType->getUnsubstitutedType(M);
27452745
}
27462746

2747+
static SILFunctionType *getNonSendableFuncType(SILType ty) {
2748+
auto fnTy = ty.castTo<SILFunctionType>();
2749+
return fnTy->getWithExtInfo(fnTy->getExtInfo().withSendable(false));
2750+
}
2751+
2752+
bool ConvertFunctionInst::onlyConvertsSendable() const {
2753+
return getNonSendableFuncType(getOperand()->getType()) ==
2754+
getNonSendableFuncType(getType());
2755+
}
2756+
27472757
ConvertEscapeToNoEscapeInst *ConvertEscapeToNoEscapeInst::create(
27482758
SILDebugLocation DebugLoc, SILValue Operand, SILType Ty, SILFunction &F,
27492759
bool isLifetimeGuaranteed) {

lib/SIL/IR/TypeLowering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3783,7 +3783,7 @@ getFunctionInterfaceTypeWithCaptures(TypeConverter &TC,
37833783
AnyFunctionType::ExtInfoBuilder(FunctionType::Representation::Thin,
37843784
funcType->isThrowing(),
37853785
funcType->getThrownError())
3786-
.withConcurrent(funcType->isSendable())
3786+
.withSendable(funcType->isSendable())
37873787
.withAsync(funcType->isAsync())
37883788
.withIsolation(funcType->getIsolation())
37893789
.withLifetimeDependenceInfo(funcType->getLifetimeDependenceInfo())

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2305,7 +2305,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
23052305
auto fnType = requireObjectType(SILFunctionType, arguments[4],
23062306
"result of createAsyncTask");
23072307
auto expectedExtInfo =
2308-
SILExtInfoBuilder().withAsync(true).withConcurrent(true).build();
2308+
SILExtInfoBuilder().withAsync(true).withSendable(true).build();
23092309
require(fnType->getExtInfo().isEqualTo(expectedExtInfo, /*clang types*/true),
23102310
"function argument to createAsyncTask has incorrect ext info");
23112311
// FIXME: it'd be better if we took a consuming closure here

lib/SILGen/SILGenBridging.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1511,7 +1511,7 @@ SILFunction *SILGenFunction::emitNativeAsyncToForeignThunk(SILDeclRef thunk) {
15111511
auto closureExtInfo = objcFnTy->getExtInfo().intoBuilder()
15121512
.withRepresentation(SILFunctionTypeRepresentation::Thin)
15131513
.withAsync()
1514-
.withConcurrent()
1514+
.withSendable()
15151515
.build();
15161516
auto closureTy = objcFnTy->getWithExtInfo(closureExtInfo);
15171517

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,7 +1620,7 @@ static ManagedValue emitCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
16201620
ASTExtInfoBuilder()
16211621
.withAsync()
16221622
.withThrows()
1623-
.withConcurrent(true)
1623+
.withSendable(true)
16241624
.withRepresentation(GenericFunctionType::Representation::Swift)
16251625
.build();
16261626

@@ -1733,7 +1733,7 @@ SILGenFunction::emitCreateAsyncMainTask(SILLocation loc, SubstitutionMap subs,
17331733
CanType flagsType = ctx.getIntType()->getCanonicalType();
17341734
CanType functionType =
17351735
FunctionType::get({}, ctx.TheEmptyTupleType,
1736-
ASTExtInfo().withAsync().withThrows().withConcurrent(true))
1736+
ASTExtInfo().withAsync().withThrows().withSendable(true))
17371737
->getCanonicalType();
17381738

17391739
using Param = FunctionType::Param;

lib/SILGen/SILGenExpr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2904,12 +2904,12 @@ static bool canEmitClosureFunctionUnderConversion(
29042904
// interferes with the implementation of `reasync`.
29052905
auto literalWithoutEffects = literalFnType->getExtInfo().intoBuilder()
29062906
.withNoEscape(false)
2907-
.withConcurrent(false)
2907+
.withSendable(false)
29082908
.withThrows(false, Type());
29092909

29102910
auto convertedWithoutEffects = convertedFnType->getExtInfo().intoBuilder()
29112911
.withNoEscape(false)
2912-
.withConcurrent(false)
2912+
.withSendable(false)
29132913
.withThrows(false, Type());
29142914

29152915
// If the converted type has erased isolation, remove the isolation from

lib/SILOptimizer/Mandatory/MandatoryInlining.cpp

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,20 @@ static SILValue getLoadedCalleeValue(LoadInst *li) {
592592
return si->getSrc();
593593
}
594594

595+
static bool convertsThinEscapeToNoescape(ConvertFunctionInst *cv) {
596+
// Example:
597+
// %1 = function_ref @thin_closure_impl : $() -> ()
598+
// %2 = convert_function %1 : $() -> () to $@noescape () -> ()
599+
//
600+
auto fromTy = cv->getOperand()->getType().castTo<SILFunctionType>();
601+
if (fromTy->getExtInfo().hasContext())
602+
return false;
603+
604+
auto toTy = cv->getType().castTo<SILFunctionType>();
605+
auto escapeToTy = toTy->getWithExtInfo(toTy->getExtInfo().withNoEscape(false));
606+
return fromTy == escapeToTy;
607+
}
608+
595609
// PartialApply/ThinToThick -> ConvertFunction patterns are generated
596610
// by @noescape closures.
597611
//
@@ -602,32 +616,13 @@ static SILValue stripFunctionConversions(SILValue CalleeValue) {
602616
// Skip any copies that we see.
603617
CalleeValue = lookThroughOwnershipInsts(CalleeValue);
604618

605-
// We can also allow a thin @escape to noescape conversion as such:
606-
// %1 = function_ref @thin_closure_impl : $@convention(thin) () -> ()
607-
// %2 = convert_function %1 :
608-
// $@convention(thin) () -> () to $@convention(thin) @noescape () -> ()
609-
// %3 = thin_to_thick_function %2 :
610-
// $@convention(thin) @noescape () -> () to
611-
// $@noescape @callee_guaranteed () -> ()
612-
// %4 = apply %3() : $@noescape @callee_guaranteed () -> ()
613619
if (auto *ConvertFn = dyn_cast<ConvertFunctionInst>(CalleeValue)) {
614-
// If the conversion only changes the substitution level of the function,
615-
// we can also look through it.
616-
if (ConvertFn->onlyConvertsSubstitutions())
620+
if (ConvertFn->onlyConvertsSubstitutions() ||
621+
ConvertFn->onlyConvertsSendable() ||
622+
convertsThinEscapeToNoescape(ConvertFn)) {
617623
return stripFunctionConversions(ConvertFn->getOperand());
618-
619-
auto FromCalleeTy =
620-
ConvertFn->getOperand()->getType().castTo<SILFunctionType>();
621-
if (FromCalleeTy->getExtInfo().hasContext())
622-
return CalleeValue;
623-
624-
auto ToCalleeTy = ConvertFn->getType().castTo<SILFunctionType>();
625-
auto EscapingCalleeTy = ToCalleeTy->getWithExtInfo(
626-
ToCalleeTy->getExtInfo().withNoEscape(false));
627-
if (FromCalleeTy != EscapingCalleeTy)
628-
return CalleeValue;
629-
630-
return lookThroughOwnershipInsts(ConvertFn->getOperand());
624+
}
625+
return CalleeValue;
631626
}
632627

633628
// Ignore mark_dependence users. A partial_apply [stack] uses them to mark

lib/SILOptimizer/Utils/ConstExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ SymbolicValue ConstExprFunctionState::computeConstantValue(SILValue value) {
520520
// TODO: Certain covariant or otherwise ABI-compatible conversions should
521521
// be handled as well.
522522
if (auto cf = dyn_cast<ConvertFunctionInst>(value)) {
523-
if (cf->onlyConvertsSubstitutions()) {
523+
if (cf->onlyConvertsSubstitutions() || cf->onlyConvertsSendable()) {
524524
return getConstantValue(cf->getOperand());
525525
}
526526
}

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2122,7 +2122,7 @@ Type swift::adjustInferredAssociatedType(TypeAdjustment adjustment, Type type,
21222122
if (adjustment == TypeAdjustment::NoescapeToEscaping)
21232123
return info.withNoEscape(false);
21242124
else
2125-
return info.withConcurrent(true);
2125+
return info.withSendable(true);
21262126
};
21272127

21282128
// If we have a noescape function type, make it escaping.

lib/Sema/CSApply.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7349,7 +7349,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
73497349
// to the closure without invalidating prior analysis.
73507350
auto fromEI = fromFunc->getExtInfo();
73517351
if (toEI.isSendable() && !fromEI.isSendable()) {
7352-
auto newFromFuncType = fromFunc->withExtInfo(fromEI.withConcurrent());
7352+
auto newFromFuncType = fromFunc->withExtInfo(fromEI.withSendable());
73537353
if (applyTypeToClosureExpr(cs, expr, newFromFuncType)) {
73547354
fromFunc = newFromFuncType->castTo<FunctionType>();
73557355

@@ -8949,7 +8949,7 @@ static Expr *wrapAsyncLetInitializer(
89498949
.has_value();
89508950
auto extInfo = ASTExtInfoBuilder()
89518951
.withAsync()
8952-
.withConcurrent()
8952+
.withSendable()
89538953
.withThrows(throws, /*FIXME:*/Type())
89548954
.build();
89558955

lib/Sema/CSBindings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ bool BindingSet::finalize(
671671
bool isKeyPathSendable = capability && capability->second;
672672
if (!isKeyPathSendable && extInfo.isSendable()) {
673673
fnType = FunctionType::get(fnType->getParams(), fnType->getResult(),
674-
extInfo.withConcurrent(false));
674+
extInfo.withSendable(false));
675675
}
676676

677677
updatedBindings.insert(binding.withType(fnType));

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11879,7 +11879,7 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
1187911879
auto closureExtInfo = inferredClosureType->getExtInfo();
1188011880
if (auto contextualFnType = contextualType->getAs<FunctionType>()) {
1188111881
if (contextualFnType->isSendable())
11882-
closureExtInfo = closureExtInfo.withConcurrent();
11882+
closureExtInfo = closureExtInfo.withSendable();
1188311883
}
1188411884

1188511885
// Isolated parameters override any other kind of isolation we might infer.

0 commit comments

Comments
 (0)