Skip to content

Commit ddd2f1e

Browse files
authored
Merge pull request #2995 from slavapestov/function-interface-type-fixes
2 parents eab2747 + ac6e335 commit ddd2f1e

File tree

51 files changed

+277
-320
lines changed

Some content is hidden

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

51 files changed

+277
-320
lines changed

include/swift/AST/ASTContext.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ class ASTContext {
755755

756756
/// \brief Retrieve the substitutions for a bound generic type, if known.
757757
Optional<ArrayRef<Substitution>>
758-
getSubstitutions(BoundGenericType *Bound, DeclContext *gpContext) const;
758+
getSubstitutions(TypeBase *type, DeclContext *gpContext) const;
759759

760760
/// Record a conformance loader and its context data for the given
761761
/// declaration.
@@ -856,10 +856,10 @@ class ASTContext {
856856
Optional<StringRef> getBriefComment(const Decl *D);
857857
void setBriefComment(const Decl *D, StringRef Comment);
858858

859-
friend class BoundGenericType;
859+
friend class TypeBase;
860860

861861
/// \brief Set the substitutions for the given bound generic type.
862-
void setSubstitutions(BoundGenericType *Bound,
862+
void setSubstitutions(TypeBase *type,
863863
DeclContext *gpContext,
864864
ArrayRef<Substitution> Subs) const;
865865

include/swift/AST/DeclContext.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,10 +367,6 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
367367

368368
/// Determine whether the innermost context is generic.
369369
bool isInnermostContextGeneric() const;
370-
371-
/// Determine whether the innermost context is either a generic type context,
372-
/// or a concrete type nested inside a generic type context.
373-
bool isGenericTypeContext() const;
374370

375371
/// Determine the maximum depth of the current generic type context's generic
376372
/// parameters. If the current context is not a generic type context, returns

include/swift/AST/Types.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,26 +1541,6 @@ class BoundGenericType : public TypeBase, public llvm::FoldingSetNode {
15411541
/// Retrieve the set of generic arguments provided at this level.
15421542
ArrayRef<Type> getGenericArgs() const { return GenericArgs; }
15431543

1544-
/// \brief Retrieve the set of substitutions used to produce this bound
1545-
/// generic type from the underlying generic type.
1546-
///
1547-
/// \param module The module in which we should compute the substitutions.
1548-
/// FIXME: We currently don't account for this properly, so it can be null.
1549-
///
1550-
/// \param resolver The resolver that handles lazy type checking, where
1551-
/// required. This can be null for a fully-type-checked AST.
1552-
///
1553-
/// \param gpContext The context from which the generic parameters will be
1554-
/// extracted, which will be either the nominal type declaration or an
1555-
/// extension thereof. If null, will be set to the nominal type declaration.
1556-
ArrayRef<Substitution> getSubstitutions(ModuleDecl *module,
1557-
LazyResolver *resolver,
1558-
DeclContext *gpContext = nullptr);
1559-
1560-
/// Retrieves the generic parameter context to use with substitutions for
1561-
/// this bound generic type, using the given context if possible.
1562-
DeclContext *getGenericParamContext(DeclContext *gpContext) const;
1563-
15641544
void Profile(llvm::FoldingSetNodeID &ID) {
15651545
RecursiveTypeProperties properties;
15661546
Profile(ID, TheDecl, Parent, GenericArgs, properties);

lib/AST/ASTContext.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ struct ASTContext::Implementation {
277277
llvm::FoldingSet<UnboundGenericType> UnboundGenericTypes;
278278
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
279279

280-
llvm::DenseMap<std::pair<BoundGenericType *, DeclContext *>,
280+
llvm::DenseMap<std::pair<TypeBase *, DeclContext *>,
281281
ArrayRef<Substitution>>
282282
BoundGenericSubstitutions;
283283

@@ -1130,35 +1130,36 @@ ASTContext::createTrivialSubstitutions(BoundGenericType *BGT,
11301130
}
11311131

11321132
Optional<ArrayRef<Substitution>>
1133-
ASTContext::getSubstitutions(BoundGenericType* bound,
1133+
ASTContext::getSubstitutions(TypeBase *type,
11341134
DeclContext *gpContext) const {
11351135
assert(gpContext && "Missing generic parameter context");
1136-
auto arena = getArena(bound->getRecursiveProperties());
1137-
assert(bound->isCanonical() && "Requesting non-canonical substitutions");
1136+
auto arena = getArena(type->getRecursiveProperties());
1137+
assert(type->isCanonical() && "Requesting non-canonical substitutions");
11381138
auto &boundGenericSubstitutions
11391139
= Impl.getArena(arena).BoundGenericSubstitutions;
1140-
auto known = boundGenericSubstitutions.find({bound, gpContext});
1140+
auto known = boundGenericSubstitutions.find({type, gpContext});
11411141
if (known != boundGenericSubstitutions.end())
11421142
return known->second;
11431143

11441144
// We can trivially create substitutions for Array and Optional.
1145-
if (bound->getDecl() == getArrayDecl() ||
1146-
bound->getDecl() == getOptionalDecl())
1147-
return createTrivialSubstitutions(bound, gpContext);
1145+
if (auto bound = dyn_cast<BoundGenericType>(type))
1146+
if (bound->getDecl() == getArrayDecl() ||
1147+
bound->getDecl() == getOptionalDecl())
1148+
return createTrivialSubstitutions(bound, gpContext);
11481149

11491150
return None;
11501151
}
11511152

1152-
void ASTContext::setSubstitutions(BoundGenericType* Bound,
1153+
void ASTContext::setSubstitutions(TypeBase* type,
11531154
DeclContext *gpContext,
11541155
ArrayRef<Substitution> Subs) const {
1155-
auto arena = getArena(Bound->getRecursiveProperties());
1156+
auto arena = getArena(type->getRecursiveProperties());
11561157
auto &boundGenericSubstitutions
11571158
= Impl.getArena(arena).BoundGenericSubstitutions;
1158-
assert(Bound->isCanonical() && "Requesting non-canonical substitutions");
1159-
assert(boundGenericSubstitutions.count({Bound, gpContext}) == 0 &&
1159+
assert(type->isCanonical() && "Requesting non-canonical substitutions");
1160+
assert(boundGenericSubstitutions.count({type, gpContext}) == 0 &&
11601161
"Already have substitutions?");
1161-
boundGenericSubstitutions[{Bound, gpContext}] = Subs;
1162+
boundGenericSubstitutions[{type, gpContext}] = Subs;
11621163
}
11631164

11641165
Type ASTContext::getTypeVariableMemberType(TypeVariableType *baseTypeVar,

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4472,7 +4472,7 @@ bool EnumElementDecl::computeType() {
44724472
if (getArgumentType())
44734473
resultTy = FunctionType::get(getArgumentType(), resultTy);
44744474

4475-
if (ED->isGenericTypeContext())
4475+
if (ED->isGenericContext())
44764476
resultTy = PolymorphicFunctionType::get(argTy, resultTy,
44774477
ED->getGenericParamsOfContext());
44784478
else

lib/AST/DeclContext.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -431,17 +431,6 @@ bool DeclContext::isGenericContext() const {
431431
llvm_unreachable("illegal declcontext hierarchy");
432432
}
433433

434-
/// Determine whether the given context nested inside a generic type context
435-
/// with no local contexts in between.
436-
bool DeclContext::isGenericTypeContext() const {
437-
for (const auto *dc = this; dc->isTypeContext(); dc = dc->getParent()) {
438-
if (dc->isInnermostContextGeneric())
439-
return true;
440-
}
441-
442-
return false;
443-
}
444-
445434
/// Determine the maximum depth of the current generic type context's generic
446435
/// parameters. If the current context is not a generic type context, returns
447436
/// the maximum depth of any generic parameter in this context.

lib/AST/Module.cpp

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -662,41 +662,40 @@ void Module::getDisplayDecls(SmallVectorImpl<Decl*> &Results) const {
662662
FORWARD(getDisplayDecls, (Results));
663663
}
664664

665-
DeclContext *BoundGenericType::getGenericParamContext(
666-
DeclContext *gpContext) const {
667-
// If no context was provided, use the declaration itself.
668-
if (!gpContext)
669-
return getDecl();
670-
671-
assert(gpContext->getAsNominalTypeOrNominalTypeExtensionContext() == getDecl() &&
672-
"not a valid context");
673-
return gpContext;
674-
}
675-
676-
ArrayRef<Substitution> BoundGenericType::getSubstitutions(
677-
Module *module,
678-
LazyResolver *resolver,
679-
DeclContext *gpContext) {
665+
ArrayRef<Substitution>
666+
TypeBase::gatherAllSubstitutions(Module *module,
667+
LazyResolver *resolver,
668+
DeclContext *gpContext) {
680669
// FIXME: If there is no module, infer one. This is a hack for callers that
681670
// don't have access to the module. It will have to go away once we're
682671
// properly differentiating bound generic types based on the protocol
683672
// conformances visible from a given module.
684673
if (!module) {
685-
module = getDecl()->getParentModule();
674+
module = getAnyNominal()->getParentModule();
686675
}
687676

688677
// Check the context, introducing the default if needed.
689-
gpContext = getGenericParamContext(gpContext);
678+
if (!gpContext)
679+
gpContext = getAnyNominal();
680+
681+
assert(gpContext->getAsNominalTypeOrNominalTypeExtensionContext()
682+
== getAnyNominal() && "not a valid context");
683+
684+
auto *genericParams = gpContext->getGenericParamsOfContext();
685+
if (!genericParams)
686+
return { };
690687

691688
// If we already have a cached copy of the substitutions, return them.
692-
auto *canon = getCanonicalType()->castTo<BoundGenericType>();
689+
auto *canon = getCanonicalType().getPointer();
693690
const ASTContext &ctx = canon->getASTContext();
694691
if (auto known = ctx.getSubstitutions(canon, gpContext))
695692
return *known;
696693

697694
// Compute the set of substitutions.
698695
TypeSubstitutionMap substitutions;
699696

697+
// The type itself contains substitutions up to the innermost
698+
// non-type context.
700699
CanType parent(canon);
701700
auto *parentDC = gpContext;
702701
while (parent) {
@@ -727,9 +726,14 @@ ArrayRef<Substitution> BoundGenericType::getSubstitutions(
727726
llvm_unreachable("Not a nominal or bound generic type");
728727
}
729728

730-
// Collect all of the archetypes.
731-
auto *genericParams = gpContext->getGenericParamsOfContext();
729+
// Add forwarding substitutions from the outer context if we have
730+
// a type nested inside a generic function.
731+
if (auto *outerGenericParams = parentDC->getGenericParamsOfContext()) {
732+
for (auto archetype : outerGenericParams->getAllNestedArchetypes())
733+
substitutions[archetype] = archetype;
734+
}
732735

736+
// Collect all of the archetypes.
733737
SmallVector<ArchetypeType *, 2> allArchetypesList;
734738
ArrayRef<ArchetypeType *> allArchetypes = genericParams->getAllArchetypes();
735739
if (genericParams->getOuterParameters()) {

lib/AST/Type.cpp

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -329,32 +329,6 @@ ArrayRef<Type> TypeBase::getAllGenericArgs(SmallVectorImpl<Type> &scratch) {
329329
return scratch;
330330
}
331331

332-
ArrayRef<Substitution>
333-
TypeBase::gatherAllSubstitutions(Module *module,
334-
LazyResolver *resolver,
335-
DeclContext *gpContext) {
336-
Type type(this);
337-
while (type) {
338-
// Skip to the parent of a nominal type.
339-
if (auto nominal = type->getAs<NominalType>()) {
340-
type = nominal->getParent();
341-
if (gpContext)
342-
gpContext = gpContext->getParent();
343-
continue;
344-
}
345-
346-
// Return the substitutions in a bound generic type.
347-
// This walks any further parent types.
348-
if (auto boundGeneric = type->getAs<BoundGenericType>())
349-
return boundGeneric->getSubstitutions(module, resolver, gpContext);
350-
351-
llvm_unreachable("Not a nominal or bound generic type");
352-
}
353-
354-
// Not a generic type.
355-
return { };
356-
}
357-
358332
bool TypeBase::isUnspecializedGeneric() {
359333
CanType CT = getCanonicalType();
360334
if (CT.getPointer() != this)
@@ -1814,11 +1788,10 @@ bool TypeBase::isBindableTo(Type b, LazyResolver *resolver) {
18141788
if (bgt->getDecl()->isInvalid())
18151789
return false;
18161790

1817-
auto origSubs = bgt->getSubstitutions(bgt->getDecl()->getParentModule(),
1818-
Resolver);
1819-
auto substSubs = substBGT->getSubstitutions(
1820-
bgt->getDecl()->getParentModule(),
1821-
Resolver);
1791+
auto origSubs = bgt->gatherAllSubstitutions(
1792+
bgt->getDecl()->getParentModule(), Resolver);
1793+
auto substSubs = substBGT->gatherAllSubstitutions(
1794+
bgt->getDecl()->getParentModule(), Resolver);
18221795
assert(origSubs.size() == substSubs.size());
18231796
for (unsigned subi : indices(origSubs)) {
18241797
if (!visit(origSubs[subi].getReplacement()->getCanonicalType(),

lib/IDE/ReconstructType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ static TypeBase *GetTemplateArgument(TypeBase *type, size_t arg_idx) {
7777
if (!bound_generic_type)
7878
break;
7979
const ArrayRef<Substitution> &substitutions =
80-
bound_generic_type->getSubstitutions(nullptr, nullptr);
80+
bound_generic_type->gatherAllSubstitutions(nullptr, nullptr);
8181
if (arg_idx >= substitutions.size())
8282
break;
8383
const Substitution &substitution = substitutions[arg_idx];

lib/IRGen/Fulfillment.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,10 @@ bool FulfillmentMap::searchBoundGenericTypeMetadata(IRGenModule &IGM,
245245
bool hadFulfillment = false;
246246

247247
GenericTypeRequirements requirements(IGM, type->getDecl());
248-
requirements.enumerateFulfillments(IGM,
249-
type->getSubstitutions(IGM.getSwiftModule(), nullptr),
250-
[&](unsigned reqtIndex, CanType arg,
251-
Optional<ProtocolConformanceRef> conf) {
248+
requirements.enumerateFulfillments(
249+
IGM, type->gatherAllSubstitutions(IGM.getSwiftModule(), nullptr),
250+
[&](unsigned reqtIndex, CanType arg,
251+
Optional<ProtocolConformanceRef> conf) {
252252
// Skip uninteresting type arguments.
253253
if (!keys.hasInterestingType(arg))
254254
return;

0 commit comments

Comments
 (0)