Skip to content

Commit 204a743

Browse files
authored
Merge pull request #64683 from rjmccall/variadic-generics-omnibus-5.9
[5.9] Omnibus merge of my recent variadic generics work
2 parents 2c3a9cc + 92afbc5 commit 204a743

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2340
-1894
lines changed
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
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+
struct ActivePackExpansion {
36+
bool isSubstExpansion = false;
37+
unsigned expansionIndex = 0;
38+
};
39+
SmallVector<ActivePackExpansion, 4> ActivePackExpansions;
40+
41+
public:
42+
InFlightSubstitution(TypeSubstitutionFn substType,
43+
LookupConformanceFn lookupConformance,
44+
SubstOptions options)
45+
: Options(options),
46+
BaselineSubstType(substType),
47+
BaselineLookupConformance(lookupConformance) {}
48+
49+
InFlightSubstitution(const InFlightSubstitution &) = delete;
50+
InFlightSubstitution &operator=(const InFlightSubstitution &) = delete;
51+
52+
// TODO: when we add PackElementType, we should recognize it during
53+
// substitution and either call different methods on this class or
54+
// pass an extra argument for the pack-expansion depth D. We should
55+
// be able to rely on that to mark a pack-element reference instead
56+
// of checking whether the original type was a pack. Substitution
57+
// should use the D'th entry from the end of ActivePackExpansions to
58+
// guide the element substitution:
59+
// - project the given index of the pack substitution
60+
// - wrap it in a PackElementType if it's a subst expansion
61+
// - the depth of that PackElementType is the number of subst
62+
// expansions between the depth entry and the end of
63+
// ActivePackExpansions
64+
65+
/// Perform primitive substitution on the given type. Returns Type()
66+
/// if the type should not be substituted as a whole.
67+
Type substType(SubstitutableType *origType);
68+
69+
/// Perform primitive conformance lookup on the given type.
70+
ProtocolConformanceRef lookupConformance(CanType dependentType,
71+
Type conformingReplacementType,
72+
ProtocolDecl *conformedProtocol);
73+
74+
/// Given the shape type of a pack expansion, invoke the given callback
75+
/// for each expanded component of it. If the substituted component
76+
/// is an expansion component, the desired shape of that expansion
77+
/// is passed as the argument; otherwise, the argument is Type().
78+
/// In either case, an active expansion is entered on this IFS for
79+
/// the duration of the call to handleComponent, and subsequent
80+
/// pack-element type references will substitute to the corresponding
81+
/// element of the substitution of the pack.
82+
void expandPackExpansionShape(Type origShape,
83+
llvm::function_ref<void(Type substComponentShape)> handleComponent);
84+
85+
/// Call the given function for each expanded component type of the
86+
/// given pack expansion type. The function will be invoked with the
87+
/// active expansion still active.
88+
void expandPackExpansionType(PackExpansionType *origExpansionType,
89+
llvm::function_ref<void(Type substType)> handleComponentType) {
90+
expandPackExpansionShape(origExpansionType->getCountType(),
91+
[&](Type substComponentShape) {
92+
auto origPatternType = origExpansionType->getPatternType();
93+
auto substEltType = origPatternType.subst(*this);
94+
95+
auto substComponentType =
96+
(substComponentShape
97+
? PackExpansionType::get(substEltType, substComponentShape)
98+
: substEltType);
99+
handleComponentType(substComponentType);
100+
});
101+
}
102+
103+
/// Return a list of component types that the pack expansion expands to.
104+
SmallVector<Type, 8>
105+
expandPackExpansionType(PackExpansionType *origExpansionType) {
106+
SmallVector<Type, 8> substComponentTypes;
107+
expandPackExpansionType(origExpansionType, substComponentTypes);
108+
return substComponentTypes;
109+
}
110+
111+
/// Expand the list of component types that the pack expansion expands
112+
/// to into the given array.
113+
void expandPackExpansionType(PackExpansionType *origExpansionType,
114+
SmallVectorImpl<Type> &substComponentTypes) {
115+
expandPackExpansionType(origExpansionType, [&](Type substComponentType) {
116+
substComponentTypes.push_back(substComponentType);
117+
});
118+
}
119+
120+
class OptionsAdjustmentScope {
121+
InFlightSubstitution &IFS;
122+
SubstOptions SavedOptions;
123+
124+
public:
125+
OptionsAdjustmentScope(InFlightSubstitution &IFS, SubstOptions newOptions)
126+
: IFS(IFS), SavedOptions(IFS.Options) {
127+
IFS.Options = newOptions;
128+
}
129+
130+
OptionsAdjustmentScope(const OptionsAdjustmentScope &) = delete;
131+
OptionsAdjustmentScope &operator=(const OptionsAdjustmentScope &) = delete;
132+
133+
~OptionsAdjustmentScope() {
134+
IFS.Options = SavedOptions;
135+
}
136+
};
137+
138+
template <class Fn>
139+
auto withNewOptions(SubstOptions options, Fn &&fn)
140+
-> decltype(std::forward<Fn>(fn)()) {
141+
OptionsAdjustmentScope scope(*this, options);
142+
return std::forward<Fn>(fn)();
143+
}
144+
145+
SubstOptions getOptions() const {
146+
return Options;
147+
}
148+
149+
bool shouldSubstituteOpaqueArchetypes() const {
150+
return Options.contains(SubstFlags::SubstituteOpaqueArchetypes);
151+
}
152+
153+
/// Is the given type invariant to substitution?
154+
bool isInvariant(Type type) const;
155+
};
156+
157+
/// A helper classes that provides stable storage for the query
158+
/// functions against a SubstitutionMap.
159+
struct InFlightSubstitutionViaSubMapHelper {
160+
QuerySubstitutionMap QueryType;
161+
LookUpConformanceInSubstitutionMap QueryConformance;
162+
163+
InFlightSubstitutionViaSubMapHelper(SubstitutionMap subMap)
164+
: QueryType{subMap}, QueryConformance(subMap) {}
165+
};
166+
class InFlightSubstitutionViaSubMap :
167+
private InFlightSubstitutionViaSubMapHelper,
168+
public InFlightSubstitution {
169+
170+
public:
171+
InFlightSubstitutionViaSubMap(SubstitutionMap subMap,
172+
SubstOptions options)
173+
: InFlightSubstitutionViaSubMapHelper(subMap),
174+
InFlightSubstitution(QueryType, QueryConformance, options) {}
175+
};
176+
177+
} // end namespace swift
178+
179+
#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
};

0 commit comments

Comments
 (0)