Skip to content

Commit 69be7b1

Browse files
authored
Merge pull request swiftlang#40282 from hborla/existential-any
[SE-0335] Introduce existential `any`
2 parents 5a6341b + f96104d commit 69be7b1

Some content is hidden

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

51 files changed

+1035
-24
lines changed

include/swift/AST/Decl.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
520520
IsComputingSemanticMembers : 1
521521
);
522522

523-
SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+8+16,
523+
SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+1+1+8+16,
524524
/// Whether the \c RequiresClass bit is valid.
525525
RequiresClassValid : 1,
526526

@@ -533,6 +533,12 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
533533
/// Whether the existential of this protocol conforms to itself.
534534
ExistentialConformsToSelf : 1,
535535

536+
/// Whether the \c ExistentialRequiresAny bit is valid.
537+
ExistentialRequiresAnyValid : 1,
538+
539+
/// Whether the existential of this protocol must be spelled with \c any.
540+
ExistentialRequiresAny : 1,
541+
536542
/// True if the protocol has requirements that cannot be satisfied (e.g.
537543
/// because they could not be imported from Objective-C).
538544
HasMissingRequirements : 1,
@@ -4244,6 +4250,21 @@ class ProtocolDecl final : public NominalTypeDecl {
42444250
Bits.ProtocolDecl.ExistentialConformsToSelf = result;
42454251
}
42464252

4253+
/// Returns the cached result of \c existentialRequiresAny or \c None if it
4254+
/// hasn't yet been computed.
4255+
Optional<bool> getCachedExistentialRequiresAny() {
4256+
if (Bits.ProtocolDecl.ExistentialRequiresAnyValid)
4257+
return Bits.ProtocolDecl.ExistentialRequiresAny;
4258+
4259+
return None;
4260+
}
4261+
4262+
/// Caches the result of \c existentialRequiresAny
4263+
void setCachedExistentialRequiresAny(bool requiresAny) {
4264+
Bits.ProtocolDecl.ExistentialRequiresAnyValid = true;
4265+
Bits.ProtocolDecl.ExistentialRequiresAny = requiresAny;
4266+
}
4267+
42474268
bool hasLazyRequirementSignature() const {
42484269
return Bits.ProtocolDecl.HasLazyRequirementSignature;
42494270
}
@@ -4257,6 +4278,7 @@ class ProtocolDecl final : public NominalTypeDecl {
42574278
friend class RequirementSignatureRequestRQM;
42584279
friend class ProtocolRequiresClassRequest;
42594280
friend class ExistentialConformsToSelfRequest;
4281+
friend class ExistentialRequiresAnyRequest;
42604282
friend class InheritedProtocolsRequest;
42614283

42624284
public:
@@ -4345,6 +4367,11 @@ class ProtocolDecl final : public NominalTypeDecl {
43454367
/// contain 'Self' in 'parameter' or 'other' position.
43464368
bool isAvailableInExistential(const ValueDecl *decl) const;
43474369

4370+
/// Determine whether an existential type must be explicitly prefixed
4371+
/// with \c any. \c any is required if any of the members contain
4372+
/// an associated type, or if \c Self appears in non-covariant position.
4373+
bool existentialRequiresAny() const;
4374+
43484375
/// Returns a list of protocol requirements that must be assessed to
43494376
/// determine a concrete's conformance effect polymorphism kind.
43504377
PolymorphicEffectRequirementList getPolymorphicEffectRequirements(

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,8 @@ ERROR(sil_function_subs_without_generics,none,
873873

874874
// Opaque types
875875
ERROR(opaque_mid_composition,none,
876-
"'some' should appear at the beginning of a composition", ())
876+
"'%0' should appear at the beginning of a composition",
877+
(StringRef))
877878

878879
//------------------------------------------------------------------------------
879880
// MARK: Layout constraint diagnostics

include/swift/AST/DiagnosticsSema.def

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4615,6 +4615,19 @@ ERROR(unchecked_not_inheritance_clause,none,
46154615
ERROR(unchecked_not_existential,none,
46164616
"'unchecked' attribute cannot apply to non-protocol type %0", (Type))
46174617

4618+
WARNING(unnecessary_any,none,
4619+
"'any' is redundant on type %0", (Type))
4620+
ERROR(any_not_existential,none,
4621+
"'any' has no effect on %select{concrete type|type parameter}0 %1",
4622+
(bool, Type))
4623+
ERROR(existential_requires_any,none,
4624+
"protocol %0 as a type must be explicitly marked as 'any'",
4625+
(Identifier))
4626+
ERROR(explicit_existential_not_supported,none,
4627+
"explicit 'any' not supported; use frontend flag "
4628+
"-enable-explicit-existential-types to enable this feature",
4629+
())
4630+
46184631
ERROR(nonisolated_let,none,
46194632
"'nonisolated' is meaningless on 'let' declarations because "
46204633
"they are immutable",

include/swift/AST/TypeCheckRequests.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,32 @@ class ExistentialConformsToSelfRequest :
287287
void cacheResult(bool value) const;
288288
};
289289

290+
/// Determine whether an existential type conforming to this protocol
291+
/// requires the \c any syntax.
292+
class ExistentialRequiresAnyRequest :
293+
public SimpleRequest<ExistentialRequiresAnyRequest,
294+
bool(ProtocolDecl *),
295+
RequestFlags::SeparatelyCached> {
296+
public:
297+
using SimpleRequest::SimpleRequest;
298+
299+
private:
300+
friend SimpleRequest;
301+
302+
// Evaluation.
303+
bool evaluate(Evaluator &evaluator, ProtocolDecl *decl) const;
304+
305+
public:
306+
// Cycle handling.
307+
void diagnoseCycle(DiagnosticEngine &diags) const;
308+
void noteCycleStep(DiagnosticEngine &diags) const;
309+
310+
// Separate caching.
311+
bool isCached() const { return true; }
312+
Optional<bool> getCachedResult() const;
313+
void cacheResult(bool value) const;
314+
};
315+
290316
class PolymorphicEffectRequirementsRequest :
291317
public SimpleRequest<PolymorphicEffectRequirementsRequest,
292318
PolymorphicEffectRequirementList(EffectKind, ProtocolDecl *),

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ SWIFT_REQUEST(TypeChecker, EnumRawTypeRequest,
9292
Type(EnumDecl *), Cached, NoLocationInfo)
9393
SWIFT_REQUEST(TypeChecker, ExistentialConformsToSelfRequest,
9494
bool(ProtocolDecl *), SeparatelyCached, NoLocationInfo)
95+
SWIFT_REQUEST(TypeChecker, ExistentialRequiresAnyRequest,
96+
bool(ProtocolDecl *), SeparatelyCached, NoLocationInfo)
9597
SWIFT_REQUEST(TypeChecker, ExtendedTypeRequest, Type(ExtensionDecl *), Cached,
9698
NoLocationInfo)
9799
SWIFT_REQUEST(TypeChecker, ResultBuilderTypeRequest, Type(ValueDecl *),

include/swift/AST/TypeDifferenceVisitor.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,12 @@ class CanTypeDifferenceVisitor : public CanTypePairVisitor<Impl, bool> {
328328
type1->getMembers(), type2->getMembers());
329329
}
330330

331+
bool visitExistentialType(CanExistentialType type1,
332+
CanExistentialType type2) {
333+
return asImpl().visit(type1.getConstraintType(),
334+
type2.getConstraintType());
335+
}
336+
331337
bool visitLValueType(CanLValueType type1, CanLValueType type2) {
332338
return asImpl().visit(type1.getObjectType(), type2.getObjectType());
333339
}

include/swift/AST/TypeMatcher.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,20 @@ class TypeMatcher {
269269
TRIVIAL_CASE(SILBoxType)
270270
TRIVIAL_CASE(ProtocolCompositionType)
271271

272+
bool visitExistentialType(CanExistentialType firstExistential,
273+
Type secondType,
274+
Type sugaredFirstType) {
275+
if (auto secondExistential = secondType->getAs<ExistentialType>()) {
276+
return this->visit(firstExistential.getConstraintType(),
277+
secondExistential->getConstraintType(),
278+
sugaredFirstType->castTo<ExistentialType>()
279+
->getConstraintType());
280+
}
281+
282+
return mismatch(firstExistential.getPointer(), secondType,
283+
sugaredFirstType);
284+
}
285+
272286
bool visitLValueType(CanLValueType firstLValue, Type secondType,
273287
Type sugaredFirstType) {
274288
if (auto secondLValue = secondType->getAs<LValueType>()) {

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ ARTIFICIAL_TYPE(SILBlockStorage, Type)
162162
ARTIFICIAL_TYPE(SILBox, Type)
163163
ARTIFICIAL_TYPE(SILToken, Type)
164164
TYPE(ProtocolComposition, Type)
165+
TYPE(Existential, Type)
165166
TYPE(LValue, Type)
166167
TYPE(InOut, Type)
167168
UNCHECKED_TYPE(TypeVariable, Type)

include/swift/AST/TypeRepr.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,35 @@ class NamedOpaqueReturnTypeRepr : public TypeRepr {
11581158
friend class TypeRepr;
11591159
};
11601160

1161+
/// A TypeRepr for an existential type spelled with \c any
1162+
///
1163+
/// Can appear anywhere a normal existential type would. This is
1164+
/// purely a more explicit spelling for existential types.
1165+
class ExistentialTypeRepr: public TypeRepr {
1166+
TypeRepr *Constraint;
1167+
SourceLoc AnyLoc;
1168+
1169+
public:
1170+
ExistentialTypeRepr(SourceLoc anyLoc, TypeRepr *constraint)
1171+
: TypeRepr(TypeReprKind::Existential), Constraint(constraint),
1172+
AnyLoc(anyLoc) {}
1173+
1174+
TypeRepr *getConstraint() const { return Constraint; }
1175+
SourceLoc getAnyLoc() const { return AnyLoc; }
1176+
1177+
static bool classof(const TypeRepr *T) {
1178+
return T->getKind() == TypeReprKind::Existential;
1179+
}
1180+
static bool classof(const ExistentialTypeRepr *T) { return true; }
1181+
1182+
private:
1183+
SourceLoc getStartLocImpl() const { return AnyLoc; }
1184+
SourceLoc getEndLocImpl() const { return Constraint->getEndLoc(); }
1185+
SourceLoc getLocImpl() const { return AnyLoc; }
1186+
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
1187+
friend class TypeRepr;
1188+
};
1189+
11611190
/// TypeRepr for a user-specified placeholder (essentially, a user-facing
11621191
/// representation of an anonymous type variable.
11631192
///
@@ -1285,6 +1314,7 @@ inline bool TypeRepr::isSimple() const {
12851314
case TypeReprKind::Composition:
12861315
case TypeReprKind::OpaqueReturn:
12871316
case TypeReprKind::NamedOpaqueReturn:
1317+
case TypeReprKind::Existential:
12881318
return false;
12891319
case TypeReprKind::SimpleIdent:
12901320
case TypeReprKind::GenericIdent:

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ TYPEREPR(Metatype, TypeRepr)
5555
TYPEREPR(Protocol, TypeRepr)
5656
TYPEREPR(OpaqueReturn, TypeRepr)
5757
TYPEREPR(NamedOpaqueReturn, TypeRepr)
58+
TYPEREPR(Existential, TypeRepr)
5859
TYPEREPR(Placeholder, TypeRepr)
5960
ABSTRACT_TYPEREPR(Specifier, TypeRepr)
6061
TYPEREPR(InOut, SpecifierTypeRepr)

0 commit comments

Comments
 (0)