Skip to content

AST: Move GenericParamList and friends to GenericParamList.{h,cpp} #34120

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 1 commit into from
Sep 30, 2020
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
360 changes: 2 additions & 358 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ namespace swift {
class BraceStmt;
class DeclAttributes;
class GenericContext;
class GenericParamList;
class GenericSignature;
class GenericTypeParamDecl;
class GenericTypeParamType;
Expand All @@ -88,6 +89,7 @@ namespace swift {
class ProtocolType;
struct RawComment;
enum class ResilienceExpansion : unsigned;
class TrailingWhereClause;
class TypeAliasDecl;
class Stmt;
class SubscriptDecl;
Expand Down Expand Up @@ -1011,364 +1013,6 @@ void *allocateMemoryForDecl(AllocatorTy &allocator, size_t baseSize,
return mem;
}

enum class RequirementReprKind : unsigned {
/// A type bound T : P, where T is a type that depends on a generic
/// parameter and P is some type that should bound T, either as a concrete
/// supertype or a protocol to which T must conform.
TypeConstraint,

/// A same-type requirement T == U, where T and U are types that shall be
/// equivalent.
SameType,

/// A layout bound T : L, where T is a type that depends on a generic
/// parameter and L is some layout specification that should bound T.
LayoutConstraint,

// Note: there is code that packs this enum in a 2-bit bitfield. Audit users
// when adding enumerators.
};

/// A single requirement in a 'where' clause, which places additional
/// restrictions on the generic parameters or associated types of a generic
/// function, type, or protocol.
///
/// This always represents a requirement spelled in the source code. It is
/// never generated implicitly.
///
/// \c GenericParamList assumes these are POD-like.
class RequirementRepr {
SourceLoc SeparatorLoc;
RequirementReprKind Kind : 2;
bool Invalid : 1;
TypeRepr *FirstType;

/// The second element represents the right-hand side of the constraint.
/// It can be e.g. a type or a layout constraint.
union {
TypeRepr *SecondType;
LayoutConstraintLoc SecondLayout;
};

/// Set during deserialization; used to print out the requirements accurately
/// for the generated interface.
StringRef AsWrittenString;

RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
TypeRepr *FirstType, TypeRepr *SecondType)
: SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
FirstType(FirstType), SecondType(SecondType) { }

RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
TypeRepr *FirstType, LayoutConstraintLoc SecondLayout)
: SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
FirstType(FirstType), SecondLayout(SecondLayout) { }

void printImpl(ASTPrinter &OS) const;

public:
/// Construct a new type-constraint requirement.
///
/// \param Subject The type that must conform to the given protocol or
/// composition, or be a subclass of the given class type.
/// \param ColonLoc The location of the ':', or an invalid location if
/// this requirement was implied.
/// \param Constraint The protocol or protocol composition to which the
/// subject must conform, or superclass from which the subject must inherit.
static RequirementRepr getTypeConstraint(TypeRepr *Subject,
SourceLoc ColonLoc,
TypeRepr *Constraint) {
return { ColonLoc, RequirementReprKind::TypeConstraint, Subject, Constraint };
}

/// Construct a new same-type requirement.
///
/// \param FirstType The first type.
/// \param EqualLoc The location of the '==' in the same-type constraint, or
/// an invalid location if this requirement was implied.
/// \param SecondType The second type.
static RequirementRepr getSameType(TypeRepr *FirstType,
SourceLoc EqualLoc,
TypeRepr *SecondType) {
return { EqualLoc, RequirementReprKind::SameType, FirstType, SecondType };
}

/// Construct a new layout-constraint requirement.
///
/// \param Subject The type that must conform to the given layout
/// requirement.
/// \param ColonLoc The location of the ':', or an invalid location if
/// this requirement was implied.
/// \param Layout The layout requirement to which the
/// subject must conform.
static RequirementRepr getLayoutConstraint(TypeRepr *Subject,
SourceLoc ColonLoc,
LayoutConstraintLoc Layout) {
return {ColonLoc, RequirementReprKind::LayoutConstraint, Subject,
Layout};
}

/// Determine the kind of requirement
RequirementReprKind getKind() const { return Kind; }

/// Determine whether this requirement is invalid.
bool isInvalid() const { return Invalid; }

/// Mark this requirement invalid.
void setInvalid() { Invalid = true; }

/// For a type-bound requirement, return the subject of the
/// conformance relationship.
TypeRepr *getSubjectRepr() const {
assert(getKind() == RequirementReprKind::TypeConstraint ||
getKind() == RequirementReprKind::LayoutConstraint);
return FirstType;
}

/// For a type-bound requirement, return the protocol or to which
/// the subject conforms or superclass it inherits.
TypeRepr *getConstraintRepr() const {
assert(getKind() == RequirementReprKind::TypeConstraint);
return SecondType;
}

LayoutConstraint getLayoutConstraint() const {
assert(getKind() == RequirementReprKind::LayoutConstraint);
return SecondLayout.getLayoutConstraint();
}

LayoutConstraintLoc &getLayoutConstraintLoc() {
assert(getKind() == RequirementReprKind::LayoutConstraint);
return SecondLayout;
}

const LayoutConstraintLoc &getLayoutConstraintLoc() const {
assert(getKind() == RequirementReprKind::LayoutConstraint);
return SecondLayout;
}

/// Retrieve the first type of a same-type requirement.
TypeRepr *getFirstTypeRepr() const {
assert(getKind() == RequirementReprKind::SameType);
return FirstType;
}

/// Retrieve the second type of a same-type requirement.
TypeRepr *getSecondTypeRepr() const {
assert(getKind() == RequirementReprKind::SameType);
return SecondType;
}

/// Retrieve the location of the ':' or '==' in an explicitly-written
/// conformance or same-type requirement respectively.
SourceLoc getSeparatorLoc() const {
return SeparatorLoc;
}

SourceRange getSourceRange() const;

/// Retrieve the first or subject type representation from the \c repr,
/// or \c nullptr if \c repr is null.
static TypeRepr *getFirstTypeRepr(const RequirementRepr *repr) {
if (!repr) return nullptr;
return repr->FirstType;
}

/// Retrieve the second or constraint type representation from the \c repr,
/// or \c nullptr if \c repr is null.
static TypeRepr *getSecondTypeRepr(const RequirementRepr *repr) {
if (!repr) return nullptr;
assert(repr->getKind() == RequirementReprKind::TypeConstraint ||
repr->getKind() == RequirementReprKind::SameType);
return repr->SecondType;
}

SWIFT_DEBUG_DUMP;
void print(raw_ostream &OS) const;
void print(ASTPrinter &Printer) const;
};

using GenericParamSource = PointerUnion<GenericContext *, GenericParamList *>;

/// GenericParamList - A list of generic parameters that is part of a generic
/// function or type, along with extra requirements placed on those generic
/// parameters and types derived from them.
class GenericParamList final :
private llvm::TrailingObjects<GenericParamList, GenericTypeParamDecl *> {
friend TrailingObjects;

SourceRange Brackets;
unsigned NumParams;
SourceLoc WhereLoc;
MutableArrayRef<RequirementRepr> Requirements;

GenericParamList *OuterParameters;

GenericParamList(SourceLoc LAngleLoc,
ArrayRef<GenericTypeParamDecl *> Params,
SourceLoc WhereLoc,
MutableArrayRef<RequirementRepr> Requirements,
SourceLoc RAngleLoc);

// Don't copy.
GenericParamList(const GenericParamList &) = delete;
GenericParamList &operator=(const GenericParamList &) = delete;

public:
/// create - Create a new generic parameter list within the given AST context.
///
/// \param Context The ASTContext in which the generic parameter list will
/// be allocated.
/// \param LAngleLoc The location of the opening angle bracket ('<')
/// \param Params The list of generic parameters, which will be copied into
/// ASTContext-allocated memory.
/// \param RAngleLoc The location of the closing angle bracket ('>')
static GenericParamList *create(ASTContext &Context,
SourceLoc LAngleLoc,
ArrayRef<GenericTypeParamDecl *> Params,
SourceLoc RAngleLoc);

/// create - Create a new generic parameter list and "where" clause within
/// the given AST context.
///
/// \param Context The ASTContext in which the generic parameter list will
/// be allocated.
/// \param LAngleLoc The location of the opening angle bracket ('<')
/// \param Params The list of generic parameters, which will be copied into
/// ASTContext-allocated memory.
/// \param WhereLoc The location of the 'where' keyword, if any.
/// \param Requirements The list of requirements, which will be copied into
/// ASTContext-allocated memory.
/// \param RAngleLoc The location of the closing angle bracket ('>')
static GenericParamList *create(const ASTContext &Context,
SourceLoc LAngleLoc,
ArrayRef<GenericTypeParamDecl *> Params,
SourceLoc WhereLoc,
ArrayRef<RequirementRepr> Requirements,
SourceLoc RAngleLoc);

MutableArrayRef<GenericTypeParamDecl *> getParams() {
return {getTrailingObjects<GenericTypeParamDecl *>(), NumParams};
}

ArrayRef<GenericTypeParamDecl *> getParams() const {
return {getTrailingObjects<GenericTypeParamDecl *>(), NumParams};
}

using iterator = GenericTypeParamDecl **;
using const_iterator = const GenericTypeParamDecl * const *;

unsigned size() const { return NumParams; }
iterator begin() { return getParams().begin(); }
iterator end() { return getParams().end(); }
const_iterator begin() const { return getParams().begin(); }
const_iterator end() const { return getParams().end(); }

/// Retrieve the location of the 'where' keyword, or an invalid
/// location if 'where' was not present.
SourceLoc getWhereLoc() const { return WhereLoc; }

/// Retrieve the set of additional requirements placed on these
/// generic parameters and types derived from them.
///
/// This list may contain both explicitly-written requirements as well as
/// implicitly-generated requirements, and may be non-empty even if no
/// 'where' keyword is present.
MutableArrayRef<RequirementRepr> getRequirements() { return Requirements; }

/// Retrieve the set of additional requirements placed on these
/// generic parameters and types derived from them.
///
/// This list may contain both explicitly-written requirements as well as
/// implicitly-generated requirements, and may be non-empty even if no
/// 'where' keyword is present.
ArrayRef<RequirementRepr> getRequirements() const { return Requirements; }

/// Retrieve the outer generic parameter list.
///
/// This is used for extensions of nested types, and in SIL mode, where a
/// single lexical context can have multiple logical generic parameter
/// lists.
GenericParamList *getOuterParameters() const { return OuterParameters; }

/// Set the outer generic parameter list. See \c getOuterParameters
/// for more information.
void setOuterParameters(GenericParamList *Outer) { OuterParameters = Outer; }

void setDeclContext(DeclContext *dc);

SourceLoc getLAngleLoc() const { return Brackets.Start; }
SourceLoc getRAngleLoc() const { return Brackets.End; }

SourceRange getSourceRange() const { return Brackets; }

/// Retrieve the source range covering the where clause.
SourceRange getWhereClauseSourceRange() const {
if (WhereLoc.isInvalid())
return SourceRange();

auto endLoc = Requirements.back().getSourceRange().End;
return SourceRange(WhereLoc, endLoc);
}

/// Configure the depth of the generic parameters in this list.
void setDepth(unsigned depth);

/// Create a copy of the generic parameter list and all of its generic
/// parameter declarations. The copied generic parameters are re-parented
/// to the given DeclContext.
GenericParamList *clone(DeclContext *dc) const;

void print(raw_ostream &OS) const;
SWIFT_DEBUG_DUMP;

bool walk(ASTWalker &walker);

/// Finds a generic parameter declaration by name. This should only
/// be used from the SIL parser.
GenericTypeParamDecl *lookUpGenericParam(Identifier name) const;
};

/// A trailing where clause.
class alignas(RequirementRepr) TrailingWhereClause final :
private llvm::TrailingObjects<TrailingWhereClause, RequirementRepr> {
friend TrailingObjects;

SourceLoc WhereLoc;

/// The number of requirements. The actual requirements are tail-allocated.
unsigned NumRequirements;

TrailingWhereClause(SourceLoc whereLoc,
ArrayRef<RequirementRepr> requirements);

public:
/// Create a new trailing where clause with the given set of requirements.
static TrailingWhereClause *create(ASTContext &ctx, SourceLoc whereLoc,
ArrayRef<RequirementRepr> requirements);

/// Retrieve the location of the 'where' keyword.
SourceLoc getWhereLoc() const { return WhereLoc; }

/// Retrieve the set of requirements.
MutableArrayRef<RequirementRepr> getRequirements() {
return {getTrailingObjects<RequirementRepr>(), NumRequirements};
}

/// Retrieve the set of requirements.
ArrayRef<RequirementRepr> getRequirements() const {
return {getTrailingObjects<RequirementRepr>(), NumRequirements};
}

/// Compute the source range containing this trailing where clause.
SourceRange getSourceRange() const {
return SourceRange(WhereLoc,
getRequirements().back().getSourceRange().End);
}

void print(llvm::raw_ostream &OS, bool printWhereKeyword) const;
};

// A private class for forcing exact field layout.
class alignas(8) _GenericContext {
// Not really public. See GenericContext.
Expand Down
3 changes: 2 additions & 1 deletion include/swift/AST/GenericEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
#define SWIFT_AST_GENERIC_ENVIRONMENT_H

#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/GenericParamKey.h"
#include "swift/AST/GenericParamList.h"
#include "swift/AST/GenericSignature.h"
#include "swift/Basic/Compiler.h"
#include "swift/Basic/Debug.h"
#include "llvm/ADT/ArrayRef.h"
Expand Down
Loading