@@ -3734,6 +3734,7 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3734
3734
3735
3735
enum class UnviabilityReason {
3736
3736
Failable,
3737
+ InvalidWrappedSelfType,
3737
3738
InvalidPropertyType,
3738
3739
InvalidStorageType,
3739
3740
Inaccessible
@@ -3815,6 +3816,7 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3815
3816
3816
3817
case UnviabilityReason::InvalidStorageType:
3817
3818
case UnviabilityReason::InvalidPropertyType:
3819
+ case UnviabilityReason::InvalidWrappedSelfType:
3818
3820
llvm_unreachable (" init(storage:) type is not checked" );
3819
3821
}
3820
3822
}
@@ -3880,15 +3882,20 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3880
3882
}
3881
3883
}
3882
3884
3883
- // subscript(propertyKeyPath: KeyPath, storedKeypath: {Writable}KeyPath)
3885
+ // subscript([wrappedSelf: Wrapped], propertyKeyPath: KeyPath, storedKeypath:
3886
+ // {Writable}KeyPath)
3884
3887
{
3885
- DeclName subscriptName (ctx, DeclBaseName::createSubscript (),
3886
- {ctx.Id_propertyKeyPath , ctx.Id_storageKeyPath });
3887
-
3888
3888
SmallVector<ValueDecl *, 2 > subscripts;
3889
- if (findMembersOrDiagnose (subscriptName, subscripts,
3890
- diag::type_wrapper_requires_subscript))
3891
- return ;
3889
+
3890
+ // Let's try to find all of the required subscripts.
3891
+ {
3892
+ DeclName subscriptName (ctx, DeclBaseName::createSubscript (),
3893
+ {ctx.Id_propertyKeyPath , ctx.Id_storageKeyPath });
3894
+
3895
+ if (findMembersOrDiagnose (subscriptName, subscripts,
3896
+ diag::type_wrapper_requires_subscript))
3897
+ return ;
3898
+ }
3892
3899
3893
3900
llvm::SmallDenseMap<SubscriptDecl *, SmallVector<UnviabilityReason, 2 >, 2 >
3894
3901
nonViableSubscripts;
@@ -3904,30 +3911,109 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3904
3911
return false ;
3905
3912
};
3906
3913
3914
+ auto getPropertyKeyPathParamIndex =
3915
+ [](SubscriptDecl *subscript) -> unsigned {
3916
+ return subscript->getIndices ()->size () == 2 ? 0 : 1 ;
3917
+ };
3918
+
3919
+ auto getStorageKeyPathParamIndex =
3920
+ [&](SubscriptDecl *subscript) -> unsigned {
3921
+ return getPropertyKeyPathParamIndex (subscript) + 1 ;
3922
+ };
3923
+
3924
+ auto diagnoseSubscript = [&](SubscriptDecl *subscript,
3925
+ ArrayRef<UnviabilityReason> reasons) {
3926
+ for (auto reason : reasons) {
3927
+ switch (reason) {
3928
+ case UnviabilityReason::InvalidWrappedSelfType: {
3929
+ auto wrappedSelfExpectedTy =
3930
+ genericParams->getParams ()[0 ]->getDeclaredInterfaceType ();
3931
+ auto paramTy = subscript->getIndices ()->get (0 )->getInterfaceType ();
3932
+ diagnose (subscript,
3933
+ diag::type_wrapper_subscript_invalid_parameter_type,
3934
+ ctx.Id_wrappedSelf , wrappedSelfExpectedTy, paramTy);
3935
+ break ;
3936
+ }
3937
+
3938
+ case UnviabilityReason::InvalidPropertyType: {
3939
+ auto paramTy = subscript->getIndices ()
3940
+ ->get (getPropertyKeyPathParamIndex (subscript))
3941
+ ->getInterfaceType ();
3942
+ diagnose (subscript,
3943
+ diag::type_wrapper_subscript_invalid_keypath_parameter,
3944
+ ctx.Id_propertyKeyPath , paramTy);
3945
+ break ;
3946
+ }
3947
+
3948
+ case UnviabilityReason::InvalidStorageType: {
3949
+ auto paramTy = subscript->getIndices ()
3950
+ ->get (getStorageKeyPathParamIndex (subscript))
3951
+ ->getInterfaceType ();
3952
+ diagnose (subscript,
3953
+ diag::type_wrapper_subscript_invalid_keypath_parameter,
3954
+ ctx.Id_storageKeyPath , paramTy);
3955
+ break ;
3956
+ }
3957
+
3958
+ case UnviabilityReason::Inaccessible:
3959
+ diagnose (subscript,
3960
+ diag::type_wrapper_type_requirement_not_accessible,
3961
+ subscript->getFormalAccess (),
3962
+ subscript->getDescriptiveKind (), subscript->getName (),
3963
+ nominal->getDeclaredType (), nominal->getFormalAccess ());
3964
+ break ;
3965
+
3966
+ case UnviabilityReason::Failable:
3967
+ llvm_unreachable (" subscripts cannot be failable" );
3968
+ }
3969
+ }
3970
+ };
3971
+
3907
3972
for (auto *decl : subscripts) {
3908
3973
auto *subscript = cast<SubscriptDecl>(decl);
3909
3974
3910
- auto *propertyKeyPathParam = subscript->getIndices ()->get (0 );
3975
+ auto *indices = subscript->getIndices ();
3976
+
3977
+ // Ignore `wrappedSelf`.
3978
+ bool forReferenceType = indices->size () == 3 ;
3979
+
3980
+ if (forReferenceType) {
3981
+ auto wrappedTypeParamTy =
3982
+ genericParams->getParams ()[0 ]->getDeclaredInterfaceType ();
3911
3983
3912
- if (!hasKeyPathType (propertyKeyPathParam)) {
3913
- nonViableSubscripts[subscript].push_back (
3914
- UnviabilityReason::InvalidPropertyType);
3984
+ auto wrappedSelf = indices->get (0 );
3985
+ if (!wrappedSelf->getInterfaceType ()->isEqual (wrappedTypeParamTy)) {
3986
+ nonViableSubscripts[subscript].push_back (
3987
+ UnviabilityReason::InvalidWrappedSelfType);
3988
+ }
3915
3989
}
3916
3990
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 ();
3923
- } else {
3924
- nonViableSubscripts[subscript].push_back (
3925
- UnviabilityReason::InvalidStorageType);
3991
+ auto *propertyKeyPathParam =
3992
+ indices->get (getPropertyKeyPathParamIndex (subscript));
3993
+ {
3994
+ if (!hasKeyPathType (propertyKeyPathParam)) {
3995
+ nonViableSubscripts[subscript].push_back (
3996
+ UnviabilityReason::InvalidPropertyType);
3997
+ }
3926
3998
}
3927
3999
3928
- if (isLessAccessibleThanType (subscript))
3929
- nonViableSubscripts[subscript].push_back (
3930
- UnviabilityReason::Inaccessible);
4000
+ auto *storageKeyPathParam =
4001
+ indices->get (getStorageKeyPathParamIndex (subscript));
4002
+ {
4003
+ if (hasKeyPathType (storageKeyPathParam)) {
4004
+ auto type = storageKeyPathParam->getInterfaceType ();
4005
+ hasReadOnly |= type->isKeyPath ();
4006
+ hasWritable |=
4007
+ type->isWritableKeyPath () || type->isReferenceWritableKeyPath ();
4008
+ } else {
4009
+ nonViableSubscripts[subscript].push_back (
4010
+ UnviabilityReason::InvalidStorageType);
4011
+ }
4012
+
4013
+ if (isLessAccessibleThanType (subscript))
4014
+ nonViableSubscripts[subscript].push_back (
4015
+ UnviabilityReason::Inaccessible);
4016
+ }
3931
4017
}
3932
4018
3933
4019
if (!hasReadOnly) {
@@ -3964,47 +4050,55 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3964
4050
" KeyPath<<#WrappedType#>, Value>, storageKeyPath "
3965
4051
" storagePath: "
3966
4052
" WritableKeyPath<<#Base#>, "
3967
- " Value>) -> Value { get { <#code#> } set { <#code#> } }" );
4053
+ " Value>) -> Value { get { <#code#> } set { <#code#> } "
4054
+ " }" );
3968
4055
});
3969
4056
attr->setInvalid ();
3970
4057
}
3971
4058
3972
4059
if (subscripts.size () - nonViableSubscripts.size () == 0 ) {
3973
4060
for (const auto &entry : nonViableSubscripts) {
3974
- auto *subscript = entry.first ;
4061
+ diagnoseSubscript (entry.first , entry.second );
4062
+ }
3975
4063
3976
- for (auto reason : entry.second ) {
3977
- switch (reason) {
3978
- case UnviabilityReason::InvalidPropertyType: {
3979
- auto paramTy = subscript->getIndices ()->get (0 )->getInterfaceType ();
3980
- diagnose (subscript, diag::type_wrapper_subscript_invalid_parameter,
3981
- ctx.Id_propertyKeyPath , paramTy);
3982
- break ;
3983
- }
4064
+ attr->setInvalid ();
4065
+ return ;
4066
+ }
3984
4067
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);
3989
- break ;
3990
- }
4068
+ // If there were no issues with required subscripts, let's look
4069
+ // for subscripts that are applicable only to reference types and
4070
+ // diagnose them inline.
4071
+ {
4072
+ DeclName subscriptName (
4073
+ ctx, DeclBaseName::createSubscript (),
4074
+ {ctx.Id_wrappedSelf , ctx.Id_propertyKeyPath , ctx.Id_storageKeyPath });
3991
4075
3992
- case UnviabilityReason::Inaccessible:
3993
- diagnose (subscript,
3994
- diag::type_wrapper_type_requirement_not_accessible,
3995
- subscript->getFormalAccess (),
3996
- subscript->getDescriptiveKind (), subscript->getName (),
3997
- nominal->getDeclaredType (), nominal->getFormalAccess ());
3998
- break ;
4076
+ for (auto *candidate : nominal->lookupDirect (subscriptName)) {
4077
+ auto *subscript = cast<SubscriptDecl>(candidate);
4078
+ auto *indices = subscript->getIndices ();
3999
4079
4000
- case UnviabilityReason::Failable:
4001
- llvm_unreachable (" subscripts cannot be failable" );
4002
- }
4080
+ auto wrappedTypeParamTy =
4081
+ genericParams->getParams ()[0 ]->getDeclaredInterfaceType ();
4082
+
4083
+ auto wrappedSelf = indices->get (0 );
4084
+ if (!wrappedSelf->getInterfaceType ()->isEqual (wrappedTypeParamTy)) {
4085
+ diagnoseSubscript (subscript,
4086
+ UnviabilityReason::InvalidWrappedSelfType);
4003
4087
}
4004
- }
4005
4088
4006
- attr->setInvalid ();
4007
- return ;
4089
+ auto *propertyKeyPathParam =
4090
+ indices->get (getPropertyKeyPathParamIndex (subscript));
4091
+ if (!hasKeyPathType (propertyKeyPathParam))
4092
+ diagnoseSubscript (subscript, UnviabilityReason::InvalidPropertyType);
4093
+
4094
+ auto *storageKeyPathParam =
4095
+ indices->get (getStorageKeyPathParamIndex (subscript));
4096
+ if (!hasKeyPathType (storageKeyPathParam))
4097
+ diagnoseSubscript (subscript, UnviabilityReason::InvalidStorageType);
4098
+
4099
+ if (isLessAccessibleThanType (subscript))
4100
+ diagnoseSubscript (subscript, UnviabilityReason::Inaccessible);
4101
+ }
4008
4102
}
4009
4103
}
4010
4104
}
0 commit comments