Skip to content

Commit 37af45f

Browse files
authored
Merge pull request #4139 from nkcsgexi/pointer-diagnosis-3.0
[FixCode] Add a diagnosis/fixit to help users convert Unsafe[Mutable]Pointer<Void> to Unsafe[Mutable]RawPointer.
2 parents a15553c + 9b05411 commit 37af45f

File tree

5 files changed

+63
-27
lines changed

5 files changed

+63
-27
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,6 +2199,9 @@ NOTE(generic_type_declared_here,none,
21992199
ERROR(cannot_partially_specialize_generic_function,none,
22002200
"cannot partially specialize a generic function", ())
22012201

2202+
WARNING(use_of_void_pointer,none,
2203+
"Unsafe%0Pointer<Void> has been replaced by Unsafe%0RawPointer", (StringRef))
2204+
22022205
// Ambiguities
22032206
ERROR(ambiguous_decl_ref,none,
22042207
"ambiguous use of %0", (DeclName))

lib/Sema/TypeCheckType.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,24 @@ Type TypeChecker::resolveTypeInContext(
408408
return ErrorType::get(Context);
409409
}
410410

411+
/// This function checks if a bound generic type is UnsafePointer<Void> or
412+
/// UnsafeMutablePointer<Void>. For these two type representations, we should
413+
/// warn users that they are deprecated and replace them with more handy
414+
/// UnsafeRawPointer and UnsafeMutableRawPointer, respectively.
415+
static bool isPointerToVoid(ASTContext &Ctx, Type Ty, bool &IsMutable) {
416+
if (Ty.isNull())
417+
return false;
418+
auto *BGT = Ty->getAs<BoundGenericType>();
419+
if (!BGT)
420+
return false;
421+
if (BGT->getDecl() != Ctx.getUnsafePointerDecl() &&
422+
BGT->getDecl() != Ctx.getUnsafeMutablePointerDecl())
423+
return false;
424+
IsMutable = BGT->getDecl() == Ctx.getUnsafeMutablePointerDecl();
425+
assert(BGT->getGenericArgs().size() == 1);
426+
return BGT->getGenericArgs().front()->isVoid();
427+
}
428+
411429
Type TypeChecker::applyGenericArguments(Type type, TypeDecl *decl,
412430
SourceLoc loc, DeclContext *dc,
413431
GenericIdentTypeRepr *generic,
@@ -473,8 +491,18 @@ Type TypeChecker::applyGenericArguments(Type type, TypeDecl *decl,
473491
for (auto tyR : genericArgs)
474492
args.push_back(tyR);
475493

476-
return applyUnboundGenericArguments(type, genericDecl, loc, dc, args,
477-
isGenericSignature, resolver);
494+
auto result = applyUnboundGenericArguments(type, genericDecl, loc, dc, args,
495+
isGenericSignature, resolver);
496+
bool isMutablePointer;
497+
if (isPointerToVoid(dc->getASTContext(), result, isMutablePointer)) {
498+
if (isMutablePointer)
499+
diagnose(loc, diag::use_of_void_pointer, "Mutable").
500+
fixItReplace(generic->getSourceRange(), "UnsafeMutableRawPointer");
501+
else
502+
diagnose(loc, diag::use_of_void_pointer, "").
503+
fixItReplace(generic->getSourceRange(), "UnsafeRawPointer");
504+
}
505+
return result;
478506
}
479507

480508
/// Apply generic arguments to the given type.

test/1_stdlib/UnsafePointerDiagnostics.swift

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
func unsafePointerConversionAvailability(
66
mrp: UnsafeMutableRawPointer,
77
rp: UnsafeRawPointer,
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
8+
umpv: UnsafeMutablePointer<Void>, // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
9+
upv: UnsafePointer<Void>, // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
1010
umpi: UnsafeMutablePointer<Int>,
1111
upi: UnsafePointer<Int>,
1212
umps: UnsafeMutablePointer<String>,
@@ -31,27 +31,24 @@ func unsafePointerConversionAvailability(
3131
_ = UnsafeRawPointer(umps)
3232
_ = UnsafeRawPointer(ups)
3333

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 {{}}
38-
_ = UnsafeMutablePointer<Void>(umpv)
39-
_ = UnsafeMutablePointer<Void>(upv) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
40-
_ = UnsafeMutablePointer<Void>(umpi)
41-
_ = UnsafeMutablePointer<Void>(upi) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
42-
_ = UnsafeMutablePointer<Void>(umps)
43-
_ = UnsafeMutablePointer<Void>(ups) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
34+
_ = UnsafeMutablePointer<Void>(rp) // expected-warning 3 {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}} 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 {{}}
35+
_ = UnsafeMutablePointer<Void>(mrp) // expected-warning 3 {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}} 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 {{}}
36+
_ = UnsafeMutablePointer<Void>(umpv) // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
37+
_ = UnsafeMutablePointer<Void>(upv) // expected-error {{'init' has been renamed to 'init(mutating:)'}} expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
38+
_ = UnsafeMutablePointer<Void>(umpi) // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
39+
_ = UnsafeMutablePointer<Void>(upi) // expected-error {{'init' has been renamed to 'init(mutating:)'}} expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
40+
_ = UnsafeMutablePointer<Void>(umps) // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
41+
_ = UnsafeMutablePointer<Void>(ups) // expected-error {{'init' has been renamed to 'init(mutating:)'}} expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
4442

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)
50-
_ = UnsafePointer<Void>(upv)
51-
_ = UnsafePointer<Void>(umpi)
52-
_ = UnsafePointer<Void>(upi)
53-
_ = UnsafePointer<Void>(umps)
54-
_ = UnsafePointer<Void>(ups)
43+
44+
_ = 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 {{}} expected-warning 3 {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
45+
_ = 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 {{}} expected-warning 3 {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
46+
_ = UnsafePointer<Void>(umpv) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
47+
_ = UnsafePointer<Void>(upv) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
48+
_ = UnsafePointer<Void>(umpi) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
49+
_ = UnsafePointer<Void>(upi) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
50+
_ = UnsafePointer<Void>(umps) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
51+
_ = UnsafePointer<Void>(ups) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
5552

5653
_ = 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 {{}}
5754
_ = 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 {{}}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %target-swift-frontend -emit-silgen -verify -parse-as-library %s
22

3-
func foo(x: UnsafeMutablePointer<UnsafeMutablePointer<()>?>) {
3+
func foo(x: UnsafeMutablePointer<UnsafeMutablePointer<()>?>) { // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
44
_ = x.pointee?.pointee
55
_ = x.pointee.map { type(of: $0) }
66
}

test/type/types.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,5 +159,13 @@ class r21949448 {
159159
// SE-0066 - Standardize function type argument syntax to require parentheses
160160
let _ : Int -> Float // expected-error {{single argument function types require parentheses}} {{9-9=(}} {{12-12=)}}
161161

162-
163-
162+
func foo1(a : UnsafePointer<Void>) {} // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}{{15-34=UnsafeRawPointer}}
163+
func foo2(a : UnsafeMutablePointer<()>) {} // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}{{15-39=UnsafeMutableRawPointer}}
164+
class C {
165+
func foo1(a : UnsafePointer<Void>) {} // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}{{17-36=UnsafeRawPointer}}
166+
func foo2(a : UnsafeMutablePointer<()>) {} // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}{{17-41=UnsafeMutableRawPointer}}
167+
func foo3() {
168+
let _ : UnsafePointer<Void> // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}{{13-32=UnsafeRawPointer}}
169+
let _ : UnsafeMutablePointer<Void> // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}{{13-39=UnsafeMutableRawPointer}}
170+
}
171+
}

0 commit comments

Comments
 (0)