Skip to content

Commit 80551ce

Browse files
committed
[NFC] Thread a common type through all the AST substitution code.
There are a lot of problems caused by our highly-abstract substitution subsystem. Most of them would be solved by a more semantic / holistic understanding of the active transformation, but that's difficult to do because we just pass around function_refs. The first step in fixing that is to pass around a better currency type. For now, it can just hold the function_refs (and the SubstOptions). I've set it up so that the places that just apply SubstitutionMaps are constructing the IFS in a standard way; that should make it easy to change those places in the future.
1 parent 4e14288 commit 80551ce

11 files changed

+258
-118
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//===--- InFlightSubstitution.h - In-flight substitution data ---*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines the InFlightSubstitution structure, which captures
14+
// all the information about a type substitution that's currently in
15+
// progress. For now, this is meant to be an internal implementation
16+
// detail of the substitution system, and other systems should not use
17+
// it (unless they are part of the extended substitution system, such as
18+
// the SIL type substituter)
19+
//
20+
//===----------------------------------------------------------------------===//
21+
22+
#ifndef SWIFT_AST_INFLIGHTSUBSTITUTION_H
23+
#define SWIFT_AST_INFLIGHTSUBSTITUTION_H
24+
25+
#include "swift/AST/SubstitutionMap.h"
26+
27+
namespace swift {
28+
class SubstitutionMap;
29+
30+
class InFlightSubstitution {
31+
SubstOptions Options;
32+
TypeSubstitutionFn BaselineSubstType;
33+
LookupConformanceFn BaselineLookupConformance;
34+
35+
public:
36+
InFlightSubstitution(TypeSubstitutionFn substType,
37+
LookupConformanceFn lookupConformance,
38+
SubstOptions options)
39+
: Options(options),
40+
BaselineSubstType(substType),
41+
BaselineLookupConformance(lookupConformance) {}
42+
43+
InFlightSubstitution(const InFlightSubstitution &) = delete;
44+
InFlightSubstitution &operator=(const InFlightSubstitution &) = delete;
45+
46+
Type substType(SubstitutableType *ty) {
47+
return BaselineSubstType(ty);
48+
}
49+
50+
ProtocolConformanceRef lookupConformance(CanType dependentType,
51+
Type conformingReplacementType,
52+
ProtocolDecl *conformedProtocol) {
53+
return BaselineLookupConformance(dependentType,
54+
conformingReplacementType,
55+
conformedProtocol);
56+
}
57+
58+
SubstOptions getOptions() const {
59+
return Options;
60+
}
61+
62+
/// Is the given type invariant to substitution?
63+
bool isInvariant(Type type) const;
64+
};
65+
66+
/// A helper classes that provides stable storage for the query
67+
/// functions against a SubstitutionMap.
68+
struct InFlightSubstitutionViaSubMapHelper {
69+
QuerySubstitutionMap QueryType;
70+
LookUpConformanceInSubstitutionMap QueryConformance;
71+
72+
InFlightSubstitutionViaSubMapHelper(SubstitutionMap subMap)
73+
: QueryType{subMap}, QueryConformance(subMap) {}
74+
};
75+
class InFlightSubstitutionViaSubMap :
76+
private InFlightSubstitutionViaSubMapHelper,
77+
public InFlightSubstitution {
78+
79+
public:
80+
InFlightSubstitutionViaSubMap(SubstitutionMap subMap,
81+
SubstOptions options)
82+
: InFlightSubstitutionViaSubMapHelper(subMap),
83+
InFlightSubstitution(QueryType, QueryConformance, options) {}
84+
};
85+
86+
} // end namespace swift
87+
88+
#endif

include/swift/AST/PackConformance.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ class alignas(1 << DeclAlignInBits) PackConformance final
8888
LookupConformanceFn conformances,
8989
SubstOptions options=None) const;
9090

91+
/// Apply an in-flight substitution to the conformances in this
92+
/// protocol conformance ref.
93+
///
94+
/// This function should generally not be used outside of the
95+
/// substitution subsystem.
96+
ProtocolConformanceRef subst(InFlightSubstitution &IFS) const;
97+
9198
SWIFT_DEBUG_DUMP;
9299
void dump(llvm::raw_ostream &out, unsigned indent = 0) const;
93100
};

include/swift/AST/ProtocolConformance.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,13 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance
309309
LookupConformanceFn conformances,
310310
SubstOptions options=None) const;
311311

312+
/// Substitute the conforming type and produce a ProtocolConformance that
313+
/// applies to the substituted type.
314+
///
315+
/// This function should generally not be used outside of the substitution
316+
/// subsystem.
317+
ProtocolConformance *subst(InFlightSubstitution &IFS) const;
318+
312319
SWIFT_DEBUG_DUMP;
313320
void dump(llvm::raw_ostream &out, unsigned indent = 0) const;
314321
};

include/swift/AST/ProtocolConformanceRef.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,13 @@ class ProtocolConformanceRef {
164164
LookupConformanceFn conformances,
165165
SubstOptions options=None) const;
166166

167+
/// Apply a substitution to the conforming type.
168+
///
169+
/// This function should generally not be used outside of the substitution
170+
/// subsystem.
171+
ProtocolConformanceRef subst(Type origType,
172+
InFlightSubstitution &IFS) const;
173+
167174
/// Map contextual types to interface types in the conformance.
168175
ProtocolConformanceRef mapConformanceOutOfContext() const;
169176

include/swift/AST/SubstitutionMap.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,14 @@ class SubstitutionMap {
121121
TypeSubstitutionFn subs,
122122
LookupConformanceFn lookupConformance);
123123

124+
/// Build a substitution map from the substitutions represented by
125+
/// the given in-flight substitution.
126+
///
127+
/// This function should generally only be used by the substitution
128+
/// subsystem.
129+
static SubstitutionMap get(GenericSignature genericSig,
130+
InFlightSubstitution &IFS);
131+
124132
/// Retrieve the generic signature describing the environment in which
125133
/// substitutions occur.
126134
GenericSignature getGenericSignature() const;
@@ -182,6 +190,13 @@ class SubstitutionMap {
182190
LookupConformanceFn conformances,
183191
SubstOptions options=None) const;
184192

193+
/// Apply an in-flight substitution to all replacement types in the map.
194+
/// Does not change keys.
195+
///
196+
/// This should generally not be used outside of the substitution
197+
/// subsystem.
198+
SubstitutionMap subst(InFlightSubstitution &subs) const;
199+
185200
/// Apply type expansion lowering to all types in the substitution map. Opaque
186201
/// archetypes will be lowered to their underlying types if the type expansion
187202
/// context allows.

include/swift/AST/Type.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class ClassDecl;
4343
class CanType;
4444
class EnumDecl;
4545
class GenericSignatureImpl;
46+
class InFlightSubstitution;
4647
class ModuleDecl;
4748
class NominalTypeDecl;
4849
class GenericTypeDecl;
@@ -343,6 +344,12 @@ class Type {
343344
LookupConformanceFn conformances,
344345
SubstOptions options=None) const;
345346

347+
/// Apply an in-flight substitution to this type.
348+
///
349+
/// This should generally not be used outside of the substitution
350+
/// subsystem.
351+
Type subst(InFlightSubstitution &subs) const;
352+
346353
bool isPrivateStdlibType(bool treatNonBuiltinProtocolsAsPublic = true) const;
347354

348355
SWIFT_DEBUG_DUMP;

lib/AST/PackConformance.cpp

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/AST/PackConformance.h"
1919
#include "swift/AST/ASTContext.h"
2020
#include "swift/AST/Decl.h"
21+
#include "swift/AST/InFlightSubstitution.h"
2122
#include "swift/AST/Module.h"
2223
#include "swift/AST/Types.h"
2324

@@ -162,9 +163,8 @@ PackConformance *PackConformance::getAssociatedConformance(
162163

163164
ProtocolConformanceRef PackConformance::subst(SubstitutionMap subMap,
164165
SubstOptions options) const {
165-
return subst(QuerySubstitutionMap{subMap},
166-
LookUpConformanceInSubstitutionMap(subMap),
167-
options);
166+
InFlightSubstitutionViaSubMap IFS(subMap, options);
167+
return subst(IFS);
168168
}
169169

170170
// TODO: Move this elsewhere since it's generally useful
@@ -206,14 +206,9 @@ namespace {
206206
template<typename ImplClass>
207207
class PackExpander {
208208
protected:
209-
TypeSubstitutionFn subs;
210-
LookupConformanceFn conformances;
211-
SubstOptions options;
209+
InFlightSubstitution &IFS;
212210

213-
PackExpander(TypeSubstitutionFn subs,
214-
LookupConformanceFn conformances,
215-
SubstOptions options)
216-
: subs(subs), conformances(conformances), options(options) {}
211+
PackExpander(InFlightSubstitution &IFS) : IFS(IFS) {}
217212

218213
ImplClass *asImpl() {
219214
return static_cast<ImplClass *>(this);
@@ -233,7 +228,7 @@ class PackExpander {
233228
// the expanded count pack type.
234229
llvm::SmallDenseMap<Type, PackType *, 2> expandedPacks;
235230
for (auto origParamType : rootParameterPacks) {
236-
auto substParamType = origParamType.subst(subs, conformances, options);
231+
auto substParamType = origParamType.subst(IFS);
237232

238233
if (auto expandedParamType = substParamType->template getAs<PackType>()) {
239234
assert(arePackShapesEqual(expandedParamType, expandedCountType) &&
@@ -262,7 +257,7 @@ class PackExpander {
262257
}
263258

264259
// Compute the substituted type using our parent substitutions.
265-
auto substType = Type(type).subst(subs, conformances, options);
260+
auto substType = Type(type).subst(IFS);
266261

267262
// If the substituted type is a pack, project the jth element.
268263
if (isRootParameterPack(type)) {
@@ -277,12 +272,13 @@ class PackExpander {
277272
return packType->getElementType(j);
278273
}
279274

280-
return subs(type);
275+
return IFS.substType(type);
281276
};
282277

283278
auto projectedConformances = [&](CanType origType, Type substType,
284279
ProtocolDecl *proto) -> ProtocolConformanceRef {
285-
auto substConformance = conformances(origType, substType, proto);
280+
auto substConformance =
281+
IFS.lookupConformance(origType, substType, proto);
286282

287283
// If the substituted conformance is a pack, project the jth element.
288284
if (isRootedInParameterPack(origType)) {
@@ -294,7 +290,7 @@ class PackExpander {
294290

295291
auto origCountElement = expandedCountType->getElementType(j);
296292
auto substCountElement = origCountElement.subst(
297-
projectedSubs, projectedConformances, options);
293+
projectedSubs, projectedConformances, IFS.getOptions());
298294

299295
asImpl()->add(origCountElement, substCountElement, i);
300296
}
@@ -304,7 +300,7 @@ class PackExpander {
304300
/// form a new pack expansion.
305301
void addUnexpandedExpansion(Type origPatternType, Type substCountType,
306302
unsigned i) {
307-
auto substPatternType = origPatternType.subst(subs, conformances, options);
303+
auto substPatternType = origPatternType.subst(IFS);
308304
auto substExpansion = PackExpansionType::get(substPatternType, substCountType);
309305

310306
asImpl()->add(origPatternType, substExpansion, i);
@@ -313,7 +309,7 @@ class PackExpander {
313309
/// Scalar elements of the original pack are substituted and added to the
314310
/// flattened pack.
315311
void addScalar(Type origElement, unsigned i) {
316-
auto substElement = origElement.subst(subs, conformances, options);
312+
auto substElement = origElement.subst(IFS);
317313

318314
asImpl()->add(origElement, substElement, i);
319315
}
@@ -323,7 +319,7 @@ class PackExpander {
323319
auto origPatternType = origExpansion->getPatternType();
324320
auto origCountType = origExpansion->getCountType();
325321

326-
auto substCountType = origCountType.subst(subs, conformances, options);
322+
auto substCountType = origCountType.subst(IFS);
327323

328324
// If the substituted count type is a pack, we're expanding the
329325
// original element.
@@ -358,19 +354,16 @@ class PackConformanceExpander : public PackExpander<PackConformanceExpander> {
358354

359355
ArrayRef<ProtocolConformanceRef> origConformances;
360356

361-
PackConformanceExpander(TypeSubstitutionFn subs,
362-
LookupConformanceFn conformances,
363-
SubstOptions options,
357+
PackConformanceExpander(InFlightSubstitution &IFS,
364358
ArrayRef<ProtocolConformanceRef> origConformances)
365-
: PackExpander(subs, conformances, options),
366-
origConformances(origConformances) {}
359+
: PackExpander(IFS), origConformances(origConformances) {}
367360

368361
void add(Type origType, Type substType, unsigned i) {
369362
substElements.push_back(substType);
370363

371364
// FIXME: Pass down projection callbacks
372365
substConformances.push_back(origConformances[i].subst(
373-
origType, subs, conformances, options));
366+
origType, IFS));
374367
}
375368
};
376369

@@ -379,8 +372,13 @@ class PackConformanceExpander : public PackExpander<PackConformanceExpander> {
379372
ProtocolConformanceRef PackConformance::subst(TypeSubstitutionFn subs,
380373
LookupConformanceFn conformances,
381374
SubstOptions options) const {
382-
PackConformanceExpander expander(subs, conformances, options,
383-
getPatternConformances());
375+
InFlightSubstitution IFS(subs, conformances, options);
376+
return subst(IFS);
377+
}
378+
379+
ProtocolConformanceRef
380+
PackConformance::subst(InFlightSubstitution &IFS) const {
381+
PackConformanceExpander expander(IFS, getPatternConformances());
384382
expander.expand(ConformingType);
385383

386384
auto &ctx = Protocol->getASTContext();

0 commit comments

Comments
 (0)