Skip to content

Commit e8541ca

Browse files
committed
[FixCode] Add a diagnosis/fixit to help users convert Unsafe[Mutable]Pointer<Void> to Unsafe[Mutable]RawPointer. rdar://27730408
1 parent 5b3a408 commit e8541ca

File tree

5 files changed

+62
-26
lines changed

5 files changed

+62
-26
lines changed

include/swift/AST/DiagnosticsSema.def

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

2199+
WARNING(use_of_void_pointer,none,
2200+
"Unsafe%0Pointer<Void> has been replaced by Unsafe%0RawPointer", (StringRef))
2201+
21992202
// Ambiguities
22002203
ERROR(ambiguous_decl_ref,none,
22012204
"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: 18 additions & 21 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 {{}}
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 {{}} expected-warning 3 {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
3735
_ = 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:)'}}
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)