Skip to content

Commit a96c40d

Browse files
authored
Merge pull request #28783 from xedin/cut-down-fn-retypecheck-in-visit-applye-expr
[CSDiag] Remove obsolete function diagnostics from `visitApplyExpr`
2 parents 065bd1e + 2db14a9 commit a96c40d

File tree

4 files changed

+45
-232
lines changed

4 files changed

+45
-232
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 0 additions & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,6 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
201201
ContextualTypePurpose CTP,
202202
Type suggestedType = Type());
203203

204-
/// Attempt to produce a diagnostic for a mismatch between a call's
205-
/// type and its assumed contextual type.
206-
bool diagnoseCallContextualConversionErrors(ApplyExpr *callEpxr,
207-
Type contextualType,
208-
ContextualTypePurpose CTP);
209-
210204
bool diagnoseImplicitSelfErrors(Expr *fnExpr, Expr *argExpr,
211205
CalleeCandidateInfo &CCI,
212206
ArrayRef<Identifier> argLabels);
@@ -1671,36 +1665,6 @@ namespace {
16711665
};
16721666
} // end anonymous namespace
16731667

1674-
/// Check if there failure associated with expression is related
1675-
/// to given contextual type.
1676-
bool FailureDiagnosis::diagnoseCallContextualConversionErrors(
1677-
ApplyExpr *callExpr, Type contextualType, ContextualTypePurpose CTP) {
1678-
if (!contextualType || contextualType->hasUnresolvedType())
1679-
return false;
1680-
1681-
auto typeCheckExpr = [&](Expr *expr, DeclContext *DC,
1682-
SmallPtrSetImpl<TypeBase *> &types) {
1683-
getPossibleTypesOfExpressionWithoutApplying(
1684-
expr, DC, types, FreeTypeVariableBinding::Disallow);
1685-
};
1686-
1687-
// First let's type-check expression without contextual type, and
1688-
// see if that's going to produce a type, if so, let's type-check
1689-
// again, this time using given contextual type.
1690-
SmallPtrSet<TypeBase *, 4> withoutContextual;
1691-
typeCheckExpr(callExpr, CS.DC, withoutContextual);
1692-
1693-
// If there are no types returned, it means that problem was
1694-
// nothing to do with contextual information, probably parameter/argument
1695-
// mismatch.
1696-
if (withoutContextual.empty())
1697-
return false;
1698-
1699-
Type exprType = withoutContextual.size() == 1 ? *withoutContextual.begin() : Type();
1700-
return diagnoseContextualConversionError(callExpr, contextualType, CTP,
1701-
exprType);
1702-
}
1703-
17041668
// Check if there is a structural problem in the function expression
17051669
// by performing type checking with the option to allow unresolved
17061670
// type variables. If that is going to produce a function type with
@@ -1731,45 +1695,8 @@ static bool shouldTypeCheckFunctionExpr(FailureDiagnosis &FD, DeclContext *DC,
17311695
return true;
17321696
}
17331697

1734-
// Check if any candidate of the overload set can accept a specified
1735-
// number of arguments, regardless of parameter type or label information.
1736-
static bool isViableOverloadSet(const CalleeCandidateInfo &CCI,
1737-
size_t numArgs) {
1738-
for (unsigned i = 0; i < CCI.size(); ++i) {
1739-
auto &&cand = CCI[i];
1740-
auto funcDecl = dyn_cast_or_null<AbstractFunctionDecl>(cand.getDecl());
1741-
1742-
// If we don't have a func decl or we haven't resolved its parameters,
1743-
// continue. The latter case can occur with `type(of:)`, which is introduced
1744-
// as a type variable.
1745-
if (!funcDecl || !cand.hasParameters())
1746-
continue;
1747-
1748-
auto params = cand.getParameters();
1749-
bool hasVariadicParameter = false;
1750-
auto pairMatcher = [&](unsigned argIdx, unsigned paramIdx) {
1751-
hasVariadicParameter |= params[paramIdx].isVariadic();
1752-
return true;
1753-
};
1754-
1755-
auto paramInfo = cand.getParameterListInfo(params);
1756-
InputMatcher IM(params, paramInfo);
1757-
auto result = IM.match(numArgs, pairMatcher);
1758-
if (result == InputMatcher::IM_Succeeded)
1759-
return true;
1760-
if (result == InputMatcher::IM_HasUnclaimedInput && hasVariadicParameter)
1761-
return true;
1762-
}
1763-
return false;
1764-
}
1765-
17661698
bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
1767-
if (diagnoseCallContextualConversionErrors(callExpr, CS.getContextualType(),
1768-
CS.getContextualTypePurpose()))
1769-
return true;
1770-
17711699
auto *fnExpr = callExpr->getFn();
1772-
auto originalFnType = CS.getType(callExpr->getFn());
17731700

17741701
if (shouldTypeCheckFunctionExpr(*this, CS.DC, fnExpr)) {
17751702
// Type check the function subexpression to resolve a type for it if
@@ -1792,162 +1719,12 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
17921719

17931720
auto fnType = getFuncType(CS.getType(fnExpr));
17941721

1795-
// Let's see if this has to do with member vs. property error
1796-
// because sometimes when there is a member and a property declared
1797-
// on the nominal type with the same name. Type-checking function
1798-
// expression separately from arguments might produce solution for
1799-
// the property instead of the member.
1800-
if (!fnType->is<AnyFunctionType>() &&
1801-
isa<UnresolvedDotExpr>(callExpr->getFn())) {
1802-
fnExpr = callExpr->getFn();
1803-
1804-
SmallPtrSet<TypeBase *, 4> types;
1805-
getPossibleTypesOfExpressionWithoutApplying(fnExpr, CS.DC, types);
1806-
1807-
auto isFunctionType = [getFuncType](Type type) -> bool {
1808-
return type && getFuncType(type)->is<AnyFunctionType>();
1809-
};
1810-
1811-
auto fnTypes = std::find_if(types.begin(), types.end(), isFunctionType);
1812-
if (fnTypes != types.end()) {
1813-
auto funcType = getFuncType(*fnTypes);
1814-
// If there is only one function type, let's use it.
1815-
if (std::none_of(std::next(fnTypes), types.end(), isFunctionType))
1816-
fnType = funcType;
1817-
} else {
1818-
fnType = getFuncType(originalFnType);
1819-
}
1820-
}
1821-
1822-
// If we have a contextual type, and if we have an ambiguously typed function
1823-
// result from our previous check, we re-type-check it using this contextual
1824-
// type to inform the result type of the callee.
1825-
//
1826-
// We only do this as a second pass because the first pass we just did may
1827-
// return something of obviously non-function-type. If this happens, we
1828-
// produce better diagnostics below by diagnosing this here rather than trying
1829-
// to peel apart the failed conversion to function type.
1830-
if (CS.getContextualType() &&
1831-
(isUnresolvedOrTypeVarType(fnType) ||
1832-
(fnType->is<AnyFunctionType>() && fnType->hasUnresolvedType()))) {
1833-
// FIXME: Prevent typeCheckChildIndependently from transforming expressions,
1834-
// because if we try to typecheck OSR expression with contextual type,
1835-
// it'll end up converting it into DeclRefExpr based on contextual info,
1836-
// instead let's try to get a type without applying and filter callee
1837-
// candidates later on.
1838-
CalleeListener listener(CS.getContextualType());
1839-
1840-
if (isa<OverloadSetRefExpr>(fnExpr)) {
1841-
assert(!cast<OverloadSetRefExpr>(fnExpr)->getReferencedDecl() &&
1842-
"unexpected declaration reference");
1843-
1844-
ConcreteDeclRef decl = nullptr;
1845-
Type type = TypeChecker::getTypeOfExpressionWithoutApplying(
1846-
fnExpr, CS.DC, decl, FreeTypeVariableBinding::UnresolvedType,
1847-
&listener);
1848-
1849-
if (type)
1850-
fnType = getFuncType(type);
1851-
} else {
1852-
fnExpr = typeCheckChildIndependently(callExpr->getFn(), Type(),
1853-
CTP_CalleeResult, TCC_ForceRecheck,
1854-
&listener);
1855-
if (!fnExpr)
1856-
return true;
1857-
1858-
fnType = getFuncType(CS.getType(fnExpr));
1859-
}
1860-
}
1861-
1862-
// If we resolved a concrete expression for the callee, and it has
1863-
// non-function/non-metatype type, then we cannot call it!
1864-
if (!isUnresolvedOrTypeVarType(fnType) &&
1865-
!fnType->is<AnyFunctionType>() && !fnType->is<MetatypeType>()) {
1866-
auto arg = callExpr->getArg();
1867-
1868-
// If the argument is a trailing ClosureExpr (i.e. {....}) and it is on
1869-
// the line after the callee, then it's likely the user forgot to
1870-
// write "do" before their brace stmt.
1871-
// Note that line differences of more than 1 are diagnosed during parsing.
1872-
if (auto *PE = dyn_cast<ParenExpr>(arg)) {
1873-
if (PE->hasTrailingClosure() && isa<ClosureExpr>(PE->getSubExpr())) {
1874-
auto *closure = cast<ClosureExpr>(PE->getSubExpr());
1875-
auto &SM = CS.getASTContext().SourceMgr;
1876-
if (closure->hasAnonymousClosureVars() &&
1877-
closure->getParameters()->size() == 0 &&
1878-
1 + SM.getLineNumber(callExpr->getFn()->getEndLoc()) ==
1879-
SM.getLineNumber(closure->getStartLoc())) {
1880-
diagnose(closure->getStartLoc(), diag::brace_stmt_suggest_do)
1881-
.fixItInsert(closure->getStartLoc(), "do ");
1882-
return true;
1883-
}
1884-
}
1885-
}
1886-
1887-
auto isExistentialMetatypeType = fnType->is<ExistentialMetatypeType>();
1888-
if (isExistentialMetatypeType) {
1889-
auto diag = diagnose(arg->getStartLoc(),
1890-
diag::missing_init_on_metatype_initialization);
1891-
diag.highlight(fnExpr->getSourceRange());
1892-
return true;
1893-
} else {
1894-
auto diag = diagnose(arg->getStartLoc(),
1895-
diag::cannot_call_non_function_value, fnType);
1896-
diag.highlight(fnExpr->getSourceRange());
1897-
1898-
// If the argument is an empty tuple, then offer a
1899-
// fix-it to remove the empty tuple and use the value
1900-
// directly.
1901-
if (auto tuple = dyn_cast<TupleExpr>(arg)) {
1902-
if (tuple->getNumElements() == 0) {
1903-
diag.fixItRemove(arg->getSourceRange());
1904-
}
1905-
}
1906-
return true;
1907-
}
1908-
}
1909-
19101722
bool hasTrailingClosure = callArgHasTrailingClosure(callExpr->getArg());
19111723

19121724
// Collect a full candidate list of callees based on the partially type
19131725
// checked function.
19141726
CalleeCandidateInfo calleeInfo(fnExpr, hasTrailingClosure, CS);
19151727

1916-
// In the case that function subexpression was resolved independently in
1917-
// the first place, the resolved type may not provide the best diagnostic.
1918-
// We consider the number of arguments to decide whether we'd go with it or
1919-
// stay with the original one.
1920-
if (fnExpr != callExpr->getFn()) {
1921-
bool isInstanceMethodAsCurriedMemberOnType = false;
1922-
if (!calleeInfo.empty()) {
1923-
auto &&cand = calleeInfo[0];
1924-
auto decl = cand.getDecl();
1925-
if (decl && decl->isInstanceMember() && !cand.skipCurriedSelf &&
1926-
cand.getParameters().size() == 1)
1927-
isInstanceMethodAsCurriedMemberOnType = true;
1928-
}
1929-
1930-
// In terms of instance method as curried member on type, we should not
1931-
// take the number of arguments into account.
1932-
if (!isInstanceMethodAsCurriedMemberOnType) {
1933-
size_t numArgs = 1;
1934-
auto arg = callExpr->getArg();
1935-
if (auto tuple = dyn_cast<TupleExpr>(arg)) {
1936-
numArgs = tuple->getNumElements();
1937-
}
1938-
1939-
if (!isViableOverloadSet(calleeInfo, numArgs)) {
1940-
CalleeCandidateInfo calleeInfoOrig(callExpr->getFn(),
1941-
hasTrailingClosure, CS);
1942-
if (isViableOverloadSet(calleeInfoOrig, numArgs)) {
1943-
fnExpr = callExpr->getFn();
1944-
fnType = getFuncType(CS.getType(fnExpr));
1945-
calleeInfo = calleeInfoOrig;
1946-
}
1947-
}
1948-
}
1949-
}
1950-
19511728
// Filter list of the candidates based on the known function type.
19521729
if (auto fn = fnType->getAs<AnyFunctionType>()) {
19531730
using Closeness = CalleeCandidateInfo::ClosenessResultTy;

lib/Sema/CSDiagnostics.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5598,6 +5598,19 @@ bool ExtraneousCallFailure::diagnoseAsError() {
55985598
}
55995599
}
56005600

5601+
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
5602+
auto *baseExpr = UDE->getBase();
5603+
auto *call = cast<CallExpr>(getRawAnchor());
5604+
5605+
if (getType(baseExpr)->isAnyObject()) {
5606+
emitDiagnostic(anchor->getLoc(), diag::cannot_call_with_params,
5607+
UDE->getName().getBaseName().userFacingName(),
5608+
getType(call->getArg())->getString(),
5609+
isa<TypeExpr>(baseExpr));
5610+
return true;
5611+
}
5612+
}
5613+
56015614
auto diagnostic = emitDiagnostic(
56025615
anchor->getLoc(), diag::cannot_call_non_function_value, getType(anchor));
56035616
removeParensFixIt(diagnostic);

lib/Sema/CSSimplify.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7427,6 +7427,26 @@ ConstraintSystem::simplifyApplicableFnConstraint(
74277427
// Track how many times we do this so that we can record a fix for each.
74287428
++unwrapCount;
74297429
}
7430+
7431+
// Let's account for optional members concept from Objective-C
7432+
// which forms a disjunction for member type to check whether
7433+
// it would be possible to use optional type directly or it has
7434+
// to be force unwrapped (because such types are imported as IUO).
7435+
if (unwrapCount > 0 && desugar2->is<TypeVariableType>()) {
7436+
auto *typeVar = desugar2->castTo<TypeVariableType>();
7437+
auto *locator = typeVar->getImpl().getLocator();
7438+
if (locator->isLastElement<LocatorPathElt::Member>()) {
7439+
auto *fix = ForceOptional::create(*this, origType2, desugar2,
7440+
getConstraintLocator(locator));
7441+
if (recordFix(fix, /*impact=*/unwrapCount))
7442+
return SolutionKind::Error;
7443+
7444+
// Since the right-hand side of the constraint has been changed
7445+
// we have to re-generate this constraint to use new type.
7446+
flags |= TMF_GenerateConstraints;
7447+
return formUnsolved();
7448+
}
7449+
}
74307450
}
74317451

74327452
// For a function, bind the output and convert the argument to the input.
@@ -7500,11 +7520,6 @@ ConstraintSystem::simplifyApplicableFnConstraint(
75007520
desugar2->is<AnyMetatypeType>())
75017521
return SolutionKind::Error;
75027522

7503-
if (auto objectTy = desugar2->lookThroughAllOptionalTypes()) {
7504-
if (objectTy->isAny() || objectTy->isAnyObject())
7505-
return SolutionKind::Error;
7506-
}
7507-
75087523
// If there are any type variables associated with arguments/result
75097524
// they have to be marked as "holes".
75107525
type1.visit([&](Type subType) {

test/Constraints/iuo_objc.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,29 @@ func iuo_error(prop: IUOProperty) {
99
// expected-note@-2{{coalesce}}
1010
// expected-note@-3{{force-unwrap}}
1111
let _: Coat? = prop.iuo.optional()!
12-
// expected-error@-1 {{cannot invoke 'optional' with no arguments}}
12+
// expected-error@-1 {{value of optional type '(() -> Coat?)?' must be unwrapped to a value of type '() -> Coat?'}}
13+
// expected-note@-2{{coalesce}}
14+
// expected-note@-3{{force-unwrap}}
1315
let _: Coat? = prop.iuo.optional!()
1416
let _: Coat? = prop.iuo.optional!()!
1517
let _: Coat? = prop.iuo!.optional()
1618
// expected-error@-1 {{value of optional type '(() -> Coat?)?' must be unwrapped}}
1719
// expected-note@-2{{coalesce}}
1820
// expected-note@-3{{force-unwrap}}
1921
let _: Coat? = prop.iuo!.optional()!
20-
// expected-error@-1 {{cannot invoke 'optional' with no arguments}}
22+
// expected-error@-1 {{value of optional type '(() -> Coat?)?' must be unwrapped to a value of type '() -> Coat?'}}
23+
// expected-note@-2{{coalesce}}
24+
// expected-note@-3{{force-unwrap}}
2125
let _: Coat? = prop.iuo!.optional!()
2226
let _: Coat? = prop.iuo!.optional!()!
2327
let _: Coat = prop.iuo.optional()
2428
// expected-error@-1 {{value of optional type '(() -> Coat)?' must be unwrapped}}
2529
// expected-note@-2{{coalesce}}
2630
// expected-note@-3{{force-unwrap}}
2731
let _: Coat = prop.iuo.optional()!
28-
// expected-error@-1 {{cannot invoke 'optional' with no arguments}}
32+
// expected-error@-1 {{value of optional type '(() -> Coat?)?' must be unwrapped to a value of type '() -> Coat?'}}
33+
// expected-note@-2{{coalesce}}
34+
// expected-note@-3{{force-unwrap}}
2935
let _: Coat = prop.iuo.optional!()
3036
let _: Coat = prop.iuo.optional!()!
3137
let _: Coat = prop.iuo!.optional()
@@ -34,7 +40,9 @@ func iuo_error(prop: IUOProperty) {
3440
// expected-note@-3{{force-unwrap}}
3541

3642
let _: Coat = prop.iuo!.optional()!
37-
// expected-error@-1 {{cannot invoke 'optional' with no arguments}}
43+
// expected-error@-1 {{value of optional type '(() -> Coat?)?' must be unwrapped to a value of type '() -> Coat?'}}
44+
// expected-note@-2{{coalesce}}
45+
// expected-note@-3{{force-unwrap}}
3846
let _: Coat = prop.iuo!.optional!()
3947
let _: Coat = prop.iuo!.optional!()!
4048

0 commit comments

Comments
 (0)