Skip to content

Commit 56f68c4

Browse files
committed
Improve diagnostics on invalid UnsafePointer conversion.
The only remaning issue is that we should have a warning to rename Unsafe[Mutable]Pointer<Void> to Unsafe[Mutable]RawPointer.
1 parent e78bdcf commit 56f68c4

File tree

5 files changed

+44
-45
lines changed

5 files changed

+44
-45
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,9 @@ ERROR(cannot_call_with_params, none,
207207
"cannot invoke %select{|initializer for type }2'%0' with an argument list"
208208
" of type '%1'", (StringRef, StringRef, bool))
209209

210-
NOTE(pointer_init_add_mutating,none,
211-
"do you want to add 'mutating'", ())
210+
NOTE(pointer_init_to_type,none,
211+
"Pointer conversion restricted: use '.assumingMemoryBound(to:)' or '.bindMemory(to:capacity:)' to view memory as a type.", ())
212+
212213
ERROR(expected_do_in_statement,none,
213214
"expected 'do' keyword to designate a block of statements", ())
214215

lib/Sema/CSDiag.cpp

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4967,26 +4967,37 @@ bool FailureDiagnosis::diagnoseNilLiteralComparison(
49674967
return true;
49684968
}
49694969

4970-
/// When initializing UnsafeMutablePointer from a given UnsafePointer, we need
4971-
/// to insert "mutating:" label before the argument to ensure the correct
4972-
/// intializer gets called. This function checks if we need to add the label.
4973-
static bool shouldAddMutating(ASTContext &Ctx, const Expr *Fn,
4974-
const Expr* Arg) {
4970+
/// When initializing Unsafe[Mutable]Pointer<T> from Unsafe[Mutable]RawPointer,
4971+
/// issue a diagnostic that refers to the API for binding memory to a type.
4972+
static bool isCastToTypedPointer(ASTContext &Ctx, const Expr *Fn,
4973+
const Expr* Arg) {
49754974
auto *TypeExp = dyn_cast<TypeExpr>(Fn);
49764975
auto *ParenExp = dyn_cast<ParenExpr>(Arg);
49774976
if (!TypeExp || !ParenExp)
49784977
return false;
4978+
49794979
auto InitType = TypeExp->getInstanceType();
49804980
auto ArgType = ParenExp->getSubExpr()->getType();
49814981
if (InitType.isNull() || ArgType.isNull())
49824982
return false;
4983-
if (auto *InitNom = InitType->getAnyNominal()) {
4984-
if (auto *ArgNom = ArgType->getAnyNominal()) {
4985-
return InitNom == Ctx.getUnsafeMutablePointerDecl() &&
4986-
ArgNom == Ctx.getUnsafePointerDecl();
4987-
}
4983+
4984+
auto *InitNom = InitType->getAnyNominal();
4985+
if (!InitNom)
4986+
return false;
4987+
4988+
if (InitNom != Ctx.getUnsafeMutablePointerDecl()
4989+
&& InitNom != Ctx.getUnsafePointerDecl()) {
4990+
return false;
49884991
}
4989-
return false;
4992+
auto *ArgNom = ArgType->getAnyNominal();
4993+
if (!ArgNom)
4994+
return false;
4995+
4996+
if (ArgNom != Ctx.getUnsafeMutableRawPointerDecl()
4997+
&& ArgNom != Ctx.getUnsafeRawPointerDecl()) {
4998+
return false;
4999+
}
5000+
return true;
49905001
}
49915002

49925003
bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
@@ -5304,10 +5315,9 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
53045315
overloadName, argString, isInitializer);
53055316
}
53065317

5307-
5308-
if (shouldAddMutating(CS->DC->getASTContext(), fnExpr, argExpr)) {
5309-
diagnose(fnExpr->getLoc(), diag::pointer_init_add_mutating).fixItInsert(
5310-
cast<ParenExpr>(argExpr)->getSubExpr()->getStartLoc(), "mutating: ");
5318+
if (isCastToTypedPointer(CS->DC->getASTContext(), fnExpr, argExpr)) {
5319+
diagnose(fnExpr->getLoc(), diag::pointer_init_to_type)
5320+
.highlight(argExpr->getSourceRange());
53115321
}
53125322

53135323
// Did the user intend on invoking a different overload?

stdlib/public/core/UnsafePointer.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ extension ${Self} {
532532
"use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.")
533533
public init?<U>(_ from : UnsafePointer<U>?) { Builtin.unreachable(); return nil }
534534

535-
% if mutable:
535+
% if mutable:
536536
@available(*, unavailable, renamed: "init(mutating:)")
537537
public init(_ from : UnsafePointer<Pointee>) { Builtin.unreachable() }
538538

test/1_stdlib/UnsafePointerDiagnostics.swift

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@
22

33
// Test availability attributes on UnsafePointer initializers.
44
// Assume the original source contains no UnsafeRawPointer types.
5-
//
6-
// TODO:
7-
// - implement the Unsafe[Mutable]Pointer<Void> to Unsafe[Mutable]RawPointer rename
8-
// - test multiple fix-its per line: type rename + initializer rename/diagnostic
95
func unsafePointerConversionAvailability(
106
mrp: UnsafeMutableRawPointer,
117
rp: UnsafeRawPointer,
12-
umpv: UnsafeMutablePointer<Void>,
13-
upv: UnsafePointer<Void>,
8+
umpv: UnsafeMutablePointer<Void>, // FIXME: This should yield a warning to rename UnsafeMutablePointer<Void> to UnsafeMutableRawPointer
9+
upv: UnsafePointer<Void>, // FIXME: This should yield a warning to rename UnsafePointer<Void> to UnsafeRawPointer
1410
umpi: UnsafeMutablePointer<Int>,
1511
upi: UnsafePointer<Int>,
1612
umps: UnsafeMutablePointer<String>,
@@ -35,42 +31,39 @@ func unsafePointerConversionAvailability(
3531
_ = UnsafeRawPointer(umps)
3632
_ = UnsafeRawPointer(ups)
3733

38-
// FIXME: All of these should yield a fix-it to rename
39-
// UnsafeMutablePointer<Void> to UnsafeMutableRawPointer(umpv)
40-
_ = UnsafeMutablePointer<Void>(rp) // expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Void>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{}}
41-
_ = UnsafeMutablePointer<Void>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Void>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{}}
34+
// FIXME: All of these should yield a warning to rename
35+
// UnsafeMutablePointer<Void> to UnsafeMutableRawPointer.
36+
_ = UnsafeMutablePointer<Void>(rp) // expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Void>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{Pointer conversion restricted: use '.assumingMemoryBound(to:)' or '.bindMemory(to:capacity:)' to view memory as a type.}} expected-note {{}}
37+
_ = UnsafeMutablePointer<Void>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Void>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{Pointer conversion restricted: use '.assumingMemoryBound(to:)' or '.bindMemory(to:capacity:)' to view memory as a type.}} expected-note {{}}
4238
_ = UnsafeMutablePointer<Void>(umpv)
4339
_ = UnsafeMutablePointer<Void>(upv) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
4440
_ = UnsafeMutablePointer<Void>(umpi)
4541
_ = UnsafeMutablePointer<Void>(upi) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
4642
_ = UnsafeMutablePointer<Void>(umps)
4743
_ = UnsafeMutablePointer<Void>(ups) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
4844

49-
// FIXME: All of these should yield a fix-it to rename
50-
// UnsafePointer<Void> to UnsafeRawPointer(umpv)
51-
_ = UnsafePointer<Void>(rp) // expected-error {{cannot invoke initializer for type 'UnsafePointer<Void>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{}}
52-
_ = UnsafePointer<Void>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafePointer<Void>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{}}
53-
_ = UnsafePointer<Void>(umpv)
45+
// FIXME: All of these should yield a warning to rename
46+
// UnsafePointer<Void> to UnsafeRawPointer.
47+
_ = UnsafePointer<Void>(rp) // expected-error {{cannot invoke initializer for type 'UnsafePointer<Void>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{Pointer conversion restricted: use '.assumingMemoryBound(to:)' or '.bindMemory(to:capacity:)' to view memory as a type.}} expected-note {{}}
48+
_ = UnsafePointer<Void>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafePointer<Void>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{Pointer conversion restricted: use '.assumingMemoryBound(to:)' or '.bindMemory(to:capacity:)' to view memory as a type.}} expected-note {{}}
49+
_ = UnsafePointer<Void>(umpv)
5450
_ = UnsafePointer<Void>(upv)
5551
_ = UnsafePointer<Void>(umpi)
5652
_ = UnsafePointer<Void>(upi)
5753
_ = UnsafePointer<Void>(umps)
5854
_ = UnsafePointer<Void>(ups)
5955

60-
// FIXME: Conversion from UnsafePointer<Void> or UnsafeRawPointer to a typed
61-
// pointer should have a diagnostic: 'init' is unavailable: Conversion
62-
// restricted. Use 'assumingMemoryBound(to:)' or 'bindMemory(to:capacity:)'
63-
_ = UnsafeMutablePointer<Int>(rp) // expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Int>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{}}
64-
_ = UnsafeMutablePointer<Int>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Int>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{}}
56+
_ = UnsafeMutablePointer<Int>(rp) // expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Int>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{Pointer conversion restricted: use '.assumingMemoryBound(to:)' or '.bindMemory(to:capacity:)' to view memory as a type.}} expected-note {{}}
57+
_ = UnsafeMutablePointer<Int>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Int>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{Pointer conversion restricted: use '.assumingMemoryBound(to:)' or '.bindMemory(to:capacity:)' to view memory as a type.}} expected-note {{}}
6558
_ = UnsafeMutablePointer<Int>(umpv) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
6659
_ = UnsafeMutablePointer<Int>(upv) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
6760
_ = UnsafeMutablePointer<Int>(umpi)
6861
_ = UnsafeMutablePointer<Int>(upi) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
6962
_ = UnsafeMutablePointer<Int>(umps) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
7063
_ = UnsafeMutablePointer<Int>(ups) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
7164

72-
_ = UnsafePointer<Int>(rp) // expected-error {{cannot invoke initializer for type 'UnsafePointer<Int>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{}}
73-
_ = UnsafePointer<Int>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafePointer<Int>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{}}
65+
_ = UnsafePointer<Int>(rp) // expected-error {{cannot invoke initializer for type 'UnsafePointer<Int>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{Pointer conversion restricted: use '.assumingMemoryBound(to:)' or '.bindMemory(to:capacity:)' to view memory as a type.}} expected-note {{}}
66+
_ = UnsafePointer<Int>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafePointer<Int>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{Pointer conversion restricted: use '.assumingMemoryBound(to:)' or '.bindMemory(to:capacity:)' to view memory as a type.}} expected-note {{}}
7467
_ = UnsafePointer<Int>(umpv) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
7568
_ = UnsafePointer<Int>(upv) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
7669
_ = UnsafePointer<Int>(umpi)

test/Sema/diag_init.swift

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)