Merge pull request #79614 from DougGregor/conformance-attributes

Factor conformance attributes into their own separate structure.
This commit is contained in:
Doug Gregor
2025-02-25 17:07:59 -08:00
committed by GitHub
5 changed files with 83 additions and 80 deletions

View File

@@ -0,0 +1,46 @@
//===--- ConformanceLookup.h - Global conformance lookup --------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_CONFORMANCEATTRIBUTES_H
#define SWIFT_AST_CONFORMANCEATTRIBUTES_H
#include "swift/Basic/SourceLoc.h"
namespace swift {
/// Describes all of the attributes that can occur on a conformance.
struct ConformanceAttributes {
/// The location of the "unchecked" attribute, if present.
SourceLoc uncheckedLoc;
/// The location of the "preconcurrency" attribute if present.
SourceLoc preconcurrencyLoc;
/// The location of the "unsafe" attribute if present.
SourceLoc unsafeLoc;
/// Merge other conformance attributes into this set.
ConformanceAttributes &
operator |=(const ConformanceAttributes &other) {
if (other.uncheckedLoc.isValid())
uncheckedLoc = other.uncheckedLoc;
if (other.preconcurrencyLoc.isValid())
preconcurrencyLoc = other.preconcurrencyLoc;
if (other.unsafeLoc.isValid())
unsafeLoc = other.unsafeLoc;
return *this;
}
};
}
#endif

View File

@@ -19,6 +19,7 @@
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/CatchNode.h"
#include "swift/AST/ConformanceAttributes.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/Module.h"
@@ -603,14 +604,7 @@ void forEachPotentialAttachedMacro(
/// Describes an inherited nominal entry.
struct InheritedNominalEntry : Located<NominalTypeDecl *> {
/// The location of the "unchecked" attribute, if present.
SourceLoc uncheckedLoc;
/// The location of the "preconcurrency" attribute if present.
SourceLoc preconcurrencyLoc;
/// The location of the "unsafe" attribute if present.
SourceLoc unsafeLoc;
ConformanceAttributes attributes;
/// Whether this inherited entry was suppressed via "~".
bool isSuppressed;
@@ -618,10 +612,9 @@ struct InheritedNominalEntry : Located<NominalTypeDecl *> {
InheritedNominalEntry() { }
InheritedNominalEntry(NominalTypeDecl *item, SourceLoc loc,
SourceLoc uncheckedLoc, SourceLoc preconcurrencyLoc,
SourceLoc unsafeLoc, bool isSuppressed)
: Located(item, loc), uncheckedLoc(uncheckedLoc),
preconcurrencyLoc(preconcurrencyLoc), unsafeLoc(unsafeLoc),
ConformanceAttributes attributes,
bool isSuppressed)
: Located(item, loc), attributes(attributes),
isSuppressed(isSuppressed) {}
};

View File

@@ -16,6 +16,7 @@
#include "ConformanceLookupTable.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ConformanceAttributes.h"
#include "swift/AST/ConformanceLookup.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ExistentialLayout.h"
@@ -148,23 +149,13 @@ void ConformanceLookupTable::destroy() {
namespace {
struct ConformanceConstructionInfo : public Located<ProtocolDecl *> {
/// The location of the "unchecked" attribute, if present.
const SourceLoc uncheckedLoc;
/// The location of the "preconcurrency" attribute if present.
const SourceLoc preconcurrencyLoc;
/// The location of the "unsafe" attribute if present.
const SourceLoc unsafeLoc;
ConformanceAttributes attributes;
ConformanceConstructionInfo() { }
ConformanceConstructionInfo(ProtocolDecl *item, SourceLoc loc,
SourceLoc uncheckedLoc,
SourceLoc preconcurrencyLoc,
SourceLoc unsafeLoc)
: Located(item, loc), uncheckedLoc(uncheckedLoc),
preconcurrencyLoc(preconcurrencyLoc), unsafeLoc(unsafeLoc) {}
ConformanceAttributes attributes)
: Located(item, loc), attributes(attributes) {}
};
}
@@ -220,7 +211,7 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage,
registerProtocolConformances(next, conformances);
for (auto conf : conformances) {
protocols.push_back(
{conf->getProtocol(), SourceLoc(), SourceLoc(), SourceLoc(), SourceLoc()});
{conf->getProtocol(), SourceLoc(), ConformanceAttributes()});
}
} else if (next->getParentSourceFile() ||
next->getParentModule()->isBuiltinModule()) {
@@ -229,9 +220,7 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage,
for (const auto &found :
getDirectlyInheritedNominalTypeDecls(next, inverses, anyObject)) {
if (auto proto = dyn_cast<ProtocolDecl>(found.Item))
protocols.push_back(
{proto, found.Loc, found.uncheckedLoc,
found.preconcurrencyLoc, found.unsafeLoc});
protocols.push_back({proto, found.Loc, found.attributes});
}
}
@@ -318,10 +307,8 @@ void ConformanceLookupTable::updateLookupTable(NominalTypeDecl *nominal,
kp.has_value() &&
"suppressed conformance for non-known protocol!?");
if (!found.isSuppressed) {
addProtocol(proto, found.Loc,
source.withUncheckedLoc(found.uncheckedLoc)
.withPreconcurrencyLoc(found.preconcurrencyLoc)
.withUnsafeLoc(found.unsafeLoc));
addProtocol(
proto, found.Loc, source.withAttributes(found.attributes));
}
}
@@ -335,9 +322,7 @@ void ConformanceLookupTable::updateLookupTable(NominalTypeDecl *nominal,
for (auto locAndProto : protos)
addProtocol(
locAndProto.Item, locAndProto.Loc,
source.withUncheckedLoc(locAndProto.uncheckedLoc)
.withPreconcurrencyLoc(locAndProto.preconcurrencyLoc)
.withUnsafeLoc(locAndProto.unsafeLoc));
source.withAttributes(locAndProto.attributes));
});
break;

View File

@@ -21,6 +21,7 @@
#define SWIFT_AST_CONFORMANCE_LOOKUP_TABLE_H
#include "swift/AST/DeclContext.h"
#include "swift/AST/ConformanceAttributes.h"
#include "swift/AST/ProtocolConformanceOptions.h"
#include "swift/Basic/Debug.h"
#include "swift/Basic/LLVM.h"
@@ -89,14 +90,7 @@ class ConformanceLookupTable : public ASTAllocated<ConformanceLookupTable> {
ConformanceEntryKind Kind;
/// The location of the "unchecked" attribute, if there is one.
SourceLoc uncheckedLoc;
/// The location of the "preconcurrency" attribute, if there is one.
SourceLoc preconcurrencyLoc;
/// The location of the "unsafe" attribute, if there is one.
SourceLoc unsafeLoc;
ConformanceAttributes attributes;
ConformanceSource(void *ptr, ConformanceEntryKind kind)
: Storage(ptr), Kind(kind) { }
@@ -140,29 +134,16 @@ class ConformanceLookupTable : public ASTAllocated<ConformanceLookupTable> {
return ConformanceSource(dc, ConformanceEntryKind::PreMacroExpansion);
}
/// Return a new conformance source with the given location of "@unchecked".
ConformanceSource withUncheckedLoc(SourceLoc uncheckedLoc) {
/// Return a new conformance source with the given conformance
/// attributes.
ConformanceSource withAttributes(ConformanceAttributes attributes) {
ConformanceSource result(*this);
if (uncheckedLoc.isValid())
result.uncheckedLoc = uncheckedLoc;
result.attributes |= attributes;
return result;
}
/// Return a new conformance source with the given location of
/// "@preconcurrency".
ConformanceSource withPreconcurrencyLoc(SourceLoc preconcurrencyLoc) {
ConformanceSource result(*this);
if (preconcurrencyLoc.isValid())
result.preconcurrencyLoc = preconcurrencyLoc;
return result;
}
/// Return a new conformance source with the given location of "@unsafe".
ConformanceSource withUnsafeLoc(SourceLoc unsafeLoc) {
ConformanceSource result(*this);
if (unsafeLoc.isValid())
result.unsafeLoc = unsafeLoc;
return result;
ConformanceAttributes getAttributes() const {
return attributes;
}
ProtocolConformanceOptions getOptions() const {
@@ -216,16 +197,16 @@ class ConformanceLookupTable : public ASTAllocated<ConformanceLookupTable> {
/// The location of the @unchecked attribute, if any.
SourceLoc getUncheckedLoc() const {
return uncheckedLoc;
return attributes.uncheckedLoc;
}
SourceLoc getPreconcurrencyLoc() const {
return preconcurrencyLoc;
return attributes.preconcurrencyLoc;
}
/// The location of the @unsafe attribute, if any.
SourceLoc getUnsafeLoc() const {
return unsafeLoc;
return attributes.unsafeLoc;
}
/// For an inherited conformance, retrieve the class declaration

View File

@@ -19,6 +19,7 @@
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/ClangModuleLoader.h"
#include "swift/AST/ConformanceAttributes.h"
#include "swift/AST/DebuggerClient.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/GenericParamList.h"
@@ -3962,23 +3963,19 @@ void swift::getDirectlyInheritedNominalTypeDecls(
// FIXME: This is a hack. We need cooperation from
// InheritedDeclsReferencedRequest to make this work.
SourceLoc loc;
SourceLoc uncheckedLoc;
SourceLoc preconcurrencyLoc;
SourceLoc unsafeLoc;
ConformanceAttributes attributes;
auto inheritedTypes = InheritedTypes(decl);
bool isSuppressed = inheritedTypes.getEntry(i).isSuppressed();
if (TypeRepr *typeRepr = inheritedTypes.getTypeRepr(i)) {
loc = typeRepr->getLoc();
uncheckedLoc = typeRepr->findAttrLoc(TypeAttrKind::Unchecked);
preconcurrencyLoc = typeRepr->findAttrLoc(TypeAttrKind::Preconcurrency);
unsafeLoc = typeRepr->findAttrLoc(TypeAttrKind::Unsafe);
attributes.uncheckedLoc = typeRepr->findAttrLoc(TypeAttrKind::Unchecked);
attributes.preconcurrencyLoc = typeRepr->findAttrLoc(TypeAttrKind::Preconcurrency);
attributes.unsafeLoc = typeRepr->findAttrLoc(TypeAttrKind::Unsafe);
}
// Form the result.
for (auto nominal : nominalTypes) {
result.push_back(
{nominal, loc, uncheckedLoc, preconcurrencyLoc, unsafeLoc,
isSuppressed});
result.push_back({nominal, loc, attributes, isSuppressed});
}
}
@@ -4008,10 +4005,11 @@ swift::getDirectlyInheritedNominalTypeDecls(
for (auto attr :
protoDecl->getAttrs().getAttributes<SynthesizedProtocolAttr>()) {
auto loc = attr->getLocation();
ConformanceAttributes attributes;
if (attr->isUnchecked())
attributes.uncheckedLoc = loc;
result.push_back(
{attr->getProtocol(), loc, attr->isUnchecked() ? loc : SourceLoc(),
/*preconcurrencyLoc=*/SourceLoc(), SourceLoc(),
/*isSuppressed=*/false});
{attr->getProtocol(), loc, attributes, /*isSuppressed=*/false});
}
// Else we have access to this information on the where clause.
@@ -4022,8 +4020,8 @@ swift::getDirectlyInheritedNominalTypeDecls(
// FIXME: Refactor SelfBoundsFromWhereClauseRequest to dig out
// the source location.
for (auto inheritedNominal : selfBounds.decls)
result.emplace_back(inheritedNominal, SourceLoc(), SourceLoc(),
SourceLoc(), SourceLoc(), /*isSuppressed=*/false);
result.emplace_back(inheritedNominal, SourceLoc(), ConformanceAttributes(),
/*isSuppressed=*/false);
return result;
}