Skip to content

Commit 1eadffc

Browse files
committed
[CodeCompletion] Don’t crash when completing in a parameter position that only constraints one of two primary associated protocol types
When completing, we call `getExistentialType` on the contextual type to get a nice and concise description of the contextual parameter’s type that doesn’t contain archetypes and which we can also serialize into a USR so we are able to calculate type relations for code completion results from the code completion cache. When completing in a position that has a contextual type which only constrains one of two primary associated protocol types, this fails because `getExistentialType` (which calls `getDependentUpperBounds`) tries to form a `ParameterizedProtocolType`, which fails since not all primary associated types have been constrained. AFAICT the fix here is to just fall back to the default behavior of returning the plain protocol type instead of `abort`ing. rdar://108835466
1 parent 7260c3b commit 1eadffc

File tree

2 files changed

+25
-10
lines changed

2 files changed

+25
-10
lines changed

lib/AST/GenericSignature.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -724,16 +724,16 @@ Type GenericSignatureImpl::getDependentUpperBounds(Type type) const {
724724
argTypes.push_back(reducedType);
725725
}
726726

727-
// We should have either constrained all primary associated types,
728-
// or none of them.
729-
if (!argTypes.empty()) {
730-
if (argTypes.size() != primaryAssocTypes.size()) {
731-
llvm::errs() << "Not all primary associated types constrained?\n";
732-
llvm::errs() << "Interface type: " << type << "\n";
733-
llvm::errs() << GenericSignature(this) << "\n";
734-
abort();
735-
}
736-
727+
// If we have constrained all primary associated types, create a
728+
// parameterized protocol type. During code completion, we might call
729+
// `getExistentialType` (which calls this method) on a generic parameter
730+
// that doesn't have all parameters specified, e.g. to get a consise
731+
// description of the parameter type to the following function.
732+
//
733+
// func foo<P: Publisher>(p: P) where P.Failure == Never
734+
//
735+
// In that case just add the base type in the default branch below.
736+
if (argTypes.size() == primaryAssocTypes.size()) {
737737
types.push_back(ParameterizedProtocolType::get(ctx, baseType, argTypes));
738738
continue;
739739
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t
3+
4+
protocol Publisher<Output, Failure> {
5+
associatedtype Output
6+
associatedtype Failure
7+
}
8+
9+
func foo<P: Publisher>(_ publisher: P) where P.Failure == Never
10+
11+
func test() {
12+
foo(#^COMPLETE^#)
13+
// Make sure we don’t crash
14+
// COMPLETE: Begin completions
15+
}

0 commit comments

Comments
 (0)