Skip to content

Commit 13e5c50

Browse files
authored
Merge pull request #22042 from jckarter/opaque-types-01-02-2019
[01-02-2019] Opaque result types
2 parents a10f65b + 7ca542a commit 13e5c50

File tree

87 files changed

+2175
-173
lines changed

Some content is hidden

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

87 files changed

+2175
-173
lines changed

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;
@@ -942,6 +943,7 @@ class ASTContext final {
942943

943944
friend TypeBase;
944945
friend ArchetypeType;
946+
friend OpaqueTypeDecl;
945947

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

include/swift/AST/Decl.h

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ enum class DescriptiveDeclKind : uint8_t {
157157
Module,
158158
MissingMember,
159159
Requirement,
160+
OpaqueType,
160161
};
161162

162163
/// Keeps track of stage of circularity checking for the given protocol.
@@ -2294,6 +2295,8 @@ class PoundDiagnosticDecl : public Decl {
22942295
return D->getKind() == DeclKind::PoundDiagnostic;
22952296
}
22962297
};
2298+
2299+
class OpaqueTypeDecl;
22972300

22982301
/// ValueDecl - All named decls that are values in the language. These can
22992302
/// have a type, etc.
@@ -2650,6 +2653,15 @@ class ValueDecl : public Decl {
26502653
/// True if this is a C function that was imported as a member of a type in
26512654
/// Swift.
26522655
bool isImportAsMember() const;
2656+
2657+
/// Get the decl for this value's opaque result type, if it has one.
2658+
OpaqueTypeDecl *getOpaqueResultTypeDecl() const;
2659+
2660+
/// Set the opaque return type decl for this decl.
2661+
///
2662+
/// `this` must be of a decl type that supports opaque return types, and
2663+
/// must not have previously had an opaque result type set.
2664+
void setOpaqueResultTypeDecl(OpaqueTypeDecl *D);
26532665
};
26542666

26552667
/// This is a common base class for declarations which declare a type.
@@ -2700,7 +2712,7 @@ class TypeDecl : public ValueDecl {
27002712
}
27012713
};
27022714

2703-
/// A type declaration that can have generic parameters attached to it. Because
2715+
/// A type declaration that can have generic parameters attached to it. Because
27042716
/// it has these generic parameters, it is always a DeclContext.
27052717
class GenericTypeDecl : public GenericContext, public TypeDecl {
27062718
public:
@@ -2725,7 +2737,69 @@ class GenericTypeDecl : public GenericContext, public TypeDecl {
27252737
}
27262738
};
27272739

2728-
2740+
/// OpaqueTypeDecl - This is a declaration of an opaque type. The opaque type
2741+
/// is formally equivalent to its underlying type, but abstracts it away from
2742+
/// clients of the opaque type, only exposing the type as something conforming
2743+
/// to a given set of constraints.
2744+
///
2745+
/// Currently, opaque types do not normally have an explicit spelling in source
2746+
/// code. One is formed implicitly when a declaration is written with an opaque
2747+
/// result type, as in:
2748+
///
2749+
/// func foo() -> opaque SignedInteger { return 1 }
2750+
///
2751+
/// The declared type is a special kind of ArchetypeType representing the
2752+
/// abstracted underlying type.
2753+
class OpaqueTypeDecl : public GenericTypeDecl {
2754+
/// The original declaration that "names" the opaque type. Although a specific
2755+
/// opaque type cannot be explicitly named, oapque types can propagate
2756+
/// arbitrarily through expressions, so we need to know *which* opaque type is
2757+
/// propagated.
2758+
ValueDecl *NamingDecl;
2759+
2760+
/// The generic signature of the opaque interface to the type. This is the
2761+
/// outer generic signature with an added generic parameter representing the
2762+
/// underlying type.
2763+
GenericSignature *OpaqueInterfaceGenericSignature;
2764+
2765+
/// The generic parameter that represents the underlying type.
2766+
GenericTypeParamType *UnderlyingInterfaceType;
2767+
2768+
/// If known, the underlying type and conformances of the opaque type,
2769+
/// expressed as a SubstitutionMap for the opaque interface generic signature.
2770+
/// This maps types in the interface generic signature to the outer generic
2771+
/// signature of the original declaration.
2772+
Optional<SubstitutionMap> UnderlyingTypeSubstitutions;
2773+
2774+
public:
2775+
OpaqueTypeDecl(ValueDecl *NamingDecl,
2776+
GenericParamList *GenericParams,
2777+
DeclContext *DC,
2778+
GenericSignature *OpaqueInterfaceGenericSignature,
2779+
GenericTypeParamType *UnderlyingInterfaceType);
2780+
2781+
ValueDecl *getNamingDecl() const { return NamingDecl; }
2782+
2783+
GenericSignature *getOpaqueInterfaceGenericSignature() const {
2784+
return OpaqueInterfaceGenericSignature;
2785+
}
2786+
2787+
GenericTypeParamType *getUnderlyingInterfaceType() const {
2788+
return UnderlyingInterfaceType;
2789+
}
2790+
2791+
Optional<SubstitutionMap> getUnderlyingTypeSubstitutions() const {
2792+
return UnderlyingTypeSubstitutions;
2793+
}
2794+
2795+
void setUnderlyingTypeSubstitutions(SubstitutionMap subs) {
2796+
assert(!UnderlyingTypeSubstitutions.hasValue() && "resetting underlying type?!");
2797+
UnderlyingTypeSubstitutions = subs;
2798+
}
2799+
2800+
// Opaque type decls are currently always implicit
2801+
SourceRange getSourceRange() const { return SourceRange(); }
2802+
};
27292803

27302804
/// TypeAliasDecl - This is a declaration of a typealias, for example:
27312805
///
@@ -5499,6 +5573,7 @@ class FuncDecl : public AbstractFunctionDecl {
54995573
TypeLoc FnRetType;
55005574

55015575
OperatorDecl *Operator = nullptr;
5576+
OpaqueTypeDecl *OpaqueReturn = nullptr;
55025577

55035578
protected:
55045579
FuncDecl(DeclKind Kind,
@@ -5652,6 +5727,14 @@ class FuncDecl : public AbstractFunctionDecl {
56525727
Operator = o;
56535728
}
56545729

5730+
OpaqueTypeDecl *getOpaqueResultTypeDecl() const {
5731+
return OpaqueReturn;
5732+
}
5733+
void setOpaqueResultTypeDecl(OpaqueTypeDecl *decl) {
5734+
assert(!OpaqueReturn && "already has opaque type decl");
5735+
OpaqueReturn = decl;
5736+
}
5737+
56555738
/// Returns true if the function is forced to be statically dispatched.
56565739
bool hasForcedStaticDispatch() const {
56575740
return Bits.FuncDecl.ForcedStaticDispatch;

include/swift/AST/DeclNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ ABSTRACT_DECL(Value, Decl)
152152
NOMINAL_TYPE_DECL(Class, NominalTypeDecl)
153153
NOMINAL_TYPE_DECL(Protocol, NominalTypeDecl)
154154
DECL_RANGE(NominalType, Enum, Protocol)
155+
GENERIC_VALUE_DECL(OpaqueType, GenericTypeDecl)
155156
GENERIC_VALUE_DECL(TypeAlias, GenericTypeDecl)
156157
DECL_RANGE(GenericType, Enum, TypeAlias)
157158
ABSTRACT_DECL(AbstractTypeParam, TypeDecl)

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,10 @@ ERROR(sil_box_expected_r_brace,none,
784784
ERROR(sil_box_expected_r_angle,none,
785785
"expected '>' to complete SIL box generic argument list", ())
786786

787+
// Opaque types
788+
ERROR(opaque_mid_composition,none,
789+
"'opaque' should appear at the beginning of a composition", ())
790+
787791
//------------------------------------------------------------------------------
788792
// MARK: Layout constraint diagnostics
789793
//------------------------------------------------------------------------------

include/swift/AST/DiagnosticsSema.def

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,6 +1503,11 @@ ERROR(noreturn_not_supported,none,
15031503
"'@noreturn' has been removed; functions that never return should have a "
15041504
"return type of 'Never' instead", ())
15051505

1506+
// Opaque return types
1507+
ERROR(opaque_type_invalid_constraint,none,
1508+
"an 'opaque' type must specify only 'Any', 'AnyObject', protocols, "
1509+
"and/or a base class", ())
1510+
15061511
// Extensions
15071512
ERROR(non_nominal_extension,none,
15081513
"non-nominal type %0 cannot be extended", (Type))
@@ -3204,6 +3209,18 @@ ERROR(trailing_closure_requires_parens,none,
32043209
"trailing closure requires parentheses for disambiguation in this"
32053210
" context", ())
32063211

3212+
ERROR(opaque_type_no_underlying_type_candidates,none,
3213+
"function declares an opaque return type, but has no return statements "
3214+
"in its body from which to infer an underlying type", ())
3215+
ERROR(opaque_type_mismatched_underlying_type_candidates,none,
3216+
"function declares an opaque return type, but the return statements "
3217+
"in its body do not have matching underlying types", ())
3218+
NOTE(opaque_type_underlying_type_candidate_here,none,
3219+
"return statement has underlying type %0", (Type))
3220+
ERROR(opaque_type_self_referential_underlying_type,none,
3221+
"function opaque return type was inferred as %0, which defines the "
3222+
"opaque type in terms of itself", (Type))
3223+
32073224
//------------------------------------------------------------------------------
32083225
// MARK: Type Check Patterns
32093226
//------------------------------------------------------------------------------
@@ -3514,6 +3531,10 @@ ERROR(unsupported_convention,none,
35143531
ERROR(unreferenced_generic_parameter,none,
35153532
"generic parameter '%0' is not used in function signature", (StringRef))
35163533

3534+
// Opaque types
3535+
ERROR(unsupported_opaque_type,none,
3536+
"'opaque' types are only implemented for the declared type of properties and subscripts and the return type of functions", ())
3537+
35173538
// SIL
35183539
ERROR(opened_non_protocol,none,
35193540
"@opened cannot be applied to non-protocol type %0", (Type))

include/swift/AST/Expr.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2871,6 +2871,17 @@ class UnevaluatedInstanceExpr : public ImplicitConversionExpr {
28712871
}
28722872
};
28732873

2874+
/// Use an opaque type to abstract a value of the underlying concrete type.
2875+
class UnderlyingToOpaqueExpr : public ImplicitConversionExpr {
2876+
public:
2877+
UnderlyingToOpaqueExpr(Expr *subExpr, Type ty)
2878+
: ImplicitConversionExpr(ExprKind::UnderlyingToOpaque, subExpr, ty) {}
2879+
2880+
static bool classof(const Expr *E) {
2881+
return E->getKind() == ExprKind::UnderlyingToOpaque;
2882+
}
2883+
};
2884+
28742885
/// TupleShuffleExpr - This represents a permutation of a tuple value to a new
28752886
/// tuple type.
28762887
///

include/swift/AST/ExprNodes.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ ABSTRACT_EXPR(ImplicitConversion, Expr)
168168
EXPR(PointerToPointer, ImplicitConversionExpr)
169169
EXPR(ForeignObjectConversion, ImplicitConversionExpr)
170170
EXPR(UnevaluatedInstance, ImplicitConversionExpr)
171-
EXPR_RANGE(ImplicitConversion, Load, UnevaluatedInstance)
171+
EXPR(UnderlyingToOpaque, ImplicitConversionExpr)
172+
EXPR_RANGE(ImplicitConversion, Load, UnderlyingToOpaque)
172173
ABSTRACT_EXPR(ExplicitCast, Expr)
173174
ABSTRACT_EXPR(CheckedCast, ExplicitCastExpr)
174175
EXPR(ForcedCheckedCast, CheckedCastExpr)

include/swift/AST/GenericSignature.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
307307
/// <t_0_0, t_0_1, t_1_0>
308308
/// then this will return 0 for t_0_0, 1 for t_0_1, and 2 for t_1_0.
309309
unsigned getGenericParamOrdinal(GenericTypeParamType *param);
310+
311+
/// Get a substitution map that maps all of the generic signature's
312+
/// generic parameters to themselves.
313+
SubstitutionMap getIdentitySubstitutionMap() const;
310314

311315
static void Profile(llvm::FoldingSetNodeID &ID,
312316
TypeArrayView<GenericTypeParamType> genericParams,

include/swift/AST/ProtocolConformance.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,8 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
323323
/// Substitute the conforming type and produce a ProtocolConformance that
324324
/// applies to the substituted type.
325325
ProtocolConformance *subst(TypeSubstitutionFn subs,
326-
LookupConformanceFn conformances) const;
326+
LookupConformanceFn conformances,
327+
SubstOptions options = None) const;
327328

328329
void dump() const;
329330
void dump(llvm::raw_ostream &out, unsigned indent = 0) const;

include/swift/AST/ProtocolConformanceRef.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,13 @@ class ProtocolConformanceRef {
106106
/// Apply a substitution to the conforming type.
107107
ProtocolConformanceRef subst(Type origType,
108108
TypeSubstitutionFn subs,
109-
LookupConformanceFn conformances) const;
109+
LookupConformanceFn conformances,
110+
SubstOptions options = None) const;
110111

112+
/// Replace opaque types in the conforming type with their underlying types,
113+
/// and resolve opaque conformances to their underlying conformances.
114+
ProtocolConformanceRef substOpaqueTypesWithUnderlyingTypes(Type origType) const;
115+
111116
/// Given a dependent type (expressed in terms of this conformance's
112117
/// protocol), follow it from the conforming type.
113118
Type getAssociatedType(Type origType, Type dependentType,

include/swift/AST/SubstitutionMap.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,12 @@ class SubstitutionMap {
169169
/// Apply a substitution to all replacement types in the map. Does not
170170
/// change keys.
171171
SubstitutionMap subst(TypeSubstitutionFn subs,
172-
LookupConformanceFn conformances) const;
172+
LookupConformanceFn conformances,
173+
SubstOptions options = None) const;
174+
175+
/// Replace opaque types in the replacement types in the map with their
176+
/// underlying types. Does not change keys.
177+
SubstitutionMap substOpaqueTypesWithUnderlyingTypes() const;
173178

174179
/// Create a substitution map for a protocol conformance.
175180
static SubstitutionMap

include/swift/AST/Type.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ class TypeBase;
5353
class Type;
5454
class TypeWalker;
5555
struct ExistentialLayout;
56-
56+
enum class ResilienceExpansion : unsigned;
57+
5758
/// Type substitution mapping from substitutable types to their
5859
/// replacements.
5960
typedef llvm::DenseMap<SubstitutableType *, Type> TypeSubstitutionMap;
@@ -147,6 +148,8 @@ enum class SubstFlags {
147148
AllowLoweredTypes = 0x02,
148149
/// Map member types to their desugared witness type.
149150
DesugarMemberTypes = 0x04,
151+
/// Substitute types involving opaque type archetypes.
152+
SubstituteOpaqueArchetypes = 0x08,
150153
};
151154

152155
/// Options for performing substitutions into a type.
@@ -312,6 +315,10 @@ class Type {
312315

313316
/// Replace references to substitutable types with error types.
314317
Type substDependentTypesWithErrorTypes() const;
318+
319+
/// Replace opaque types with their underlying types when visible at the given
320+
/// resilience expansion.
321+
Type substOpaqueTypesWithUnderlyingTypes() const;
315322

316323
bool isPrivateStdlibType(bool treatNonBuiltinProtocolsAsPublic = true) const;
317324

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ TYPE(DynamicSelf, Type)
133133
ABSTRACT_TYPE(Substitutable, Type)
134134
ABSTRACT_TYPE(Archetype, SubstitutableType)
135135
ALWAYS_CANONICAL_TYPE(PrimaryArchetype, ArchetypeType)
136+
ALWAYS_CANONICAL_TYPE(OpaqueTypeArchetype, ArchetypeType)
136137
ALWAYS_CANONICAL_TYPE(OpenedArchetype, ArchetypeType)
137138
ALWAYS_CANONICAL_TYPE(NestedArchetype, ArchetypeType)
138139
TYPE_RANGE(Archetype, PrimaryArchetype, NestedArchetype)

include/swift/AST/TypeRepr.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,45 @@ class SILBoxTypeReprField {
10101010
TypeRepr *getFieldType() const { return FieldTypeAndMutable.getPointer(); }
10111011
bool isMutable() const { return FieldTypeAndMutable.getInt(); }
10121012
};
1013+
1014+
/// TypeRepr for opaque return types.
1015+
///
1016+
/// This can occur in the return position of a function declaration, or the
1017+
/// top-level type of a property, to specify that the concrete return type
1018+
/// should be abstracted from callers, given a set of generic constraints that
1019+
/// the concrete return type satisfies:
1020+
///
1021+
/// func foo() -> opaque Collection { return [1,2,3] }
1022+
/// var bar: opaque SignedInteger = 1
1023+
///
1024+
/// It is currently illegal for this to appear in any other position.
1025+
class OpaqueReturnTypeRepr : public TypeRepr {
1026+
/// The type repr for the immediate constraints on the opaque type.
1027+
/// In valid code this must resolve to a class, protocol, or composition type.
1028+
TypeRepr *Constraint;
1029+
SourceLoc OpaqueLoc;
1030+
1031+
public:
1032+
OpaqueReturnTypeRepr(SourceLoc opaqueLoc, TypeRepr *constraint)
1033+
: TypeRepr(TypeReprKind::OpaqueReturn), Constraint(constraint),
1034+
OpaqueLoc(opaqueLoc)
1035+
{}
1036+
1037+
TypeRepr *getConstraint() const { return Constraint; }
1038+
SourceLoc getOpaqueLoc() const { return OpaqueLoc; }
1039+
1040+
static bool classof(const TypeRepr *T) {
1041+
return T->getKind() == TypeReprKind::OpaqueReturn;
1042+
}
1043+
static bool classof(const OpaqueReturnTypeRepr *T) { return true; }
1044+
1045+
private:
1046+
SourceLoc getStartLocImpl() const { return OpaqueLoc; }
1047+
SourceLoc getEndLocImpl() const { return Constraint->getEndLoc(); }
1048+
SourceLoc getLocImpl() const { return OpaqueLoc; }
1049+
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
1050+
friend class TypeRepr;
1051+
};
10131052

10141053
/// SIL-only TypeRepr for box types.
10151054
///
@@ -1108,6 +1147,7 @@ inline bool TypeRepr::isSimple() const {
11081147
case TypeReprKind::Function:
11091148
case TypeReprKind::InOut:
11101149
case TypeReprKind::Composition:
1150+
case TypeReprKind::OpaqueReturn:
11111151
return false;
11121152
case TypeReprKind::SimpleIdent:
11131153
case TypeReprKind::GenericIdent:

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ TYPEREPR(Tuple, TypeRepr)
5353
TYPEREPR(Composition, TypeRepr)
5454
TYPEREPR(Metatype, TypeRepr)
5555
TYPEREPR(Protocol, TypeRepr)
56+
TYPEREPR(OpaqueReturn, TypeRepr)
5657
ABSTRACT_TYPEREPR(Specifier, TypeRepr)
5758
TYPEREPR(InOut, SpecifierTypeRepr)
5859
TYPEREPR(Shared, SpecifierTypeRepr)

0 commit comments

Comments
 (0)