Skip to content

Commit 97042d2

Browse files
authored
Merge pull request #7683 from slavapestov/sema-generic-subscripts
Preliminary Sema support for generic subscripts
2 parents 388733d + 7133d92 commit 97042d2

File tree

13 files changed

+481
-241
lines changed

13 files changed

+481
-241
lines changed

lib/AST/ASTMangler.cpp

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,8 +1458,7 @@ void ASTMangler::appendInitializerEntity(const VarDecl *var) {
14581458
/// Self type out of its mangling.
14591459
static bool isMethodDecl(const Decl *decl) {
14601460
return isa<AbstractFunctionDecl>(decl)
1461-
&& (isa<NominalTypeDecl>(decl->getDeclContext())
1462-
|| isa<ExtensionDecl>(decl->getDeclContext()));
1461+
&& decl->getDeclContext()->isTypeContext();
14631462
}
14641463

14651464
static bool genericParamIsBelowDepth(Type type, unsigned methodDepth) {
@@ -1501,28 +1500,32 @@ CanType ASTMangler::getDeclTypeForMangling(
15011500
requirements = {};
15021501
}
15031502

1504-
// Shed the 'self' type and generic requirements from method manglings.
1505-
if (isMethodDecl(decl) && type && !type->hasError()) {
1506-
// Drop the Self argument clause from the type.
1507-
type = cast<AnyFunctionType>(type).getResult();
1508-
1509-
// Drop generic parameters and requirements from the method's context.
1510-
if (auto parentGenericSig =
1511-
decl->getDeclContext()->getGenericSignatureOfContext()) {
1512-
// The method's depth starts below the depth of the context.
1513-
if (!parentGenericSig->getGenericParams().empty())
1514-
initialParamDepth =
1515-
parentGenericSig->getGenericParams().back()->getDepth()+1;
1516-
1517-
while (!genericParams.empty()) {
1518-
if (genericParams.front()->getDepth() >= initialParamDepth)
1519-
break;
1520-
genericParams = genericParams.slice(1);
1521-
}
1503+
if (!type->hasError()) {
1504+
// Shed the 'self' type and generic requirements from method manglings.
1505+
if (isMethodDecl(decl)) {
1506+
// Drop the Self argument clause from the type.
1507+
type = cast<AnyFunctionType>(type).getResult();
1508+
}
15221509

1523-
requirementsBuf.clear();
1524-
for (auto &reqt : sig->getRequirements()) {
1525-
switch (reqt.getKind()) {
1510+
if (isMethodDecl(decl) || isa<SubscriptDecl>(decl)) {
1511+
// Drop generic parameters and requirements from the method's context.
1512+
auto parentGenericSig =
1513+
decl->getDeclContext()->getGenericSignatureOfContext();
1514+
if (parentGenericSig && sig) {
1515+
// The method's depth starts below the depth of the context.
1516+
if (!parentGenericSig->getGenericParams().empty())
1517+
initialParamDepth =
1518+
parentGenericSig->getGenericParams().back()->getDepth()+1;
1519+
1520+
while (!genericParams.empty()) {
1521+
if (genericParams.front()->getDepth() >= initialParamDepth)
1522+
break;
1523+
genericParams = genericParams.slice(1);
1524+
}
1525+
1526+
requirementsBuf.clear();
1527+
for (auto &reqt : sig->getRequirements()) {
1528+
switch (reqt.getKind()) {
15261529
case RequirementKind::Conformance:
15271530
case RequirementKind::Layout:
15281531
case RequirementKind::Superclass:
@@ -1538,12 +1541,13 @@ CanType ASTMangler::getDeclTypeForMangling(
15381541
!genericParamIsBelowDepth(reqt.getSecondType(),initialParamDepth))
15391542
continue;
15401543
break;
1541-
}
1544+
}
15421545

1543-
// If we fell through the switch, mangle the requirement.
1544-
requirementsBuf.push_back(reqt);
1546+
// If we fell through the switch, mangle the requirement.
1547+
requirementsBuf.push_back(reqt);
1548+
}
1549+
requirements = requirementsBuf;
15451550
}
1546-
requirements = requirementsBuf;
15471551
}
15481552
}
15491553
return type->getCanonicalType();

lib/AST/Mangle.cpp

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,7 @@ void Mangler::mangleDeclTypeForDebugger(const ValueDecl *decl) {
466466
/// Self type out of its mangling.
467467
static bool isMethodDecl(const Decl *decl) {
468468
return isa<AbstractFunctionDecl>(decl)
469-
&& (isa<NominalTypeDecl>(decl->getDeclContext())
470-
|| isa<ExtensionDecl>(decl->getDeclContext()));
469+
&& decl->getDeclContext()->isTypeContext();
471470
}
472471

473472
static bool genericParamIsBelowDepth(Type type, unsigned methodDepth) {
@@ -510,27 +509,31 @@ CanType Mangler::getDeclTypeForMangling(
510509
}
511510

512511
// Shed the 'self' type and generic requirements from method manglings.
513-
if (isMethodDecl(decl) && type && !type->hasError()) {
514-
// Drop the Self argument clause from the type.
515-
type = cast<AnyFunctionType>(type).getResult();
516-
517-
// Drop generic parameters and requirements from the method's context.
518-
if (auto parentGenericSig =
519-
decl->getDeclContext()->getGenericSignatureOfContext()) {
520-
// The method's depth starts below the depth of the context.
521-
if (!parentGenericSig->getGenericParams().empty())
522-
initialParamDepth =
523-
parentGenericSig->getGenericParams().back()->getDepth()+1;
524-
525-
while (!genericParams.empty()) {
526-
if (genericParams.front()->getDepth() >= initialParamDepth)
527-
break;
528-
genericParams = genericParams.slice(1);
529-
}
512+
if (!type->hasError()) {
513+
if (isMethodDecl(decl)) {
514+
// Drop the Self argument clause from the type.
515+
type = cast<AnyFunctionType>(type).getResult();
516+
}
530517

531-
requirementsBuf.clear();
532-
for (auto &reqt : sig->getRequirements()) {
533-
switch (reqt.getKind()) {
518+
if (isMethodDecl(decl) || isa<SubscriptDecl>(decl)) {
519+
// Drop generic parameters and requirements from the method's context.
520+
auto parentGenericSig =
521+
decl->getDeclContext()->getGenericSignatureOfContext();
522+
if (parentGenericSig && sig) {
523+
// The method's depth starts below the depth of the context.
524+
if (!parentGenericSig->getGenericParams().empty())
525+
initialParamDepth =
526+
parentGenericSig->getGenericParams().back()->getDepth()+1;
527+
528+
while (!genericParams.empty()) {
529+
if (genericParams.front()->getDepth() >= initialParamDepth)
530+
break;
531+
genericParams = genericParams.slice(1);
532+
}
533+
534+
requirementsBuf.clear();
535+
for (auto &reqt : sig->getRequirements()) {
536+
switch (reqt.getKind()) {
534537
case RequirementKind::Conformance:
535538
case RequirementKind::Layout:
536539
case RequirementKind::Superclass:
@@ -546,12 +549,13 @@ CanType Mangler::getDeclTypeForMangling(
546549
!genericParamIsBelowDepth(reqt.getSecondType(),initialParamDepth))
547550
continue;
548551
break;
549-
}
552+
}
550553

551-
// If we fell through the switch, mangle the requirement.
552-
requirementsBuf.push_back(reqt);
554+
// If we fell through the switch, mangle the requirement.
555+
requirementsBuf.push_back(reqt);
556+
}
557+
requirements = requirementsBuf;
553558
}
554-
requirements = requirementsBuf;
555559
}
556560
}
557561

lib/AST/NameLookup.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,8 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
711711

712712
// Look in the generic parameters after checking our local declaration.
713713
GenericParams = AFD->getGenericParams();
714+
} else if (auto *SD = dyn_cast<SubscriptDecl>(DC)) {
715+
GenericParams = SD->getGenericParams();
714716
} else if (auto *ACE = dyn_cast<AbstractClosureExpr>(DC)) {
715717
// Look for local variables; normally, the parser resolves these
716718
// for us, but it can't do the right thing inside local types.
@@ -847,6 +849,8 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
847849
dcGenericParams = nominal->getGenericParams();
848850
else if (auto ext = dyn_cast<ExtensionDecl>(DC))
849851
dcGenericParams = ext->getGenericParams();
852+
else if (auto subscript = dyn_cast<SubscriptDecl>(DC))
853+
dcGenericParams = subscript->getGenericParams();
850854

851855
while (dcGenericParams) {
852856
namelookup::FindLocalVal localVal(SM, Loc, Consumer);

lib/ClangImporter/ImportDecl.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5998,7 +5998,12 @@ SwiftDeclConverter::importSubscript(Decl *decl,
59985998
SourceLoc());
59995999
auto indicesType = bodyParams->getType(C);
60006000

6001-
auto fnType = FunctionType::get(indicesType, elementTy);
6001+
AnyFunctionType *fnType;
6002+
if (auto *sig = dc->getGenericSignatureOfContext())
6003+
fnType = GenericFunctionType::get(sig, indicesType, elementTy,
6004+
AnyFunctionType::ExtInfo());
6005+
else
6006+
fnType = FunctionType::get(indicesType, elementTy);
60026007
subscript->setInterfaceType(fnType);
60036008

60046009
addObjCAttribute(subscript, None);

lib/SILGen/SILGenMaterializeForSet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ struct MaterializeForSetEmitter {
154154
CanType witnessIfaceType =
155155
WitnessStorage->getInterfaceType()->getCanonicalType();
156156
if (isa<SubscriptDecl>(WitnessStorage))
157-
witnessIfaceType = cast<FunctionType>(witnessIfaceType).getResult();
157+
witnessIfaceType = cast<AnyFunctionType>(witnessIfaceType).getResult();
158158
SubstStorageType = getSubstWitnessInterfaceType(
159159
witnessIfaceType.getReferenceStorageReferent());
160160

lib/Sema/CSRanking.cpp

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -297,10 +297,16 @@ static Type addCurriedSelfType(ASTContext &ctx, Type type, DeclContext *dc) {
297297
if (!dc->isTypeContext())
298298
return type;
299299

300-
auto nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
301-
auto selfTy = nominal->getInterfaceType()->castTo<MetatypeType>()
302-
->getInstanceType();
303-
if (auto sig = nominal->getGenericSignatureOfContext())
300+
GenericSignature *sig = dc->getGenericSignatureOfContext();
301+
if (auto *genericFn = type->getAs<GenericFunctionType>()) {
302+
sig = genericFn->getGenericSignature();
303+
type = FunctionType::get(genericFn->getInput(),
304+
genericFn->getResult(),
305+
genericFn->getExtInfo());
306+
}
307+
308+
auto selfTy = dc->getDeclaredInterfaceType();
309+
if (sig)
304310
return GenericFunctionType::get(sig, selfTy, type,
305311
AnyFunctionType::ExtInfo());
306312
return FunctionType::get(selfTy, type);
@@ -315,31 +321,38 @@ static bool isDeclMoreConstrainedThan(ValueDecl *decl1, ValueDecl *decl2) {
315321

316322
if (decl1->getKind() != decl2->getKind() || isa<TypeDecl>(decl1))
317323
return false;
318-
324+
325+
GenericParamList *gp1 = nullptr, *gp2 = nullptr;
326+
319327
auto func1 = dyn_cast<FuncDecl>(decl1);
320328
auto func2 = dyn_cast<FuncDecl>(decl2);
321-
322329
if (func1 && func2) {
323-
324-
auto gp1 = func1->getGenericParams();
325-
auto gp2 = func2->getGenericParams();
326-
327-
if (gp1 && gp2) {
328-
auto params1 = gp1->getParams();
329-
auto params2 = gp2->getParams();
330+
gp1 = func1->getGenericParams();
331+
gp2 = func2->getGenericParams();
332+
}
333+
334+
auto subscript1 = dyn_cast<SubscriptDecl>(decl1);
335+
auto subscript2 = dyn_cast<SubscriptDecl>(decl2);
336+
if (subscript1 && subscript2) {
337+
gp1 = subscript1->getGenericParams();
338+
gp2 = subscript2->getGenericParams();
339+
}
340+
341+
if (gp1 && gp2) {
342+
auto params1 = gp1->getParams();
343+
auto params2 = gp2->getParams();
330344

331-
if (params1.size() == params2.size()) {
332-
for (size_t i = 0; i < params1.size(); i++) {
333-
auto p1 = params1[i];
334-
auto p2 = params2[i];
345+
if (params1.size() == params2.size()) {
346+
for (size_t i = 0; i < params1.size(); i++) {
347+
auto p1 = params1[i];
348+
auto p2 = params2[i];
335349

336-
int np1 = static_cast<int>(p1->getConformingProtocols().size());
337-
int np2 = static_cast<int>(p2->getConformingProtocols().size());
338-
int aDelta = np1 - np2;
350+
int np1 = static_cast<int>(p1->getConformingProtocols().size());
351+
int np2 = static_cast<int>(p2->getConformingProtocols().size());
352+
int aDelta = np1 - np2;
339353

340-
if (aDelta)
341-
return aDelta > 0;
342-
}
354+
if (aDelta)
355+
return aDelta > 0;
343356
}
344357
}
345358
}
@@ -475,9 +488,14 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
475488
// A non-generic declaration is more specialized than a generic declaration.
476489
if (auto func1 = dyn_cast<AbstractFunctionDecl>(decl1)) {
477490
auto func2 = cast<AbstractFunctionDecl>(decl2);
478-
if (static_cast<bool>(func1->getGenericParams()) !=
479-
static_cast<bool>(func2->getGenericParams()))
480-
return func2->getGenericParams();
491+
if (func1->isGeneric() != func2->isGeneric())
492+
return func2->isGeneric();
493+
}
494+
495+
if (auto subscript1 = dyn_cast<SubscriptDecl>(decl1)) {
496+
auto subscript2 = cast<SubscriptDecl>(decl2);
497+
if (subscript1->isGeneric() != subscript2->isGeneric())
498+
return subscript2->isGeneric();
481499
}
482500

483501
// A witness is always more specialized than the requirement it satisfies.
@@ -531,8 +549,6 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
531549
}
532550
} else {
533551
// Add a curried 'self' type.
534-
assert(!type1->is<GenericFunctionType>() && "Odd generic function type?");
535-
assert(!type2->is<GenericFunctionType>() && "Odd generic function type?");
536552
type1 = addCurriedSelfType(tc.Context, type1, decl1->getDeclContext());
537553
type2 = addCurriedSelfType(tc.Context, type2, decl2->getDeclContext());
538554

0 commit comments

Comments
 (0)