@@ -2516,47 +2516,15 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25162516 return Type ();
25172517 }
25182518
2519- void addVarDeclRef (const VarDecl *VD, DeclVisibilityKind Reason,
2520- DynamicLookupInfo dynamicLookupInfo) {
2521- if (!VD->hasName ())
2522- return ;
2523-
2524- const Identifier Name = VD->getName ();
2525- assert (!Name.empty () && " name should not be empty" );
2526-
2527- CommandWordsPairs Pairs;
2528- CodeCompletionResultBuilder Builder (
2529- Sink, CodeCompletionResult::ResultKind::Declaration,
2530- getSemanticContext (VD, Reason, dynamicLookupInfo), expectedTypeContext);
2531- Builder.setAssociatedDecl (VD);
2532- addLeadingDot (Builder);
2533- addValueBaseName (Builder, Name);
2534- setClangDeclKeywords (VD, Pairs, Builder);
2519+ void analyzeActorIsolation (
2520+ const ValueDecl *VD, Type T, bool &implicitlyAsync,
2521+ Optional<CodeCompletionResult::NotRecommendedReason> &NotRecommended) {
2522+ auto isolation = getActorIsolation (const_cast <ValueDecl *>(VD));
25352523
2536- Optional<CodeCompletionResult::NotRecommendedReason> NotRecommended;
2537- // "not recommended" in its own getter.
2538- if (Kind == LookupKind::ValueInDeclContext) {
2539- if (auto accessor = dyn_cast<AccessorDecl>(CurrDeclContext)) {
2540- if (accessor->getStorage () == VD && accessor->isGetter ())
2541- NotRecommended = CodeCompletionResult::NoReason;
2542- }
2543- }
2544-
2545- if (!VD->hasInterfaceType ())
2546- return ;
2547-
2548- // Add a type annotation.
2549- Type VarType = getTypeOfMember (VD, dynamicLookupInfo);
2550-
2551- bool implicitlyAsync = false ;
2552- auto isolation = getActorIsolation (const_cast <VarDecl *>(VD));
25532524 switch (isolation.getKind ()) {
25542525 case ActorIsolation::ActorInstance: {
25552526 if (IsCrossActorReference) {
25562527 implicitlyAsync = true ;
2557- if (!isSendableType (CurrDeclContext, VarType)) {
2558- NotRecommended = CodeCompletionResult::CrossActorReference;
2559- }
25602528 // TODO: 'NotRecommended' if this is a r-value reference.
25612529 }
25622530 break ;
@@ -2568,16 +2536,75 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25682536 case ActorIsolation::Unspecified:
25692537 case ActorIsolation::Independent:
25702538 case ActorIsolation::IndependentUnsafe:
2571- break ;
2539+ return ;
25722540 }
25732541
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+
2567+ void addVarDeclRef (const VarDecl *VD, DeclVisibilityKind Reason,
2568+ DynamicLookupInfo dynamicLookupInfo) {
2569+ if (!VD->hasName ())
2570+ return ;
2571+
2572+ const Identifier Name = VD->getName ();
2573+ assert (!Name.empty () && " name should not be empty" );
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);
25742589 if (!NotRecommended && implicitlyAsync && !CanCurrDeclContextHandleAsync) {
25752590 NotRecommended = CodeCompletionResult::InvalidContext;
25762591 }
25772592
2593+ CommandWordsPairs Pairs;
2594+ CodeCompletionResultBuilder Builder (
2595+ Sink, CodeCompletionResult::ResultKind::Declaration,
2596+ getSemanticContext (VD, Reason, dynamicLookupInfo), expectedTypeContext);
2597+ Builder.setAssociatedDecl (VD);
2598+ addLeadingDot (Builder);
2599+ addValueBaseName (Builder, Name);
2600+ setClangDeclKeywords (VD, Pairs, Builder);
2601+
25782602 if (NotRecommended)
25792603 Builder.setNotRecommended (*NotRecommended);
25802604
2605+ if (!VarType)
2606+ return ;
2607+
25812608 if (auto *PD = dyn_cast<ParamDecl>(VD)) {
25822609 if (Name != Ctx.Id_self && PD->isInOut ()) {
25832610 // It is useful to show inout for function parameters.
@@ -3013,38 +3040,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
30133040
30143041 Optional<CodeCompletionResult::NotRecommendedReason> NotRecommended;
30153042 bool implictlyAsync = false ;
3016- auto isolation = getActorIsolation (const_cast <FuncDecl *>(FD));
3017- switch (isolation.getKind ()) {
3018- case ActorIsolation::ActorInstance: {
3019- if (IsCrossActorReference) {
3020- implictlyAsync = true ;
3021-
3022- // Check if the result and the param types are all concurrent values.
3023- if (AFT) {
3024- if (!isSendableType (CurrDeclContext, AFT->getResult ())) {
3025- NotRecommended = CodeCompletionResult::CrossActorReference;
3026- } else {
3027- for (auto ¶m : AFT->getParams ()) {
3028- Type paramType = param.getPlainType ();
3029- if (!isSendableType (CurrDeclContext, paramType)) {
3030- NotRecommended = CodeCompletionResult::CrossActorReference;
3031- break ;
3032- }
3033- }
3034- }
3035- }
3036- }
3037- break ;
3038- }
3039- case ActorIsolation::GlobalActor:
3040- case ActorIsolation::GlobalActorUnsafe:
3041- // TODO: implement.
3042- break ;
3043- case ActorIsolation::Unspecified:
3044- case ActorIsolation::Independent:
3045- case ActorIsolation::IndependentUnsafe:
3046- break ;
3047- }
3043+ analyzeActorIsolation (FD, AFT, implictlyAsync, NotRecommended);
30483044
30493045 if (!NotRecommended && !IsImplicitlyCurriedInstanceMethod &&
30503046 ((AFT && AFT->isAsync ()) || implictlyAsync) &&
@@ -3300,36 +3296,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
33003296
33013297 Optional<CodeCompletionResult::NotRecommendedReason> NotRecommended;
33023298 bool implictlyAsync = false ;
3303- auto isolation = getActorIsolation (const_cast <SubscriptDecl *>(SD));
3304- switch (isolation.getKind ()) {
3305- case ActorIsolation::ActorInstance: {
3306- if (IsCrossActorReference) {
3307- implictlyAsync = true ;
3308-
3309- // Check if the result and the param types are all concurrent values.
3310- if (!isSendableType (CurrDeclContext, subscriptType->getResult ())) {
3311- NotRecommended = CodeCompletionResult::CrossActorReference;
3312- } else {
3313- for (auto ¶m : subscriptType->getParams ()) {
3314- Type paramType = param.getPlainType ();
3315- if (!isSendableType (CurrDeclContext, paramType))
3316- NotRecommended = CodeCompletionResult::CrossActorReference;
3317- }
3318- }
3319-
3320- // TODO: 'NotRecommended' if this is a r-value reference.
3321- }
3322- break ;
3323- }
3324- case ActorIsolation::GlobalActor:
3325- case ActorIsolation::GlobalActorUnsafe:
3326- // TODO: implement.
3327- break ;
3328- case ActorIsolation::Unspecified:
3329- case ActorIsolation::Independent:
3330- case ActorIsolation::IndependentUnsafe:
3331- break ;
3332- }
3299+ analyzeActorIsolation (SD, subscriptType, implictlyAsync, NotRecommended);
33333300
33343301 if (!NotRecommended && implictlyAsync && !CanCurrDeclContextHandleAsync) {
33353302 NotRecommended = CodeCompletionResult::InvalidContext;
0 commit comments