@@ -793,71 +793,6 @@ static bool isConcurrentValueType(const DeclContext *dc, Type type) {
793
793
return checker.visit (type);
794
794
}
795
795
796
- Optional<NonConcurrentType> NonConcurrentType::get (
797
- const DeclContext *dc, ConcreteDeclRef declRef) {
798
- // For functions, check the parameter and result types.
799
- SubstitutionMap subs = declRef.getSubstitutions ();
800
- if (auto function = dyn_cast<AbstractFunctionDecl>(declRef.getDecl ())) {
801
- for (auto param : *function->getParameters ()) {
802
- Type paramType = param->getInterfaceType ().subst (subs);
803
- if (!isConcurrentValueType (dc, paramType)) {
804
- return NonConcurrentType {
805
- Kind::Parameter, ConcreteDeclRef (param, subs), paramType };
806
- }
807
- }
808
-
809
- // Check the result type of a function.
810
- if (auto func = dyn_cast<FuncDecl>(function)) {
811
- Type resultType = func->getResultInterfaceType ().subst (subs);
812
- if (!isConcurrentValueType (dc, resultType)) {
813
- return NonConcurrentType { Kind::Result, declRef, resultType };
814
- }
815
- }
816
-
817
- // Check the "self" type of an instance method.
818
- if (function->isInstanceMember ()) {
819
- if (auto selfParam = function->getImplicitSelfDecl ()) {
820
- Type paramType = selfParam->getInterfaceType ().subst (subs);
821
- if (!isConcurrentValueType (dc, paramType)) {
822
- return NonConcurrentType {
823
- Kind::Parameter, ConcreteDeclRef (selfParam, subs),
824
- paramType };
825
- }
826
- }
827
- }
828
- } else if (auto var = dyn_cast<VarDecl>(declRef.getDecl ())) {
829
- Type propertyType = var->getValueInterfaceType ().subst (subs);
830
- if (!isConcurrentValueType (dc, propertyType)) {
831
- return NonConcurrentType {
832
- Kind::Property, declRef, propertyType };
833
- }
834
- }
835
-
836
- return None;
837
- }
838
-
839
- void NonConcurrentType::diagnose (SourceLoc loc) {
840
- ASTContext &ctx = declRef.getDecl ()->getASTContext ();
841
-
842
- switch (kind) {
843
- case Parameter:
844
- ctx.Diags .diagnose (loc, diag::non_concurrent_param_type, type);
845
- break ;
846
-
847
- case Result:
848
- ctx.Diags .diagnose (loc, diag::non_concurrent_result_type, type);
849
- break ;
850
-
851
- case Property: {
852
- auto var = cast<VarDecl>(declRef.getDecl ());
853
- ctx.Diags .diagnose (loc, diag::non_concurrent_property_type,
854
- var->getDescriptiveKind (), var->getName (),
855
- type, var->isLocalCapture ());
856
- break ;
857
- }
858
- }
859
- }
860
-
861
796
static bool diagnoseNonConcurrentParameter (
862
797
SourceLoc loc, ConcurrentReferenceKind refKind, ConcreteDeclRef declRef,
863
798
ParamDecl *param, Type paramType) {
@@ -1176,6 +1111,22 @@ namespace {
1176
1111
}
1177
1112
}
1178
1113
1114
+ // Key paths require any captured values to be ConcurrentValue-conforming.
1115
+ if (auto keyPath = dyn_cast<KeyPathExpr>(expr)) {
1116
+ for (const auto &component : keyPath->getComponents ()) {
1117
+ auto indexExpr = component.getIndexExpr ();
1118
+ if (!indexExpr || !indexExpr->getType ())
1119
+ continue ;
1120
+
1121
+ if (ctx.LangOpts .EnableExperimentalConcurrentValueChecking &&
1122
+ !isConcurrentValueType (getDeclContext (), indexExpr->getType ())) {
1123
+ ctx.Diags .diagnose (
1124
+ component.getLoc (), diag::non_concurrent_keypath_capture,
1125
+ indexExpr->getType ());
1126
+ }
1127
+ }
1128
+ }
1129
+
1179
1130
// The children of #selector expressions are not evaluated, so we do not
1180
1131
// need to do isolation checking there. This is convenient because such
1181
1132
// expressions tend to violate restrictions on the use of instance
0 commit comments