Skip to content

Commit d1847ff

Browse files
authored
Merge pull request #75068 from slavapestov/simplify-sub-map
Simplify and optimize SubstitutionMap
2 parents 38631ac + eca5a1c commit d1847ff

37 files changed

+302
-215
lines changed

include/swift/AST/SubstitutionMap.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,22 +73,6 @@ class SubstitutionMap {
7373
/// signature nor any replacement types/conformances.
7474
Storage *storage = nullptr;
7575

76-
public:
77-
/// Retrieve the array of replacement types, which line up with the
78-
/// generic parameters.
79-
///
80-
/// Note that the types may be null, for cases where the generic parameter
81-
/// is concrete but hasn't been queried yet.
82-
///
83-
/// Prefer \c getReplacementTypes, this is public for printing purposes.
84-
ArrayRef<Type> getReplacementTypesBuffer() const;
85-
86-
private:
87-
MutableArrayRef<Type> getReplacementTypesBuffer();
88-
89-
/// Retrieve a mutable reference to the buffer of conformances.
90-
MutableArrayRef<ProtocolConformanceRef> getConformancesBuffer();
91-
9276
/// Form a substitution map for the given generic signature with the
9377
/// specified replacement types and conformances.
9478
SubstitutionMap(GenericSignature genericSig,

include/swift/AST/Types.h

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,26 +1289,22 @@ class alignas(1 << TypeAlignInBits) TypeBase
12891289
/// Otherwise, it returns the type itself.
12901290
Type getReferenceStorageReferent();
12911291

1292-
/// Determine the set of substitutions that should be applied to a
1293-
/// type spelled within the given DeclContext to treat it as a
1294-
/// member of this type.
1292+
/// Assumes this is a nominal type. Returns a substitution map that sends each
1293+
/// generic parameter of the declaration's generic signature to the corresponding
1294+
/// generic argument of this nominal type.
12951295
///
1296-
/// For example, given:
1297-
/// \code
1298-
/// struct X<T, U> { }
1299-
/// extension X {
1300-
/// typealias SomeArray = [T]
1301-
/// }
1302-
/// \endcode
1296+
/// Eg: Array<Int> ---> { Element := Int }
1297+
SubstitutionMap getContextSubstitutionMap();
1298+
1299+
/// More general form of the above that handles additional cases:
13031300
///
1304-
/// Asking for the member substitutions of \c X<Int,String> within
1305-
/// the context of the extension above will produce substitutions T
1306-
/// -> Int and U -> String suitable for mapping the type of
1307-
/// \c SomeArray.
1301+
/// 1) dc is the nominal type itself or an unconstrained extension
1302+
/// 2) dc is a superclass
1303+
/// 3) dc is a protocol
13081304
///
1309-
/// \param genericEnv If non-null and the type is nested inside of a
1310-
/// generic function, generic parameters of the outer context are
1311-
/// mapped to context archetypes of this generic environment.
1305+
/// In Case 2) and 3), the substitution map has the generic signature of the dc,
1306+
/// and not the nominal. In Case 1), this is the same as the no-argument overload
1307+
/// of getContextSubstitutionMap().
13121308
SubstitutionMap getContextSubstitutionMap(const DeclContext *dc,
13131309
GenericEnvironment *genericEnv=nullptr);
13141310

@@ -1530,6 +1526,9 @@ END_CAN_TYPE_WRAPPER(AnyGenericType, Type)
15301526
/// fields exist at the same offset in memory to improve code generation of the
15311527
/// compiler itself.
15321528
class NominalOrBoundGenericNominalType : public AnyGenericType {
1529+
friend class TypeBase;
1530+
SubstitutionMap ContextSubMap;
1531+
15331532
public:
15341533
template <typename... Args>
15351534
NominalOrBoundGenericNominalType(Args &&...args)

include/swift/SILOptimizer/OptimizerBridgingImpl.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,7 @@ void BridgedPassContext::loadFunction(BridgedFunction function, bool loadCallees
415415

416416
BridgedSubstitutionMap BridgedPassContext::getContextSubstitutionMap(BridgedType type) const {
417417
swift::SILType ty = type.unbridged();
418-
auto *ntd = ty.getASTType()->getAnyNominal();
419-
return ty.getASTType()->getContextSubstitutionMap(ntd);
418+
return ty.getASTType()->getContextSubstitutionMap();
420419
}
421420

422421
BridgedType BridgedPassContext::getBuiltinIntegerType(SwiftInt bitWidth) const {

lib/AST/ASTContext.cpp

Lines changed: 108 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,8 @@ struct ASTContext::Implementation {
584584
}
585585

586586
size_t getTotalMemory() const;
587+
588+
void dump(llvm::raw_ostream &out) const;
587589
};
588590

589591
llvm::DenseMap<ModuleDecl*, ModuleType*> ModuleTypes;
@@ -672,6 +674,8 @@ struct ASTContext::Implementation {
672674
BuiltinTupleType *TheTupleType = nullptr;
673675

674676
std::array<ProtocolDecl *, NumInvertibleProtocols> InvertibleProtocolDecls = {};
677+
678+
void dump(llvm::raw_ostream &out) const;
675679
};
676680

677681
ASTContext::Implementation::Implementation()
@@ -803,9 +807,59 @@ ASTContext::ASTContext(
803807
}
804808
}
805809

810+
void ASTContext::Implementation::dump(llvm::raw_ostream &os) const {
811+
os << "-------------------------------------------------\n";
812+
os << "Arena\t0\t" << Allocator.getBytesAllocated() << "\n";
813+
Permanent.dump(os);
814+
815+
#define SIZE(Name) os << #Name << "\t" << Name.size() << "\t0\n"
816+
#define SIZE_AND_BYTES(Name) os << #Name << "\t" \
817+
<< Name.size() << "\t" \
818+
<< llvm::capacity_in_bytes(Name) << "\n"
819+
820+
SIZE(LoadedModules);
821+
SIZE(IdentifierTable);
822+
SIZE(Cleanups);
823+
SIZE_AND_BYTES(ModuleLoaders);
824+
SIZE_AND_BYTES(ExternalSourceLocs);
825+
SIZE_AND_BYTES(ForeignErrorConventions);
826+
SIZE_AND_BYTES(ForeignAsyncConventions);
827+
SIZE_AND_BYTES(AssociativityCache);
828+
SIZE_AND_BYTES(DelayedConformanceDiags);
829+
SIZE_AND_BYTES(LazyContexts);
830+
SIZE_AND_BYTES(ExistentialSignatures);
831+
SIZE_AND_BYTES(ElementSignatures);
832+
SIZE_AND_BYTES(Overrides);
833+
SIZE_AND_BYTES(DefaultWitnesses);
834+
SIZE_AND_BYTES(DefaultTypeWitnesses);
835+
SIZE_AND_BYTES(DefaultAssociatedConformanceWitnesses);
836+
SIZE_AND_BYTES(DefaultTypeRequestCaches);
837+
SIZE_AND_BYTES(PropertyWrapperBackingVarTypes);
838+
SIZE_AND_BYTES(OriginalWrappedProperties);
839+
SIZE_AND_BYTES(BuiltinInitWitness);
840+
SIZE_AND_BYTES(OriginalBodySourceRanges);
841+
SIZE_AND_BYTES(NextMacroDiscriminator);
842+
SIZE_AND_BYTES(NextDiscriminator);
843+
SIZE_AND_BYTES(ModuleTypes);
844+
SIZE_AND_BYTES(GenericParamTypes);
845+
SIZE_AND_BYTES(SILBlockStorageTypes);
846+
SIZE_AND_BYTES(SILMoveOnlyWrappedTypes);
847+
SIZE_AND_BYTES(IntegerTypes);
848+
SIZE_AND_BYTES(OpenedExistentialEnvironments);
849+
SIZE_AND_BYTES(OpenedElementEnvironments);
850+
SIZE_AND_BYTES(ForeignRepresentableCache);
851+
SIZE(SearchPathsSet);
852+
853+
#undef SIZE
854+
#undef SIZE_AND_BYTES
855+
}
856+
806857
ASTContext::~ASTContext() {
807-
if (LangOpts.AnalyzeRequestEvaluator)
858+
if (LangOpts.AnalyzeRequestEvaluator) {
808859
evaluator.dump(llvm::dbgs());
860+
getImpl().dump(llvm::dbgs());
861+
}
862+
809863
getImpl().~Implementation();
810864
}
811865

@@ -3064,6 +3118,56 @@ size_t ASTContext::Implementation::Arena::getTotalMemory() const {
30643118
// BuiltinConformances ?
30653119
}
30663120

3121+
void ASTContext::Implementation::Arena::dump(llvm::raw_ostream &os) const {
3122+
#define SIZE(Name) os << #Name << "\t" << Name.size() << "\t0\n"
3123+
#define SIZE_AND_BYTES(Name) os << #Name << "\t" \
3124+
<< Name.size() << "\t" \
3125+
<< llvm::capacity_in_bytes(Name) << "\n"
3126+
3127+
SIZE_AND_BYTES(ErrorTypesWithOriginal);
3128+
SIZE(TypeAliasTypes);
3129+
SIZE(TupleTypes);
3130+
SIZE(PackTypes);
3131+
SIZE(PackExpansionTypes);
3132+
SIZE(PackElementTypes);
3133+
SIZE_AND_BYTES(MetatypeTypes);
3134+
SIZE_AND_BYTES(ExistentialMetatypeTypes);
3135+
SIZE_AND_BYTES(ArraySliceTypes);
3136+
SIZE_AND_BYTES(VariadicSequenceTypes);
3137+
SIZE_AND_BYTES(DictionaryTypes);
3138+
SIZE_AND_BYTES(OptionalTypes);
3139+
SIZE_AND_BYTES(ParenTypes);
3140+
SIZE_AND_BYTES(ReferenceStorageTypes);
3141+
SIZE_AND_BYTES(LValueTypes);
3142+
SIZE_AND_BYTES(InOutTypes);
3143+
SIZE_AND_BYTES(DependentMemberTypes);
3144+
SIZE(ErrorUnionTypes);
3145+
SIZE_AND_BYTES(PlaceholderTypes);
3146+
SIZE_AND_BYTES(DynamicSelfTypes);
3147+
SIZE_AND_BYTES(EnumTypes);
3148+
SIZE_AND_BYTES(StructTypes);
3149+
SIZE_AND_BYTES(ClassTypes);
3150+
SIZE_AND_BYTES(ProtocolTypes);
3151+
SIZE_AND_BYTES(ExistentialTypes);
3152+
SIZE(UnboundGenericTypes);
3153+
SIZE(BoundGenericTypes);
3154+
SIZE(ProtocolCompositionTypes);
3155+
SIZE(ParameterizedProtocolTypes);
3156+
SIZE(LayoutConstraints);
3157+
SIZE_AND_BYTES(OpaqueArchetypeEnvironments);
3158+
SIZE(FunctionTypes);
3159+
SIZE(NormalConformances);
3160+
SIZE(SelfConformances);
3161+
SIZE(SpecializedConformances);
3162+
SIZE(InheritedConformances);
3163+
SIZE_AND_BYTES(BuiltinConformances);
3164+
SIZE(PackConformances);
3165+
SIZE(SubstitutionMaps);
3166+
3167+
#undef SIZE
3168+
#undef SIZE_AND_BYTES
3169+
}
3170+
30673171
void AbstractFunctionDecl::setForeignErrorConvention(
30683172
const ForeignErrorConvention &conv) {
30693173
assert(hasThrows() && "setting error convention on non-throwing decl");
@@ -5192,21 +5296,11 @@ void SubstitutionMap::Storage::Profile(
51925296
id.AddPointer(genericSig.getPointer());
51935297
if (!genericSig) return;
51945298

5195-
// Profile those replacement types that corresponding to canonical generic
5196-
// parameters within the generic signature.
5197-
id.AddInteger(replacementTypes.size());
5198-
5199-
unsigned i = 0;
5200-
genericSig->forEachParam([&](GenericTypeParamType *gp, bool canonical) {
5201-
if (canonical)
5202-
id.AddPointer(replacementTypes[i].getPointer());
5203-
else
5204-
id.AddPointer(nullptr);
5205-
++i;
5206-
});
5299+
// Replacement types.
5300+
for (auto replacementType : replacementTypes)
5301+
id.AddPointer(replacementType.getPointer());
52075302

52085303
// Conformances.
5209-
id.AddInteger(conformances.size());
52105304
for (auto conformance : conformances)
52115305
id.AddPointer(conformance.getOpaqueValue());
52125306
}

lib/AST/ASTDumper.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3816,16 +3816,13 @@ class PrintConformance : public PrintBase {
38163816

38173817
auto genericParams = genericSig.getGenericParams();
38183818
auto replacementTypes =
3819-
static_cast<const SubstitutionMap &>(map).getReplacementTypesBuffer();
3819+
static_cast<const SubstitutionMap &>(map).getReplacementTypes();
38203820
for (unsigned i : indices(genericParams)) {
38213821
if (style == SubstitutionMap::DumpStyle::Minimal) {
38223822
printFieldRaw([&](raw_ostream &out) {
38233823
genericParams[i]->print(out);
38243824
out << " -> ";
3825-
if (replacementTypes[i])
3826-
out << replacementTypes[i];
3827-
else
3828-
out << "<unresolved concrete type>";
3825+
out << replacementTypes[i];
38293826
}, "");
38303827
} else {
38313828
printRecArbitrary([&](StringRef label) {
@@ -3834,8 +3831,7 @@ class PrintConformance : public PrintBase {
38343831
genericParams[i]->print(out);
38353832
out << " -> ";
38363833
}, "");
3837-
if (replacementTypes[i])
3838-
printRec(replacementTypes[i]);
3834+
printRec(replacementTypes[i]);
38393835
printFoot();
38403836
});
38413837
}

lib/AST/ASTMangler.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,10 +1976,9 @@ void ASTMangler::appendRetroactiveConformances(Type type, GenericSignature sig)
19761976
if (type->hasUnboundGenericType())
19771977
return;
19781978

1979-
auto nominal = type->getAnyNominal();
1980-
if (!nominal) return;
1979+
if (!type->getAnyNominal()) return;
19811980

1982-
subMap = type->getContextSubstitutionMap(nominal);
1981+
subMap = type->getContextSubstitutionMap();
19831982
}
19841983

19851984
appendRetroactiveConformances(subMap, sig);

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,9 @@ struct InferRequirementsWalker : public TypeWalker {
637637
}
638638
}
639639

640-
if (!ty->isSpecialized())
640+
// Both is<ExistentialType>() and isSpecialized() end up being true if we
641+
// have invalid code where a protocol is nested inside a generic nominal.
642+
if (ty->is<ExistentialType>() || !ty->isSpecialized())
641643
return Action::Continue;
642644

643645
// Infer from generic nominal types.

0 commit comments

Comments
 (0)