Skip to content

Commit a69bcf8

Browse files
authored
Merge pull request #67930 from kavon/copyable-requirement
Copyable as a Requirement Against the Machine
2 parents 975b5f3 + 80097bc commit a69bcf8

Some content is hidden

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

61 files changed

+706
-157
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,6 +2346,10 @@ ERROR(inferred_opaque_type,none,
23462346
"property definition has inferred type %0, involving the 'some' "
23472347
"return type of another declaration", (Type))
23482348

2349+
// Inverse Constraints
2350+
ERROR(inverse_type_not_invertable,none,
2351+
"type %0 is not invertable", (Type))
2352+
23492353
// Extensions
23502354
ERROR(non_nominal_extension,none,
23512355
"non-nominal type %0 cannot be extended", (Type))

include/swift/AST/KnownProtocols.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ PROTOCOL(AsyncIteratorProtocol)
126126

127127
PROTOCOL(FloatingPoint)
128128

129-
PROTOCOL_(Copyable)
129+
PROTOCOL(Copyable)
130130

131131
EXPRESSIBLE_BY_LITERAL_PROTOCOL(ExpressibleByArrayLiteral, "Array", false)
132132
EXPRESSIBLE_BY_LITERAL_PROTOCOL(ExpressibleByBooleanLiteral, "BooleanLiteralType", true)

include/swift/AST/KnownProtocols.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_AST_KNOWNPROTOCOLS_H
1515

1616
#include "swift/Basic/InlineBitfield.h"
17+
#include "swift/Basic/FixedBitSet.h"
1718
#include "swift/Config.h"
1819

1920
namespace llvm {
@@ -41,6 +42,12 @@ enum : uint8_t {
4142
enum : unsigned { NumKnownProtocolKindBits =
4243
countBitsUsed(static_cast<unsigned>(NumKnownProtocols - 1)) };
4344

45+
using KnownProtocolSet = FixedBitSet<NumKnownProtocols, KnownProtocolKind>;
46+
47+
/// Produces a set of all protocols that have an inverse, i.e., for every
48+
/// known protocol KP in the set, ~KP exists.
49+
KnownProtocolSet getInvertableProtocols();
50+
4451
/// Retrieve the name of the given known protocol.
4552
llvm::StringRef getProtocolName(KnownProtocolKind kind);
4653

include/swift/AST/TypeRepr.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,6 +1321,34 @@ class ExistentialTypeRepr: public TypeRepr {
13211321
friend class TypeRepr;
13221322
};
13231323

1324+
/// A type repr represeting the inverse of some constraint. For example,
1325+
/// ~Copyable
1326+
/// where `Copyable` is the constraint type.
1327+
class InverseTypeRepr : public TypeRepr {
1328+
TypeRepr *Constraint;
1329+
SourceLoc TildeLoc;
1330+
1331+
public:
1332+
InverseTypeRepr(SourceLoc tildeLoc, TypeRepr *constraint)
1333+
: TypeRepr(TypeReprKind::Inverse), Constraint(constraint),
1334+
TildeLoc(tildeLoc) {}
1335+
1336+
TypeRepr *getConstraint() const { return Constraint; }
1337+
SourceLoc getTildeLoc() const { return TildeLoc; }
1338+
1339+
static bool classof(const TypeRepr *T) {
1340+
return T->getKind() == TypeReprKind::Inverse;
1341+
}
1342+
static bool classof(const InverseTypeRepr *T) { return true; }
1343+
1344+
private:
1345+
SourceLoc getStartLocImpl() const { return TildeLoc; }
1346+
SourceLoc getEndLocImpl() const { return Constraint->getEndLoc(); }
1347+
SourceLoc getLocImpl() const { return TildeLoc; }
1348+
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
1349+
friend class TypeRepr;
1350+
};
1351+
13241352
/// TypeRepr for a user-specified placeholder (essentially, a user-facing
13251353
/// representation of an anonymous type variable.
13261354
///
@@ -1459,6 +1487,7 @@ inline bool TypeRepr::isSimple() const {
14591487
case TypeReprKind::Dictionary:
14601488
case TypeReprKind::Optional:
14611489
case TypeReprKind::ImplicitlyUnwrappedOptional:
1490+
case TypeReprKind::Inverse:
14621491
case TypeReprKind::Vararg:
14631492
case TypeReprKind::PackExpansion:
14641493
case TypeReprKind::Pack:

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ TYPEREPR(Protocol, TypeRepr)
6565
TYPEREPR(OpaqueReturn, TypeRepr)
6666
TYPEREPR(NamedOpaqueReturn, TypeRepr)
6767
TYPEREPR(Existential, TypeRepr)
68+
TYPEREPR(Inverse, TypeRepr)
6869
TYPEREPR(Pack, TypeRepr)
6970
TYPEREPR(PackElement, TypeRepr)
7071
TYPEREPR(Placeholder, TypeRepr)

include/swift/AST/Types.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -634,8 +634,8 @@ class alignas(1 << TypeAlignInBits) TypeBase
634634

635635
bool isPlaceholder();
636636

637-
/// Returns true if this is a move-only type.
638-
bool isPureMoveOnly();
637+
/// Returns true if this is a noncopyable type.
638+
bool isNoncopyable();
639639

640640
/// Does the type have outer parenthesis?
641641
bool hasParenSugar() const { return getKind() == TypeKind::Paren; }
@@ -5351,7 +5351,7 @@ class SILMoveOnlyWrappedType final : public TypeBase,
53515351
: TypeBase(TypeKind::SILMoveOnlyWrapped, &innerType->getASTContext(),
53525352
innerType->getRecursiveProperties()),
53535353
innerType(innerType) {
5354-
assert(!innerType->isPureMoveOnly() && "Inner type must be copyable");
5354+
assert(!innerType->isNoncopyable() && "Inner type must be copyable");
53555355
}
53565356

53575357
public:

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ EXPERIMENTAL_FEATURE(RawLayout, true)
235235
/// Enables the "embedded" swift mode (no runtime).
236236
EXPERIMENTAL_FEATURE(Embedded, true)
237237

238+
/// Enables noncopyable generics
239+
EXPERIMENTAL_FEATURE(NoncopyableGenerics, false)
240+
238241
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
239242
#undef EXPERIMENTAL_FEATURE
240243
#undef UPCOMING_FEATURE

include/swift/Parse/Parser.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,11 @@ class Parser {
158158
bool InSwiftKeyPath = false;
159159
bool InFreestandingMacroArgument = false;
160160

161+
// A cached answer to
162+
// Context.LangOpts.hasFeature(Feature::NoncopyableGenerics)
163+
// to ensure there's no parsing performance regression.
164+
bool EnabledNoncopyableGenerics;
165+
161166
/// Whether we should delay parsing nominal type, extension, and function
162167
/// bodies.
163168
bool isDelayedParsingEnabled() const;
@@ -2058,6 +2063,11 @@ class Parser {
20582063

20592064
void performIDEInspectionSecondPassImpl(
20602065
IDEInspectionDelayedDeclState &info);
2066+
2067+
/// Returns true if the caller should skip calling `parseType` afterwards.
2068+
bool parseLegacyTildeCopyable(SourceLoc *parseTildeCopyable,
2069+
ParserStatus &Status,
2070+
SourceLoc &TildeCopyableLoc);
20612071
};
20622072

20632073
/// Describes a parsed declaration name.

include/swift/SIL/SILType.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -748,10 +748,6 @@ class SILType {
748748
/// wrapped type.
749749
bool isMoveOnly() const;
750750

751-
/// Is this a type that is a first class move only type. This returns false
752-
/// for a move only wrapped type.
753-
bool isPureMoveOnly() const;
754-
755751
/// Return true if this is a value type (struct/enum) that requires
756752
/// deinitialization beyond destruction of its members.
757753
bool isValueTypeWithDeinit() const;

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ llvm::StringRef swift::getProtocolName(KnownProtocolKind kind) {
102102
llvm_unreachable("bad KnownProtocolKind");
103103
}
104104

105+
KnownProtocolSet swift::getInvertableProtocols() {
106+
return { KnownProtocolKind::Copyable };
107+
}
108+
105109
namespace {
106110
enum class SearchPathKind : uint8_t {
107111
Import = 1 << 0,

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3229,6 +3229,12 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr, void, StringRef>,
32293229
printFoot();
32303230
}
32313231

3232+
void visitInverseTypeRepr(InverseTypeRepr *T, StringRef label) {
3233+
printCommon("inverse", label);
3234+
printRec(T->getConstraint());
3235+
printFoot();
3236+
}
3237+
32323238
void visitArrayTypeRepr(ArrayTypeRepr *T, StringRef label) {
32333239
printCommon("type_array", label);
32343240
printRec(T->getBase());

lib/AST/ASTPrinter.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
//===--- ASTPrinter.cpp - Swift Language AST Printer ----------------------===//
21
//
32
// This source file is part of the Swift.org open source project
43
//
@@ -3338,7 +3337,7 @@ static bool usesFeatureMoveOnly(Decl *decl) {
33383337
// Check for move-only types in the types of this declaration.
33393338
if (Type type = value->getInterfaceType()) {
33403339
bool hasMoveOnly = type.findIf([](Type type) {
3341-
return type->isPureMoveOnly();
3340+
return type->isNoncopyable();
33423341
});
33433342

33443343
if (hasMoveOnly)
@@ -3385,6 +3384,12 @@ static bool usesFeatureMoveOnlyPartialConsumption(Decl *decl) {
33853384
return false;
33863385
}
33873386

3387+
static bool usesFeatureNoncopyableGenerics(Decl *decl) {
3388+
// FIXME: need to look for suppressed entries on generic parameters or
3389+
// inheritance clauses!
3390+
return false;
3391+
}
3392+
33883393
static bool usesFeatureOneWayClosureParameters(Decl *decl) {
33893394
return false;
33903395
}

lib/AST/ASTWalker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2210,6 +2210,10 @@ bool Traversal::visitExistentialTypeRepr(ExistentialTypeRepr *T) {
22102210
return doIt(T->getConstraint());
22112211
}
22122212

2213+
bool Traversal::visitInverseTypeRepr(InverseTypeRepr *T) {
2214+
return doIt(T->getConstraint());
2215+
}
2216+
22132217
bool Traversal::visitPlaceholderTypeRepr(PlaceholderTypeRepr *T) {
22142218
return false;
22152219
}

lib/AST/Decl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7514,7 +7514,7 @@ LifetimeAnnotation ParamDecl::getLifetimeAnnotation() const {
75147514
auto specifier = getSpecifier();
75157515
// Copyable parameters which are consumed have eager-move semantics.
75167516
if (specifier == ParamDecl::Specifier::Consuming &&
7517-
!getTypeInContext()->isPureMoveOnly()) {
7517+
!getTypeInContext()->isNoncopyable()) {
75187518
if (getAttrs().hasAttribute<NoEagerMoveAttr>())
75197519
return LifetimeAnnotation::Lexical;
75207520
return LifetimeAnnotation::EagerMove;
@@ -9750,7 +9750,7 @@ LifetimeAnnotation FuncDecl::getLifetimeAnnotation() const {
97509750
// Copyable parameters which are consumed have eager-move semantics.
97519751
if (getSelfAccessKind() == SelfAccessKind::Consuming) {
97529752
auto *selfDecl = getImplicitSelfDecl();
9753-
if (selfDecl && !selfDecl->getTypeInContext()->isPureMoveOnly()) {
9753+
if (selfDecl && !selfDecl->getTypeInContext()->isNoncopyable()) {
97549754
if (getAttrs().hasAttribute<NoEagerMoveAttr>())
97559755
return LifetimeAnnotation::Lexical;
97569756
return LifetimeAnnotation::EagerMove;

lib/AST/Module.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1797,7 +1797,7 @@ static ProtocolConformanceRef getBuiltinMetaTypeTypeConformance(
17971797

17981798
// Only metatypes of Copyable types are Copyable.
17991799
if (protocol->isSpecificProtocol(KnownProtocolKind::Copyable) &&
1800-
!metatypeType->getInstanceType()->isPureMoveOnly()) {
1800+
!metatypeType->getInstanceType()->isNoncopyable()) {
18011801
return ProtocolConformanceRef(
18021802
ctx.getBuiltinConformance(type, protocol,
18031803
BuiltinConformanceKind::Synthesized));

lib/AST/NameLookup.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3018,6 +3018,7 @@ directReferencesForTypeRepr(Evaluator &evaluator,
30183018
case TypeReprKind::OpaqueReturn:
30193019
case TypeReprKind::NamedOpaqueReturn:
30203020
case TypeReprKind::Existential:
3021+
case TypeReprKind::Inverse:
30213022
return { };
30223023

30233024
case TypeReprKind::Fixed:

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,7 @@ void swift::rewriting::realizeInheritedRequirements(
732732
auto inheritedTypes = decl->getInherited();
733733
auto *dc = decl->getInnermostDeclContext();
734734
auto *moduleForInference = dc->getParentModule();
735+
auto defaults = getInvertableProtocols();
735736

736737
for (auto index : inheritedTypes.getIndices()) {
737738
Type inheritedType =
@@ -749,13 +750,41 @@ void swift::rewriting::realizeInheritedRequirements(
749750

750751
auto *typeRepr = inheritedTypes.getTypeRepr(index);
751752
SourceLoc loc = (typeRepr ? typeRepr->getStartLoc() : SourceLoc());
753+
754+
// For any inverses, we only need to cancel out a default requirement.
755+
if (dyn_cast_or_null<InverseTypeRepr>(typeRepr)) {
756+
if (auto protoTy = inheritedType->getAs<ProtocolType>())
757+
if (auto protoDecl = protoTy->getDecl())
758+
if (auto kp = protoDecl->getKnownProtocolKind())
759+
defaults.remove(*kp);
760+
761+
continue;
762+
}
763+
752764
if (shouldInferRequirements) {
753765
inferRequirements(inheritedType, loc, moduleForInference,
754766
decl->getInnermostDeclContext(), result);
755767
}
756768

757769
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors);
758770
}
771+
772+
auto &ctx = dc->getASTContext();
773+
if (ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
774+
// Add the remaining default conformance requirements to this
775+
// associated type or generic type param.
776+
for (auto kp : defaults) {
777+
ProtocolDecl *decl = ctx.getProtocol(kp);
778+
assert(decl && "couldn't load protocol??");
779+
780+
SourceLoc loc = decl->getLoc();
781+
Type protocolType = decl->getDeclaredInterfaceType();
782+
783+
// Add the protocol as an "inferred" requirement.
784+
Requirement req(RequirementKind::Conformance, type, protocolType);
785+
result.push_back({req, loc, /*wasInferred=*/true});
786+
}
787+
}
759788
}
760789

761790
/// StructuralRequirementsRequest realizes all the user-written requirements

lib/AST/Type.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,18 +157,18 @@ bool TypeBase::isMarkerExistential() {
157157
return true;
158158
}
159159

160-
bool TypeBase::isPureMoveOnly() {
160+
bool TypeBase::isNoncopyable() {
161161
if (auto *nom = getAnyNominal())
162162
return nom->isMoveOnly();
163163

164164
if (auto *expansion = getAs<PackExpansionType>()) {
165-
return expansion->getPatternType()->isPureMoveOnly();
165+
return expansion->getPatternType()->isNoncopyable();
166166
}
167167

168168
// if any components of the tuple are move-only, then the tuple is move-only.
169169
if (auto *tupl = getCanonicalType()->getAs<TupleType>()) {
170170
for (auto eltTy : tupl->getElementTypes())
171-
if (eltTy->isPureMoveOnly())
171+
if (eltTy->isNoncopyable())
172172
return true;
173173
}
174174

lib/AST/TypeRepr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,12 @@ void NamedOpaqueReturnTypeRepr::printImpl(ASTPrinter &Printer,
588588
printTypeRepr(Base, Printer, Opts);
589589
}
590590

591+
void InverseTypeRepr::printImpl(ASTPrinter &Printer,
592+
const PrintOptions &Opts) const {
593+
Printer << "~";
594+
printTypeRepr(Constraint, Printer, Opts);
595+
}
596+
591597
void SpecifierTypeRepr::printImpl(ASTPrinter &Printer,
592598
const PrintOptions &Opts) const {
593599
switch (getKind()) {

lib/IRGen/GenReflection.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ getTypeRefByFunction(IRGenModule &IGM,
266266

267267
// If a type is noncopyable, lie about the resolved type unless the
268268
// runtime is sufficiently aware of noncopyable types.
269-
if (substT->isPureMoveOnly()) {
269+
if (substT->isNoncopyable()) {
270270
// Darwin-based platforms have ABI stability, and we want binaries
271271
// that use noncopyable types nongenerically today to be forward
272272
// compatible with a future OS runtime that supports noncopyable
@@ -391,7 +391,7 @@ getTypeRefImpl(IRGenModule &IGM,
391391
// noncopyable, use a function to emit the type ref which will look for a
392392
// signal from future runtimes whether they support noncopyable types before
393393
// exposing their metadata to them.
394-
if (type->isPureMoveOnly()) {
394+
if (type->isNoncopyable()) {
395395
IGM.IRGen.noteUseOfTypeMetadata(type);
396396
return getTypeRefByFunction(IGM, sig, type);
397397
}

0 commit comments

Comments
 (0)