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