Skip to content

Commit 775a8bc

Browse files
authored
Merge pull request #7906 from DougGregor/requirement-source-sourcelocs
2 parents fc6c876 + 84c5d3e commit 775a8bc

File tree

4 files changed

+240
-187
lines changed

4 files changed

+240
-187
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 99 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ class GenericSignatureBuilder {
7474
using RequirementRHS =
7575
llvm::PointerUnion3<Type, PotentialArchetype *, LayoutConstraint>;
7676

77+
/// The location of a requirement as written somewhere in the source.
78+
typedef llvm::PointerUnion<const TypeRepr *, const RequirementRepr *>
79+
WrittenRequirementLoc;
80+
7781
class RequirementSource;
7882

7983
class FloatingRequirementSource;
@@ -306,13 +310,19 @@ class GenericSignatureBuilder {
306310
/// \brief Add a new generic parameter for which there may be requirements.
307311
void addGenericParameter(GenericTypeParamType *GenericParam);
308312

313+
/// \brief Add a new requirement.
314+
///
315+
/// \returns true if this requirement makes the set of requirements
316+
/// inconsistent, in which case a diagnostic will have been issued.
317+
bool addRequirement(const RequirementRepr *req);
318+
309319
/// \brief Add a new requirement.
310320
///
311321
/// \returns true if this requirement makes the set of requirements
312322
/// inconsistent, in which case a diagnostic will have been issued.
313323
bool addRequirement(const RequirementRepr *Req,
314-
const RequirementSource *source = nullptr,
315-
const SubstitutionMap *subMap = nullptr);
324+
FloatingRequirementSource source,
325+
const SubstitutionMap *subMap);
316326

317327
/// \brief Add an already-checked requirement.
318328
///
@@ -473,7 +483,10 @@ class GenericSignatureBuilder {
473483
/// Requirement sources are uniqued within a generic signature builder.
474484
class GenericSignatureBuilder::RequirementSource final
475485
: public llvm::FoldingSetNode,
476-
private llvm::TrailingObjects<RequirementSource, PotentialArchetype *> {
486+
private llvm::TrailingObjects<RequirementSource, ProtocolDecl *,
487+
WrittenRequirementLoc> {
488+
489+
friend class FloatingRequirementSource;
477490

478491
public:
479492
enum Kind : uint8_t {
@@ -541,8 +554,6 @@ class GenericSignatureBuilder::RequirementSource final
541554
/// The kind of storage we have.
542555
enum class StorageKind : uint8_t {
543556
RootArchetype,
544-
TypeRepr,
545-
RequirementRepr,
546557
ProtocolDecl,
547558
ProtocolConformance,
548559
AssociatedTypeDecl,
@@ -551,17 +562,14 @@ class GenericSignatureBuilder::RequirementSource final
551562
/// The kind of storage we have.
552563
const StorageKind storageKind;
553564

565+
/// Whether there is a trailing written requirement location.
566+
const bool hasTrailingWrittenRequirementLoc;
567+
554568
/// The actual storage, described by \c storageKind.
555569
union {
556570
/// The root archetype.
557571
PotentialArchetype *rootArchetype;
558572

559-
/// The type representation describing where the requirement came from.
560-
const TypeRepr *typeRepr;
561-
562-
/// Where a requirement came from.
563-
const RequirementRepr *requirementRepr;
564-
565573
/// The protocol being described.
566574
ProtocolDecl *protocol;
567575

@@ -574,16 +582,14 @@ class GenericSignatureBuilder::RequirementSource final
574582

575583
friend TrailingObjects;
576584

577-
/// The trailing potential archetype, for
578-
size_t numTrailingObjects(OverloadToken<PotentialArchetype *>) const {
585+
/// The trailing protocol declaration, if there is one.
586+
size_t numTrailingObjects(OverloadToken<ProtocolDecl *>) const {
579587
switch (kind) {
580588
case RequirementSignatureSelf:
581589
return 1;
582590

583591
case Explicit:
584592
case Inferred:
585-
return storageKind == StorageKind::RootArchetype ? 0 : 1;
586-
587593
case NestedTypeNameMatch:
588594
case ProtocolRequirement:
589595
case Superclass:
@@ -595,16 +601,25 @@ class GenericSignatureBuilder::RequirementSource final
595601
llvm_unreachable("Unhandled RequirementSourceKind in switch.");
596602
}
597603

604+
/// The trailing written requirement location, if there is one.
605+
size_t numTrailingObjects(OverloadToken<WrittenRequirementLoc>) const {
606+
return hasTrailingWrittenRequirementLoc ? 1 : 0;
607+
}
608+
598609
/// Determines whether we have been provided with an acceptable storage kind
599610
/// for the given requirement source kind.
600611
static bool isAcceptableStorageKind(Kind kind, StorageKind storageKind);
601612

602613
/// Retrieve the opaque storage as a single pointer, for use in uniquing.
603-
const void *getOpaqueStorage() const;
614+
const void *getOpaqueStorage1() const;
615+
616+
/// Retrieve the second opaque storage as a single pointer, for use in
617+
/// uniquing.
618+
const void *getOpaqueStorage2() const;
604619

605-
/// Retrieve the extra opaque storage as a single pointer, for use in
620+
/// Retrieve the third opaque storage as a single pointer, for use in
606621
/// uniquing.
607-
const void *getExtraOpaqueStorage() const;
622+
const void *getOpaqueStorage3() const;
608623

609624
/// Whether this kind of requirement source is a root.
610625
static bool isRootKind(Kind kind) {
@@ -632,53 +647,43 @@ class GenericSignatureBuilder::RequirementSource final
632647
/// requirement source with one of the "root" kinds.
633648
const RequirementSource * const parent;
634649

635-
RequirementSource(Kind kind, const RequirementSource *parent,
636-
PotentialArchetype *rootArchetype)
637-
: kind(kind), storageKind(StorageKind::RootArchetype), parent(parent) {
638-
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
639-
"Root RequirementSource should not have parent (or vice versa)");
650+
RequirementSource(Kind kind, PotentialArchetype *rootArchetype,
651+
ProtocolDecl *protocol,
652+
WrittenRequirementLoc writtenReqLoc)
653+
: kind(kind), storageKind(StorageKind::RootArchetype),
654+
hasTrailingWrittenRequirementLoc(!writtenReqLoc.isNull()),
655+
parent(nullptr) {
640656
assert(isAcceptableStorageKind(kind, storageKind) &&
641657
"RequirementSource kind/storageKind mismatch");
642658

643659
storage.rootArchetype = rootArchetype;
660+
if (kind == RequirementSignatureSelf)
661+
getTrailingObjects<ProtocolDecl *>()[0] = protocol;
662+
if (hasTrailingWrittenRequirementLoc)
663+
getTrailingObjects<WrittenRequirementLoc>()[0] = writtenReqLoc;
644664
}
645665

646666
RequirementSource(Kind kind, const RequirementSource *parent,
647-
const TypeRepr *typeRepr)
648-
: kind(kind), storageKind(StorageKind::TypeRepr), parent(parent) {
649-
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
650-
"Root RequirementSource should not have parent (or vice versa)");
651-
assert(isAcceptableStorageKind(kind, storageKind) &&
652-
"RequirementSource kind/storageKind mismatch");
667+
ProtocolDecl *protocol,
668+
WrittenRequirementLoc writtenReqLoc)
669+
: kind(kind), storageKind(StorageKind::ProtocolDecl),
670+
hasTrailingWrittenRequirementLoc(!writtenReqLoc.isNull()),
653671

654-
storage.typeRepr = typeRepr;
655-
}
656-
657-
RequirementSource(Kind kind, const RequirementSource *parent,
658-
const RequirementRepr *requirementRepr)
659-
: kind(kind), storageKind(StorageKind::RequirementRepr), parent(parent) {
660-
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
661-
"Root RequirementSource should not have parent (or vice versa)");
662-
assert(isAcceptableStorageKind(kind, storageKind) &&
663-
"RequirementSource kind/storageKind mismatch");
664-
665-
storage.requirementRepr = requirementRepr;
666-
}
667-
668-
RequirementSource(Kind kind, const RequirementSource *parent,
669-
ProtocolDecl *protocol)
670-
: kind(kind), storageKind(StorageKind::ProtocolDecl), parent(parent) {
672+
parent(parent) {
671673
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
672674
"Root RequirementSource should not have parent (or vice versa)");
673675
assert(isAcceptableStorageKind(kind, storageKind) &&
674676
"RequirementSource kind/storageKind mismatch");
675677

676678
storage.protocol = protocol;
679+
if (hasTrailingWrittenRequirementLoc)
680+
getTrailingObjects<WrittenRequirementLoc>()[0] = writtenReqLoc;
677681
}
678682

679683
RequirementSource(Kind kind, const RequirementSource *parent,
680684
ProtocolConformance *conformance)
681685
: kind(kind), storageKind(StorageKind::ProtocolConformance),
686+
hasTrailingWrittenRequirementLoc(false),
682687
parent(parent) {
683688
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
684689
"Root RequirementSource should not have parent (or vice versa)");
@@ -691,6 +696,7 @@ class GenericSignatureBuilder::RequirementSource final
691696
RequirementSource(Kind kind, const RequirementSource *parent,
692697
AssociatedTypeDecl *assocType)
693698
: kind(kind), storageKind(StorageKind::AssociatedTypeDecl),
699+
hasTrailingWrittenRequirementLoc(false),
694700
parent(parent) {
695701
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
696702
"Root RequirementSource should not have parent (or vice versa)");
@@ -705,15 +711,9 @@ class GenericSignatureBuilder::RequirementSource final
705711
static const RequirementSource *forAbstract(PotentialArchetype *root);
706712

707713
/// Retrieve a requirement source representing an explicit requirement
708-
/// stated in an 'inheritance' clause.
714+
/// stated in an 'inheritance' or 'where' clause.
709715
static const RequirementSource *forExplicit(PotentialArchetype *root,
710-
const TypeRepr *typeRepr);
711-
712-
/// Retrieve a requirement source representing an explicit requirement
713-
/// stated in an 'where' clause.
714-
static const RequirementSource *forExplicit(
715-
PotentialArchetype *root,
716-
const RequirementRepr *requirementRepr);
716+
WrittenRequirementLoc writtenLoc);
717717

718718
/// Retrieve a requirement source representing a requirement that is
719719
/// inferred from some part of a generic declaration's signature, e.g., the
@@ -731,12 +731,16 @@ class GenericSignatureBuilder::RequirementSource final
731731
static const RequirementSource *forNestedTypeNameMatch(
732732
PotentialArchetype *root);
733733

734+
private:
734735
/// A requirement source that describes that a requirement comes from a
735736
/// requirement of the given protocol described by the parent.
736737
const RequirementSource *viaAbstractProtocolRequirement(
737738
GenericSignatureBuilder &builder,
738-
ProtocolDecl *protocol) const;
739+
ProtocolDecl *protocol,
740+
WrittenRequirementLoc writtenLoc =
741+
WrittenRequirementLoc()) const;
739742

743+
public:
740744
/// A requirement source that describes that a requirement that is resolved
741745
/// via a superclass requirement.
742746
const RequirementSource *viaSuperclass(
@@ -789,15 +793,17 @@ class GenericSignatureBuilder::RequirementSource final
789793

790794
/// Retrieve the type representation for this requirement, if there is one.
791795
const TypeRepr *getTypeRepr() const {
792-
if (storageKind != StorageKind::TypeRepr) return nullptr;
793-
return storage.typeRepr;
796+
if (!hasTrailingWrittenRequirementLoc) return nullptr;
797+
return getTrailingObjects<WrittenRequirementLoc>()[0]
798+
.dyn_cast<const TypeRepr *>();
794799
}
795800

796801
/// Retrieve the requirement representation for this requirement, if there is
797802
/// one.
798803
const RequirementRepr *getRequirementRepr() const {
799-
if (storageKind != StorageKind::RequirementRepr) return nullptr;
800-
return storage.requirementRepr;
804+
if (!hasTrailingWrittenRequirementLoc) return nullptr;
805+
return getTrailingObjects<WrittenRequirementLoc>()[0]
806+
.dyn_cast<const RequirementRepr *>();
801807
}
802808

803809
/// Retrieve the protocol for this requirement, if there is one.
@@ -818,17 +824,19 @@ class GenericSignatureBuilder::RequirementSource final
818824

819825
/// Profiling support for \c FoldingSet.
820826
void Profile(llvm::FoldingSetNodeID &ID) {
821-
Profile(ID, kind, parent, getOpaqueStorage(), getExtraOpaqueStorage());
827+
Profile(ID, kind, parent, getOpaqueStorage1(), getOpaqueStorage2(),
828+
getOpaqueStorage3());
822829
}
823830

824831
/// Profiling support for \c FoldingSet.
825832
static void Profile(llvm::FoldingSetNodeID &ID, Kind kind,
826-
const RequirementSource *parent, const void *storage,
827-
const void *extraStorage) {
833+
const RequirementSource *parent, const void *storage1,
834+
const void *storage2, const void *storage3) {
828835
ID.AddInteger(kind);
829836
ID.AddPointer(parent);
830-
ID.AddPointer(storage);
831-
ID.AddPointer(extraStorage);
837+
ID.AddPointer(storage1);
838+
ID.AddPointer(storage2);
839+
ID.AddPointer(storage3);
832840
}
833841

834842
LLVM_ATTRIBUTE_DEPRECATED(
@@ -857,7 +865,9 @@ class GenericSignatureBuilder::FloatingRequirementSource {
857865
/// An explicit requirement source lacking a root.
858866
Explicit,
859867
/// An inferred requirement source lacking a root.
860-
Inferred
868+
Inferred,
869+
/// A requirement source augmented by an abstract protocol requirement
870+
AbstractProtocol,
861871
} kind;
862872

863873
using Storage =
@@ -866,6 +876,12 @@ class GenericSignatureBuilder::FloatingRequirementSource {
866876

867877
Storage storage;
868878

879+
// Additional storage for an abstract protocol requirement.
880+
struct {
881+
ProtocolDecl *protocol = nullptr;
882+
WrittenRequirementLoc written;
883+
} abstractProtocolReq;
884+
869885
FloatingRequirementSource(Kind kind, Storage storage)
870886
: kind(kind), storage(storage) { }
871887

@@ -891,6 +907,24 @@ class GenericSignatureBuilder::FloatingRequirementSource {
891907
return { Inferred, typeRepr };
892908
}
893909

910+
static FloatingRequirementSource viaAbstractProtocolRequirement(
911+
const RequirementSource *base,
912+
ProtocolDecl *inProtocol) {
913+
FloatingRequirementSource result{ AbstractProtocol, base };
914+
result.abstractProtocolReq.protocol = inProtocol;
915+
return result;
916+
}
917+
918+
static FloatingRequirementSource viaAbstractProtocolRequirement(
919+
const RequirementSource *base,
920+
ProtocolDecl *inProtocol,
921+
WrittenRequirementLoc written) {
922+
FloatingRequirementSource result{ AbstractProtocol, base };
923+
result.abstractProtocolReq.protocol = inProtocol;
924+
result.abstractProtocolReq.written = written;
925+
return result;
926+
}
927+
894928
/// Retrieve the complete requirement source rooted at the given potential
895929
/// archetype.
896930
const RequirementSource *getSource(PotentialArchetype *pa) const;

0 commit comments

Comments
 (0)