@@ -1761,7 +1761,7 @@ static bool hasTrivialTrailingClosure(const FuncDecl *FD,
17611761}
17621762
17631763// / Returns \c true if \p DC can handles async call.
1764- static bool canDeclContextHandlesAsync (const DeclContext *DC) {
1764+ static bool canDeclContextHandleAsync (const DeclContext *DC) {
17651765 if (auto *func = dyn_cast<AbstractFunctionDecl>(DC))
17661766 return func->isAsyncContext ();
17671767
@@ -1840,6 +1840,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18401840 // / Expected types of the code completion expression.
18411841 ExpectedTypeContext expectedTypeContext;
18421842
1843+ bool CanCurrDeclContextHandleAsync = false ;
18431844 bool HaveDot = false ;
18441845 bool IsUnwrappedOptional = false ;
18451846 SourceLoc DotLoc;
@@ -1855,6 +1856,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18551856 bool IsSwiftKeyPathExpr = false ;
18561857 bool IsAfterSwiftKeyPathRoot = false ;
18571858 bool IsDynamicLookup = false ;
1859+ bool IsCrossActorReference = false ;
18581860 bool PreferFunctionReferencesToCalls = false ;
18591861 bool HaveLeadingSpace = false ;
18601862
@@ -1987,6 +1989,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19871989 CurrentMethod = CurrDeclContext->getInnermostMethodContext ();
19881990 if (auto *FD = dyn_cast_or_null<FuncDecl>(CurrentMethod))
19891991 InsideStaticMethod = FD->isStatic ();
1992+ CanCurrDeclContextHandleAsync = canDeclContextHandleAsync (CurrDeclContext);
19901993 }
19911994 }
19921995
@@ -2513,6 +2516,54 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25132516 return Type ();
25142517 }
25152518
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+
25162567 void addVarDeclRef (const VarDecl *VD, DeclVisibilityKind Reason,
25172568 DynamicLookupInfo dynamicLookupInfo) {
25182569 if (!VD->hasName ())
@@ -2521,6 +2572,24 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25212572 const Identifier Name = VD->getName ();
25222573 assert (!Name.empty () && " name should not be empty" );
25232574
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+
25242593 CommandWordsPairs Pairs;
25252594 CodeCompletionResultBuilder Builder (
25262595 Sink, CodeCompletionResult::ResultKind::Declaration,
@@ -2530,19 +2599,12 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25302599 addValueBaseName (Builder, Name);
25312600 setClangDeclKeywords (VD, Pairs, Builder);
25322601
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);
25402604
2541- if (!VD-> hasInterfaceType () )
2605+ if (!VarType )
25422606 return ;
25432607
2544- // Add a type annotation.
2545- Type VarType = getTypeOfMember (VD, dynamicLookupInfo);
25462608 if (auto *PD = dyn_cast<ParamDecl>(VD)) {
25472609 if (Name != Ctx.Id_self && PD->isInOut ()) {
25482610 // It is useful to show inout for function parameters.
@@ -2566,6 +2628,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25662628 else
25672629 addTypeAnnotation (Builder, VarType, genericSig);
25682630
2631+ if (implicitlyAsync)
2632+ Builder.addAnnotatedAsync ();
2633+
25692634 if (isUnresolvedMemberIdealType (VarType))
25702635 Builder.setSemanticContext (SemanticContextKind::ExpressionSpecific);
25712636 }
@@ -2686,11 +2751,12 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
26862751
26872752 static void addEffectsSpecifiers (CodeCompletionResultBuilder &Builder,
26882753 const AnyFunctionType *AFT,
2689- const AbstractFunctionDecl *AFD) {
2754+ const AbstractFunctionDecl *AFD,
2755+ bool forceAsync = false ) {
26902756 assert (AFT != nullptr );
26912757
26922758 // 'async'.
2693- if ((AFD && AFD->hasAsync ()) || AFT->isAsync ())
2759+ if (forceAsync || (AFD && AFD->hasAsync ()) || AFT->isAsync ())
26942760 Builder.addAnnotatedAsync ();
26952761
26962762 // 'throws' or 'rethrows'.
@@ -2861,8 +2927,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28612927 else
28622928 addTypeAnnotation (Builder, AFT->getResult (), genericSig);
28632929
2864- if (AFT->isAsync () &&
2865- !canDeclContextHandlesAsync (CurrDeclContext)) {
2930+ if (AFT->isAsync () && !CanCurrDeclContextHandleAsync) {
28662931 Builder.setNotRecommended (
28672932 CodeCompletionResult::NotRecommendedReason::InvalidContext);
28682933 }
@@ -2973,6 +3038,16 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
29733038 if (AFT && !IsImplicitlyCurriedInstanceMethod)
29743039 trivialTrailingClosure = hasTrivialTrailingClosure (FD, AFT);
29753040
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+
29763051 // Add the method, possibly including any default arguments.
29773052 auto addMethodImpl = [&](bool includeDefaultArgs = true ,
29783053 bool trivialTrailingClosure = false ) {
@@ -2983,6 +3058,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
29833058 expectedTypeContext);
29843059 setClangDeclKeywords (FD, Pairs, Builder);
29853060 Builder.setAssociatedDecl (FD);
3061+
3062+ if (NotRecommended)
3063+ Builder.setNotRecommended (*NotRecommended);
3064+
29863065 addLeadingDot (Builder);
29873066 addValueBaseName (Builder, Name);
29883067 if (IsDynamicLookup)
@@ -3004,14 +3083,14 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
30043083 Builder.addRightParen ();
30053084 } else if (trivialTrailingClosure) {
30063085 Builder.addBraceStmtWithCursor (" { code }" );
3007- addEffectsSpecifiers (Builder, AFT, FD);
3086+ addEffectsSpecifiers (Builder, AFT, FD, implictlyAsync );
30083087 } else {
30093088 Builder.addLeftParen ();
30103089 addCallArgumentPatterns (Builder, AFT, FD->getParameters (),
30113090 FD->getGenericSignatureOfContext (),
30123091 includeDefaultArgs);
30133092 Builder.addRightParen ();
3014- addEffectsSpecifiers (Builder, AFT, FD);
3093+ addEffectsSpecifiers (Builder, AFT, FD, implictlyAsync );
30153094 }
30163095
30173096 // Build type annotation.
@@ -3076,13 +3155,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
30763155 ResultType->isVoid ()) {
30773156 Builder.setExpectedTypeRelation (CodeCompletionResult::Invalid);
30783157 }
3079-
3080- if (!IsImplicitlyCurriedInstanceMethod &&
3081- AFT->isAsync () &&
3082- !canDeclContextHandlesAsync (CurrDeclContext)) {
3083- Builder.setNotRecommended (
3084- CodeCompletionResult::NotRecommendedReason::InvalidContext);
3085- }
30863158 };
30873159
30883160 if (!AFT || IsImplicitlyCurriedInstanceMethod) {
@@ -3170,8 +3242,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
31703242 addTypeAnnotation (Builder, *Result, CD->getGenericSignatureOfContext ());
31713243 }
31723244
3173- if (ConstructorType->isAsync () &&
3174- !canDeclContextHandlesAsync (CurrDeclContext)) {
3245+ if (ConstructorType->isAsync () && !CanCurrDeclContextHandleAsync) {
31753246 Builder.setNotRecommended (
31763247 CodeCompletionResult::NotRecommendedReason::InvalidContext);
31773248 }
@@ -3223,13 +3294,24 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
32233294 if (!subscriptType)
32243295 return ;
32253296
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+
32263305 CommandWordsPairs Pairs;
32273306 CodeCompletionResultBuilder Builder (
32283307 Sink, CodeCompletionResult::ResultKind::Declaration,
32293308 getSemanticContext (SD, Reason, dynamicLookupInfo), expectedTypeContext);
32303309 Builder.setAssociatedDecl (SD);
32313310 setClangDeclKeywords (SD, Pairs, Builder);
32323311
3312+ if (NotRecommended)
3313+ Builder.setNotRecommended (*NotRecommended);
3314+
32333315 // '\TyName#^TOKEN^#' requires leading dot.
32343316 if (!HaveDot && IsAfterSwiftKeyPathRoot)
32353317 Builder.addLeadingDot ();
@@ -3251,6 +3333,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
32513333 // Optional<T> type.
32523334 resultTy = OptionalType::get (resultTy);
32533335 }
3336+
3337+ if (implictlyAsync)
3338+ Builder.addAnnotatedAsync ();
3339+
32543340 addTypeAnnotation (Builder, resultTy, SD->getGenericSignatureOfContext ());
32553341 }
32563342
@@ -3916,6 +4002,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
39164002 if (ExprType->isAnyExistentialType ())
39174003 ExprType = OpenedArchetypeType::getAny (ExprType);
39184004
4005+ if (!IsSelfRefExpr && !IsSuperRefExpr && ExprType->getAnyNominal () &&
4006+ ExprType->getAnyNominal ()->isActor ()) {
4007+ IsCrossActorReference = true ;
4008+ }
4009+
39194010 if (WasOptional)
39204011 ExprType = OptionalType::get (ExprType);
39214012
0 commit comments