Skip to content

Commit 9584883

Browse files
authored
Merge pull request #42240 from ahoppen/pr-5.7/complete-top-level-func-with-error-param
[5.7][CodeCompletion] Allow references to top-level functions with error parameters
2 parents 54a516b + 6488548 commit 9584883

File tree

3 files changed

+54
-33
lines changed

3 files changed

+54
-33
lines changed

lib/Sema/CSGen.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1346,7 +1346,11 @@ namespace {
13461346

13471347
// If declaration is invalid, let's turn it into a potential hole
13481348
// and keep generating constraints.
1349-
if (!knownType && E->getDecl()->isInvalid()) {
1349+
// For code completion, we still resolve the overload and replace error
1350+
// types inside the function decl with placeholders
1351+
// (in getTypeOfReference) so we can match non-error param types.
1352+
if (!knownType && E->getDecl()->isInvalid() &&
1353+
!CS.isForCodeCompletion()) {
13501354
auto *hole = CS.createTypeVariable(locator, TVO_CanBindToHole);
13511355
(void)CS.recordFix(AllowRefToInvalidDecl::create(CS, locator));
13521356
CS.setType(E, hole);

lib/Sema/ConstraintSystem.cpp

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,6 +1397,38 @@ AnyFunctionType *ConstraintSystem::adjustFunctionTypeForConcurrency(
13971397
fnType, decl, dc, numApplies, isMainDispatchQueue, GetClosureType{*this});
13981398
}
13991399

1400+
/// For every parameter in \p type that has an error type, replace that
1401+
/// parameter's type by a placeholder type, where \p value is the declaration
1402+
/// that declared \p type. This is useful for code completion so we can match
1403+
/// the types we do know instead of bailing out completely because \p type
1404+
/// contains an error type.
1405+
static Type replaceParamErrorTypeByPlaceholder(Type type, ValueDecl *value) {
1406+
if (!type->is<AnyFunctionType>() || !isa<AbstractFunctionDecl>(value)) {
1407+
return type;
1408+
}
1409+
auto funcType = type->castTo<AnyFunctionType>();
1410+
auto funcDecl = cast<AbstractFunctionDecl>(value);
1411+
1412+
auto declParams = funcDecl->getParameters();
1413+
auto typeParams = funcType->getParams();
1414+
assert(declParams->size() == typeParams.size());
1415+
SmallVector<AnyFunctionType::Param, 4> newParams;
1416+
newParams.reserve(declParams->size());
1417+
for (auto i : indices(typeParams)) {
1418+
AnyFunctionType::Param param = typeParams[i];
1419+
if (param.getPlainType()->is<ErrorType>()) {
1420+
auto paramDecl = declParams->get(i);
1421+
auto placeholder =
1422+
PlaceholderType::get(paramDecl->getASTContext(), paramDecl);
1423+
newParams.push_back(param.withType(placeholder));
1424+
} else {
1425+
newParams.push_back(param);
1426+
}
1427+
}
1428+
assert(newParams.size() == declParams->size());
1429+
return FunctionType::get(newParams, funcType->getResult());
1430+
}
1431+
14001432
std::pair<Type, Type>
14011433
ConstraintSystem::getTypeOfReference(ValueDecl *value,
14021434
FunctionRefKind functionRefKind,
@@ -1458,6 +1490,12 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
14581490
openedType->getAs<FunctionType>(),
14591491
locator);
14601492

1493+
if (isForCodeCompletion() && openedType->hasError()) {
1494+
// In code completion, replace error types by placeholder types so we can
1495+
// match the types we know instead of bailing out completely.
1496+
openedType = replaceParamErrorTypeByPlaceholder(openedType, value);
1497+
}
1498+
14611499
// If we opened up any type variables, record the replacements.
14621500
recordOpenedTypes(locator, replacements);
14631501

@@ -1950,38 +1988,6 @@ Type constraints::typeEraseOpenedExistentialReference(
19501988
});
19511989
}
19521990

1953-
/// For every parameter in \p type that has an error type, replace that
1954-
/// parameter's type by a placeholder type, where \p value is the declaration
1955-
/// that declared \p type. This is useful for code completion so we can match
1956-
/// the types we do know instead of bailing out completely because \p type
1957-
/// contains an error type.
1958-
static Type replaceParamErrorTypeByPlaceholder(Type type, ValueDecl *value) {
1959-
if (!type->is<AnyFunctionType>() || !isa<AbstractFunctionDecl>(value)) {
1960-
return type;
1961-
}
1962-
auto funcType = type->castTo<AnyFunctionType>();
1963-
auto funcDecl = cast<AbstractFunctionDecl>(value);
1964-
1965-
auto declParams = funcDecl->getParameters();
1966-
auto typeParams = funcType->getParams();
1967-
assert(declParams->size() == typeParams.size());
1968-
SmallVector<AnyFunctionType::Param, 4> newParams;
1969-
newParams.reserve(declParams->size());
1970-
for (auto i : indices(typeParams)) {
1971-
AnyFunctionType::Param param = typeParams[i];
1972-
if (param.getPlainType()->is<ErrorType>()) {
1973-
auto paramDecl = declParams->get(i);
1974-
auto placeholder =
1975-
PlaceholderType::get(paramDecl->getASTContext(), paramDecl);
1976-
newParams.push_back(param.withType(placeholder));
1977-
} else {
1978-
newParams.push_back(param);
1979-
}
1980-
}
1981-
assert(newParams.size() == declParams->size());
1982-
return FunctionType::get(newParams, funcType->getResult());
1983-
}
1984-
19851991
std::pair<Type, Type>
19861992
ConstraintSystem::getTypeOfMemberReference(
19871993
Type baseTy, ValueDecl *value, DeclContext *useDC,

test/IDE/complete_call_arg.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,3 +1371,14 @@ func testDynamicMemberSubscriptLookup() {
13711371
// DYNAMIC_MEMBER_SUBSCRIPT_LOOKUP-DAG: Decl[LocalVar]/Local/TypeRelation[Identical]: index[#Int#]; name=index
13721372
// DYNAMIC_MEMBER_SUBSCRIPT_LOOKUP-DAG: Pattern/CurrNominal/Flair[ArgLabels]: ['[']{#keyPath: KeyPath<Binding<MyStruct>, Value>#}[']'][#Value#]; name=keyPath:
13731373
// DYNAMIC_MEMBER_SUBSCRIPT_LOOKUP: End completions
1374+
1375+
func testTopLevelFuncWithErrorParam() {
1376+
enum A { case a }
1377+
func foo(x: A, b: Undefined) {}
1378+
1379+
foo(x: .#^TOP_LEVEL_FUNC_WITH_ERROR_PARAM^#)
1380+
// TOP_LEVEL_FUNC_WITH_ERROR_PARAM: Begin completions, 2 items
1381+
// TOP_LEVEL_FUNC_WITH_ERROR_PARAM-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: a[#A#]; name=a
1382+
// TOP_LEVEL_FUNC_WITH_ERROR_PARAM-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): A#})[#(into: inout Hasher) -> Void#]; name=hash(:)
1383+
// TOP_LEVEL_FUNC_WITH_ERROR_PARAM: End completions
1384+
}

0 commit comments

Comments
 (0)