Skip to content

Commit d60835e

Browse files
committed
[ConstraintSystem] correct the @preconcurrency adjustment of var references
We intended to introduce AST conversions that strip concurrency attributes off of types associated with `@preconcurrency` decls. But for VarDecl references, we stripped it too early, leading to things like a MemberVarDecl that doesn't have `@Sendable` in its result type, but the VarDecl it refers to does have it. That caused crashes in SIL where types didn't match up. This patch fixes things by delaying the stripping until the right point. resolves rdar://98018067
1 parent ba001ec commit d60835e

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4764,7 +4764,8 @@ class ConstraintSystem {
47644764
Type getUnopenedTypeOfReference(VarDecl *value, Type baseType,
47654765
DeclContext *UseDC,
47664766
ConstraintLocator *memberLocator = nullptr,
4767-
bool wantInterfaceType = false);
4767+
bool wantInterfaceType = false,
4768+
bool adjustForPreconcurrency = true);
47684769

47694770
/// Return the type-of-reference of the given value.
47704771
///
@@ -4786,6 +4787,7 @@ class ConstraintSystem {
47864787
llvm::function_ref<Type(VarDecl *)> getType,
47874788
ConstraintLocator *memberLocator = nullptr,
47884789
bool wantInterfaceType = false,
4790+
bool adjustForPreconcurrency = true,
47894791
llvm::function_ref<Type(const AbstractClosureExpr *)> getClosureType =
47904792
[](const AbstractClosureExpr *) {
47914793
return Type();

lib/Sema/CSApply.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,15 @@ namespace {
919919

920920
auto &context = cs.getASTContext();
921921

922+
// turn LValues into RValues first
923+
if (openedType->hasLValueType()) {
924+
assert(adjustedOpenedType->hasLValueType() && "lvalue-ness mismatch?");
925+
return adjustTypeForDeclReference(cs.coerceToRValue(expr),
926+
openedType->getRValueType(),
927+
adjustedOpenedType->getRValueType(),
928+
getNewType);
929+
}
930+
922931
// If we have an optional type, wrap it up in a monadic '?' and recurse.
923932
if (Type objectType = openedType->getOptionalObjectType()) {
924933
Type adjustedRefType = getNewType(adjustedOpenedType);
@@ -1669,10 +1678,17 @@ namespace {
16691678
adjustedRefTy = adjustedRefTy->replaceCovariantResultType(
16701679
containerTy, 1);
16711680
}
1672-
cs.setType(memberRefExpr, refTy->castTo<FunctionType>()->getResult());
1681+
1682+
// \returns result of the given function type
1683+
auto resultType = [](Type fnTy) -> Type {
1684+
return fnTy->castTo<FunctionType>()->getResult();
1685+
};
1686+
1687+
cs.setType(memberRefExpr, resultType(refTy));
16731688

16741689
Expr *result = memberRefExpr;
1675-
result = adjustTypeForDeclReference(result, refTy, adjustedRefTy);
1690+
result = adjustTypeForDeclReference(result, resultType(refTy),
1691+
resultType(adjustedRefTy));
16761692
closeExistentials(result, locator);
16771693

16781694
// If the property is of dynamic 'Self' type, wrap an implicit

lib/Sema/ConstraintSystem.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,7 +1259,8 @@ ClosureIsolatedByPreconcurrency::operator()(const ClosureExpr *expr) const {
12591259

12601260
Type ConstraintSystem::getUnopenedTypeOfReference(
12611261
VarDecl *value, Type baseType, DeclContext *UseDC,
1262-
ConstraintLocator *memberLocator, bool wantInterfaceType) {
1262+
ConstraintLocator *memberLocator, bool wantInterfaceType,
1263+
bool adjustForPreconcurrency) {
12631264
return ConstraintSystem::getUnopenedTypeOfReference(
12641265
value, baseType, UseDC,
12651266
[&](VarDecl *var) -> Type {
@@ -1272,22 +1273,25 @@ Type ConstraintSystem::getUnopenedTypeOfReference(
12721273

12731274
return wantInterfaceType ? var->getInterfaceType() : var->getType();
12741275
},
1275-
memberLocator, wantInterfaceType, GetClosureType{*this},
1276+
memberLocator, wantInterfaceType, adjustForPreconcurrency,
1277+
GetClosureType{*this},
12761278
ClosureIsolatedByPreconcurrency{*this});
12771279
}
12781280

12791281
Type ConstraintSystem::getUnopenedTypeOfReference(
12801282
VarDecl *value, Type baseType, DeclContext *UseDC,
12811283
llvm::function_ref<Type(VarDecl *)> getType,
1282-
ConstraintLocator *memberLocator, bool wantInterfaceType,
1284+
ConstraintLocator *memberLocator,
1285+
bool wantInterfaceType, bool adjustForPreconcurrency,
12831286
llvm::function_ref<Type(const AbstractClosureExpr *)> getClosureType,
12841287
llvm::function_ref<bool(const ClosureExpr *)> isolatedByPreconcurrency) {
12851288
Type requestedType =
12861289
getType(value)->getWithoutSpecifierType()->getReferenceStorageReferent();
12871290

1288-
// Adjust the type for concurrency.
1289-
requestedType = adjustVarTypeForConcurrency(
1290-
requestedType, value, UseDC, getClosureType, isolatedByPreconcurrency);
1291+
// Adjust the type for concurrency if requested.
1292+
if (adjustForPreconcurrency)
1293+
requestedType = adjustVarTypeForConcurrency(
1294+
requestedType, value, UseDC, getClosureType, isolatedByPreconcurrency);
12911295

12921296
// If we're dealing with contextual types, and we referenced this type from
12931297
// a different context, map the type.
@@ -2309,9 +2313,14 @@ ConstraintSystem::getTypeOfMemberReference(
23092313
FunctionType::ExtInfo info;
23102314
refType = FunctionType::get(indices, elementTy, info);
23112315
} else {
2316+
// Delay the adjustment for preconcurrency until after we've formed
2317+
// the function type for this kind of reference. Otherwise we will lose
2318+
// track of the adjustment in the formed function's return type.
2319+
23122320
refType = getUnopenedTypeOfReference(cast<VarDecl>(value), baseTy, useDC,
23132321
locator,
2314-
/*wantInterfaceType=*/true);
2322+
/*wantInterfaceType=*/true,
2323+
/*adjustForPreconcurrency=*/false);
23152324
}
23162325

23172326
auto selfTy = outerDC->getSelfInterfaceType();
@@ -2432,6 +2441,16 @@ ConstraintSystem::getTypeOfMemberReference(
24322441
openedType = adjustFunctionTypeForConcurrency(
24332442
origOpenedType->castTo<AnyFunctionType>(), subscript, useDC,
24342443
/*numApplies=*/2, /*isMainDispatchQueue=*/false, replacements);
2444+
} else if (auto var = dyn_cast<VarDecl>(value)) {
2445+
// Adjust the function's result type, since that's the Var's actual type.
2446+
auto origFnType = origOpenedType->castTo<AnyFunctionType>();
2447+
2448+
auto resultTy = adjustVarTypeForConcurrency(
2449+
origFnType->getResult(), var, useDC, GetClosureType{*this},
2450+
ClosureIsolatedByPreconcurrency{*this});
2451+
2452+
openedType = FunctionType::get(
2453+
origFnType->getParams(), resultTy, origFnType->getExtInfo());
24352454
}
24362455

24372456
// Compute the type of the reference.

0 commit comments

Comments
 (0)