Skip to content

Commit 6549e0e

Browse files
committed
AST: Introduce representation for pack conformances
1 parent e75174e commit 6549e0e

File tree

6 files changed

+575
-0
lines changed

6 files changed

+575
-0
lines changed

include/swift/AST/PackConformance.h

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//===--- PackConformance.h - Variadic Protocol Conformance ------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines the PackConformance structure, which describes the
14+
// conformance of a type pack parameter to a protocol.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
#ifndef SWIFT_AST_PACKCONFORMANCE_H
18+
#define SWIFT_AST_PACKCONFORMANCE_H
19+
20+
#include "swift/AST/ASTAllocated.h"
21+
#include "swift/AST/ProtocolConformanceRef.h"
22+
#include "swift/AST/Type.h"
23+
#include "swift/AST/TypeAlignments.h"
24+
#include "swift/Basic/Compiler.h"
25+
#include "llvm/ADT/ArrayRef.h"
26+
#include "llvm/ADT/FoldingSet.h"
27+
#include "llvm/Support/TrailingObjects.h"
28+
29+
namespace swift {
30+
31+
class PackType;
32+
33+
class alignas(1 << DeclAlignInBits) PackConformance final
34+
: public ASTAllocated<PackConformance>,
35+
public llvm::FoldingSetNode,
36+
private llvm::TrailingObjects<PackConformance, ProtocolConformanceRef> {
37+
friend class ASTContext;
38+
friend TrailingObjects;
39+
40+
/// The pack type conforming to the protocol.
41+
PackType *ConformingType;
42+
43+
/// The conformed-to protocol.
44+
ProtocolDecl *Protocol;
45+
46+
public:
47+
void Profile(llvm::FoldingSetNodeID &ID) const;
48+
static void Profile(llvm::FoldingSetNodeID &ID,
49+
PackType *conformingType,
50+
ProtocolDecl *protocol,
51+
ArrayRef<ProtocolConformanceRef> conformances);
52+
53+
private:
54+
PackConformance(PackType *conformingType,
55+
ProtocolDecl *protocol,
56+
ArrayRef<ProtocolConformanceRef> conformances);
57+
58+
size_t numTrailingObjects(OverloadToken<ProtocolConformanceRef>) const;
59+
60+
public:
61+
static PackConformance *get(PackType *conformingType,
62+
ProtocolDecl *protocol,
63+
ArrayRef<ProtocolConformanceRef> conformances);
64+
65+
PackType *getType() const { return ConformingType; }
66+
67+
ProtocolDecl *getProtocol() const { return Protocol; }
68+
69+
ArrayRef<ProtocolConformanceRef> getPatternConformances() const;
70+
71+
bool isCanonical() const;
72+
73+
PackConformance *getCanonicalConformance() const;
74+
75+
PackType *getAssociatedType(Type assocType) const;
76+
77+
PackConformance *
78+
getAssociatedConformance(Type assocType, ProtocolDecl *protocol) const;
79+
80+
PackConformance *subst(SubstitutionMap subMap,
81+
SubstOptions options=None) const;
82+
83+
PackConformance *subst(TypeSubstitutionFn subs,
84+
LookupConformanceFn conformances,
85+
SubstOptions options=None) const;
86+
87+
SWIFT_DEBUG_DUMP;
88+
void dump(llvm::raw_ostream &out, unsigned indent = 0) const;
89+
};
90+
91+
void simple_display(llvm::raw_ostream &out, PackConformance *conformance);
92+
93+
} // end namespace swift
94+
95+
#endif // SWIFT_AST_PACKCONFORMANCE_H

include/swift/AST/TypeAlignments.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ namespace swift {
4646
class NormalProtocolConformance;
4747
class OpaqueValueExpr;
4848
class OperatorDecl;
49+
class PackConformance;
4950
class Pattern;
5051
class ProtocolDecl;
5152
class ProtocolConformance;
@@ -133,6 +134,7 @@ LLVM_DECLARE_TYPE_ALIGNMENT(swift::Expr, swift::ExprAlignInBits)
133134
LLVM_DECLARE_TYPE_ALIGNMENT(swift::CaptureListExpr, swift::ExprAlignInBits)
134135
LLVM_DECLARE_TYPE_ALIGNMENT(swift::AbstractClosureExpr, swift::ExprAlignInBits)
135136
LLVM_DECLARE_TYPE_ALIGNMENT(swift::OpaqueValueExpr, swift::ExprAlignInBits)
137+
LLVM_DECLARE_TYPE_ALIGNMENT(swift::PackConformance, swift::DeclAlignInBits)
136138
LLVM_DECLARE_TYPE_ALIGNMENT(swift::ProtocolConformance, swift::DeclAlignInBits)
137139
LLVM_DECLARE_TYPE_ALIGNMENT(swift::NormalProtocolConformance,
138140
swift::DeclAlignInBits)

lib/AST/ASTContext.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "swift/AST/ModuleDependencies.h"
3838
#include "swift/AST/ModuleLoader.h"
3939
#include "swift/AST/NameLookup.h"
40+
#include "swift/AST/PackConformance.h"
4041
#include "swift/AST/ParameterList.h"
4142
#include "swift/AST/PrettyStackTrace.h"
4243
#include "swift/AST/PropertyWrappers.h"
@@ -445,6 +446,9 @@ struct ASTContext::Implementation {
445446
llvm::DenseMap<std::pair<Type, ProtocolDecl *>,
446447
BuiltinProtocolConformance *> BuiltinConformances;
447448

449+
/// The set of pack conformances.
450+
llvm::FoldingSet<PackConformance> PackConformances;
451+
448452
/// The set of substitution maps (uniqued by their storage).
449453
llvm::FoldingSet<SubstitutionMap::Storage> SubstitutionMaps;
450454

@@ -2473,6 +2477,48 @@ ASTContext::getInheritedConformance(Type type, ProtocolConformance *inherited) {
24732477
return result;
24742478
}
24752479

2480+
PackConformance *PackConformance::get(PackType *conformingType,
2481+
ProtocolDecl *protocol,
2482+
ArrayRef<ProtocolConformanceRef> conformances) {
2483+
auto properties = conformingType->getRecursiveProperties();
2484+
2485+
for (auto conformance : conformances) {
2486+
if (conformance.isAbstract() || conformance.isInvalid())
2487+
continue;
2488+
2489+
auto *concrete = conformance.getConcrete();
2490+
properties |= concrete->getType()->getRecursiveProperties();
2491+
}
2492+
2493+
auto &ctx = protocol->getASTContext();
2494+
2495+
llvm::FoldingSetNodeID id;
2496+
PackConformance::Profile(id, conformingType, protocol, conformances);
2497+
2498+
// Figure out which arena this conformance should go into.
2499+
AllocationArena arena = getArena(properties);
2500+
2501+
// Did we already record the pack conformance?
2502+
void *insertPos;
2503+
auto &packConformances = ctx.getImpl().getArena(arena).PackConformances;
2504+
if (auto result = packConformances.FindNodeOrInsertPos(id, insertPos))
2505+
return result;
2506+
2507+
// Build a new pack conformance.
2508+
auto size = totalSizeToAlloc<ProtocolConformanceRef>(conformances.size());
2509+
auto mem = ctx.Allocate(size, alignof(PackConformance), arena);
2510+
2511+
auto result
2512+
= new (mem) PackConformance(conformingType, protocol,
2513+
conformances);
2514+
auto node = packConformances.FindNodeOrInsertPos(id, insertPos);
2515+
(void)node;
2516+
assert(!node);
2517+
packConformances.InsertNode(result, insertPos);
2518+
2519+
return result;
2520+
}
2521+
24762522
LazyContextData *ASTContext::getOrCreateLazyContextData(
24772523
const DeclContext *dc,
24782524
LazyMemberLoader *lazyLoader) {

lib/AST/ASTDumper.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/ForeignErrorConvention.h"
2424
#include "swift/AST/GenericEnvironment.h"
2525
#include "swift/AST/Initializer.h"
26+
#include "swift/AST/PackConformance.h"
2627
#include "swift/AST/ParameterList.h"
2728
#include "swift/AST/ProtocolConformance.h"
2829
#include "swift/AST/SourceFile.h"
@@ -3404,6 +3405,27 @@ static void dumpProtocolConformanceRec(
34043405
PrintWithColorRAII(out, ParenthesisColor) << ')';
34053406
}
34063407

3408+
static void dumpPackConformanceRec(
3409+
const PackConformance *conformance, llvm::raw_ostream &out,
3410+
unsigned indent,
3411+
llvm::SmallPtrSetImpl<const ProtocolConformance *> &visited) {
3412+
out.indent(indent);
3413+
PrintWithColorRAII(out, ParenthesisColor) << '(';
3414+
out << "pack_conformance type=" << Type(conformance->getType())
3415+
<< " protocol=" << conformance->getProtocol()->getName();
3416+
3417+
auto conformances = conformance->getPatternConformances();
3418+
if (!conformances.empty()) {
3419+
out << "\n";
3420+
3421+
for (auto conformanceRef : conformances) {
3422+
dumpProtocolConformanceRefRec(conformanceRef, out, indent, visited);
3423+
}
3424+
}
3425+
3426+
PrintWithColorRAII(out, ParenthesisColor) << ')';
3427+
}
3428+
34073429
static void dumpSubstitutionMapRec(
34083430
SubstitutionMap map, llvm::raw_ostream &out,
34093431
SubstitutionMap::DumpStyle style, unsigned indent,
@@ -3501,6 +3523,11 @@ void ProtocolConformance::dump(llvm::raw_ostream &out, unsigned indent) const {
35013523
dumpProtocolConformanceRec(this, out, indent, visited);
35023524
}
35033525

3526+
void PackConformance::dump(llvm::raw_ostream &out, unsigned indent) const {
3527+
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
3528+
dumpPackConformanceRec(this, out, indent, visited);
3529+
}
3530+
35043531
void SubstitutionMap::dump(llvm::raw_ostream &out, DumpStyle style,
35053532
unsigned indent) const {
35063533
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ add_swift_host_library(swiftAST STATIC
6969
NameLookup.cpp
7070
NameLookupRequests.cpp
7171
OperatorNameLookup.cpp
72+
PackConformance.cpp
7273
Parameter.cpp
7374
Pattern.cpp
7475
PlatformKind.cpp

0 commit comments

Comments
 (0)