Skip to content

AST: Change return type of Requirement::subst() to Requirement [5.7] #60587

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions include/swift/AST/Requirement.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,15 @@ class Requirement

/// Subst the types involved in this requirement.
///
/// The \c args arguments are passed through to Type::subst. This doesn't
/// touch the superclasses, protocols or layout constraints.
/// The \c args arguments are passed through to Type::subst.
template <typename ...Args>
llvm::Optional<Requirement> subst(Args &&...args) const {
Requirement subst(Args &&...args) const {
auto newFirst = getFirstType().subst(std::forward<Args>(args)...);
if (newFirst->hasError())
return None;

switch (getKind()) {
case RequirementKind::Conformance:
case RequirementKind::Superclass:
case RequirementKind::SameType: {
auto newSecond = getSecondType().subst(std::forward<Args>(args)...);
if (newSecond->hasError())
return None;
return Requirement(getKind(), newFirst, newSecond);
}
case RequirementKind::Layout:
Expand Down
5 changes: 2 additions & 3 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5340,9 +5340,8 @@ ASTContext::getOverrideGenericSignature(const ValueDecl *base,
};

for (auto reqt : baseGenericSig.getRequirements()) {
if (auto substReqt = reqt.subst(substFn, lookupConformanceFn)) {
addedRequirements.push_back(*substReqt);
}
auto substReqt = reqt.subst(substFn, lookupConformanceFn);
addedRequirements.push_back(substReqt);
}
}

Expand Down
5 changes: 1 addition & 4 deletions lib/AST/ExistentialGeneralization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,7 @@ class Generalizer : public CanTypeVisitor<Generalizer, Type> {
if (origReq.getKind() != RequirementKind::Conformance) continue;
auto origConformance = origConformances[i++];

auto optNewReq = origReq.subst(newSubs);
assert(optNewReq && "generalization substitution failed");
auto &newReq = *optNewReq;

auto newReq = origReq.subst(newSubs);
addedRequirements.push_back(newReq);

substConformances.insert({{newReq.getFirstType()->getCanonicalType(),
Expand Down
7 changes: 1 addition & 6 deletions lib/AST/GenericSignature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,19 +373,14 @@ bool GenericSignatureImpl::isRequirementSatisfied(
if (requirement.getFirstType()->hasTypeParameter()) {
auto *genericEnv = getGenericEnvironment();

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

return type;
},
LookUpConformanceInSignature(this));

if (!substituted)
return false;

requirement = *substituted;
}

// FIXME: Need to check conditional requirements here.
Expand Down
10 changes: 5 additions & 5 deletions lib/AST/GenericSignatureBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5169,8 +5169,8 @@ class GenericSignatureBuilder::InferRequirementsWalker : public TypeWalker {
auto decl = TypeAlias->getDecl();
auto subMap = TypeAlias->getSubstitutionMap();
for (const auto &rawReq : decl->getGenericSignature().getRequirements()) {
if (auto req = rawReq.subst(subMap))
Builder.addRequirement(*req, source, nullptr);
auto req = rawReq.subst(subMap);
Builder.addRequirement(req, source, nullptr);
}

return Action::Continue;
Expand Down Expand Up @@ -5237,8 +5237,8 @@ class GenericSignatureBuilder::InferRequirementsWalker : public TypeWalker {
// Handle the requirements.
// FIXME: Inaccurate TypeReprs.
for (const auto &rawReq : genericSig.getRequirements()) {
if (auto req = rawReq.subst(subMap))
Builder.addRequirement(*req, source, nullptr);
auto req = rawReq.subst(subMap);
Builder.addRequirement(req, source, nullptr);
}

return Action::Continue;
Expand Down Expand Up @@ -8402,7 +8402,7 @@ AbstractGenericSignatureRequestGSB::evaluate(
},
MakeAbstractConformanceForGenericType(),
SubstFlags::AllowLoweredTypes);
resugaredRequirements.push_back(*resugaredReq);
resugaredRequirements.push_back(resugaredReq);
}

return GenericSignatureWithError(
Expand Down
8 changes: 4 additions & 4 deletions lib/AST/ProtocolConformance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -992,9 +992,9 @@ void SpecializedProtocolConformance::computeConditionalRequirements() const {

SmallVector<Requirement, 4> newReqs;
for (auto oldReq : *parentCondReqs) {
if (auto newReq = oldReq.subst(QuerySubstitutionMap{subMap},
LookUpConformanceInModule(module)))
newReqs.push_back(*newReq);
auto newReq = oldReq.subst(QuerySubstitutionMap{subMap},
LookUpConformanceInModule(module));
newReqs.push_back(newReq);
}
auto &ctxt = getProtocol()->getASTContext();
ConditionalRequirements = ctxt.AllocateCopy(newReqs);
Expand Down Expand Up @@ -1201,7 +1201,7 @@ ProtocolConformance::subst(TypeSubstitutionFn subs,

SmallVector<Requirement, 2> requirements;
for (auto req : getConditionalRequirements()) {
requirements.push_back(*req.subst(subs, conformances, options));
requirements.push_back(req.subst(subs, conformances, options));
}

auto kind = cast<BuiltinProtocolConformance>(this)
Expand Down
10 changes: 5 additions & 5 deletions lib/AST/RequirementEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ RequirementEnvironment::RequirementEnvironment(

if (conformanceSig) {
for (auto &rawReq : conformanceSig.getRequirements()) {
if (auto req = rawReq.subst(conformanceToSyntheticTypeFn,
conformanceToSyntheticConformanceFn))
requirements.push_back(*req);
auto req = rawReq.subst(conformanceToSyntheticTypeFn,
conformanceToSyntheticConformanceFn);
requirements.push_back(req);
}
}

Expand All @@ -207,8 +207,8 @@ RequirementEnvironment::RequirementEnvironment(
// Next, add each of the requirements (mapped from the requirement's
// interface types into the abstract type parameters).
for (auto &rawReq : reqSig.getRequirements()) {
if (auto req = rawReq.subst(reqToSyntheticEnvMap))
requirements.push_back(*req);
auto req = rawReq.subst(reqToSyntheticEnvMap);
requirements.push_back(req);
}

// Produce the generic signature and environment.
Expand Down
7 changes: 3 additions & 4 deletions lib/AST/RequirementMachine/RequirementLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,8 +465,7 @@ struct InferRequirementsWalker : public TypeWalker {
auto decl = typeAlias->getDecl();
auto subMap = typeAlias->getSubstitutionMap();
for (const auto &rawReq : decl->getGenericSignature().getRequirements()) {
if (auto req = rawReq.subst(subMap))
desugarRequirement(*req, SourceLoc(), reqs, errors);
desugarRequirement(rawReq.subst(subMap), SourceLoc(), reqs, errors);
}

return Action::Continue;
Expand Down Expand Up @@ -532,8 +531,8 @@ struct InferRequirementsWalker : public TypeWalker {
// Handle the requirements.
// FIXME: Inaccurate TypeReprs.
for (const auto &rawReq : genericSig.getRequirements()) {
if (auto req = rawReq.subst(subMap))
desugarRequirement(*req, SourceLoc(), reqs, errors);
auto req = rawReq.subst(subMap);
desugarRequirement(req, SourceLoc(), reqs, errors);
}

return Action::Continue;
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/RequirementMachine/RequirementMachineRequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ AbstractGenericSignatureRequestRQM::evaluate(
},
MakeAbstractConformanceForGenericType(),
SubstFlags::AllowLoweredTypes);
resugaredRequirements.push_back(*resugaredReq);
resugaredRequirements.push_back(resugaredReq);
}

return GenericSignatureWithError(
Expand Down
16 changes: 3 additions & 13 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4527,26 +4527,16 @@ static Type substGenericFunctionType(GenericFunctionType *genericFnType,
for (const auto &req : genericFnType->getRequirements()) {
// Substitute into the requirement.
auto substReqt = req.subst(substitutions, lookupConformances, options);
if (!substReqt) {
anySemanticChanges = true;
continue;
}

// Did anything change?
if (!anySemanticChanges &&
(!req.getFirstType()->isEqual(substReqt->getFirstType()) ||
(!req.getFirstType()->isEqual(substReqt.getFirstType()) ||
(req.getKind() != RequirementKind::Layout &&
!req.getSecondType()->isEqual(substReqt->getSecondType())))) {
!req.getSecondType()->isEqual(substReqt.getSecondType())))) {
anySemanticChanges = true;
}

// Skip any erroneous requirements.
if (substReqt->getFirstType()->hasError() ||
(substReqt->getKind() != RequirementKind::Layout &&
substReqt->getSecondType()->hasError()))
continue;

requirements.push_back(*substReqt);
requirements.push_back(substReqt);
}

GenericSignature genericSig;
Expand Down
12 changes: 5 additions & 7 deletions lib/IDE/IDETypeChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,15 +323,13 @@ struct SynthesizedExtensionAnalyzer::Implementation {
if (!BaseType->isExistentialType()) {
// Apply any substitutions we need to map the requirements from a
// a protocol extension to an extension on the conforming type.
auto SubstReq = Req.subst(subMap);
if (!SubstReq) {
Req = Req.subst(subMap);
if (Req.hasError()) {
// Substitution with interface type bases can only fail
// if a concrete type fails to conform to a protocol.
// In this case, just give up on the extension altogether.
return true;
}

Req = *SubstReq;
}

assert(!Req.getFirstType()->hasArchetype());
Expand All @@ -346,13 +344,13 @@ struct SynthesizedExtensionAnalyzer::Implementation {
return type;
},
LookUpConformanceInModule(M));
if (!SubstReq)
if (SubstReq.hasError())
return true;

// FIXME: Need to handle conditional requirements here!
ArrayRef<Requirement> conditionalRequirements;
if (!SubstReq->isSatisfied(conditionalRequirements)) {
if (!SubstReq->canBeSatisfied())
if (!SubstReq.isSatisfied(conditionalRequirements)) {
if (!SubstReq.canBeSatisfied())
return true;

MergeInfo.addRequirement(Req);
Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/Utils/Generics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1540,7 +1540,7 @@ void FunctionSignaturePartialSpecializer::addRequirements(
for (auto &reqReq : Reqs) {
LLVM_DEBUG(llvm::dbgs() << "\n\nRe-mapping the requirement:\n";
reqReq.dump(llvm::dbgs()));
AllRequirements.push_back(*reqReq.subst(SubsMap));
AllRequirements.push_back(reqReq.subst(SubsMap));
}
}

Expand Down
7 changes: 4 additions & 3 deletions lib/Sema/CodeSynthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,9 +529,10 @@ computeDesignatedInitOverrideSignature(ASTContext &ctx,
};

SmallVector<Requirement, 2> requirements;
for (auto reqt : superclassCtorSig.getRequirements())
if (auto substReqt = reqt.subst(substFn, lookupConformanceFn))
requirements.push_back(*substReqt);
for (auto reqt : superclassCtorSig.getRequirements()) {
auto substReqt = reqt.subst(substFn, lookupConformanceFn);
requirements.push_back(substReqt);
}

// Now form the substitution map that will be used to remap parameter
// types.
Expand Down
14 changes: 8 additions & 6 deletions lib/Sema/TypeCheckGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,9 +925,10 @@ CheckGenericArgumentsResult TypeChecker::checkGenericArgumentsForDiagnostics(
Requirement substReq = req;
if (isPrimaryReq) {
// Primary requirements do not have substitutions applied.
if (auto resolved =
req.subst(substitutions, LookUpConformanceInModule(module))) {
substReq = *resolved;
auto resolved =
req.subst(substitutions, LookUpConformanceInModule(module));
if (!resolved.hasError()) {
substReq = resolved;
} else {
// Another requirement might fail later; just continue.
hadSubstFailure = true;
Expand Down Expand Up @@ -969,9 +970,10 @@ CheckGenericArgumentsResult::Kind TypeChecker::checkGenericArguments(
bool valid = true;

for (auto req : requirements) {
if (auto resolved = req.subst(substitutions,
LookUpConformanceInModule(module), options)) {
worklist.push_back(*resolved);
auto resolved = req.subst(substitutions,
LookUpConformanceInModule(module), options);
if (!resolved.hasError()) {
worklist.push_back(resolved);
} else {
valid = false;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,8 @@ matchWitnessDifferentiableAttr(DeclContext *dc, ValueDecl *req,
witnessConfig.derivativeGenericSignature.getRequirements()) {
auto substReq = req.subst(result.WitnessSubstitutions);
bool reqDiffGenSigSatisfies =
reqDiffGenSig && substReq &&
reqDiffGenSig->isRequirementSatisfied(*substReq);
reqDiffGenSig && !substReq.hasError() &&
reqDiffGenSig->isRequirementSatisfied(substReq);
bool conformanceGenSigSatisfies =
conformanceGenSig &&
conformanceGenSig->isRequirementSatisfied(req);
Expand Down
8 changes: 8 additions & 0 deletions validation-test/IDE/crashers_fixed/rdar98565072.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: %target-swift-ide-test -code-completion -code-completion-token COMPLETE -source-filename %s

protocol PreferenceKey {
associatedtype Value
}
protocol View {}

func propagateHeight<K: PreferenceKey>() -> some View where K.Value == #^COMPLETE^#