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