Skip to content

Commit fc6011c

Browse files
authored
Merge pull request #72644 from DougGregor/demangle-extensions-without-written-requirements
2 parents ceee764 + 994e342 commit fc6011c

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

include/swift/AST/Decl.h

+26
Original file line numberDiff line numberDiff line change
@@ -1864,6 +1864,32 @@ class ExtensionDecl final : public GenericContext, public Decl,
18641864
/// the original nominal type context.
18651865
bool isInSameDefiningModule() const;
18661866

1867+
/// Determine whether this extension is equivalent to one that requires at
1868+
/// at least some constraints to be written in the source.
1869+
///
1870+
/// This result will differ from `isConstrainedExtension()` when any of
1871+
/// the generic parameters of the type are invertible, e.g.,
1872+
/// \code
1873+
/// struct X<T: ~Copyable>: ~Copyable { }
1874+
///
1875+
/// // Implies `T: Copyable`. This extension `!isWrittenWithConstraints()`
1876+
/// // and `isConstrainedExtension()`.
1877+
/// extension X { }
1878+
///
1879+
/// // This extension `isWrittenWithConstraints()`
1880+
/// // and `!isConstrainedExtension()`.
1881+
/// extension X where T: ~Copyable { }
1882+
///
1883+
/// // Implies `T: Copyable`. This extension `isWrittenWithConstraints()`
1884+
/// // and `isConstrainedExtension()`.
1885+
/// extension X where T: P { }
1886+
///
1887+
/// // This extension `isWrittenWithConstraints()`
1888+
/// // and `isConstrainedExtension()`.
1889+
/// extension X where T: Q, T: ~Copyable { }
1890+
/// \endcode
1891+
bool isWrittenWithConstraints() const;
1892+
18671893
/// Returns the name of the category specified by the \c \@_objcImplementation
18681894
/// attribute, or \c None if the name is invalid or
18691895
/// \c isObjCImplementation() is false.

lib/AST/ASTDemangler.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,9 @@ ASTBuilder::findDeclContext(NodePointer node) {
12981298
continue;
12991299
}
13001300

1301+
if (!ext->isWrittenWithConstraints() && !genericSig)
1302+
return ext;
1303+
13011304
auto extSig = ext->getGenericSignature().getCanonicalSignature();
13021305
if (extSig == genericSig) {
13031306
return ext;

lib/AST/Decl.cpp

+48
Original file line numberDiff line numberDiff line change
@@ -1763,6 +1763,54 @@ bool ExtensionDecl::isConstrainedExtension() const {
17631763
return !typeSig->isEqual(extSig);
17641764
}
17651765

1766+
bool ExtensionDecl::isWrittenWithConstraints() const {
1767+
auto nominal = getExtendedNominal();
1768+
if (!nominal)
1769+
return false;
1770+
1771+
// If there's no generic signature, then it's written without constraints.
1772+
CanGenericSignature extSig = getGenericSignature().getCanonicalSignature();
1773+
if (!extSig)
1774+
return false;
1775+
1776+
CanGenericSignature typeSig =
1777+
nominal->getGenericSignature().getCanonicalSignature();
1778+
1779+
// Get the requirements and inverses for both the extension and type.
1780+
SmallVector<Requirement, 2> extReqs;
1781+
SmallVector<InverseRequirement, 2> extInverseReqs;
1782+
extSig->getRequirementsWithInverses(extReqs, extInverseReqs);
1783+
1784+
SmallVector<Requirement, 2> typeReqs;
1785+
SmallVector<InverseRequirement, 2> typeInverseReqs;
1786+
typeSig->getRequirementsWithInverses(typeReqs, typeInverseReqs);
1787+
1788+
// If the (non-inverse) requirements are different between the extension and
1789+
// the original type, it's written with constraints. Note that
1790+
// the extension can only add requirements, so we need only check the size
1791+
// (not the specific requirements).
1792+
if (extReqs.size() > typeReqs.size()) {
1793+
return true;
1794+
}
1795+
1796+
assert(extReqs.size() == typeReqs.size());
1797+
1798+
// If the type has no inverse requirements, there are no extra constraints
1799+
// to write.
1800+
if (typeInverseReqs.empty()) {
1801+
return false;
1802+
}
1803+
1804+
// If the extension has no inverse requirements, then there are no constraints
1805+
// that need to be written down.
1806+
if (extInverseReqs.empty()) {
1807+
return false;
1808+
}
1809+
1810+
// We have inverses that need to be written out.
1811+
return true;
1812+
}
1813+
17661814
bool ExtensionDecl::isInSameDefiningModule() const {
17671815
auto decl = getExtendedNominal();
17681816
auto extensionAlterName = getAlternateModuleName();

test/IRGen/mangling_inverse_generics_evolution.swift

+14
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,20 @@ extension XQ: Q where T: ~Copyable {
6262
struct A { }
6363
}
6464

65+
protocol HasResult {
66+
associatedtype Success
67+
}
68+
69+
extension Result: HasResult {
70+
func testMe() -> Success? {
71+
var x: Result.Success? = nil
72+
if case let .success(s) = self {
73+
x = s
74+
}
75+
return x
76+
}
77+
}
78+
6579
// Class metadata
6680

6781
@_fixed_layout

0 commit comments

Comments
 (0)