Skip to content

Commit 1c29764

Browse files
authored
Merge pull request #60152 from slavapestov/witness-cleanup
Fix some job security in the witness representation
2 parents 8fa3d2f + 03b3ec8 commit 1c29764

File tree

8 files changed

+78
-102
lines changed

8 files changed

+78
-102
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
#include "swift/AST/TypeAlignments.h"
3636
#include "swift/AST/TypeWalker.h"
3737
#include "swift/AST/Types.h"
38-
#include "swift/AST/Witness.h"
3938
#include "swift/Basic/ArrayRefView.h"
4039
#include "swift/Basic/Compiler.h"
4140
#include "swift/Basic/Debug.h"
@@ -105,6 +104,7 @@ namespace swift {
105104
class ValueDecl;
106105
class VarDecl;
107106
class OpaqueReturnTypeRepr;
107+
class Witness;
108108

109109
namespace ast_scope {
110110
class AbstractPatternEntryScope;

include/swift/AST/RequirementEnvironment.h

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ namespace swift {
3535
/// environment are the type parameters of the conformance context
3636
/// (\c conformanceDC) with another (deeper) level of type parameters for
3737
/// generic requirements. See the \c Witness class for more information about
38-
/// this synthetic environment.
38+
/// the witness thunk signature.
3939
class RequirementEnvironment {
4040
/// A generic signature that combines the generic parameters of the
4141
/// concrete conforming type with the generic parameters of the
@@ -52,7 +52,7 @@ class RequirementEnvironment {
5252
/// <Self : P, T>
5353
/// <A, B, T>
5454
///
55-
/// The synthetic signature in this case is just the witness signature.
55+
/// The witness thunk signature in this case is just the witness signature.
5656
///
5757
/// It may be that the witness is more generic than the requirement,
5858
/// for example:
@@ -65,22 +65,21 @@ class RequirementEnvironment {
6565
/// <Self : P>
6666
/// <A, B, T>
6767
///
68-
/// The synthetic signature is just:
68+
/// The witness thunk signature is just:
6969
///
7070
/// <A, B>
7171
///
72-
/// The witness thunk emitted by SILGen uses the synthetic signature.
72+
/// The witness thunk emitted by SILGen uses the witness thunk signature.
7373
/// Therefore one invariant we preserve is that the witness thunk is
7474
/// ABI compatible with the requirement's function type.
75-
GenericSignature syntheticSignature = GenericSignature();
76-
GenericEnvironment *syntheticEnvironment = nullptr;
75+
GenericSignature witnessThunkSig = GenericSignature();
7776

7877
/// The generic signature of the protocol requirement member.
7978
GenericSignature reqSig = GenericSignature();
8079

8180
/// A substitution map mapping the requirement signature to the
82-
/// generic parameters of the synthetic signature.
83-
SubstitutionMap reqToSyntheticEnvMap;
81+
/// generic parameters of the witness thunk signature.
82+
SubstitutionMap reqToWitnessThunkSigMap;
8483

8584
public:
8685
/// Create a new environment for matching the given requirement within a
@@ -102,20 +101,20 @@ class RequirementEnvironment {
102101
ClassDecl *covariantSelf,
103102
ProtocolConformance *conformance);
104103

105-
/// Retrieve the synthetic generic environment.
106-
GenericEnvironment *getSyntheticEnvironment() const {
107-
return syntheticEnvironment;
108-
}
109-
110104
/// Retrieve the generic signature of the requirement.
111105
GenericSignature getRequirementSignature() const {
112106
return reqSig;
113107
}
114108

109+
/// Retrieve the generic signature of the witness thunk.
110+
GenericSignature getWitnessThunkSignature() const {
111+
return witnessThunkSig;
112+
}
113+
115114
/// Retrieve the substitution map that maps the interface types of the
116-
/// requirement to the interface types of the synthetic environment.
117-
SubstitutionMap getRequirementToSyntheticMap() const {
118-
return reqToSyntheticEnvMap;
115+
/// requirement to the interface types of the witness thunk signature.
116+
SubstitutionMap getRequirementToWitnessThunkSubs() const {
117+
return reqToWitnessThunkSigMap;
119118
}
120119
};
121120

include/swift/AST/Witness.h

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class ValueDecl;
7272
/// The witness for \c R.foo(x:) is \c X<U, V>.foo(x:), but the generic
7373
/// functions that describe the generic requirement in \c R and the generic
7474
/// method in \c X have very different signatures. To handle this case, the
75-
/// \c Witness class produces a "synthetic" environment that pulls together
75+
/// \c Witness class produces a witness thunk signature that pulls together
7676
/// all of the information needed to map from the requirement to the witness.
7777
/// It is a generic environment that combines the constraints of the
7878
/// requirement with the constraints from the context of the protocol
@@ -81,19 +81,19 @@ class ValueDecl;
8181
/// environment are those of the context of the protocol conformance (\c U
8282
/// and \c V, in the example above) and the innermost generic parameters are
8383
/// those of the generic requirement (\c T, in the example above). The
84-
/// \c Witness class contains this synthetic environment (both its generic
84+
/// \c Witness class contains this witness thunk signature (both its generic
8585
/// signature and a generic environment providing archetypes), a substitution
8686
/// map that allows one to map the interface types of the requirement into
87-
/// the interface types of the synthetic domain, and the set of substitutions
88-
/// required to use the witness from the synthetic domain (e.g., how one would
87+
/// the interface types of the witness thunk domain, and the set of substitutions
88+
/// required to use the witness from the witness thunk domain (e.g., how one would
8989
/// call the witness from the witness thunk).
9090
class Witness {
9191
struct StoredWitness {
9292
/// The witness declaration, along with the substitutions needed to use
93-
/// the witness declaration from the synthetic environment.
93+
/// the witness declaration from the witness thunk signature.
9494
ConcreteDeclRef declRef;
95-
GenericEnvironment *syntheticEnvironment;
96-
SubstitutionMap reqToSyntheticEnvSubs;
95+
GenericSignature witnessThunkSig;
96+
SubstitutionMap reqToWitnessThunkSigSubs;
9797
/// The derivative generic signature, when the requirement is a derivative
9898
/// function.
9999
GenericSignature derivativeGenSig;
@@ -124,7 +124,7 @@ class Witness {
124124

125125
/// Create a witness for the given requirement.
126126
///
127-
/// Deserialized witnesses do not have a synthetic environment.
127+
/// Deserialized witnesses do not have a witness thunk signature.
128128
static Witness forDeserialized(ValueDecl *decl,
129129
SubstitutionMap substitutions,
130130
Optional<ActorIsolation> enterIsolation) {
@@ -139,12 +139,12 @@ class Witness {
139139
/// \param decl The declaration for the witness.
140140
///
141141
/// \param substitutions The substitutions required to use the witness from
142-
/// the synthetic environment.
142+
/// the witness thunk signature.
143143
///
144-
/// \param syntheticEnv The synthetic environment.
144+
/// \param witnessThunkSig The witness thunk signature.
145145
///
146-
/// \param reqToSyntheticEnvSubs The mapping from the interface types of the
147-
/// requirement into the interface types of the synthetic environment.
146+
/// \param reqToWitnessThunkSigSubs The mapping from the interface types of the
147+
/// requirement into the interface types of the witness thunk signature.
148148
///
149149
/// \param derivativeGenSig The derivative generic signature, when the
150150
/// requirement is a derivative function.
@@ -153,13 +153,13 @@ class Witness {
153153
/// need to hop to before calling the witness.
154154
Witness(ValueDecl *decl,
155155
SubstitutionMap substitutions,
156-
GenericEnvironment *syntheticEnv,
157-
SubstitutionMap reqToSyntheticEnvSubs,
156+
GenericSignature witnessThunkSig,
157+
SubstitutionMap reqToWitnessThunkSigSubs,
158158
GenericSignature derivativeGenSig,
159159
Optional<ActorIsolation> enterIsolation);
160160

161161
/// Retrieve the witness declaration reference, which includes the
162-
/// substitutions needed to use the witness from the synthetic environment
162+
/// substitutions needed to use the witness from the witness thunk signature
163163
/// (if any).
164164
ConcreteDeclRef getDeclRef() const {
165165
if (auto stored = storage.dyn_cast<StoredWitness *>())
@@ -175,26 +175,23 @@ class Witness {
175175
explicit operator bool() const { return !storage.isNull(); }
176176

177177
/// Retrieve the substitutions required to use this witness from the
178-
/// synthetic environment.
179-
///
180-
/// The substitutions are substitutions for the witness, providing interface
181-
/// types from the synthetic environment.
178+
/// witness thunk signature.
182179
SubstitutionMap getSubstitutions() const {
183180
return getDeclRef().getSubstitutions();
184181
}
185182

186-
/// Retrieve the synthetic generic environment.
187-
GenericEnvironment *getSyntheticEnvironment() const {
183+
/// Retrieve the witness thunk generic signature.
184+
GenericSignature getWitnessThunkSignature() const {
188185
if (auto *storedWitness = storage.dyn_cast<StoredWitness *>())
189-
return storedWitness->syntheticEnvironment;
186+
return storedWitness->witnessThunkSig;
190187
return nullptr;
191188
}
192189

193190
/// Retrieve the substitution map that maps the interface types of the
194-
/// requirement to the interface types of the synthetic environment.
195-
SubstitutionMap getRequirementToSyntheticSubs() const {
191+
/// requirement to the interface types of the witness thunk signature.
192+
SubstitutionMap getRequirementToWitnessThunkSubs() const {
196193
if (auto *storedWitness = storage.dyn_cast<StoredWitness *>())
197-
return storedWitness->reqToSyntheticEnvSubs;
194+
return storedWitness->reqToWitnessThunkSigSubs;
198195
return {};
199196
}
200197

lib/AST/ASTVerifier.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2716,21 +2716,6 @@ class Verifier : public ASTWalker {
27162716
abort();
27172717
}
27182718

2719-
// Check the witness substitutions.
2720-
const auto &witness = normal->getWitnessUncached(req);
2721-
2722-
if (auto *genericEnv = witness.getSyntheticEnvironment())
2723-
Generics.push_back(genericEnv->getGenericSignature());
2724-
2725-
verifyChecked(witness.getRequirementToSyntheticSubs());
2726-
verifyChecked(witness.getSubstitutions());
2727-
2728-
if (auto *genericEnv = witness.getSyntheticEnvironment()) {
2729-
assert(Generics.back().get<GenericSignature>().getPointer()
2730-
== genericEnv->getGenericSignature().getPointer());
2731-
Generics.pop_back();
2732-
}
2733-
27342719
continue;
27352720
}
27362721
}

lib/AST/ProtocolConformance.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,29 +42,29 @@ STATISTIC(NumConformanceLookupTables, "# of conformance lookup tables built");
4242
using namespace swift;
4343

4444
Witness::Witness(ValueDecl *decl, SubstitutionMap substitutions,
45-
GenericEnvironment *syntheticEnv,
46-
SubstitutionMap reqToSynthesizedEnvSubs,
45+
GenericSignature witnessThunkSig,
46+
SubstitutionMap reqToWitnessThunkSigSubs,
4747
GenericSignature derivativeGenSig,
4848
Optional<ActorIsolation> enterIsolation) {
49-
if (!syntheticEnv && substitutions.empty() &&
50-
reqToSynthesizedEnvSubs.empty() && !enterIsolation) {
49+
if (!witnessThunkSig && substitutions.empty() &&
50+
reqToWitnessThunkSigSubs.empty() && !enterIsolation) {
5151
storage = decl;
5252
return;
5353
}
5454

5555
auto &ctx = decl->getASTContext();
5656
auto declRef = ConcreteDeclRef(decl, substitutions);
5757
auto storedMem = ctx.Allocate(sizeof(StoredWitness), alignof(StoredWitness));
58-
auto stored = new (storedMem) StoredWitness{declRef, syntheticEnv,
59-
reqToSynthesizedEnvSubs,
58+
auto stored = new (storedMem) StoredWitness{declRef, witnessThunkSig,
59+
reqToWitnessThunkSigSubs,
6060
derivativeGenSig, enterIsolation};
6161

6262
storage = stored;
6363
}
6464

6565
Witness Witness::withEnterIsolation(ActorIsolation enterIsolation) const {
66-
return Witness(getDecl(), getSubstitutions(), getSyntheticEnvironment(),
67-
getRequirementToSyntheticSubs(),
66+
return Witness(getDecl(), getSubstitutions(), getWitnessThunkSignature(),
67+
getRequirementToWitnessThunkSubs(),
6868
getDerivativeGenericSignature(), enterIsolation);
6969
}
7070

@@ -919,13 +919,13 @@ RootProtocolConformance::getWitnessDeclRef(ValueDecl *requirement) const {
919919
auto *witnessDecl = witness.getDecl();
920920

921921
// If the witness is generic, you have to call getWitness() and build
922-
// your own substitutions in terms of the synthetic environment.
922+
// your own substitutions in terms of the witness thunk signature.
923923
if (auto *witnessDC = dyn_cast<DeclContext>(witnessDecl))
924924
assert(!witnessDC->isInnermostContextGeneric());
925925

926926
// If the witness is not generic, use type substitutions from the
927927
// witness's parent. Don't use witness.getSubstitutions(), which
928-
// are written in terms of the synthetic environment.
928+
// are written in terms of the witness thunk signature.
929929
auto subs =
930930
getType()->getContextSubstitutionMap(getDeclContext()->getParentModule(),
931931
witnessDecl->getDeclContext());

lib/AST/RequirementEnvironment.cpp

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ RequirementEnvironment::RequirementEnvironment(
4444
auto conformanceSig = conformanceDC->getGenericSignatureOfContext();
4545

4646
// This is a substitution function from the generic parameters of the
47-
// conforming type to the synthetic environment.
47+
// conforming type to the witness thunk environment.
4848
//
4949
// For structs, enums and protocols, this is a 1:1 mapping; for classes,
5050
// we increase the depth of each generic parameter by 1 so that we can
@@ -53,7 +53,7 @@ RequirementEnvironment::RequirementEnvironment(
5353
// This is a raw function rather than a substitution map because we need to
5454
// keep generic parameters as generic, even if the conformanceSig (the best
5555
// way to create the substitution map) equates them to concrete types.
56-
auto conformanceToSyntheticTypeFn = [&](SubstitutableType *type) {
56+
auto conformanceToWitnessThunkTypeFn = [&](SubstitutableType *type) {
5757
auto *genericParam = cast<GenericTypeParamType>(type);
5858
if (covariantSelf) {
5959
return GenericTypeParamType::get(genericParam->isTypeSequence(),
@@ -65,14 +65,14 @@ RequirementEnvironment::RequirementEnvironment(
6565
genericParam->getDepth(),
6666
genericParam->getIndex(), ctx);
6767
};
68-
auto conformanceToSyntheticConformanceFn =
68+
auto conformanceToWitnessThunkConformanceFn =
6969
MakeAbstractConformanceForGenericType();
7070

7171
auto substConcreteType = concreteType.subst(
72-
conformanceToSyntheticTypeFn, conformanceToSyntheticConformanceFn);
72+
conformanceToWitnessThunkTypeFn, conformanceToWitnessThunkConformanceFn);
7373

7474
// Calculate the depth at which the requirement's generic parameters
75-
// appear in the synthetic signature.
75+
// appear in the witness thunk signature.
7676
unsigned depth = 0;
7777
if (covariantSelf) {
7878
++depth;
@@ -88,7 +88,7 @@ RequirementEnvironment::RequirementEnvironment(
8888
auto selfType = cast<GenericTypeParamType>(
8989
proto->getSelfInterfaceType()->getCanonicalType());
9090

91-
reqToSyntheticEnvMap = SubstitutionMap::get(reqSig,
91+
reqToWitnessThunkSigMap = SubstitutionMap::get(reqSig,
9292
[selfType, substConcreteType, depth, covariantSelf, &ctx]
9393
(SubstitutableType *type) -> Type {
9494
// If the conforming type is a class, the protocol 'Self' maps to
@@ -136,15 +136,13 @@ RequirementEnvironment::RequirementEnvironment(
136136
return ProtocolConformanceRef(proto);
137137
});
138138

139-
// If the requirement itself is non-generic, the synthetic signature
139+
// If the requirement itself is non-generic, the witness thunk signature
140140
// is that of the conformance context.
141141
if (!covariantSelf &&
142142
reqSig.getGenericParams().size() == 1 &&
143143
reqSig.getRequirements().size() == 1) {
144-
syntheticSignature = conformanceDC->getGenericSignatureOfContext().getCanonicalSignature();
145-
syntheticEnvironment =
146-
syntheticSignature.getGenericEnvironment();
147-
144+
witnessThunkSig = conformanceDC->getGenericSignatureOfContext()
145+
.getCanonicalSignature();
148146
return;
149147
}
150148

@@ -164,8 +162,8 @@ RequirementEnvironment::RequirementEnvironment(
164162
// Now, add all generic parameters from the conforming type.
165163
if (conformanceSig) {
166164
for (auto param : conformanceSig.getGenericParams()) {
167-
auto substParam = Type(param).subst(conformanceToSyntheticTypeFn,
168-
conformanceToSyntheticConformanceFn);
165+
auto substParam = Type(param).subst(conformanceToWitnessThunkTypeFn,
166+
conformanceToWitnessThunkConformanceFn);
169167
genericParamTypes.push_back(substParam->castTo<GenericTypeParamType>());
170168
}
171169
}
@@ -181,8 +179,8 @@ RequirementEnvironment::RequirementEnvironment(
181179

182180
if (conformanceSig) {
183181
for (auto &rawReq : conformanceSig.getRequirements()) {
184-
if (auto req = rawReq.subst(conformanceToSyntheticTypeFn,
185-
conformanceToSyntheticConformanceFn))
182+
if (auto req = rawReq.subst(conformanceToWitnessThunkTypeFn,
183+
conformanceToWitnessThunkConformanceFn))
186184
requirements.push_back(*req);
187185
}
188186
}
@@ -207,13 +205,11 @@ RequirementEnvironment::RequirementEnvironment(
207205
// Next, add each of the requirements (mapped from the requirement's
208206
// interface types into the abstract type parameters).
209207
for (auto &rawReq : reqSig.getRequirements()) {
210-
if (auto req = rawReq.subst(reqToSyntheticEnvMap))
208+
if (auto req = rawReq.subst(reqToWitnessThunkSigMap))
211209
requirements.push_back(*req);
212210
}
213211

214-
// Produce the generic signature and environment.
215-
syntheticSignature = buildGenericSignature(ctx, GenericSignature(),
216-
std::move(genericParamTypes),
217-
std::move(requirements));
218-
syntheticEnvironment = syntheticSignature.getGenericEnvironment();
212+
witnessThunkSig = buildGenericSignature(ctx, GenericSignature(),
213+
std::move(genericParamTypes),
214+
std::move(requirements));
219215
}

lib/SILGen/SILGenType.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -723,13 +723,11 @@ SILFunction *SILGenModule::emitProtocolWitness(
723723

724724
// Mapping from the requirement's generic signature to the witness
725725
// thunk's generic signature.
726-
auto reqtSubMap = witness.getRequirementToSyntheticSubs();
726+
auto reqtSubMap = witness.getRequirementToWitnessThunkSubs();
727727

728728
// The generic environment for the witness thunk.
729-
auto *genericEnv = witness.getSyntheticEnvironment();
730-
CanGenericSignature genericSig;
731-
if (genericEnv)
732-
genericSig = genericEnv->getGenericSignature().getCanonicalSignature();
729+
auto *genericEnv = witness.getWitnessThunkSignature().getGenericEnvironment();
730+
auto genericSig = witness.getWitnessThunkSignature().getCanonicalSignature();
733731

734732
// The type of the witness thunk.
735733
auto reqtSubstTy = cast<AnyFunctionType>(

0 commit comments

Comments
 (0)