Skip to content

Commit fc85f1b

Browse files
authored
Merge pull request #59834 from CodaFi/mangle-tangle
2 parents 5097375 + f30bf85 commit fc85f1b

25 files changed

+498
-274
lines changed

docs/ABI/Mangling.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ Types
637637
type ::= protocol-list 'p' // existential type
638638
type ::= protocol-list superclass 'Xc' // existential type with superclass
639639
type ::= protocol-list 'Xl' // existential type with AnyObject
640-
type ::= protocol-list 'y' (type* '_')* type* retroactive-conformance* 'XP' // parameterized protocol type
640+
type ::= protocol-list requirement* '_' 'XP' // constrained existential type
641641
type ::= type-list 't' // tuple
642642
type ::= type generic-signature 'u' // generic type
643643
type ::= 'x' // generic param, depth=0, idx=0
@@ -878,6 +878,7 @@ now codified into the ABI; the index 0 is therefore reserved.
878878
GENERIC-PARAM-INDEX ::= 'z' // depth = 0, idx = 0
879879
GENERIC-PARAM-INDEX ::= INDEX // depth = 0, idx = N+1
880880
GENERIC-PARAM-INDEX ::= 'd' INDEX INDEX // depth = M+1, idx = N
881+
GENERIC-PARAM-INDEX ::= 's' // depth = 0, idx = 0; Constrained existential 'Self' type
881882

882883
LAYOUT-CONSTRAINT ::= 'N' // NativeRefCountedObject
883884
LAYOUT-CONSTRAINT ::= 'R' // RefCountedObject

include/swift/AST/ASTDemangler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ class ASTBuilder {
119119

120120
Type createProtocolTypeFromDecl(ProtocolDecl *protocol);
121121

122-
Type createParameterizedProtocolType(Type base, ArrayRef<Type> args);
122+
Type createConstrainedExistentialType(Type base,
123+
ArrayRef<BuiltRequirement> constraints);
123124

124125
Type createExistentialMetatypeType(Type instance,
125126
Optional<Demangle::ImplMetatypeRepresentation> repr=None);

include/swift/AST/ASTMangler.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,8 @@ class ASTMangler : public Mangler {
343343
bool &isAssocTypeAtDepth);
344344

345345
void appendOpWithGenericParamIndex(StringRef,
346-
const GenericTypeParamType *paramTy);
346+
const GenericTypeParamType *paramTy,
347+
bool baseIsProtocolSelf = false);
347348

348349
/// Mangles a sugared type iff we are mangling for the debugger.
349350
template <class T> void appendSugaredType(Type type,
@@ -444,8 +445,17 @@ class ASTMangler : public Mangler {
444445
bool appendGenericSignature(GenericSignature sig,
445446
GenericSignature contextSig = nullptr);
446447

447-
void appendRequirement(const Requirement &reqt,
448-
GenericSignature sig);
448+
/// Append a requirement to the mangling.
449+
///
450+
/// \param reqt The requirement to mangle
451+
/// \param sig The generic signature.
452+
/// \param lhsBaseIsProtocolSelf If \c true, mangle the base of the left-hand
453+
/// side of the constraint with a special protocol 'Self' sentinel node. This
454+
/// supports distinguishing requirements rooted at 'Self' in constrained
455+
/// existentials from ambient generic parameters that would otherwise be
456+
/// at e.g. (0, 0) as well.
457+
void appendRequirement(const Requirement &reqt, GenericSignature sig,
458+
bool lhsBaseIsProtocolSelf = false);
449459

450460
void appendGenericSignatureParts(GenericSignature sig,
451461
ArrayRef<CanTypeWrapper<GenericTypeParamType>> params,
@@ -521,6 +531,9 @@ class ASTMangler : public Mangler {
521531
Demangle::AutoDiffFunctionKind kind,
522532
const AutoDiffConfig &config);
523533
void appendIndexSubset(IndexSubset *indexSubset);
534+
535+
void appendConstrainedExistential(Type base, GenericSignature sig,
536+
const ValueDecl *forDecl);
524537
};
525538

526539
} // end namespace Mangle

include/swift/Demangling/DemangleNodes.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ NODE(FunctionSignatureSpecializationReturn)
9898
NODE(FunctionSignatureSpecializationParamKind)
9999
NODE(FunctionSignatureSpecializationParamPayload)
100100
NODE(FunctionType)
101+
NODE(ConstrainedExistential)
102+
NODE(ConstrainedExistentialRequirementList)
103+
NODE(ConstrainedExistentialSelf)
101104
NODE(GenericPartialSpecialization)
102105
NODE(GenericPartialSpecializationNotReAbstracted)
103106
NODE(GenericProtocolWitnessTable)
@@ -170,7 +173,6 @@ NODE(EscapingObjCBlock)
170173
CONTEXT_NODE(OtherNominalType)
171174
CONTEXT_NODE(OwningAddressor)
172175
CONTEXT_NODE(OwningMutableAddressor)
173-
NODE(ParameterizedProtocol)
174176
NODE(PartialApplyForwarder)
175177
NODE(PartialApplyObjCForwarder)
176178
NODE(PostfixOperator)

include/swift/Demangling/Demangler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,8 @@ class Demangler : public NodeFactory {
580580
NodePointer demangleIndexSubset();
581581
NodePointer demangleDifferentiableFunctionType();
582582

583+
NodePointer demangleConstrainedExistentialRequirementList();
584+
583585
bool demangleBoundGenerics(Vector<NodePointer> &TypeListList,
584586
NodePointer &RetroactiveConformances);
585587

include/swift/Demangling/TypeDecoder.h

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ class TypeDecoder {
713713
forRequirement);
714714
}
715715

716-
case NodeKind::ParameterizedProtocol: {
716+
case NodeKind::ConstrainedExistential: {
717717
if (Node->getNumChildren() < 2)
718718
return MAKE_NODE_TYPE_ERROR(Node,
719719
"fewer children (%zu) than required (2)",
@@ -723,23 +723,20 @@ class TypeDecoder {
723723
if (protocolType.isError())
724724
return protocolType;
725725

726-
llvm::SmallVector<BuiltType, 8> args;
726+
llvm::SmallVector<BuiltRequirement, 8> requirements;
727727

728-
const auto &genericArgs = Node->getChild(1);
729-
if (genericArgs->getKind() != NodeKind::TypeList)
730-
return MAKE_NODE_TYPE_ERROR0(genericArgs, "is not TypeList");
728+
auto *reqts = Node->getChild(1);
729+
if (reqts->getKind() != NodeKind::ConstrainedExistentialRequirementList)
730+
return MAKE_NODE_TYPE_ERROR0(reqts, "is not requirement list");
731731

732-
for (auto genericArg : *genericArgs) {
733-
auto paramType = decodeMangledType(genericArg, depth + 1,
734-
/*forRequirement=*/false);
735-
if (paramType.isError())
736-
return paramType;
737-
args.push_back(paramType.getType());
738-
}
732+
decodeRequirement<BuiltType, BuiltRequirement, BuiltLayoutConstraint,
733+
BuilderType>(reqts, requirements, Builder);
739734

740-
return Builder.createParameterizedProtocolType(protocolType.getType(),
741-
args);
735+
return Builder.createConstrainedExistentialType(protocolType.getType(),
736+
requirements);
742737
}
738+
case NodeKind::ConstrainedExistentialSelf:
739+
return Builder.createGenericTypeParameterType(/*depth*/ 0, /*index*/ 0);
743740

744741
case NodeKind::Protocol:
745742
case NodeKind::ProtocolSymbolicReference: {

include/swift/Reflection/TypeRef.h

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -563,39 +563,48 @@ class ProtocolCompositionTypeRef final : public TypeRef {
563563
}
564564
};
565565

566-
class ParameterizedProtocolTypeRef final : public TypeRef {
566+
class ConstrainedExistentialTypeRef final : public TypeRef {
567567
const ProtocolCompositionTypeRef *Base;
568-
std::vector<const TypeRef *> Args;
568+
std::vector<TypeRefRequirement> Requirements;
569569

570570
static TypeRefID Profile(const ProtocolCompositionTypeRef *Protocol,
571-
std::vector<const TypeRef *> Args) {
571+
std::vector<TypeRefRequirement> Requirements) {
572572
TypeRefID ID;
573573
ID.addPointer(Protocol);
574-
for (auto Arg : Args) {
575-
ID.addPointer(Arg);
574+
for (auto reqt : Requirements) {
575+
ID.addPointer(reqt.getFirstType());
576+
if (reqt.getKind() != RequirementKind::Layout)
577+
ID.addPointer(reqt.getSecondType());
578+
else
579+
ID.addInteger(
580+
unsigned(0)); // FIXME: Layout constraints aren't implemented yet
581+
ID.addInteger(unsigned(reqt.getKind()));
576582
}
577583
return ID;
578584
}
579585

580586
public:
581-
ParameterizedProtocolTypeRef(const ProtocolCompositionTypeRef *Protocol,
582-
std::vector<const TypeRef *> Args)
583-
: TypeRef(TypeRefKind::ParameterizedProtocol), Base(Protocol),
584-
Args(Args) {}
587+
ConstrainedExistentialTypeRef(const ProtocolCompositionTypeRef *Protocol,
588+
std::vector<TypeRefRequirement> Requirements)
589+
: TypeRef(TypeRefKind::ConstrainedExistential), Base(Protocol),
590+
Requirements(Requirements) {}
585591

586592
template <typename Allocator>
587-
static const ParameterizedProtocolTypeRef *
593+
static const ConstrainedExistentialTypeRef *
588594
create(Allocator &A, const ProtocolCompositionTypeRef *Protocol,
589-
std::vector<const TypeRef *> Args) {
590-
FIND_OR_CREATE_TYPEREF(A, ParameterizedProtocolTypeRef, Protocol, Args);
595+
std::vector<TypeRefRequirement> Requirements) {
596+
FIND_OR_CREATE_TYPEREF(A, ConstrainedExistentialTypeRef, Protocol,
597+
Requirements);
591598
}
592599

593600
const ProtocolCompositionTypeRef *getBase() const { return Base; }
594601

595-
const std::vector<const TypeRef *> &getArgs() const { return Args; }
602+
const std::vector<TypeRefRequirement> &getRequirements() const {
603+
return Requirements;
604+
}
596605

597606
static bool classof(const TypeRef *TR) {
598-
return TR->getKind() == TypeRefKind::ParameterizedProtocol;
607+
return TR->getKind() == TypeRefKind::ConstrainedExistential;
599608
}
600609
};
601610

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -650,13 +650,12 @@ class TypeRefBuilder {
650650
isClassBound);
651651
}
652652

653-
const ParameterizedProtocolTypeRef *
654-
createParameterizedProtocolType(const TypeRef *base,
655-
llvm::ArrayRef<const TypeRef *> args) {
653+
const ConstrainedExistentialTypeRef *createConstrainedExistentialType(
654+
const TypeRef *base, llvm::ArrayRef<BuiltRequirement> constraints) {
656655
auto *baseProto = llvm::dyn_cast<ProtocolCompositionTypeRef>(base);
657656
if (!baseProto)
658657
return nullptr;
659-
return ParameterizedProtocolTypeRef::create(*this, baseProto, args);
658+
return ConstrainedExistentialTypeRef::create(*this, baseProto, constraints);
660659
}
661660

662661
const ExistentialMetatypeTypeRef *createExistentialMetatypeType(

include/swift/Reflection/TypeRefs.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ TYPEREF(BoundGeneric, TypeRef)
2222
TYPEREF(Tuple, TypeRef)
2323
TYPEREF(Function, TypeRef)
2424
TYPEREF(ProtocolComposition, TypeRef)
25-
TYPEREF(ParameterizedProtocol, TypeRef)
25+
TYPEREF(ConstrainedExistential, TypeRef)
2626
TYPEREF(Metatype, TypeRef)
2727
TYPEREF(ExistentialMetatype, TypeRef)
2828
TYPEREF(GenericTypeParameter, TypeRef)

lib/AST/ASTDemangler.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -625,12 +625,38 @@ Type ASTBuilder::createExistentialMetatypeType(Type instance,
625625
getMetatypeRepresentation(*repr));
626626
}
627627

628-
Type ASTBuilder::createParameterizedProtocolType(Type base,
629-
ArrayRef<Type> args) {
628+
Type ASTBuilder::createConstrainedExistentialType(
629+
Type base, ArrayRef<BuiltRequirement> constraints) {
630+
// FIXME: Generalize to other kinds of bases.
630631
if (!base->getAs<ProtocolType>())
631632
return Type();
632-
return ParameterizedProtocolType::get(base->getASTContext(),
633-
base->castTo<ProtocolType>(), args);
633+
auto baseTy = base->castTo<ProtocolType>();
634+
auto baseDecl = baseTy->getDecl();
635+
llvm::SmallDenseMap<Identifier, Type> cmap;
636+
for (const auto &req : constraints) {
637+
switch (req.getKind()) {
638+
case RequirementKind::Conformance:
639+
case RequirementKind::Superclass:
640+
case RequirementKind::Layout:
641+
continue;
642+
643+
case RequirementKind::SameType:
644+
if (auto *DMT = req.getFirstType()->getAs<DependentMemberType>())
645+
if (baseDecl->getAssociatedType(DMT->getName()))
646+
cmap[DMT->getName()] = req.getSecondType();
647+
}
648+
}
649+
llvm::SmallVector<Type, 4> args;
650+
for (auto *assocTy : baseDecl->getPrimaryAssociatedTypes()) {
651+
auto argTy = cmap.find(assocTy->getName());
652+
if (argTy == cmap.end()) {
653+
return Type();
654+
}
655+
args.push_back(argTy->getSecond());
656+
}
657+
auto constrainedBase =
658+
ParameterizedProtocolType::get(base->getASTContext(), baseTy, args);
659+
return ExistentialType::get(constrainedBase);
634660
}
635661

636662
Type ASTBuilder::createMetatypeType(Type instance,

0 commit comments

Comments
 (0)