Skip to content

Commit

Permalink
Merge pull request swiftlang#8770 from slavapestov/anyobject-removal-…
Browse files Browse the repository at this point in the history
…preparations

AnyObject removal preparations
  • Loading branch information
slavapestov authored Apr 14, 2017
2 parents 54e1f83 + 0708323 commit e4905b9
Show file tree
Hide file tree
Showing 65 changed files with 797 additions and 479 deletions.
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

0 comments on commit e4905b9

Please sign in to comment.