Skip to content

Commit 93d25c1

Browse files
author
Nathan Hawes
authored
Merge pull request #26889 from nathawes/r53959978-code-completion-hang-in-getContextSubstitutions-5.1
[5.1][IDE][Sema] Fix code completion unreachable/hang in TypeBase::getContextSubtitutions
2 parents e90298c + d1bedea commit 93d25c1

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

lib/AST/Type.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3481,7 +3481,9 @@ TypeBase::getContextSubstitutions(const DeclContext *dc,
34813481
continue;
34823482
}
34833483

3484-
llvm_unreachable("Bad base type");
3484+
// Assert and break to avoid hanging if we get an unexpected baseTy.
3485+
assert(0 && "Bad base type");
3486+
break;
34853487
}
34863488

34873489
while (n > 0) {

lib/Sema/LookupVisibleDecls.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,14 @@ static void lookupDeclsFromProtocolsBeingConformedTo(
410410
continue;
411411

412412
// Skip unsatisfied conditional conformances.
413-
if (Conformance->getConditionalRequirementsIfAvailable() &&
414-
!Module->conformsToProtocol(BaseTy, Proto))
415-
continue;
413+
// We can't check them if this type has an UnboundGenericType or if they
414+
// couldn't be computed, so assume they conform in such cases.
415+
if (!BaseTy->hasUnboundGenericType()) {
416+
if (auto res = Conformance->getConditionalRequirementsIfAvailable()) {
417+
if (!res->empty() && !Module->conformsToProtocol(BaseTy, Proto))
418+
continue;
419+
}
420+
}
416421

417422
DeclVisibilityKind ReasonForThisProtocol;
418423
if (Reason == DeclVisibilityKind::MemberOfCurrentNominal)
@@ -793,6 +798,7 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer {
793798
// don't substitute either.
794799
bool shouldSubst = (Reason != DeclVisibilityKind::DynamicLookup &&
795800
!BaseTy->isAnyObject() && !BaseTy->hasTypeVariable() &&
801+
!BaseTy->hasUnboundGenericType() &&
796802
(BaseTy->getNominalOrBoundGenericNominal() ||
797803
BaseTy->is<ArchetypeType>()) &&
798804
VD->getDeclContext()->isTypeContext());

test/IDE/complete_type.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,8 @@
397397
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERIC_ARGS_LOCAL_RETURN | %FileCheck %s -check-prefix=WITH_GLOBAL_TYPES
398398

399399
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_DOT_1 | %FileCheck %s -check-prefix=PROTOCOL_DOT_1
400+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNBOUND_DOT | %FileCheck %s -check-prefix=UNBOUND_DOT
401+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNBOUND_DOT_2 | %FileCheck %s -check-prefix=UNBOUND_DOT_2
400402

401403
//===--- Helper types that are used in this test
402404

@@ -1093,3 +1095,37 @@ func testProtocol() {
10931095
// PROTOCOL_DOT_1-DAG: Keyword/None: Type[#FooProtocol.Type#]; name=Type
10941096
// PROTOCOL_DOT_1: End completions
10951097
}
1098+
1099+
//===---
1100+
//===--- Test we can complete unbound generic types
1101+
//===---
1102+
1103+
public final class Task<Success> {
1104+
public enum Inner {
1105+
public typealias Failure = Int
1106+
case success(Success)
1107+
case failure(Failure)
1108+
}
1109+
}
1110+
extension Task.Inner {
1111+
public init(left error: Failure) {
1112+
fatalError()
1113+
}
1114+
}
1115+
extension Task.Inner.#^UNBOUND_DOT^# {}
1116+
func testUnbound(x: Task.Inner.#^UNBOUND_DOT^#) {}
1117+
// UNBOUND_DOT: Begin completions
1118+
// UNBOUND_DOT-DAG: Decl[TypeAlias]/CurrNominal: Failure[#Int#]; name=Failure
1119+
// UNBOUND_DOT-DAG: Keyword/None: Type[#Task.Inner.Type#]; name=Type
1120+
// UNBOUND_DOT: End completions
1121+
1122+
1123+
protocol MyProtocol {}
1124+
struct OuterStruct<U> {
1125+
class Inner<V>: MyProtocol {}
1126+
}
1127+
1128+
func testUnbound2(x: OuterStruct<Int>.Inner.#^UNBOUND_DOT_2^#) {}
1129+
// UNBOUND_DOT_2: Begin completions
1130+
// UNBOUND_DOT_2-DAG: Keyword/None: Type[#OuterStruct<Int>.Inner.Type#]; name=Type
1131+
// UNBOUND_DOT_2: End completions

0 commit comments

Comments
 (0)