Skip to content

Commit 0af627b

Browse files
committed
Mangling: handle inverse requirements
1 parent a2ec1da commit 0af627b

22 files changed

+778
-72
lines changed

docs/ABI/Mangling.rst

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -680,12 +680,14 @@ Types
680680
METATYPE-REPR ::= 'T' // Thick metatype representation
681681
METATYPE-REPR ::= 'o' // ObjC metatype representation
682682

683+
existential-layout ::= protocol-list 'p' // existential layout
684+
existential-layout ::= protocol-list superclass 'Xc' // existential layout with superclass
685+
existential-layout ::= protocol-list 'Xl' // existential layout with AnyObject
686+
683687
type ::= associated-type
684688
type ::= any-generic-type
685-
type ::= protocol-list 'p' // existential type
686-
type ::= protocol-list superclass 'Xc' // existential type with superclass
687-
type ::= protocol-list 'Xl' // existential type with AnyObject
688-
type ::= protocol-list requirement* '_' 'XP' // constrained existential type
689+
type ::= existential-layout // existential type
690+
type ::= existential-layout requirement '_' requirement* 'XP' // constrained existential type
689691
type ::= type-list 't' // tuple
690692
type ::= type generic-signature 'u' // generic type
691693
type ::= 'x' // generic param, depth=0, idx=0
@@ -925,13 +927,19 @@ now codified into the ABI; the index 0 is therefore reserved.
925927

926928
generic-param-pack-marker ::= 'Rv' GENERIC_PARAM-INDEX // generic parameter pack marker
927929

930+
INVERTIBLE-KIND ::= 'c' // Copyable
931+
INVERTIBLE-KIND ::= 'e' // Escapable
932+
928933
GENERIC-PARAM-COUNT ::= 'z' // zero parameters
929934
GENERIC-PARAM-COUNT ::= INDEX // N+1 parameters
930935

931936
requirement ::= protocol 'R' GENERIC-PARAM-INDEX // protocol requirement
932937
requirement ::= protocol assoc-type-name 'Rp' GENERIC-PARAM-INDEX // protocol requirement on associated type
933938
requirement ::= protocol assoc-type-list 'RP' GENERIC-PARAM-INDEX // protocol requirement on associated type at depth
934939
requirement ::= protocol substitution 'RQ' // protocol requirement with substitution
940+
#if SWIFT_RUNTIME_VERSION >= 6.0
941+
requirement ::= 'Ri' INVERTIBLE-KIND GENERIC-PARAM-INDEX // inverse requirement
942+
#endif
935943
requirement ::= type 'Rb' GENERIC-PARAM-INDEX // base class requirement
936944
requirement ::= type assoc-type-name 'Rc' GENERIC-PARAM-INDEX // base class requirement on associated type
937945
requirement ::= type assoc-type-list 'RC' GENERIC-PARAM-INDEX // base class requirement on associated type at depth

include/swift/AST/ASTMangler.h

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,14 +452,16 @@ class ASTMangler : public Mangler {
452452

453453
void appendContextOf(const ValueDecl *decl);
454454

455-
void appendContext(const DeclContext *ctx, StringRef useModuleName);
455+
void appendContext(const DeclContext *ctx, StringRef useModuleName,
456+
bool shouldMangleInverseGenerics = false);
456457

457458
void appendModule(const ModuleDecl *module, StringRef useModuleName);
458459

459460
void appendProtocolName(const ProtocolDecl *protocol,
460461
bool allowStandardSubstitution = true);
461462

462-
void appendAnyGenericType(const GenericTypeDecl *decl);
463+
void appendAnyGenericType(const GenericTypeDecl *decl,
464+
bool shouldMangleInverseGenerics = false);
463465

464466
enum FunctionManglingKind {
465467
NoFunctionMangling,
@@ -510,10 +512,22 @@ class ASTMangler : public Mangler {
510512
/// \param contextSig The signature of the known context. This function
511513
/// will only mangle the difference between \c sig and \c contextSig.
512514
///
515+
/// \param skipEquivalenceCheck Whether we should skip the sig == contextSig
516+
/// check. Skipping this check means we will mangle the signature regardless
517+
/// of if the surrounding context has the same signature. This should
518+
/// generally always be false, but there are inverse generic mangling concerns
519+
/// that need to force signature mangling.
520+
///
521+
/// \param shouldMangleInverseGenerics Whether we should append inverse
522+
/// generic requirements to the signature mangling. If @_preInverseGenerics is
523+
/// present do not mangle them in addition to other requirements.
524+
///
513525
/// \returns \c true if a generic signature was appended, \c false
514526
/// if it was empty.
515527
bool appendGenericSignature(GenericSignature sig,
516-
GenericSignature contextSig = nullptr);
528+
GenericSignature contextSig = nullptr,
529+
bool skipEquivalenceCheck = false,
530+
bool shouldMangleInverseGenerics = true);
517531

518532
/// Append a requirement to the mangling.
519533
///
@@ -527,10 +541,21 @@ class ASTMangler : public Mangler {
527541
void appendRequirement(const Requirement &reqt, GenericSignature sig,
528542
bool lhsBaseIsProtocolSelf = false);
529543

544+
/// Append an inverse requirement into the mangling.
545+
///
546+
/// Instead of mangling the presence of an invertible protocol, we mangle
547+
/// their absence, which is what an inverse represents.
548+
///
549+
/// \param req The inverse requirement to mangle.
550+
void appendInverseRequirement(const InverseRequirement &req,
551+
GenericSignature sig,
552+
bool lhsBaseIsProtocolSelf = false);
553+
530554
void appendGenericSignatureParts(GenericSignature sig,
531555
ArrayRef<CanTypeWrapper<GenericTypeParamType>> params,
532556
unsigned initialParamDepth,
533-
ArrayRef<Requirement> requirements);
557+
ArrayRef<Requirement> requirements,
558+
ArrayRef<InverseRequirement> inverseRequirements);
534559

535560
DependentMemberType *dropProtocolFromAssociatedType(DependentMemberType *dmt,
536561
GenericSignature sig);

include/swift/AST/Decl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,6 +1856,10 @@ class ExtensionDecl final : public GenericContext, public Decl,
18561856
/// resiliently moved into the original protocol itself.
18571857
bool isEquivalentToExtendedContext() const;
18581858

1859+
/// Determine whether this extension context is in the same defining module as
1860+
/// the original nominal type context.
1861+
bool isInSameDefiningModule() const;
1862+
18591863
/// Returns the name of the category specified by the \c \@_objcImplementation
18601864
/// attribute, or \c None if the name is invalid or
18611865
/// \c isObjCImplementation() is false.

include/swift/AST/DeclAttr.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,10 @@ SIMPLE_DECL_ATTR(_noObjCBridging, NoObjCBridging,
488488
DECL_ATTR(_distributedThunkTarget, DistributedThunkTarget,
489489
OnAbstractFunction | UserInaccessible | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
490490
156)
491-
LAST_DECL_ATTR(DistributedThunkTarget)
491+
SIMPLE_DECL_ATTR(_preInverseGenerics, PreInverseGenerics,
492+
OnAbstractFunction | OnSubscript | OnVar | UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
493+
157)
494+
LAST_DECL_ATTR(PreInverseGenerics)
492495

493496
#undef DECL_ATTR_ALIAS
494497
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/GenericSignature.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,16 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final
479479
/// Utility wrapper for use when this is an opened existential signature.
480480
Type getExistentialType(Type type) const;
481481

482+
/// Determines if this generic signature is the complete opposite of a generic
483+
/// signature with inverse requirements.
484+
///
485+
/// Given the following 'other' signature (this assumes Equatable: ~Copyable):
486+
/// <T: ~Copyable & Equatable, U: ~Copyable, V: Copyable>
487+
/// returns true iff our generic signature is:
488+
/// <T: Copyable & Equatable, U: Copyable, V: Copyable>
489+
bool areAllRequirementsPositiveInverseRequirementsSatisfying(
490+
GenericSignature other) const;
491+
482492
static void Profile(llvm::FoldingSetNodeID &ID,
483493
ArrayRef<GenericTypeParamType *> genericParams,
484494
ArrayRef<Requirement> requirements);
@@ -560,11 +570,11 @@ void validateGenericSignaturesInModule(ModuleDecl *module);
560570
/// required to be minimal or canonical, and may contain unresolved
561571
/// DependentMemberTypes.
562572
///
563-
/// If \p baseSignature is non-null, the new parameters and requirements
564-
/// are added on; existing requirements of the base signature might become
565-
/// redundant.
566-
///
567-
/// If \p baseSignature is null, build a new signature from scratch.
573+
/// \param baseSignature if non-null, the new parameters and requirements
574+
///// are added on; existing requirements of the base signature might become
575+
///// redundant. Otherwise if null, build a new signature from scratch.
576+
/// \param allowInverses if true, default requirements to Copyable/Escapable are
577+
/// expanded for generic parameters.
568578
GenericSignature buildGenericSignature(
569579
ASTContext &ctx,
570580
GenericSignature baseSignature,

include/swift/AST/Requirement.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ struct InverseRequirement {
251251

252252
InvertibleProtocolKind getKind() const;
253253

254+
/// Linear order on inverse requirements in a generic signature.
255+
int compare(const InverseRequirement &other) const;
256+
254257
/// Appends additional requirements corresponding to defaults for the given
255258
/// generic parameters.
256259
static void expandDefaults(ASTContext &ctx,

include/swift/AST/Types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6007,6 +6007,7 @@ class ProtocolCompositionType final : public TypeBase,
60076007
}
60086008

60096009
InvertibleProtocolSet getInverses() const { return Inverses; }
6010+
bool hasInverse() const { return !Inverses.empty(); }
60106011

60116012
void Profile(llvm::FoldingSetNodeID &ID) {
60126013
Profile(ID, getMembers(), getInverses(), hasExplicitAnyObject());

include/swift/Demangling/DemangleNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,5 +396,7 @@ NODE(OutlinedAssignWithTakeNoValueWitness)
396396
NODE(OutlinedAssignWithCopyNoValueWitness)
397397
NODE(OutlinedDestroyNoValueWitness)
398398

399+
NODE(DependentGenericInverseConformanceRequirement)
400+
399401
#undef CONTEXT_NODE
400402
#undef NODE

include/swift/Demangling/TypeDecoder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,14 @@ void decodeRequirement(NodePointer node,
448448
child->getChild(1), /*forRequirement=*/false);
449449
if (!constraintType)
450450
return;
451+
} else if (child->getKind() ==
452+
Demangle::Node::Kind::DependentGenericInverseConformanceRequirement) {
453+
// FIXME(kavon): this is unimplemented! We should build a PCT here with
454+
// the inverse in it.
455+
return;
451456
}
452457

458+
453459
switch (child->getKind()) {
454460
case Demangle::Node::Kind::DependentGenericConformanceRequirement: {
455461
requirements.push_back(BuiltRequirement(

0 commit comments

Comments
 (0)