Skip to content

Commit 4ab09b4

Browse files
authored
Merge pull request #4685 from slavapestov/add-substitution-map
New SubstitutionMap data structure
2 parents a118e24 + b677a2e commit 4ab09b4

32 files changed

+452
-417
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define SWIFT_AST_GENERIC_ENVIRONMENT_H
1919

2020
#include "swift/AST/ProtocolConformance.h"
21+
#include "swift/AST/SubstitutionMap.h"
2122

2223
namespace swift {
2324

@@ -60,12 +61,17 @@ class GenericEnvironment final {
6061
/// Derive a contextual type substitution map from a substitution array.
6162
/// This is just like GenericSignature::getSubstitutionMap(), except
6263
/// with contextual types instead of interface types.
64+
SubstitutionMap
65+
getSubstitutionMap(ModuleDecl *mod,
66+
GenericSignature *sig,
67+
ArrayRef<Substitution> subs) const;
68+
69+
/// Same as above, but updates an existing map.
6370
void
6471
getSubstitutionMap(ModuleDecl *mod,
6572
GenericSignature *sig,
6673
ArrayRef<Substitution> subs,
67-
TypeSubstitutionMap &subsMap,
68-
ArchetypeConformanceMap &conformanceMap) const;
74+
SubstitutionMap &subMap) const;
6975

7076
ArrayRef<Substitution>
7177
getForwardingSubstitutions(ModuleDecl *M, GenericSignature *sig) const;

include/swift/AST/GenericSignature.h

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626
namespace swift {
2727

2828
class ArchetypeBuilder;
29+
class ProtocolConformanceRef;
2930
class ProtocolType;
30-
31-
using TypeConformanceMap
32-
= llvm::DenseMap<TypeBase *, ArrayRef<ProtocolConformanceRef>>;
31+
class Substitution;
32+
class SubstitutionMap;
3333

3434
/// Iterator that walks the generic parameter types declared in a generic
3535
/// signature and their dependent members.
@@ -170,14 +170,11 @@ class GenericSignature final : public llvm::FoldingSetNode,
170170

171171
/// Build an interface type substitution map from a vector of Substitutions
172172
/// that correspond to the generic parameters in this generic signature.
173-
/// The order of primary archetypes in the substitution vector must match
174-
/// the order of generic parameters in getGenericParams().
175-
TypeSubstitutionMap getSubstitutionMap(ArrayRef<Substitution> args) const;
173+
SubstitutionMap getSubstitutionMap(ArrayRef<Substitution> args) const;
176174

177-
/// Variant of the above that also returns conformances.
178-
void getSubstitutionMap(ArrayRef<Substitution> subs,
179-
TypeSubstitutionMap &subMap,
180-
TypeConformanceMap &conformanceMap) const;
175+
/// Same as above, but updates an existing map.
176+
void getSubstitutionMap(ArrayRef<Substitution> args,
177+
SubstitutionMap &subMap) const;
181178

182179
using LookupConformanceFn =
183180
llvm::function_ref<ProtocolConformanceRef(CanType, Type, ProtocolType *)>;
@@ -192,8 +189,7 @@ class GenericSignature final : public llvm::FoldingSetNode,
192189
/// Build an array of substitutions from an interface type substitution map,
193190
/// using the given function to look up conformances.
194191
void getSubstitutions(ModuleDecl &mod,
195-
const TypeSubstitutionMap &subMap,
196-
const TypeConformanceMap &conformanceMap,
192+
const SubstitutionMap &subMap,
197193
SmallVectorImpl<Substitution> &result) const;
198194

199195
/// Return a range that iterates through first all of the generic parameters

include/swift/AST/ProtocolConformance.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,7 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
296296
/// applies to the substituted type.
297297
ProtocolConformance *subst(ModuleDecl *module,
298298
Type substType,
299-
TypeSubstitutionMap &subMap,
300-
ArchetypeConformanceMap &conformanceMap);
299+
const SubstitutionMap &subMap) const;
301300
};
302301

303302
/// Normal protocol conformance, which involves mapping each of the protocol

include/swift/AST/Substitution.h

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_AST_SUBSTITUTION_H
1818
#define SWIFT_AST_SUBSTITUTION_H
1919

20+
#include "swift/AST/SubstitutionMap.h"
2021
#include "swift/AST/Type.h"
2122
#include "llvm/ADT/ArrayRef.h"
2223
#include "llvm/ADT/Optional.h"
@@ -26,33 +27,7 @@ namespace llvm {
2627
}
2728

2829
namespace swift {
29-
class ArchetypeType;
3030
class GenericEnvironment;
31-
class ProtocolConformanceRef;
32-
33-
/// Data structure type used internally by Substitution::subst to track
34-
/// conformances applied to archetypes.
35-
class ArchetypeConformanceMap {
36-
using ParentType = std::pair<ArchetypeType *, AssociatedTypeDecl *>;
37-
38-
llvm::DenseMap<ArchetypeType *, ArrayRef<ProtocolConformanceRef>> map;
39-
llvm::DenseMap<ArchetypeType *, SmallVector<ParentType, 1>> parents;
40-
41-
Optional<ProtocolConformanceRef>
42-
lookupArchetypeConformance(ProtocolDecl *proto,
43-
ArrayRef<ProtocolConformanceRef> conformances) const;
44-
45-
public:
46-
Optional<ProtocolConformanceRef>
47-
lookupArchetypeConformance(ArchetypeType *replacement,
48-
ProtocolDecl *proto) const;
49-
50-
void addArchetypeConformances(ArchetypeType *replacement,
51-
ArrayRef<ProtocolConformanceRef> conformances);
52-
53-
void addArchetypeParent(ArchetypeType *replacement, ArchetypeType *parent,
54-
AssociatedTypeDecl *assocType);
55-
};
5631

5732
/// Substitution - A substitution into a generic specialization.
5833
class Substitution {
@@ -92,8 +67,7 @@ class Substitution {
9267
ArrayRef<Substitution> subs) const;
9368

9469
Substitution subst(ModuleDecl *module,
95-
TypeSubstitutionMap &subMap,
96-
ArchetypeConformanceMap &conformanceMap) const;
70+
const SubstitutionMap &subMap) const;
9771

9872
private:
9973
friend class ProtocolConformance;

include/swift/AST/SubstitutionMap.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===--- SubstitutionMap.h - Swift Substitution Map ASTs --------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines the SubstitutionMap class.
14+
//
15+
// This is a data structure type describing the mapping of abstract types to
16+
// replacement types, together with associated conformances to use for deriving
17+
// nested types.
18+
//
19+
// Depending on how the SubstitutionMap is constructed, the abstract types are
20+
// either archetypes or interface types. Care must be exercised to only look up
21+
// one or the other.
22+
//
23+
//===----------------------------------------------------------------------===//
24+
25+
#ifndef SWIFT_AST_SUBSTITUTION_MAP_H
26+
#define SWIFT_AST_SUBSTITUTION_MAP_H
27+
28+
#include "swift/AST/ProtocolConformanceRef.h"
29+
#include "swift/AST/Type.h"
30+
#include "llvm/ADT/ArrayRef.h"
31+
#include "llvm/ADT/DenseMap.h"
32+
#include "llvm/ADT/Optional.h"
33+
#include "llvm/ADT/SmallVector.h"
34+
35+
namespace swift {
36+
37+
class SubstitutionMap {
38+
using ParentType = std::pair<CanType, AssociatedTypeDecl *>;
39+
40+
llvm::DenseMap<TypeBase *, Type> subMap;
41+
llvm::DenseMap<TypeBase *, ArrayRef<ProtocolConformanceRef>> conformanceMap;
42+
llvm::DenseMap<TypeBase *, SmallVector<ParentType, 1>> parentMap;
43+
44+
Optional<ProtocolConformanceRef>
45+
lookupConformance(ProtocolDecl *proto,
46+
ArrayRef<ProtocolConformanceRef> conformances) const;
47+
48+
template<typename Fn>
49+
Optional<ProtocolConformanceRef> forEachParent(CanType type, Fn fn) const;
50+
51+
public:
52+
Optional<ProtocolConformanceRef>
53+
lookupConformance(CanType type, ProtocolDecl *proto) const;
54+
55+
const llvm::DenseMap<TypeBase *, Type> &getMap() const {
56+
return subMap;
57+
}
58+
59+
void addSubstitution(CanType type, Type replacement);
60+
61+
void addConformances(CanType type, ArrayRef<ProtocolConformanceRef> conformances);
62+
63+
void addParent(CanType type, CanType parent,
64+
AssociatedTypeDecl *assocType);
65+
66+
void removeType(CanType type);
67+
};
68+
69+
} // end namespace swift
70+
71+
#endif

include/swift/AST/Type.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class NormalProtocolConformance;
4242
enum OptionalTypeKind : unsigned;
4343
class ProtocolDecl;
4444
class StructDecl;
45+
class SubstitutionMap;
4546
class TypeBase;
4647
class Type;
4748
class TypeWalker;
@@ -159,7 +160,7 @@ class Type {
159160
/// Replace references to substitutable types with new, concrete types and
160161
/// return the substituted result.
161162
///
162-
/// \param module The module in which the substitution occurs.
163+
/// \param module The module to use for conformance lookups.
163164
///
164165
/// \param substitutions The mapping from substitutable types to their
165166
/// replacements.
@@ -171,6 +172,18 @@ class Type {
171172
const TypeSubstitutionMap &substitutions,
172173
SubstOptions options) const;
173174

175+
/// Replace references to substitutable types with new, concrete types and
176+
/// return the substituted result.
177+
///
178+
/// \param substitutions The mapping from substitutable types to their
179+
/// replacements and conformances.
180+
///
181+
/// \param options Options that affect the substitutions.
182+
///
183+
/// \returns the substituted type, or a null type if an error occurred.
184+
Type subst(const SubstitutionMap &substitutions,
185+
SubstOptions options) const;
186+
174187
bool isPrivateStdlibType(bool whitelistProtocols=true) const;
175188

176189
void dump() const;

include/swift/AST/Types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2480,7 +2480,7 @@ class GenericFunctionType : public AnyFunctionType,
24802480
/// function type and return the resulting non-generic type.
24812481
///
24822482
/// The order of Substitutions must match the order of generic parameters.
2483-
FunctionType *substGenericArgs(ModuleDecl *M, ArrayRef<Substitution> subs);
2483+
FunctionType *substGenericArgs(ArrayRef<Substitution> subs);
24842484

24852485
void Profile(llvm::FoldingSetNodeID &ID) {
24862486
Profile(ID, getGenericSignature(), getInput(), getResult(),

include/swift/SIL/TypeSubstCloner.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
5555

5656
TypeSubstCloner(SILFunction &To,
5757
SILFunction &From,
58-
TypeSubstitutionMap &ContextSubs,
58+
const SubstitutionMap &ContextSubs,
5959
ArrayRef<Substitution> ApplySubs,
6060
SILOpenedArchetypesTracker &OpenedArchetypesTracker,
6161
bool Inlining = false)
@@ -68,7 +68,7 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
6868

6969
TypeSubstCloner(SILFunction &To,
7070
SILFunction &From,
71-
TypeSubstitutionMap &ContextSubs,
71+
const SubstitutionMap &ContextSubs,
7272
ArrayRef<Substitution> ApplySubs,
7373
bool Inlining = false)
7474
: SILClonerWithScopes<ImplClass>(To, Inlining),
@@ -81,11 +81,12 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
8181

8282
protected:
8383
SILType remapType(SILType Ty) {
84-
return SILType::substType(Original.getModule(), SwiftMod, SubsMap, Ty);
84+
return SILType::substType(Original.getModule(), SwiftMod,
85+
SubsMap.getMap(), Ty);
8586
}
8687

8788
CanType remapASTType(CanType ty) {
88-
return ty.subst(SwiftMod, SubsMap, None)->getCanonicalType();
89+
return ty.subst(SubsMap, None)->getCanonicalType();
8990
}
9091

9192
Substitution remapSubstitution(Substitution sub) {
@@ -288,7 +289,7 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
288289
/// The Swift module that the cloned function belongs to.
289290
Module *SwiftMod;
290291
/// The substitutions list for the specialization.
291-
TypeSubstitutionMap &SubsMap;
292+
const SubstitutionMap &SubsMap;
292293
/// The original function to specialize.
293294
SILFunction &Original;
294295
/// The substitutions used at the call site.

include/swift/SILOptimizer/Utils/GenericCloner.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class GenericCloner : public TypeSubstCloner<GenericCloner> {
4141
GenericCloner(SILFunction *F,
4242
IsFragile_t Fragile,
4343
const ReabstractionInfo &ReInfo,
44-
TypeSubstitutionMap &ContextSubs,
44+
SubstitutionMap &ContextSubs,
4545
ArrayRef<Substitution> ParamSubs,
4646
StringRef NewName,
4747
CloneCollector::CallbackType Callback)
@@ -56,7 +56,7 @@ class GenericCloner : public TypeSubstCloner<GenericCloner> {
5656
cloneFunction(SILFunction *F,
5757
IsFragile_t Fragile,
5858
const ReabstractionInfo &ReInfo,
59-
TypeSubstitutionMap &ContextSubs,
59+
SubstitutionMap &ContextSubs,
6060
ArrayRef<Substitution> ParamSubs,
6161
StringRef NewName,
6262
CloneCollector::CallbackType Callback =nullptr) {

include/swift/SILOptimizer/Utils/Generics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class GenericFuncSpecializer {
138138
IsFragile_t Fragile;
139139
const ReabstractionInfo &ReInfo;
140140

141-
TypeSubstitutionMap ContextSubs;
141+
SubstitutionMap ContextSubs;
142142
std::string ClonedName;
143143
public:
144144
GenericFuncSpecializer(SILFunction *GenericFunc,

include/swift/SILOptimizer/Utils/Local.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,15 @@ void replaceDeadApply(ApplySite Old, ValueBase *New);
138138

139139
/// \brief Return true if the substitution map contains a
140140
/// substitution that is an unbound generic type.
141-
bool hasUnboundGenericTypes(TypeSubstitutionMap &SubsMap);
141+
bool hasUnboundGenericTypes(const TypeSubstitutionMap &SubsMap);
142142

143143
/// Return true if the substitution list contains a substitution
144144
/// that is an unbound generic.
145145
bool hasUnboundGenericTypes(ArrayRef<Substitution> Subs);
146146

147147
/// \brief Return true if the substitution map contains a
148148
/// substitution that refers to the dynamic Self type.
149-
bool hasDynamicSelfTypes(TypeSubstitutionMap &SubsMap);
149+
bool hasDynamicSelfTypes(const TypeSubstitutionMap &SubsMap);
150150

151151
/// \brief Return true if the substitution list contains a
152152
/// substitution that refers to the dynamic Self type.

include/swift/SILOptimizer/Utils/SILInliner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class SILInliner : public TypeSubstCloner<SILInliner> {
4646
};
4747

4848
SILInliner(SILFunction &To, SILFunction &From, InlineKind IKind,
49-
TypeSubstitutionMap &ContextSubs, ArrayRef<Substitution> ApplySubs,
49+
SubstitutionMap &ContextSubs, ArrayRef<Substitution> ApplySubs,
5050
SILOpenedArchetypesTracker &OpenedArchetypesTracker,
5151
CloneCollector::CallbackType Callback = nullptr)
5252
: TypeSubstCloner<SILInliner>(To, From, ContextSubs, ApplySubs,

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ add_swift_library(swiftAST STATIC
3939
Stmt.cpp
4040
SourceEntityWalker.cpp
4141
Substitution.cpp
42+
SubstitutionMap.cpp
4243
Type.cpp
4344
TypeJoinMeet.cpp
4445
TypeRefinementContext.cpp

0 commit comments

Comments
 (0)