@@ -62,6 +62,10 @@ namespace clang {
62
62
class PointerAuthQualifier ;
63
63
} // end namespace clang
64
64
65
+ namespace {
66
+ class AttributeChecker ;
67
+ } // end anonymous namespace
68
+
65
69
namespace swift {
66
70
enum class AccessSemantics : unsigned char ;
67
71
class AccessorDecl ;
@@ -509,9 +513,24 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
509
513
defaultArgumentKind : NumDefaultArgumentKindBits
510
514
);
511
515
512
- SWIFT_INLINE_BITFIELD (SubscriptDecl, VarDecl, 2 ,
513
- StaticSpelling : 2
516
+ SWIFT_INLINE_BITFIELD (SubscriptDecl, VarDecl, 2 +2 ,
517
+ StaticSpelling : 2 ,
518
+
519
+ // / Whether this decl has been evaluated as eligible to satisfy an
520
+ // / `@dynamicMemberLookup` requirement, and if eligible, the type of dynamic
521
+ // / member parameter it would use to satisfy the requirement.
522
+ // /
523
+ // / * 0b00 - not yet evaluated
524
+ // / * 0b01 - evaluated; not eligible
525
+ // / * 0b10 - evaluated; eligible, taking a `{{Reference}Writable}KeyPath`
526
+ // / value
527
+ // / * 0b11 - evaluated; eligible, taking an `ExpressibleByStringLiteral`
528
+ // / value
529
+ // /
530
+ // / i.e., 0 or `DynamicMemberLookupSubscriptEligibility` values + 1
531
+ DynamicMemberLookupEligibility : 2
514
532
);
533
+
515
534
SWIFT_INLINE_BITFIELD (AbstractFunctionDecl, ValueDecl, 3 +2 +2 +2 +8 +1 +1 +1 +1 +1 +1 ,
516
535
// / \see AbstractFunctionDecl::BodyKind
517
536
BodyKind : 3 ,
@@ -7381,6 +7400,36 @@ enum class ObjCSubscriptKind {
7381
7400
Keyed
7382
7401
};
7383
7402
7403
+ // / Describes how a `SubscriptDecl` could be eligible to fulfill a
7404
+ // / `@dynamicMemberLookup` requirement.
7405
+ // /
7406
+ // / `@dynamicMemberLookup` requires that a subscript:
7407
+ // /
7408
+ // / 1. Take an initial argument with an explicit `dynamicMember` argument
7409
+ // / label,
7410
+ // / 2. Whose parameter type is non-variadic and is either
7411
+ // / * A `{{Reference}Writable}KeyPath`, or
7412
+ // / * A concrete type conforming to `ExpressibleByStringLiteral`,
7413
+ // / 3. And whose following arguments (if any) are all either variadic or have
7414
+ // / a default value
7415
+ // /
7416
+ // / Subscripts which don't meet these requirements strictly are not eligible.
7417
+ enum class DynamicMemberLookupSubscriptEligibility : uint8_t {
7418
+ // / The `SubscriptDecl` cannot fulfill a `@dynamicMemberLookup` requirement.
7419
+ // /
7420
+ // / This can be due to a name mismatch, type mismatch, missing default
7421
+ // / arguments, or otherwise.
7422
+ None,
7423
+
7424
+ // / The `SubscriptDecl` can fulfill a `@dynamicMemberLookup` requirement with
7425
+ // / a `{{Reference}Writable}KeyPath` dynamic member parameter.
7426
+ KeyPath,
7427
+
7428
+ // / The `SubscriptDecl` can fulfill a `@dynamicMemberLookup` requirement with
7429
+ // / an `ExpressibleByStringLiteral`-conforming dynamic member parameter.
7430
+ String,
7431
+ };
7432
+
7384
7433
// / Declares a subscripting operator for a type.
7385
7434
// /
7386
7435
// / A subscript declaration is defined as a get/set pair that produces a
@@ -7410,13 +7459,23 @@ enum class ObjCSubscriptKind {
7410
7459
// / signatures (indices and element type) are distinct.
7411
7460
// /
7412
7461
class SubscriptDecl : public GenericContext , public AbstractStorageDecl {
7462
+ friend AttributeChecker;
7413
7463
friend class ResultTypeRequest ;
7414
7464
7415
7465
SourceLoc StaticLoc;
7416
7466
SourceLoc ArrowLoc;
7417
7467
ParameterList *Indices;
7418
7468
TypeLoc ElementTy;
7419
7469
7470
+ // Maps `Bits.SubscriptDecl.DynamicMemberLookupEligibility` as stored to a
7471
+ // `DynamicMemberLookupSubscriptEligibility`; `None` if `@dynamicMemberLookup`
7472
+ // requirements have not been checked yet.
7473
+ DynamicMemberLookupSubscriptEligibility
7474
+ getStoredDynamicMemberLookupEligibility () const ;
7475
+
7476
+ void setDynamicMemberLookupEligibility (
7477
+ DynamicMemberLookupSubscriptEligibility eligibility);
7478
+
7420
7479
void setElementInterfaceType (Type type);
7421
7480
7422
7481
SubscriptDecl (DeclName Name,
@@ -7435,6 +7494,24 @@ class SubscriptDecl : public GenericContext, public AbstractStorageDecl {
7435
7494
setIndices (Indices);
7436
7495
}
7437
7496
7497
+ // Evaluates whether `SD` could satisfy `@dynamicMemberLookup` requirements
7498
+ // (without storing the result in `SD`). `ignoreArgLabel` allows checking of
7499
+ // requirements even if the subscript doesn't have a `dynamicMember:` argument
7500
+ // label; this is used by `AttributeChecker::visitDynamicMemberLookupAttr` to
7501
+ // produce fix-its and should otherwise be `false`.
7502
+ //
7503
+ // Implemented in the typechecker because it requires access to type checking
7504
+ // to validate the conformance of the `dynamicMember:` argument to
7505
+ // `ExpressibleByStringLiteral`.
7506
+ static DynamicMemberLookupSubscriptEligibility
7507
+ evaluateDynamicMemberLookupEligibility (const SubscriptDecl *SD,
7508
+ bool ignoreArgLabel = false );
7509
+
7510
+ // / Returns the given as a `BoundGenericType` if it is a
7511
+ // / `{{Reference}Writable}KeyPath` type which could be used to fulfill
7512
+ // / `@dynamicMemberLookup` requirements; `nullptr` otherwise.
7513
+ static BoundGenericType *getDynamicMemberParamTypeAsKeyPathType (Type paramTy);
7514
+
7438
7515
public:
7439
7516
// / Factory function only for use by deserialization.
7440
7517
static SubscriptDecl *createDeserialized (ASTContext &Context, DeclName Name,
@@ -7496,6 +7573,16 @@ class SubscriptDecl : public GenericContext, public AbstractStorageDecl {
7496
7573
// / implies.
7497
7574
ObjCSubscriptKind getObjCSubscriptKind () const ;
7498
7575
7576
+ // / Determines, caches, and returns whether the decl can be used to satisfy an
7577
+ // / `@dynamicMemberLookup` requirement (and if so, how).
7578
+ DynamicMemberLookupSubscriptEligibility
7579
+ getDynamicMemberLookupSubscriptEligibility ();
7580
+
7581
+ // / If the decl can be used to satisfy an `@dynamicMemberLookup` requirement
7582
+ // / using a `{{Reference}Writable}KeyPath` dynamic member parameter, returns
7583
+ // / the type of that parameter; `nullptr` otherwise.
7584
+ BoundGenericType *getDynamicMemberLookupKeyPathType ();
7585
+
7499
7586
SubscriptDecl *getOverriddenDecl () const {
7500
7587
return cast_or_null<SubscriptDecl>(
7501
7588
AbstractStorageDecl::getOverriddenDecl ());
0 commit comments