Skip to content

Commit 31afb2c

Browse files
authored
Merge pull request #42160 from ahoppen/pr/complete-top-level-func-with-error-param
[CodeCompletion] Allow references to top-level functions with error parameters
2 parents 15839ff + ed58b68 commit 31afb2c

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
@@ -1383,8 +1383,19 @@ func testVarInitializedByCallingClosure() {
13831383
Bundle_main.vrl(forResource: "turnips", #^VAR_INITIALIZED_BY_CALLING_CLOSURE^#withExtension: "js")
13841384
}()
13851385
}
1386+
}
13861387

13871388
// VAR_INITIALIZED_BY_CALLING_CLOSURE: Begin completions, 1 items
13881389
// VAR_INITIALIZED_BY_CALLING_CLOSURE-DAG: Pattern/Local/Flair[ArgLabels]: {#withExtension: String?#}[#String?#];
13891390
// VAR_INITIALIZED_BY_CALLING_CLOSURE: End completions
1391+
1392+
func testTopLevelFuncWithErrorParam() {
1393+
enum A { case a }
1394+
func foo(x: A, b: Undefined) {}
1395+
1396+
foo(x: .#^TOP_LEVEL_FUNC_WITH_ERROR_PARAM^#)
1397+
// TOP_LEVEL_FUNC_WITH_ERROR_PARAM: Begin completions, 2 items
1398+
// TOP_LEVEL_FUNC_WITH_ERROR_PARAM-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: a[#A#]; name=a
1399+
// TOP_LEVEL_FUNC_WITH_ERROR_PARAM-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): A#})[#(into: inout Hasher) -> Void#]; name=hash(:)
1400+
// TOP_LEVEL_FUNC_WITH_ERROR_PARAM: End completions
13901401
}

0 commit comments

Comments
 (0)