Skip to content

Commit 10b1bae

Browse files
authored
Merge pull request #27362 from xedin/port-missing-args
[Diagnostics] Port missing argument(s) diagnostics
2 parents 5e8ba1d + ec6a874 commit 10b1bae

29 files changed

+776
-344
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,8 @@ ERROR(missing_argument_named,none,
11161116
"missing argument for parameter %0 in call", (Identifier))
11171117
ERROR(missing_argument_positional,none,
11181118
"missing argument for parameter #%0 in call", (unsigned))
1119+
ERROR(missing_arguments_in_call,none,
1120+
"missing arguments for parameters %0 in call", (StringRef))
11191121
ERROR(extra_argument_named,none,
11201122
"extra argument %0 in call", (Identifier))
11211123
ERROR(extra_argument_positional,none,
@@ -3493,6 +3495,10 @@ ERROR(single_tuple_parameter_mismatch_normal,none,
34933495
(DescriptiveDeclKind, DeclBaseName, Type, StringRef))
34943496
ERROR(unknown_single_tuple_parameter_mismatch,none,
34953497
"single parameter of type %0 is expected in call", (Type))
3498+
ERROR(cannot_convert_single_tuple_into_multiple_arguments,none,
3499+
"%0 %select{%1 |}2expects %3 separate arguments"
3500+
"%select{|; remove extra parentheses to change tuple into separate arguments}4",
3501+
(DescriptiveDeclKind, DeclName, bool, unsigned, bool))
34963502

34973503
ERROR(enum_element_pattern_assoc_values_mismatch,none,
34983504
"pattern with associated values does not match enum case %0",

lib/Sema/CSDiag.cpp

Lines changed: 3 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,7 +2147,6 @@ bool FailureDiagnosis::diagnoseImplicitSelfErrors(
21472147

21482148
class ArgumentMatcher : public MatchCallArgumentListener {
21492149
TypeChecker &TC;
2150-
Expr *FnExpr;
21512150
Expr *ArgExpr;
21522151
ArrayRef<AnyFunctionType::Param> &Parameters;
21532152
const ParameterListInfo &ParamInfo;
@@ -2164,12 +2163,12 @@ class ArgumentMatcher : public MatchCallArgumentListener {
21642163
SmallVector<ParamBinding, 4> Bindings;
21652164

21662165
public:
2167-
ArgumentMatcher(Expr *fnExpr, Expr *argExpr,
2166+
ArgumentMatcher(Expr *argExpr,
21682167
ArrayRef<AnyFunctionType::Param> &params,
21692168
const ParameterListInfo &paramInfo,
21702169
SmallVectorImpl<AnyFunctionType::Param> &args,
21712170
CalleeCandidateInfo &CCI, bool isSubscript)
2172-
: TC(CCI.CS.TC), FnExpr(fnExpr), ArgExpr(argExpr), Parameters(params),
2171+
: TC(CCI.CS.TC), ArgExpr(argExpr), Parameters(params),
21732172
ParamInfo(paramInfo), Arguments(args), CandidateInfo(CCI),
21742173
IsSubscript(isSubscript) {}
21752174

@@ -2211,159 +2210,6 @@ class ArgumentMatcher : public MatchCallArgumentListener {
22112210
Diagnosed = true;
22122211
}
22132212

2214-
void missingArgument(unsigned missingParamIdx) override {
2215-
auto &param = Parameters[missingParamIdx];
2216-
Identifier name = param.getLabel();
2217-
2218-
// Search insertion index.
2219-
unsigned argIdx = 0;
2220-
for (int Idx = missingParamIdx - 1; Idx >= 0; --Idx) {
2221-
if (Bindings[Idx].empty())
2222-
continue;
2223-
argIdx = Bindings[Idx].back() + 1;
2224-
break;
2225-
}
2226-
2227-
unsigned insertableEndIdx = Arguments.size();
2228-
if (CandidateInfo.hasTrailingClosure)
2229-
insertableEndIdx -= 1;
2230-
2231-
// Build argument string for fix-it.
2232-
SmallString<32> insertBuf;
2233-
llvm::raw_svector_ostream insertText(insertBuf);
2234-
2235-
if (argIdx != 0)
2236-
insertText << ", ";
2237-
if (!name.empty())
2238-
insertText << name.str() << ": ";
2239-
Type Ty = param.getOldType();
2240-
// Explode inout type.
2241-
if (param.isInOut()) {
2242-
insertText << "&";
2243-
Ty = param.getPlainType();
2244-
}
2245-
// @autoclosure; the type should be the result type.
2246-
if (param.isAutoClosure())
2247-
Ty = param.getPlainType()->castTo<FunctionType>()->getResult();
2248-
insertText << "<#" << Ty << "#>";
2249-
if (argIdx == 0 && insertableEndIdx != 0)
2250-
insertText << ", ";
2251-
2252-
SourceLoc insertLoc;
2253-
if (argIdx > insertableEndIdx) {
2254-
// Unreachable for now.
2255-
// FIXME: matchCallArguments() doesn't detect "missing argument after
2256-
// trailing closure". E.g.
2257-
// func fn(x: Int, y: () -> Int, z: Int) { ... }
2258-
// fn(x: 1) { return 1 }
2259-
// is diagnosed as "missing argument for 'y'" (missingParamIdx 1).
2260-
// It should be "missing argument for 'z'" (missingParamIdx 2).
2261-
} else if (auto *TE = dyn_cast<TupleExpr>(ArgExpr)) {
2262-
// fn():
2263-
// fn([argMissing])
2264-
// fn(argX, argY):
2265-
// fn([argMissing, ]argX, argY)
2266-
// fn(argX[, argMissing], argY)
2267-
// fn(argX, argY[, argMissing])
2268-
// fn(argX) { closure }:
2269-
// fn([argMissing, ]argX) { closure }
2270-
// fn(argX[, argMissing]) { closure }
2271-
// fn(argX[, closureLabel: ]{closure}[, argMissing)] // Not impl.
2272-
if (insertableEndIdx == 0)
2273-
insertLoc = TE->getRParenLoc();
2274-
else if (argIdx != 0)
2275-
insertLoc = Lexer::getLocForEndOfToken(
2276-
TC.Context.SourceMgr, TE->getElement(argIdx - 1)->getEndLoc());
2277-
else {
2278-
insertLoc = TE->getElementNameLoc(0);
2279-
if (insertLoc.isInvalid())
2280-
insertLoc = TE->getElement(0)->getStartLoc();
2281-
}
2282-
} else if (auto *PE = dyn_cast<ParenExpr>(ArgExpr)) {
2283-
assert(argIdx <= 1);
2284-
if (PE->getRParenLoc().isValid()) {
2285-
// fn(argX):
2286-
// fn([argMissing, ]argX)
2287-
// fn(argX[, argMissing])
2288-
// fn() { closure }:
2289-
// fn([argMissing]) {closure}
2290-
// fn([closureLabel: ]{closure}[, argMissing]) // Not impl.
2291-
if (insertableEndIdx == 0)
2292-
insertLoc = PE->getRParenLoc();
2293-
else if (argIdx == 0)
2294-
insertLoc = PE->getSubExpr()->getStartLoc();
2295-
else
2296-
insertLoc = Lexer::getLocForEndOfToken(TC.Context.SourceMgr,
2297-
PE->getSubExpr()->getEndLoc());
2298-
} else {
2299-
// fn { closure }:
2300-
// fn[(argMissing)] { closure }
2301-
// fn[(closureLabel:] { closure }[, missingArg)] // Not impl.
2302-
assert(!IsSubscript && "bracket less subscript");
2303-
assert(PE->hasTrailingClosure() &&
2304-
"paren less ParenExpr without trailing closure");
2305-
insertBuf.insert(insertBuf.begin(), '(');
2306-
insertBuf.insert(insertBuf.end(), ')');
2307-
insertLoc = Lexer::getLocForEndOfToken(TC.Context.SourceMgr,
2308-
FnExpr->getEndLoc());
2309-
}
2310-
} else {
2311-
auto &CS = CandidateInfo.CS;
2312-
(void)CS;
2313-
// FIXME: Due to a quirk of CSApply, we can end up without a
2314-
// ParenExpr if the argument has an '@lvalue TupleType'.
2315-
assert((isa<TupleType>(CS.getType(ArgExpr).getPointer()) ||
2316-
CS.getType(ArgExpr)->hasParenSugar()) &&
2317-
"unexpected argument expression type");
2318-
insertLoc = ArgExpr->getLoc();
2319-
}
2320-
2321-
assert(insertLoc.isValid() && "missing argument after trailing closure?");
2322-
2323-
if (name.empty()) {
2324-
TC.diagnose(insertLoc, diag::missing_argument_positional,
2325-
missingParamIdx + 1)
2326-
.fixItInsert(insertLoc, insertText.str());
2327-
} else {
2328-
if (isPropertyWrapperImplicitInit()) {
2329-
auto TE = cast<TypeExpr>(FnExpr);
2330-
TC.diagnose(TE->getLoc(), diag::property_wrapper_missing_arg_init, name,
2331-
TE->getInstanceType()->getString());
2332-
} else {
2333-
TC.diagnose(insertLoc, diag::missing_argument_named, name)
2334-
.fixItInsert(insertLoc, insertText.str());
2335-
}
2336-
}
2337-
2338-
auto candidate = CandidateInfo[0];
2339-
if (candidate.getDecl())
2340-
TC.diagnose(candidate.getDecl(), diag::decl_declared_here,
2341-
candidate.getDecl()->getFullName());
2342-
2343-
Diagnosed = true;
2344-
}
2345-
2346-
bool isPropertyWrapperImplicitInit() {
2347-
auto TE = dyn_cast<TypeExpr>(FnExpr);
2348-
if (!TE)
2349-
return false;
2350-
2351-
auto instanceTy = TE->getInstanceType();
2352-
if (!instanceTy)
2353-
return false;
2354-
2355-
auto nominalDecl = instanceTy->getAnyNominal();
2356-
if (!(nominalDecl &&
2357-
nominalDecl->getAttrs().hasAttribute<PropertyWrapperAttr>()))
2358-
return false;
2359-
2360-
if (auto *parentExpr = CandidateInfo.CS.getParentExpr(FnExpr)) {
2361-
return parentExpr->isImplicit() && isa<CallExpr>(parentExpr);
2362-
}
2363-
2364-
return false;
2365-
}
2366-
23672213
bool missingLabel(unsigned paramIdx) override {
23682214
return false;
23692215
}
@@ -2499,7 +2345,7 @@ diagnoseSingleCandidateFailures(CalleeCandidateInfo &CCI, Expr *fnExpr,
24992345

25002346
// If we have a single candidate that failed to match the argument list,
25012347
// attempt to use matchCallArguments to diagnose the problem.
2502-
return ArgumentMatcher(fnExpr, argExpr, params, paramInfo, args, CCI,
2348+
return ArgumentMatcher(argExpr, params, paramInfo, args, CCI,
25032349
isa<SubscriptExpr>(fnExpr))
25042350
.diagnose();
25052351
}

0 commit comments

Comments
 (0)