mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[FixCode] Help users construct mutable pointer from a pointer by inserting 'mutating'. rdar://27500578 (#3971)
This commit is contained in:
@@ -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", ())
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
5
test/Sema/diag_init.swift
Normal file
5
test/Sema/diag_init.swift
Normal 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>?)}}
|
||||
}
|
||||
Reference in New Issue
Block a user