Skip to content

Commit 171fb0a

Browse files
committed
[CSSimplify] Synthesize conformances for ad-hoc distributed witness requirements
Instead of handing failures in `matchWitness` let's syntehsize conformances during solving. Next step would be to record them and use in `Solution::computeSubstitutions`.
1 parent c05497f commit 171fb0a

File tree

3 files changed

+48
-32
lines changed

3 files changed

+48
-32
lines changed

include/swift/Sema/ConstraintLocator.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,37 @@ class ConstraintLocatorBuilder {
12931293
return false;
12941294
}
12951295

1296+
std::optional<std::pair</*witness=*/ValueDecl *, GenericTypeParamType *>>
1297+
isForWitnessGenericParameterRequirement() const {
1298+
SmallVector<LocatorPathElt, 2> path;
1299+
getLocatorParts(path);
1300+
1301+
// -> witness -> generic env -> requirement
1302+
if (path.size() < 3)
1303+
return std::nullopt;
1304+
1305+
GenericTypeParamType *GP = nullptr;
1306+
if (auto reqLoc =
1307+
path.back().getAs<LocatorPathElt::TypeParameterRequirement>()) {
1308+
path.pop_back();
1309+
if (auto openedGeneric =
1310+
path.back().getAs<LocatorPathElt::OpenedGeneric>()) {
1311+
auto signature = openedGeneric->getSignature();
1312+
auto requirement = signature.getRequirements()[reqLoc->getIndex()];
1313+
GP = requirement.getFirstType()->getAs<GenericTypeParamType>();
1314+
}
1315+
}
1316+
1317+
if (!GP)
1318+
return std::nullopt;
1319+
1320+
auto witness = path.front().getAs<LocatorPathElt::Witness>();
1321+
if (!witness)
1322+
return std::nullopt;
1323+
1324+
return std::make_pair(witness->getDecl(), GP);
1325+
}
1326+
12961327
/// Checks whether this locator is describing an argument application for a
12971328
/// non-ephemeral parameter.
12981329
bool isNonEphemeralParameterApplication() const {

lib/Sema/CSSimplify.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8572,6 +8572,23 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
85728572
if (conformance) {
85738573
return recordConformance(conformance);
85748574
}
8575+
8576+
// Account for ad-hoc requirements on some distributed actor
8577+
// requirements.
8578+
if (auto witnessInfo = locator.isForWitnessGenericParameterRequirement()) {
8579+
auto *GP = witnessInfo->second;
8580+
8581+
// Conformance requirement between on `Res` and `SerializationRequirement`
8582+
// of `DistributedActorSystem.remoteCall` are not expressible at the moment
8583+
// but they are verified by Sema so it's okay to omit them here and lookup
8584+
// dynamically during IRGen.
8585+
if (auto *witness = dyn_cast<FuncDecl>(witnessInfo->first)) {
8586+
if (witness->isDistributedActorSystemRemoteCall(/*isVoidReturn=*/false)) {
8587+
if (GP->isEqual(cast<FuncDecl>(witness)->getResultInterfaceType()))
8588+
return recordConformance(ProtocolConformanceRef(protocol));
8589+
}
8590+
}
8591+
}
85758592
} break;
85768593

85778594
default:

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,38 +1246,6 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache,
12461246
}))
12471247
return true;
12481248

1249-
auto *funcDecl = dyn_cast<AbstractFunctionDecl>(req);
1250-
// Conformance requirement between on `Res` and `SerializationRequirement`
1251-
// of `DistributedActorSystem.remoteCall` are not expressible at the moment
1252-
// but they are verified by Sema so it's okay to omit them here and lookup
1253-
// dynamically during IRGen.
1254-
if (funcDecl && funcDecl->isDistributedActorSystemRemoteCallRequirement(
1255-
/*withResult=*/true)) {
1256-
if (llvm::all_of(solution.Fixes, [&witness](constraints::ConstraintFix
1257-
*fix) {
1258-
auto conformance = dyn_cast<MissingConformance>(fix);
1259-
if (!conformance)
1260-
return false;
1261-
1262-
auto *locator = fix->getLocator();
1263-
auto requirement = locator->getLastElementAs<
1264-
LocatorPathElt::TypeParameterRequirement>();
1265-
if (!requirement)
1266-
return false;
1267-
1268-
auto signature =
1269-
locator->findLast<LocatorPathElt::OpenedGeneric>()
1270-
->getSignature();
1271-
1272-
auto subject =
1273-
signature.getRequirements()[requirement->getIndex()]
1274-
.getFirstType();
1275-
// `Res` is the result type so we can check against that.
1276-
return subject->isEqual(
1277-
cast<FuncDecl>(witness)->getResultInterfaceType());
1278-
}))
1279-
return true;
1280-
}
12811249
// In all other cases - disallow the match.
12821250
return false;
12831251
};

0 commit comments

Comments
 (0)