Skip to content

Commit 5a13cc0

Browse files
authored
Merge pull request #38343 from DougGregor/unchecked-sendable
[SE-0302] Implement '@unchecked Sendable' syntax.
2 parents cd55abb + 6269170 commit 5a13cc0

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

+455
-306
lines changed

include/swift/AST/ASTContext.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,7 +1019,8 @@ class ASTContext final {
10191019
ProtocolDecl *protocol,
10201020
SourceLoc loc,
10211021
DeclContext *dc,
1022-
ProtocolConformanceState state);
1022+
ProtocolConformanceState state,
1023+
bool isUnchecked);
10231024

10241025
/// Produce a self-conformance for the given protocol.
10251026
SelfProtocolConformance *

include/swift/AST/ASTPrinter.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/Basic/QuotedString.h"
1818
#include "swift/Basic/UUID.h"
1919
#include "swift/AST/Identifier.h"
20+
#include "swift/AST/Decl.h"
2021
#include "llvm/ADT/SmallString.h"
2122
#include "llvm/ADT/StringRef.h"
2223
#include "llvm/ADT/DenseSet.h"
@@ -351,8 +352,9 @@ void printEnumElementsAsCases(
351352
llvm::DenseSet<EnumElementDecl *> &UnhandledElements,
352353
llvm::raw_ostream &OS);
353354

354-
void getInheritedForPrinting(const Decl *decl, const PrintOptions &options,
355-
llvm::SmallVectorImpl<TypeLoc> &Results);
355+
void getInheritedForPrinting(
356+
const Decl *decl, const PrintOptions &options,
357+
llvm::SmallVectorImpl<InheritedEntry> &Results);
356358

357359
StringRef getAccessorKindString(AccessorKind value);
358360

include/swift/AST/Attr.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ TYPE_ATTR(differentiable)
5555
TYPE_ATTR(noDerivative)
5656
TYPE_ATTR(async)
5757
TYPE_ATTR(Sendable)
58+
TYPE_ATTR(unchecked)
5859

5960
// SIL-specific attributes
6061
TYPE_ATTR(block_storage)

include/swift/AST/Decl.h

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,17 @@ class ImportDecl final : public Decl,
12091209
}
12101210
};
12111211

1212+
/// An entry in the "inherited" list of a type or extension.
1213+
struct InheritedEntry : public TypeLoc {
1214+
/// Whether there was an @unchecked attribute.
1215+
bool isUnchecked = false;
1216+
1217+
InheritedEntry(const TypeLoc &typeLoc);
1218+
1219+
InheritedEntry(const TypeLoc &typeLoc, bool isUnchecked)
1220+
: TypeLoc(typeLoc), isUnchecked(isUnchecked) { }
1221+
};
1222+
12121223
/// ExtensionDecl - This represents a type extension containing methods
12131224
/// associated with the type. This is not a ValueDecl and has no Type because
12141225
/// there are no runtime values of the Extension's type.
@@ -1227,7 +1238,7 @@ class ExtensionDecl final : public GenericContext, public Decl,
12271238
/// extended nominal.
12281239
llvm::PointerIntPair<NominalTypeDecl *, 1, bool> ExtendedNominal;
12291240

1230-
ArrayRef<TypeLoc> Inherited;
1241+
ArrayRef<InheritedEntry> Inherited;
12311242

12321243
/// The next extension in the linked list of extensions.
12331244
///
@@ -1246,7 +1257,7 @@ class ExtensionDecl final : public GenericContext, public Decl,
12461257
friend class IterableDeclContext;
12471258

12481259
ExtensionDecl(SourceLoc extensionLoc, TypeRepr *extendedType,
1249-
ArrayRef<TypeLoc> inherited,
1260+
ArrayRef<InheritedEntry> inherited,
12501261
DeclContext *parent,
12511262
TrailingWhereClause *trailingWhereClause);
12521263

@@ -1271,7 +1282,7 @@ class ExtensionDecl final : public GenericContext, public Decl,
12711282
/// Create a new extension declaration.
12721283
static ExtensionDecl *create(ASTContext &ctx, SourceLoc extensionLoc,
12731284
TypeRepr *extendedType,
1274-
ArrayRef<TypeLoc> inherited,
1285+
ArrayRef<InheritedEntry> inherited,
12751286
DeclContext *parent,
12761287
TrailingWhereClause *trailingWhereClause,
12771288
ClangNode clangNode = ClangNode());
@@ -1326,9 +1337,9 @@ class ExtensionDecl final : public GenericContext, public Decl,
13261337

13271338
/// Retrieve the set of protocols that this type inherits (i.e,
13281339
/// explicitly conforms to).
1329-
ArrayRef<TypeLoc> getInherited() const { return Inherited; }
1340+
ArrayRef<InheritedEntry> getInherited() const { return Inherited; }
13301341

1331-
void setInherited(ArrayRef<TypeLoc> i) { Inherited = i; }
1342+
void setInherited(ArrayRef<InheritedEntry> i) { Inherited = i; }
13321343

13331344
bool hasDefaultAccessLevel() const {
13341345
return Bits.ExtensionDecl.DefaultAndMaxAccessLevel != 0;
@@ -2538,12 +2549,12 @@ class ValueDecl : public Decl {
25382549

25392550
/// This is a common base class for declarations which declare a type.
25402551
class TypeDecl : public ValueDecl {
2541-
ArrayRef<TypeLoc> Inherited;
2552+
ArrayRef<InheritedEntry> Inherited;
25422553

25432554
protected:
25442555
TypeDecl(DeclKind K, llvm::PointerUnion<DeclContext *, ASTContext *> context,
25452556
Identifier name, SourceLoc NameLoc,
2546-
ArrayRef<TypeLoc> inherited) :
2557+
ArrayRef<InheritedEntry> inherited) :
25472558
ValueDecl(K, context, name, NameLoc), Inherited(inherited) {}
25482559

25492560
public:
@@ -2561,9 +2572,9 @@ class TypeDecl : public ValueDecl {
25612572

25622573
/// Retrieve the set of protocols that this type inherits (i.e,
25632574
/// explicitly conforms to).
2564-
ArrayRef<TypeLoc> getInherited() const { return Inherited; }
2575+
ArrayRef<InheritedEntry> getInherited() const { return Inherited; }
25652576

2566-
void setInherited(ArrayRef<TypeLoc> i) { Inherited = i; }
2577+
void setInherited(ArrayRef<InheritedEntry> i) { Inherited = i; }
25672578

25682579
static bool classof(const Decl *D) {
25692580
return D->getKind() >= DeclKind::First_TypeDecl &&
@@ -2588,7 +2599,7 @@ class GenericTypeDecl : public GenericContext, public TypeDecl {
25882599
public:
25892600
GenericTypeDecl(DeclKind K, DeclContext *DC,
25902601
Identifier name, SourceLoc nameLoc,
2591-
ArrayRef<TypeLoc> inherited,
2602+
ArrayRef<InheritedEntry> inherited,
25922603
GenericParamList *GenericParams);
25932604

25942605
// Resolve ambiguity due to multiple base classes.
@@ -3115,7 +3126,7 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
31153126

31163127
NominalTypeDecl(DeclKind K, DeclContext *DC, Identifier name,
31173128
SourceLoc NameLoc,
3118-
ArrayRef<TypeLoc> inherited,
3129+
ArrayRef<InheritedEntry> inherited,
31193130
GenericParamList *GenericParams) :
31203131
GenericTypeDecl(K, DC, name, NameLoc, inherited, GenericParams),
31213132
IterableDeclContext(IterableDeclContextKind::NominalTypeDecl)
@@ -3411,7 +3422,7 @@ class EnumDecl final : public NominalTypeDecl {
34113422

34123423
public:
34133424
EnumDecl(SourceLoc EnumLoc, Identifier Name, SourceLoc NameLoc,
3414-
ArrayRef<TypeLoc> Inherited,
3425+
ArrayRef<InheritedEntry> Inherited,
34153426
GenericParamList *GenericParams, DeclContext *DC);
34163427

34173428
SourceLoc getStartLoc() const { return EnumLoc; }
@@ -3579,7 +3590,7 @@ class StructDecl final : public NominalTypeDecl {
35793590

35803591
public:
35813592
StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc,
3582-
ArrayRef<TypeLoc> Inherited,
3593+
ArrayRef<InheritedEntry> Inherited,
35833594
GenericParamList *GenericParams, DeclContext *DC);
35843595

35853596
SourceLoc getStartLoc() const { return StructLoc; }
@@ -3725,7 +3736,7 @@ class ClassDecl final : public NominalTypeDecl {
37253736

37263737
public:
37273738
ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
3728-
ArrayRef<TypeLoc> Inherited,
3739+
ArrayRef<InheritedEntry> Inherited,
37293740
GenericParamList *GenericParams, DeclContext *DC,
37303741
bool isActor);
37313742

@@ -4160,7 +4171,7 @@ class ProtocolDecl final : public NominalTypeDecl {
41604171

41614172
public:
41624173
ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc,
4163-
Identifier Name, ArrayRef<TypeLoc> Inherited,
4174+
Identifier Name, ArrayRef<InheritedEntry> Inherited,
41644175
TrailingWhereClause *TrailingWhere);
41654176

41664177
using Decl::getASTContext;

include/swift/AST/DiagnosticsSema.def

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4516,16 +4516,23 @@ ERROR(concurrent_value_class_mutable_property,none,
45164516
(DeclName, DescriptiveDeclKind, DeclName))
45174517
ERROR(concurrent_value_outside_source_file,none,
45184518
"conformance to 'Sendable' must occur in the same source file as "
4519-
"%0 %1; use 'UnsafeSendable' for retroactive conformance",
4519+
"%0 %1; use '@unchecked Sendable' for retroactive conformance",
45204520
(DescriptiveDeclKind, DeclName))
45214521
ERROR(concurrent_value_nonfinal_class,none,
45224522
"non-final class %0 cannot conform to `Sendable`; "
4523-
"use `UnsafeSendable`", (DeclName))
4523+
"use `@unchecked Sendable`", (DeclName))
45244524
ERROR(concurrent_value_inherit,none,
45254525
"`Sendable` class %1 cannot inherit from another class"
45264526
"%select{| other than 'NSObject'}0",
45274527
(bool, DeclName))
45284528

4529+
WARNING(unchecked_conformance_not_special,none,
4530+
"@unchecked conformance to %0 has no meaning", (Type))
4531+
ERROR(unchecked_not_inheritance_clause,none,
4532+
"'unchecked' attribute only applies in inheritance clauses", ())
4533+
ERROR(unchecked_not_existential,none,
4534+
"'unchecked' attribute cannot apply to non-protocol type %0", (Type))
4535+
45294536
ERROR(nonisolated_let,none,
45304537
"'nonisolated' is meaningless on 'let' declarations because "
45314538
"they are immutable",

include/swift/AST/NameLookup.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,19 @@ void filterForDiscriminator(SmallVectorImpl<Result> &results,
503503

504504
} // end namespace namelookup
505505

506+
/// Describes an inherited nominal entry.
507+
struct InheritedNominalEntry : Located<NominalTypeDecl *> {
508+
/// The location of the "unchecked" attribute, if present.
509+
SourceLoc uncheckedLoc;
510+
511+
InheritedNominalEntry() { }
512+
513+
InheritedNominalEntry(
514+
NominalTypeDecl *item, SourceLoc loc,
515+
SourceLoc uncheckedLoc
516+
) : Located(item, loc), uncheckedLoc(uncheckedLoc) { }
517+
};
518+
506519
/// Retrieve the set of nominal type declarations that are directly
507520
/// "inherited" by the given declaration at a particular position in the
508521
/// list of "inherited" types.
@@ -511,15 +524,15 @@ void filterForDiscriminator(SmallVectorImpl<Result> &results,
511524
/// AnyObject type, set \c anyObject true.
512525
void getDirectlyInheritedNominalTypeDecls(
513526
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl,
514-
unsigned i, llvm::SmallVectorImpl<Located<NominalTypeDecl *>> &result,
527+
unsigned i, llvm::SmallVectorImpl<InheritedNominalEntry> &result,
515528
bool &anyObject);
516529

517530
/// Retrieve the set of nominal type declarations that are directly
518531
/// "inherited" by the given declaration, looking through typealiases
519532
/// and splitting out the components of compositions.
520533
///
521534
/// If we come across the AnyObject type, set \c anyObject true.
522-
SmallVector<Located<NominalTypeDecl *>, 4> getDirectlyInheritedNominalTypeDecls(
535+
SmallVector<InheritedNominalEntry, 4> getDirectlyInheritedNominalTypeDecls(
523536
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl,
524537
bool &anyObject);
525538

include/swift/AST/ProtocolConformance.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -412,11 +412,20 @@ class NormalProtocolConformance : public RootProtocolConformance,
412412
/// The location of this protocol conformance in the source.
413413
SourceLoc Loc;
414414

415+
// Flag bits used in ContextAndBits.
416+
enum {
417+
/// The conformance is invalid.
418+
InvalidFlag = 0x01,
419+
420+
/// The conformance was labeled with @unchecked.
421+
UncheckedFlag = 0x02,
422+
};
423+
415424
/// The declaration context containing the ExtensionDecl or
416425
/// NominalTypeDecl that declared the conformance.
417426
///
418-
/// Also stores the "invalid" bit.
419-
llvm::PointerIntPair<DeclContext *, 1, bool> ContextAndInvalid;
427+
/// Also stores the "invalid" and "unchecked" bits.
428+
llvm::PointerIntPair<DeclContext *, 2, unsigned> ContextAndBits;
420429

421430
/// The reason that this conformance exists.
422431
///
@@ -457,11 +466,12 @@ class NormalProtocolConformance : public RootProtocolConformance,
457466
public:
458467
NormalProtocolConformance(Type conformingType, ProtocolDecl *protocol,
459468
SourceLoc loc, DeclContext *dc,
460-
ProtocolConformanceState state)
469+
ProtocolConformanceState state,
470+
bool isUnchecked)
461471
: RootProtocolConformance(ProtocolConformanceKind::Normal,
462472
conformingType),
463473
ProtocolAndState(protocol, state), Loc(loc),
464-
ContextAndInvalid(dc, false) {
474+
ContextAndBits(dc, isUnchecked ? UncheckedFlag : 0) {
465475
assert(!conformingType->hasArchetype() &&
466476
"ProtocolConformances should store interface types");
467477
}
@@ -475,7 +485,7 @@ class NormalProtocolConformance : public RootProtocolConformance,
475485
/// Get the declaration context that contains the conforming extension or
476486
/// nominal type declaration.
477487
DeclContext *getDeclContext() const {
478-
return ContextAndInvalid.getPointer();
488+
return ContextAndBits.getPointer();
479489
}
480490

481491
/// Get any additional requirements that are required for this conformance to
@@ -497,15 +507,20 @@ class NormalProtocolConformance : public RootProtocolConformance,
497507

498508
/// Determine whether this conformance is invalid.
499509
bool isInvalid() const {
500-
return ContextAndInvalid.getInt();
510+
return ContextAndBits.getInt() & InvalidFlag;
501511
}
502512

503513
/// Mark this conformance as invalid.
504514
void setInvalid() {
505-
ContextAndInvalid.setInt(true);
515+
ContextAndBits.setInt(ContextAndBits.getInt() | InvalidFlag);
506516
SignatureConformances = {};
507517
}
508518

519+
/// Whether this is an "unchecked" conformance.
520+
bool isUnchecked() const {
521+
return ContextAndBits.getInt() & UncheckedFlag;
522+
}
523+
509524
/// Get the kind of source from which this conformance comes.
510525
ConformanceEntryKind getSourceKind() const {
511526
return SourceKindAndImplyingConformance.getInt();

include/swift/AST/TypeLoc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class TypeRepr;
2929

3030
/// TypeLoc - Provides source location information for a parsed type.
3131
/// A TypeLoc is stored in AST nodes which use an explicitly written type.
32-
class alignas(1 << TypeReprAlignInBits) TypeLoc final {
32+
class alignas(1 << TypeReprAlignInBits) TypeLoc {
3333
Type Ty;
3434
TypeRepr *TyR = nullptr;
3535

include/swift/AST/TypeRepr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ class alignas(1 << TypeReprAlignInBits) TypeRepr {
135135
SourceLoc getEndLoc() const;
136136
SourceRange getSourceRange() const;
137137

138+
/// Find an @unchecked attribute and return its source location, or return
139+
/// an invalid source location if there is no such attribute.
140+
SourceLoc findUncheckedAttrLoc() const;
141+
138142
/// Is this type grammatically a type-simple?
139143
inline bool isSimple() const; // bottom of this file
140144

include/swift/Parse/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,7 @@ class Parser {
11271127

11281128
ParserResult<ImportDecl> parseDeclImport(ParseDeclOptions Flags,
11291129
DeclAttributes &Attributes);
1130-
ParserStatus parseInheritance(SmallVectorImpl<TypeLoc> &Inherited,
1130+
ParserStatus parseInheritance(SmallVectorImpl<InheritedEntry> &Inherited,
11311131
bool allowClassRequirement,
11321132
bool allowAnyObject);
11331133
ParserStatus parseDeclItem(bool &PreviousHadSemi,

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,7 +2188,8 @@ ASTContext::getConformance(Type conformingType,
21882188
ProtocolDecl *protocol,
21892189
SourceLoc loc,
21902190
DeclContext *dc,
2191-
ProtocolConformanceState state) {
2191+
ProtocolConformanceState state,
2192+
bool isUnchecked) {
21922193
assert(dc->isTypeContext());
21932194

21942195
llvm::FoldingSetNodeID id;
@@ -2204,7 +2205,8 @@ ASTContext::getConformance(Type conformingType,
22042205
// Build a new normal protocol conformance.
22052206
auto result
22062207
= new (*this, AllocationArena::Permanent)
2207-
NormalProtocolConformance(conformingType, protocol, loc, dc, state);
2208+
NormalProtocolConformance(
2209+
conformingType, protocol, loc, dc, state,isUnchecked);
22082210
normalConformances.InsertNode(result, insertPos);
22092211

22102212
return result;

lib/AST/ASTDumper.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,11 +499,12 @@ namespace {
499499
PrintWithColorRAII(OS, DeclModifierColor) << " trailing_semi";
500500
}
501501

502-
void printInherited(ArrayRef<TypeLoc> Inherited) {
502+
void printInherited(ArrayRef<InheritedEntry> Inherited) {
503503
if (Inherited.empty())
504504
return;
505505
OS << " inherits: ";
506-
interleave(Inherited, [&](TypeLoc Super) { Super.getType().print(OS); },
506+
interleave(Inherited,
507+
[&](InheritedEntry Super) { Super.getType().print(OS); },
507508
[&] { OS << ", "; });
508509
}
509510

0 commit comments

Comments
 (0)