Skip to content

Commit 46dbe06

Browse files
committed
SIL: buildThunkType() uses (new) LocalRequirementArchetypeCollector
1 parent 8421251 commit 46dbe06

File tree

1 file changed

+34
-173
lines changed

1 file changed

+34
-173
lines changed

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 34 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/DiagnosticsSIL.h"
2525
#include "swift/AST/ForeignInfo.h"
2626
#include "swift/AST/GenericEnvironment.h"
27+
#include "swift/AST/LocalArchetypeRequirementCollector.h"
2728
#include "swift/AST/Module.h"
2829
#include "swift/AST/ModuleLoader.h"
2930
#include "swift/AST/TypeCheckRequests.h"
@@ -2871,148 +2872,6 @@ CanSILFunctionType swift::getNativeSILFunctionType(
28712872
substConstant, reqtSubs, witnessMethodConformance);
28722873
}
28732874

2874-
namespace {
2875-
struct LocalArchetypeRequirementCollector {
2876-
const ASTContext &Context;
2877-
unsigned Depth;
2878-
2879-
/// The lists of new parameters and requirements to add to the signature.
2880-
SmallVector<GenericTypeParamType *, 2> Params;
2881-
SmallVector<Requirement, 2> Requirements;
2882-
2883-
/// The list of contextual types from the original function to use as
2884-
/// substitutions for the new parameters; parallel to Params.
2885-
SmallVector<Type, 4> ParamSubs;
2886-
2887-
/// A mapping of local archetypes to the corresponding type parameters
2888-
/// created for them.
2889-
llvm::DenseMap<CanType, Type> ParamsForLocalArchetypes;
2890-
2891-
/// The set of element environments we've processed.
2892-
llvm::SmallPtrSet<GenericEnvironment*, 4> ElementEnvs;
2893-
2894-
LocalArchetypeRequirementCollector(const ASTContext &ctx, unsigned depth)
2895-
: Context(ctx), Depth(depth) {}
2896-
2897-
void collect(CanLocalArchetypeType archetype) {
2898-
if (auto openedExistential = dyn_cast<OpenedArchetypeType>(archetype)) {
2899-
collect(openedExistential);
2900-
} else {
2901-
collect(cast<ElementArchetypeType>(archetype));
2902-
}
2903-
}
2904-
2905-
void collect(CanOpenedArchetypeType archetype) {
2906-
auto param = addParameter(archetype);
2907-
2908-
assert(archetype->isRoot());
2909-
auto constraint = archetype->getExistentialType();
2910-
if (auto existential = constraint->getAs<ExistentialType>())
2911-
constraint = existential->getConstraintType();
2912-
2913-
addRequirement(RequirementKind::Conformance, param, constraint);
2914-
}
2915-
2916-
void collect(CanElementArchetypeType archetype) {
2917-
size_t startingIndex = Params.size();
2918-
2919-
// Check whether we've already handled this environment.
2920-
// This can happen with opened-element environments because
2921-
// they can open multiple archetypes.
2922-
auto env = archetype->getGenericEnvironment();
2923-
if (!ElementEnvs.insert(env).second) return;
2924-
2925-
// Add a parameter for each of the opened elements in this environment.
2926-
auto sig = env->getGenericSignature();
2927-
auto elementParams = sig.getInnermostGenericParams();
2928-
#ifndef NDEBUG
2929-
unsigned nextIndex = 0;
2930-
#endif
2931-
for (auto elementParam : elementParams) {
2932-
assert(elementParam->getIndex() == nextIndex++);
2933-
auto elementArchetype = env->mapTypeIntoContext(elementParam);
2934-
addParameter(cast<LocalArchetypeType>(CanType(elementArchetype)));
2935-
}
2936-
2937-
// Clone the element requirements.
2938-
2939-
// The element parameters should all have the same depth, and their
2940-
// index values are dense and in order from 0..<N in that depth.
2941-
// We asserted that above, and we'll use it below to map them to
2942-
// their new parameters in Params.
2943-
auto elementDepth = elementParams.front()->getDepth();
2944-
2945-
// Helper function: does the given type refer to an opened element
2946-
// parameter from the opened element generic signature?
2947-
auto refersToElementType = [=](Type type) {
2948-
return type.findIf([&](Type t) {
2949-
if (auto *param = t->getAs<GenericTypeParamType>())
2950-
return (param->getDepth() == elementDepth);
2951-
return false;
2952-
});
2953-
};
2954-
// Helper function: replace references to opened element parameters
2955-
// with one of the type parameters we just created for this
2956-
// environment.
2957-
auto rewriteElementType = [=](Type type) {
2958-
return type.transformRec([&](Type t) -> std::optional<Type> {
2959-
if (auto *param = t->getAs<GenericTypeParamType>()) {
2960-
if (param->getDepth() == elementDepth)
2961-
return Type(Params[startingIndex + param->getIndex()]);
2962-
}
2963-
return std::nullopt;
2964-
});
2965-
};
2966-
2967-
for (auto req : sig.getRequirements()) {
2968-
switch (req.getKind()) {
2969-
case RequirementKind::SameShape:
2970-
// These never involve element types.
2971-
break;
2972-
case RequirementKind::Conformance:
2973-
if (refersToElementType(req.getFirstType())) {
2974-
addRequirement(RequirementKind::Conformance,
2975-
rewriteElementType(req.getFirstType()),
2976-
req.getSecondType());
2977-
}
2978-
break;
2979-
case RequirementKind::Superclass:
2980-
case RequirementKind::SameType:
2981-
if (refersToElementType(req.getFirstType()) ||
2982-
refersToElementType(req.getSecondType())) {
2983-
addRequirement(req.getKind(),
2984-
rewriteElementType(req.getFirstType()),
2985-
rewriteElementType(req.getSecondType()));
2986-
}
2987-
break;
2988-
break;
2989-
case RequirementKind::Layout:
2990-
if (refersToElementType(req.getFirstType())) {
2991-
addRequirement(RequirementKind::Layout,
2992-
rewriteElementType(req.getFirstType()),
2993-
req.getLayoutConstraint());
2994-
}
2995-
break;
2996-
}
2997-
}
2998-
}
2999-
3000-
GenericTypeParamType *addParameter(CanLocalArchetypeType localArchetype) {
3001-
auto *param = GenericTypeParamType::get(/*pack*/ false, Depth,
3002-
Params.size(), Context);
3003-
Params.push_back(param);
3004-
ParamSubs.push_back(localArchetype);
3005-
ParamsForLocalArchetypes.insert(std::make_pair(localArchetype, param));
3006-
return param;
3007-
}
3008-
3009-
template <class... Args>
3010-
void addRequirement(Args &&... args) {
3011-
Requirements.emplace_back(std::forward<Args>(args)...);
3012-
}
3013-
};
3014-
} // end anonymous namespace
3015-
30162875
/// Build a generic signature and environment for a re-abstraction thunk.
30172876
///
30182877
/// Most thunks share the generic environment with their original function.
@@ -3047,33 +2906,35 @@ buildThunkSignature(SILFunction *fn,
30472906
return genericSig;
30482907
}
30492908

3050-
// Add the existing generic signature.
3051-
unsigned depth = 0;
3052-
GenericSignature baseGenericSig;
3053-
if (auto genericSig =
3054-
fn->getLoweredFunctionType()->getInvocationGenericSignature()) {
3055-
baseGenericSig = genericSig;
3056-
depth = genericSig.getGenericParams().back()->getDepth() + 1;
3057-
}
3058-
3059-
// Add new generic parameters to replace the local archetypes.
3060-
LocalArchetypeRequirementCollector collector(ctx, depth);
2909+
// Get the existing generic signature.
2910+
auto baseGenericSig =
2911+
fn->getLoweredFunctionType()->getInvocationGenericSignature();
30612912

2913+
SmallVector<GenericEnvironment *, 2> capturedEnvs;
30622914
for (auto archetype : localArchetypes) {
3063-
collector.collect(archetype);
2915+
auto *genericEnv = archetype->getGenericEnvironment();
2916+
if (std::find(capturedEnvs.begin(), capturedEnvs.end(), genericEnv)
2917+
== capturedEnvs.end()) {
2918+
capturedEnvs.push_back(genericEnv);
2919+
}
30642920
}
30652921

3066-
auto genericSig = buildGenericSignature(ctx, baseGenericSig,
3067-
collector.Params,
3068-
collector.Requirements,
3069-
/*allowInverses=*/false);
2922+
auto genericSig = buildGenericSignatureWithCapturedEnvironments(
2923+
ctx, baseGenericSig, capturedEnvs);
2924+
LLVM_DEBUG(llvm::dbgs() << "Thunk generic signature: " << genericSig << "\n");
2925+
30702926
genericEnv = genericSig.getGenericEnvironment();
30712927

2928+
MapLocalArchetypesOutOfContext mapOutOfContext(genericSig, capturedEnvs);
2929+
30722930
// Map the local archetypes to their new parameter types.
30732931
for (auto localArchetype : localArchetypes) {
3074-
auto param =
3075-
collector.ParamsForLocalArchetypes.find(localArchetype)->second;
3076-
auto thunkArchetype = genericEnv->mapTypeIntoContext(param);
2932+
auto thunkInterfaceType = Type(localArchetype).subst(
2933+
mapOutOfContext,
2934+
MakeAbstractConformanceForGenericType(),
2935+
SubstFlags::PreservePackExpansionLevel);
2936+
auto thunkArchetype = genericEnv->mapTypeIntoContext(
2937+
thunkInterfaceType);
30772938
contextLocalArchetypes.insert(std::make_pair(localArchetype,
30782939
thunkArchetype));
30792940
}
@@ -3088,18 +2949,18 @@ buildThunkSignature(SILFunction *fn,
30882949
}
30892950

30902951
// Calculate substitutions to map interface types to the caller's archetypes.
3091-
3092-
interfaceSubs = SubstitutionMap::get(
3093-
genericSig,
3094-
[&](SubstitutableType *type) -> Type {
3095-
if (auto param = dyn_cast<GenericTypeParamType>(type)) {
3096-
if (param->getDepth() == depth) {
3097-
return collector.ParamSubs[param->getIndex()];
3098-
}
3099-
}
3100-
return Type(type).subst(forwardingSubs);
3101-
},
3102-
MakeAbstractConformanceForGenericType());
2952+
interfaceSubs = buildSubstitutionMapWithCapturedEnvironments(
2953+
forwardingSubs, genericSig, capturedEnvs);
2954+
LLVM_DEBUG(llvm::dbgs() << "Thunk substitution map: " << interfaceSubs << "\n");
2955+
2956+
for (auto pair : contextLocalArchetypes) {
2957+
auto substArchetype = Type(pair.second).subst(interfaceSubs);
2958+
if (!pair.first->isEqual(substArchetype)) {
2959+
llvm::errs() << "Expected: "; pair.first->dump(llvm::errs());
2960+
llvm::errs() << "Got: "; substArchetype->dump(llvm::errs());
2961+
abort();
2962+
}
2963+
}
31032964

31042965
return genericSig.getCanonicalSignature();
31052966
}

0 commit comments

Comments
 (0)