Skip to content

[AST] Introduce "all members" query to reduce non-determinism in serialization & interface printing #35523

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 9 commits into from
Jan 21, 2021
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
34 changes: 17 additions & 17 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ class alignas(1 << DeclAlignInBits) Decl {
NumElements : 32
);

SWIFT_INLINE_BITFIELD(ValueDecl, Decl, 1+1+1,
SWIFT_INLINE_BITFIELD(ValueDecl, Decl, 1+1+1+1,
AlreadyInLookupTable : 1,

/// Whether we have already checked whether this declaration is a
Expand All @@ -342,7 +342,11 @@ class alignas(1 << DeclAlignInBits) Decl {

/// Whether the decl can be accessed by swift users; for instance,
/// a.storage for lazy var a is a decl that cannot be accessed.
IsUserAccessible : 1
IsUserAccessible : 1,

/// Whether this member was synthesized as part of a derived
/// protocol conformance.
Synthesized : 1
);

SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1,
Expand Down Expand Up @@ -387,7 +391,7 @@ class alignas(1 << DeclAlignInBits) Decl {
SWIFT_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2,
StaticSpelling : 2
);
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+1+1+1+1+1+1+1,
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+1+1+1+1+1+1,
/// \see AbstractFunctionDecl::BodyKind
BodyKind : 3,

Expand All @@ -406,10 +410,6 @@ class alignas(1 << DeclAlignInBits) Decl {
/// Whether the function body throws.
Throws : 1,

/// Whether this member was synthesized as part of a derived
/// protocol conformance.
Synthesized : 1,

/// Whether this member's body consists of a single expression.
HasSingleExpressionBody : 1,

Expand Down Expand Up @@ -2020,6 +2020,7 @@ class ValueDecl : public Decl {
Bits.ValueDecl.AlreadyInLookupTable = false;
Bits.ValueDecl.CheckedRedeclaration = false;
Bits.ValueDecl.IsUserAccessible = true;
Bits.ValueDecl.Synthesized = false;
}

// MemberLookupTable borrows a bit from this type
Expand Down Expand Up @@ -2057,6 +2058,14 @@ class ValueDecl : public Decl {
return Bits.ValueDecl.IsUserAccessible;
}

bool isSynthesized() const {
return Bits.ValueDecl.Synthesized;
}

void setSynthesized(bool value = true) {
Bits.ValueDecl.Synthesized = value;
}

bool hasName() const { return bool(Name); }
bool isOperator() const { return Name.isOperator(); }

Expand Down Expand Up @@ -3532,7 +3541,7 @@ class ClassDecl final : public NominalTypeDecl {

friend class SuperclassDeclRequest;
friend class SuperclassTypeRequest;
friend class SemanticMembersRequest;
friend class ABIMembersRequest;
friend class HasMissingDesignatedInitializersRequest;
friend class InheritsSuperclassInitializersRequest;

Expand Down Expand Up @@ -5577,7 +5586,6 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
Bits.AbstractFunctionDecl.Overridden = false;
Bits.AbstractFunctionDecl.Async = Async;
Bits.AbstractFunctionDecl.Throws = Throws;
Bits.AbstractFunctionDecl.Synthesized = false;
Bits.AbstractFunctionDecl.HasSingleExpressionBody = false;
Bits.AbstractFunctionDecl.HasNestedTypeDeclarations = false;
}
Expand Down Expand Up @@ -5784,14 +5792,6 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
/// vtable.
bool needsNewVTableEntry() const;

bool isSynthesized() const {
return Bits.AbstractFunctionDecl.Synthesized;
}

void setSynthesized(bool value = true) {
Bits.AbstractFunctionDecl.Synthesized = value;
}

public:
/// Retrieve the source range of the function body.
SourceRange getBodySourceRange() const;
Expand Down
13 changes: 10 additions & 3 deletions include/swift/AST/DeclContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -778,10 +778,17 @@ class IterableDeclContext {
/// the implementation.
ArrayRef<Decl *> getParsedMembers() const;

/// Get all the members that are semantically within this context,
/// including any implicitly-synthesized members.
/// Get all of the members within this context that can affect ABI, including
/// any implicitly-synthesized members.
///
/// The resulting list of members will be stable across translation units.
ArrayRef<Decl *> getABIMembers() const;

/// Get all of the members within this context, including any
/// implicitly-synthesized members.
///
/// The resulting list of members will be stable across translation units.
ArrayRef<Decl *> getSemanticMembers() const;
ArrayRef<Decl *> getAllMembers() const;

/// Retrieve the set of members in this context without loading any from the
/// associated lazy loader; this should only be used as part of implementing
Expand Down
7 changes: 7 additions & 0 deletions include/swift/AST/PrintOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@ struct PrintOptions {
/// such as _silgen_name, transparent, etc.
bool PrintUserInaccessibleAttrs = true;

/// Whether to limit ourselves to printing only the "current" set of members
/// in a nominal type or extension, which is semantically unstable but can
/// prevent printing from doing "extra" work.
bool PrintCurrentMembersOnly = false;

/// List of attribute kinds that should not be printed.
std::vector<AnyAttrKind> ExcludeAttrList = {DAK_Transparent, DAK_Effects,
DAK_FixedLayout,
Expand Down Expand Up @@ -517,6 +522,7 @@ struct PrintOptions {
result.ShouldQualifyNestedDeclarations =
QualifyNestedDeclarations::TypesOnly;
result.PrintDocumentationComments = false;
result.PrintCurrentMembersOnly = true;
return result;
}

Expand All @@ -538,6 +544,7 @@ struct PrintOptions {
result.SkipUnderscoredKeywords = true;
result.EnumRawValues = EnumRawValueMode::PrintObjCOnly;
result.MapCrossImportOverlaysToDeclaringModule = true;
result.PrintCurrentMembersOnly = false;
return result;
}

Expand Down
22 changes: 20 additions & 2 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -1220,8 +1220,26 @@ class SynthesizeAccessorRequest :
void cacheResult(AccessorDecl *value) const;
};

class SemanticMembersRequest :
public SimpleRequest<SemanticMembersRequest,
class ABIMembersRequest :
public SimpleRequest<ABIMembersRequest,
ArrayRef<Decl *>(IterableDeclContext *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

// Evaluation.
ArrayRef<Decl *>
evaluate(Evaluator &evaluator, IterableDeclContext *idc) const;

public:
bool isCached() const { return true; }
};

class AllMembersRequest :
public SimpleRequest<AllMembersRequest,
ArrayRef<Decl *>(IterableDeclContext *),
RequestFlags::Cached> {
public:
Expand Down
4 changes: 3 additions & 1 deletion include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ SWIFT_REQUEST(TypeChecker, TypeEraserHasViableInitRequest,
SWIFT_REQUEST(TypeChecker, DynamicallyReplacedDeclRequest,
ValueDecl *(ValueDecl *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, SemanticMembersRequest,
SWIFT_REQUEST(TypeChecker, ABIMembersRequest,
ArrayRef<Decl *>(IterableDeclContext *), Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, AllMembersRequest,
ArrayRef<Decl *>(IterableDeclContext *), Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, SpecializeAttrTargetDeclRequest,
ValueDecl *(const ValueDecl *, SpecializeAttr *),
Expand Down
2 changes: 1 addition & 1 deletion include/swift/SIL/SILVTableVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ template <class T> class SILVTableVisitor {
if (!theClass->hasKnownSwiftImplementation())
return;

for (auto member : theClass->getSemanticMembers())
for (auto member : theClass->getABIMembers())
maybeAddMember(member);
}
};
Expand Down
23 changes: 14 additions & 9 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(ModuleDecl *ModuleToPrint,
localModule->isImportedImplementationOnly(nominalModule)) {

bool shouldPrintMembers = llvm::any_of(
ED->getMembers(),
ED->getAllMembers(),
[&](const Decl *member) -> bool {
return shouldPrint(member, options);
});
Expand Down Expand Up @@ -1750,7 +1750,7 @@ bool ShouldPrintChecker::shouldPrint(const Decl *D,
getInheritedForPrinting(Ext, Options, ProtocolsToPrint);
if (ProtocolsToPrint.empty()) {
bool HasMemberToPrint = false;
for (auto Member : Ext->getMembers()) {
for (auto Member : Ext->getAllMembers()) {
if (shouldPrint(Member, Options)) {
HasMemberToPrint = true;
break;
Expand Down Expand Up @@ -2050,24 +2050,29 @@ void PrintAST::printMembersOfDecl(Decl *D, bool needComma,
bool openBracket,
bool closeBracket) {
llvm::SmallVector<Decl *, 3> Members;
auto AddDeclFunc = [&](DeclRange Range) {
for (auto RD : Range)
Members.push_back(RD);
auto AddMembers = [&](IterableDeclContext *idc) {
if (Options.PrintCurrentMembersOnly) {
for (auto RD : idc->getMembers())
Members.push_back(RD);
} else {
for (auto RD : idc->getAllMembers())
Members.push_back(RD);
}
};

if (auto Ext = dyn_cast<ExtensionDecl>(D)) {
AddDeclFunc(Ext->getMembers());
AddMembers(Ext);
} else if (auto NTD = dyn_cast<NominalTypeDecl>(D)) {
AddDeclFunc(NTD->getMembers());
AddMembers(NTD);
for (auto Ext : NTD->getExtensions()) {
if (Options.printExtensionContentAsMembers(Ext))
AddDeclFunc(Ext->getMembers());
AddMembers(Ext);
}
if (Options.PrintExtensionFromConformingProtocols) {
for (auto Conf : NTD->getAllConformances()) {
for (auto Ext : Conf->getProtocol()->getExtensions()) {
if (Options.printExtensionContentAsMembers(Ext))
AddDeclFunc(Ext->getMembers());
AddMembers(Ext);
}
}
}
Expand Down
12 changes: 10 additions & 2 deletions lib/AST/DeclContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,11 +758,19 @@ ArrayRef<Decl *> IterableDeclContext::getParsedMembers() const {
.members;
}

ArrayRef<Decl *> IterableDeclContext::getSemanticMembers() const {
ArrayRef<Decl *> IterableDeclContext::getABIMembers() const {
ASTContext &ctx = getASTContext();
return evaluateOrDefault(
ctx.evaluator,
SemanticMembersRequest{const_cast<IterableDeclContext *>(this)},
ABIMembersRequest{const_cast<IterableDeclContext *>(this)},
ArrayRef<Decl *>());
}

ArrayRef<Decl *> IterableDeclContext::getAllMembers() const {
ASTContext &ctx = getASTContext();
return evaluateOrDefault(
ctx.evaluator,
AllMembersRequest{const_cast<IterableDeclContext *>(this)},
ArrayRef<Decl *>());
}

Expand Down
2 changes: 1 addition & 1 deletion lib/SILGen/SILGenType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1038,7 +1038,7 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {

// Build a vtable if this is a class.
if (auto theClass = dyn_cast<ClassDecl>(theType)) {
for (Decl *member : theClass->getSemanticMembers())
for (Decl *member : theClass->getABIMembers())
visit(member);

SILGenVTable genVTable(SGM, theClass);
Expand Down
1 change: 1 addition & 0 deletions lib/Sema/CodeSynthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,

// Mark implicit.
ctor->setImplicit();
ctor->setSynthesized();
ctor->setAccess(accessLevel);

if (ICK == ImplicitConstructorKind::Memberwise) {
Expand Down
2 changes: 2 additions & 0 deletions lib/Sema/DerivedConformanceCodable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) {
auto *enumDecl = new (C) EnumDecl(SourceLoc(), C.Id_CodingKeys, SourceLoc(),
inherited, nullptr, target);
enumDecl->setImplicit();
enumDecl->setSynthesized();
enumDecl->setAccess(AccessLevel::Private);

// For classes which inherit from something Encodable or Decodable, we
Expand Down Expand Up @@ -349,6 +350,7 @@ static VarDecl *createKeyedContainer(ASTContext &C, DeclContext *DC,
auto *containerDecl = new (C) VarDecl(/*IsStatic=*/false, introducer,
SourceLoc(), C.Id_container, DC);
containerDecl->setImplicit();
containerDecl->setSynthesized();
containerDecl->setInterfaceType(containerType);
return containerDecl;
}
Expand Down
3 changes: 3 additions & 0 deletions lib/Sema/DerivedConformanceDifferentiable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ static ValueDecl *deriveDifferentiable_method(
/*Async=*/false,
/*Throws=*/false,
/*GenericParams=*/nullptr, params, returnType, parentDC);
funcDecl->setSynthesized();
if (!nominal->getSelfClassDecl())
funcDecl->setSelfAccessKind(SelfAccessKind::Mutating);
funcDecl->setBodySynthesizer(bodySynthesizer.Fn, bodySynthesizer.Context);
Expand Down Expand Up @@ -458,6 +459,7 @@ getOrSynthesizeTangentVectorStruct(DerivedConformance &derived, Identifier id) {
/*GenericParams*/ {}, parentDC);
structDecl->setBraces({synthesizedLoc, synthesizedLoc});
structDecl->setImplicit();
structDecl->setSynthesized();
structDecl->copyFormalAccessFrom(nominal, /*sourceIsParentContext*/ true);

// Add stored properties to the `TangentVector` struct.
Expand All @@ -467,6 +469,7 @@ getOrSynthesizeTangentVectorStruct(DerivedConformance &derived, Identifier id) {
auto *tangentProperty = new (C) VarDecl(
member->isStatic(), member->getIntroducer(),
/*NameLoc*/ SourceLoc(), member->getName(), structDecl);
tangentProperty->setSynthesized();
// Note: `tangentProperty` is not marked as implicit here, because that
// incorrectly affects memberwise initializer synthesis.
auto memberContextualType =
Expand Down
2 changes: 2 additions & 0 deletions lib/Sema/DerivedConformanceEquatableHashable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,7 @@ static ValueDecl *deriveHashable_hashValue(DerivedConformance &derived) {
new (C) VarDecl(/*IsStatic*/false, VarDecl::Introducer::Var,
SourceLoc(), C.Id_hashValue, parentDC);
hashValueDecl->setInterfaceType(intType);
hashValueDecl->setSynthesized();

ParameterList *params = ParameterList::createEmpty(C);

Expand All @@ -894,6 +895,7 @@ static ValueDecl *deriveHashable_hashValue(DerivedConformance &derived) {
intType, parentDC);
getterDecl->setImplicit();
getterDecl->setBodySynthesizer(&deriveBodyHashable_hashValue);
getterDecl->setSynthesized();
getterDecl->setIsTransparent(false);

getterDecl->copyFormalAccessFrom(derived.Nominal,
Expand Down
1 change: 1 addition & 0 deletions lib/Sema/DerivedConformances.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ DerivedConformance::declareDerivedProperty(Identifier name,
VarDecl(/*IsStatic*/ isStatic, VarDecl::Introducer::Var,
SourceLoc(), name, parentDC);
propDecl->setImplicit();
propDecl->setSynthesized();
propDecl->copyFormalAccessFrom(Nominal, /*sourceIsParentContext*/ true);
propDecl->setInterfaceType(propertyInterfaceType);

Expand Down
Loading