@@ -1761,7 +1761,7 @@ static bool hasTrivialTrailingClosure(const FuncDecl *FD,
1761
1761
}
1762
1762
1763
1763
// / Returns \c true if \p DC can handles async call.
1764
- static bool canDeclContextHandlesAsync (const DeclContext *DC) {
1764
+ static bool canDeclContextHandleAsync (const DeclContext *DC) {
1765
1765
if (auto *func = dyn_cast<AbstractFunctionDecl>(DC))
1766
1766
return func->isAsyncContext ();
1767
1767
@@ -1840,6 +1840,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
1840
1840
// / Expected types of the code completion expression.
1841
1841
ExpectedTypeContext expectedTypeContext;
1842
1842
1843
+ bool CanCurrDeclContextHandleAsync = false ;
1843
1844
bool HaveDot = false ;
1844
1845
bool IsUnwrappedOptional = false ;
1845
1846
SourceLoc DotLoc;
@@ -1855,6 +1856,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
1855
1856
bool IsSwiftKeyPathExpr = false ;
1856
1857
bool IsAfterSwiftKeyPathRoot = false ;
1857
1858
bool IsDynamicLookup = false ;
1859
+ bool IsCrossActorReference = false ;
1858
1860
bool PreferFunctionReferencesToCalls = false ;
1859
1861
bool HaveLeadingSpace = false ;
1860
1862
@@ -1987,6 +1989,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
1987
1989
CurrentMethod = CurrDeclContext->getInnermostMethodContext ();
1988
1990
if (auto *FD = dyn_cast_or_null<FuncDecl>(CurrentMethod))
1989
1991
InsideStaticMethod = FD->isStatic ();
1992
+ CanCurrDeclContextHandleAsync = canDeclContextHandleAsync (CurrDeclContext);
1990
1993
}
1991
1994
}
1992
1995
@@ -2513,6 +2516,54 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2513
2516
return Type ();
2514
2517
}
2515
2518
2519
+ void analyzeActorIsolation (
2520
+ const ValueDecl *VD, Type T, bool &implicitlyAsync,
2521
+ Optional<CodeCompletionResult::NotRecommendedReason> &NotRecommended) {
2522
+ auto isolation = getActorIsolation (const_cast <ValueDecl *>(VD));
2523
+
2524
+ switch (isolation.getKind ()) {
2525
+ case ActorIsolation::ActorInstance: {
2526
+ if (IsCrossActorReference) {
2527
+ implicitlyAsync = true ;
2528
+ // TODO: 'NotRecommended' if this is a r-value reference.
2529
+ }
2530
+ break ;
2531
+ }
2532
+ case ActorIsolation::GlobalActor:
2533
+ case ActorIsolation::GlobalActorUnsafe:
2534
+ // TODO: Implement.
2535
+ break ;
2536
+ case ActorIsolation::Unspecified:
2537
+ case ActorIsolation::Independent:
2538
+ case ActorIsolation::IndependentUnsafe:
2539
+ return ;
2540
+ }
2541
+
2542
+ // If the reference is 'async', all types must be 'Sendable'.
2543
+ if (implicitlyAsync && T) {
2544
+ if (isa<VarDecl>(VD)) {
2545
+ if (!isSendableType (CurrDeclContext, T)) {
2546
+ NotRecommended = CodeCompletionResult::CrossActorReference;
2547
+ }
2548
+ } else {
2549
+ assert (isa<FuncDecl>(VD) || isa<SubscriptDecl>(VD));
2550
+ // Check if the result and the param types are all 'Sendable'.
2551
+ auto *AFT = T->castTo <AnyFunctionType>();
2552
+ if (!isSendableType (CurrDeclContext, AFT->getResult ())) {
2553
+ NotRecommended = CodeCompletionResult::CrossActorReference;
2554
+ } else {
2555
+ for (auto ¶m : AFT->getParams ()) {
2556
+ Type paramType = param.getPlainType ();
2557
+ if (!isSendableType (CurrDeclContext, paramType)) {
2558
+ NotRecommended = CodeCompletionResult::CrossActorReference;
2559
+ break ;
2560
+ }
2561
+ }
2562
+ }
2563
+ }
2564
+ }
2565
+ }
2566
+
2516
2567
void addVarDeclRef (const VarDecl *VD, DeclVisibilityKind Reason,
2517
2568
DynamicLookupInfo dynamicLookupInfo) {
2518
2569
if (!VD->hasName ())
@@ -2521,6 +2572,24 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2521
2572
const Identifier Name = VD->getName ();
2522
2573
assert (!Name.empty () && " name should not be empty" );
2523
2574
2575
+ Type VarType;
2576
+ if (VD->hasInterfaceType ())
2577
+ VarType = getTypeOfMember (VD, dynamicLookupInfo);
2578
+
2579
+ Optional<CodeCompletionResult::NotRecommendedReason> NotRecommended;
2580
+ // "not recommended" in its own getter.
2581
+ if (Kind == LookupKind::ValueInDeclContext) {
2582
+ if (auto accessor = dyn_cast<AccessorDecl>(CurrDeclContext)) {
2583
+ if (accessor->getStorage () == VD && accessor->isGetter ())
2584
+ NotRecommended = CodeCompletionResult::NoReason;
2585
+ }
2586
+ }
2587
+ bool implicitlyAsync = false ;
2588
+ analyzeActorIsolation (VD, VarType, implicitlyAsync, NotRecommended);
2589
+ if (!NotRecommended && implicitlyAsync && !CanCurrDeclContextHandleAsync) {
2590
+ NotRecommended = CodeCompletionResult::InvalidContext;
2591
+ }
2592
+
2524
2593
CommandWordsPairs Pairs;
2525
2594
CodeCompletionResultBuilder Builder (
2526
2595
Sink, CodeCompletionResult::ResultKind::Declaration,
@@ -2530,19 +2599,12 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2530
2599
addValueBaseName (Builder, Name);
2531
2600
setClangDeclKeywords (VD, Pairs, Builder);
2532
2601
2533
- // "not recommended" in its own getter.
2534
- if (Kind == LookupKind::ValueInDeclContext) {
2535
- if (auto accessor = dyn_cast<AccessorDecl>(CurrDeclContext)) {
2536
- if (accessor->getStorage () == VD && accessor->isGetter ())
2537
- Builder.setNotRecommended (CodeCompletionResult::NoReason);
2538
- }
2539
- }
2602
+ if (NotRecommended)
2603
+ Builder.setNotRecommended (*NotRecommended);
2540
2604
2541
- if (!VD-> hasInterfaceType () )
2605
+ if (!VarType )
2542
2606
return ;
2543
2607
2544
- // Add a type annotation.
2545
- Type VarType = getTypeOfMember (VD, dynamicLookupInfo);
2546
2608
if (auto *PD = dyn_cast<ParamDecl>(VD)) {
2547
2609
if (Name != Ctx.Id_self && PD->isInOut ()) {
2548
2610
// It is useful to show inout for function parameters.
@@ -2566,6 +2628,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2566
2628
else
2567
2629
addTypeAnnotation (Builder, VarType, genericSig);
2568
2630
2631
+ if (implicitlyAsync)
2632
+ Builder.addAnnotatedAsync ();
2633
+
2569
2634
if (isUnresolvedMemberIdealType (VarType))
2570
2635
Builder.setSemanticContext (SemanticContextKind::ExpressionSpecific);
2571
2636
}
@@ -2686,11 +2751,12 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2686
2751
2687
2752
static void addEffectsSpecifiers (CodeCompletionResultBuilder &Builder,
2688
2753
const AnyFunctionType *AFT,
2689
- const AbstractFunctionDecl *AFD) {
2754
+ const AbstractFunctionDecl *AFD,
2755
+ bool forceAsync = false ) {
2690
2756
assert (AFT != nullptr );
2691
2757
2692
2758
// 'async'.
2693
- if ((AFD && AFD->hasAsync ()) || AFT->isAsync ())
2759
+ if (forceAsync || (AFD && AFD->hasAsync ()) || AFT->isAsync ())
2694
2760
Builder.addAnnotatedAsync ();
2695
2761
2696
2762
// 'throws' or 'rethrows'.
@@ -2861,8 +2927,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2861
2927
else
2862
2928
addTypeAnnotation (Builder, AFT->getResult (), genericSig);
2863
2929
2864
- if (AFT->isAsync () &&
2865
- !canDeclContextHandlesAsync (CurrDeclContext)) {
2930
+ if (AFT->isAsync () && !CanCurrDeclContextHandleAsync) {
2866
2931
Builder.setNotRecommended (
2867
2932
CodeCompletionResult::NotRecommendedReason::InvalidContext);
2868
2933
}
@@ -2973,6 +3038,16 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2973
3038
if (AFT && !IsImplicitlyCurriedInstanceMethod)
2974
3039
trivialTrailingClosure = hasTrivialTrailingClosure (FD, AFT);
2975
3040
3041
+ Optional<CodeCompletionResult::NotRecommendedReason> NotRecommended;
3042
+ bool implictlyAsync = false ;
3043
+ analyzeActorIsolation (FD, AFT, implictlyAsync, NotRecommended);
3044
+
3045
+ if (!NotRecommended && !IsImplicitlyCurriedInstanceMethod &&
3046
+ ((AFT && AFT->isAsync ()) || implictlyAsync) &&
3047
+ !CanCurrDeclContextHandleAsync) {
3048
+ NotRecommended = CodeCompletionResult::InvalidContext;
3049
+ }
3050
+
2976
3051
// Add the method, possibly including any default arguments.
2977
3052
auto addMethodImpl = [&](bool includeDefaultArgs = true ,
2978
3053
bool trivialTrailingClosure = false ) {
@@ -2983,6 +3058,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2983
3058
expectedTypeContext);
2984
3059
setClangDeclKeywords (FD, Pairs, Builder);
2985
3060
Builder.setAssociatedDecl (FD);
3061
+
3062
+ if (NotRecommended)
3063
+ Builder.setNotRecommended (*NotRecommended);
3064
+
2986
3065
addLeadingDot (Builder);
2987
3066
addValueBaseName (Builder, Name);
2988
3067
if (IsDynamicLookup)
@@ -3004,14 +3083,14 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3004
3083
Builder.addRightParen ();
3005
3084
} else if (trivialTrailingClosure) {
3006
3085
Builder.addBraceStmtWithCursor (" { code }" );
3007
- addEffectsSpecifiers (Builder, AFT, FD);
3086
+ addEffectsSpecifiers (Builder, AFT, FD, implictlyAsync );
3008
3087
} else {
3009
3088
Builder.addLeftParen ();
3010
3089
addCallArgumentPatterns (Builder, AFT, FD->getParameters (),
3011
3090
FD->getGenericSignatureOfContext (),
3012
3091
includeDefaultArgs);
3013
3092
Builder.addRightParen ();
3014
- addEffectsSpecifiers (Builder, AFT, FD);
3093
+ addEffectsSpecifiers (Builder, AFT, FD, implictlyAsync );
3015
3094
}
3016
3095
3017
3096
// Build type annotation.
@@ -3076,13 +3155,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3076
3155
ResultType->isVoid ()) {
3077
3156
Builder.setExpectedTypeRelation (CodeCompletionResult::Invalid);
3078
3157
}
3079
-
3080
- if (!IsImplicitlyCurriedInstanceMethod &&
3081
- AFT->isAsync () &&
3082
- !canDeclContextHandlesAsync (CurrDeclContext)) {
3083
- Builder.setNotRecommended (
3084
- CodeCompletionResult::NotRecommendedReason::InvalidContext);
3085
- }
3086
3158
};
3087
3159
3088
3160
if (!AFT || IsImplicitlyCurriedInstanceMethod) {
@@ -3170,8 +3242,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3170
3242
addTypeAnnotation (Builder, *Result, CD->getGenericSignatureOfContext ());
3171
3243
}
3172
3244
3173
- if (ConstructorType->isAsync () &&
3174
- !canDeclContextHandlesAsync (CurrDeclContext)) {
3245
+ if (ConstructorType->isAsync () && !CanCurrDeclContextHandleAsync) {
3175
3246
Builder.setNotRecommended (
3176
3247
CodeCompletionResult::NotRecommendedReason::InvalidContext);
3177
3248
}
@@ -3223,13 +3294,24 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3223
3294
if (!subscriptType)
3224
3295
return ;
3225
3296
3297
+ Optional<CodeCompletionResult::NotRecommendedReason> NotRecommended;
3298
+ bool implictlyAsync = false ;
3299
+ analyzeActorIsolation (SD, subscriptType, implictlyAsync, NotRecommended);
3300
+
3301
+ if (!NotRecommended && implictlyAsync && !CanCurrDeclContextHandleAsync) {
3302
+ NotRecommended = CodeCompletionResult::InvalidContext;
3303
+ }
3304
+
3226
3305
CommandWordsPairs Pairs;
3227
3306
CodeCompletionResultBuilder Builder (
3228
3307
Sink, CodeCompletionResult::ResultKind::Declaration,
3229
3308
getSemanticContext (SD, Reason, dynamicLookupInfo), expectedTypeContext);
3230
3309
Builder.setAssociatedDecl (SD);
3231
3310
setClangDeclKeywords (SD, Pairs, Builder);
3232
3311
3312
+ if (NotRecommended)
3313
+ Builder.setNotRecommended (*NotRecommended);
3314
+
3233
3315
// '\TyName#^TOKEN^#' requires leading dot.
3234
3316
if (!HaveDot && IsAfterSwiftKeyPathRoot)
3235
3317
Builder.addLeadingDot ();
@@ -3251,6 +3333,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3251
3333
// Optional<T> type.
3252
3334
resultTy = OptionalType::get (resultTy);
3253
3335
}
3336
+
3337
+ if (implictlyAsync)
3338
+ Builder.addAnnotatedAsync ();
3339
+
3254
3340
addTypeAnnotation (Builder, resultTy, SD->getGenericSignatureOfContext ());
3255
3341
}
3256
3342
@@ -3916,6 +4002,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3916
4002
if (ExprType->isAnyExistentialType ())
3917
4003
ExprType = OpenedArchetypeType::getAny (ExprType);
3918
4004
4005
+ if (!IsSelfRefExpr && !IsSuperRefExpr && ExprType->getAnyNominal () &&
4006
+ ExprType->getAnyNominal ()->isActor ()) {
4007
+ IsCrossActorReference = true ;
4008
+ }
4009
+
3919
4010
if (WasOptional)
3920
4011
ExprType = OptionalType::get (ExprType);
3921
4012
0 commit comments