Skip to content

AST: Change signature of LookupConformanceFn #81202

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 3 commits into from
May 1, 2025
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
16 changes: 8 additions & 8 deletions include/swift/AST/SubstitutionMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,9 @@ class LookUpConformanceInSubstitutionMap {
explicit LookUpConformanceInSubstitutionMap(SubstitutionMap Subs)
: Subs(Subs) {}

ProtocolConformanceRef operator()(CanType dependentType,
Type conformingReplacementType,
ProtocolDecl *conformedProtocol) const;
ProtocolConformanceRef operator()(InFlightSubstitution &IFS,
Type dependentType,
ProtocolDecl *proto) const;
};

struct OverrideSubsInfo {
Expand Down Expand Up @@ -326,8 +326,8 @@ struct LookUpConformanceInOverrideSubs {
explicit LookUpConformanceInOverrideSubs(const OverrideSubsInfo &info)
: info(info) {}

ProtocolConformanceRef operator()(CanType type,
Type substType,
ProtocolConformanceRef operator()(InFlightSubstitution &IFS,
Type dependentType,
ProtocolDecl *proto) const;
};

Expand All @@ -338,9 +338,9 @@ struct OuterSubstitutions {
unsigned depth;

Type operator()(SubstitutableType *type) const;
ProtocolConformanceRef operator()(CanType dependentType,
Type conformingReplacementType,
ProtocolDecl *conformedProtocol) const;
ProtocolConformanceRef operator()(InFlightSubstitution &IFS,
Type dependentType,
ProtocolDecl *proto) const;
};

} // end namespace swift
Expand Down
18 changes: 9 additions & 9 deletions include/swift/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ struct QueryTypeSubstitutionMap {
};

/// Function used to resolve conformances.
using GenericFunction = auto(CanType dependentType,
Type conformingReplacementType,
ProtocolDecl *conformedProtocol)
using GenericFunction = auto(InFlightSubstitution &IFS,
Type dependentType,
ProtocolDecl *proto)
-> ProtocolConformanceRef;
using LookupConformanceFn = llvm::function_ref<GenericFunction>;

Expand All @@ -100,19 +100,19 @@ class LookUpConformanceInModule {
public:
explicit LookUpConformanceInModule() {}

ProtocolConformanceRef operator()(CanType dependentType,
Type conformingReplacementType,
ProtocolDecl *conformedProtocol) const;
ProtocolConformanceRef operator()(InFlightSubstitution &IFS,
Type dependentType,
ProtocolDecl *proto) const;
};

/// Functor class suitable for use as a \c LookupConformanceFn that provides
/// only abstract conformances for generic types. Asserts that the replacement
/// type is an opaque generic type.
class MakeAbstractConformanceForGenericType {
public:
ProtocolConformanceRef operator()(CanType dependentType,
Type conformingReplacementType,
ProtocolDecl *conformedProtocol) const;
ProtocolConformanceRef operator()(InFlightSubstitution &IFS,
Type dependentType,
ProtocolDecl *proto) const;
};

/// Flags that can be passed when substituting into a type.
Expand Down
8 changes: 4 additions & 4 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -7069,8 +7069,8 @@ class ReplaceOpaqueTypesWithUnderlyingTypes {
Type operator()(SubstitutableType *maybeOpaqueType) const;

/// LookupConformanceFn
ProtocolConformanceRef operator()(CanType maybeOpaqueType,
Type replacementType,
ProtocolConformanceRef operator()(InFlightSubstitution &IFS,
Type maybeOpaqueType,
ProtocolDecl *protocol) const;

OpaqueSubstitutionKind
Expand Down Expand Up @@ -7108,8 +7108,8 @@ class ReplaceExistentialArchetypesWithConcreteTypes {
Type operator()(SubstitutableType *type) const;

/// LookupConformanceFn
ProtocolConformanceRef operator()(CanType origType,
Type substType,
ProtocolConformanceRef operator()(InFlightSubstitution &IFS,
Type origType,
ProtocolDecl *protocol) const;

};
Expand Down
23 changes: 13 additions & 10 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,20 +80,23 @@ struct SubstitutionMapWithLocalArchetypes {
return Type(type);
}

ProtocolConformanceRef operator()(CanType origType,
Type substType,
ProtocolConformanceRef operator()(InFlightSubstitution &IFS,
Type origType,
ProtocolDecl *proto) {
if (isa<LocalArchetypeType>(origType))
return swift::lookupConformance(substType, proto);
if (origType->is<LocalArchetypeType>())
return swift::lookupConformance(origType.subst(IFS), proto);

if (isa<PrimaryArchetypeType>(origType) ||
isa<PackArchetypeType>(origType))
origType = origType->mapTypeOutOfContext()->getCanonicalType();
if (origType->is<PrimaryArchetypeType>() ||
origType->is<PackArchetypeType>())
origType = origType->mapTypeOutOfContext();

if (SubsMap)
return SubsMap->lookupConformance(origType, proto);
if (SubsMap) {
return SubsMap->lookupConformance(
origType->getCanonicalType(), proto);
}

return ProtocolConformanceRef::forAbstract(substType, proto);
return ProtocolConformanceRef::forAbstract(
origType.subst(IFS), proto);
}

void dump(llvm::raw_ostream &out) const {
Expand Down
12 changes: 3 additions & 9 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1914,15 +1914,9 @@ void PrintAST::printSingleDepthOfGenericSignature(
if (subMap.empty())
return param;

return param.subst(
[&](SubstitutableType *type) -> Type {
if (cast<GenericTypeParamType>(type)->getDepth() < typeContextDepth)
return Type(type).subst(subMap);
return type;
},
[&](CanType depType, Type substType, ProtocolDecl *proto) {
return lookupConformance(substType, proto);
});
OuterSubstitutions replacer{subMap, typeContextDepth};
return param.subst(replacer, replacer,
SubstFlags::PreservePackExpansionLevel);
};

/// Separate the explicit generic parameters from the implicit, opaque
Expand Down
7 changes: 4 additions & 3 deletions lib/AST/ExistentialGeneralization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ class Generalizer : public CanTypeVisitor<Generalizer, Type> {
assert(it != substTypes.end());
return it->second;
};
auto lookupConformance = [&](CanType dependentType,
Type conformingReplacementType,
auto lookupConformance = [&](InFlightSubstitution &IFS,
Type dependentType,
ProtocolDecl *conformedProtocol) {
auto it = substConformances.find({dependentType, conformedProtocol});
auto it = substConformances.find(
{dependentType->getCanonicalType(), conformedProtocol});
assert(it != substConformances.end());
return it->second;
};
Expand Down
8 changes: 4 additions & 4 deletions lib/AST/LocalArchetypeRequirementCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,10 @@ swift::buildSubstitutionMapWithCapturedEnvironments(
return mapIntoLocalContext(param, baseDepth, capturedEnvs);
return Type(type).subst(baseSubMap);
},
[&](CanType origType, Type substType,
ProtocolDecl *proto) -> ProtocolConformanceRef {
[&](InFlightSubstitution &IFS, Type origType, ProtocolDecl *proto)
-> ProtocolConformanceRef {
if (origType->getRootGenericParam()->getDepth() >= baseDepth)
return ProtocolConformanceRef::forAbstract(substType, proto);
return baseSubMap.lookupConformance(origType, proto);
return ProtocolConformanceRef::forAbstract(origType.subst(IFS), proto);
return baseSubMap.lookupConformance(origType->getCanonicalType(), proto);
});
}
16 changes: 7 additions & 9 deletions lib/AST/RequirementEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,13 @@ RequirementEnvironment::RequirementEnvironment(
// parameters of the requirement into a combined context that provides the
// type parameters of the conformance context and the parameters of the
// requirement.
auto selfType = cast<GenericTypeParamType>(
proto->getSelfInterfaceType()->getCanonicalType());

reqToWitnessThunkSigMap = SubstitutionMap::get(reqSig,
[selfType, substConcreteType, depth, covariantSelf, &ctx]
[substConcreteType, depth, covariantSelf, &ctx]
(SubstitutableType *type) -> Type {
// If the conforming type is a class, the protocol 'Self' maps to
// the class-constrained 'Self'. Otherwise, it maps to the concrete
// type.
if (type->isEqual(selfType)) {
if (type->isEqual(ctx.TheSelfType)) {
if (covariantSelf)
return ctx.TheSelfType;
return substConcreteType;
Expand All @@ -114,11 +111,12 @@ RequirementEnvironment::RequirementEnvironment(
}
return substGenericParam;
},
[selfType, substConcreteType, conformance, conformanceDC, covariantSelf, &ctx](
CanType type, Type replacement, ProtocolDecl *proto)
[substConcreteType, conformance, conformanceDC, covariantSelf, &ctx](
InFlightSubstitution &IFS, Type type, ProtocolDecl *proto)
-> ProtocolConformanceRef {
// The protocol 'Self' conforms concretely to the conforming type.
if (type->isEqual(selfType)) {
if (type->isEqual(ctx.TheSelfType)) {
auto replacement = type.subst(IFS);
ASSERT(covariantSelf || replacement->isEqual(substConcreteType));

if (conformance) {
Expand Down Expand Up @@ -148,7 +146,7 @@ RequirementEnvironment::RequirementEnvironment(

// All other generic parameters come from the requirement itself
// and conform abstractly.
return MakeAbstractConformanceForGenericType()(type, replacement, proto);
return MakeAbstractConformanceForGenericType()(IFS, type, proto);
});

// If the requirement itself is non-generic, the witness thunk signature
Expand Down
94 changes: 33 additions & 61 deletions lib/AST/SubstitutionMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,61 +272,31 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {

auto path = genericSig->getConformancePath(type, proto);

ProtocolConformanceRef conformance;
for (const auto &step : path) {
// For the first step, grab the initial conformance.
if (conformance.isInvalid()) {
if (auto initialConformance = getSignatureConformance(
step.first, step.second)) {
conformance = *initialConformance;
continue;
// For the first step, grab the initial conformance.
auto iter = path.begin();
const auto step = *iter++;

ProtocolConformanceRef conformance =
*getSignatureConformance(step.first, step.second);

// For each remaining step, project an associated conformance.
while (iter != path.end()) {
// FIXME: Remove this hack. It is unsound, because we may not have diagnosed
// anything but still end up with an ErrorType in the AST.
if (conformance.isConcrete()) {
auto concrete = conformance.getConcrete();
auto normal = concrete->getRootNormalConformance();

if (!normal->hasComputedAssociatedConformances()) {
if (proto->getASTContext().evaluator.hasActiveRequest(
ResolveTypeWitnessesRequest{normal})) {
return ProtocolConformanceRef::forInvalid();
}
}

// We couldn't find the initial conformance, fail.
return ProtocolConformanceRef::forInvalid();
}

// If we've hit an abstract conformance, everything from here on out is
// abstract.
// FIXME: This may not always be true, but it holds for now.
if (conformance.isAbstract()) {
// FIXME: Rip this out once we can get a concrete conformance from
// an archetype.
return swift::lookupConformance(type.subst(*this), proto);
}

// For the second step, we're looking into the requirement signature for
// this protocol.
if (conformance.isPack()) {
auto pack = conformance.getPack();
conformance = ProtocolConformanceRef(
pack->getAssociatedConformance(step.first, step.second));
if (conformance.isInvalid())
return conformance;

continue;
}

auto concrete = conformance.getConcrete();
auto normal = concrete->getRootNormalConformance();

// If we haven't set the signature conformances yet, force the issue now.
if (!normal->hasComputedAssociatedConformances()) {
// If we're in the process of checking the type witnesses, fail
// gracefully.
//
// FIXME: This is unsound, because we may not have diagnosed anything but
// still end up with an ErrorType in the AST.
if (proto->getASTContext().evaluator.hasActiveRequest(
ResolveTypeWitnessesRequest{normal})) {
return ProtocolConformanceRef::forInvalid();
}
}

// Get the associated conformance.
conformance = concrete->getAssociatedConformance(step.first, step.second);
if (conformance.isInvalid())
return conformance;
const auto step = *iter++;
conformance = conformance.getAssociatedConformance(step.first, step.second);
}

return conformance;
Expand Down Expand Up @@ -473,16 +443,18 @@ Type QueryOverrideSubs::operator()(SubstitutableType *type) const {
}

ProtocolConformanceRef
LookUpConformanceInOverrideSubs::operator()(CanType type,
Type substType,
LookUpConformanceInOverrideSubs::operator()(InFlightSubstitution &IFS,
Type type,
ProtocolDecl *proto) const {
if (type->getRootGenericParam()->getDepth() >= info.BaseDepth)
return ProtocolConformanceRef::forAbstract(substType, proto);
return ProtocolConformanceRef::forAbstract(type.subst(IFS), proto);

if (auto conformance = info.BaseSubMap.lookupConformance(type, proto))
if (auto conformance = info.BaseSubMap.lookupConformance(
type->getCanonicalType(), proto)) {
return conformance;
}

return lookupConformance(substType, proto);
return lookupConformance(type.subst(IFS), proto);
}

SubstitutionMap
Expand Down Expand Up @@ -665,8 +637,8 @@ Type OuterSubstitutions::operator()(SubstitutableType *type) const {
}

ProtocolConformanceRef OuterSubstitutions::operator()(
CanType dependentType,
Type conformingReplacementType,
InFlightSubstitution &IFS,
Type dependentType,
ProtocolDecl *conformedProtocol) const {
auto sig = subs.getGenericSignature();
if (!sig->isValidTypeParameter(dependentType) ||
Expand All @@ -683,10 +655,10 @@ ProtocolConformanceRef OuterSubstitutions::operator()(
// Once we check for that and handle it properly, the lookupConformance()
// can become a forAbstract().
return swift::lookupConformance(
conformingReplacementType, conformedProtocol);
dependentType.subst(IFS), conformedProtocol);
}

return LookUpConformanceInSubstitutionMap(subs)(
dependentType, conformingReplacementType, conformedProtocol);
IFS, dependentType, conformedProtocol);
}

Loading