Skip to content

Commit 62334e2

Browse files
authored
Merge pull request #37628 from slavapestov/preserve-source-locs-when-rebuilding-signature
GSB: Preserve source locations when rebuilding a generic signature
2 parents 972366d + 294a1ab commit 62334e2

File tree

9 files changed

+312
-290
lines changed

9 files changed

+312
-290
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,9 +2429,6 @@ WARNING(missing_protocol_refinement, none,
24292429
"protocol %0 should be declared to refine %1 due to a same-type constraint on 'Self'",
24302430
(ProtocolDecl *, ProtocolDecl *))
24312431

2432-
ERROR(unsupported_recursive_requirements, none,
2433-
"requirement involves recursion that is not currently supported", ())
2434-
24352432
ERROR(same_type_conflict,none,
24362433
"%select{generic parameter |protocol |}0%1 cannot be equal to both "
24372434
"%2 and %3", (unsigned, Type, Type, Type))

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 60 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,6 @@ class GenericSignatureBuilder {
9898
using RequirementRHS =
9999
llvm::PointerUnion<Type, ProtocolDecl *, LayoutConstraint>;
100100

101-
/// The location of a requirement as written somewhere in the source.
102-
typedef llvm::PointerUnion<const TypeRepr *, const RequirementRepr *>
103-
WrittenRequirementLoc;
104-
105101
class RequirementSource;
106102

107103
class FloatingRequirementSource;
@@ -342,10 +338,8 @@ class GenericSignatureBuilder {
342338
UnresolvedHandlingKind unresolvedHandling);
343339

344340
/// Add any conditional requirements from the given conformance.
345-
///
346-
/// \returns \c true if an error occurred, \c false if not.
347-
bool addConditionalRequirements(ProtocolConformanceRef conformance,
348-
ModuleDecl *inferForModule, SourceLoc loc);
341+
void addConditionalRequirements(ProtocolConformanceRef conformance,
342+
ModuleDecl *inferForModule);
349343

350344
/// Resolve the conformance of the given type to the given protocol when the
351345
/// potential archetype is known to be equivalent to a concrete type.
@@ -630,8 +624,7 @@ class GenericSignatureBuilder {
630624
/// generic signature builder no longer has valid state.
631625
GenericSignature computeGenericSignature(
632626
bool allowConcreteGenericParams = false,
633-
const ProtocolDecl *requirementSignatureSelfProto = nullptr,
634-
bool rebuildingWithoutRedundantConformances = false) &&;
627+
const ProtocolDecl *requirementSignatureSelfProto = nullptr) &&;
635628

636629
/// Compute the requirement signature for the given protocol.
637630
static GenericSignature computeRequirementSignature(ProtocolDecl *proto);
@@ -692,7 +685,8 @@ class GenericSignatureBuilder {
692685
void diagnoseProtocolRefinement(
693686
const ProtocolDecl *requirementSignatureSelfProto);
694687

695-
void diagnoseRedundantRequirements() const;
688+
void diagnoseRedundantRequirements(
689+
bool onlyDiagnoseExplicitConformancesImpliedByConcrete=false) const;
696690

697691
void diagnoseConflictingConcreteTypeRequirements(
698692
const ProtocolDecl *requirementSignatureSelfProto);
@@ -845,7 +839,7 @@ class GenericSignatureBuilder {
845839
class GenericSignatureBuilder::RequirementSource final
846840
: public llvm::FoldingSetNode,
847841
private llvm::TrailingObjects<RequirementSource, ProtocolDecl *,
848-
WrittenRequirementLoc> {
842+
SourceLoc> {
849843

850844
friend class FloatingRequirementSource;
851845
friend class GenericSignature;
@@ -947,7 +941,7 @@ class GenericSignatureBuilder::RequirementSource final
947941
const StorageKind storageKind;
948942

949943
/// Whether there is a trailing written requirement location.
950-
const bool hasTrailingWrittenRequirementLoc;
944+
const bool hasTrailingSourceLoc;
951945

952946
private:
953947
/// The actual storage, described by \c storageKind.
@@ -987,8 +981,8 @@ class GenericSignatureBuilder::RequirementSource final
987981
}
988982

989983
/// The trailing written requirement location, if there is one.
990-
size_t numTrailingObjects(OverloadToken<WrittenRequirementLoc>) const {
991-
return hasTrailingWrittenRequirementLoc ? 1 : 0;
984+
size_t numTrailingObjects(OverloadToken<SourceLoc>) const {
985+
return hasTrailingSourceLoc ? 1 : 0;
992986
}
993987

994988
#ifndef NDEBUG
@@ -1039,25 +1033,25 @@ class GenericSignatureBuilder::RequirementSource final
10391033

10401034
RequirementSource(Kind kind, Type rootType,
10411035
ProtocolDecl *protocol,
1042-
WrittenRequirementLoc writtenReqLoc)
1036+
SourceLoc writtenReqLoc)
10431037
: kind(kind), storageKind(StorageKind::StoredType),
1044-
hasTrailingWrittenRequirementLoc(!writtenReqLoc.isNull()),
1038+
hasTrailingSourceLoc(writtenReqLoc.isValid()),
10451039
parent(nullptr) {
10461040
assert(isAcceptableStorageKind(kind, storageKind) &&
10471041
"RequirementSource kind/storageKind mismatch");
10481042

10491043
storage.type = rootType.getPointer();
10501044
if (kind == RequirementSignatureSelf)
10511045
getTrailingObjects<ProtocolDecl *>()[0] = protocol;
1052-
if (hasTrailingWrittenRequirementLoc)
1053-
getTrailingObjects<WrittenRequirementLoc>()[0] = writtenReqLoc;
1046+
if (hasTrailingSourceLoc)
1047+
getTrailingObjects<SourceLoc>()[0] = writtenReqLoc;
10541048
}
10551049

10561050
RequirementSource(Kind kind, const RequirementSource *parent,
10571051
Type type, ProtocolDecl *protocol,
1058-
WrittenRequirementLoc writtenReqLoc)
1052+
SourceLoc writtenReqLoc)
10591053
: kind(kind), storageKind(StorageKind::StoredType),
1060-
hasTrailingWrittenRequirementLoc(!writtenReqLoc.isNull()),
1054+
hasTrailingSourceLoc(writtenReqLoc.isValid()),
10611055
parent(parent) {
10621056
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
10631057
"Root RequirementSource should not have parent (or vice versa)");
@@ -1067,14 +1061,14 @@ class GenericSignatureBuilder::RequirementSource final
10671061
storage.type = type.getPointer();
10681062
if (isProtocolRequirement())
10691063
getTrailingObjects<ProtocolDecl *>()[0] = protocol;
1070-
if (hasTrailingWrittenRequirementLoc)
1071-
getTrailingObjects<WrittenRequirementLoc>()[0] = writtenReqLoc;
1064+
if (hasTrailingSourceLoc)
1065+
getTrailingObjects<SourceLoc>()[0] = writtenReqLoc;
10721066
}
10731067

10741068
RequirementSource(Kind kind, const RequirementSource *parent,
10751069
ProtocolConformanceRef conformance)
10761070
: kind(kind), storageKind(StorageKind::ProtocolConformance),
1077-
hasTrailingWrittenRequirementLoc(false), parent(parent) {
1071+
hasTrailingSourceLoc(false), parent(parent) {
10781072
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
10791073
"Root RequirementSource should not have parent (or vice versa)");
10801074
assert(isAcceptableStorageKind(kind, storageKind) &&
@@ -1086,7 +1080,7 @@ class GenericSignatureBuilder::RequirementSource final
10861080
RequirementSource(Kind kind, const RequirementSource *parent,
10871081
AssociatedTypeDecl *assocType)
10881082
: kind(kind), storageKind(StorageKind::AssociatedTypeDecl),
1089-
hasTrailingWrittenRequirementLoc(false), parent(parent) {
1083+
hasTrailingSourceLoc(false), parent(parent) {
10901084
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
10911085
"Root RequirementSource should not have parent (or vice versa)");
10921086
assert(isAcceptableStorageKind(kind, storageKind) &&
@@ -1097,7 +1091,7 @@ class GenericSignatureBuilder::RequirementSource final
10971091

10981092
RequirementSource(Kind kind, const RequirementSource *parent)
10991093
: kind(kind), storageKind(StorageKind::None),
1100-
hasTrailingWrittenRequirementLoc(false), parent(parent) {
1094+
hasTrailingSourceLoc(false), parent(parent) {
11011095
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
11021096
"Root RequirementSource should not have parent (or vice versa)");
11031097
assert(isAcceptableStorageKind(kind, storageKind) &&
@@ -1107,7 +1101,7 @@ class GenericSignatureBuilder::RequirementSource final
11071101
RequirementSource(Kind kind, const RequirementSource *parent,
11081102
Type newType)
11091103
: kind(kind), storageKind(StorageKind::StoredType),
1110-
hasTrailingWrittenRequirementLoc(false), parent(parent) {
1104+
hasTrailingSourceLoc(false), parent(parent) {
11111105
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
11121106
"Root RequirementSource should not have parent (or vice versa)");
11131107
assert(isAcceptableStorageKind(kind, storageKind) &&
@@ -1124,14 +1118,14 @@ class GenericSignatureBuilder::RequirementSource final
11241118
/// stated in an 'inheritance' or 'where' clause.
11251119
static const RequirementSource *forExplicit(GenericSignatureBuilder &builder,
11261120
Type rootType,
1127-
WrittenRequirementLoc writtenLoc);
1121+
SourceLoc writtenLoc);
11281122

11291123
/// Retrieve a requirement source representing a requirement that is
11301124
/// inferred from some part of a generic declaration's signature, e.g., the
11311125
/// parameter or result type of a generic function.
11321126
static const RequirementSource *forInferred(GenericSignatureBuilder &builder,
11331127
Type rootType,
1134-
const TypeRepr *typeRepr);
1128+
SourceLoc writtenLoc);
11351129

11361130
/// Retrieve a requirement source representing the requirement signature
11371131
/// computation for a protocol.
@@ -1153,8 +1147,8 @@ class GenericSignatureBuilder::RequirementSource final
11531147
Type dependentType,
11541148
ProtocolDecl *protocol,
11551149
bool inferred,
1156-
WrittenRequirementLoc writtenLoc =
1157-
WrittenRequirementLoc()) const;
1150+
SourceLoc writtenLoc =
1151+
SourceLoc()) const;
11581152
public:
11591153
/// A requirement source that describes a conformance requirement resolved
11601154
/// via a superclass requirement.
@@ -1287,20 +1281,9 @@ class GenericSignatureBuilder::RequirementSource final
12871281
int compare(const RequirementSource *other) const;
12881282

12891283
/// Retrieve the written requirement location, if there is one.
1290-
WrittenRequirementLoc getWrittenRequirementLoc() const {
1291-
if (!hasTrailingWrittenRequirementLoc) return WrittenRequirementLoc();
1292-
return getTrailingObjects<WrittenRequirementLoc>()[0];
1293-
}
1294-
1295-
/// Retrieve the type representation for this requirement, if there is one.
1296-
const TypeRepr *getTypeRepr() const {
1297-
return getWrittenRequirementLoc().dyn_cast<const TypeRepr *>();
1298-
}
1299-
1300-
/// Retrieve the requirement representation for this requirement, if there is
1301-
/// one.
1302-
const RequirementRepr *getRequirementRepr() const {
1303-
return getWrittenRequirementLoc().dyn_cast<const RequirementRepr *>();
1284+
SourceLoc getSourceLoc() const {
1285+
if (!hasTrailingSourceLoc) return SourceLoc();
1286+
return getTrailingObjects<SourceLoc>()[0];
13041287
}
13051288

13061289
/// Retrieve the type stored in this requirement.
@@ -1354,88 +1337,82 @@ class GenericSignatureBuilder::RequirementSource final
13541337
/// The root will be supplied as soon as the appropriate dependent type is
13551338
/// resolved.
13561339
class GenericSignatureBuilder::FloatingRequirementSource {
1357-
enum Kind {
1340+
enum Kind : uint8_t {
13581341
/// A fully-resolved requirement source, which does not need a root.
13591342
Resolved,
1360-
/// An explicit requirement source lacking a root.
1343+
/// An explicit requirement in a generic signature.
13611344
Explicit,
1362-
/// An inferred requirement source lacking a root.
1345+
/// A requirement inferred from a concrete type application in a
1346+
/// generic signature.
13631347
Inferred,
1364-
/// A requirement source augmented by an abstract protocol requirement
1365-
AbstractProtocol,
1348+
/// An explicit requirement written inside a protocol.
1349+
ProtocolRequirement,
1350+
/// A requirement inferred from a concrete type application inside a
1351+
/// protocol.
1352+
InferredProtocolRequirement,
13661353
/// A requirement source for a nested-type-name match introduced by
13671354
/// the given source.
13681355
NestedTypeNameMatch,
13691356
} kind;
13701357

1371-
using Storage =
1372-
llvm::PointerUnion<const RequirementSource *, const TypeRepr *,
1373-
const RequirementRepr *>;
1374-
1375-
Storage storage;
1358+
const RequirementSource *source;
1359+
SourceLoc loc;
13761360

13771361
// Additional storage for an abstract protocol requirement.
13781362
union {
1379-
struct {
1380-
ProtocolDecl *protocol = nullptr;
1381-
WrittenRequirementLoc written;
1382-
bool inferred = false;
1383-
} protocolReq;
1384-
1363+
ProtocolDecl *protocol = nullptr;
13851364
Identifier nestedName;
13861365
};
13871366

1388-
FloatingRequirementSource(Kind kind, Storage storage)
1389-
: kind(kind), storage(storage) { }
1367+
FloatingRequirementSource(Kind kind, const RequirementSource *source)
1368+
: kind(kind), source(source) { }
13901369

13911370
public:
13921371
/// Implicit conversion from a resolved requirement source.
13931372
FloatingRequirementSource(const RequirementSource *source)
13941373
: FloatingRequirementSource(Resolved, source) { }
13951374

13961375
static FloatingRequirementSource forAbstract() {
1397-
return { Explicit, Storage() };
1398-
}
1399-
1400-
static FloatingRequirementSource forExplicit(const TypeRepr *typeRepr) {
1401-
return { Explicit, typeRepr };
1376+
return { Explicit, nullptr };
14021377
}
14031378

1404-
static FloatingRequirementSource forExplicit(
1405-
const RequirementRepr *requirementRepr) {
1406-
return { Explicit, requirementRepr };
1379+
static FloatingRequirementSource forExplicit(SourceLoc loc) {
1380+
FloatingRequirementSource result{ Explicit, nullptr };
1381+
result.loc = loc;
1382+
return result;
14071383
}
14081384

1409-
static FloatingRequirementSource forInferred(const TypeRepr *typeRepr) {
1410-
return { Inferred, typeRepr };
1385+
static FloatingRequirementSource forInferred(SourceLoc loc) {
1386+
FloatingRequirementSource result{ Inferred, nullptr };
1387+
result.loc = loc;
1388+
return result;
14111389
}
14121390

14131391
static FloatingRequirementSource viaProtocolRequirement(
14141392
const RequirementSource *base,
14151393
ProtocolDecl *inProtocol,
14161394
bool inferred) {
1417-
FloatingRequirementSource result{ AbstractProtocol, base };
1418-
result.protocolReq.protocol = inProtocol;
1419-
result.protocolReq.written = WrittenRequirementLoc();
1420-
result.protocolReq.inferred = inferred;
1395+
auto kind = (inferred ? InferredProtocolRequirement : ProtocolRequirement);
1396+
FloatingRequirementSource result{ kind, base };
1397+
result.protocol = inProtocol;
14211398
return result;
14221399
}
14231400

14241401
static FloatingRequirementSource viaProtocolRequirement(
14251402
const RequirementSource *base,
14261403
ProtocolDecl *inProtocol,
1427-
WrittenRequirementLoc written,
1404+
SourceLoc written,
14281405
bool inferred) {
1429-
FloatingRequirementSource result{ AbstractProtocol, base };
1430-
result.protocolReq.protocol = inProtocol;
1431-
result.protocolReq.written = written;
1432-
result.protocolReq.inferred = inferred;
1406+
auto kind = (inferred ? InferredProtocolRequirement : ProtocolRequirement);
1407+
FloatingRequirementSource result{ kind, base };
1408+
result.protocol = inProtocol;
1409+
result.loc = written;
14331410
return result;
14341411
}
14351412

14361413
static FloatingRequirementSource forNestedTypeNameMatch(
14371414
Identifier nestedName) {
1438-
FloatingRequirementSource result{ NestedTypeNameMatch, Storage() };
1415+
FloatingRequirementSource result{ NestedTypeNameMatch, nullptr };
14391416
result.nestedName = nestedName;
14401417
return result;
14411418
};

0 commit comments

Comments
 (0)