Skip to content

Commit cc02728

Browse files
author
Nathan Hawes
authored
Merge pull request #15471 from nathawes/rdar38188989-code-completion-assertion-failure-in-getValueExprCompletions
[code-completion] Fix assertion failure in getValueExprCompletions
2 parents b5ade01 + d4bd291 commit cc02728

File tree

2 files changed

+79
-43
lines changed

2 files changed

+79
-43
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,6 +1594,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
15941594
std::vector<Type> ExpectedTypes;
15951595

15961596
bool HaveDot = false;
1597+
bool IsUnwrappedOptional = false;
15971598
SourceLoc DotLoc;
15981599
bool NeedLeadingDot = false;
15991600

@@ -1734,6 +1735,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
17341735
this->DotLoc = DotLoc;
17351736
}
17361737

1738+
void setIsUnwrappedOptional(bool value) {
1739+
IsUnwrappedOptional = value;
1740+
}
1741+
17371742
void setIsStaticMetatype(bool value) {
17381743
IsStaticMetatype = value;
17391744
}
@@ -3131,9 +3136,13 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
31313136
return false;
31323137
}
31333138

3134-
void getTupleExprCompletions(TupleType *ExprType) {
3139+
bool tryTupleExprCompletions(Type ExprType) {
3140+
auto *TT = ExprType->getAs<TupleType>();
3141+
if (!TT)
3142+
return false;
3143+
31353144
unsigned Index = 0;
3136-
for (auto TupleElt : ExprType->getElements()) {
3145+
for (auto TupleElt : TT->getElements()) {
31373146
CodeCompletionResultBuilder Builder(
31383147
Sink,
31393148
CodeCompletionResult::ResultKind::Pattern,
@@ -3152,6 +3161,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
31523161
addTypeAnnotation(Builder, TupleElt.getType());
31533162
Index++;
31543163
}
3164+
return true;
31553165
}
31563166

31573167
bool tryFunctionCallCompletions(Type ExprType, const ValueDecl *VD) {
@@ -3167,7 +3177,24 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
31673177
return false;
31683178
}
31693179

3170-
bool tryStdlibOptionalCompletions(Type ExprType, bool isIUO) {
3180+
bool tryModuleCompletions(Type ExprType) {
3181+
if (auto MT = ExprType->getAs<ModuleType>()) {
3182+
ModuleDecl *M = MT->getModule();
3183+
if (CurrDeclContext->getParentModule() != M) {
3184+
// Only use the cache if it is not the current module.
3185+
RequestedCachedResults = RequestedResultsTy::fromModule(M)
3186+
.needLeadingDot(needDot());
3187+
return true;
3188+
}
3189+
}
3190+
return false;
3191+
}
3192+
3193+
/// If the given ExprType is optional, this adds completions for the unwrapped
3194+
/// type.
3195+
///
3196+
/// \return true if the given type was Optional .
3197+
bool tryUnwrappedCompletions(Type ExprType, bool isIUO) {
31713198
// FIXME: consider types convertible to T?.
31723199

31733200
ExprType = ExprType->getRValueType();
@@ -3177,10 +3204,13 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
31773204
if (Type Unwrapped = ExprType->getOptionalObjectType()) {
31783205
lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext,
31793206
TypeResolver.get(), IncludeInstanceMembers);
3180-
} else {
3181-
llvm_unreachable("IUOs should always be optionals.");
3207+
return true;
31823208
}
3183-
} else if (Type Unwrapped = ExprType->getOptionalObjectType()) {
3209+
assert(IsUnwrappedOptional && "IUOs should be optional if not bound/forced");
3210+
return false;
3211+
}
3212+
3213+
if (Type Unwrapped = ExprType->getOptionalObjectType()) {
31843214
llvm::SaveAndRestore<bool> ChangeNeedOptionalUnwrap(NeedOptionalUnwrap,
31853215
true);
31863216
if (DotLoc.isValid()) {
@@ -3191,26 +3221,15 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
31913221
}
31923222
if (NumBytesToEraseForOptionalUnwrap <=
31933223
CodeCompletionResult::MaxNumBytesToErase) {
3194-
if (auto *TT = Unwrapped->getAs<TupleType>()) {
3195-
getTupleExprCompletions(TT);
3196-
} else {
3224+
if (!tryTupleExprCompletions(Unwrapped)) {
31973225
lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext,
31983226
TypeResolver.get(),
31993227
IncludeInstanceMembers);
32003228
}
32013229
}
3202-
} else {
3203-
return false;
3230+
return true;
32043231
}
3205-
3206-
// Ignore the members of Optional, like getLogicValue(), map(), and
3207-
// flatMap().
3208-
//
3209-
// These are not commonly used and cause noise and confusion when showing
3210-
// among the members of the underlying type. If someone really wants to
3211-
// use them they can write them directly.
3212-
3213-
return true;
3232+
return false;
32143233
}
32153234

32163235
void getValueExprCompletions(Type ExprType, ValueDecl *VD = nullptr) {
@@ -3231,30 +3250,20 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
32313250
}
32323251
}
32333252

3234-
bool Done = false;
3253+
// Handle special cases
3254+
bool isIUO = VD && VD->getAttrs()
3255+
.hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
32353256
if (tryFunctionCallCompletions(ExprType, VD))
3236-
Done = true;
3237-
if (auto MT = ExprType->getAs<ModuleType>()) {
3238-
ModuleDecl *M = MT->getModule();
3239-
if (CurrDeclContext->getParentModule() != M) {
3240-
// Only use the cache if it is not the current module.
3241-
RequestedCachedResults = RequestedResultsTy::fromModule(M)
3242-
.needLeadingDot(needDot());
3243-
Done = true;
3244-
}
3245-
}
3246-
if (auto *TT = ExprType->getAs<TupleType>()) {
3247-
getTupleExprCompletions(TT);
3248-
Done = true;
3249-
}
3250-
bool isIUO =
3251-
VD && VD->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
3252-
tryStdlibOptionalCompletions(ExprType, isIUO);
3253-
if (!Done) {
3254-
lookupVisibleMemberDecls(*this, ExprType, CurrDeclContext,
3255-
TypeResolver.get(),
3256-
IncludeInstanceMembers);
3257-
}
3257+
return;
3258+
if (tryModuleCompletions(ExprType))
3259+
return;
3260+
if (tryTupleExprCompletions(ExprType))
3261+
return;
3262+
// Don't check/return so we still add the members of Optional itself below
3263+
tryUnwrappedCompletions(ExprType, isIUO);
3264+
3265+
lookupVisibleMemberDecls(*this, ExprType, CurrDeclContext,
3266+
TypeResolver.get(), IncludeInstanceMembers);
32583267
}
32593268

32603269
template <typename T>
@@ -5294,6 +5303,9 @@ void CodeCompletionCallbacksImpl::doneParsing() {
52945303
if (isDynamicLookup(*ExprType))
52955304
Lookup.setIsDynamicLookup();
52965305

5306+
if (isa<BindOptionalExpr>(ParsedExpr) || isa<ForceValueExpr>(ParsedExpr))
5307+
Lookup.setIsUnwrappedOptional(true);
5308+
52975309
::CodeCompletionTypeContextAnalyzer TypeAnalyzer(CurDeclContext, ParsedExpr);
52985310
llvm::SmallVector<Type, 2> PossibleTypes;
52995311
if (TypeAnalyzer.Analyze(PossibleTypes)) {

test/IDE/complete_call_arg.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=EMPTY_OVERLOAD_1 | %FileCheck %s -check-prefix=EMPTY_OVERLOAD
4242
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=EMPTY_OVERLOAD_2 | %FileCheck %s -check-prefix=EMPTY_OVERLOAD
4343

44+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CALLARG_IUO | %FileCheck %s -check-prefix=CALLARG_IUO
45+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=BOUND_IUO | %FileCheck %s -check-prefix=MEMBEROF_IUO
46+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=FORCED_IUO | %FileCheck %s -check-prefix=MEMBEROF_IUO
47+
4448
var i1 = 1
4549
var i2 = 2
4650
var oi1 : Int?
@@ -383,3 +387,23 @@ _ = EmptyOverload(foo: #^EMPTY_OVERLOAD_2^#)
383387
// EMPTY_OVERLOAD-DAG: Decl[GlobalVar]/Local{{.*}}: i2[#Int#];
384388
// EMPTY_OVERLOAD-DAG: Decl[GlobalVar]/Local{{.*}}: i1[#Int#];
385389
// EMPTY_OVERLOAD: End completions
390+
391+
public func fopen() -> TestBoundGeneric1! { fatalError() }
392+
func other() {
393+
_ = fopen(#^CALLARG_IUO^#)
394+
// CALLARG_IUO-NOT: Begin completions
395+
// CALLARG_IUO-NOT: End completions
396+
}
397+
398+
class Foo { let x: Int }
399+
class Bar {
400+
var collectionView: Foo!
401+
402+
func foo() {
403+
self.collectionView? .#^BOUND_IUO^#x
404+
self.collectionView! .#^FORCED_IUO^#x
405+
}
406+
// MEMBEROF_IUO: Begin completions, 1 items
407+
// MEMBEROF_IUO: Decl[InstanceVar]/CurrNominal: x[#Int#]; name=x
408+
// MEMBEROF_IUO: End completions
409+
}

0 commit comments

Comments
 (0)