Skip to content

[5.1 04-24-2019] Opaque result types, SE-244 #24282

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
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
fdfcda6
Parse opaque types.
jckarter Nov 30, 2018
7fd234c
AST: Represent OpaqueTypeDecls.
jckarter Dec 3, 2018
504247d
Add an OpaqueTypeArchetypeType subclass.
jckarter Dec 15, 2018
1c0a633
Sema: Infer the underlying type for opaque return types from function…
jckarter Dec 19, 2018
e60facb
SILGen: Substitute away opaque types.
jckarter Dec 21, 2018
43e0609
Support nested types on opaque archetypes (and maybe opened ones).
jckarter Jan 8, 2019
86ae5b7
Serialization: Serialize opaque types and their decls.
jckarter Jan 10, 2019
bf6c357
IRGen: Substitute out opaque types when emitting associated types.
jckarter Jan 15, 2019
e85f03a
Enable opaque result types.
jckarter Jan 16, 2019
6feef4b
Respond to Slava's feedback
jckarter Jan 18, 2019
3c7fa2c
Mangle opaque types without underlying types as ErrorType for now.
jckarter Jan 18, 2019
265b697
Remove ResilienceExpansion from substOpaqueTypes for now.
jckarter Jan 18, 2019
e8eb94e
Sema: Don't allow properties with inferred types to infer opaque resu…
jckarter Jan 23, 2019
abc14d6
Add test for deserializing opaque types across modules
jckarter Jan 23, 2019
8fd73ed
SILGen: Start supporting opaque result types resiliently.
jckarter Jan 23, 2019
f417b15
Mangle opaque result types.
jckarter Jan 29, 2019
196c304
IRGen: Emit runtime calls to fetch opaque type metadata.
jckarter Jan 30, 2019
f7d19b4
IRGen: Use runtime calls to get opaque type metadata and conformances…
jckarter Feb 20, 2019
aec97eb
opaque descriptor wip
jckarter Feb 27, 2019
84fd9d8
IRGen: Emit opaque type descriptors.
jckarter Mar 5, 2019
c5e0435
Push the conformance accessor hack down into getTypeByMangledName.
jckarter Mar 6, 2019
0d2148e
IRGen: Inline helper into its last remaining use
jckarter Mar 7, 2019
bb51997
IRGen: Extract GenKeyPath's emitWitnessTableRefString to be usable el…
jckarter Mar 8, 2019
1987c22
fill in witness tables
jckarter Mar 8, 2019
8429891
change signature
jckarter Mar 8, 2019
7cfba10
runtime interface fixup irgen
jckarter Mar 9, 2019
3a1f87f
Runtime: Implement entry points for opaque type support
jckarter Mar 9, 2019
9d1706f
Decode opaque types in the runtime demangler.
jckarter Mar 15, 2019
7278b2c
add changelog entry for opaque types
jckarter Mar 15, 2019
2146b82
Switch __opaque to some, per the latest rev of the proposal
jckarter Mar 15, 2019
dc013e0
update tests
jckarter Mar 15, 2019
c5a3864
fix rdar://problem/49230987
jckarter Apr 1, 2019
5f593d7
IRGen: Bind local metadata before emitting opaque type assoc type wit…
jckarter Apr 4, 2019
734c4f7
TBD: Include opaque type descriptors
jckarter Apr 4, 2019
2690ed7
Parsable interface and type reconstruction support for opaque types.
jckarter Apr 10, 2019
d8ed01e
merge fixup
jckarter Apr 11, 2019
af5fd13
Relax some assertions to allow opaque-type values at global scope in …
jckarter Apr 11, 2019
eb99ea4
Serialization: Handle reentrance while deserializing OpaqueTypeDecl. …
jckarter Apr 12, 2019
f2d63ef
Allow OpaqueTypeDecls to be (de)mangled as contexts, rdar://problem/4…
jckarter Apr 12, 2019
cb2fcb6
merge fixup
jckarter Apr 15, 2019
f135577
Validate opaque return types for properties and subscripts.
jckarter Apr 16, 2019
c45ad97
Check the underlying type of get-only computed properties with opaque…
jckarter Apr 16, 2019
a632916
Serialize opaque return type of var/subscript decls.
jckarter Apr 16, 2019
ba025c3
Visit var/subscript opaque return decls during IRGen/TBDGen.
jckarter Apr 17, 2019
01df1ac
Track var/subscript opaque return decls for type reconstruction.
jckarter Apr 17, 2019
0dbaa43
Demangler: Register substitution for opaque archetype manglings
jckarter Apr 17, 2019
efb43e3
Serialization: Cross-reference opaque return types by mangled name. r…
jckarter Apr 18, 2019
b8915f6
MetadataLookup: Use extension's generic context for non-nominal exten…
jckarter Apr 19, 2019
aaa800f
[Opaque result types] Fix mangling issues with opaque result types.
DougGregor Apr 22, 2019
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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@ CHANGELOG
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-0254][]:

Subscripts can now be declared `static` or (inside classes) `class`.
Expand Down
36 changes: 33 additions & 3 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 @@ -952,6 +953,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,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 @@ -82,6 +90,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
Loading