Skip to content

[Diagnostics] Switch to using FunctionType::getParams instead of input type #15843

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 103 additions & 94 deletions lib/Sema/CSDiag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1805,8 +1805,8 @@ bool FailureDiagnosis::diagnoseGeneralConversionFailure(Constraint *constraint){
if (!srcFT->isNoEscape()) destExtInfo = destExtInfo.withNoEscape(false);
if (!srcFT->throws()) destExtInfo = destExtInfo.withThrows(false);
if (destExtInfo != destFT->getExtInfo())
toType = FunctionType::get(destFT->getInput(),
destFT->getResult(), destExtInfo);
toType = FunctionType::get(destFT->getParams(), destFT->getResult(),
destExtInfo);

// If this is a function conversion that discards throwability or
// noescape, emit a specific diagnostic about that.
Expand Down Expand Up @@ -2978,7 +2978,7 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
// If we're trying to convert something of type "() -> T" to T, then we
// probably meant to call the value.
if (auto srcFT = exprType->getAs<AnyFunctionType>()) {
if (srcFT->getInput()->isVoid() &&
if (srcFT->getParams().empty() &&
!isUnresolvedOrTypeVarType(srcFT->getResult()) &&
CS.TC.isConvertibleTo(srcFT->getResult(), contextualType, CS.DC)) {
diagnose(expr->getLoc(), diag::missing_nullary_call, srcFT->getResult())
Expand Down Expand Up @@ -3071,7 +3071,7 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
if (!srcFT->isNoEscape()) destExtInfo = destExtInfo.withNoEscape(false);
if (!srcFT->throws()) destExtInfo = destExtInfo.withThrows(false);
if (destExtInfo != destFT->getExtInfo())
contextualType = FunctionType::get(destFT->getInput(),
contextualType = FunctionType::get(destFT->getParams(),
destFT->getResult(), destExtInfo);

// If this is a function conversion that discards throwability or
Expand Down Expand Up @@ -3896,7 +3896,8 @@ diagnoseInstanceMethodAsCurriedMemberOnType(CalleeCandidateInfo &CCI,
}

static bool diagnoseTupleParameterMismatch(CalleeCandidateInfo &CCI,
Type paramType, Type argType,
ArrayRef<AnyFunctionType::Param> params,
ArrayRef<AnyFunctionType::Param> args,
Expr *fnExpr, Expr *argExpr,
bool isTopLevel = true) {
// Try to diagnose function call tuple parameter splat only if
Expand All @@ -3913,72 +3914,96 @@ static bool diagnoseTupleParameterMismatch(CalleeCandidateInfo &CCI,
}
}

if (auto *paramFnType = paramType->getAs<AnyFunctionType>()) {
// Only if both of the parameter and argument types are functions
// let's recur into diagnosing their arguments.
if (auto *argFnType = argType->getAs<AnyFunctionType>())
return diagnoseTupleParameterMismatch(CCI, paramFnType->getInput(),
argFnType->getInput(), fnExpr,
argExpr, /* isTopLevel */ false);
return false;
if (params.size() == 1 && args.size() == 1) {
auto paramType = params.front().getType();
auto argType = args.front().getType();

if (auto *paramFnType = paramType->getAs<AnyFunctionType>()) {
// Only if both of the parameter and argument types are functions
// let's recur into diagnosing their arguments.
if (auto *argFnType = argType->getAs<AnyFunctionType>())
return diagnoseTupleParameterMismatch(CCI, paramFnType->getParams(),
argFnType->getParams(), fnExpr,
argExpr, /* isTopLevel */ false);
return false;
}
}

unsigned parameterCount = 1, argumentCount = 1;
if (params.size() != 1 || args.empty())
return false;

// Don't try to desugar ParenType which is going to result in incorrect
// inferred argument/parameter count.
auto paramType = params.front().getType();

if (auto *paramTypeTy = dyn_cast<TupleType>(paramType.getPointer()))
parameterCount = paramTypeTy->getNumElements();
if (args.size() == 1) {
auto argType = args.front().getType();
if (auto *paramFnType = paramType->getAs<AnyFunctionType>()) {
// Only if both of the parameter and argument types are functions
// let's recur into diagnosing their arguments.
if (auto *argFnType = argType->getAs<AnyFunctionType>())
return diagnoseTupleParameterMismatch(CCI, paramFnType->getParams(),
argFnType->getParams(), fnExpr,
argExpr, /* isTopLevel */ false);
}

if (auto *argTupleTy = dyn_cast<TupleType>(argType.getPointer()))
argumentCount = argTupleTy->getNumElements();
return false;
}

if (parameterCount == 1 && argumentCount > 1) {
// Let's see if inferred argument is actually a tuple inside of Paren.
auto *paramTupleTy = paramType->getAs<TupleType>();
if (!paramTupleTy)
return false;
// Let's see if inferred argument is actually a tuple inside of Paren.
auto *paramTupleTy = paramType->getAs<TupleType>();
if (!paramTupleTy)
return false;

// Looks like the number of tuple elements matches number
// of function arguments, which means we can we can emit an
// error about an attempt to make use of tuple splat or tuple
// destructuring, unfortunately we can't provide a fix-it for
// this case.
if (paramTupleTy->getNumElements() == argumentCount) {
auto &TC = CCI.CS.TC;
if (isTopLevel) {
if (auto *decl = CCI[0].getDecl()) {
Identifier name;
auto kind = decl->getDescriptiveKind();
// Constructors/descructors and subscripts don't really have names.
if (!(isa<ConstructorDecl>(decl) || isa<DestructorDecl>(decl) ||
isa<SubscriptDecl>(decl))) {
name = decl->getBaseName().getIdentifier();
}
if (paramTupleTy->getNumElements() != args.size())
return false;

TC.diagnose(argExpr->getLoc(), diag::single_tuple_parameter_mismatch,
kind, name, paramType, !name.empty())
.highlight(argExpr->getSourceRange())
.fixItInsertAfter(argExpr->getStartLoc(), "(")
.fixItInsert(argExpr->getEndLoc(), ")");
} else {
TC.diagnose(argExpr->getLoc(),
diag::unknown_single_tuple_parameter_mismatch, paramType)
.highlight(argExpr->getSourceRange())
.fixItInsertAfter(argExpr->getStartLoc(), "(")
.fixItInsert(argExpr->getEndLoc(), ")");
}
} else {
TC.diagnose(argExpr->getLoc(),
diag::nested_tuple_parameter_destructuring, paramType,
CCI.CS.getType(fnExpr));
// Looks like the number of tuple elements matches number
// of function arguments, which means we can we can emit an
// error about an attempt to make use of tuple splat or tuple
// destructuring, unfortunately we can't provide a fix-it for
// this case.
auto &TC = CCI.CS.TC;
if (isTopLevel) {
if (auto *decl = CCI[0].getDecl()) {
Identifier name;
auto kind = decl->getDescriptiveKind();
// Constructors/descructors and subscripts don't really have names.
if (!(isa<ConstructorDecl>(decl) || isa<DestructorDecl>(decl) ||
isa<SubscriptDecl>(decl))) {
name = decl->getBaseName().getIdentifier();
}
return true;

TC.diagnose(argExpr->getLoc(), diag::single_tuple_parameter_mismatch,
kind, name, paramTupleTy, !name.empty())
.highlight(argExpr->getSourceRange())
.fixItInsertAfter(argExpr->getStartLoc(), "(")
.fixItInsert(argExpr->getEndLoc(), ")");
} else {
TC.diagnose(argExpr->getLoc(),
diag::unknown_single_tuple_parameter_mismatch, paramTupleTy)
.highlight(argExpr->getSourceRange())
.fixItInsertAfter(argExpr->getStartLoc(), "(")
.fixItInsert(argExpr->getEndLoc(), ")");
}
} else {
TC.diagnose(argExpr->getLoc(),
diag::nested_tuple_parameter_destructuring, paramTupleTy,
CCI.CS.getType(fnExpr));
}

return false;
return true;
}

static bool diagnoseTupleParameterMismatch(CalleeCandidateInfo &CCI,
Type paramType, Type argType,
Expr *fnExpr, Expr *argExpr,
bool isTopLevel = true) {
llvm::SmallVector<AnyFunctionType::Param, 4> params, args;

FunctionType::decomposeInput(paramType, params);
FunctionType::decomposeInput(argType, args);

return diagnoseTupleParameterMismatch(CCI, params, args, fnExpr, argExpr,
isTopLevel);
}

class ArgumentMatcher : public MatchCallArgumentListener {
Expand Down Expand Up @@ -4650,7 +4675,9 @@ bool FailureDiagnosis::diagnoseSubscriptErrors(SubscriptExpr *SE,
auto candType = baseType->getTypeOfMember(CS.DC->getParentModule(),
cand.getDecl(), nullptr);
if (auto *candFunc = candType->getAs<FunctionType>()) {
auto paramsType = candFunc->getInput();
auto paramsType = FunctionType::composeInput(CS.getASTContext(),
candFunc->getParams(),
false);
if (!typeCheckChildIndependently(
indexExpr, paramsType, CTP_CallArgument, TCC_ForceRecheck))
return true;
Expand Down Expand Up @@ -5227,25 +5254,11 @@ bool FailureDiagnosis::diagnoseTrailingClosureErrors(ApplyExpr *callExpr) {
if (!fnType)
continue;

auto paramType = fnType->getInput();
switch (paramType->getKind()) {
case TypeKind::Tuple: {
auto tuple = paramType->getAs<TupleType>();
if (tuple->getNumElements() != 1)
continue;

paramType = tuple->getElement(0).getType();
break;
}

case TypeKind::Paren:
paramType = paramType->getWithoutParens();
break;

default:
auto params = fnType->getParams();
if (params.size() != 1)
return false;
}

Type paramType = params.front().getType();
if (auto paramFnType = paramType->getAs<AnyFunctionType>()) {
auto closureType = CS.getType(closureExpr);
if (auto *argFnType = closureType->getAs<AnyFunctionType>()) {
Expand Down Expand Up @@ -5298,7 +5311,7 @@ bool FailureDiagnosis::diagnoseTrailingClosureErrors(ApplyExpr *callExpr) {
}
};

auto expectedArgType = FunctionType::get(fnType->getInput(), resultType,
auto expectedArgType = FunctionType::get(fnType->getParams(), resultType,
fnType->getExtInfo());

llvm::SaveAndRestore<DeclContext *> SavedDC(CS.DC, DC);
Expand Down Expand Up @@ -5582,10 +5595,11 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
calleeInfo))
return true;

Type argType; // Type of the argument list, if knowable.
if (auto FTy = fnType->getAs<AnyFunctionType>())
argType = FTy->getInput();
else if (auto MTT = fnType->getAs<AnyMetatypeType>()) {
Type argType; // argument list, if known.
if (auto FTy = fnType->getAs<AnyFunctionType>()) {
argType = FunctionType::composeInput(CS.getASTContext(), FTy->getParams(),
false);
} else if (auto MTT = fnType->getAs<AnyMetatypeType>()) {
// If we are constructing a tuple with initializer syntax, the expected
// argument list is the tuple type itself - and there is no initdecl.
auto instanceTy = MTT->getInstanceType();
Expand Down Expand Up @@ -6242,7 +6256,7 @@ bool FailureDiagnosis::diagnoseClosureExpr(
if (contextualType && contextualType->is<AnyFunctionType>()) {
auto fnType = contextualType->getAs<AnyFunctionType>();
auto *params = CE->getParameters();
Type inferredArgType = fnType->getInput();
auto inferredArgs = fnType->getParams();

// It is very common for a contextual type to disagree with the argument
// list built into the closure expr. This can be because the closure expr
Expand All @@ -6252,11 +6266,7 @@ bool FailureDiagnosis::diagnoseClosureExpr(
// { $0 + $1 }
// in either case, we want to produce nice and clear diagnostics.
unsigned actualArgCount = params->size();
unsigned inferredArgCount = 1;
// Don't try to desugar ParenType which is going to result in incorrect
// inferred argument count.
if (auto *argTupleTy = dyn_cast<TupleType>(inferredArgType.getPointer()))
inferredArgCount = argTupleTy->getNumElements();
unsigned inferredArgCount = inferredArgs.size();

if (actualArgCount != inferredArgCount) {
// If the closure didn't specify any arguments and it is in a context that
Expand Down Expand Up @@ -6288,8 +6298,9 @@ bool FailureDiagnosis::diagnoseClosureExpr(
}

if (inferredArgCount == 1 && actualArgCount > 1) {
auto *argTupleTy = inferredArgs.front().getType()->getAs<TupleType>();
// Let's see if inferred argument is actually a tuple inside of Paren.
if (auto *argTupleTy = inferredArgType->getAs<TupleType>()) {
if (argTupleTy) {
// Looks like the number of closure parameters matches number
// of inferred arguments, which means we can we can emit an
// error about an attempt to make use of tuple splat or tuple
Expand All @@ -6310,9 +6321,6 @@ bool FailureDiagnosis::diagnoseClosureExpr(
auto diag = diagnose(params->getStartLoc(),
diag::closure_tuple_parameter_destructuring,
argTupleTy);
Type actualArgType;
if (auto *actualFnType = CS.getType(CE)->getAs<AnyFunctionType>())
actualArgType = actualFnType->getInput();

auto *closureBody = CE->getBody();
if (!closureBody)
Expand Down Expand Up @@ -6432,7 +6440,8 @@ bool FailureDiagnosis::diagnoseClosureExpr(
// Okay, the wrong number of arguments was used, complain about that.
// Before doing so, strip attributes off the function type so that they
// don't confuse the issue.
fnType = FunctionType::get(fnType->getInput(), fnType->getResult());
fnType = FunctionType::get(fnType->getParams(), fnType->getResult(),
fnType->getExtInfo(), false);
auto diag = diagnose(
params->getStartLoc(), diag::closure_argument_list_tuple, fnType,
inferredArgCount, actualArgCount, (actualArgCount == 1));
Expand Down Expand Up @@ -7490,7 +7499,7 @@ bool FailureDiagnosis::diagnoseMemberFailures(
// call the function, e.g. in "a.b.c" where they had to write "a.b().c".
// Produce a specific diagnostic + fixit for this situation.
if (auto baseFTy = baseObjTy->getAs<AnyFunctionType>()) {
if (baseExpr && baseFTy->getInput()->isVoid()) {
if (baseExpr && baseFTy->getParams().empty()) {
SourceLoc insertLoc = baseExpr->getEndLoc();

if (auto *DRE = dyn_cast<DeclRefExpr>(baseExpr)) {
Expand Down
Loading