Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preliminary Sema support for generic subscripts #7683

Merged
merged 10 commits into from
Feb 22, 2017
58 changes: 31 additions & 27 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1458,8 +1458,7 @@ void ASTMangler::appendInitializerEntity(const VarDecl *var) {
/// Self type out of its mangling.
static bool isMethodDecl(const Decl *decl) {
return isa<AbstractFunctionDecl>(decl)
&& (isa<NominalTypeDecl>(decl->getDeclContext())
|| isa<ExtensionDecl>(decl->getDeclContext()));
&& decl->getDeclContext()->isTypeContext();
}

static bool genericParamIsBelowDepth(Type type, unsigned methodDepth) {
Expand Down Expand Up @@ -1501,28 +1500,32 @@ CanType ASTMangler::getDeclTypeForMangling(
requirements = {};
}

// Shed the 'self' type and generic requirements from method manglings.
if (isMethodDecl(decl) && type && !type->hasError()) {
// Drop the Self argument clause from the type.
type = cast<AnyFunctionType>(type).getResult();

// Drop generic parameters and requirements from the method's context.
if (auto parentGenericSig =
decl->getDeclContext()->getGenericSignatureOfContext()) {
// The method's depth starts below the depth of the context.
if (!parentGenericSig->getGenericParams().empty())
initialParamDepth =
parentGenericSig->getGenericParams().back()->getDepth()+1;

while (!genericParams.empty()) {
if (genericParams.front()->getDepth() >= initialParamDepth)
break;
genericParams = genericParams.slice(1);
}
if (!type->hasError()) {
// Shed the 'self' type and generic requirements from method manglings.
if (isMethodDecl(decl)) {
// Drop the Self argument clause from the type.
type = cast<AnyFunctionType>(type).getResult();
}

requirementsBuf.clear();
for (auto &reqt : sig->getRequirements()) {
switch (reqt.getKind()) {
if (isMethodDecl(decl) || isa<SubscriptDecl>(decl)) {
// Drop generic parameters and requirements from the method's context.
auto parentGenericSig =
decl->getDeclContext()->getGenericSignatureOfContext();
if (parentGenericSig && sig) {
// The method's depth starts below the depth of the context.
if (!parentGenericSig->getGenericParams().empty())
initialParamDepth =
parentGenericSig->getGenericParams().back()->getDepth()+1;

while (!genericParams.empty()) {
if (genericParams.front()->getDepth() >= initialParamDepth)
break;
genericParams = genericParams.slice(1);
}

requirementsBuf.clear();
for (auto &reqt : sig->getRequirements()) {
switch (reqt.getKind()) {
case RequirementKind::Conformance:
case RequirementKind::Layout:
case RequirementKind::Superclass:
Expand All @@ -1538,12 +1541,13 @@ CanType ASTMangler::getDeclTypeForMangling(
!genericParamIsBelowDepth(reqt.getSecondType(),initialParamDepth))
continue;
break;
}
}

// If we fell through the switch, mangle the requirement.
requirementsBuf.push_back(reqt);
// If we fell through the switch, mangle the requirement.
requirementsBuf.push_back(reqt);
}
requirements = requirementsBuf;
}
requirements = requirementsBuf;
}
}
return type->getCanonicalType();
Expand Down
56 changes: 30 additions & 26 deletions lib/AST/Mangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,8 +466,7 @@ void Mangler::mangleDeclTypeForDebugger(const ValueDecl *decl) {
/// Self type out of its mangling.
static bool isMethodDecl(const Decl *decl) {
return isa<AbstractFunctionDecl>(decl)
&& (isa<NominalTypeDecl>(decl->getDeclContext())
|| isa<ExtensionDecl>(decl->getDeclContext()));
&& decl->getDeclContext()->isTypeContext();
}

static bool genericParamIsBelowDepth(Type type, unsigned methodDepth) {
Expand Down Expand Up @@ -510,27 +509,31 @@ CanType Mangler::getDeclTypeForMangling(
}

// Shed the 'self' type and generic requirements from method manglings.
if (isMethodDecl(decl) && type && !type->hasError()) {
// Drop the Self argument clause from the type.
type = cast<AnyFunctionType>(type).getResult();

// Drop generic parameters and requirements from the method's context.
if (auto parentGenericSig =
decl->getDeclContext()->getGenericSignatureOfContext()) {
// The method's depth starts below the depth of the context.
if (!parentGenericSig->getGenericParams().empty())
initialParamDepth =
parentGenericSig->getGenericParams().back()->getDepth()+1;

while (!genericParams.empty()) {
if (genericParams.front()->getDepth() >= initialParamDepth)
break;
genericParams = genericParams.slice(1);
}
if (!type->hasError()) {
if (isMethodDecl(decl)) {
// Drop the Self argument clause from the type.
type = cast<AnyFunctionType>(type).getResult();
}

requirementsBuf.clear();
for (auto &reqt : sig->getRequirements()) {
switch (reqt.getKind()) {
if (isMethodDecl(decl) || isa<SubscriptDecl>(decl)) {
// Drop generic parameters and requirements from the method's context.
auto parentGenericSig =
decl->getDeclContext()->getGenericSignatureOfContext();
if (parentGenericSig && sig) {
// The method's depth starts below the depth of the context.
if (!parentGenericSig->getGenericParams().empty())
initialParamDepth =
parentGenericSig->getGenericParams().back()->getDepth()+1;

while (!genericParams.empty()) {
if (genericParams.front()->getDepth() >= initialParamDepth)
break;
genericParams = genericParams.slice(1);
}

requirementsBuf.clear();
for (auto &reqt : sig->getRequirements()) {
switch (reqt.getKind()) {
case RequirementKind::Conformance:
case RequirementKind::Layout:
case RequirementKind::Superclass:
Expand All @@ -546,12 +549,13 @@ CanType Mangler::getDeclTypeForMangling(
!genericParamIsBelowDepth(reqt.getSecondType(),initialParamDepth))
continue;
break;
}
}

// If we fell through the switch, mangle the requirement.
requirementsBuf.push_back(reqt);
// If we fell through the switch, mangle the requirement.
requirementsBuf.push_back(reqt);
}
requirements = requirementsBuf;
}
requirements = requirementsBuf;
}
}

Expand Down
4 changes: 4 additions & 0 deletions lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,8 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,

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

while (dcGenericParams) {
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
Expand Down
7 changes: 6 additions & 1 deletion lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5998,7 +5998,12 @@ SwiftDeclConverter::importSubscript(Decl *decl,
SourceLoc());
auto indicesType = bodyParams->getType(C);

auto fnType = FunctionType::get(indicesType, elementTy);
AnyFunctionType *fnType;
if (auto *sig = dc->getGenericSignatureOfContext())
fnType = GenericFunctionType::get(sig, indicesType, elementTy,
AnyFunctionType::ExtInfo());
else
fnType = FunctionType::get(indicesType, elementTy);
subscript->setInterfaceType(fnType);

addObjCAttribute(subscript, None);
Expand Down
2 changes: 1 addition & 1 deletion lib/SILGen/SILGenMaterializeForSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ struct MaterializeForSetEmitter {
CanType witnessIfaceType =
WitnessStorage->getInterfaceType()->getCanonicalType();
if (isa<SubscriptDecl>(WitnessStorage))
witnessIfaceType = cast<FunctionType>(witnessIfaceType).getResult();
witnessIfaceType = cast<AnyFunctionType>(witnessIfaceType).getResult();
SubstStorageType = getSubstWitnessInterfaceType(
witnessIfaceType.getReferenceStorageReferent());

Expand Down
72 changes: 44 additions & 28 deletions lib/Sema/CSRanking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,16 @@ static Type addCurriedSelfType(ASTContext &ctx, Type type, DeclContext *dc) {
if (!dc->isTypeContext())
return type;

auto nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
auto selfTy = nominal->getInterfaceType()->castTo<MetatypeType>()
->getInstanceType();
if (auto sig = nominal->getGenericSignatureOfContext())
GenericSignature *sig = dc->getGenericSignatureOfContext();
if (auto *genericFn = type->getAs<GenericFunctionType>()) {
sig = genericFn->getGenericSignature();
type = FunctionType::get(genericFn->getInput(),
genericFn->getResult(),
genericFn->getExtInfo());
}

auto selfTy = dc->getDeclaredInterfaceType();
if (sig)
return GenericFunctionType::get(sig, selfTy, type,
AnyFunctionType::ExtInfo());
return FunctionType::get(selfTy, type);
Expand All @@ -315,31 +321,38 @@ static bool isDeclMoreConstrainedThan(ValueDecl *decl1, ValueDecl *decl2) {

if (decl1->getKind() != decl2->getKind() || isa<TypeDecl>(decl1))
return false;


GenericParamList *gp1 = nullptr, *gp2 = nullptr;

auto func1 = dyn_cast<FuncDecl>(decl1);
auto func2 = dyn_cast<FuncDecl>(decl2);

if (func1 && func2) {

auto gp1 = func1->getGenericParams();
auto gp2 = func2->getGenericParams();

if (gp1 && gp2) {
auto params1 = gp1->getParams();
auto params2 = gp2->getParams();
gp1 = func1->getGenericParams();
gp2 = func2->getGenericParams();
}

auto subscript1 = dyn_cast<SubscriptDecl>(decl1);
auto subscript2 = dyn_cast<SubscriptDecl>(decl2);
if (subscript1 && subscript2) {
gp1 = subscript1->getGenericParams();
gp2 = subscript2->getGenericParams();
}

if (gp1 && gp2) {
auto params1 = gp1->getParams();
auto params2 = gp2->getParams();

if (params1.size() == params2.size()) {
for (size_t i = 0; i < params1.size(); i++) {
auto p1 = params1[i];
auto p2 = params2[i];
if (params1.size() == params2.size()) {
for (size_t i = 0; i < params1.size(); i++) {
auto p1 = params1[i];
auto p2 = params2[i];

int np1 = static_cast<int>(p1->getConformingProtocols().size());
int np2 = static_cast<int>(p2->getConformingProtocols().size());
int aDelta = np1 - np2;
int np1 = static_cast<int>(p1->getConformingProtocols().size());
int np2 = static_cast<int>(p2->getConformingProtocols().size());
int aDelta = np1 - np2;

if (aDelta)
return aDelta > 0;
}
if (aDelta)
return aDelta > 0;
}
}
}
Expand Down Expand Up @@ -475,9 +488,14 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
// A non-generic declaration is more specialized than a generic declaration.
if (auto func1 = dyn_cast<AbstractFunctionDecl>(decl1)) {
auto func2 = cast<AbstractFunctionDecl>(decl2);
if (static_cast<bool>(func1->getGenericParams()) !=
static_cast<bool>(func2->getGenericParams()))
return func2->getGenericParams();
if (func1->isGeneric() != func2->isGeneric())
return func2->isGeneric();
}

if (auto subscript1 = dyn_cast<SubscriptDecl>(decl1)) {
auto subscript2 = cast<SubscriptDecl>(decl2);
if (subscript1->isGeneric() != subscript2->isGeneric())
return subscript2->isGeneric();
}

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

Expand Down
Loading