Skip to content

Commit 7d8f3e6

Browse files
committed
AST: Change return type of Requirement::subst() to Requirement
Instead of returning None, let callers check hasError() if they need to. Fixes rdar://problem/98565072.
1 parent eb7a23f commit 7d8f3e6

14 files changed

+47
-65
lines changed

include/swift/AST/Requirement.h

+2-8
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,15 @@ class Requirement
5353

5454
/// Subst the types involved in this requirement.
5555
///
56-
/// The \c args arguments are passed through to Type::subst. This doesn't
57-
/// touch the superclasses, protocols or layout constraints.
56+
/// The \c args arguments are passed through to Type::subst.
5857
template <typename ...Args>
59-
llvm::Optional<Requirement> subst(Args &&...args) const {
58+
Requirement subst(Args &&...args) const {
6059
auto newFirst = getFirstType().subst(std::forward<Args>(args)...);
61-
if (newFirst->hasError())
62-
return None;
63-
6460
switch (getKind()) {
6561
case RequirementKind::Conformance:
6662
case RequirementKind::Superclass:
6763
case RequirementKind::SameType: {
6864
auto newSecond = getSecondType().subst(std::forward<Args>(args)...);
69-
if (newSecond->hasError())
70-
return None;
7165
return Requirement(getKind(), newFirst, newSecond);
7266
}
7367
case RequirementKind::Layout:

lib/AST/ASTContext.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -5307,10 +5307,9 @@ ASTContext::getOverrideGenericSignature(const NominalTypeDecl *baseNominal,
53075307
baseGenericSig, derivedParams);
53085308

53095309
for (auto reqt : baseGenericSig.getRequirements()) {
5310-
if (auto substReqt = reqt.subst(QueryOverrideSubs(info),
5311-
LookUpConformanceInOverrideSubs(info))) {
5312-
addedRequirements.push_back(*substReqt);
5313-
}
5310+
auto substReqt = reqt.subst(QueryOverrideSubs(info),
5311+
LookUpConformanceInOverrideSubs(info));
5312+
addedRequirements.push_back(substReqt);
53145313
}
53155314

53165315
auto genericSig = buildGenericSignature(*this, derivedNominalSig,

lib/AST/ExistentialGeneralization.cpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,7 @@ class Generalizer : public CanTypeVisitor<Generalizer, Type> {
213213
if (origReq.getKind() != RequirementKind::Conformance) continue;
214214
auto origConformance = origConformances[i++];
215215

216-
auto optNewReq = origReq.subst(newSubs);
217-
assert(optNewReq && "generalization substitution failed");
218-
auto &newReq = *optNewReq;
219-
216+
auto newReq = origReq.subst(newSubs);
220217
addedRequirements.push_back(newReq);
221218

222219
substConformances.insert({{newReq.getFirstType()->getCanonicalType(),

lib/AST/GenericSignature.cpp

+1-6
Original file line numberDiff line numberDiff line change
@@ -373,19 +373,14 @@ bool GenericSignatureImpl::isRequirementSatisfied(
373373
if (requirement.getFirstType()->hasTypeParameter()) {
374374
auto *genericEnv = getGenericEnvironment();
375375

376-
auto substituted = requirement.subst(
376+
requirement = requirement.subst(
377377
[&](SubstitutableType *type) -> Type {
378378
if (auto *paramType = type->getAs<GenericTypeParamType>())
379379
return genericEnv->mapTypeIntoContext(paramType);
380380

381381
return type;
382382
},
383383
LookUpConformanceInSignature(this));
384-
385-
if (!substituted)
386-
return false;
387-
388-
requirement = *substituted;
389384
}
390385

391386
// FIXME: Need to check conditional requirements here.

lib/AST/ProtocolConformance.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -962,9 +962,9 @@ void SpecializedProtocolConformance::computeConditionalRequirements() const {
962962

963963
SmallVector<Requirement, 4> newReqs;
964964
for (auto oldReq : *parentCondReqs) {
965-
if (auto newReq = oldReq.subst(QuerySubstitutionMap{subMap},
966-
LookUpConformanceInModule(module)))
967-
newReqs.push_back(*newReq);
965+
auto newReq = oldReq.subst(QuerySubstitutionMap{subMap},
966+
LookUpConformanceInModule(module));
967+
newReqs.push_back(newReq);
968968
}
969969
auto &ctxt = getProtocol()->getASTContext();
970970
ConditionalRequirements = ctxt.AllocateCopy(newReqs);
@@ -1163,7 +1163,7 @@ ProtocolConformance::subst(TypeSubstitutionFn subs,
11631163

11641164
SmallVector<Requirement, 2> requirements;
11651165
for (auto req : getConditionalRequirements()) {
1166-
requirements.push_back(*req.subst(subs, conformances, options));
1166+
requirements.push_back(req.subst(subs, conformances, options));
11671167
}
11681168

11691169
auto kind = cast<BuiltinProtocolConformance>(this)

lib/AST/RequirementEnvironment.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,9 @@ RequirementEnvironment::RequirementEnvironment(
179179

180180
if (conformanceSig) {
181181
for (auto &rawReq : conformanceSig.getRequirements()) {
182-
if (auto req = rawReq.subst(conformanceToWitnessThunkTypeFn,
183-
conformanceToWitnessThunkConformanceFn))
184-
requirements.push_back(*req);
182+
auto req = rawReq.subst(conformanceToWitnessThunkTypeFn,
183+
conformanceToWitnessThunkConformanceFn);
184+
requirements.push_back(req);
185185
}
186186
}
187187

@@ -205,8 +205,8 @@ RequirementEnvironment::RequirementEnvironment(
205205
// Next, add each of the requirements (mapped from the requirement's
206206
// interface types into the abstract type parameters).
207207
for (auto &rawReq : reqSig.getRequirements()) {
208-
if (auto req = rawReq.subst(reqToWitnessThunkSigMap))
209-
requirements.push_back(*req);
208+
auto req = rawReq.subst(reqToWitnessThunkSigMap);
209+
requirements.push_back(req);
210210
}
211211

212212
witnessThunkSig = buildGenericSignature(ctx, GenericSignature(),

lib/AST/RequirementMachine/RequirementLowering.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -465,8 +465,7 @@ struct InferRequirementsWalker : public TypeWalker {
465465
auto decl = typeAlias->getDecl();
466466
auto subMap = typeAlias->getSubstitutionMap();
467467
for (const auto &rawReq : decl->getGenericSignature().getRequirements()) {
468-
if (auto req = rawReq.subst(subMap))
469-
desugarRequirement(*req, SourceLoc(), reqs, errors);
468+
desugarRequirement(rawReq.subst(subMap), SourceLoc(), reqs, errors);
470469
}
471470

472471
return Action::Continue;
@@ -532,8 +531,8 @@ struct InferRequirementsWalker : public TypeWalker {
532531
// Handle the requirements.
533532
// FIXME: Inaccurate TypeReprs.
534533
for (const auto &rawReq : genericSig.getRequirements()) {
535-
if (auto req = rawReq.subst(subMap))
536-
desugarRequirement(*req, SourceLoc(), reqs, errors);
534+
auto req = rawReq.subst(subMap);
535+
desugarRequirement(req, SourceLoc(), reqs, errors);
537536
}
538537

539538
return Action::Continue;

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ AbstractGenericSignatureRequest::evaluate(
596596
},
597597
MakeAbstractConformanceForGenericType(),
598598
SubstFlags::AllowLoweredTypes);
599-
resugaredRequirements.push_back(*resugaredReq);
599+
resugaredRequirements.push_back(resugaredReq);
600600
}
601601

602602
return GenericSignatureWithError(

lib/AST/Type.cpp

+3-13
Original file line numberDiff line numberDiff line change
@@ -4523,26 +4523,16 @@ static Type substGenericFunctionType(GenericFunctionType *genericFnType,
45234523
for (const auto &req : genericFnType->getRequirements()) {
45244524
// Substitute into the requirement.
45254525
auto substReqt = req.subst(substitutions, lookupConformances, options);
4526-
if (!substReqt) {
4527-
anySemanticChanges = true;
4528-
continue;
4529-
}
45304526

45314527
// Did anything change?
45324528
if (!anySemanticChanges &&
4533-
(!req.getFirstType()->isEqual(substReqt->getFirstType()) ||
4529+
(!req.getFirstType()->isEqual(substReqt.getFirstType()) ||
45344530
(req.getKind() != RequirementKind::Layout &&
4535-
!req.getSecondType()->isEqual(substReqt->getSecondType())))) {
4531+
!req.getSecondType()->isEqual(substReqt.getSecondType())))) {
45364532
anySemanticChanges = true;
45374533
}
45384534

4539-
// Skip any erroneous requirements.
4540-
if (substReqt->getFirstType()->hasError() ||
4541-
(substReqt->getKind() != RequirementKind::Layout &&
4542-
substReqt->getSecondType()->hasError()))
4543-
continue;
4544-
4545-
requirements.push_back(*substReqt);
4535+
requirements.push_back(substReqt);
45464536
}
45474537

45484538
GenericSignature genericSig;

lib/IDE/IDETypeChecking.cpp

+5-7
Original file line numberDiff line numberDiff line change
@@ -323,15 +323,13 @@ struct SynthesizedExtensionAnalyzer::Implementation {
323323
if (!BaseType->isExistentialType()) {
324324
// Apply any substitutions we need to map the requirements from a
325325
// a protocol extension to an extension on the conforming type.
326-
auto SubstReq = Req.subst(subMap);
327-
if (!SubstReq) {
326+
Req = Req.subst(subMap);
327+
if (Req.hasError()) {
328328
// Substitution with interface type bases can only fail
329329
// if a concrete type fails to conform to a protocol.
330330
// In this case, just give up on the extension altogether.
331331
return true;
332332
}
333-
334-
Req = *SubstReq;
335333
}
336334

337335
assert(!Req.getFirstType()->hasArchetype());
@@ -346,13 +344,13 @@ struct SynthesizedExtensionAnalyzer::Implementation {
346344
return type;
347345
},
348346
LookUpConformanceInModule(M));
349-
if (!SubstReq)
347+
if (SubstReq.hasError())
350348
return true;
351349

352350
// FIXME: Need to handle conditional requirements here!
353351
ArrayRef<Requirement> conditionalRequirements;
354-
if (!SubstReq->isSatisfied(conditionalRequirements)) {
355-
if (!SubstReq->canBeSatisfied())
352+
if (!SubstReq.isSatisfied(conditionalRequirements)) {
353+
if (!SubstReq.canBeSatisfied())
356354
return true;
357355

358356
MergeInfo.addRequirement(Req);

lib/SILOptimizer/Utils/Generics.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1553,7 +1553,7 @@ void FunctionSignaturePartialSpecializer::addRequirements(
15531553
for (auto &reqReq : Reqs) {
15541554
LLVM_DEBUG(llvm::dbgs() << "\n\nRe-mapping the requirement:\n";
15551555
reqReq.dump(llvm::dbgs()));
1556-
AllRequirements.push_back(*reqReq.subst(SubsMap));
1556+
AllRequirements.push_back(reqReq.subst(SubsMap));
15571557
}
15581558
}
15591559

lib/Sema/TypeCheckGeneric.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -868,9 +868,10 @@ CheckGenericArgumentsResult TypeChecker::checkGenericArgumentsForDiagnostics(
868868
Requirement substReq = req;
869869
if (isPrimaryReq) {
870870
// Primary requirements do not have substitutions applied.
871-
if (auto resolved =
872-
req.subst(substitutions, LookUpConformanceInModule(module))) {
873-
substReq = *resolved;
871+
auto resolved =
872+
req.subst(substitutions, LookUpConformanceInModule(module));
873+
if (!resolved.hasError()) {
874+
substReq = resolved;
874875
} else {
875876
// Another requirement might fail later; just continue.
876877
hadSubstFailure = true;
@@ -912,9 +913,10 @@ CheckGenericArgumentsResult::Kind TypeChecker::checkGenericArguments(
912913
bool valid = true;
913914

914915
for (auto req : requirements) {
915-
if (auto resolved = req.subst(substitutions,
916-
LookUpConformanceInModule(module), options)) {
917-
worklist.push_back(*resolved);
916+
auto resolved = req.subst(substitutions,
917+
LookUpConformanceInModule(module), options);
918+
if (!resolved.hasError()) {
919+
worklist.push_back(resolved);
918920
} else {
919921
valid = false;
920922
}

lib/Sema/TypeCheckProtocol.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,8 @@ matchWitnessDifferentiableAttr(DeclContext *dc, ValueDecl *req,
391391
witnessConfig.derivativeGenericSignature.getRequirements()) {
392392
auto substReq = req.subst(result.WitnessSubstitutions);
393393
bool reqDiffGenSigSatisfies =
394-
reqDiffGenSig && substReq &&
395-
reqDiffGenSig->isRequirementSatisfied(*substReq);
394+
reqDiffGenSig && !substReq.hasError() &&
395+
reqDiffGenSig->isRequirementSatisfied(substReq);
396396
bool conformanceGenSigSatisfies =
397397
conformanceGenSig &&
398398
conformanceGenSig->isRequirementSatisfied(req);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-swift-ide-test -code-completion -code-completion-token COMPLETE -source-filename %s
2+
3+
protocol PreferenceKey {
4+
associatedtype Value
5+
}
6+
protocol View {}
7+
8+
func propagateHeight<K: PreferenceKey>() -> some View where K.Value == #^COMPLETE^#

0 commit comments

Comments
 (0)