Skip to content

Commit a8c2b50

Browse files
authored
Merge pull request #22072 from jckarter/opaque-type-runtime
Opaque types with resilience
2 parents fa43e3b + b87a566 commit a8c2b50

File tree

143 files changed

+4467
-545
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

143 files changed

+4467
-545
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,20 @@ Swift Next
4444
Swift 5.1
4545
---------
4646

47+
* [SE-0244][]:
48+
49+
Functions can now hide their concrete return type by declaring what protocols
50+
it conforms to instead of specifying the exact return type:
51+
52+
```
53+
func makeMeACollection() -> some Collection {
54+
return [1, 2, 3]
55+
}
56+
```
57+
58+
Code that calls the function can use the interface of the protocol, but
59+
does not have visibility into the underlying type.
60+
4761
* [SE-0256][]:
4862

4963
Subscripts can now be declared `static` or (inside classes) `class`.

docs/ABI/Mangling.rst

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,13 @@ The following symbolic reference kinds are currently implemented:
7878

7979
::
8080

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

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

9297
associated-conformance-access-function ::= '\x07' .{4} // Reference points directly to associated conformance access function relative to the protocol
9398
associated-conformance-access-function ::= '\x08' .{4} // Reference points directly to associated conformance access function relative to the conforming type
94-
keypath-metadata-access-function ::= '\x09' {.4} // Reference points directly to keypath conformance access function
99+
100+
// keypaths only in Swift 5.0, generalized in Swift 5.1
101+
#if SWIFT_RUNTIME_VERSION >= 5.1
102+
metadata-access-function ::= '\x09' .{4} // Reference points directly to metadata access function that can be invoked to produce referenced object
103+
#endif
104+
105+
A mangled name may also include ``\xFF`` bytes, which are only used for
106+
alignment padding. They do not affect what the mangled name references and can
107+
be skipped over and ignored.
95108

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

619+
::
620+
621+
#if SWIFT_VERSION >= 5.1
622+
type ::= 'Qr' // opaque result type (of current decl)
623+
type ::= opaque-type-decl-name bound-generic-args 'Qo' INDEX // opaque type
624+
625+
opaque-type-decl-name ::= entity 'QO' // opaque result type of specified decl
626+
#endif
627+
628+
Opaque return types have a special short representation in the mangling of
629+
their defining entity. In structural position, opaque types are fully qualified
630+
by mangling the defining entity for the opaque declaration and the substitutions
631+
into the defining entity's generic environment.
632+
603633
The ``type*`` list contains parameter and return types (including the error
604634
result), in that order.
605635
The number of parameters and results must match with the number of

include/swift/ABI/Metadata.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3005,6 +3005,58 @@ struct TargetProtocolDescriptor final
30053005
return cd->getKind() == ContextDescriptorKind::Protocol;
30063006
}
30073007
};
3008+
3009+
/// The descriptor for an opaque type.
3010+
template <typename Runtime>
3011+
struct TargetOpaqueTypeDescriptor final
3012+
: TargetContextDescriptor<Runtime>,
3013+
TrailingGenericContextObjects<TargetOpaqueTypeDescriptor<Runtime>,
3014+
TargetGenericContextDescriptorHeader,
3015+
RelativeDirectPointer<const char>>
3016+
{
3017+
private:
3018+
using TrailingGenericContextObjects
3019+
= TrailingGenericContextObjects<TargetOpaqueTypeDescriptor<Runtime>,
3020+
TargetGenericContextDescriptorHeader,
3021+
RelativeDirectPointer<const char>>;
3022+
using TrailingObjects =
3023+
typename TrailingGenericContextObjects::TrailingObjects;
3024+
friend TrailingObjects;
3025+
3026+
template<typename T>
3027+
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
3028+
3029+
public:
3030+
using TrailingGenericContextObjects::getGenericContext;
3031+
using TrailingGenericContextObjects::getGenericContextHeader;
3032+
using TrailingGenericContextObjects::getFullGenericContextHeader;
3033+
using TrailingGenericContextObjects::getGenericParams;
3034+
3035+
// The kind-specific flags area is used to store the count of the generic
3036+
// arguments for underlying type(s) encoded in the descriptor.
3037+
unsigned getNumUnderlyingTypeArguments() const {
3038+
return this->Flags.getKindSpecificFlags();
3039+
}
3040+
3041+
using TrailingGenericContextObjects::numTrailingObjects;
3042+
size_t numTrailingObjects(OverloadToken<RelativeDirectPointer<const char>>) const {
3043+
return getNumUnderlyingTypeArguments();
3044+
}
3045+
3046+
StringRef getUnderlyingTypeArgument(unsigned i) const {
3047+
assert(i < getNumUnderlyingTypeArguments());
3048+
const char *ptr =
3049+
(this->template getTrailingObjects<RelativeDirectPointer<const char>>())[i];
3050+
3051+
return Demangle::makeSymbolicMangledNameStringRef(ptr);
3052+
}
3053+
3054+
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
3055+
return cd->getKind() == ContextDescriptorKind::OpaqueType;
3056+
}
3057+
};
3058+
3059+
using OpaqueTypeDescriptor = TargetOpaqueTypeDescriptor<InProcess>;
30083060

30093061
/// The instantiation cache for generic metadata. This must be guaranteed
30103062
/// to zero-initialized before it is first accessed. Its contents are private
@@ -4213,6 +4265,9 @@ TargetContextDescriptor<Runtime>::getGenericContext() const {
42134265
case ContextDescriptorKind::Struct:
42144266
return llvm::cast<TargetStructDescriptor<Runtime>>(this)
42154267
->getGenericContext();
4268+
case ContextDescriptorKind::OpaqueType:
4269+
return llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)
4270+
->getGenericContext();
42164271
default:
42174272
// We don't know about this kind of descriptor.
42184273
return nullptr;
@@ -4264,6 +4319,8 @@ TargetTypeContextDescriptor<Runtime>::getGenericParams() const {
42644319
return llvm::cast<TargetEnumDescriptor<Runtime>>(this)->getGenericParams();
42654320
case ContextDescriptorKind::Struct:
42664321
return llvm::cast<TargetStructDescriptor<Runtime>>(this)->getGenericParams();
4322+
case ContextDescriptorKind::OpaqueType:
4323+
return llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)->getGenericParams();
42674324
default:
42684325
swift_runtime_unreachable("Not a type context descriptor.");
42694326
}

include/swift/ABI/MetadataValues.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,9 @@ enum class ContextDescriptorKind : uint8_t {
11021102

11031103
/// This context descriptor represents a protocol context.
11041104
Protocol = 3,
1105+
1106+
/// This context descriptor represents an opaque type alias.
1107+
OpaqueType = 4,
11051108

11061109
/// First kind that represents a type of any sort.
11071110
Type_First = 16,

include/swift/AST/ASTContext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ namespace swift {
8484
class ModuleLoader;
8585
class NominalTypeDecl;
8686
class NormalProtocolConformance;
87+
class OpaqueTypeDecl;
8788
class InheritedProtocolConformance;
8889
class SelfProtocolConformance;
8990
class SpecializedProtocolConformance;
@@ -943,6 +944,7 @@ class ASTContext final {
943944

944945
friend TypeBase;
945946
friend ArchetypeType;
947+
friend OpaqueTypeDecl;
946948

947949
/// Provide context-level uniquing for SIL lowered type layouts and boxes.
948950
friend SILLayout;

include/swift/AST/ASTDemangler.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ class ASTBuilder {
5858
using BuiltTypeDecl = swift::GenericTypeDecl *; // nominal or type alias
5959
using BuiltProtocolDecl = swift::ProtocolDecl *;
6060
explicit ASTBuilder(ASTContext &ctx) : Ctx(ctx) {}
61+
62+
/// The resolver to use for type checking, if necessary.
63+
LazyResolver *Resolver = nullptr;
6164

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

8487
Type createBoundGenericType(GenericTypeDecl *decl, ArrayRef<Type> args);
88+
89+
Type resolveOpaqueType(NodePointer opaqueDescriptor,
90+
ArrayRef<Type> args,
91+
unsigned ordinal);
8592

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

include/swift/AST/ASTMangler.h

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,18 @@ class ASTMangler : public Mangler {
5959

6060
public:
6161
using SymbolicReferent = llvm::PointerUnion<const NominalTypeDecl *,
62-
const ProtocolConformance *>;
62+
const OpaqueTypeDecl *>;
6363
protected:
6464

6565
/// If set, the mangler calls this function to determine whether to symbolic
66-
/// reference a given entity. Defaults to always returning true.
66+
/// reference a given entity. If null, the mangler acts as if it's set to
67+
/// always return true.
6768
std::function<bool (SymbolicReferent)> CanSymbolicReference;
69+
70+
bool canSymbolicReference(SymbolicReferent referent) {
71+
return AllowSymbolicReferences
72+
&& (!CanSymbolicReference || CanSymbolicReference(referent));
73+
}
6874

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

@@ -201,7 +207,7 @@ class ASTMangler : public Mangler {
201207

202208
void appendSymbolKind(SymbolKind SKind);
203209

204-
void appendType(Type type);
210+
void appendType(Type type, const ValueDecl *forDecl = nullptr);
205211

206212
void appendDeclName(const ValueDecl *decl);
207213

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

216222
void bindGenericParameters(CanGenericSignature sig);
217223

224+
/// Mangles a sugared type iff we are mangling for the debugger.
225+
template <class T> void appendSugaredType(Type type,
226+
const ValueDecl *forDecl) {
227+
assert(DWARFMangling &&
228+
"sugared types are only legal when mangling for the debugger");
229+
auto *BlandTy = cast<T>(type.getPointer())->getSinglyDesugaredType();
230+
appendType(BlandTy, forDecl);
231+
}
232+
218233
void appendBoundGenericArgs(Type type, bool &isFirstArgList);
219234

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

229244
/// Append any retroactive conformances.
230245
void appendRetroactiveConformances(Type type);
231-
246+
void appendRetroactiveConformances(SubstitutionMap subMap,
247+
ModuleDecl *fromModule);
232248
void appendImplFunctionType(SILFunctionType *fn);
233249

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

243259
void appendAnyGenericType(const GenericTypeDecl *decl);
244260

245-
void appendFunction(AnyFunctionType *fn, bool isFunctionMangling = false);
246-
void appendFunctionType(AnyFunctionType *fn, bool isAutoClosure = false);
261+
void appendFunction(AnyFunctionType *fn, bool isFunctionMangling = false,
262+
const ValueDecl *forDecl = nullptr);
263+
void appendFunctionType(AnyFunctionType *fn, bool isAutoClosure = false,
264+
const ValueDecl *forDecl = nullptr);
247265

248-
void appendFunctionSignature(AnyFunctionType *fn);
266+
void appendFunctionSignature(AnyFunctionType *fn,
267+
const ValueDecl *forDecl = nullptr);
249268

250-
void appendFunctionInputType(ArrayRef<AnyFunctionType::Param> params);
251-
void appendFunctionResultType(Type resultType);
269+
void appendFunctionInputType(ArrayRef<AnyFunctionType::Param> params,
270+
const ValueDecl *forDecl = nullptr);
271+
void appendFunctionResultType(Type resultType,
272+
const ValueDecl *forDecl = nullptr);
252273

253-
void appendTypeList(Type listTy);
274+
void appendTypeList(Type listTy, const ValueDecl *forDecl = nullptr);
254275
void appendTypeListElement(Identifier name, Type elementType,
255-
ParameterTypeFlags flags);
276+
ParameterTypeFlags flags,
277+
const ValueDecl *forDecl = nullptr);
256278

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

321343
void appendSymbolicReference(SymbolicReferent referent);
344+
345+
void appendOpaqueDeclName(const OpaqueTypeDecl *opaqueDecl);
322346
};
323347

324348
} // end namespace Mangle

include/swift/AST/Attr.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ TYPE_ATTR(yield_many)
8282
TYPE_ATTR(thin)
8383
TYPE_ATTR(thick)
8484

85+
// Generated interface attributes
86+
TYPE_ATTR(_opaqueReturnTypeOf)
87+
8588
// Schema for DECL_ATTR:
8689
//
8790
// - Attribute name.

include/swift/AST/Attr.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ class TypeAttributes {
6767

6868
// For an opened existential type, the known ID.
6969
Optional<UUID> OpenedID;
70+
71+
// For a reference to an opaque return type, the mangled name and argument
72+
// index into the generic signature.
73+
struct OpaqueReturnTypeRef {
74+
StringRef mangledName;
75+
unsigned index;
76+
};
77+
Optional<OpaqueReturnTypeRef> OpaqueReturnTypeOf;
7078

7179
TypeAttributes() {}
7280

@@ -84,6 +92,10 @@ class TypeAttributes {
8492
return AttrLocs[A];
8593
}
8694

95+
void setOpaqueReturnTypeOf(StringRef mangling, unsigned index) {
96+
OpaqueReturnTypeOf = OpaqueReturnTypeRef{mangling, index};
97+
}
98+
8799
void setAttr(TypeAttrKind A, SourceLoc L) {
88100
assert(!L.isInvalid() && "Cannot clear attribute with this method");
89101
AttrLocs[A] = L;

0 commit comments

Comments
 (0)