[FixCode] Help users construct mutable pointer from a pointer by inserting 'mutating'. rdar://27500578 (#3971)

This commit is contained in:
Xi Ge
2016-08-03 16:30:06 -07:00
committed by GitHub
parent b5f90af862
commit 63243147af
3 changed files with 32 additions and 0 deletions

View File

@@ -204,6 +204,8 @@ ERROR(cannot_call_with_params, none,
"cannot invoke %select{|initializer for type }2'%0' with an argument list"
" of type '%1'", (StringRef, StringRef, bool))
NOTE(pointer_init_add_mutating,none,
"do you want to add 'mutating'", ())
ERROR(expected_do_in_statement,none,
"expected 'do' keyword to designate a block of statements", ())

View File

@@ -4913,6 +4913,25 @@ bool FailureDiagnosis::diagnoseNilLiteralComparison(
return true;
}
static bool shouldAddMutating(ASTContext &Ctx, const Expr *Fn,
const Expr* Arg) {
auto *TypeExp = dyn_cast<TypeExpr>(Fn);
auto *ParenExp = dyn_cast<ParenExpr>(Arg);
if (!TypeExp || !ParenExp)
return false;
auto InitType = TypeExp->getInstanceType();
auto ArgType = ParenExp->getSubExpr()->getType();
if (InitType.isNull() || ArgType.isNull())
return false;
if (auto *InitNom = InitType->getAnyNominal()) {
if (auto *ArgNom = ArgType->getAnyNominal()) {
return InitNom == Ctx.getUnsafeMutablePointerDecl() &&
ArgNom == Ctx.getUnsafePointerDecl();
}
}
return false;
}
bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
// Type check the function subexpression to resolve a type for it if possible.
auto fnExpr = typeCheckChildIndependently(callExpr->getFn());
@@ -5227,6 +5246,12 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
diagnose(fnExpr->getLoc(), diag::cannot_call_with_params,
overloadName, argString, isInitializer);
}
if (shouldAddMutating(CS->DC->getASTContext(), fnExpr, argExpr)) {
diagnose(fnExpr->getLoc(), diag::pointer_init_add_mutating).fixItInsert(
dyn_cast<ParenExpr>(argExpr)->getSubExpr()->getStartLoc(), "mutating: ");
}
// Did the user intend on invoking a different overload?
calleeInfo.suggestPotentialOverloads(fnExpr->getLoc());

View File

@@ -0,0 +1,5 @@
// RUN: %target-parse-verify-swift
func foo(a : UnsafePointer<Void>)->UnsafeMutablePointer<Void> {
return UnsafeMutablePointer(a) // expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<_>' with an argument list of type '(UnsafePointer<Void>)'}} // expected-note {{do you want to add 'mutating'}}{{31-31=mutating: }} // expected-note {{overloads for 'UnsafeMutablePointer<_>' exist with these partially matching parameter lists: (RawPointer), (OpaquePointer), (OpaquePointer?), (UnsafeMutablePointer<Pointee>), (UnsafeMutablePointer<Pointee>?)}}
}