Skip to content

RequirementMachine: Protocol typealias support #41333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 9 additions & 19 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "swift/AST/IfConfigClause.h"
#include "swift/AST/LayoutConstraint.h"
#include "swift/AST/ReferenceCounting.h"
#include "swift/AST/RequirementSignature.h"
#include "swift/AST/StorageImpl.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/AST/TypeWalker.h"
Expand Down Expand Up @@ -525,7 +526,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
IsComputingSemanticMembers : 1
);

SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+1+1+8+16,
SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+1+1+8,
/// Whether the \c RequiresClass bit is valid.
RequiresClassValid : 1,

Expand Down Expand Up @@ -564,10 +565,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {

/// If this is a compiler-known protocol, this will be a KnownProtocolKind
/// value, plus one. Otherwise, it will be 0.
KnownProtocol : 8, // '8' for speed. This only needs 6.

/// The number of requirements in the requirement signature.
NumRequirementsInSignature : 16
KnownProtocol : 8 // '8' for speed. This only needs 6.
);

SWIFT_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 1+1+2+1+1+1+1+1+1,
Expand Down Expand Up @@ -4313,7 +4311,7 @@ class ProtocolDecl final : public NominalTypeDecl {

/// The generic signature representing exactly the new requirements introduced
/// by this protocol.
const Requirement *RequirementSignature = nullptr;
Optional<RequirementSignature> RequirementSig;

/// Returns the cached result of \c requiresClass or \c None if it hasn't yet
/// been computed.
Expand Down Expand Up @@ -4574,34 +4572,26 @@ class ProtocolDecl final : public NominalTypeDecl {
/// requirements. Computed from the structural requirements, above.
ArrayRef<ProtocolDecl *> getProtocolDependencies() const;

/// Retrieve the requirements that describe this protocol.
///
/// These are the requirements including any inherited protocols
/// and conformances for associated types that are introduced in this
/// protocol. Requirements implied via any other protocol (e.g., inherited
/// protocols of the inherited protocols) are not mentioned. The conformance
/// requirements listed here become entries in the witness table.
ArrayRef<Requirement> getRequirementSignature() const;
/// Retrieve the requirements that describe this protocol from the point of
/// view of the generic system; see RequirementSignature.h for details.
RequirementSignature getRequirementSignature() const;

/// Is the requirement signature currently being computed?
bool isComputingRequirementSignature() const;

/// Has the requirement signature been computed yet?
bool isRequirementSignatureComputed() const {
return RequirementSignature != nullptr;
return RequirementSig.hasValue();
}

void setRequirementSignature(ArrayRef<Requirement> requirements);
void setRequirementSignature(RequirementSignature requirementSig);

void setLazyRequirementSignature(LazyMemberLoader *lazyLoader,
uint64_t requirementSignatureData);

void setLazyAssociatedTypeMembers(LazyMemberLoader *lazyLoader,
uint64_t associatedTypesData);

private:
ArrayRef<Requirement> getCachedRequirementSignature() const;

public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
Expand Down
5 changes: 3 additions & 2 deletions include/swift/AST/LazyResolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#ifndef SWIFT_AST_LAZYRESOLVER_H
#define SWIFT_AST_LAZYRESOLVER_H

#include "swift/AST/ProtocolConformanceRef.h"
#include "llvm/ADT/PointerEmbeddedInt.h"

namespace swift {
Expand All @@ -32,6 +31,7 @@ class NominalTypeDecl;
class NormalProtocolConformance;
class ProtocolConformance;
class ProtocolDecl;
class ProtocolTypeAlias;
class TypeDecl;
class ValueDecl;
class VarDecl;
Expand Down Expand Up @@ -99,7 +99,8 @@ class alignas(void*) LazyMemberLoader {
/// Loads the requirement signature for a protocol.
virtual void
loadRequirementSignature(const ProtocolDecl *proto, uint64_t contextData,
SmallVectorImpl<Requirement> &requirements) = 0;
SmallVectorImpl<Requirement> &requirements,
SmallVectorImpl<ProtocolTypeAlias> &typeAliases) = 0;

/// Loads the associated types of a protocol.
virtual void
Expand Down
72 changes: 72 additions & 0 deletions include/swift/AST/RequirementSignature.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//===--- RequirementSignature.h - Requirement Signature AST -----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the RequirementSignature class.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_AST_REQUIREMENT_SIGNATURE_H
#define SWIFT_AST_REQUIREMENT_SIGNATURE_H

#include "swift/AST/Type.h"

namespace swift {

/// A description of a typealias defined in a protocol.
class ProtocolTypeAlias final {
Identifier Name;
Type UnderlyingType;

public:
ProtocolTypeAlias(Identifier name, Type underlyingType)
: Name(name), UnderlyingType(underlyingType) {}

/// Returns the name of the typealias.
Identifier getName() const { return Name; }

/// Returns the underlying type of the typealias.
Type getUnderlyingType() const { return UnderlyingType; }
};

/// The requirements that describe a protocol from the viewpoint of the
/// generics system.
class RequirementSignature final {
ArrayRef<Requirement> Requirements;
ArrayRef<ProtocolTypeAlias> TypeAliases;

public:
RequirementSignature() = default;

RequirementSignature(ArrayRef<Requirement> requirements,
ArrayRef<ProtocolTypeAlias> typeAliases)
: Requirements(requirements), TypeAliases(typeAliases) {}

/// The requirements including any inherited protocols and conformances for
/// associated types that are introduced in this protocol.
///
/// Requirements implied via any other protocol (e.g., inherited protocols
/// of the inherited protocols) are not mentioned.
///
/// The conformance requirements listed here become entries in witness tables
/// for conformances to this protocol.
ArrayRef<Requirement> getRequirements() const {
return Requirements;
}

ArrayRef<ProtocolTypeAlias> getTypeAliases() const {
return TypeAliases;
}
};

} // end namespace swift

#endif // SWIFT_AST_REQUIREMENT_SIGNATURE_H
12 changes: 6 additions & 6 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ class ProtocolDependenciesRequest :
/// be folded into RequirementSignatureRequest.
class RequirementSignatureRequestRQM :
public SimpleRequest<RequirementSignatureRequestRQM,
ArrayRef<Requirement>(ProtocolDecl *),
RequirementSignature(ProtocolDecl *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;
Expand All @@ -485,7 +485,7 @@ class RequirementSignatureRequestRQM :
friend SimpleRequest;

// Evaluation.
ArrayRef<Requirement>
RequirementSignature
evaluate(Evaluator &evaluator, ProtocolDecl *proto) const;

public:
Expand All @@ -495,7 +495,7 @@ class RequirementSignatureRequestRQM :
/// Compute the requirements that describe a protocol.
class RequirementSignatureRequest :
public SimpleRequest<RequirementSignatureRequest,
ArrayRef<Requirement>(ProtocolDecl *),
RequirementSignature(ProtocolDecl *),
RequestFlags::SeparatelyCached> {
public:
using SimpleRequest::SimpleRequest;
Expand All @@ -504,14 +504,14 @@ class RequirementSignatureRequest :
friend SimpleRequest;

// Evaluation.
ArrayRef<Requirement>
RequirementSignature
evaluate(Evaluator &evaluator, ProtocolDecl *proto) const;

public:
// Separate caching.
bool isCached() const { return true; }
Optional<ArrayRef<Requirement>> getCachedResult() const;
void cacheResult(ArrayRef<Requirement> value) const;
Optional<RequirementSignature> getCachedResult() const;
void cacheResult(RequirementSignature value) const;
};

/// Compute the default definition type of an associated type.
Expand Down
4 changes: 2 additions & 2 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,10 @@ SWIFT_REQUEST(TypeChecker, ProtocolDependenciesRequest,
ArrayRef<ProtocolDecl *>(ProtocolDecl *), Cached,
HasNearestLocation)
SWIFT_REQUEST(TypeChecker, RequirementSignatureRequestRQM,
ArrayRef<Requirement>(ProtocolDecl *), Cached,
RequirementSignature(ProtocolDecl *), Cached,
NoLocationInfo)
SWIFT_REQUEST(TypeChecker, RequirementSignatureRequest,
ArrayRef<Requirement>(ProtocolDecl *), SeparatelyCached,
RequirementSignature(ProtocolDecl *), SeparatelyCached,
NoLocationInfo)
SWIFT_REQUEST(TypeChecker, RequiresOpaqueAccessorsRequest, bool(VarDecl *),
SeparatelyCached, NoLocationInfo)
Expand Down
5 changes: 3 additions & 2 deletions include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "swift/AST/Module.h"
#include "swift/AST/ProtocolAssociations.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/RequirementSignature.h"
#include "swift/AST/Types.h"
#include "swift/IRGen/ValueWitness.h"
#include "swift/SIL/SILFunction.h"
Expand Down Expand Up @@ -607,7 +608,7 @@ class LinkEntity {
CanType associatedType,
ProtocolDecl *requirement) {
unsigned index = 0;
for (const auto &reqt : proto->getRequirementSignature()) {
for (const auto &reqt : proto->getRequirementSignature().getRequirements()) {
if (reqt.getKind() == RequirementKind::Conformance &&
reqt.getFirstType()->getCanonicalType() == associatedType &&
reqt.getProtocolDecl() == requirement) {
Expand All @@ -631,7 +632,7 @@ class LinkEntity {
static std::pair<CanType, ProtocolDecl*>
getAssociatedConformanceByIndex(const ProtocolDecl *proto,
unsigned index) {
auto &reqt = proto->getRequirementSignature()[index];
auto &reqt = proto->getRequirementSignature().getRequirements()[index];
assert(reqt.getKind() == RequirementKind::Conformance);
return { reqt.getFirstType()->getCanonicalType(),
reqt.getProtocolDecl() };
Expand Down
3 changes: 2 additions & 1 deletion include/swift/SIL/SILWitnessVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ template <class T> class SILWitnessVisitor : public ASTVisitor<T> {
// The protocol conformance descriptor gets added first.
asDerived().addProtocolConformanceDescriptor();

for (const auto &reqt : protocol->getRequirementSignature()) {
auto requirements = protocol->getRequirementSignature().getRequirements();
for (const auto &reqt : requirements) {
switch (reqt.getKind()) {
// These requirements don't show up in the witness table.
case RequirementKind::Superclass:
Expand Down
3 changes: 2 additions & 1 deletion lib/APIDigester/ModuleAnalyzerNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,8 @@ static StringRef printGenericSignature(SDKContext &Ctx, Decl *D, bool Canonical)
llvm::SmallString<32> Result;
llvm::raw_svector_ostream OS(Result);
if (auto *PD = dyn_cast<ProtocolDecl>(D)) {
return printGenericSignature(Ctx, PD->getRequirementSignature(), Canonical);
return printGenericSignature(Ctx, PD->getRequirementSignature().getRequirements(),
Canonical);
}
PrintOptions Opts = getTypePrintOpts(Ctx.getOpts());
if (auto *GC = D->getAsGenericContext()) {
Expand Down
4 changes: 2 additions & 2 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -618,8 +618,8 @@ namespace {

OS << " requirement signature=";
if (PD->isRequirementSignatureComputed()) {
OS << GenericSignature::get({PD->getProtocolSelfType()} ,
PD->getRequirementSignature())
auto requirements = PD->getRequirementSignature().getRequirements();
OS << GenericSignature::get({PD->getProtocolSelfType()}, requirements)
->getAsString();
} else {
OS << "<null>";
Expand Down
5 changes: 2 additions & 3 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3284,9 +3284,8 @@ void ASTMangler::appendDependentProtocolConformance(

// Conformances are relative to the current protocol's requirement
// signature.
auto index =
conformanceRequirementIndex(entry,
currentProtocol->getRequirementSignature());
auto reqs = currentProtocol->getRequirementSignature().getRequirements();
auto index = conformanceRequirementIndex(entry, reqs);

// Inherited conformance.
bool isInheritedConformance =
Expand Down
14 changes: 9 additions & 5 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1487,7 +1487,7 @@ void PrintAST::printInheritedFromRequirementSignature(ProtocolDecl *proto,
Decl *attachingTo) {
printGenericSignature(
GenericSignature::get({proto->getProtocolSelfType()} ,
proto->getRequirementSignature()),
proto->getRequirementSignature().getRequirements()),
PrintInherited,
[&](const Requirement &req) {
// Skip the inferred 'Self : AnyObject' constraint if this is an
Expand All @@ -1511,7 +1511,7 @@ void PrintAST::printWhereClauseFromRequirementSignature(ProtocolDecl *proto,
flags |= SwapSelfAndDependentMemberType;
printGenericSignature(
GenericSignature::get({proto->getProtocolSelfType()} ,
proto->getRequirementSignature()),
proto->getRequirementSignature().getRequirements()),
flags,
[&](const Requirement &req) {
auto location = bestRequirementPrintLocation(proto, req);
Expand Down Expand Up @@ -6307,10 +6307,14 @@ void Requirement::dump(raw_ostream &out) const {
break;
}

if (getFirstType())
out << getFirstType() << " ";
PrintOptions opts;
opts.ProtocolQualifiedDependentMemberTypes = true;

getFirstType().print(out, opts);
out << " ";

if (getKind() != RequirementKind::Layout && getSecondType())
out << getSecondType();
getSecondType().print(out, opts);
else if (getLayoutConstraint())
out << getLayoutConstraint();
}
Expand Down
3 changes: 2 additions & 1 deletion lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2720,7 +2720,8 @@ class Verifier : public ASTWalker {
if (!normal->isInvalid()){
auto conformances = normal->getSignatureConformances();
unsigned idx = 0;
for (const auto &req : proto->getRequirementSignature()) {
auto reqs = proto->getRequirementSignature().getRequirements();
for (const auto &req : reqs) {
if (req.getKind() != RequirementKind::Conformance)
continue;

Expand Down
Loading