Skip to content

AnyObject removal preparations #8770

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/ABI.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,8 @@ Types
type ::= associated-type
type ::= nominal-type
type ::= protocol-list 'p' // existential type
type ::= protocol-list superclass 'XE' // existential type with superclass
type ::= protocol-list superclass 'Xc' // existential type with superclass
type ::= protocol-list 'Xl' // existential type with AnyObject
type ::= type-list 't' // tuple
type ::= type generic-signature 'u' // generic type
type ::= 'x' // generic param, depth=0, idx=0
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,9 @@ class ASTContext {
/// Retrieve the declaration of the "pointee" property of a pointer type.
VarDecl *getPointerPointeePropertyDecl(PointerTypeKind ptrKind) const;

/// Retrieve the type Swift.AnyObject.
CanType getAnyObjectType() const;

/// Retrieve the type Swift.Never.
CanType getNeverType() const;

Expand Down
2 changes: 0 additions & 2 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,6 @@ WARNING(expr_keypath_swift3_objc_inference,none,
"argument of '#keyPath' refers to property %0 in %1 that depends on "
"'@objc' attribute inference deprecated in Swift 4",
(DeclName, Identifier))
ERROR(stdlib_anyobject_not_found,none,
"broken standard library: cannot find 'AnyObject' protocol", ())
ERROR(expr_keypath_type_of_property,none,
"cannot refer to type member %0 within instance of type %1",
(DeclName, Type))
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/ExistentialLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ struct ExistentialLayout {
return multipleProtocols;
}

LayoutConstraint getLayoutConstraint() const;

private:
// Inline storage for 'protocols' member above when computing
// layout of a single ProtocolType
Expand Down
12 changes: 0 additions & 12 deletions include/swift/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,6 @@ class CanType : public Type {
static bool isAnyExistentialTypeImpl(CanType type);
static void getExistentialTypeProtocolsImpl(CanType type,
SmallVectorImpl<ProtocolDecl*> &protocols);
static void getAnyExistentialTypeProtocolsImpl(CanType type,
SmallVectorImpl<ProtocolDecl*> &protocols);
static bool isObjCExistentialTypeImpl(CanType type);
static CanType getAnyOptionalObjectTypeImpl(CanType type,
OptionalTypeKind &kind);
Expand Down Expand Up @@ -413,11 +411,6 @@ class CanType : public Type {
void getExistentialTypeProtocols(
SmallVectorImpl<ProtocolDecl *> &protocols);

/// Given that this type is any kind of existential, return its
/// protocols in a canonical order.
void getAnyExistentialTypeProtocols(
SmallVectorImpl<ProtocolDecl *> &protocols);

/// Break an existential down into a set of constraints.
ExistentialLayout getExistentialLayout();

Expand All @@ -434,11 +427,6 @@ class CanType : public Type {
NominalTypeDecl *getAnyNominal() const;
GenericTypeDecl *getAnyGeneric() const;

/// Returns information about the layout constraint represented by
/// this type. If this type does not represent a layout constraint,
/// it returns an empty LayoutConstraint.
LayoutConstraint getLayoutConstraint() const;

CanType getAnyOptionalObjectType() const {
OptionalTypeKind kind;
return getAnyOptionalObjectTypeImpl(*this, kind);
Expand Down
74 changes: 48 additions & 26 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,15 @@ class alignas(1 << TypeAlignInBits) TypeBase {
};
enum { NumAnyMetatypeTypeBits = NumTypeBaseBits + 2 };
static_assert(NumAnyMetatypeTypeBits <= 32, "fits in an unsigned");

struct ProtocolCompositionTypeBitfields {
unsigned : NumTypeBaseBits;
/// Whether we have an explicitly-stated class constraint not
/// implied by any of our members.
unsigned HasExplicitAnyObject : 1;
};
enum { NumProtocolCompositionTypeBits = NumTypeBaseBits + 1 };
static_assert(NumProtocolCompositionTypeBits <= 32, "fits in an unsigned");

union {
TypeBaseBitfields TypeBaseBits;
Expand All @@ -334,6 +343,7 @@ class alignas(1 << TypeAlignInBits) TypeBase {
ArchetypeTypeBitfields ArchetypeTypeBits;
SILFunctionTypeBitfields SILFunctionTypeBits;
AnyMetatypeTypeBitfields AnyMetatypeTypeBits;
ProtocolCompositionTypeBitfields ProtocolCompositionTypeBits;
};

protected:
Expand Down Expand Up @@ -580,10 +590,6 @@ class alignas(1 << TypeAlignInBits) TypeBase {
/// its list of protocols.
void getExistentialTypeProtocols(SmallVectorImpl<ProtocolDecl *> &protocols);

/// Given that this type is any kind of existential type, produce
/// its list of protocols.
void getAnyExistentialTypeProtocols(SmallVectorImpl<ProtocolDecl *> &protocols);

/// Break an existential down into a set of constraints.
ExistentialLayout getExistentialLayout();

Expand Down Expand Up @@ -707,12 +713,6 @@ class alignas(1 << TypeAlignInBits) TypeBase {
/// concrete types to form the argument type.
bool isBindableTo(Type ty, LazyResolver *resolver);

/// \brief Retrieve the layout constraint of this type.
///
/// \returns The layout constraint of this type, or a null layout constraint
/// if it has no layout constraint.
LayoutConstraint getLayoutConstraint();

/// \brief Determines whether this type is permitted as a method override
/// of the \p other.
bool canOverride(Type other, OverrideMatchMode matchMode,
Expand Down Expand Up @@ -3662,44 +3662,66 @@ END_CAN_TYPE_WRAPPER(ProtocolType, NominalType)
/// protocol, then the canonical type is that protocol type. Otherwise, it is
/// a composition of the protocols in that list.
class ProtocolCompositionType : public TypeBase, public llvm::FoldingSetNode {
ArrayRef<Type> Protocols;
ArrayRef<Type> Members;

public:
/// \brief Retrieve an instance of a protocol composition type with the
/// given set of protocols.
static Type get(const ASTContext &C, ArrayRef<Type> Protocols);
/// given set of members.
static Type get(const ASTContext &C, ArrayRef<Type> Members,
bool HasExplicitAnyObject);

/// \brief Retrieve the set of protocols composed to create this type.
ArrayRef<Type> getProtocols() const { return Protocols; }
/// \brief Retrieve the set of members composed to create this type.
///
/// For non-canonical types, this can contain classes, protocols and
/// protocol compositions in any order. There can be at most one unique
/// class constraint, either stated directly or as recursive member.
///
/// In canonical types, this list will contain the superclass first if
/// any, followed by zero or more protocols in a canonical sorted order,
/// minimized to remove duplicates or protocols implied by inheritance.
///
/// Note that the list of members is not sufficient to uniquely identify
/// a protocol composition type; you also have to look at
/// hasExplicitAnyObject().
ArrayRef<Type> getMembers() const { return Members; }

void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Protocols);
Profile(ID, Members, hasExplicitAnyObject());
}
static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef<Type> Protocols);
static void Profile(llvm::FoldingSetNodeID &ID,
ArrayRef<Type> Members,
bool HasExplicitAnyObject);

/// True if one or more of the protocols is class.
/// True if the composition requires the concrete conforming type to
/// be a class, either via a directly-stated superclass constraint or
/// one of its member protocols being class-constrained.
bool requiresClass();


/// True if the class requirement is stated directly via '& AnyObject'.
bool hasExplicitAnyObject() {
return ProtocolCompositionTypeBits.HasExplicitAnyObject;
}

// Implement isa/cast/dyncast/etc.
static bool classof(const TypeBase *T) {
return T->getKind() == TypeKind::ProtocolComposition;
}

private:
static ProtocolCompositionType *build(const ASTContext &C,
ArrayRef<Type> Protocols);
ArrayRef<Type> Members,
bool HasExplicitAnyObject);

ProtocolCompositionType(const ASTContext *ctx, ArrayRef<Type> protocols,
ProtocolCompositionType(const ASTContext *ctx, ArrayRef<Type> members,
bool hasExplicitAnyObject,
RecursiveTypeProperties properties)
: TypeBase(TypeKind::ProtocolComposition, /*Context=*/ctx,
properties),
Protocols(protocols) { }
Members(members) {
ProtocolCompositionTypeBits.HasExplicitAnyObject = hasExplicitAnyObject;
}
};
BEGIN_CAN_TYPE_WRAPPER(ProtocolCompositionType, Type)
/// In the canonical representation, these are all ProtocolTypes.
CanTypeArrayRef getProtocols() const {
return CanTypeArrayRef(getPointer()->getProtocols());
}
END_CAN_TYPE_WRAPPER(ProtocolCompositionType, Type)

/// LValueType - An l-value is a handle to a physical object. The
Expand Down
1 change: 1 addition & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ NODE(ProtocolConformance)
NODE(ProtocolDescriptor)
NODE(ProtocolList)
NODE(ProtocolListWithClass)
NODE(ProtocolListWithAnyObject)
NODE(ProtocolWitness)
NODE(ProtocolWitnessTable)
NODE(ProtocolWitnessTableAccessor)
Expand Down
1 change: 1 addition & 0 deletions include/swift/Demangling/Demangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ class Demangler : public NodeFactory {
NodePointer demangleMetatypeRepresentation();
NodePointer demangleFunctionEntity();
NodePointer demangleEntity(Node::Kind Kind);
NodePointer demangleProtocolList();
NodePointer demangleProtocolListType();
NodePointer demangleGenericSignature(bool hasParamCounts);
NodePointer demangleGenericRequirement();
Expand Down
9 changes: 8 additions & 1 deletion include/swift/Runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -2441,6 +2441,11 @@ struct TargetExistentialTypeMetadata : public TargetMetadata<Runtime> {
return Flags.getClassConstraint() == ProtocolClassConstraint::Class;
}

const Metadata *getSuperclassConstraint() const {
// FIXME
return nullptr;
}

static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Existential;
}
Expand Down Expand Up @@ -3176,7 +3181,9 @@ swift_getExistentialMetatypeMetadata(const Metadata *instanceType);
/// referenced by \c protocols will be sorted in-place.
SWIFT_RT_ENTRY_VISIBILITY
const ExistentialTypeMetadata *
swift_getExistentialTypeMetadata(size_t numProtocols,
swift_getExistentialTypeMetadata(ProtocolClassConstraint classConstraint,
const Metadata *superclassConstraint,
size_t numProtocols,
const ProtocolDescriptor **protocols)
SWIFT_CC(RegisterPreservingCC);

Expand Down
9 changes: 7 additions & 2 deletions include/swift/Runtime/RuntimeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -791,12 +791,17 @@ FUNCTION(GetTupleMetadata3, swift_getTupleTypeMetadata3, DefaultCC,
Int8PtrTy, WitnessTablePtrTy),
ATTRS(NoUnwind, ReadOnly))

// Metadata *swift_getExistentialTypeMetadata(size_t numProtocols,
// Metadata *swift_getExistentialTypeMetadata(
// ProtocolClassConstraint classConstraint,
// const Metadata *superclassConstraint,
// size_t numProtocols,
// const protocol_descriptor_t * const *protocols);
//
// Note: ProtocolClassConstraint::Class is 0, ::Any is 1.
FUNCTION(GetExistentialMetadata,
swift_getExistentialTypeMetadata, RegisterPreservingCC,
RETURNS(TypeMetadataPtrTy),
ARGS(SizeTy,
ARGS(Int1Ty, TypeMetadataPtrTy, SizeTy,
ProtocolDescriptorPtrTy->getPointerTo()),
ATTRS(NoUnwind, ReadOnly))

Expand Down
3 changes: 2 additions & 1 deletion include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
const uint16_t VERSION_MINOR = 333; // Last change: AST constant_string_literal
const uint16_t VERSION_MINOR = 334; // Last change: AnyObject bit in ProtocolCompositionType

using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
Expand Down Expand Up @@ -660,6 +660,7 @@ namespace decls_block {

using ProtocolCompositionTypeLayout = BCRecordLayout<
PROTOCOL_COMPOSITION_TYPE,
BCFixed<1>, // has AnyObject constraint
BCArray<TypeIDField> // protocols
>;

Expand Down
47 changes: 40 additions & 7 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ struct ASTContext::Implementation {
/// The declaration of Swift.DefaultPrecedence.
PrecedenceGroupDecl *DefaultPrecedence = nullptr;

/// The AnyObject type.
CanType AnyObjectType;

#define KNOWN_STDLIB_TYPE_DECL(NAME, DECL_CLASS, NUM_GENERIC_PARAMS) \
/** The declaration of Swift.NAME. */ \
DECL_CLASS *NAME##Decl = nullptr;
Expand Down Expand Up @@ -415,7 +418,8 @@ ASTContext::ASTContext(LangOptions &langOpts, SearchPathOptions &SearchPathOpts,
TheUnresolvedType(new (*this, AllocationArena::Permanent)
UnresolvedType(*this)),
TheEmptyTupleType(TupleType::get(ArrayRef<TupleTypeElt>(), *this)),
TheAnyType(ProtocolCompositionType::get(*this, ArrayRef<Type>())),
TheAnyType(ProtocolCompositionType::get(*this, ArrayRef<Type>(),
/*hasExplicitAnyObject=*/false)),
TheNativeObjectType(new (*this, AllocationArena::Permanent)
BuiltinNativeObjectType(*this)),
TheBridgeObjectType(new (*this, AllocationArena::Permanent)
Expand Down Expand Up @@ -670,6 +674,29 @@ ASTContext::getPointerPointeePropertyDecl(PointerTypeKind ptrKind) const {
llvm_unreachable("bad pointer kind");
}

CanType ASTContext::getAnyObjectType() const {
if (Impl.AnyObjectType) {
return Impl.AnyObjectType;
}

// Go find 'AnyObject' in the Swift module.
//
// FIXME: This is going away.
SmallVector<ValueDecl *, 1> results;
lookupInSwiftModule("AnyObject", results);
for (auto result : results) {
if (auto proto = dyn_cast<ProtocolDecl>(result)) {
Impl.AnyObjectType = proto->getDeclaredType()->getCanonicalType();
return Impl.AnyObjectType;
}
}

Impl.AnyObjectType = CanType(
ProtocolCompositionType::get(
*this, {}, /*hasExplicitAnyObject=*/true));
return Impl.AnyObjectType;
}

CanType ASTContext::getNeverType() const {
return getNeverDecl()->getDeclaredType()->getCanonicalType();
}
Expand Down Expand Up @@ -2834,15 +2861,16 @@ void ClassType::Profile(llvm::FoldingSetNodeID &ID, ClassDecl *D, Type Parent) {
}

ProtocolCompositionType *
ProtocolCompositionType::build(const ASTContext &C, ArrayRef<Type> Protocols) {
ProtocolCompositionType::build(const ASTContext &C, ArrayRef<Type> Members,
bool HasExplicitAnyObject) {
// Check to see if we've already seen this protocol composition before.
void *InsertPos = nullptr;
llvm::FoldingSetNodeID ID;
ProtocolCompositionType::Profile(ID, Protocols);
ProtocolCompositionType::Profile(ID, Members, HasExplicitAnyObject);

bool isCanonical = true;
RecursiveTypeProperties properties;
for (Type t : Protocols) {
for (Type t : Members) {
if (!t->isCanonical())
isCanonical = false;
properties |= t->getRecursiveProperties();
Expand All @@ -2859,7 +2887,8 @@ ProtocolCompositionType::build(const ASTContext &C, ArrayRef<Type> Protocols) {
auto compTy
= new (C, arena)
ProtocolCompositionType(isCanonical ? &C : nullptr,
C.AllocateCopy(Protocols),
C.AllocateCopy(Members),
HasExplicitAnyObject,
properties);
C.Impl.getArena(arena).ProtocolCompositionTypes
.InsertNode(compTy, InsertPos);
Expand Down Expand Up @@ -3510,17 +3539,21 @@ CanArchetypeType ArchetypeType::getOpened(Type existential,
for (auto proto : layout.getProtocols())
protos.push_back(proto->getDecl());

auto layoutConstraint = layout.getLayoutConstraint();

auto arena = AllocationArena::Permanent;
void *mem = ctx.Allocate(
totalSizeToAlloc<ProtocolDecl *, Type, LayoutConstraint, UUID>(
protos.size(), layout.superclass ? 1 : 0, 0, 1),
protos.size(),
layout.superclass ? 1 : 0,
layoutConstraint ? 1 : 0, 1),
alignof(ArchetypeType), arena);

// FIXME: Pass in class layout constraint
auto result =
::new (mem) ArchetypeType(ctx, existential,
protos, layout.superclass,
existential->getLayoutConstraint(), *knownID);
layoutConstraint, *knownID);
openedExistentialArchetypes[*knownID] = result;

return CanArchetypeType(result);
Expand Down
4 changes: 3 additions & 1 deletion lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3075,7 +3075,9 @@ namespace {
void visitProtocolCompositionType(ProtocolCompositionType *T,
StringRef label) {
printCommon(T, label, "protocol_composition_type");
for (auto proto : T->getProtocols()) {
if (T->hasExplicitAnyObject())
OS << " any_object";
for (auto proto : T->getMembers()) {
printRec(proto);
}
OS << ")";
Expand Down
Loading