Skip to content

Commit 680c0b2

Browse files
committed
[Macros] Add a request to get the resolved constraint types in the 'conformances:'
list of an attached extension macro attribute.
1 parent 74c9bfb commit 680c0b2

8 files changed

+106
-28
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3336,6 +3336,25 @@ class ResolveMacroRequest
33363336
void noteCycleStep(DiagnosticEngine &diags) const;
33373337
};
33383338

3339+
/// Returns the resolved constraint types that an extension macro
3340+
/// adds conformances to.
3341+
class ResolveExtensionMacroConformances
3342+
: public SimpleRequest<ResolveExtensionMacroConformances,
3343+
ArrayRef<Type>(const MacroRoleAttr *, const Decl *),
3344+
RequestFlags::Cached> {
3345+
public:
3346+
using SimpleRequest::SimpleRequest;
3347+
3348+
private:
3349+
friend SimpleRequest;
3350+
3351+
ArrayRef<Type> evaluate(Evaluator &evaluator,
3352+
const MacroRoleAttr *, const Decl *) const;
3353+
3354+
public:
3355+
bool isCached() const { return true; }
3356+
};
3357+
33393358
class ResolveTypeEraserTypeRequest
33403359
: public SimpleRequest<ResolveTypeEraserTypeRequest,
33413360
Type (ProtocolDecl *, TypeEraserAttr *),

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,9 @@ SWIFT_REQUEST(TypeChecker, ResolveImplicitMemberRequest,
360360
SWIFT_REQUEST(TypeChecker, ResolveMacroRequest,
361361
ConcreteDeclRef(UnresolvedMacroReference, const Decl *),
362362
Cached, NoLocationInfo)
363+
SWIFT_REQUEST(TypeChecker, ResolveExtensionMacroConformances,
364+
ArrayRef<Type>(const MacroRoleAttr *, const Decl *),
365+
Cached, NoLocationInfo)
363366
SWIFT_REQUEST(TypeChecker, ResolveTypeEraserTypeRequest,
364367
Type(ProtocolDecl *, TypeEraserAttr *),
365368
SeparatelyCached, NoLocationInfo)

lib/AST/Decl.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10702,8 +10702,13 @@ void MacroDecl::getIntroducedConformances(
1070210702
if (!attr)
1070310703
return;
1070410704

10705-
for (auto repr : attr->getConformances()) {
10706-
auto constraint = repr->getInstanceType();
10705+
auto &ctx = getASTContext();
10706+
auto constraintTypes = evaluateOrDefault(
10707+
ctx.evaluator,
10708+
ResolveExtensionMacroConformances{attr, this},
10709+
{});
10710+
10711+
for (auto constraint : constraintTypes) {
1070710712
assert(constraint->isConstraintType());
1070810713

1070910714
std::function<void(Type)> addConstraint =

lib/Sema/TypeCheckAttr.cpp

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7136,31 +7136,10 @@ void AttributeChecker::visitMacroRoleAttr(MacroRoleAttr *attr) {
71367136
}
71377137
}
71387138

7139-
for (auto *typeExpr : attr->getConformances()) {
7140-
if (auto *typeRepr = typeExpr->getTypeRepr()) {
7141-
auto *dc = D->getDeclContext();
7142-
auto resolved =
7143-
TypeResolution::forInterface(
7144-
dc, TypeResolverContext::GenericRequirement,
7145-
/*unboundTyOpener*/ nullptr,
7146-
/*placeholderHandler*/ nullptr,
7147-
/*packElementOpener*/ nullptr)
7148-
.resolveType(typeRepr);
7149-
7150-
if (resolved->is<ErrorType>()) {
7151-
attr->setInvalid();
7152-
continue;
7153-
}
7154-
7155-
if (!resolved->isConstraintType()) {
7156-
diagnoseAndRemoveAttr(attr, diag::extension_macro_invalid_conformance,
7157-
resolved);
7158-
continue;
7159-
}
7160-
7161-
typeExpr->setType(MetatypeType::get(resolved));
7162-
}
7163-
}
7139+
(void)evaluateOrDefault(
7140+
Ctx.evaluator,
7141+
ResolveExtensionMacroConformances{attr, D},
7142+
{});
71647143
}
71657144

71667145
namespace {

lib/Sema/TypeCheckMacros.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "TypeCheckMacros.h"
1818
#include "../AST/InlinableText.h"
1919
#include "TypeChecker.h"
20+
#include "TypeCheckType.h"
2021
#include "swift/ABI/MetadataValues.h"
2122
#include "swift/AST/ASTContext.h"
2223
#include "swift/AST/ASTMangler.h"
@@ -1675,6 +1676,43 @@ ConcreteDeclRef ResolveMacroRequest::evaluate(Evaluator &evaluator,
16751676
return macroExpansion->getMacroRef();
16761677
}
16771678

1679+
ArrayRef<Type>
1680+
ResolveExtensionMacroConformances::evaluate(Evaluator &evaluator,
1681+
const MacroRoleAttr *attr,
1682+
const Decl *decl) const {
1683+
auto *dc = decl->getDeclContext();
1684+
auto &ctx = dc->getASTContext();
1685+
1686+
SmallVector<Type, 2> protocols;
1687+
for (auto *typeExpr : attr->getConformances()) {
1688+
if (auto *typeRepr = typeExpr->getTypeRepr()) {
1689+
auto resolved =
1690+
TypeResolution::forInterface(
1691+
dc, TypeResolverContext::GenericRequirement,
1692+
/*unboundTyOpener*/ nullptr,
1693+
/*placeholderHandler*/ nullptr,
1694+
/*packElementOpener*/ nullptr)
1695+
.resolveType(typeRepr);
1696+
1697+
if (resolved->is<ErrorType>())
1698+
continue;
1699+
1700+
if (!resolved->isConstraintType()) {
1701+
diagnoseAndRemoveAttr(
1702+
decl, attr,
1703+
diag::extension_macro_invalid_conformance,
1704+
resolved);
1705+
continue;
1706+
}
1707+
1708+
typeExpr->setType(MetatypeType::get(resolved));
1709+
protocols.push_back(resolved);
1710+
}
1711+
}
1712+
1713+
return ctx.AllocateCopy(protocols);
1714+
}
1715+
16781716
// MARK: for IDE.
16791717

16801718
SourceFile *swift::evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
struct STest {
22
var x = requireEquatable(S())
33
}
4+
5+
@ConformanceViaExtension
6+
class Child: Parent {}

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,30 @@ public struct EquatableMacro: ConformanceMacro {
12531253
}
12541254
}
12551255

1256+
public struct ConformanceViaExtensionMacro: ExtensionMacro {
1257+
public static func expansion(
1258+
of node: AttributeSyntax,
1259+
attachedTo decl: some DeclGroupSyntax,
1260+
providingExtensionsOf type: some TypeSyntaxProtocol,
1261+
conformingTo protocols: [TypeSyntax],
1262+
in context: some MacroExpansionContext
1263+
) throws -> [ExtensionDeclSyntax] {
1264+
if (protocols.isEmpty) {
1265+
return []
1266+
}
1267+
1268+
let decl: DeclSyntax =
1269+
"""
1270+
extension \(raw: type.trimmedDescription): MyProtocol {
1271+
}
1272+
"""
1273+
1274+
return [
1275+
decl.cast(ExtensionDeclSyntax.self)
1276+
]
1277+
}
1278+
}
1279+
12561280
public struct HashableMacro: ConformanceMacro {
12571281
public static func expansion(
12581282
of node: AttributeSyntax,

test/Macros/macro_expand_conformances_multi.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
55

66
// Make sure we see the conformances from another file.
7-
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -swift-version 5 -primary-file %S/Inputs/macro_expand_conformances_other.swift -DDISABLE_TOP_LEVEL_CODE
7+
// RUN: %target-typecheck-verify-swift -enable-experimental-feature ExtensionMacros -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -swift-version 5 -primary-file %S/Inputs/macro_expand_conformances_other.swift -DDISABLE_TOP_LEVEL_CODE
88

99
@attached(conformance)
1010
macro Equatable() = #externalMacro(module: "MacroDefinition", type: "EquatableMacro")
@@ -24,3 +24,10 @@ func requireHashable(_ value: some Hashable) {
2424
@Equatable
2525
struct S {}
2626

27+
protocol MyProtocol {}
28+
29+
@attached(extension, conformances: MyProtocol)
30+
macro ConformanceViaExtension() = #externalMacro(module: "MacroDefinition", type: "ConformanceViaExtensionMacro")
31+
32+
@ConformanceViaExtension
33+
class Parent {}

0 commit comments

Comments
 (0)