Skip to content

Commit 488e0dd

Browse files
committed
[NCGenerics] fold InverseType into PCT
We already need to track the inverses separate from the members in a ProtocolCompositionType, since inverses aren't real types. Thus, the only purpose being served by InverseType is to be eliminated by RequirementLowering when it appears in a conformance requirement. We already have another RequirementKind that normally does not correspond to a Constrant that we can use for the purpose of carrying inverses in StructuralRequirements prior to lowering. That is the LayoutConstraint. In summary: InverseType here got replaced by ProtocolCompositionType when used as a type. When desugaring a requirement to conform to a PCT that contains an inverse, we add a LayoutConstraint::Noncopyable requirement so that RequirementLowering is aware that there was a `~Copyable` requirement.
1 parent 1574e85 commit 488e0dd

28 files changed

+135
-226
lines changed

include/swift/AST/ASTContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,7 @@ class ASTContext final {
10231023
const CanType TheEmptyTupleType; /// This is '()', aka Void
10241024
const CanType TheEmptyPackType;
10251025
const CanType TheAnyType; /// This is 'Any', the empty protocol composition
1026+
const CanType InverseCopyable; /// This is '~Copyable', the inverse of Copyable.
10261027
#define SINGLETON_TYPE(SHORT_ID, ID) \
10271028
const CanType The##SHORT_ID##Type;
10281029
#include "swift/AST/TypeNodes.def"

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3158,8 +3158,8 @@ ERROR(requires_not_suitable_archetype,none,
31583158
(Type))
31593159

31603160
ERROR(requires_not_suitable_inverse_subject,none,
3161-
"cannot apply inverse %1 to type %0 in conformance requirement",
3162-
(Type, Type))
3161+
"cannot apply inverse '~%1' to type %0 in conformance requirement",
3162+
(Type, StringRef))
31633163

31643164
ERROR(requires_not_suitable_inverse_outer_subject,none,
31653165
"cannot add inverse constraint '%0: %1' "

include/swift/AST/ExistentialLayout.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ struct ExistentialLayout {
3737
}
3838

3939
ExistentialLayout(CanProtocolType type);
40-
ExistentialLayout(CanInverseType type);
4140
ExistentialLayout(CanProtocolCompositionType type);
4241
ExistentialLayout(CanParameterizedProtocolType type);
4342

include/swift/AST/LayoutConstraint.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
namespace swift {
3232

3333
class ASTPrinter;
34+
enum class InvertibleProtocolKind : uint8_t;
3435

3536
/// This is a class representing the layout constraint.
3637
class LayoutConstraintInfo
@@ -171,10 +172,14 @@ class LayoutConstraintInfo
171172
std::string getString(const PrintOptions &PO = PrintOptions()) const;
172173

173174
/// Return the name of this layout constraint.
174-
StringRef getName(bool useClassLayoutName = false) const;
175+
StringRef getName(bool internalName = false) const;
176+
177+
/// If this layout constraint represents an inverse of an invertible protocol,
178+
/// returns the kind of protocol.
179+
llvm::Optional<InvertibleProtocolKind> getInverseKind() const;
175180

176181
/// Return the name of a layout constraint with a given kind.
177-
static StringRef getName(LayoutConstraintKind Kind, bool useClassLayoutName = false);
182+
static StringRef getName(LayoutConstraintKind Kind, bool internalName = false);
178183

179184
static bool isKnownLayout(LayoutConstraintKind Kind);
180185

@@ -217,6 +222,7 @@ class LayoutConstraintInfo
217222
static LayoutConstraintInfo ClassConstraintInfo;
218223
static LayoutConstraintInfo NativeClassConstraintInfo;
219224
static LayoutConstraintInfo TrivialConstraintInfo;
225+
static LayoutConstraintInfo NoncopyableConstraintInfo;
220226
};
221227

222228
/// A wrapper class containing a reference to the actual LayoutConstraintInfo
@@ -232,6 +238,8 @@ class LayoutConstraint {
232238
static LayoutConstraint getLayoutConstraint(LayoutConstraintKind Kind,
233239
ASTContext &C);
234240

241+
static LayoutConstraint getInverseConstraint(InvertibleProtocolKind Kind);
242+
235243
static LayoutConstraint getLayoutConstraint(LayoutConstraintKind Kind);
236244

237245
static LayoutConstraint getLayoutConstraint(LayoutConstraintKind Kind,

include/swift/AST/LayoutConstraintKind.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ enum class LayoutConstraintKind : uint8_t {
3939
RefCountedObject,
4040
// It is a layout constraint representing a native reference counted object.
4141
NativeRefCountedObject,
42-
LastLayout = NativeRefCountedObject,
42+
// It is a layout constraint representing a noncopyable value.
43+
Noncopyable,
44+
LastLayout = Noncopyable,
4345
};
4446

4547
#endif

include/swift/AST/PrintOptions.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,8 @@ struct PrintOptions {
328328
/// Whether to print generic requirements in a where clause.
329329
bool PrintGenericRequirements = true;
330330

331-
/// Whether to print the real layout name instead of AnyObject
332-
/// for class layout
333-
bool PrintClassLayoutName = false;
331+
/// Whether to print the internal layout name instead of AnyObject, etc.
332+
bool PrintInternalLayoutName = false;
334333

335334
/// Suppress emitting @available(*, noasync)
336335
bool SuppressNoAsyncAvailabilityAttr = false;

include/swift/AST/TypeMatcher.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -495,14 +495,6 @@ class TypeMatcher {
495495
sugaredFirstType);
496496
}
497497

498-
bool visitInverseType(CanInverseType firstInverse,
499-
Type secondType,
500-
Type sugaredFirstType) {
501-
// NOTE: If this visitor is reached, determine whether it should've been
502-
// before implementing this.
503-
llvm_unreachable("Yahaha! You found me!");
504-
}
505-
506498
bool visitLValueType(CanLValueType firstLValue, Type secondType,
507499
Type sugaredFirstType) {
508500
if (auto secondLValue = secondType->getAs<LValueType>()) {

include/swift/AST/TypeNodes.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ ARTIFICIAL_TYPE(SILMoveOnlyWrapped, Type)
180180
ALWAYS_CANONICAL_ARTIFICIAL_TYPE(SILPack, Type)
181181
ARTIFICIAL_TYPE(SILToken, Type)
182182
TYPE(ProtocolComposition, Type)
183-
UNCHECKED_TYPE(Inverse, Type)
184183
TYPE(ParameterizedProtocol, Type)
185184
TYPE(Existential, Type)
186185
TYPE(LValue, Type)

include/swift/AST/Types.h

Lines changed: 4 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,48 +1532,6 @@ class NominalOrBoundGenericNominalType : public AnyGenericType {
15321532
};
15331533
DEFINE_EMPTY_CAN_TYPE_WRAPPER(NominalOrBoundGenericNominalType, AnyGenericType)
15341534

1535-
/// InverseType represents the "inverse" of a ProtocolType as a constraint.
1536-
/// An inverse represents the _absence_ of an implicit constraint to the given
1537-
/// protocol.
1538-
///
1539-
/// Otherwise, an inverse is not a real type! It's an annotation for other types
1540-
/// to signal whether an implicit requirement on that type should be omitted.
1541-
/// Because that annotation is expressed in the surface language as if it _were_
1542-
/// a type (that is, as a type constraint) we still model it as a Type through
1543-
/// typechecking.
1544-
class InverseType final : public TypeBase {
1545-
Type protocol;
1546-
1547-
InverseType(Type type,
1548-
const ASTContext *canonicalContext,
1549-
RecursiveTypeProperties properties)
1550-
: TypeBase(TypeKind::Inverse, canonicalContext, properties),
1551-
protocol(type) {
1552-
assert(protocol->is<ProtocolType>());
1553-
}
1554-
1555-
public:
1556-
/// Produce an inverse constraint type for the given protocol type.
1557-
static Type get(Type protocolType);
1558-
1559-
1560-
/// Obtain the underlying \c ProtocolType that was inverted.
1561-
Type getInvertedProtocol() const {
1562-
return protocol;
1563-
}
1564-
1565-
/// Get known kind of inverse this type represents.
1566-
InvertibleProtocolKind getInverseKind() const;
1567-
1568-
// Implement isa/cast/dyncast/etc.
1569-
static bool classof(const TypeBase *T) {
1570-
return T->getKind() == TypeKind::Inverse;
1571-
}
1572-
};
1573-
BEGIN_CAN_TYPE_WRAPPER(InverseType, Type)
1574-
PROXY_CAN_TYPE_SIMPLE_GETTER(getInvertedProtocol)
1575-
END_CAN_TYPE_WRAPPER(InverseType, Type)
1576-
15771535
/// ErrorType - Represents the type of an erroneously constructed declaration,
15781536
/// expression, or type. When creating ErrorTypes, an associated error
15791537
/// diagnostic should always be emitted. That way when later stages of
@@ -5811,6 +5769,9 @@ class ProtocolCompositionType final : public TypeBase,
58115769
/// Constructs a protocol composition corresponding to the `AnyObject` type.
58125770
static Type theAnyObjectType(const ASTContext &C);
58135771

5772+
/// Constructs a protocol composition corresponding to the `~IP` type.
5773+
static Type theInverseOf(const ASTContext &C, InvertibleProtocolKind IP);
5774+
58145775
/// Canonical protocol composition types are minimized only to a certain
58155776
/// degree to preserve ABI compatibility. This routine enables performing
58165777
/// slower, but stricter minimization at need (e.g. redeclaration checking).
@@ -7294,8 +7255,7 @@ inline bool TypeBase::isConstraintType() const {
72947255
inline bool CanType::isConstraintTypeImpl(CanType type) {
72957256
return (isa<ProtocolType>(type) ||
72967257
isa<ProtocolCompositionType>(type) ||
7297-
isa<ParameterizedProtocolType>(type) ||
7298-
isa<InverseType>(type));
7258+
isa<ParameterizedProtocolType>(type));
72997259
}
73007260

73017261
inline bool TypeBase::isExistentialType() {
@@ -7311,7 +7271,6 @@ inline bool CanType::isExistentialTypeImpl(CanType type) {
73117271
isa<ProtocolCompositionType>(type) ||
73127272
isa<ExistentialType>(type) ||
73137273
isa<ParameterizedProtocolType>(type);
7314-
// TODO(kavon): treat InverseType as an existential, etc?
73157274
}
73167275

73177276
inline bool CanType::isAnyExistentialTypeImpl(CanType type) {

lib/AST/ASTContext.cpp

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,6 @@ struct ASTContext::Implementation {
460460
llvm::DenseMap<std::pair<ClassDecl*, Type>, ClassType*> ClassTypes;
461461
llvm::DenseMap<std::pair<ProtocolDecl*, Type>, ProtocolType*> ProtocolTypes;
462462
llvm::DenseMap<Type, ExistentialType *> ExistentialTypes;
463-
llvm::DenseMap<Type, InverseType *> InverseTypes;
464463
llvm::FoldingSet<UnboundGenericType> UnboundGenericTypes;
465464
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
466465
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
@@ -685,6 +684,8 @@ ASTContext::ASTContext(
685684
TheEmptyTupleType(TupleType::get(ArrayRef<TupleTypeElt>(), *this)),
686685
TheEmptyPackType(PackType::get(*this, {})),
687686
TheAnyType(ProtocolCompositionType::theAnyType(*this)),
687+
InverseCopyable(ProtocolCompositionType::theInverseOf(*this,
688+
InvertibleProtocolKind::Copyable)),
688689
#define SINGLETON_TYPE(SHORT_ID, ID) \
689690
The##SHORT_ID##Type(new (*this, AllocationArena::Permanent) \
690691
ID##Type(*this)),
@@ -3844,28 +3845,6 @@ Type ExistentialMetatypeType::getExistentialInstanceType() {
38443845
return ExistentialType::get(getInstanceType());
38453846
}
38463847

3847-
InvertibleProtocolKind InverseType::getInverseKind() const {
3848-
return *getInvertibleProtocolKind(*protocol->getKnownProtocol());
3849-
}
3850-
3851-
Type InverseType::get(Type invertedProto) {
3852-
auto &C = invertedProto->getASTContext();
3853-
3854-
auto properties = invertedProto->getRecursiveProperties();
3855-
auto arena = getArena(properties);
3856-
3857-
auto &entry = C.getImpl().getArena(arena).InverseTypes[invertedProto];
3858-
if (entry)
3859-
return entry;
3860-
3861-
const ASTContext *canonicalContext =
3862-
invertedProto->isCanonical() ? &C : nullptr;
3863-
3864-
return entry = new (C, arena) InverseType(invertedProto,
3865-
canonicalContext,
3866-
properties);
3867-
}
3868-
38693848
ModuleType *ModuleType::get(ModuleDecl *M) {
38703849
ASTContext &C = M->getASTContext();
38713850

@@ -6039,6 +6018,14 @@ CanSILBoxType SILBoxType::get(CanType boxedType) {
60396018
return get(boxedType->getASTContext(), layout, subMap);
60406019
}
60416020

6021+
LayoutConstraint
6022+
LayoutConstraint::getInverseConstraint(InvertibleProtocolKind Kind) {
6023+
switch (Kind) {
6024+
case InvertibleProtocolKind::Copyable:
6025+
return getLayoutConstraint(LayoutConstraintKind::Noncopyable);
6026+
}
6027+
}
6028+
60426029
LayoutConstraint
60436030
LayoutConstraint::getLayoutConstraint(LayoutConstraintKind Kind,
60446031
ASTContext &C) {

lib/AST/ASTDumper.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4368,12 +4368,6 @@ namespace {
43684368
printFoot();
43694369
}
43704370

4371-
void visitInverseType(InverseType *T, StringRef label) {
4372-
printCommon("inverse_type", label);
4373-
printRec(T->getInvertedProtocol());
4374-
printFoot();
4375-
}
4376-
43774371
void visitLValueType(LValueType *T, StringRef label) {
43784372
printCommon("lvalue_type", label);
43794373
printRec(T->getObjectType());

lib/AST/ASTMangler.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,9 +1401,6 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
14011401
case TypeKind::LValue:
14021402
llvm_unreachable("@lvalue types should not occur in function interfaces");
14031403

1404-
case TypeKind::Inverse:
1405-
llvm_unreachable("inverse types should not appear in interfaces");
1406-
14071404
case TypeKind::InOut:
14081405
appendType(cast<InOutType>(tybase)->getObjectType(), sig, forDecl);
14091406
return appendOperator("z");
@@ -3804,6 +3801,9 @@ void ASTMangler::appendOpParamForLayoutConstraint(LayoutConstraint layout) {
38043801
appendOperatorParam("M", Index(layout->getTrivialSizeInBits()),
38053802
Index(layout->getAlignmentInBits()));
38063803
break;
3804+
case LayoutConstraintKind::Noncopyable:
3805+
appendOperatorParam("nc");
3806+
break;
38073807
}
38083808
}
38093809

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6314,11 +6314,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
63146314
Printer << "_";
63156315
}
63166316

6317-
void visitInverseType(InverseType *T) {
6318-
Printer << "~";
6319-
visit(T->getInvertedProtocol());
6320-
}
6321-
63226317
void visitPlaceholderType(PlaceholderType *T) {
63236318
if (Options.PrintTypesForDebugging) {
63246319
Printer << "<<placeholder for ";
@@ -7667,15 +7662,16 @@ void LayoutConstraint::print(raw_ostream &OS,
76677662

76687663
void LayoutConstraintInfo::print(ASTPrinter &Printer,
76697664
const PrintOptions &PO) const {
7670-
Printer << getName(PO.PrintClassLayoutName);
7665+
Printer << getName(PO.PrintInternalLayoutName);
76717666
switch (getKind()) {
76727667
case LayoutConstraintKind::UnknownLayout:
76737668
case LayoutConstraintKind::RefCountedObject:
76747669
case LayoutConstraintKind::NativeRefCountedObject:
76757670
case LayoutConstraintKind::Class:
76767671
case LayoutConstraintKind::NativeClass:
76777672
case LayoutConstraintKind::Trivial:
7678-
return;
7673+
case LayoutConstraintKind::Noncopyable:
7674+
return; // non-parameterized cases
76797675
case LayoutConstraintKind::TrivialOfAtMostSize:
76807676
case LayoutConstraintKind::TrivialOfExactSize:
76817677
Printer << "(";

lib/AST/Attr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1261,7 +1261,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
12611261
Printer << "@_noMetadata ";
12621262
}
12631263
auto OptionsCopy = Options;
1264-
OptionsCopy.PrintClassLayoutName = typeErased;
1264+
OptionsCopy.PrintInternalLayoutName = typeErased;
12651265
req.print(Printer, OptionsCopy);
12661266
},
12671267
[&] { Printer << ", "; });

lib/AST/ExistentialGeneralization.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,6 @@ class Generalizer : public CanTypeVisitor<Generalizer, Type> {
110110
origType->hasExplicitAnyObject());
111111
}
112112

113-
Type visitInverseType(CanInverseType type) {
114-
// TODO(kavon): determine how to handle inverses for ExistentialGeneralization
115-
llvm_unreachable("unimplemented");
116-
}
117-
118113
// Generalize the type arguments of nominal types.
119114
Type visitBoundGenericType(CanBoundGenericType origType) {
120115
return generalizeGenericArguments(origType->getDecl(), origType);

0 commit comments

Comments
 (0)