@@ -3732,7 +3732,12 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3732
3732
std::min (nominal->getFormalAccess (), AccessLevel::Public);
3733
3733
};
3734
3734
3735
- enum class UnviabilityReason { Failable, InvalidType, Inaccessible };
3735
+ enum class UnviabilityReason {
3736
+ Failable,
3737
+ InvalidPropertyType,
3738
+ InvalidStorageType,
3739
+ Inaccessible
3740
+ };
3736
3741
3737
3742
auto findMembersOrDiagnose = [&](DeclName memberName,
3738
3743
SmallVectorImpl<ValueDecl *> &results,
@@ -3808,7 +3813,8 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3808
3813
nominal->getFormalAccess ());
3809
3814
break ;
3810
3815
3811
- case UnviabilityReason::InvalidType:
3816
+ case UnviabilityReason::InvalidStorageType:
3817
+ case UnviabilityReason::InvalidPropertyType:
3812
3818
llvm_unreachable (" init(storage:) type is not checked" );
3813
3819
}
3814
3820
}
@@ -3874,11 +3880,10 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3874
3880
}
3875
3881
}
3876
3882
3877
- // subscript(storedKeypath: KeyPath<...> )
3883
+ // subscript(propertyKeyPath: KeyPath, storedKeypath: {Writable} KeyPath)
3878
3884
{
3879
- DeclName subscriptName (
3880
- ctx, DeclBaseName::createSubscript (),
3881
- ArrayRef<Identifier>(ctx.getIdentifier (" storageKeyPath" )));
3885
+ DeclName subscriptName (ctx, DeclBaseName::createSubscript (),
3886
+ {ctx.Id_propertyKeyPath , ctx.Id_storageKeyPath });
3882
3887
3883
3888
SmallVector<ValueDecl *, 2 > subscripts;
3884
3889
if (findMembersOrDiagnose (subscriptName, subscripts,
@@ -3891,25 +3896,33 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3891
3896
bool hasReadOnly = false ;
3892
3897
bool hasWritable = false ;
3893
3898
3899
+ auto hasKeyPathType = [](ParamDecl *PD) {
3900
+ if (auto *BGT = PD->getInterfaceType ()->getAs <BoundGenericType>()) {
3901
+ return BGT->isKeyPath () || BGT->isWritableKeyPath () ||
3902
+ BGT->isReferenceWritableKeyPath ();
3903
+ }
3904
+ return false ;
3905
+ };
3906
+
3894
3907
for (auto *decl : subscripts) {
3895
3908
auto *subscript = cast<SubscriptDecl>(decl);
3896
3909
3897
- auto *keyPathParam = subscript->getIndices ()->get (0 );
3898
-
3899
- if (auto *BGT =
3900
- keyPathParam-> getInterfaceType ()-> getAs <BoundGenericType>()) {
3901
- if (!(BGT-> isKeyPath () || BGT-> isWritableKeyPath () ||
3902
- BGT-> isReferenceWritableKeyPath ())) {
3903
- nonViableSubscripts[subscript]. push_back (
3904
- UnviabilityReason::InvalidType );
3905
- } else {
3906
- hasReadOnly |= BGT-> isKeyPath ();
3907
- hasWritable |=
3908
- BGT-> isWritableKeyPath () || BGT-> isReferenceWritableKeyPath ();
3909
- }
3910
+ auto *propertyKeyPathParam = subscript->getIndices ()->get (0 );
3911
+
3912
+ if (! hasKeyPathType (propertyKeyPathParam)) {
3913
+ nonViableSubscripts[subscript]. push_back (
3914
+ UnviabilityReason::InvalidPropertyType);
3915
+ }
3916
+
3917
+ auto *storageKeyPathParam = subscript-> getIndices ()-> get ( 1 );
3918
+ if ( hasKeyPathType (storageKeyPathParam)) {
3919
+ auto type = storageKeyPathParam-> getInterfaceType ();
3920
+ hasReadOnly |= type-> isKeyPath ();
3921
+ hasWritable |=
3922
+ type-> isWritableKeyPath () || type-> isReferenceWritableKeyPath ();
3910
3923
} else {
3911
3924
nonViableSubscripts[subscript].push_back (
3912
- UnviabilityReason::InvalidType );
3925
+ UnviabilityReason::InvalidStorageType );
3913
3926
}
3914
3927
3915
3928
if (isLessAccessibleThanType (subscript))
@@ -3928,7 +3941,9 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3928
3941
diag::add_type_wrapper_subscript_stub_note)
3929
3942
.fixItInsertAfter (
3930
3943
nominal->getBraces ().Start ,
3931
- " \n subscript<Value>(storageKeyPath path: KeyPath<<#Base#>, "
3944
+ " \n subscript<Value>(propertyKeyPath propPath: "
3945
+ " KeyPath<<#WrappedType#>, Value>, storageKeyPath "
3946
+ " storagePath: KeyPath<<#Base#>, "
3932
3947
" Value>) -> Value { get { <#code#> } }" );
3933
3948
});
3934
3949
attr->setInvalid ();
@@ -3945,7 +3960,9 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3945
3960
diag::add_type_wrapper_subscript_stub_note)
3946
3961
.fixItInsertAfter (
3947
3962
nominal->getBraces ().Start ,
3948
- " \n subscript<Value>(storageKeyPath path: "
3963
+ " \n subscript<Value>(propertyKeyPath propPath: "
3964
+ " KeyPath<<#WrappedType#>, Value>, storageKeyPath "
3965
+ " storagePath: "
3949
3966
" WritableKeyPath<<#Base#>, "
3950
3967
" Value>) -> Value { get { <#code#> } set { <#code#> } }" );
3951
3968
});
@@ -3958,10 +3975,17 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3958
3975
3959
3976
for (auto reason : entry.second ) {
3960
3977
switch (reason) {
3961
- case UnviabilityReason::InvalidType : {
3978
+ case UnviabilityReason::InvalidPropertyType : {
3962
3979
auto paramTy = subscript->getIndices ()->get (0 )->getInterfaceType ();
3963
- diagnose (subscript, diag::type_wrapper_invalid_subscript_param_type,
3964
- paramTy);
3980
+ diagnose (subscript, diag::type_wrapper_subscript_invalid_parameter,
3981
+ ctx.Id_propertyKeyPath , paramTy);
3982
+ break ;
3983
+ }
3984
+
3985
+ case UnviabilityReason::InvalidStorageType: {
3986
+ auto paramTy = subscript->getIndices ()->get (1 )->getInterfaceType ();
3987
+ diagnose (subscript, diag::type_wrapper_subscript_invalid_parameter,
3988
+ ctx.Id_storageKeyPath , paramTy);
3965
3989
break ;
3966
3990
}
3967
3991
0 commit comments