@@ -3686,6 +3686,7 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3686
3686
3687
3687
enum class UnviabilityReason {
3688
3688
Failable,
3689
+ InvalidWrappedSelfType,
3689
3690
InvalidPropertyType,
3690
3691
InvalidStorageType,
3691
3692
Inaccessible
@@ -3767,6 +3768,7 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3767
3768
3768
3769
case UnviabilityReason::InvalidStorageType:
3769
3770
case UnviabilityReason::InvalidPropertyType:
3771
+ case UnviabilityReason::InvalidWrappedSelfType:
3770
3772
llvm_unreachable (" init(storage:) type is not checked" );
3771
3773
}
3772
3774
}
@@ -3832,15 +3834,20 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3832
3834
}
3833
3835
}
3834
3836
3835
- // subscript(propertyKeyPath: KeyPath, storedKeypath: {Writable}KeyPath)
3837
+ // subscript([wrappedSelf: Wrapped], propertyKeyPath: KeyPath, storedKeypath:
3838
+ // {Writable}KeyPath)
3836
3839
{
3837
- DeclName subscriptName (ctx, DeclBaseName::createSubscript (),
3838
- {ctx.Id_propertyKeyPath , ctx.Id_storageKeyPath });
3839
-
3840
3840
SmallVector<ValueDecl *, 2 > subscripts;
3841
- if (findMembersOrDiagnose (subscriptName, subscripts,
3842
- diag::type_wrapper_requires_subscript))
3843
- return ;
3841
+
3842
+ // Let's try to find all of the required subscripts.
3843
+ {
3844
+ DeclName subscriptName (ctx, DeclBaseName::createSubscript (),
3845
+ {ctx.Id_propertyKeyPath , ctx.Id_storageKeyPath });
3846
+
3847
+ if (findMembersOrDiagnose (subscriptName, subscripts,
3848
+ diag::type_wrapper_requires_subscript))
3849
+ return ;
3850
+ }
3844
3851
3845
3852
llvm::SmallDenseMap<SubscriptDecl *, SmallVector<UnviabilityReason, 2 >, 2 >
3846
3853
nonViableSubscripts;
@@ -3856,30 +3863,109 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3856
3863
return false ;
3857
3864
};
3858
3865
3866
+ auto getPropertyKeyPathParamIndex =
3867
+ [](SubscriptDecl *subscript) -> unsigned {
3868
+ return subscript->getIndices ()->size () == 2 ? 0 : 1 ;
3869
+ };
3870
+
3871
+ auto getStorageKeyPathParamIndex =
3872
+ [&](SubscriptDecl *subscript) -> unsigned {
3873
+ return getPropertyKeyPathParamIndex (subscript) + 1 ;
3874
+ };
3875
+
3876
+ auto diagnoseSubscript = [&](SubscriptDecl *subscript,
3877
+ ArrayRef<UnviabilityReason> reasons) {
3878
+ for (auto reason : reasons) {
3879
+ switch (reason) {
3880
+ case UnviabilityReason::InvalidWrappedSelfType: {
3881
+ auto wrappedSelfExpectedTy =
3882
+ genericParams->getParams ()[0 ]->getDeclaredInterfaceType ();
3883
+ auto paramTy = subscript->getIndices ()->get (0 )->getInterfaceType ();
3884
+ diagnose (subscript,
3885
+ diag::type_wrapper_subscript_invalid_parameter_type,
3886
+ ctx.Id_wrappedSelf , wrappedSelfExpectedTy, paramTy);
3887
+ break ;
3888
+ }
3889
+
3890
+ case UnviabilityReason::InvalidPropertyType: {
3891
+ auto paramTy = subscript->getIndices ()
3892
+ ->get (getPropertyKeyPathParamIndex (subscript))
3893
+ ->getInterfaceType ();
3894
+ diagnose (subscript,
3895
+ diag::type_wrapper_subscript_invalid_keypath_parameter,
3896
+ ctx.Id_propertyKeyPath , paramTy);
3897
+ break ;
3898
+ }
3899
+
3900
+ case UnviabilityReason::InvalidStorageType: {
3901
+ auto paramTy = subscript->getIndices ()
3902
+ ->get (getStorageKeyPathParamIndex (subscript))
3903
+ ->getInterfaceType ();
3904
+ diagnose (subscript,
3905
+ diag::type_wrapper_subscript_invalid_keypath_parameter,
3906
+ ctx.Id_storageKeyPath , paramTy);
3907
+ break ;
3908
+ }
3909
+
3910
+ case UnviabilityReason::Inaccessible:
3911
+ diagnose (subscript,
3912
+ diag::type_wrapper_type_requirement_not_accessible,
3913
+ subscript->getFormalAccess (),
3914
+ subscript->getDescriptiveKind (), subscript->getName (),
3915
+ nominal->getDeclaredType (), nominal->getFormalAccess ());
3916
+ break ;
3917
+
3918
+ case UnviabilityReason::Failable:
3919
+ llvm_unreachable (" subscripts cannot be failable" );
3920
+ }
3921
+ }
3922
+ };
3923
+
3859
3924
for (auto *decl : subscripts) {
3860
3925
auto *subscript = cast<SubscriptDecl>(decl);
3861
3926
3862
- auto *propertyKeyPathParam = subscript->getIndices ()->get (0 );
3927
+ auto *indices = subscript->getIndices ();
3928
+
3929
+ // Ignore `wrappedSelf`.
3930
+ bool forReferenceType = indices->size () == 3 ;
3931
+
3932
+ if (forReferenceType) {
3933
+ auto wrappedTypeParamTy =
3934
+ genericParams->getParams ()[0 ]->getDeclaredInterfaceType ();
3863
3935
3864
- if (!hasKeyPathType (propertyKeyPathParam)) {
3865
- nonViableSubscripts[subscript].push_back (
3866
- UnviabilityReason::InvalidPropertyType);
3936
+ auto wrappedSelf = indices->get (0 );
3937
+ if (!wrappedSelf->getInterfaceType ()->isEqual (wrappedTypeParamTy)) {
3938
+ nonViableSubscripts[subscript].push_back (
3939
+ UnviabilityReason::InvalidWrappedSelfType);
3940
+ }
3867
3941
}
3868
3942
3869
- auto *storageKeyPathParam = subscript->getIndices ()->get (1 );
3870
- if (hasKeyPathType (storageKeyPathParam)) {
3871
- auto type = storageKeyPathParam->getInterfaceType ();
3872
- hasReadOnly |= type->isKeyPath ();
3873
- hasWritable |=
3874
- type->isWritableKeyPath () || type->isReferenceWritableKeyPath ();
3875
- } else {
3876
- nonViableSubscripts[subscript].push_back (
3877
- UnviabilityReason::InvalidStorageType);
3943
+ auto *propertyKeyPathParam =
3944
+ indices->get (getPropertyKeyPathParamIndex (subscript));
3945
+ {
3946
+ if (!hasKeyPathType (propertyKeyPathParam)) {
3947
+ nonViableSubscripts[subscript].push_back (
3948
+ UnviabilityReason::InvalidPropertyType);
3949
+ }
3878
3950
}
3879
3951
3880
- if (isLessAccessibleThanType (subscript))
3881
- nonViableSubscripts[subscript].push_back (
3882
- UnviabilityReason::Inaccessible);
3952
+ auto *storageKeyPathParam =
3953
+ indices->get (getStorageKeyPathParamIndex (subscript));
3954
+ {
3955
+ if (hasKeyPathType (storageKeyPathParam)) {
3956
+ auto type = storageKeyPathParam->getInterfaceType ();
3957
+ hasReadOnly |= type->isKeyPath ();
3958
+ hasWritable |=
3959
+ type->isWritableKeyPath () || type->isReferenceWritableKeyPath ();
3960
+ } else {
3961
+ nonViableSubscripts[subscript].push_back (
3962
+ UnviabilityReason::InvalidStorageType);
3963
+ }
3964
+
3965
+ if (isLessAccessibleThanType (subscript))
3966
+ nonViableSubscripts[subscript].push_back (
3967
+ UnviabilityReason::Inaccessible);
3968
+ }
3883
3969
}
3884
3970
3885
3971
if (!hasReadOnly) {
@@ -3916,47 +4002,55 @@ void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3916
4002
" KeyPath<<#WrappedType#>, Value>, storageKeyPath "
3917
4003
" storagePath: "
3918
4004
" WritableKeyPath<<#Base#>, "
3919
- " Value>) -> Value { get { <#code#> } set { <#code#> } }" );
4005
+ " Value>) -> Value { get { <#code#> } set { <#code#> } "
4006
+ " }" );
3920
4007
});
3921
4008
attr->setInvalid ();
3922
4009
}
3923
4010
3924
4011
if (subscripts.size () - nonViableSubscripts.size () == 0 ) {
3925
4012
for (const auto &entry : nonViableSubscripts) {
3926
- auto *subscript = entry.first ;
4013
+ diagnoseSubscript (entry.first , entry.second );
4014
+ }
3927
4015
3928
- for (auto reason : entry.second ) {
3929
- switch (reason) {
3930
- case UnviabilityReason::InvalidPropertyType: {
3931
- auto paramTy = subscript->getIndices ()->get (0 )->getInterfaceType ();
3932
- diagnose (subscript, diag::type_wrapper_subscript_invalid_parameter,
3933
- ctx.Id_propertyKeyPath , paramTy);
3934
- break ;
3935
- }
4016
+ attr->setInvalid ();
4017
+ return ;
4018
+ }
3936
4019
3937
- case UnviabilityReason::InvalidStorageType: {
3938
- auto paramTy = subscript->getIndices ()->get (1 )->getInterfaceType ();
3939
- diagnose (subscript, diag::type_wrapper_subscript_invalid_parameter,
3940
- ctx.Id_storageKeyPath , paramTy);
3941
- break ;
3942
- }
4020
+ // If there were no issues with required subscripts, let's look
4021
+ // for subscripts that are applicable only to reference types and
4022
+ // diagnose them inline.
4023
+ {
4024
+ DeclName subscriptName (
4025
+ ctx, DeclBaseName::createSubscript (),
4026
+ {ctx.Id_wrappedSelf , ctx.Id_propertyKeyPath , ctx.Id_storageKeyPath });
3943
4027
3944
- case UnviabilityReason::Inaccessible:
3945
- diagnose (subscript,
3946
- diag::type_wrapper_type_requirement_not_accessible,
3947
- subscript->getFormalAccess (),
3948
- subscript->getDescriptiveKind (), subscript->getName (),
3949
- nominal->getDeclaredType (), nominal->getFormalAccess ());
3950
- break ;
4028
+ for (auto *candidate : nominal->lookupDirect (subscriptName)) {
4029
+ auto *subscript = cast<SubscriptDecl>(candidate);
4030
+ auto *indices = subscript->getIndices ();
3951
4031
3952
- case UnviabilityReason::Failable:
3953
- llvm_unreachable (" subscripts cannot be failable" );
3954
- }
4032
+ auto wrappedTypeParamTy =
4033
+ genericParams->getParams ()[0 ]->getDeclaredInterfaceType ();
4034
+
4035
+ auto wrappedSelf = indices->get (0 );
4036
+ if (!wrappedSelf->getInterfaceType ()->isEqual (wrappedTypeParamTy)) {
4037
+ diagnoseSubscript (subscript,
4038
+ UnviabilityReason::InvalidWrappedSelfType);
3955
4039
}
3956
- }
3957
4040
3958
- attr->setInvalid ();
3959
- return ;
4041
+ auto *propertyKeyPathParam =
4042
+ indices->get (getPropertyKeyPathParamIndex (subscript));
4043
+ if (!hasKeyPathType (propertyKeyPathParam))
4044
+ diagnoseSubscript (subscript, UnviabilityReason::InvalidPropertyType);
4045
+
4046
+ auto *storageKeyPathParam =
4047
+ indices->get (getStorageKeyPathParamIndex (subscript));
4048
+ if (!hasKeyPathType (storageKeyPathParam))
4049
+ diagnoseSubscript (subscript, UnviabilityReason::InvalidStorageType);
4050
+
4051
+ if (isLessAccessibleThanType (subscript))
4052
+ diagnoseSubscript (subscript, UnviabilityReason::Inaccessible);
4053
+ }
3960
4054
}
3961
4055
}
3962
4056
}
0 commit comments