Skip to content

[NFC] Make RequirementRepr a Purely Syntactic Object #32331

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 8 commits into from
Jun 12, 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
95 changes: 13 additions & 82 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1030,12 +1030,12 @@ class RequirementRepr {
SourceLoc SeparatorLoc;
RequirementReprKind Kind : 2;
bool Invalid : 1;
TypeLoc FirstType;
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 {
TypeLoc SecondType;
TypeRepr *SecondType;
LayoutConstraintLoc SecondLayout;
};

Expand All @@ -1044,16 +1044,16 @@ class RequirementRepr {
StringRef AsWrittenString;

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

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

void printImpl(ASTPrinter &OS, bool AsWritten) const;
void printImpl(ASTPrinter &OS) const;

public:
/// Construct a new type-constraint requirement.
Expand All @@ -1064,9 +1064,9 @@ class RequirementRepr {
/// 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(TypeLoc Subject,
static RequirementRepr getTypeConstraint(TypeRepr *Subject,
SourceLoc ColonLoc,
TypeLoc Constraint) {
TypeRepr *Constraint) {
return { ColonLoc, RequirementReprKind::TypeConstraint, Subject, Constraint };
}

Expand All @@ -1076,9 +1076,9 @@ class RequirementRepr {
/// \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(TypeLoc FirstType,
static RequirementRepr getSameType(TypeRepr *FirstType,
SourceLoc EqualLoc,
TypeLoc SecondType) {
TypeRepr *SecondType) {
return { EqualLoc, RequirementReprKind::SameType, FirstType, SecondType };
}

Expand All @@ -1090,7 +1090,7 @@ class RequirementRepr {
/// this requirement was implied.
/// \param Layout The layout requirement to which the
/// subject must conform.
static RequirementRepr getLayoutConstraint(TypeLoc Subject,
static RequirementRepr getLayoutConstraint(TypeRepr *Subject,
SourceLoc ColonLoc,
LayoutConstraintLoc Layout) {
return {ColonLoc, RequirementReprKind::LayoutConstraint, Subject,
Expand All @@ -1108,48 +1108,15 @@ class RequirementRepr {

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

TypeRepr *getSubjectRepr() const {
assert(getKind() == RequirementReprKind::TypeConstraint ||
getKind() == RequirementReprKind::LayoutConstraint);
return FirstType.getTypeRepr();
}

TypeLoc &getSubjectLoc() {
assert(getKind() == RequirementReprKind::TypeConstraint ||
getKind() == RequirementReprKind::LayoutConstraint);
return FirstType;
}

const TypeLoc &getSubjectLoc() 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.
Type getConstraint() const {
assert(getKind() == RequirementReprKind::TypeConstraint);
return SecondType.getType();
}

TypeRepr *getConstraintRepr() const {
assert(getKind() == RequirementReprKind::TypeConstraint);
return SecondType.getTypeRepr();
}

TypeLoc &getConstraintLoc() {
assert(getKind() == RequirementReprKind::TypeConstraint);
return SecondType;
}

const TypeLoc &getConstraintLoc() const {
assert(getKind() == RequirementReprKind::TypeConstraint);
return SecondType;
}
Expand All @@ -1170,43 +1137,13 @@ class RequirementRepr {
}

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

TypeRepr *getFirstTypeRepr() const {
assert(getKind() == RequirementReprKind::SameType);
return FirstType.getTypeRepr();
}

TypeLoc &getFirstTypeLoc() {
assert(getKind() == RequirementReprKind::SameType);
return FirstType;
}

const TypeLoc &getFirstTypeLoc() const {
assert(getKind() == RequirementReprKind::SameType);
return FirstType;
}

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

TypeRepr *getSecondTypeRepr() const {
assert(getKind() == RequirementReprKind::SameType);
return SecondType.getTypeRepr();
}

TypeLoc &getSecondTypeLoc() {
assert(getKind() == RequirementReprKind::SameType);
return SecondType;
}

const TypeLoc &getSecondTypeLoc() const {
assert(getKind() == RequirementReprKind::SameType);
return SecondType;
}
Expand All @@ -1217,19 +1154,13 @@ class RequirementRepr {
return SeparatorLoc;
}

SourceRange getSourceRange() const {
if (getKind() == RequirementReprKind::LayoutConstraint)
return SourceRange(FirstType.getSourceRange().Start,
SecondLayout.getSourceRange().End);
return SourceRange(FirstType.getSourceRange().Start,
SecondType.getSourceRange().End);
}
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.getTypeRepr();
return repr->FirstType;
}

/// Retrieve the second or constraint type representation from the \c repr,
Expand All @@ -1238,7 +1169,7 @@ class RequirementRepr {
if (!repr) return nullptr;
assert(repr->getKind() == RequirementReprKind::TypeConstraint ||
repr->getKind() == RequirementReprKind::SameType);
return repr->SecondType.getTypeRepr();
return repr->SecondType;
}

SWIFT_DEBUG_DUMP;
Expand Down
6 changes: 2 additions & 4 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ class RequirementRequest :
public SimpleRequest<RequirementRequest,
Requirement(WhereClauseOwner, unsigned,
TypeResolutionStage),
RequestFlags::SeparatelyCached> {
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

Expand All @@ -464,10 +464,8 @@ class RequirementRequest :
// Cycle handling.
void noteCycleStep(DiagnosticEngine &diags) const;

// Separate caching.
// Caching.
bool isCached() const;
Optional<Requirement> getCachedResult() const;
void cacheResult(Requirement value) const;
};

/// Generate the USR for the given declaration.
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ SWIFT_REQUEST(TypeChecker, ProtocolRequiresClassRequest, bool(ProtocolDecl *),
SeparatelyCached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, RequirementRequest,
Requirement(WhereClauseOwner, unsigned, TypeResolutionStage),
SeparatelyCached, HasNearestLocation)
Cached, HasNearestLocation)
SWIFT_REQUEST(TypeChecker, RequirementSignatureRequest,
ArrayRef<Requirement>(ProtocolDecl *), SeparatelyCached,
NoLocationInfo)
Expand Down
34 changes: 18 additions & 16 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,47 +121,49 @@ void RequirementRepr::dump() const {
llvm::errs() << "\n";
}

void RequirementRepr::printImpl(ASTPrinter &out, bool AsWritten) const {
auto printTy = [&](const TypeLoc &TyLoc) {
if (AsWritten && TyLoc.getTypeRepr()) {
TyLoc.getTypeRepr()->print(out, PrintOptions());
} else {
TyLoc.getType().print(out, PrintOptions());
}
};

void RequirementRepr::printImpl(ASTPrinter &out) const {
auto printLayoutConstraint =
[&](const LayoutConstraintLoc &LayoutConstraintLoc) {
LayoutConstraintLoc.getLayoutConstraint()->print(out, PrintOptions());
};

switch (getKind()) {
case RequirementReprKind::LayoutConstraint:
printTy(getSubjectLoc());
if (auto *repr = getSubjectRepr()) {
repr->print(out, PrintOptions());
}
out << " : ";
printLayoutConstraint(getLayoutConstraintLoc());
break;

case RequirementReprKind::TypeConstraint:
printTy(getSubjectLoc());
if (auto *repr = getSubjectRepr()) {
repr->print(out, PrintOptions());
}
out << " : ";
printTy(getConstraintLoc());
if (auto *repr = getConstraintRepr()) {
repr->print(out, PrintOptions());
}
break;

case RequirementReprKind::SameType:
printTy(getFirstTypeLoc());
if (auto *repr = getFirstTypeRepr()) {
repr->print(out, PrintOptions());
}
out << " == ";
printTy(getSecondTypeLoc());
if (auto *repr = getSecondTypeRepr()) {
repr->print(out, PrintOptions());
}
break;
}
}

void RequirementRepr::print(raw_ostream &out) const {
StreamPrinter printer(out);
printImpl(printer, /*AsWritten=*/true);
printImpl(printer);
}
void RequirementRepr::print(ASTPrinter &out) const {
printImpl(out, /*AsWritten=*/true);
printImpl(out);
}

static void printTrailingRequirements(ASTPrinter &Printer,
Expand Down
6 changes: 3 additions & 3 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1345,15 +1345,15 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
bool doIt(RequirementRepr &Req) {
switch (Req.getKind()) {
case RequirementReprKind::SameType:
if (doIt(Req.getFirstTypeLoc()) || doIt(Req.getSecondTypeLoc()))
if (doIt(Req.getFirstTypeRepr()) || doIt(Req.getSecondTypeRepr()))
return true;
break;
case RequirementReprKind::TypeConstraint:
if (doIt(Req.getSubjectLoc()) || doIt(Req.getConstraintLoc()))
if (doIt(Req.getSubjectRepr()) || doIt(Req.getConstraintRepr()))
return true;
break;
case RequirementReprKind::LayoutConstraint:
if (doIt(Req.getFirstTypeLoc()))
if (doIt(Req.getFirstTypeRepr()))
return true;
break;
}
Expand Down
27 changes: 10 additions & 17 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,26 +431,13 @@ createGenericParam(ASTContext &ctx, const char *name, unsigned index) {

/// Create a generic parameter list with multiple generic parameters.
static GenericParamList *getGenericParams(ASTContext &ctx,
unsigned numParameters,
bool isAnyObject) {
unsigned numParameters) {
assert(numParameters <= llvm::array_lengthof(GenericParamNames));

SmallVector<GenericTypeParamDecl*, 2> genericParams;
SmallVector<GenericTypeParamDecl *, 2> genericParams;
for (unsigned i = 0; i != numParameters; ++i)
genericParams.push_back(createGenericParam(ctx, GenericParamNames[i], i));


if (isAnyObject) {
CanType ao = ctx.getAnyObjectType();
SmallVector<RequirementRepr, 1> req;
req.push_back(RequirementRepr::getTypeConstraint(TypeLoc::withoutLoc(genericParams[0]->getInterfaceType()), SourceLoc(),
TypeLoc::withoutLoc(ao)));

auto paramList = GenericParamList::create(ctx, SourceLoc(), genericParams,
SourceLoc(), req, SourceLoc());
return paramList;
}

auto paramList = GenericParamList::create(ctx, SourceLoc(), genericParams,
SourceLoc());
return paramList;
Expand All @@ -474,9 +461,15 @@ namespace {

public:
BuiltinFunctionBuilder(ASTContext &ctx, unsigned numGenericParams = 1,
bool isAnyObject = false)
bool wantsAdditionalAnyObjectRequirement = false)
: Context(ctx) {
TheGenericParamList = getGenericParams(ctx, numGenericParams, isAnyObject);
TheGenericParamList = getGenericParams(ctx, numGenericParams);
if (wantsAdditionalAnyObjectRequirement) {
Requirement req(RequirementKind::Conformance,
TheGenericParamList->getParams()[0]->getInterfaceType(),
ctx.getAnyObjectType());
addedRequirements.push_back(req);
}
for (auto gp : TheGenericParamList->getParams()) {
genericParamTypes.push_back(
gp->getDeclaredInterfaceType()->castTo<GenericTypeParamType>());
Expand Down
9 changes: 9 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,15 @@ bool Decl::isWeakImported(ModuleDecl *fromModule) const {
return !fromContext.isContainedIn(containingContext);
}


SourceRange RequirementRepr::getSourceRange() const {
if (getKind() == RequirementReprKind::LayoutConstraint)
return SourceRange(FirstType->getSourceRange().Start,
SecondLayout.getSourceRange().End);
return SourceRange(FirstType->getSourceRange().Start,
SecondType->getSourceRange().End);
}

GenericParamList::GenericParamList(SourceLoc LAngleLoc,
ArrayRef<GenericTypeParamDecl *> Params,
SourceLoc WhereLoc,
Expand Down
Loading