Skip to content

Commit f9e3e50

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 4c347d2 commit f9e3e50

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
@@ -4530,7 +4530,8 @@ class ConstraintSystem {
45304530
Type getUnopenedTypeOfReference(VarDecl *value, Type baseType,
45314531
DeclContext *UseDC,
45324532
ConstraintLocator *memberLocator = nullptr,
4533-
bool wantInterfaceType = false);
4533+
bool wantInterfaceType = false,
4534+
bool adjustForPreconcurrency = true);
45344535

45354536
/// Return the type-of-reference of the given value.
45364537
///
@@ -4552,6 +4553,7 @@ class ConstraintSystem {
45524553
llvm::function_ref<Type(VarDecl *)> getType,
45534554
ConstraintLocator *memberLocator = nullptr,
45544555
bool wantInterfaceType = false,
4556+
bool adjustForPreconcurrency = true,
45554557
llvm::function_ref<Type(const AbstractClosureExpr *)> getClosureType =
45564558
[](const AbstractClosureExpr *) {
45574559
return Type();

lib/Sema/CSApply.cpp

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

914914
auto &context = cs.getASTContext();
915915

916+
// turn LValues into RValues first
917+
if (openedType->hasLValueType()) {
918+
assert(adjustedOpenedType->hasLValueType() && "lvalue-ness mismatch?");
919+
return adjustTypeForDeclReference(cs.coerceToRValue(expr),
920+
openedType->getRValueType(),
921+
adjustedOpenedType->getRValueType(),
922+
getNewType);
923+
}
924+
916925
// If we have an optional type, wrap it up in a monadic '?' and recurse.
917926
if (Type objectType = openedType->getOptionalObjectType()) {
918927
Type adjustedRefType = getNewType(adjustedOpenedType);
@@ -1700,10 +1709,17 @@ namespace {
17001709
adjustedRefTy = adjustedRefTy->replaceCovariantResultType(
17011710
containerTy, 1);
17021711
}
1703-
cs.setType(memberRefExpr, refTy->castTo<FunctionType>()->getResult());
1712+
1713+
// \returns result of the given function type
1714+
auto resultType = [](Type fnTy) -> Type {
1715+
return fnTy->castTo<FunctionType>()->getResult();
1716+
};
1717+
1718+
cs.setType(memberRefExpr, resultType(refTy));
17041719

17051720
Expr *result = memberRefExpr;
1706-
result = adjustTypeForDeclReference(result, refTy, adjustedRefTy);
1721+
result = adjustTypeForDeclReference(result, resultType(refTy),
1722+
resultType(adjustedRefTy));
17071723
closeExistentials(result, locator);
17081724

17091725
// 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
@@ -1210,7 +1210,8 @@ ClosureIsolatedByPreconcurrency::operator()(const ClosureExpr *expr) const {
12101210

12111211
Type ConstraintSystem::getUnopenedTypeOfReference(
12121212
VarDecl *value, Type baseType, DeclContext *UseDC,
1213-
ConstraintLocator *memberLocator, bool wantInterfaceType) {
1213+
ConstraintLocator *memberLocator, bool wantInterfaceType,
1214+
bool adjustForPreconcurrency) {
12141215
return ConstraintSystem::getUnopenedTypeOfReference(
12151216
value, baseType, UseDC,
12161217
[&](VarDecl *var) -> Type {
@@ -1223,22 +1224,25 @@ Type ConstraintSystem::getUnopenedTypeOfReference(
12231224

12241225
return wantInterfaceType ? var->getInterfaceType() : var->getType();
12251226
},
1226-
memberLocator, wantInterfaceType, GetClosureType{*this},
1227+
memberLocator, wantInterfaceType, adjustForPreconcurrency,
1228+
GetClosureType{*this},
12271229
ClosureIsolatedByPreconcurrency{*this});
12281230
}
12291231

12301232
Type ConstraintSystem::getUnopenedTypeOfReference(
12311233
VarDecl *value, Type baseType, DeclContext *UseDC,
12321234
llvm::function_ref<Type(VarDecl *)> getType,
1233-
ConstraintLocator *memberLocator, bool wantInterfaceType,
1235+
ConstraintLocator *memberLocator,
1236+
bool wantInterfaceType, bool adjustForPreconcurrency,
12341237
llvm::function_ref<Type(const AbstractClosureExpr *)> getClosureType,
12351238
llvm::function_ref<bool(const ClosureExpr *)> isolatedByPreconcurrency) {
12361239
Type requestedType =
12371240
getType(value)->getWithoutSpecifierType()->getReferenceStorageReferent();
12381241

1239-
// Adjust the type for concurrency.
1240-
requestedType = adjustVarTypeForConcurrency(
1241-
requestedType, value, UseDC, getClosureType, isolatedByPreconcurrency);
1242+
// Adjust the type for concurrency if requested.
1243+
if (adjustForPreconcurrency)
1244+
requestedType = adjustVarTypeForConcurrency(
1245+
requestedType, value, UseDC, getClosureType, isolatedByPreconcurrency);
12421246

12431247
// If we're dealing with contextual types, and we referenced this type from
12441248
// a different context, map the type.
@@ -2260,9 +2264,14 @@ ConstraintSystem::getTypeOfMemberReference(
22602264
FunctionType::ExtInfo info;
22612265
refType = FunctionType::get(indices, elementTy, info);
22622266
} else {
2267+
// Delay the adjustment for preconcurrency until after we've formed
2268+
// the function type for this kind of reference. Otherwise we will lose
2269+
// track of the adjustment in the formed function's return type.
2270+
22632271
refType = getUnopenedTypeOfReference(cast<VarDecl>(value), baseTy, useDC,
22642272
locator,
2265-
/*wantInterfaceType=*/true);
2273+
/*wantInterfaceType=*/true,
2274+
/*adjustForPreconcurrency=*/false);
22662275
}
22672276

22682277
auto selfTy = outerDC->getSelfInterfaceType();
@@ -2383,6 +2392,16 @@ ConstraintSystem::getTypeOfMemberReference(
23832392
openedType = adjustFunctionTypeForConcurrency(
23842393
origOpenedType->castTo<AnyFunctionType>(), subscript, useDC,
23852394
/*numApplies=*/2, /*isMainDispatchQueue=*/false, replacements);
2395+
} else if (auto var = dyn_cast<VarDecl>(value)) {
2396+
// Adjust the function's result type, since that's the Var's actual type.
2397+
auto origFnType = origOpenedType->castTo<AnyFunctionType>();
2398+
2399+
auto resultTy = adjustVarTypeForConcurrency(
2400+
origFnType->getResult(), var, useDC, GetClosureType{*this},
2401+
ClosureIsolatedByPreconcurrency{*this});
2402+
2403+
openedType = FunctionType::get(
2404+
origFnType->getParams(), resultTy, origFnType->getExtInfo());
23862405
}
23872406

23882407
// Compute the type of the reference.

0 commit comments

Comments
 (0)