-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathSubstitutionMap.cpp
703 lines (569 loc) · 23.5 KB
/
SubstitutionMap.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
//===--- SubstitutionMap.cpp - Type substitution map ----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the SubstitutionMap class. A SubstitutionMap packages
// together a set of replacement types and protocol conformances, given by
// the generic parameters and conformance requirements of the substitution map's
// input generic signature.
//
// To substitute a type, call Type::subst() with the right SubstitutionMap.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/SubstitutionMap.h"
#include "SubstitutionMapStorage.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ConformanceLookup.h"
#include "swift/AST/Decl.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/GenericParamList.h"
#include "swift/AST/InFlightSubstitution.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
#include "swift/AST/PackConformance.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Assertions.h"
#include "swift/Basic/Defer.h"
#include "llvm/Support/Debug.h"
using namespace swift;
SubstitutionMap::Storage::Storage(
GenericSignature genericSig,
ArrayRef<Type> replacementTypes,
ArrayRef<ProtocolConformanceRef> conformances)
: genericSig(genericSig),
numConformanceRequirements(genericSig->getNumConformanceRequirements())
{
assert(replacementTypes.size() == getNumReplacementTypes());
assert(conformances.size() == numConformanceRequirements);
std::copy(replacementTypes.begin(), replacementTypes.end(),
getReplacementTypes().data());
std::copy(conformances.begin(), conformances.end(),
getConformances().data());
}
SubstitutionMap::SubstitutionMap(
GenericSignature genericSig,
ArrayRef<Type> replacementTypes,
ArrayRef<ProtocolConformanceRef> conformances)
: storage(Storage::get(genericSig, replacementTypes, conformances)) {
if (genericSig->getASTContext().LangOpts.VerifyAllSubstitutionMaps)
verify();
}
ArrayRef<ProtocolConformanceRef> SubstitutionMap::getConformances() const {
return storage ? storage->getConformances()
: ArrayRef<ProtocolConformanceRef>();
}
ArrayRef<Type> SubstitutionMap::getReplacementTypes() const {
if (empty()) return { };
return storage->getReplacementTypes();
}
ArrayRef<Type> SubstitutionMap::getInnermostReplacementTypes() const {
if (empty()) return { };
return getReplacementTypes().take_back(
getGenericSignature().getInnermostGenericParams().size());
}
GenericSignature SubstitutionMap::getGenericSignature() const {
return storage ? storage->getGenericSignature() : nullptr;
}
bool SubstitutionMap::empty() const {
return getGenericSignature().isNull();
}
bool SubstitutionMap::hasAnySubstitutableParams() const {
auto genericSig = getGenericSignature();
if (!genericSig) return false;
return !genericSig->areAllParamsConcrete();
}
RecursiveTypeProperties SubstitutionMap::getRecursiveProperties() const {
RecursiveTypeProperties properties;
for (auto replacementTy : getReplacementTypes())
properties |= replacementTy->getRecursiveProperties();
return properties;
}
bool SubstitutionMap::isCanonical() const {
if (empty()) return true;
if (!getGenericSignature()->isCanonical()) return false;
for (Type replacementTy : getReplacementTypes()) {
if (!replacementTy->isCanonical())
return false;
}
for (auto conf : getConformances()) {
if (!conf.isCanonical())
return false;
}
return true;
}
SubstitutionMap SubstitutionMap::getCanonical(bool canonicalizeSignature) const {
if (empty()) return *this;
auto sig = getGenericSignature();
if (canonicalizeSignature) sig = sig.getCanonicalSignature();
SmallVector<Type, 4> replacementTypes;
for (Type replacementType : getReplacementTypes()) {
replacementTypes.push_back(replacementType->getCanonicalType());
}
SmallVector<ProtocolConformanceRef, 4> conformances;
for (auto conf : getConformances()) {
conformances.push_back(conf.getCanonicalConformanceRef());
}
return SubstitutionMap::get(sig,
ArrayRef<Type>(replacementTypes),
ArrayRef<ProtocolConformanceRef>(conformances));
}
SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
SubstitutionMap substitutions) {
if (!genericSig)
return SubstitutionMap();
return SubstitutionMap::get(genericSig,
QuerySubstitutionMap{substitutions},
LookUpConformanceInSubstitutionMap(substitutions));
}
SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
TypeSubstitutionFn subs,
LookupConformanceFn lookupConformance) {
InFlightSubstitution IFS(subs, lookupConformance, std::nullopt);
return get(genericSig, IFS);
}
SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
ArrayRef<Type> types,
LookupConformanceFn lookupConformance) {
QueryReplacementTypeArray subs{genericSig, types};
InFlightSubstitution IFS(subs, lookupConformance, std::nullopt);
return get(genericSig, types, IFS);
}
SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
ArrayRef<Type> types,
InFlightSubstitution &IFS) {
// Form the stored conformances.
SmallVector<ProtocolConformanceRef, 4> conformances;
for (const auto &req : genericSig.getRequirements()) {
if (req.getKind() != RequirementKind::Conformance) continue;
CanType depTy = req.getFirstType()->getCanonicalType();
auto replacement = depTy.subst(IFS);
auto *proto = req.getProtocolDecl();
auto conformance = IFS.lookupConformance(depTy, replacement, proto,
/*level=*/0);
conformances.push_back(conformance);
}
return SubstitutionMap(genericSig, types, conformances);
}
SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
InFlightSubstitution &IFS) {
if (!genericSig) {
return SubstitutionMap();
}
// Form the replacement types.
SmallVector<Type, 4> replacementTypes;
replacementTypes.reserve(genericSig.getGenericParams().size());
for (auto *gp : genericSig.getGenericParams()) {
// Record the replacement.
Type replacement = IFS.substType(gp, /*level=*/0);
if (!replacement)
replacement = ErrorType::get(gp->getASTContext());
assert((replacement->hasError() ||
gp->isParameterPack() == replacement->is<PackType>()) &&
"replacement for pack parameter must be a pack type");
replacementTypes.push_back(replacement);
}
return SubstitutionMap::get(genericSig, replacementTypes, IFS);
}
Type SubstitutionMap::lookupSubstitution(GenericTypeParamType *genericParam) const {
if (empty())
return Type();
// Find the index of the replacement type based on the generic parameter we
// have.
GenericSignature genericSig = getGenericSignature();
auto genericParams = genericSig.getGenericParams();
auto replacementIndex =
GenericParamKey(genericParam).findIndexIn(genericParams);
// If this generic parameter isn't represented, we don't have a replacement
// type for it.
if (replacementIndex == genericParams.size())
return Type();
return getReplacementTypes()[replacementIndex];
}
ProtocolConformanceRef
SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
if (!type->isTypeParameter() || empty())
return ProtocolConformanceRef::forInvalid();
auto genericSig = getGenericSignature();
auto getSignatureConformance =
[&](Type type,
ProtocolDecl *proto) -> std::optional<ProtocolConformanceRef> {
unsigned index = 0;
for (auto reqt : genericSig.getRequirements()) {
if (reqt.getKind() == RequirementKind::Conformance) {
if (reqt.getFirstType()->isEqual(type) &&
reqt.getProtocolDecl() == proto)
return getConformances()[index];
++index;
}
}
return std::nullopt;
};
// Fast path -- check if the generic signature directly states the
// conformance.
if (auto directConformance = getSignatureConformance(type, proto))
return *directConformance;
// If the type doesn't conform to this protocol, the result isn't formed
// from these requirements.
if (!genericSig->requiresProtocol(type, proto)) {
Type substType = type.subst(*this);
return ProtocolConformanceRef::forMissingOrInvalid(substType, proto);
}
// If the protocol is invertible, fall back to a global lookup instead of
// evaluating a conformance path, to avoid an infinite substitution issue.
if (proto->getInvertibleProtocolKind())
return swift::lookupConformance(type.subst(*this), proto);
auto path = genericSig->getConformancePath(type, proto);
ProtocolConformanceRef conformance;
for (const auto &step : path) {
// For the first step, grab the initial conformance.
if (conformance.isInvalid()) {
if (auto initialConformance = getSignatureConformance(
step.first, step.second)) {
conformance = *initialConformance;
continue;
}
// We couldn't find the initial conformance, fail.
return ProtocolConformanceRef::forInvalid();
}
// If we've hit an abstract conformance, everything from here on out is
// abstract.
// FIXME: This may not always be true, but it holds for now.
if (conformance.isAbstract()) {
// FIXME: Rip this out once we can get a concrete conformance from
// an archetype.
return swift::lookupConformance(type.subst(*this), proto);
}
// For the second step, we're looking into the requirement signature for
// this protocol.
if (conformance.isPack()) {
auto pack = conformance.getPack();
conformance = ProtocolConformanceRef(
pack->getAssociatedConformance(step.first, step.second));
if (conformance.isInvalid())
return conformance;
continue;
}
auto concrete = conformance.getConcrete();
auto normal = concrete->getRootNormalConformance();
// If we haven't set the signature conformances yet, force the issue now.
if (!normal->hasComputedAssociatedConformances()) {
// If we're in the process of checking the type witnesses, fail
// gracefully.
//
// FIXME: This is unsound, because we may not have diagnosed anything but
// still end up with an ErrorType in the AST.
if (proto->getASTContext().evaluator.hasActiveRequest(
ResolveTypeWitnessesRequest{normal})) {
return ProtocolConformanceRef::forInvalid();
}
}
// Get the associated conformance.
conformance = concrete->getAssociatedConformance(step.first, step.second);
if (conformance.isInvalid())
return conformance;
}
return conformance;
}
SubstitutionMap SubstitutionMap::mapReplacementTypesOutOfContext() const {
return subst(MapTypeOutOfContext(),
MakeAbstractConformanceForGenericType(),
SubstFlags::PreservePackExpansionLevel |
SubstFlags::SubstitutePrimaryArchetypes);
}
SubstitutionMap SubstitutionMap::subst(SubstitutionMap subMap,
SubstOptions options) const {
InFlightSubstitutionViaSubMap IFS(subMap, options);
return subst(IFS);
}
SubstitutionMap SubstitutionMap::subst(TypeSubstitutionFn subs,
LookupConformanceFn conformances,
SubstOptions options) const {
InFlightSubstitution IFS(subs, conformances, options);
return subst(IFS);
}
SubstitutionMap SubstitutionMap::subst(InFlightSubstitution &IFS) const {
if (empty()) return SubstitutionMap();
SmallVector<Type, 4> newSubs;
for (Type type : getReplacementTypes()) {
newSubs.push_back(type.subst(IFS));
assert(type->is<PackType>() == newSubs.back()->is<PackType>() &&
"substitution changed the pack-ness of a replacement type");
}
SmallVector<ProtocolConformanceRef, 4> newConformances;
auto oldConformances = getConformances();
auto genericSig = getGenericSignature();
for (const auto &req : genericSig.getRequirements()) {
if (req.getKind() != RequirementKind::Conformance) continue;
auto conformance = oldConformances[0];
// Fast path for concrete case -- we don't need to compute substType
// at all.
if (conformance.isConcrete() &&
!IFS.shouldSubstituteOpaqueArchetypes()) {
newConformances.push_back(
ProtocolConformanceRef(conformance.getConcrete()->subst(IFS)));
} else {
auto origType = req.getFirstType();
auto substType = origType.subst(*this, IFS.getOptions());
newConformances.push_back(conformance.subst(substType, IFS));
}
oldConformances = oldConformances.slice(1);
}
assert(oldConformances.empty());
return SubstitutionMap(genericSig, newSubs, newConformances);
}
SubstitutionMap
SubstitutionMap::getProtocolSubstitutions(ProtocolDecl *protocol,
Type selfType,
ProtocolConformanceRef conformance) {
return get(protocol->getGenericSignature(), llvm::ArrayRef<Type>(selfType),
llvm::ArrayRef<ProtocolConformanceRef>(conformance));
}
SubstitutionMap
SubstitutionMap::getOverrideSubstitutions(
const ValueDecl *baseDecl,
const ValueDecl *derivedDecl) {
// For overrides within a protocol hierarchy, substitute the Self type.
if (auto baseProto = baseDecl->getDeclContext()->getSelfProtocolDecl()) {
auto baseSig = baseDecl->getInnermostDeclContext()
->getGenericSignatureOfContext();
return baseSig->getIdentitySubstitutionMap();
}
auto *baseClass = baseDecl->getDeclContext()->getSelfClassDecl();
auto *derivedClass = derivedDecl->getDeclContext()->getSelfClassDecl();
auto baseSig = baseDecl->getInnermostDeclContext()
->getGenericSignatureOfContext();
// If more kinds of overridable decls with generic parameter lists appear,
// add them here.
GenericParamList *derivedParams = nullptr;
if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(derivedDecl))
derivedParams = funcDecl->getGenericParams();
else if (auto *subscriptDecl = dyn_cast<SubscriptDecl>(derivedDecl))
derivedParams = subscriptDecl->getGenericParams();
return getOverrideSubstitutions(baseClass, derivedClass, baseSig, derivedParams);
}
OverrideSubsInfo::OverrideSubsInfo(const NominalTypeDecl *baseNominal,
const NominalTypeDecl *derivedNominal,
GenericSignature baseSig,
const GenericParamList *derivedParams)
: Ctx(baseSig->getASTContext()),
BaseDepth(0),
OrigDepth(0),
DerivedParams(derivedParams) {
if (auto baseNominalSig = baseNominal->getGenericSignature()) {
BaseDepth = baseNominalSig.getNextDepth();
auto *genericEnv = derivedNominal->getGenericEnvironment();
auto derivedNominalTy = derivedNominal->getDeclaredInterfaceType();
// FIXME: Map in and out of context to get more accurate
// conformance information. If the base generic signature
// is <T: P> and the derived generic signature is <T: C>
// where C is a class that conforms to P, then we want the
// substitution map to store the concrete conformance C: P
// and not the abstract conformance T: P.
if (genericEnv) {
derivedNominalTy = genericEnv->mapTypeIntoContext(
derivedNominalTy);
}
BaseSubMap = derivedNominalTy->getContextSubstitutionMap(
baseNominal, genericEnv);
BaseSubMap = BaseSubMap.mapReplacementTypesOutOfContext();
}
if (auto derivedNominalSig = derivedNominal->getGenericSignature())
OrigDepth = derivedNominalSig.getNextDepth();
}
Type QueryOverrideSubs::operator()(SubstitutableType *type) const {
if (auto gp = type->getAs<GenericTypeParamType>()) {
if (gp->getDepth() >= info.BaseDepth) {
assert(gp->getDepth() == info.BaseDepth);
if (info.DerivedParams != nullptr) {
return info.DerivedParams->getParams()[gp->getIndex()]
->getDeclaredInterfaceType();
}
return GenericTypeParamType::get(
gp->getParamKind(),
gp->getDepth() + info.OrigDepth - info.BaseDepth,
gp->getIndex(), gp->getValueType(), info.Ctx);
}
}
return Type(type).subst(info.BaseSubMap);
}
ProtocolConformanceRef
LookUpConformanceInOverrideSubs::operator()(CanType type,
Type substType,
ProtocolDecl *proto) const {
if (type->getRootGenericParam()->getDepth() >= info.BaseDepth)
return ProtocolConformanceRef::forAbstract(substType, proto);
if (auto conformance = info.BaseSubMap.lookupConformance(type, proto))
return conformance;
return lookupConformance(substType, proto);
}
SubstitutionMap
SubstitutionMap::getOverrideSubstitutions(const NominalTypeDecl *baseNominal,
const NominalTypeDecl *derivedNominal,
GenericSignature baseSig,
const GenericParamList *derivedParams) {
if (baseSig.isNull())
return SubstitutionMap();
OverrideSubsInfo info(baseNominal, derivedNominal, baseSig, derivedParams);
return get(baseSig,
QueryOverrideSubs(info),
LookUpConformanceInOverrideSubs(info));
}
void SubstitutionMap::verify(bool allowInvalid) const {
if (empty())
return;
auto genericSig = getGenericSignature();
auto &ctx = genericSig->getASTContext();
if (ctx.isRecursivelyConstructingRequirementMachine(
genericSig.getCanonicalSignature()))
return;
unsigned conformanceIndex = 0;
for (const auto &req : genericSig.getRequirements()) {
if (req.getKind() != RequirementKind::Conformance)
continue;
SWIFT_DEFER { ++conformanceIndex; };
auto conformance = getConformances()[conformanceIndex];
auto substType = req.getFirstType().subst(*this);
// Unwrap various strange things.
substType = substType->getReferenceStorageReferent();
if (auto *selfType = substType->getAs<DynamicSelfType>())
substType = selfType->getSelfType();
// Don't bother validating these cases.
if (allowInvalid && substType->hasUnboundGenericType())
return;
if (conformance.isInvalid()) {
if (!allowInvalid) {
llvm::errs() << "Unexpected invalid conformance in substitution map:\n";
dump(llvm::dbgs());
llvm::errs() << "\n";
abort();
}
continue;
}
if (conformance.isAbstract()) {
if (!substType->isTypeParameter() &&
!substType->is<PackElementType>() &&
!substType->is<ArchetypeType>() &&
!substType->isTypeVariableOrMember() &&
!substType->is<UnresolvedType>() &&
!substType->is<PlaceholderType>() &&
!substType->is<ErrorType>()) {
llvm::errs() << "Unexpected abstract conformance in substitution map:\n";
dump(llvm::errs());
llvm::errs() << "\n";
abort();
}
continue;
}
if (conformance.isPack()) {
// FIXME: Implement some kind of check here.
continue;
}
auto *concrete = conformance.getConcrete();
if (substType->isExistentialType()) {
if (req.getProtocolDecl()->isSpecificProtocol(KnownProtocolKind::Sendable) &&
isa<BuiltinProtocolConformance>(concrete)) {
continue;
}
if (!isa<SelfProtocolConformance>(concrete)) {
// A superclass-constrained self-conforming existential might conform
// concretely.
if (substType->getSuperclass())
continue;
llvm::errs() << "Expected to find a self conformance:\n";
substType->dump(llvm::errs());
llvm::errs() << "Substitution map:\n";
dump(llvm::errs());
llvm::errs() << "\n";
abort();
}
continue;
}
if (substType->isTypeParameter())
continue;
if (!concrete->getType()->isEqual(substType)) {
llvm::errs() << "Conformance with wrong conforming type:\n";
concrete->getType()->dump(llvm::errs());
llvm::errs() << "Should be:\n";
substType->dump(llvm::errs());
llvm::errs() << "Substitution map:\n";
dump(llvm::errs());
llvm::errs() << "\n";
abort();
}
}
}
void SubstitutionMap::profile(llvm::FoldingSetNodeID &id) const {
id.AddPointer(storage);
}
bool SubstitutionMap::isIdentity() const {
if (empty())
return true;
for (auto conf : getConformances()) {
if (conf.isAbstract())
continue;
if (conf.isPack()) {
auto patternConfs = conf.getPack()->getPatternConformances();
if (patternConfs.size() == 1 && patternConfs[0].isAbstract())
continue;
}
return false;
}
GenericSignature sig = getGenericSignature();
bool hasNonIdentityReplacement = false;
auto replacements = getReplacementTypes();
sig->forEachParam([&](GenericTypeParamType *paramTy, bool isCanonical) {
if (isCanonical) {
Type wrappedParamTy = paramTy;
if (paramTy->isParameterPack())
wrappedParamTy = PackType::getSingletonPackExpansion(paramTy);
if (!wrappedParamTy->isEqual(replacements[0]))
hasNonIdentityReplacement = true;
}
replacements = replacements.slice(1);
});
assert(replacements.empty());
return !hasNonIdentityReplacement;
}
SubstitutionMap SubstitutionMap::mapIntoTypeExpansionContext(
TypeExpansionContext context) const {
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
context.getContext(), context.getResilienceExpansion(),
context.isWholeModuleContext());
return this->subst(replacer, replacer,
SubstFlags::SubstituteOpaqueArchetypes |
SubstFlags::PreservePackExpansionLevel);
}
bool OuterSubstitutions::isUnsubstitutedTypeParameter(Type type) const {
if (!type->isTypeParameter())
return false;
if (auto depMemTy = type->getAs<DependentMemberType>())
return isUnsubstitutedTypeParameter(depMemTy->getBase());
if (auto genericParam = type->getAs<GenericTypeParamType>())
return genericParam->getDepth() >= depth;
return false;
}
Type OuterSubstitutions::operator()(SubstitutableType *type) const {
if (isUnsubstitutedTypeParameter(type))
return Type(type);
return QuerySubstitutionMap{subs}(type);
}
ProtocolConformanceRef OuterSubstitutions::operator()(
CanType dependentType,
Type conformingReplacementType,
ProtocolDecl *conformedProtocol) const {
if (isUnsubstitutedTypeParameter(dependentType))
return ProtocolConformanceRef::forAbstract(
conformingReplacementType, conformedProtocol);
return LookUpConformanceInSubstitutionMap(subs)(
dependentType, conformingReplacementType, conformedProtocol);
}