Skip to content

Commit 84c5d3e

Browse files
committed
[GSB] Start tracking source locations for requirements within protocols.
Start reshuffling RequirementSource to store more information about requirements in protocols. As a small step, track the source locations for requirements written within the protocols themselves. Note: there's a QoI regression here where we get duplicated diagnostics (due to multiple generic signature builders being built from a bad signature).
1 parent 6c9394a commit 84c5d3e

File tree

4 files changed

+171
-170
lines changed

4 files changed

+171
-170
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 62 additions & 66 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;
@@ -479,7 +483,8 @@ class GenericSignatureBuilder {
479483
/// Requirement sources are uniqued within a generic signature builder.
480484
class GenericSignatureBuilder::RequirementSource final
481485
: public llvm::FoldingSetNode,
482-
private llvm::TrailingObjects<RequirementSource, PotentialArchetype *> {
486+
private llvm::TrailingObjects<RequirementSource, ProtocolDecl *,
487+
WrittenRequirementLoc> {
483488

484489
friend class FloatingRequirementSource;
485490

@@ -549,8 +554,6 @@ class GenericSignatureBuilder::RequirementSource final
549554
/// The kind of storage we have.
550555
enum class StorageKind : uint8_t {
551556
RootArchetype,
552-
TypeRepr,
553-
RequirementRepr,
554557
ProtocolDecl,
555558
ProtocolConformance,
556559
AssociatedTypeDecl,
@@ -559,17 +562,14 @@ class GenericSignatureBuilder::RequirementSource final
559562
/// The kind of storage we have.
560563
const StorageKind storageKind;
561564

565+
/// Whether there is a trailing written requirement location.
566+
const bool hasTrailingWrittenRequirementLoc;
567+
562568
/// The actual storage, described by \c storageKind.
563569
union {
564570
/// The root archetype.
565571
PotentialArchetype *rootArchetype;
566572

567-
/// The type representation describing where the requirement came from.
568-
const TypeRepr *typeRepr;
569-
570-
/// Where a requirement came from.
571-
const RequirementRepr *requirementRepr;
572-
573573
/// The protocol being described.
574574
ProtocolDecl *protocol;
575575

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

583583
friend TrailingObjects;
584584

585-
/// The trailing potential archetype, for
586-
size_t numTrailingObjects(OverloadToken<PotentialArchetype *>) const {
585+
/// The trailing protocol declaration, if there is one.
586+
size_t numTrailingObjects(OverloadToken<ProtocolDecl *>) const {
587587
switch (kind) {
588588
case RequirementSignatureSelf:
589589
return 1;
590590

591591
case Explicit:
592592
case Inferred:
593-
return storageKind == StorageKind::RootArchetype ? 0 : 1;
594-
595593
case NestedTypeNameMatch:
596594
case ProtocolRequirement:
597595
case Superclass:
@@ -603,16 +601,25 @@ class GenericSignatureBuilder::RequirementSource final
603601
llvm_unreachable("Unhandled RequirementSourceKind in switch.");
604602
}
605603

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

610613
/// Retrieve the opaque storage as a single pointer, for use in uniquing.
611-
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;
612619

613-
/// 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
614621
/// uniquing.
615-
const void *getExtraOpaqueStorage() const;
622+
const void *getOpaqueStorage3() const;
616623

617624
/// Whether this kind of requirement source is a root.
618625
static bool isRootKind(Kind kind) {
@@ -640,53 +647,43 @@ class GenericSignatureBuilder::RequirementSource final
640647
/// requirement source with one of the "root" kinds.
641648
const RequirementSource * const parent;
642649

643-
RequirementSource(Kind kind, const RequirementSource *parent,
644-
PotentialArchetype *rootArchetype)
645-
: kind(kind), storageKind(StorageKind::RootArchetype), parent(parent) {
646-
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
647-
"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) {
648656
assert(isAcceptableStorageKind(kind, storageKind) &&
649657
"RequirementSource kind/storageKind mismatch");
650658

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

654666
RequirementSource(Kind kind, const RequirementSource *parent,
655-
const TypeRepr *typeRepr)
656-
: kind(kind), storageKind(StorageKind::TypeRepr), parent(parent) {
657-
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
658-
"Root RequirementSource should not have parent (or vice versa)");
659-
assert(isAcceptableStorageKind(kind, storageKind) &&
660-
"RequirementSource kind/storageKind mismatch");
667+
ProtocolDecl *protocol,
668+
WrittenRequirementLoc writtenReqLoc)
669+
: kind(kind), storageKind(StorageKind::ProtocolDecl),
670+
hasTrailingWrittenRequirementLoc(!writtenReqLoc.isNull()),
661671

662-
storage.typeRepr = typeRepr;
663-
}
664-
665-
RequirementSource(Kind kind, const RequirementSource *parent,
666-
const RequirementRepr *requirementRepr)
667-
: kind(kind), storageKind(StorageKind::RequirementRepr), parent(parent) {
668-
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
669-
"Root RequirementSource should not have parent (or vice versa)");
670-
assert(isAcceptableStorageKind(kind, storageKind) &&
671-
"RequirementSource kind/storageKind mismatch");
672-
673-
storage.requirementRepr = requirementRepr;
674-
}
675-
676-
RequirementSource(Kind kind, const RequirementSource *parent,
677-
ProtocolDecl *protocol)
678-
: kind(kind), storageKind(StorageKind::ProtocolDecl), parent(parent) {
672+
parent(parent) {
679673
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
680674
"Root RequirementSource should not have parent (or vice versa)");
681675
assert(isAcceptableStorageKind(kind, storageKind) &&
682676
"RequirementSource kind/storageKind mismatch");
683677

684678
storage.protocol = protocol;
679+
if (hasTrailingWrittenRequirementLoc)
680+
getTrailingObjects<WrittenRequirementLoc>()[0] = writtenReqLoc;
685681
}
686682

687683
RequirementSource(Kind kind, const RequirementSource *parent,
688684
ProtocolConformance *conformance)
689685
: kind(kind), storageKind(StorageKind::ProtocolConformance),
686+
hasTrailingWrittenRequirementLoc(false),
690687
parent(parent) {
691688
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
692689
"Root RequirementSource should not have parent (or vice versa)");
@@ -699,6 +696,7 @@ class GenericSignatureBuilder::RequirementSource final
699696
RequirementSource(Kind kind, const RequirementSource *parent,
700697
AssociatedTypeDecl *assocType)
701698
: kind(kind), storageKind(StorageKind::AssociatedTypeDecl),
699+
hasTrailingWrittenRequirementLoc(false),
702700
parent(parent) {
703701
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
704702
"Root RequirementSource should not have parent (or vice versa)");
@@ -713,15 +711,9 @@ class GenericSignatureBuilder::RequirementSource final
713711
static const RequirementSource *forAbstract(PotentialArchetype *root);
714712

715713
/// Retrieve a requirement source representing an explicit requirement
716-
/// stated in an 'inheritance' clause.
714+
/// stated in an 'inheritance' or 'where' clause.
717715
static const RequirementSource *forExplicit(PotentialArchetype *root,
718-
const TypeRepr *typeRepr);
719-
720-
/// Retrieve a requirement source representing an explicit requirement
721-
/// stated in an 'where' clause.
722-
static const RequirementSource *forExplicit(
723-
PotentialArchetype *root,
724-
const RequirementRepr *requirementRepr);
716+
WrittenRequirementLoc writtenLoc);
725717

726718
/// Retrieve a requirement source representing a requirement that is
727719
/// inferred from some part of a generic declaration's signature, e.g., the
@@ -744,7 +736,9 @@ class GenericSignatureBuilder::RequirementSource final
744736
/// requirement of the given protocol described by the parent.
745737
const RequirementSource *viaAbstractProtocolRequirement(
746738
GenericSignatureBuilder &builder,
747-
ProtocolDecl *protocol) const;
739+
ProtocolDecl *protocol,
740+
WrittenRequirementLoc writtenLoc =
741+
WrittenRequirementLoc()) const;
748742

749743
public:
750744
/// A requirement source that describes that a requirement that is resolved
@@ -799,15 +793,17 @@ class GenericSignatureBuilder::RequirementSource final
799793

800794
/// Retrieve the type representation for this requirement, if there is one.
801795
const TypeRepr *getTypeRepr() const {
802-
if (storageKind != StorageKind::TypeRepr) return nullptr;
803-
return storage.typeRepr;
796+
if (!hasTrailingWrittenRequirementLoc) return nullptr;
797+
return getTrailingObjects<WrittenRequirementLoc>()[0]
798+
.dyn_cast<const TypeRepr *>();
804799
}
805800

806801
/// Retrieve the requirement representation for this requirement, if there is
807802
/// one.
808803
const RequirementRepr *getRequirementRepr() const {
809-
if (storageKind != StorageKind::RequirementRepr) return nullptr;
810-
return storage.requirementRepr;
804+
if (!hasTrailingWrittenRequirementLoc) return nullptr;
805+
return getTrailingObjects<WrittenRequirementLoc>()[0]
806+
.dyn_cast<const RequirementRepr *>();
811807
}
812808

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

829825
/// Profiling support for \c FoldingSet.
830826
void Profile(llvm::FoldingSetNodeID &ID) {
831-
Profile(ID, kind, parent, getOpaqueStorage(), getExtraOpaqueStorage());
827+
Profile(ID, kind, parent, getOpaqueStorage1(), getOpaqueStorage2(),
828+
getOpaqueStorage3());
832829
}
833830

834831
/// Profiling support for \c FoldingSet.
835832
static void Profile(llvm::FoldingSetNodeID &ID, Kind kind,
836-
const RequirementSource *parent, const void *storage,
837-
const void *extraStorage) {
833+
const RequirementSource *parent, const void *storage1,
834+
const void *storage2, const void *storage3) {
838835
ID.AddInteger(kind);
839836
ID.AddPointer(parent);
840-
ID.AddPointer(storage);
841-
ID.AddPointer(extraStorage);
837+
ID.AddPointer(storage1);
838+
ID.AddPointer(storage2);
839+
ID.AddPointer(storage3);
842840
}
843841

844842
LLVM_ATTRIBUTE_DEPRECATED(
@@ -881,7 +879,7 @@ class GenericSignatureBuilder::FloatingRequirementSource {
881879
// Additional storage for an abstract protocol requirement.
882880
struct {
883881
ProtocolDecl *protocol = nullptr;
884-
llvm::PointerUnion<const TypeRepr *, const RequirementRepr *> written;
882+
WrittenRequirementLoc written;
885883
} abstractProtocolReq;
886884

887885
FloatingRequirementSource(Kind kind, Storage storage)
@@ -920,9 +918,7 @@ class GenericSignatureBuilder::FloatingRequirementSource {
920918
static FloatingRequirementSource viaAbstractProtocolRequirement(
921919
const RequirementSource *base,
922920
ProtocolDecl *inProtocol,
923-
llvm::PointerUnion<
924-
const TypeRepr *,
925-
const RequirementRepr *> written) {
921+
WrittenRequirementLoc written) {
926922
FloatingRequirementSource result{ AbstractProtocol, base };
927923
result.abstractProtocolReq.protocol = inProtocol;
928924
result.abstractProtocolReq.written = written;

0 commit comments

Comments
 (0)