Skip to content

Commit d47ef5f

Browse files
authored
Merge pull request #68818 from kavon/noncopyable-means-no-conformance
Noncopyable means no conformance to Copyable
2 parents ab1c369 + 0f2a8d5 commit d47ef5f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1087
-298
lines changed

include/swift/AST/Decl.h

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,9 @@ class InheritedTypes {
15961596
size_t size() const { return Entries.size(); }
15971597
IntRange<size_t> const getIndices() { return indices(Entries); }
15981598

1599+
/// Returns the ASTContext associated with the wrapped declaration.
1600+
ASTContext &getASTContext() const;
1601+
15991602
/// Returns the `TypeRepr *` for the entry of the inheritance clause at the
16001603
/// given index.
16011604
TypeRepr *getTypeRepr(unsigned i) const { return Entries[i].getTypeRepr(); }
@@ -1615,6 +1618,10 @@ class InheritedTypes {
16151618
/// NOTE: The `Type` associated with the entry may not be resolved yet.
16161619
const InheritedEntry &getEntry(unsigned i) const { return Entries[i]; }
16171620

1621+
// Retrieve the location of the colon character introducing the inheritance
1622+
// clause.
1623+
SourceLoc getColonLoc() const;
1624+
16181625
/// Returns the source location of the beginning of the inheritance clause.
16191626
SourceLoc getStartLoc() const {
16201627
return getEntries().front().getSourceRange().Start;
@@ -1624,6 +1631,10 @@ class InheritedTypes {
16241631
SourceLoc getEndLoc() const {
16251632
return getEntries().back().getSourceRange().End;
16261633
}
1634+
1635+
/// Compute the SourceRange to be used when removing entry \c i from the
1636+
/// inheritance clause. Accounts for commas and colons as-needed.
1637+
SourceRange getRemovalRange(unsigned i) const;
16271638
};
16281639

16291640
/// ExtensionDecl - This represents a type extension containing methods
@@ -2606,12 +2617,6 @@ class ValueDecl : public Decl {
26062617
/// optional result.
26072618
unsigned isIUO : 1;
26082619

2609-
/// Whether the "isMoveOnly" bit has been computed yet.
2610-
unsigned isMoveOnlyComputed : 1;
2611-
2612-
/// Whether this declaration can not be copied and thus is move only.
2613-
unsigned isMoveOnly : 1;
2614-
26152620
/// Whether the "isEscapable" bit has been computed yet.
26162621
unsigned isEscapable : 1;
26172622

@@ -2623,7 +2628,6 @@ class ValueDecl : public Decl {
26232628
friend class OverriddenDeclsRequest;
26242629
friend class IsObjCRequest;
26252630
friend class IsFinalRequest;
2626-
friend class IsMoveOnlyRequest;
26272631
friend class IsEscapableRequest;
26282632
friend class IsDynamicRequest;
26292633
friend class IsImplicitlyUnwrappedOptionalRequest;
@@ -2927,9 +2931,6 @@ class ValueDecl : public Decl {
29272931
/// Is this declaration 'final'?
29282932
bool isFinal() const;
29292933

2930-
/// Is this declaration 'moveOnly'?
2931-
bool isMoveOnly() const;
2932-
29332934
/// Is this declaration escapable?
29342935
bool isEscapable() const;
29352936

@@ -3105,8 +3106,18 @@ class ValueDecl : public Decl {
31053106

31063107
/// This is a common base class for declarations which declare a type.
31073108
class TypeDecl : public ValueDecl {
3109+
private:
31083110
ArrayRef<InheritedEntry> Inherited;
31093111

3112+
struct {
3113+
/// Whether the "hasNoncopyableAnnotation" bit has been computed yet.
3114+
unsigned isNoncopyableAnnotationComputed : 1;
3115+
3116+
/// Whether this declaration had a noncopyable inverse written somewhere.
3117+
unsigned hasNoncopyableAnnotation : 1;
3118+
} LazySemanticInfo = { };
3119+
friend class HasNoncopyableAnnotationRequest;
3120+
31103121
protected:
31113122
TypeDecl(DeclKind K, llvm::PointerUnion<DeclContext *, ASTContext *> context,
31123123
Identifier name, SourceLoc NameLoc,
@@ -3134,6 +3145,10 @@ class TypeDecl : public ValueDecl {
31343145

31353146
void setInherited(ArrayRef<InheritedEntry> i) { Inherited = i; }
31363147

3148+
/// Is this type _always_ noncopyable? Will answer 'false' if the type is
3149+
/// conditionally copyable.
3150+
bool isNoncopyable() const;
3151+
31373152
static bool classof(const Decl *D) {
31383153
return D->getKind() >= DeclKind::First_TypeDecl &&
31393154
D->getKind() <= DeclKind::Last_TypeDecl;

include/swift/AST/DiagnosticsSema.def

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2392,6 +2392,10 @@ ERROR(inferred_opaque_type,none,
23922392
// Inverse Constraints
23932393
ERROR(inverse_type_not_invertible,none,
23942394
"type %0 is not invertible", (Type))
2395+
ERROR(inverse_duplicate,none,
2396+
"duplicate inverse constraint", ())
2397+
NOTE(inverse_duplicate_previous,none,
2398+
"previous inverse constraint here", ())
23952399

23962400
// Extensions
23972401
ERROR(non_nominal_extension,none,
@@ -7445,6 +7449,28 @@ ERROR(accessor_macro_not_single_var, none,
74457449
// MARK: Noncopyable Types Diagnostics
74467450
//------------------------------------------------------------------------------
74477451

7452+
ERROR(noncopyable_class, none,
7453+
"classes cannot be noncopyable",
7454+
())
7455+
ERROR(noncopyable_type_member_in_copyable,none,
7456+
"%select{stored property %2|associated value %2}1 of "
7457+
"'Copyable'-conforming %kind3 has noncopyable type %0",
7458+
(Type, bool, DeclName, const ValueDecl *))
7459+
NOTE(add_inverse_for_containment,none,
7460+
"consider removing implicit '%1' conformance from %kind0",
7461+
(const ValueDecl *, StringRef))
7462+
NOTE(remove_inverse_on_generic_parameter_for_conformance,none,
7463+
"consider removing '~%1' from generic parameter %0 so it conforms to the '%1' protocol",
7464+
(Type, StringRef))
7465+
NOTE(remove_inverse_on_nominal_for_conformance,none,
7466+
"consider removing '~%1' from %kind0 so it conforms to the '%1' protocol",
7467+
(const ValueDecl *, StringRef))
7468+
NOTE(add_explicit_protocol_for_conformance,none,
7469+
"consider making %kind0 explicitly conform to the '%1' protocol",
7470+
(const ValueDecl *, StringRef))
7471+
7472+
// -- older ones below --
7473+
74487474
ERROR(noncopyable_within_copyable, none,
74497475
"%kind0 cannot contain a noncopyable type without also being noncopyable",
74507476
(const ValueDecl *))
@@ -7460,11 +7486,6 @@ ERROR(noncopyable_parameter_subscript_unsupported, none,
74607486
"subscripts cannot have noncopyable parameters yet", ())
74617487
NOTE(noncopyable_parameter_ownership_suggestion, none,
74627488
"add '%0' %1", (StringRef, StringRef))
7463-
ERROR(ownership_specifier_copyable,none,
7464-
"copyable types cannot be 'consuming' or 'borrowing' yet", ())
7465-
ERROR(self_ownership_specifier_copyable,none,
7466-
"%0 is not yet valid on %1s of a copyable type",
7467-
(SelfAccessKind, DescriptiveDeclKind))
74687489
ERROR(ownership_specifier_nonescaping_closure,none,
74697490
"'%0' cannot be applied to nonescaping closure", (StringRef))
74707491
ERROR(noncopyable_generics, none,

include/swift/AST/TypeCheckRequests.h

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,10 @@ class IsFinalRequest :
407407
void cacheResult(bool value) const;
408408
};
409409

410-
/// Determine whether the given declaration is 'moveOnly'.
411-
class IsMoveOnlyRequest
412-
: public SimpleRequest<IsMoveOnlyRequest, bool(ValueDecl *),
410+
/// Determine whether the given declaration has any markings that would cause it
411+
/// to not have an implicit, unconditional conformance to Copyable.
412+
class HasNoncopyableAnnotationRequest
413+
: public SimpleRequest<HasNoncopyableAnnotationRequest, bool(TypeDecl *),
413414
RequestFlags::SeparatelyCached> {
414415
public:
415416
using SimpleRequest::SimpleRequest;
@@ -418,7 +419,7 @@ class IsMoveOnlyRequest
418419
friend SimpleRequest;
419420

420421
// Evaluation.
421-
bool evaluate(Evaluator &evaluator, ValueDecl *decl) const;
422+
bool evaluate(Evaluator &evaluator, TypeDecl *decl) const;
422423

423424
public:
424425
// Separate caching.
@@ -427,7 +428,6 @@ class IsMoveOnlyRequest
427428
void cacheResult(bool value) const;
428429
};
429430

430-
431431
/// Determine whether the given declaration is escapable.
432432
class IsEscapableRequest
433433
: public SimpleRequest<IsEscapableRequest, bool(ValueDecl *),
@@ -448,6 +448,25 @@ class IsEscapableRequest
448448
void cacheResult(bool value) const;
449449
};
450450

451+
/// Determine whether the given type is noncopyable. Assumes type parameters
452+
/// have become archetypes.
453+
class IsNoncopyableRequest
454+
: public SimpleRequest<IsNoncopyableRequest, bool(CanType),
455+
RequestFlags::Cached> {
456+
public:
457+
using SimpleRequest::SimpleRequest;
458+
459+
private:
460+
friend SimpleRequest;
461+
462+
// Evaluation.
463+
bool evaluate(Evaluator &evaluator, CanType type) const;
464+
465+
public:
466+
// Caching.
467+
bool isCached() const { return true; }
468+
};
469+
451470
/// Determine whether the given declaration is 'dynamic''.
452471
class IsDynamicRequest :
453472
public SimpleRequest<IsDynamicRequest,
@@ -3779,11 +3798,11 @@ class SynthesizeMainFunctionRequest
37793798
bool isCached() const { return true; }
37803799
};
37813800

3782-
/// Retrieve the implicit conformance for the given nominal type to
3783-
/// the Sendable protocol.
3784-
class GetImplicitSendableRequest :
3785-
public SimpleRequest<GetImplicitSendableRequest,
3786-
ProtocolConformance *(NominalTypeDecl *),
3801+
/// Compute the implicit conformance for the given nominal type to
3802+
/// an known protocol, if implicit conformances are permitted.
3803+
class ImplicitKnownProtocolConformanceRequest :
3804+
public SimpleRequest<ImplicitKnownProtocolConformanceRequest,
3805+
ProtocolConformance *(NominalTypeDecl *, KnownProtocolKind),
37873806
RequestFlags::Cached> {
37883807
public:
37893808
using SimpleRequest::SimpleRequest;
@@ -3792,7 +3811,7 @@ class GetImplicitSendableRequest :
37923811
friend SimpleRequest;
37933812

37943813
ProtocolConformance *evaluate(
3795-
Evaluator &evaluator, NominalTypeDecl *nominal) const;
3814+
Evaluator &evaluator, NominalTypeDecl *nominal, KnownProtocolKind kp) const;
37963815

37973816
public:
37983817
// Caching

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,11 @@ SWIFT_REQUEST(TypeChecker, IsDynamicRequest, bool(ValueDecl *),
210210
SeparatelyCached, NoLocationInfo)
211211
SWIFT_REQUEST(TypeChecker, IsFinalRequest, bool(ValueDecl *), SeparatelyCached,
212212
NoLocationInfo)
213-
SWIFT_REQUEST(TypeChecker, IsMoveOnlyRequest, bool(ValueDecl *), SeparatelyCached,
213+
SWIFT_REQUEST(TypeChecker, HasNoncopyableAnnotationRequest, bool(TypeDecl *), SeparatelyCached,
214214
NoLocationInfo)
215+
SWIFT_REQUEST(TypeChecker, IsNoncopyableRequest,
216+
bool (CanType),
217+
Cached, NoLocationInfo)
215218
SWIFT_REQUEST(TypeChecker, IsEscapableRequest, bool(ValueDecl *),
216219
SeparatelyCached, NoLocationInfo)
217220
SWIFT_REQUEST(TypeChecker, IsGetterMutatingRequest, bool(AbstractStorageDecl *),
@@ -426,8 +429,8 @@ SWIFT_REQUEST(TypeChecker, SimpleDidSetRequest,
426429
bool(AccessorDecl *), Cached, NoLocationInfo)
427430
SWIFT_REQUEST(TypeChecker, SynthesizeMainFunctionRequest,
428431
FuncDecl *(Decl *), Cached, NoLocationInfo)
429-
SWIFT_REQUEST(TypeChecker, GetImplicitSendableRequest,
430-
ProtocolConformance *(NominalTypeDecl *),
432+
SWIFT_REQUEST(TypeChecker, ImplicitKnownProtocolConformanceRequest,
433+
ProtocolConformance *(NominalTypeDecl *, KnownProtocolKind),
431434
Cached, NoLocationInfo)
432435
SWIFT_REQUEST(TypeChecker, RenamedDeclRequest,
433436
ValueDecl *(const ValueDecl *, const AvailableAttr *),

include/swift/AST/TypeRepr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,7 @@ class ExistentialTypeRepr: public TypeRepr {
13251325
friend class TypeRepr;
13261326
};
13271327

1328-
/// A type repr represeting the inverse of some constraint. For example,
1328+
/// A type repr representing the inverse of some constraint. For example,
13291329
/// ~Copyable
13301330
/// where `Copyable` is the constraint type.
13311331
class InverseTypeRepr : public TypeRepr {

include/swift/AST/Types.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class ProtocolConformance;
100100
enum PointerTypeKind : unsigned;
101101
struct ValueOwnershipKind;
102102
class ErrorExpr;
103+
enum class KnownProtocolKind : uint8_t;
103104

104105
typedef CanTypeWrapper<SILFunctionType> CanSILFunctionType;
105106

@@ -636,9 +637,12 @@ class alignas(1 << TypeAlignInBits) TypeBase
636637

637638
bool isPlaceholder();
638639

639-
/// Returns true if this is a noncopyable type.
640+
/// DEPRECIATED: Returns true if this is a noncopyable type.
640641
bool isNoncopyable();
641642

643+
/// Returns true if this type lacks conformance to Copyable in the context.
644+
bool isNoncopyable(const DeclContext *dc);
645+
642646
/// Does the type have outer parenthesis?
643647
bool hasParenSugar() const { return getKind() == TypeKind::Paren; }
644648

@@ -928,6 +932,9 @@ class alignas(1 << TypeAlignInBits) TypeBase
928932
return getAnyBufferPointerElementType(Ignore);
929933
}
930934

935+
/// If this type is a known protocol, return its kind.
936+
llvm::Optional<KnownProtocolKind> getKnownProtocol();
937+
931938
/// Determine whether the given type is "specialized", meaning that
932939
/// it involves generic types for which generic arguments have been provided.
933940
/// For example, the types Vector<Int> and Vector<Int>.Element are both
@@ -7333,6 +7340,10 @@ inline GenericTypeDecl *TypeBase::getAnyGeneric() {
73337340
return getCanonicalType().getAnyGeneric();
73347341
}
73357342

7343+
//inline TypeDecl *TypeBase::getAnyTypeDecl() {
7344+
// return getCanonicalType().getAnyTypeDecl();
7345+
//}
7346+
73367347
inline bool TypeBase::isBuiltinIntegerType(unsigned n) {
73377348
if (auto intTy = dyn_cast<BuiltinIntegerType>(getCanonicalType()))
73387349
return intTy->getWidth().isFixedWidth()

lib/AST/ASTContext.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6174,6 +6174,17 @@ BuiltinTupleDecl *ASTContext::getBuiltinTupleDecl() {
61746174
result = new (*this) BuiltinTupleDecl(Id_TheTupleType, dc);
61756175
result->setAccess(AccessLevel::Public);
61766176

6177+
// Avoid going through InferredGenericSignatureRequest and directly set the
6178+
// generic signature to <each Element>
6179+
{
6180+
GenericParamList *list = result->getGenericParams();
6181+
assert(list->size() == 1);
6182+
auto paramTy = (*list->begin())->getDeclaredInterfaceType()
6183+
->castTo<GenericTypeParamType>();
6184+
auto baseSig = GenericSignature::get({paramTy}, {});
6185+
result->setGenericSignature(baseSig);
6186+
}
6187+
61776188
// Cook up conditional conformances to Sendable and Copyable.
61786189
auto buildFakeExtension = [&](ProtocolDecl *proto) {
61796190
auto protoTy = proto->getDeclaredInterfaceType();

lib/AST/ASTPrinter.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3327,14 +3327,16 @@ static bool usesFeatureFlowSensitiveConcurrencyCaptures(Decl *decl) {
33273327
static bool usesFeatureMoveOnly(Decl *decl) {
33283328
if (auto *extension = dyn_cast<ExtensionDecl>(decl)) {
33293329
if (auto *nominal = extension->getSelfNominalTypeDecl())
3330-
if (nominal->isMoveOnly())
3330+
if (nominal->isNoncopyable())
33313331
return true;
33323332
}
33333333

3334-
if (auto value = dyn_cast<ValueDecl>(decl)) {
3335-
if (value->isMoveOnly())
3336-
return true;
3334+
if (auto typeDecl = dyn_cast<TypeDecl>(decl)) {
3335+
if (typeDecl->isNoncopyable())
3336+
return true;
3337+
}
33373338

3339+
if (auto value = dyn_cast<ValueDecl>(decl)) {
33383340
// Check for move-only types in the types of this declaration.
33393341
if (Type type = value->getInterfaceType()) {
33403342
bool hasMoveOnly = type.findIf([](Type type) {

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->isMoveOnly() && !DD->isInvalid()) {
3241+
if (!isa<ClassDecl>(ND) && !ND->isNoncopyable() && !DD->isInvalid()) {
32423242
Out << "DestructorDecls outside classes/move only types should be "
32433243
"marked invalid\n";
32443244
abort();

lib/AST/ConformanceLookupTable.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,8 @@ DeclContext *ConformanceLookupTable::getConformingContext(
848848
const auto &superclassConformances =
849849
superclassDecl->ConformanceTable->Conformances[protocol];
850850
if (superclassConformances.empty()) {
851-
assert(protocol->isSpecificProtocol(KnownProtocolKind::Sendable));
851+
assert(protocol->isSpecificProtocol(KnownProtocolKind::Sendable) ||
852+
protocol->isSpecificProtocol(KnownProtocolKind::Copyable));
852853

853854
// Go dig for a superclass that does conform to Sendable.
854855
// FIXME: This is a hack because the inherited conformances aren't

0 commit comments

Comments
 (0)