Skip to content

Commit c30bc08

Browse files
authored
Merge pull request swiftlang#12391 from DougGregor/sr-6107
[Mangling] Mangle generic signature requirements not satisfied by parent context
2 parents b4e78b9 + 3771f03 commit c30bc08

File tree

4 files changed

+102
-96
lines changed

4 files changed

+102
-96
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,17 @@ class ASTMangler : public Mangler {
195195

196196
void appendTypeList(Type listTy);
197197

198-
void appendGenericSignature(const GenericSignature *sig);
198+
/// Append a generic signature to the mangling.
199+
///
200+
/// \param sig The generic signature.
201+
///
202+
/// \param contextSig The signature of the known context. This function
203+
/// will only mangle the difference between \c sig and \c contextSig.
204+
///
205+
/// \returns \c true if a generic signature was appended, \c false
206+
/// if it was empty.
207+
bool appendGenericSignature(const GenericSignature *sig,
208+
GenericSignature *contextSig = nullptr);
199209

200210
void appendRequirement(const Requirement &reqt);
201211

@@ -218,10 +228,8 @@ class ASTMangler : public Mangler {
218228
void appendInitializerEntity(const VarDecl *var);
219229

220230
CanType getDeclTypeForMangling(const ValueDecl *decl,
221-
ArrayRef<GenericTypeParamType *> &genericParams,
222-
unsigned &initialParamIndex,
223-
ArrayRef<Requirement> &requirements,
224-
SmallVectorImpl<Requirement> &requirementsBuf);
231+
GenericSignature *&genericSig,
232+
GenericSignature *&parentGenericSig);
225233

226234
void appendDeclType(const ValueDecl *decl, bool isFunctionMangling = false);
227235

lib/AST/ASTMangler.cpp

Lines changed: 67 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,11 +1537,57 @@ void ASTMangler::appendTypeList(Type listTy) {
15371537
}
15381538
}
15391539

1540-
void ASTMangler::appendGenericSignature(const GenericSignature *sig) {
1540+
bool ASTMangler::appendGenericSignature(const GenericSignature *sig,
1541+
GenericSignature *contextSig) {
15411542
auto canSig = sig->getCanonicalSignature();
15421543
CurGenericSignature = canSig;
1543-
appendGenericSignatureParts(canSig->getGenericParams(), 0,
1544-
canSig->getRequirements());
1544+
1545+
unsigned initialParamDepth;
1546+
ArrayRef<GenericTypeParamType *> genericParams;
1547+
ArrayRef<Requirement> requirements;
1548+
SmallVector<Requirement, 4> requirementsBuffer;
1549+
if (contextSig) {
1550+
// If the signature is the same as the context signature, there's nothing
1551+
// to do.
1552+
if (contextSig->getCanonicalSignature() == canSig) {
1553+
return false;
1554+
}
1555+
1556+
// The signature depth starts above the depth of the context signature.
1557+
if (!contextSig->getGenericParams().empty()) {
1558+
initialParamDepth = contextSig->getGenericParams().back()->getDepth() + 1;
1559+
}
1560+
1561+
// Find the parameters at this depth (or greater).
1562+
genericParams = canSig->getGenericParams();
1563+
unsigned firstParam = genericParams.size();
1564+
while (firstParam > 1 &&
1565+
genericParams[firstParam-1]->getDepth() >= initialParamDepth)
1566+
--firstParam;
1567+
genericParams = genericParams.slice(firstParam);
1568+
1569+
for (auto &reqt : canSig->getRequirements()) {
1570+
// If the requirement is satisfied by the context signature,
1571+
// we don't need to mangle it here.
1572+
if (contextSig->isRequirementSatisfied(reqt))
1573+
continue;
1574+
1575+
// Mangle the requirement.
1576+
requirementsBuffer.push_back(reqt);
1577+
}
1578+
requirements = requirementsBuffer;
1579+
} else {
1580+
// Use the complete canonical signature.
1581+
initialParamDepth = 0;
1582+
genericParams = canSig->getGenericParams();
1583+
requirements = canSig->getRequirements();
1584+
}
1585+
1586+
if (genericParams.empty() && requirements.empty())
1587+
return false;
1588+
1589+
appendGenericSignatureParts(genericParams, initialParamDepth, requirements);
1590+
return true;
15451591
}
15461592

15471593
void ASTMangler::appendRequirement(const Requirement &reqt) {
@@ -1736,23 +1782,13 @@ static bool isMethodDecl(const Decl *decl) {
17361782
&& decl->getDeclContext()->isTypeContext();
17371783
}
17381784

1739-
static bool genericParamIsBelowDepth(Type type, unsigned methodDepth) {
1740-
if (!type->hasTypeParameter())
1741-
return true;
1742-
1743-
return !type.findIf([methodDepth](Type t) -> bool {
1744-
if (auto *gp = t->getAs<GenericTypeParamType>())
1745-
return gp->getDepth() >= methodDepth;
1746-
return false;
1747-
});
1748-
}
1749-
17501785
CanType ASTMangler::getDeclTypeForMangling(
1751-
const ValueDecl *decl,
1752-
ArrayRef<GenericTypeParamType *> &genericParams,
1753-
unsigned &initialParamDepth,
1754-
ArrayRef<Requirement> &requirements,
1755-
SmallVectorImpl<Requirement> &requirementsBuf) {
1786+
const ValueDecl *decl,
1787+
GenericSignature *&genericSig,
1788+
GenericSignature *&parentGenericSig) {
1789+
genericSig = nullptr;
1790+
parentGenericSig = nullptr;
1791+
17561792
auto &C = decl->getASTContext();
17571793
if (!decl->hasInterfaceType() || decl->getInterfaceType()->is<ErrorType>()) {
17581794
if (isa<AbstractFunctionDecl>(decl))
@@ -1761,21 +1797,14 @@ CanType ASTMangler::getDeclTypeForMangling(
17611797
return C.TheErrorType;
17621798
}
17631799

1764-
auto type = decl->getInterfaceType()->getCanonicalType();
17651800

1766-
initialParamDepth = 0;
1767-
CanGenericSignature sig;
1801+
CanType type = decl->getInterfaceType()->getCanonicalType();
17681802
if (auto gft = dyn_cast<GenericFunctionType>(type)) {
1769-
sig = gft.getGenericSignature();
1770-
CurGenericSignature = sig;
1771-
genericParams = sig->getGenericParams();
1772-
requirements = sig->getRequirements();
1803+
genericSig = gft.getGenericSignature();
1804+
CurGenericSignature = gft.getGenericSignature();
17731805

17741806
type = CanFunctionType::get(gft->getParams(), gft.getResult(),
17751807
gft->getExtInfo());
1776-
} else {
1777-
genericParams = {};
1778-
requirements = {};
17791808
}
17801809

17811810
if (!type->hasError()) {
@@ -1785,62 +1814,19 @@ CanType ASTMangler::getDeclTypeForMangling(
17851814
type = cast<AnyFunctionType>(type).getResult();
17861815
}
17871816

1788-
if (isMethodDecl(decl) || isa<SubscriptDecl>(decl)) {
1789-
// Drop generic parameters and requirements from the method's context.
1790-
auto parentGenericSig =
1791-
decl->getDeclContext()->getGenericSignatureOfContext();
1792-
if (parentGenericSig && sig) {
1793-
// The method's depth starts above the depth of the context.
1794-
if (!parentGenericSig->getGenericParams().empty())
1795-
initialParamDepth =
1796-
parentGenericSig->getGenericParams().back()->getDepth() + 1;
1797-
1798-
while (!genericParams.empty()) {
1799-
if (genericParams.front()->getDepth() >= initialParamDepth)
1800-
break;
1801-
genericParams = genericParams.slice(1);
1802-
}
1803-
1804-
requirementsBuf.clear();
1805-
for (auto &reqt : sig->getRequirements()) {
1806-
switch (reqt.getKind()) {
1807-
case RequirementKind::Conformance:
1808-
case RequirementKind::Layout:
1809-
case RequirementKind::Superclass:
1810-
// We don't need the requirement if the constrained type is below the
1811-
// method depth.
1812-
if (genericParamIsBelowDepth(reqt.getFirstType(), initialParamDepth))
1813-
continue;
1814-
break;
1815-
case RequirementKind::SameType:
1816-
// We don't need the requirement if both types are below the method
1817-
// depth, or non-dependent.
1818-
if (genericParamIsBelowDepth(reqt.getFirstType(), initialParamDepth) &&
1819-
genericParamIsBelowDepth(reqt.getSecondType(), initialParamDepth))
1820-
continue;
1821-
break;
1822-
}
1823-
1824-
// If we fell through the switch, mangle the requirement.
1825-
requirementsBuf.push_back(reqt);
1826-
}
1827-
requirements = requirementsBuf;
1828-
}
1829-
}
1817+
if (isMethodDecl(decl) || isa<SubscriptDecl>(decl))
1818+
parentGenericSig = decl->getDeclContext()->getGenericSignatureOfContext();
18301819
}
1831-
return type->getCanonicalType();
1820+
1821+
return type;
18321822
}
18331823

18341824
void ASTMangler::appendDeclType(const ValueDecl *decl, bool isFunctionMangling) {
1835-
ArrayRef<GenericTypeParamType *> genericParams;
1836-
unsigned initialParamDepth;
1837-
ArrayRef<Requirement> requirements;
1838-
SmallVector<Requirement, 4> requirementsBuf;
18391825
Mod = decl->getModuleContext();
1840-
auto type = getDeclTypeForMangling(decl,
1841-
genericParams, initialParamDepth,
1842-
requirements, requirementsBuf);
1843-
1826+
GenericSignature *genericSig = nullptr;
1827+
GenericSignature *parentGenericSig = nullptr;
1828+
auto type = getDeclTypeForMangling(decl, genericSig, parentGenericSig);
1829+
18441830
if (AnyFunctionType *FuncTy = type->getAs<AnyFunctionType>()) {
18451831

18461832
const ParameterList *Params = nullptr;
@@ -1865,9 +1851,7 @@ void ASTMangler::appendDeclType(const ValueDecl *decl, bool isFunctionMangling)
18651851
}
18661852

18671853
// Mangle the generic signature, if any.
1868-
if (!genericParams.empty() || !requirements.empty()) {
1869-
appendGenericSignatureParts(genericParams, initialParamDepth,
1870-
requirements);
1854+
if (genericSig && appendGenericSignature(genericSig, parentGenericSig)) {
18711855
// The 'F' function mangling doesn't need a 'u' for its generic signature.
18721856
if (!isFunctionMangling)
18731857
appendOperator("u");

lib/AST/GenericSignature.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -678,14 +678,17 @@ bool GenericSignature::isRequirementSatisfied(Requirement requirement) {
678678
case RequirementKind::Layout: {
679679
auto requiredLayout = requirement.getLayoutConstraint();
680680

681-
if (canFirstType->isTypeParameter())
682-
return getLayoutConstraint(canFirstType) == requiredLayout;
683-
else {
684-
// The requirement is on a concrete type, so it's either globally correct
685-
// or globally incorrect, independent of this generic context. The latter
686-
// case should be diagnosed elsewhere, so let's assume it's correct.
687-
return true;
681+
if (canFirstType->isTypeParameter()) {
682+
if (auto layout = getLayoutConstraint(canFirstType))
683+
return static_cast<bool>(layout.merge(requiredLayout));
684+
685+
return false;
688686
}
687+
688+
// The requirement is on a concrete type, so it's either globally correct
689+
// or globally incorrect, independent of this generic context. The latter
690+
// case should be diagnosed elsewhere, so let's assume it's correct.
691+
return true;
689692
}
690693
}
691694
}

test/SILGen/mangling_generic_extensions.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ extension Foo {
2121
// NO-SELF-LABEL: sil hidden @_T027mangling_generic_extensions3FooV4zangyqd__lF
2222
func zang<U>(_: U) { }
2323
// NO-SELF-LABEL: sil hidden @_T027mangling_generic_extensions3FooV4zungyqd__AA8RuncibleRd__3HatQyd__Rs_lF
24-
func zung<U: Runcible where U.Hat == T>(_: U) { }
24+
func zung<U: Runcible>(_: U) where U.Hat == T { }
2525
}
2626

2727
extension Foo where T: Runcible {
@@ -56,3 +56,14 @@ extension Runcible where Self.Spoon == Self.Hat {
5656
// CHECK-LABEL: sil hidden @_T027mangling_generic_extensions8RunciblePA2aBRz5SpoonQz3HatRtzlE5runceyyF
5757
func runce() {}
5858
}
59+
60+
61+
struct Bar<T: Runcible, U: Runcible> { }
62+
63+
extension Bar {
64+
// CHECK-LABEL: _T027mangling_generic_extensions3BarV4bar1yqd__AA8RuncibleRd__AaE5SpoonRpzAFQy_AGRSlF
65+
func bar1<V: Runcible>(_: V) where U.Spoon: Runcible, T.Spoon == U.Spoon { }
66+
67+
// CHECK-LABEL: _T027mangling_generic_extensions3BarV4bar1yqd__AA8RuncibleRd__AaE5SpoonRp_lF
68+
func bar1<V: Runcible>(_: V) where U.Spoon: Runcible { }
69+
}

0 commit comments

Comments
 (0)