Skip to content

Commit a9c64ba

Browse files
committed
[Sema] refactor TypeDecl::isNoncopyable
In preparation for reporting whether the inverse marking on a TypeDecl was inferred instead of explicit.
1 parent 455fcdc commit a9c64ba

27 files changed

+96
-72
lines changed

include/swift/AST/Decl.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3118,13 +3118,14 @@ class TypeDecl : public ValueDecl {
31183118
ArrayRef<InheritedEntry> Inherited;
31193119

31203120
struct {
3121-
/// Whether the "hasNoncopyableAnnotation" bit has been computed yet.
3121+
/// Whether the "noncopyableAnnotationKind" field has been computed yet.
31223122
unsigned isNoncopyableAnnotationComputed : 1;
31233123

3124-
/// Whether this declaration had a noncopyable inverse written somewhere.
3125-
unsigned hasNoncopyableAnnotation : 1;
3124+
unsigned noncopyableAnnotationKind : 2;
3125+
static_assert((unsigned)InverseMarkingKind::LAST < 4);
3126+
31263127
} LazySemanticInfo = { };
3127-
friend class HasNoncopyableAnnotationRequest;
3128+
friend class NoncopyableAnnotationRequest;
31283129

31293130
protected:
31303131
TypeDecl(DeclKind K, llvm::PointerUnion<DeclContext *, ASTContext *> context,
@@ -3153,9 +3154,15 @@ class TypeDecl : public ValueDecl {
31533154

31543155
void setInherited(ArrayRef<InheritedEntry> i) { Inherited = i; }
31553156

3156-
/// Is this type _always_ noncopyable? Will answer 'false' if the type is
3157-
/// conditionally copyable.
3158-
bool isNoncopyable() const;
3157+
/// Is it possible for this type to lack a Copyable constraint?
3158+
/// If you need a more precise answer, ask this Decl's corresponding
3159+
/// Type if it `isNoncopyable` instead of using this.
3160+
bool canBeNoncopyable() const {
3161+
return getNoncopyableMarking() != InverseMarkingKind::None;
3162+
}
3163+
3164+
/// Determine how the ~Copyable was applied to this TypeDecl, if at all.
3165+
InverseMarkingKind getNoncopyableMarking() const;
31593166

31603167
static bool classof(const Decl *D) {
31613168
return D->getKind() >= DeclKind::First_TypeDecl &&

include/swift/AST/KnownProtocols.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,15 @@ llvm::Optional<InvertibleProtocolKind>
7373
/// Returns the KnownProtocolKind corresponding to an InvertibleProtocolKind.
7474
KnownProtocolKind getKnownProtocolKind(InvertibleProtocolKind ip);
7575

76+
/// Describes the way an inverse was applied to a TypeDecl.
77+
enum class InverseMarkingKind: uint8_t {
78+
None, // No inverse marking is present
79+
Inferred, // Inverse is inferred based on generic parameters.
80+
Explicit, // Inverse is explicitly present.
81+
82+
LAST = Explicit
83+
};
84+
7685
} // end namespace swift
7786

7887
#endif

include/swift/AST/TypeCheckRequests.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -427,10 +427,10 @@ class IsFinalRequest :
427427
void cacheResult(bool value) const;
428428
};
429429

430-
/// Determine whether the given declaration has any markings that would cause it
431-
/// to not have an implicit, unconditional conformance to Copyable.
432-
class HasNoncopyableAnnotationRequest
433-
: public SimpleRequest<HasNoncopyableAnnotationRequest, bool(TypeDecl *),
430+
/// Determine the kind of noncopyable marking present for this declaration.
431+
class NoncopyableAnnotationRequest
432+
: public SimpleRequest<NoncopyableAnnotationRequest,
433+
InverseMarkingKind(TypeDecl *),
434434
RequestFlags::SeparatelyCached> {
435435
public:
436436
using SimpleRequest::SimpleRequest;
@@ -439,13 +439,13 @@ class HasNoncopyableAnnotationRequest
439439
friend SimpleRequest;
440440

441441
// Evaluation.
442-
bool evaluate(Evaluator &evaluator, TypeDecl *decl) const;
442+
InverseMarkingKind evaluate(Evaluator &evaluator, TypeDecl *decl) const;
443443

444444
public:
445445
// Separate caching.
446446
bool isCached() const { return true; }
447-
llvm::Optional<bool> getCachedResult() const;
448-
void cacheResult(bool value) const;
447+
llvm::Optional<InverseMarkingKind> getCachedResult() const;
448+
void cacheResult(InverseMarkingKind value) const;
449449
};
450450

451451
/// Determine whether the given declaration is escapable.

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,9 @@ SWIFT_REQUEST(TypeChecker, IsDynamicRequest, bool(ValueDecl *),
210210
SeparatelyCached, NoLocationInfo)
211211
SWIFT_REQUEST(TypeChecker, IsFinalRequest, bool(ValueDecl *), SeparatelyCached,
212212
NoLocationInfo)
213-
SWIFT_REQUEST(TypeChecker, HasNoncopyableAnnotationRequest, bool(TypeDecl *), SeparatelyCached,
214-
NoLocationInfo)
213+
SWIFT_REQUEST(TypeChecker, NoncopyableAnnotationRequest,
214+
InverseMarkingKind(TypeDecl *),
215+
SeparatelyCached, NoLocationInfo)
215216
SWIFT_REQUEST(TypeChecker, IsNoncopyableRequest,
216217
bool (CanType),
217218
Cached, NoLocationInfo)

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3324,12 +3324,12 @@ static bool usesFeatureFlowSensitiveConcurrencyCaptures(Decl *decl) {
33243324
static bool usesFeatureMoveOnly(Decl *decl) {
33253325
if (auto *extension = dyn_cast<ExtensionDecl>(decl)) {
33263326
if (auto *nominal = extension->getSelfNominalTypeDecl())
3327-
if (nominal->isNoncopyable())
3327+
if (nominal->canBeNoncopyable())
33283328
return true;
33293329
}
33303330

33313331
if (auto typeDecl = dyn_cast<TypeDecl>(decl)) {
3332-
if (typeDecl->isNoncopyable())
3332+
if (typeDecl->canBeNoncopyable())
33333333
return true;
33343334
}
33353335

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3238,7 +3238,7 @@ class Verifier : public ASTWalker {
32383238
PrettyStackTraceDecl debugStack("verifying DestructorDecl", DD);
32393239

32403240
auto *ND = DD->getDeclContext()->getSelfNominalTypeDecl();
3241-
if (!isa<ClassDecl>(ND) && !ND->isNoncopyable() && !DD->isInvalid()) {
3241+
if (!isa<ClassDecl>(ND) && !ND->canBeNoncopyable() && !DD->isInvalid()) {
32423242
Out << "DestructorDecls outside classes/move only types should be "
32433243
"marked invalid\n";
32443244
abort();

lib/AST/Decl.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4876,12 +4876,11 @@ GenericParameterReferenceInfo ValueDecl::findExistentialSelfReferences(
48764876
llvm::None);
48774877
}
48784878

4879-
bool TypeDecl::isNoncopyable() const {
4880-
// NOTE: must answer true iff it is unconditionally noncopyable.
4879+
InverseMarkingKind TypeDecl::getNoncopyableMarking() const {
48814880
return evaluateOrDefault(getASTContext().evaluator,
4882-
HasNoncopyableAnnotationRequest{
4881+
NoncopyableAnnotationRequest{
48834882
const_cast<TypeDecl *>(this)},
4884-
true); // default to true for safety
4883+
InverseMarkingKind::Explicit);
48854884
}
48864885

48874886
Type TypeDecl::getDeclaredInterfaceType() const {

lib/AST/Module.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2019,7 +2019,7 @@ LookupConformanceInModuleRequest::evaluate(
20192019
// We only need to do this until we are properly dealing with or
20202020
// omitting Copyable conformances in modules/interfaces.
20212021

2022-
if (nominal->isNoncopyable())
2022+
if (nominal->canBeNoncopyable())
20232023
return ProtocolConformanceRef::forMissingOrInvalid(type, protocol);
20242024
else
20252025
return ProtocolConformanceRef(protocol);

lib/AST/ProtocolConformance.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,7 @@ void NominalTypeDecl::prepareConformanceTable() const {
10471047
return;
10481048

10491049
// No synthesized conformances for move-only nominals.
1050-
if (isNoncopyable()) {
1050+
if (canBeNoncopyable()) {
10511051
// assumption is Sendable gets synthesized elsewhere.
10521052
assert(!proto->isSpecificProtocol(KnownProtocolKind::Sendable));
10531053
return;

lib/AST/SwiftNameTranslation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ swift::cxx_translation::getDeclRepresentation(const ValueDecl *VD) {
234234
if (isa<ProtocolDecl>(typeDecl))
235235
return {Unsupported, UnrepresentableProtocol};
236236
// Swift's consume semantics are not yet supported in C++.
237-
if (typeDecl->isNoncopyable())
237+
if (typeDecl->canBeNoncopyable())
238238
return {Unsupported, UnrepresentableMoveOnly};
239239
if (typeDecl->isGeneric()) {
240240
if (isa<ClassDecl>(VD))

0 commit comments

Comments
 (0)