Skip to content

[Sema] NFC: Ensure that Decls have one-way validation state #15427

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
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
36 changes: 22 additions & 14 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ bool conflicting(const OverloadSignature& sig1, const OverloadSignature& sig2,

/// Decl - Base class for all declarations in Swift.
class alignas(1 << DeclAlignInBits) Decl {
enum class ValidationState {
Unchecked,
Checking,
Checked,
};

protected:
union { uint64_t OpaqueBits;

Expand All @@ -235,12 +241,8 @@ class alignas(1 << DeclAlignInBits) Decl {
/// FIXME: This is ugly.
EarlyAttrValidation : 1,

/// \brief Whether this declaration is currently being validated.
BeingValidated : 1,

/// \brief Whether we have started validating the declaration; this *isn't*
/// reset after finishing it.
ValidationStarted : 1,
/// \brief The validation state of this declaration.
ValidationState : 2,

/// \brief Whether this declaration was added to the surrounding
/// DeclContext of an active #if config clause.
Expand Down Expand Up @@ -609,8 +611,7 @@ class alignas(1 << DeclAlignInBits) Decl {
Bits.Decl.Implicit = false;
Bits.Decl.FromClang = false;
Bits.Decl.EarlyAttrValidation = false;
Bits.Decl.BeingValidated = false;
Bits.Decl.ValidationStarted = false;
Bits.Decl.ValidationState = unsigned(ValidationState::Unchecked);
Bits.Decl.EscapedFromIfConfig = false;
}

Expand Down Expand Up @@ -759,25 +760,32 @@ class alignas(1 << DeclAlignInBits) Decl {
/// Whether the declaration has a valid interface type and
/// generic signature.
bool isBeingValidated() const {
return Bits.Decl.BeingValidated;
return Bits.Decl.ValidationState == unsigned(ValidationState::Checking);
}

/// Toggle whether or not the declaration is being validated.
void setIsBeingValidated(bool ibv = true) {
assert(Bits.Decl.BeingValidated != ibv);
Bits.Decl.BeingValidated = ibv;
if (ibv) {
Bits.Decl.ValidationStarted = true;
assert(Bits.Decl.ValidationState == unsigned(ValidationState::Unchecked));
Bits.Decl.ValidationState = unsigned(ValidationState::Checking);
} else {
assert(Bits.Decl.ValidationState == unsigned(ValidationState::Checking));
Bits.Decl.ValidationState = unsigned(ValidationState::Checked);
}
}

bool hasValidationStarted() const { return Bits.Decl.ValidationStarted; }
bool hasValidationStarted() const {
return Bits.Decl.ValidationState >= unsigned(ValidationState::Checking);
}

/// Manually indicate that validation has started for the declaration.
///
/// This is implied by setIsBeingValidated(true) (i.e. starting validation)
/// and so rarely needs to be called directly.
void setValidationStarted() { Bits.Decl.ValidationStarted = true; }
void setValidationStarted() {
if (Bits.Decl.ValidationState != unsigned(ValidationState::Checking))
Bits.Decl.ValidationState = unsigned(ValidationState::Checked);
}

bool escapedFromIfConfig() const {
return Bits.Decl.EscapedFromIfConfig;
Expand Down
9 changes: 7 additions & 2 deletions lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6990,8 +6990,13 @@ void TypeChecker::validateDecl(ValueDecl *D) {
validateAccessControl(aliasDecl);

// Check generic parameters, if needed.
aliasDecl->setIsBeingValidated();
SWIFT_DEFER { aliasDecl->setIsBeingValidated(false); };
bool validated = aliasDecl->hasValidationStarted();
if (!validated)
aliasDecl->setIsBeingValidated();
SWIFT_DEFER {
if (!validated)
aliasDecl->setIsBeingValidated(false);
};

validateTypealiasType(*this, aliasDecl);
}
Expand Down