Skip to content

Correctly set the parent DeclContext of ParamDecls in EnumElementDecls #27583

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 2 commits into from
Oct 9, 2019
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
11 changes: 2 additions & 9 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3541,8 +3541,6 @@ class EnumDecl final : public NominalTypeDecl {
return SourceRange(EnumLoc, getBraces().End);
}

EnumElementDecl *getElement(Identifier Name) const;

public:
/// A range for iterating the elements of an enum.
using ElementRange = DowncastFilterRange<EnumElementDecl, DeclRange>;
Expand Down Expand Up @@ -6355,13 +6353,7 @@ class EnumElementDecl : public DeclContext, public ValueDecl {
ParameterList *Params,
SourceLoc EqualsLoc,
LiteralExpr *RawValueExpr,
DeclContext *DC)
: DeclContext(DeclContextKind::EnumElementDecl, DC),
ValueDecl(DeclKind::EnumElement, DC, Name, IdentifierLoc),
Params(Params),
EqualsLoc(EqualsLoc),
RawValueExpr(RawValueExpr)
{}
DeclContext *DC);

Identifier getName() const { return getFullName().getBaseIdentifier(); }

Expand All @@ -6377,6 +6369,7 @@ class EnumElementDecl : public DeclContext, public ValueDecl {

Type getArgumentInterfaceType() const;

void setParameterList(ParameterList *params);
ParameterList *getParameterList() const { return Params; }

/// Retrieves a fully typechecked raw value expression associated
Expand Down
27 changes: 19 additions & 8 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4182,14 +4182,6 @@ EnumCaseDecl *EnumCaseDecl::create(SourceLoc CaseLoc,
return ::new (buf) EnumCaseDecl(CaseLoc, Elements, DC);
}

EnumElementDecl *EnumDecl::getElement(Identifier Name) const {
// FIXME: Linear search is not great for large enum decls.
for (EnumElementDecl *Elt : getAllElements())
if (Elt->getName() == Name)
return Elt;
return nullptr;
}

bool EnumDecl::hasPotentiallyUnavailableCaseValue() const {
switch (static_cast<AssociatedValueCheck>(Bits.EnumDecl.HasAssociatedValues)) {
case AssociatedValueCheck::Unchecked:
Expand Down Expand Up @@ -7070,6 +7062,18 @@ SourceRange FuncDecl::getSourceRange() const {
return StartLoc;
}

EnumElementDecl::EnumElementDecl(SourceLoc IdentifierLoc, DeclName Name,
ParameterList *Params,
SourceLoc EqualsLoc,
LiteralExpr *RawValueExpr,
DeclContext *DC)
: DeclContext(DeclContextKind::EnumElementDecl, DC),
ValueDecl(DeclKind::EnumElement, DC, Name, IdentifierLoc),
EqualsLoc(EqualsLoc),
RawValueExpr(RawValueExpr) {
setParameterList(Params);
}

SourceRange EnumElementDecl::getSourceRange() const {
if (RawValueExpr && !RawValueExpr->isImplicit())
return {getStartLoc(), RawValueExpr->getEndLoc()};
Expand Down Expand Up @@ -7127,6 +7131,13 @@ Type EnumElementDecl::getArgumentInterfaceType() const {
return TupleType::get(elements, ctx);
}

void EnumElementDecl::setParameterList(ParameterList *params) {
Params = params;

if (params)
params->setDeclContextOfParamDecls(this);
}

EnumCaseDecl *EnumElementDecl::getParentCase() const {
for (EnumCaseDecl *EC : getParentEnum()->getAllCases()) {
ArrayRef<EnumElementDecl *> CaseElements = EC->getElements();
Expand Down
3 changes: 2 additions & 1 deletion lib/AST/UnqualifiedLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,8 @@ void UnqualifiedLookupFactory::lookupNamesIntroducedByMiscContext(
assert(isa<TopLevelCodeDecl>(dc) ||
isa<Initializer>(dc) ||
isa<TypeAliasDecl>(dc) ||
isa<SubscriptDecl>(dc));
isa<SubscriptDecl>(dc) ||
isa<EnumElementDecl>(dc));
finishLookingInContext(
AddGenericParameters::Yes,
dc,
Expand Down
16 changes: 9 additions & 7 deletions lib/Serialization/Deserialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1874,6 +1874,8 @@ DeclContext *ModuleFile::getDeclContext(DeclContextID DCID) {
return AFD;
if (auto SD = dyn_cast<SubscriptDecl>(D))
return SD;
if (auto EED = dyn_cast<EnumElementDecl>(D))
return EED;

llvm_unreachable("Unknown Decl : DeclContext kind");
}
Expand Down Expand Up @@ -3554,24 +3556,24 @@ class swift::DeclDeserializer {
}
}

// Read payload parameter list, if it exists.
ParameterList *paramList = nullptr;
if (hasPayload) {
paramList = MF.readParameterList();
}

DeclContext *DC = MF.getDeclContext(contextID);
if (declOrOffset.isComplete())
return declOrOffset;

auto elem = MF.createDecl<EnumElementDecl>(SourceLoc(),
name,
paramList,
nullptr,
SourceLoc(),
nullptr,
DC);
declOrOffset = elem;

// Read payload parameter list, if it exists.
if (hasPayload) {
auto *paramList = MF.readParameterList();
elem->setParameterList(paramList);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of delaying this, would it make more sense to serialize ParamDecls without a DeclContext?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds sensible. I'll take a crack at it.

}

// Deserialize the literal raw value, if any.
switch ((EnumElementRawValueKind)rawValueKindID) {
case EnumElementRawValueKind::None:
Expand Down
2 changes: 1 addition & 1 deletion lib/Serialization/Serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ static ASTContext &getContext(ModuleOrSourceFile DC) {

static bool shouldSerializeAsLocalContext(const DeclContext *DC) {
return DC->isLocalContext() && !isa<AbstractFunctionDecl>(DC) &&
!isa<SubscriptDecl>(DC);
!isa<SubscriptDecl>(DC) && !isa<EnumElementDecl>(DC);
}

namespace {
Expand Down
6 changes: 3 additions & 3 deletions test/IDE/comment_attach.swift
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,10 @@ func unterminatedBlockDocComment() {}
// CHECK-NEXT: comment_attach.swift:166:6: Enum/decl_enum_1 RawComment=[/// decl_enum_1 Aaa.\n]
// CHECK-NEXT: comment_attach.swift:168:8: EnumElement/decl_enum_1.Case1 RawComment=[/// Case1 Aaa.\n]
// CHECK-NEXT: comment_attach.swift:171:8: EnumElement/decl_enum_1.Case2 RawComment=[/// Case2 Aaa.\n]
// CHECK-NEXT: Param/decl_enum_1.<anonymous> RawComment=none BriefComment=none DocCommentAsXML=none
// CHECK-NEXT: Param/<anonymous> RawComment=none BriefComment=none DocCommentAsXML=none
// CHECK-NEXT: comment_attach.swift:174:8: EnumElement/decl_enum_1.Case3 RawComment=[/// Case3 Aaa.\n]
// CHECK-NEXT: Param/decl_enum_1.<anonymous> RawComment=none BriefComment=none DocCommentAsXML=none
// CHECK-NEXT: Param/decl_enum_1.<anonymous> RawComment=none BriefComment=none DocCommentAsXML=none
// CHECK-NEXT: Param/<anonymous> RawComment=none BriefComment=none DocCommentAsXML=none
// CHECK-NEXT: Param/<anonymous> RawComment=none BriefComment=none DocCommentAsXML=none
// CHECK-NEXT: comment_attach.swift:177:8: EnumElement/decl_enum_1.Case4 RawComment=[/// Case4 Case5 Aaa.\n]
// CHECK-NEXT: comment_attach.swift:177:15: EnumElement/decl_enum_1.Case5 RawComment=[/// Case4 Case5 Aaa.\n]
// CHECK-NEXT: comment_attach.swift:181:7: Class/decl_class_1 RawComment=[/// decl_class_1 Aaa.\n]
Expand Down