@@ -4563,7 +4563,7 @@ synthesizeBaseClassFieldGetterBody(AbstractFunctionDecl *afd, void *context) {
4563
4563
ASTContext &ctx = afd->getASTContext ();
4564
4564
4565
4565
AccessorDecl *getterDecl = cast<AccessorDecl>(afd);
4566
- VarDecl *baseClassVar = static_cast <VarDecl *>(context);
4566
+ AbstractStorageDecl *baseClassVar = static_cast <AbstractStorageDecl *>(context);
4567
4567
StructDecl *baseStruct =
4568
4568
cast<StructDecl>(baseClassVar->getDeclContext ()->getAsDecl ());
4569
4569
StructDecl *derivedStruct =
@@ -4590,10 +4590,29 @@ synthesizeBaseClassFieldGetterBody(AbstractFunctionDecl *afd, void *context) {
4590
4590
AccessSemantics accessKind = baseClassVar->getClangDecl ()
4591
4591
? AccessSemantics::DirectToStorage
4592
4592
: AccessSemantics::DirectToImplementation;
4593
- auto baseMember =
4594
- new (ctx) MemberRefExpr (casted, SourceLoc (), baseClassVar, DeclNameLoc (),
4595
- /* Implicit=*/ true , accessKind);
4596
- baseMember->setType (baseClassVar->getType ());
4593
+ Expr *baseMember = nullptr ;
4594
+ if (auto subscript = dyn_cast<SubscriptDecl>(baseClassVar)) {
4595
+ auto paramDecl = getterDecl->getParameters ()->get (0 );
4596
+ auto paramRefExpr = new (ctx) DeclRefExpr (paramDecl,
4597
+ DeclNameLoc (),
4598
+ /* Implicit=*/ true );
4599
+ paramRefExpr->setType (paramDecl->getType ());
4600
+
4601
+ auto *argList = ArgumentList::forImplicitUnlabeled (ctx, {paramRefExpr});
4602
+ baseMember = SubscriptExpr::create (ctx, casted, argList, subscript);
4603
+ baseMember->setType (subscript->getElementInterfaceType ());
4604
+ } else {
4605
+ // If the base class var has a clang decl, that means it's an access into a
4606
+ // stored field. Otherwise, we're looking into another base class, so it's a
4607
+ // another synthesized accessor.
4608
+ AccessSemantics accessKind = baseClassVar->getClangDecl ()
4609
+ ? AccessSemantics::DirectToStorage
4610
+ : AccessSemantics::DirectToImplementation;
4611
+ baseMember =
4612
+ new (ctx) MemberRefExpr (casted, SourceLoc (), baseClassVar, DeclNameLoc (),
4613
+ /* Implicit=*/ true , accessKind);
4614
+ baseMember->setType (cast<VarDecl>(baseClassVar)->getType ());
4615
+ }
4597
4616
4598
4617
auto ret = new (ctx) ReturnStmt (SourceLoc (), baseMember);
4599
4618
auto body = BraceStmt::create (ctx, SourceLoc (), {ret}, SourceLoc (),
@@ -4611,7 +4630,7 @@ synthesizeBaseClassFieldGetterBody(AbstractFunctionDecl *afd, void *context) {
4611
4630
static std::pair<BraceStmt *, bool >
4612
4631
synthesizeBaseClassFieldSetterBody (AbstractFunctionDecl *afd, void *context) {
4613
4632
auto setterDecl = cast<AccessorDecl>(afd);
4614
- VarDecl *baseClassVar = static_cast <VarDecl *>(context);
4633
+ AbstractStorageDecl *baseClassVar = static_cast <AbstractStorageDecl *>(context);
4615
4634
ASTContext &ctx = setterDecl->getASTContext ();
4616
4635
4617
4636
StructDecl *baseStruct =
@@ -4622,16 +4641,30 @@ synthesizeBaseClassFieldSetterBody(AbstractFunctionDecl *afd, void *context) {
4622
4641
auto *pointeePropertyRefExpr =
4623
4642
getInOutSelfInteropStaticCast (setterDecl, baseStruct, derivedStruct);
4624
4643
4625
- // If the base class var has a clang decl, that means it's an access into a
4626
- // stored field. Otherwise, we're looking into another base class, so it's a
4627
- // another synthesized accessor.
4628
- AccessSemantics accessKind = baseClassVar->getClangDecl ()
4629
- ? AccessSemantics::DirectToStorage
4630
- : AccessSemantics::DirectToImplementation;
4631
- auto storedRef =
4632
- new (ctx) MemberRefExpr (pointeePropertyRefExpr, SourceLoc (), baseClassVar,
4633
- DeclNameLoc (), /* Implicit=*/ true , accessKind);
4634
- storedRef->setType (LValueType::get (baseClassVar->getType ()));
4644
+ Expr *storedRef = nullptr ;
4645
+ if (auto subscript = dyn_cast<SubscriptDecl>(baseClassVar)) {
4646
+ auto paramDecl = setterDecl->getParameters ()->get (1 );
4647
+ auto paramRefExpr = new (ctx) DeclRefExpr (paramDecl,
4648
+ DeclNameLoc (),
4649
+ /* Implicit=*/ true );
4650
+ paramRefExpr->setType (paramDecl->getType ());
4651
+
4652
+ auto *argList = ArgumentList::forImplicitUnlabeled (ctx, {paramRefExpr});
4653
+ storedRef = SubscriptExpr::create (ctx, pointeePropertyRefExpr, argList, subscript);
4654
+ storedRef->setType (subscript->getElementInterfaceType ());
4655
+ } else {
4656
+ // If the base class var has a clang decl, that means it's an access into a
4657
+ // stored field. Otherwise, we're looking into another base class, so it's a
4658
+ // another synthesized accessor.
4659
+ AccessSemantics accessKind = baseClassVar->getClangDecl ()
4660
+ ? AccessSemantics::DirectToStorage
4661
+ : AccessSemantics::DirectToImplementation;
4662
+
4663
+ storedRef =
4664
+ new (ctx) MemberRefExpr (pointeePropertyRefExpr, SourceLoc (), baseClassVar,
4665
+ DeclNameLoc (), /* Implicit=*/ true , accessKind);
4666
+ storedRef->setType (LValueType::get (cast<VarDecl>(baseClassVar)->getType ()));
4667
+ }
4635
4668
4636
4669
auto newValueParamRefExpr =
4637
4670
new (ctx) DeclRefExpr (setterDecl->getParameters ()->get (0 ), DeclNameLoc (),
@@ -4648,12 +4681,23 @@ synthesizeBaseClassFieldSetterBody(AbstractFunctionDecl *afd, void *context) {
4648
4681
return {body, /* isTypeChecked=*/ true };
4649
4682
}
4650
4683
4651
- static std::array<AccessorDecl *, 2 >
4652
- makeBaseClassFieldAccessors (DeclContext *declContext, VarDecl *computedVar,
4653
- VarDecl *baseClassVar) {
4684
+ static SmallVector<AccessorDecl *, 2 >
4685
+ makeBaseClassMemberAccessors (DeclContext *declContext,
4686
+ AbstractStorageDecl *computedVar,
4687
+ AbstractStorageDecl *baseClassVar) {
4654
4688
auto &ctx = declContext->getASTContext ();
4655
4689
auto computedType = computedVar->getInterfaceType ();
4656
4690
4691
+ ParameterList *bodyParams = nullptr ;
4692
+ if (auto subscript = dyn_cast<SubscriptDecl>(baseClassVar)) {
4693
+ computedType = computedType->getAs <FunctionType>()->getResult ();
4694
+
4695
+ auto idxParam = subscript->getIndices ()->get (0 );
4696
+ bodyParams = ParameterList::create (ctx, { idxParam });
4697
+ } else {
4698
+ bodyParams = ParameterList::createEmpty (ctx);
4699
+ }
4700
+
4657
4701
auto getterDecl = AccessorDecl::create (
4658
4702
ctx,
4659
4703
/* FuncLoc=*/ SourceLoc (),
@@ -4663,18 +4707,31 @@ makeBaseClassFieldAccessors(DeclContext *declContext, VarDecl *computedVar,
4663
4707
/* Async=*/ false , /* AsyncLoc=*/ SourceLoc (),
4664
4708
/* Throws=*/ false ,
4665
4709
/* ThrowsLoc=*/ SourceLoc (),
4666
- /* GenericParams=*/ nullptr , ParameterList::createEmpty (ctx) , computedType,
4710
+ /* GenericParams=*/ nullptr , bodyParams , computedType,
4667
4711
declContext);
4668
4712
getterDecl->setIsTransparent (true );
4669
4713
getterDecl->setAccess (AccessLevel::Public);
4670
4714
getterDecl->setBodySynthesizer (synthesizeBaseClassFieldGetterBody,
4671
4715
baseClassVar);
4672
4716
4717
+ if (baseClassVar->getWriteImpl () == WriteImplKind::Immutable)
4718
+ return {getterDecl};
4719
+
4673
4720
auto newValueParam =
4674
4721
new (ctx) ParamDecl (SourceLoc (), SourceLoc (), Identifier (), SourceLoc (),
4675
4722
ctx.getIdentifier (" newValue" ), declContext);
4676
4723
newValueParam->setSpecifier (ParamSpecifier::Default);
4677
4724
newValueParam->setInterfaceType (computedType);
4725
+
4726
+ ParameterList *setterBodyParams = nullptr ;
4727
+ if (auto subscript = dyn_cast<SubscriptDecl>(baseClassVar)) {
4728
+ auto idxParam = subscript->getIndices ()->get (0 );
4729
+ bodyParams = ParameterList::create (ctx, { idxParam });
4730
+ setterBodyParams = ParameterList::create (ctx, { newValueParam, idxParam });
4731
+ } else {
4732
+ setterBodyParams = ParameterList::create (ctx, { newValueParam });
4733
+ }
4734
+
4678
4735
auto setterDecl = AccessorDecl::create (
4679
4736
ctx,
4680
4737
/* FuncLoc=*/ SourceLoc (),
@@ -4684,7 +4741,7 @@ makeBaseClassFieldAccessors(DeclContext *declContext, VarDecl *computedVar,
4684
4741
/* Async=*/ false , /* AsyncLoc=*/ SourceLoc (),
4685
4742
/* Throws=*/ false ,
4686
4743
/* ThrowsLoc=*/ SourceLoc (),
4687
- /* GenericParams=*/ nullptr , ParameterList::create (ctx, {newValueParam}) ,
4744
+ /* GenericParams=*/ nullptr , setterBodyParams ,
4688
4745
TupleType::getEmpty (ctx), declContext);
4689
4746
setterDecl->setIsTransparent (true );
4690
4747
setterDecl->setAccess (AccessLevel::Public);
@@ -4717,6 +4774,20 @@ ValueDecl *cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
4717
4774
return out;
4718
4775
}
4719
4776
4777
+ if (auto subscript = dyn_cast<SubscriptDecl>(decl)) {
4778
+ auto out = SubscriptDecl::create (
4779
+ subscript->getASTContext (), subscript->getName (), subscript->getStaticLoc (),
4780
+ subscript->getStaticSpelling (), subscript->getSubscriptLoc (),
4781
+ subscript->getIndices (), subscript->getNameLoc (), subscript->getElementInterfaceType (),
4782
+ newContext, subscript->getGenericParams ());
4783
+ out->copyFormalAccessFrom (subscript);
4784
+ out->setAccessors (SourceLoc (),
4785
+ makeBaseClassMemberAccessors (newContext, out, subscript),
4786
+ SourceLoc ());
4787
+ out->setImplInfo (subscript->getImplInfo ());
4788
+ return out;
4789
+ }
4790
+
4720
4791
if (auto var = dyn_cast<VarDecl>(decl)) {
4721
4792
auto rawMemory = allocateMemoryForDecl<VarDecl>(var->getASTContext (),
4722
4793
sizeof (VarDecl), false );
@@ -4728,9 +4799,11 @@ ValueDecl *cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
4728
4799
out->setIsDynamic (var->isDynamic ());
4729
4800
out->copyFormalAccessFrom (var);
4730
4801
out->setAccessors (SourceLoc (),
4731
- makeBaseClassFieldAccessors (newContext, out, var),
4802
+ makeBaseClassMemberAccessors (newContext, out, var),
4732
4803
SourceLoc ());
4733
- out->setImplInfo (StorageImplInfo::getComputed (StorageIsMutable));
4804
+ auto isMutable = var->getWriteImpl () == WriteImplKind::Immutable
4805
+ ? StorageIsNotMutable : StorageIsMutable;
4806
+ out->setImplInfo (StorageImplInfo::getComputed (isMutable));
4734
4807
out->setIsSetterMutating (true );
4735
4808
return out;
4736
4809
}
0 commit comments