Skip to content
Merged
3 changes: 0 additions & 3 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -2428,9 +2428,6 @@ WARNING(missing_protocol_refinement, none,
"protocol %0 should be declared to refine %1 due to a same-type constraint on 'Self'",
(ProtocolDecl *, ProtocolDecl *))

ERROR(unsupported_recursive_requirements, none,
"requirement involves recursion that is not currently supported", ())

ERROR(same_type_conflict,none,
"%select{generic parameter |protocol |}0%1 cannot be equal to both "
"%2 and %3", (unsigned, Type, Type, Type))
Expand Down
143 changes: 60 additions & 83 deletions include/swift/AST/GenericSignatureBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,6 @@ class GenericSignatureBuilder {
using RequirementRHS =
llvm::PointerUnion<Type, ProtocolDecl *, LayoutConstraint>;

/// The location of a requirement as written somewhere in the source.
typedef llvm::PointerUnion<const TypeRepr *, const RequirementRepr *>
WrittenRequirementLoc;

class RequirementSource;

class FloatingRequirementSource;
Expand Down Expand Up @@ -342,10 +338,8 @@ class GenericSignatureBuilder {
UnresolvedHandlingKind unresolvedHandling);

/// Add any conditional requirements from the given conformance.
///
/// \returns \c true if an error occurred, \c false if not.
bool addConditionalRequirements(ProtocolConformanceRef conformance,
ModuleDecl *inferForModule, SourceLoc loc);
void addConditionalRequirements(ProtocolConformanceRef conformance,
ModuleDecl *inferForModule);

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

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

void diagnoseRedundantRequirements() const;
void diagnoseRedundantRequirements(
bool onlyDiagnoseExplicitConformancesImpliedByConcrete=false) const;

void diagnoseConflictingConcreteTypeRequirements(
const ProtocolDecl *requirementSignatureSelfProto);
Expand Down Expand Up @@ -845,7 +839,7 @@ class GenericSignatureBuilder {
class GenericSignatureBuilder::RequirementSource final
: public llvm::FoldingSetNode,
private llvm::TrailingObjects<RequirementSource, ProtocolDecl *,
WrittenRequirementLoc> {
SourceLoc> {

friend class FloatingRequirementSource;
friend class GenericSignature;
Expand Down Expand Up @@ -947,7 +941,7 @@ class GenericSignatureBuilder::RequirementSource final
const StorageKind storageKind;

/// Whether there is a trailing written requirement location.
const bool hasTrailingWrittenRequirementLoc;
const bool hasTrailingSourceLoc;

private:
/// The actual storage, described by \c storageKind.
Expand Down Expand Up @@ -987,8 +981,8 @@ class GenericSignatureBuilder::RequirementSource final
}

/// The trailing written requirement location, if there is one.
size_t numTrailingObjects(OverloadToken<WrittenRequirementLoc>) const {
return hasTrailingWrittenRequirementLoc ? 1 : 0;
size_t numTrailingObjects(OverloadToken<SourceLoc>) const {
return hasTrailingSourceLoc ? 1 : 0;
}

#ifndef NDEBUG
Expand Down Expand Up @@ -1039,25 +1033,25 @@ class GenericSignatureBuilder::RequirementSource final

RequirementSource(Kind kind, Type rootType,
ProtocolDecl *protocol,
WrittenRequirementLoc writtenReqLoc)
SourceLoc writtenReqLoc)
: kind(kind), storageKind(StorageKind::StoredType),
hasTrailingWrittenRequirementLoc(!writtenReqLoc.isNull()),
hasTrailingSourceLoc(writtenReqLoc.isValid()),
parent(nullptr) {
assert(isAcceptableStorageKind(kind, storageKind) &&
"RequirementSource kind/storageKind mismatch");

storage.type = rootType.getPointer();
if (kind == RequirementSignatureSelf)
getTrailingObjects<ProtocolDecl *>()[0] = protocol;
if (hasTrailingWrittenRequirementLoc)
getTrailingObjects<WrittenRequirementLoc>()[0] = writtenReqLoc;
if (hasTrailingSourceLoc)
getTrailingObjects<SourceLoc>()[0] = writtenReqLoc;
}

RequirementSource(Kind kind, const RequirementSource *parent,
Type type, ProtocolDecl *protocol,
WrittenRequirementLoc writtenReqLoc)
SourceLoc writtenReqLoc)
: kind(kind), storageKind(StorageKind::StoredType),
hasTrailingWrittenRequirementLoc(!writtenReqLoc.isNull()),
hasTrailingSourceLoc(writtenReqLoc.isValid()),
parent(parent) {
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
"Root RequirementSource should not have parent (or vice versa)");
Expand All @@ -1067,14 +1061,14 @@ class GenericSignatureBuilder::RequirementSource final
storage.type = type.getPointer();
if (isProtocolRequirement())
getTrailingObjects<ProtocolDecl *>()[0] = protocol;
if (hasTrailingWrittenRequirementLoc)
getTrailingObjects<WrittenRequirementLoc>()[0] = writtenReqLoc;
if (hasTrailingSourceLoc)
getTrailingObjects<SourceLoc>()[0] = writtenReqLoc;
}

RequirementSource(Kind kind, const RequirementSource *parent,
ProtocolConformanceRef conformance)
: kind(kind), storageKind(StorageKind::ProtocolConformance),
hasTrailingWrittenRequirementLoc(false), parent(parent) {
hasTrailingSourceLoc(false), parent(parent) {
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
"Root RequirementSource should not have parent (or vice versa)");
assert(isAcceptableStorageKind(kind, storageKind) &&
Expand All @@ -1086,7 +1080,7 @@ class GenericSignatureBuilder::RequirementSource final
RequirementSource(Kind kind, const RequirementSource *parent,
AssociatedTypeDecl *assocType)
: kind(kind), storageKind(StorageKind::AssociatedTypeDecl),
hasTrailingWrittenRequirementLoc(false), parent(parent) {
hasTrailingSourceLoc(false), parent(parent) {
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
"Root RequirementSource should not have parent (or vice versa)");
assert(isAcceptableStorageKind(kind, storageKind) &&
Expand All @@ -1097,7 +1091,7 @@ class GenericSignatureBuilder::RequirementSource final

RequirementSource(Kind kind, const RequirementSource *parent)
: kind(kind), storageKind(StorageKind::None),
hasTrailingWrittenRequirementLoc(false), parent(parent) {
hasTrailingSourceLoc(false), parent(parent) {
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
"Root RequirementSource should not have parent (or vice versa)");
assert(isAcceptableStorageKind(kind, storageKind) &&
Expand All @@ -1107,7 +1101,7 @@ class GenericSignatureBuilder::RequirementSource final
RequirementSource(Kind kind, const RequirementSource *parent,
Type newType)
: kind(kind), storageKind(StorageKind::StoredType),
hasTrailingWrittenRequirementLoc(false), parent(parent) {
hasTrailingSourceLoc(false), parent(parent) {
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
"Root RequirementSource should not have parent (or vice versa)");
assert(isAcceptableStorageKind(kind, storageKind) &&
Expand All @@ -1124,14 +1118,14 @@ class GenericSignatureBuilder::RequirementSource final
/// stated in an 'inheritance' or 'where' clause.
static const RequirementSource *forExplicit(GenericSignatureBuilder &builder,
Type rootType,
WrittenRequirementLoc writtenLoc);
SourceLoc writtenLoc);

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

/// Retrieve a requirement source representing the requirement signature
/// computation for a protocol.
Expand All @@ -1153,8 +1147,8 @@ class GenericSignatureBuilder::RequirementSource final
Type dependentType,
ProtocolDecl *protocol,
bool inferred,
WrittenRequirementLoc writtenLoc =
WrittenRequirementLoc()) const;
SourceLoc writtenLoc =
SourceLoc()) const;
public:
/// A requirement source that describes a conformance requirement resolved
/// via a superclass requirement.
Expand Down Expand Up @@ -1287,20 +1281,9 @@ class GenericSignatureBuilder::RequirementSource final
int compare(const RequirementSource *other) const;

/// Retrieve the written requirement location, if there is one.
WrittenRequirementLoc getWrittenRequirementLoc() const {
if (!hasTrailingWrittenRequirementLoc) return WrittenRequirementLoc();
return getTrailingObjects<WrittenRequirementLoc>()[0];
}

/// Retrieve the type representation for this requirement, if there is one.
const TypeRepr *getTypeRepr() const {
return getWrittenRequirementLoc().dyn_cast<const TypeRepr *>();
}

/// Retrieve the requirement representation for this requirement, if there is
/// one.
const RequirementRepr *getRequirementRepr() const {
return getWrittenRequirementLoc().dyn_cast<const RequirementRepr *>();
SourceLoc getSourceLoc() const {
if (!hasTrailingSourceLoc) return SourceLoc();
return getTrailingObjects<SourceLoc>()[0];
}

/// Retrieve the type stored in this requirement.
Expand Down Expand Up @@ -1354,88 +1337,82 @@ class GenericSignatureBuilder::RequirementSource final
/// The root will be supplied as soon as the appropriate dependent type is
/// resolved.
class GenericSignatureBuilder::FloatingRequirementSource {
enum Kind {
enum Kind : uint8_t {
/// A fully-resolved requirement source, which does not need a root.
Resolved,
/// An explicit requirement source lacking a root.
/// An explicit requirement in a generic signature.
Explicit,
/// An inferred requirement source lacking a root.
/// A requirement inferred from a concrete type application in a
/// generic signature.
Inferred,
/// A requirement source augmented by an abstract protocol requirement
AbstractProtocol,
/// An explicit requirement written inside a protocol.
ProtocolRequirement,
/// A requirement inferred from a concrete type application inside a
/// protocol.
InferredProtocolRequirement,
/// A requirement source for a nested-type-name match introduced by
/// the given source.
NestedTypeNameMatch,
} kind;

using Storage =
llvm::PointerUnion<const RequirementSource *, const TypeRepr *,
const RequirementRepr *>;

Storage storage;
const RequirementSource *source;
SourceLoc loc;

// Additional storage for an abstract protocol requirement.
union {
struct {
ProtocolDecl *protocol = nullptr;
WrittenRequirementLoc written;
bool inferred = false;
} protocolReq;

ProtocolDecl *protocol = nullptr;
Identifier nestedName;
};

FloatingRequirementSource(Kind kind, Storage storage)
: kind(kind), storage(storage) { }
FloatingRequirementSource(Kind kind, const RequirementSource *source)
: kind(kind), source(source) { }

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

static FloatingRequirementSource forAbstract() {
return { Explicit, Storage() };
}

static FloatingRequirementSource forExplicit(const TypeRepr *typeRepr) {
return { Explicit, typeRepr };
return { Explicit, nullptr };
}

static FloatingRequirementSource forExplicit(
const RequirementRepr *requirementRepr) {
return { Explicit, requirementRepr };
static FloatingRequirementSource forExplicit(SourceLoc loc) {
FloatingRequirementSource result{ Explicit, nullptr };
result.loc = loc;
return result;
}

static FloatingRequirementSource forInferred(const TypeRepr *typeRepr) {
return { Inferred, typeRepr };
static FloatingRequirementSource forInferred(SourceLoc loc) {
FloatingRequirementSource result{ Inferred, nullptr };
result.loc = loc;
return result;
}

static FloatingRequirementSource viaProtocolRequirement(
const RequirementSource *base,
ProtocolDecl *inProtocol,
bool inferred) {
FloatingRequirementSource result{ AbstractProtocol, base };
result.protocolReq.protocol = inProtocol;
result.protocolReq.written = WrittenRequirementLoc();
result.protocolReq.inferred = inferred;
auto kind = (inferred ? InferredProtocolRequirement : ProtocolRequirement);
FloatingRequirementSource result{ kind, base };
result.protocol = inProtocol;
return result;
}

static FloatingRequirementSource viaProtocolRequirement(
const RequirementSource *base,
ProtocolDecl *inProtocol,
WrittenRequirementLoc written,
SourceLoc written,
bool inferred) {
FloatingRequirementSource result{ AbstractProtocol, base };
result.protocolReq.protocol = inProtocol;
result.protocolReq.written = written;
result.protocolReq.inferred = inferred;
auto kind = (inferred ? InferredProtocolRequirement : ProtocolRequirement);
FloatingRequirementSource result{ kind, base };
result.protocol = inProtocol;
result.loc = written;
return result;
}

static FloatingRequirementSource forNestedTypeNameMatch(
Identifier nestedName) {
FloatingRequirementSource result{ NestedTypeNameMatch, Storage() };
FloatingRequirementSource result{ NestedTypeNameMatch, nullptr };
result.nestedName = nestedName;
return result;
};
Expand Down
Loading