Skip to content
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

Opaque types with resilience #22072

Merged
merged 46 commits into from Apr 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
5e14979
Parse opaque types.
jckarter Nov 30, 2018
71912bb
AST: Represent OpaqueTypeDecls.
jckarter Dec 3, 2018
dd2b51d
Add an OpaqueTypeArchetypeType subclass.
jckarter Dec 15, 2018
f008019
Sema: Infer the underlying type for opaque return types from function…
jckarter Dec 19, 2018
c771a7e
SILGen: Substitute away opaque types.
jckarter Dec 21, 2018
a419754
Support nested types on opaque archetypes (and maybe opened ones).
jckarter Jan 8, 2019
2d19110
Serialization: Serialize opaque types and their decls.
jckarter Jan 10, 2019
325ba60
IRGen: Substitute out opaque types when emitting associated types.
jckarter Jan 15, 2019
a82b992
Enable opaque result types.
jckarter Jan 16, 2019
7a8b940
Respond to Slava's feedback
jckarter Jan 18, 2019
a6c9254
Mangle opaque types without underlying types as ErrorType for now.
jckarter Jan 18, 2019
e3bbd8c
Remove ResilienceExpansion from substOpaqueTypes for now.
jckarter Jan 18, 2019
6db0540
Sema: Don't allow properties with inferred types to infer opaque resu…
jckarter Jan 23, 2019
141d6bf
Add test for deserializing opaque types across modules
jckarter Jan 23, 2019
0255baa
SILGen: Start supporting opaque result types resiliently.
jckarter Jan 23, 2019
42e1824
Mangle opaque result types.
jckarter Jan 29, 2019
09ca7a7
IRGen: Emit runtime calls to fetch opaque type metadata.
jckarter Jan 30, 2019
34620a9
IRGen: Use runtime calls to get opaque type metadata and conformances…
jckarter Feb 20, 2019
ca537d1
opaque descriptor wip
jckarter Feb 27, 2019
ffc9fd5
IRGen: Emit opaque type descriptors.
jckarter Mar 5, 2019
05dfec0
Push the conformance accessor hack down into getTypeByMangledName.
jckarter Mar 6, 2019
60d719c
IRGen: Inline helper into its last remaining use
jckarter Mar 7, 2019
1841a1f
IRGen: Extract GenKeyPath's emitWitnessTableRefString to be usable el…
jckarter Mar 8, 2019
5ec394c
fill in witness tables
jckarter Mar 8, 2019
cf00892
change signature
jckarter Mar 8, 2019
f363a10
runtime interface fixup irgen
jckarter Mar 9, 2019
a3c17bd
Runtime: Implement entry points for opaque type support
jckarter Mar 9, 2019
95c43f4
Decode opaque types in the runtime demangler.
jckarter Mar 15, 2019
4075749
add changelog entry for opaque types
jckarter Mar 15, 2019
be0140f
Switch __opaque to some, per the latest rev of the proposal
jckarter Mar 15, 2019
0b47f5b
update tests
jckarter Mar 15, 2019
455f060
fix rdar://problem/49230987
jckarter Apr 1, 2019
29a8c67
IRGen: Bind local metadata before emitting opaque type assoc type wit…
jckarter Apr 4, 2019
733b08b
TBD: Include opaque type descriptors
jckarter Apr 4, 2019
399332b
Parsable interface and type reconstruction support for opaque types.
jckarter Apr 10, 2019
60aa49d
merge fixup
jckarter Apr 11, 2019
78b4870
Relax some assertions to allow opaque-type values at global scope in …
jckarter Apr 11, 2019
f96ca72
Serialization: Handle reentrance while deserializing OpaqueTypeDecl. …
jckarter Apr 12, 2019
5bb22b0
Allow OpaqueTypeDecls to be (de)mangled as contexts, rdar://problem/4…
jckarter Apr 12, 2019
c58737f
merge fixup
jckarter Apr 15, 2019
59fd141
Validate opaque return types for properties and subscripts.
jckarter Apr 16, 2019
0fcc7cd
Check the underlying type of get-only computed properties with opaque…
jckarter Apr 16, 2019
b57f352
Serialize opaque return type of var/subscript decls.
jckarter Apr 16, 2019
a99716b
Visit var/subscript opaque return decls during IRGen/TBDGen.
jckarter Apr 17, 2019
dbd3a48
Track var/subscript opaque return decls for type reconstruction.
jckarter Apr 17, 2019
b87a566
Demangler: Register substitution for opaque archetype manglings
jckarter Apr 17, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Expand Up @@ -44,6 +44,20 @@ Swift Next
Swift 5.1
---------

* [SE-0244][]:

Functions can now hide their concrete return type by declaring what protocols
it conforms to instead of specifying the exact return type:

```
func makeMeACollection() -> some Collection {
return [1, 2, 3]
}
```

Code that calls the function can use the interface of the protocol, but
does not have visibility into the underlying type.

* [SE-0256][]:

Subscripts can now be declared `static` or (inside classes) `class`.
Expand Down
36 changes: 33 additions & 3 deletions docs/ABI/Mangling.rst
Expand Up @@ -78,8 +78,13 @@ The following symbolic reference kinds are currently implemented:

::

{any-generic-type, protocol} ::= '\x01' .{4} // Reference points directly to context descriptor
{any-generic-type, protocol} ::= '\x02' .{4} // Reference points indirectly to context descriptor
#if SWIFT_RUNTIME_VERSION < 5.1
{any-generic-type, protocol} ::= '\x01' .{4} // Reference points directly to context descriptor
{any-generic-type, protocol} ::= '\x02' .{4} // Reference points indirectly to context descriptor
#else
{any-generic-type, protocol, opaque-type-decl-name} ::= '\x01' .{4} // Reference points directly to context descriptor
{any-generic-type, protocol, opaque-type-decl-name} ::= '\x02' .{4} // Reference points indirectly to context descriptor
#endif
// The grammatical role of the symbolic reference is determined by the
// kind of context descriptor referenced

Expand All @@ -91,7 +96,15 @@ The following symbolic reference kinds are currently implemented:

associated-conformance-access-function ::= '\x07' .{4} // Reference points directly to associated conformance access function relative to the protocol
associated-conformance-access-function ::= '\x08' .{4} // Reference points directly to associated conformance access function relative to the conforming type
keypath-metadata-access-function ::= '\x09' {.4} // Reference points directly to keypath conformance access function

// keypaths only in Swift 5.0, generalized in Swift 5.1
#if SWIFT_RUNTIME_VERSION >= 5.1
metadata-access-function ::= '\x09' .{4} // Reference points directly to metadata access function that can be invoked to produce referenced object
#endif

A mangled name may also include ``\xFF`` bytes, which are only used for
alignment padding. They do not affect what the mangled name references and can
be skipped over and ignored.

Globals
~~~~~~~
Expand All @@ -110,6 +123,9 @@ Globals
global ::= nominal-type 'Ml' // in-place type initialization cache
global ::= nominal-type 'Mm' // class metaclass
global ::= nominal-type 'Mn' // nominal type descriptor
#if SWIFT_RUNTIME_VERSION >= 5.1
global ::= opaque-type-decl-name 'MQ' // opaque type descriptor -- added in Swift 5.1
#endif
global ::= nominal-type 'Mu' // class method lookup function
global ::= nominal-type 'MU' // ObjC metadata update callback function
global ::= nominal-type 'Ms' // ObjC resilient class stub
Expand Down Expand Up @@ -600,6 +616,20 @@ For the most part, manglings follow the structure of formal language
types. However, in some cases it is more useful to encode the exact
implementation details of a function type.

::

#if SWIFT_VERSION >= 5.1
type ::= 'Qr' // opaque result type (of current decl)
type ::= opaque-type-decl-name bound-generic-args 'Qo' INDEX // opaque type

opaque-type-decl-name ::= entity 'QO' // opaque result type of specified decl
#endif

Opaque return types have a special short representation in the mangling of
their defining entity. In structural position, opaque types are fully qualified
by mangling the defining entity for the opaque declaration and the substitutions
into the defining entity's generic environment.

The ``type*`` list contains parameter and return types (including the error
result), in that order.
The number of parameters and results must match with the number of
Expand Down
57 changes: 57 additions & 0 deletions include/swift/ABI/Metadata.h
Expand Up @@ -3005,6 +3005,58 @@ struct TargetProtocolDescriptor final
return cd->getKind() == ContextDescriptorKind::Protocol;
}
};

/// The descriptor for an opaque type.
template <typename Runtime>
struct TargetOpaqueTypeDescriptor final
: TargetContextDescriptor<Runtime>,
TrailingGenericContextObjects<TargetOpaqueTypeDescriptor<Runtime>,
TargetGenericContextDescriptorHeader,
RelativeDirectPointer<const char>>
{
private:
using TrailingGenericContextObjects
= TrailingGenericContextObjects<TargetOpaqueTypeDescriptor<Runtime>,
TargetGenericContextDescriptorHeader,
RelativeDirectPointer<const char>>;
using TrailingObjects =
typename TrailingGenericContextObjects::TrailingObjects;
friend TrailingObjects;

template<typename T>
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;

public:
using TrailingGenericContextObjects::getGenericContext;
using TrailingGenericContextObjects::getGenericContextHeader;
using TrailingGenericContextObjects::getFullGenericContextHeader;
using TrailingGenericContextObjects::getGenericParams;

// The kind-specific flags area is used to store the count of the generic
// arguments for underlying type(s) encoded in the descriptor.
unsigned getNumUnderlyingTypeArguments() const {
return this->Flags.getKindSpecificFlags();
}

using TrailingGenericContextObjects::numTrailingObjects;
size_t numTrailingObjects(OverloadToken<RelativeDirectPointer<const char>>) const {
return getNumUnderlyingTypeArguments();
}

StringRef getUnderlyingTypeArgument(unsigned i) const {
assert(i < getNumUnderlyingTypeArguments());
const char *ptr =
(this->template getTrailingObjects<RelativeDirectPointer<const char>>())[i];

return Demangle::makeSymbolicMangledNameStringRef(ptr);
}

static bool classof(const TargetContextDescriptor<Runtime> *cd) {
return cd->getKind() == ContextDescriptorKind::OpaqueType;
}
};

using OpaqueTypeDescriptor = TargetOpaqueTypeDescriptor<InProcess>;

/// The instantiation cache for generic metadata. This must be guaranteed
/// to zero-initialized before it is first accessed. Its contents are private
Expand Down Expand Up @@ -4213,6 +4265,9 @@ TargetContextDescriptor<Runtime>::getGenericContext() const {
case ContextDescriptorKind::Struct:
return llvm::cast<TargetStructDescriptor<Runtime>>(this)
->getGenericContext();
case ContextDescriptorKind::OpaqueType:
return llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)
->getGenericContext();
default:
// We don't know about this kind of descriptor.
return nullptr;
Expand Down Expand Up @@ -4264,6 +4319,8 @@ TargetTypeContextDescriptor<Runtime>::getGenericParams() const {
return llvm::cast<TargetEnumDescriptor<Runtime>>(this)->getGenericParams();
case ContextDescriptorKind::Struct:
return llvm::cast<TargetStructDescriptor<Runtime>>(this)->getGenericParams();
case ContextDescriptorKind::OpaqueType:
return llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)->getGenericParams();
default:
swift_runtime_unreachable("Not a type context descriptor.");
}
Expand Down
3 changes: 3 additions & 0 deletions include/swift/ABI/MetadataValues.h
Expand Up @@ -1102,6 +1102,9 @@ enum class ContextDescriptorKind : uint8_t {

/// This context descriptor represents a protocol context.
Protocol = 3,

/// This context descriptor represents an opaque type alias.
OpaqueType = 4,

/// First kind that represents a type of any sort.
Type_First = 16,
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/ASTContext.h
Expand Up @@ -84,6 +84,7 @@ namespace swift {
class ModuleLoader;
class NominalTypeDecl;
class NormalProtocolConformance;
class OpaqueTypeDecl;
class InheritedProtocolConformance;
class SelfProtocolConformance;
class SpecializedProtocolConformance;
Expand Down Expand Up @@ -943,6 +944,7 @@ class ASTContext final {

friend TypeBase;
friend ArchetypeType;
friend OpaqueTypeDecl;

/// Provide context-level uniquing for SIL lowered type layouts and boxes.
friend SILLayout;
Expand Down
7 changes: 7 additions & 0 deletions include/swift/AST/ASTDemangler.h
Expand Up @@ -58,6 +58,9 @@ class ASTBuilder {
using BuiltTypeDecl = swift::GenericTypeDecl *; // nominal or type alias
using BuiltProtocolDecl = swift::ProtocolDecl *;
explicit ASTBuilder(ASTContext &ctx) : Ctx(ctx) {}

/// The resolver to use for type checking, if necessary.
LazyResolver *Resolver = nullptr;

ASTContext &getASTContext() { return Ctx; }
DeclContext *getNotionalDC();
Expand All @@ -82,6 +85,10 @@ class ASTBuilder {
Type createTypeAliasType(GenericTypeDecl *decl, Type parent);

Type createBoundGenericType(GenericTypeDecl *decl, ArrayRef<Type> args);

Type resolveOpaqueType(NodePointer opaqueDescriptor,
ArrayRef<Type> args,
unsigned ordinal);

Type createBoundGenericType(GenericTypeDecl *decl, ArrayRef<Type> args,
Type parent);
Expand Down
46 changes: 35 additions & 11 deletions include/swift/AST/ASTMangler.h
Expand Up @@ -59,12 +59,18 @@ class ASTMangler : public Mangler {

public:
using SymbolicReferent = llvm::PointerUnion<const NominalTypeDecl *,
const ProtocolConformance *>;
const OpaqueTypeDecl *>;
protected:

/// If set, the mangler calls this function to determine whether to symbolic
/// reference a given entity. Defaults to always returning true.
/// reference a given entity. If null, the mangler acts as if it's set to
/// always return true.
std::function<bool (SymbolicReferent)> CanSymbolicReference;

bool canSymbolicReference(SymbolicReferent referent) {
return AllowSymbolicReferences
&& (!CanSymbolicReference || CanSymbolicReference(referent));
}

std::vector<std::pair<SymbolicReferent, unsigned>> SymbolicReferences;

Expand Down Expand Up @@ -201,7 +207,7 @@ class ASTMangler : public Mangler {

void appendSymbolKind(SymbolKind SKind);

void appendType(Type type);
void appendType(Type type, const ValueDecl *forDecl = nullptr);

void appendDeclName(const ValueDecl *decl);

Expand All @@ -215,6 +221,15 @@ class ASTMangler : public Mangler {

void bindGenericParameters(CanGenericSignature sig);

/// Mangles a sugared type iff we are mangling for the debugger.
template <class T> void appendSugaredType(Type type,
const ValueDecl *forDecl) {
assert(DWARFMangling &&
"sugared types are only legal when mangling for the debugger");
auto *BlandTy = cast<T>(type.getPointer())->getSinglyDesugaredType();
appendType(BlandTy, forDecl);
}

void appendBoundGenericArgs(Type type, bool &isFirstArgList);

/// Append the bound generics arguments for the given declaration context
Expand All @@ -228,7 +243,8 @@ class ASTMangler : public Mangler {

/// Append any retroactive conformances.
void appendRetroactiveConformances(Type type);

void appendRetroactiveConformances(SubstitutionMap subMap,
ModuleDecl *fromModule);
void appendImplFunctionType(SILFunctionType *fn);

void appendContextOf(const ValueDecl *decl);
Expand All @@ -242,17 +258,23 @@ class ASTMangler : public Mangler {

void appendAnyGenericType(const GenericTypeDecl *decl);

void appendFunction(AnyFunctionType *fn, bool isFunctionMangling = false);
void appendFunctionType(AnyFunctionType *fn, bool isAutoClosure = false);
void appendFunction(AnyFunctionType *fn, bool isFunctionMangling = false,
const ValueDecl *forDecl = nullptr);
void appendFunctionType(AnyFunctionType *fn, bool isAutoClosure = false,
const ValueDecl *forDecl = nullptr);

void appendFunctionSignature(AnyFunctionType *fn);
void appendFunctionSignature(AnyFunctionType *fn,
const ValueDecl *forDecl = nullptr);

void appendFunctionInputType(ArrayRef<AnyFunctionType::Param> params);
void appendFunctionResultType(Type resultType);
void appendFunctionInputType(ArrayRef<AnyFunctionType::Param> params,
const ValueDecl *forDecl = nullptr);
void appendFunctionResultType(Type resultType,
const ValueDecl *forDecl = nullptr);

void appendTypeList(Type listTy);
void appendTypeList(Type listTy, const ValueDecl *forDecl = nullptr);
void appendTypeListElement(Identifier name, Type elementType,
ParameterTypeFlags flags);
ParameterTypeFlags flags,
const ValueDecl *forDecl = nullptr);

/// Append a generic signature to the mangling.
///
Expand Down Expand Up @@ -319,6 +341,8 @@ class ASTMangler : public Mangler {
void appendOpParamForLayoutConstraint(LayoutConstraint Layout);

void appendSymbolicReference(SymbolicReferent referent);

void appendOpaqueDeclName(const OpaqueTypeDecl *opaqueDecl);
};

} // end namespace Mangle
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/Attr.def
Expand Up @@ -82,6 +82,9 @@ TYPE_ATTR(yield_many)
TYPE_ATTR(thin)
TYPE_ATTR(thick)

// Generated interface attributes
TYPE_ATTR(_opaqueReturnTypeOf)

// Schema for DECL_ATTR:
//
// - Attribute name.
Expand Down
12 changes: 12 additions & 0 deletions include/swift/AST/Attr.h
Expand Up @@ -67,6 +67,14 @@ class TypeAttributes {

// For an opened existential type, the known ID.
Optional<UUID> OpenedID;

// For a reference to an opaque return type, the mangled name and argument
// index into the generic signature.
struct OpaqueReturnTypeRef {
StringRef mangledName;
unsigned index;
};
Optional<OpaqueReturnTypeRef> OpaqueReturnTypeOf;

TypeAttributes() {}

Expand All @@ -84,6 +92,10 @@ class TypeAttributes {
return AttrLocs[A];
}

void setOpaqueReturnTypeOf(StringRef mangling, unsigned index) {
OpaqueReturnTypeOf = OpaqueReturnTypeRef{mangling, index};
}

void setAttr(TypeAttrKind A, SourceLoc L) {
assert(!L.isInvalid() && "Cannot clear attribute with this method");
AttrLocs[A] = L;
Expand Down