Skip to content

Commit 41dd243

Browse files
committed
Add some availability attributes for UnsafePointer conversion.
This introduces some important diagnostics to help migration. Some of the diagnostics that we would like to provide are impossible on a generic class because they introduce ambiguity. Renaming UnsafePointer<Void> to UnsafeRawPointer makes extensions and global operators ambiguous. We would also like to provide this fix-it on conversion from UnsafePointer<Void> or UnsafeRawPointer to UnsafePointer<T> with this message: Conversion restricted. Use 'assumingMemoryBound(to:)' or 'bindMemory(to:capacity:)'}} However, that introduces ambiguous overloads that defeat other diagnostics.
1 parent 977e687 commit 41dd243

File tree

5 files changed

+120
-2
lines changed

5 files changed

+120
-2
lines changed

stdlib/public/core/Integers.swift.gyb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ extension BinaryInteger {
230230
public init?<T : FloatingPoint>(exactly source: T) {
231231
// FIXME(integers): implement
232232
fatalError()
233+
return nil
233234
}
234235

235236
public init<T : FloatingPoint>(_ source: T) {

stdlib/public/core/UnsafePointer.swift.gyb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,30 @@ public func -= <Pointee>(lhs: inout ${Self}<Pointee>, rhs: Int) {
517517
}
518518

519519
extension ${Self} {
520+
@available(*, unavailable, message:
521+
"use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.")
522+
public init<U>(_ from : UnsafeMutablePointer<U>) { Builtin.unreachable() }
523+
524+
@available(*, unavailable, message:
525+
"use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.")
526+
public init?<U>(_ from : UnsafeMutablePointer<U>?) { Builtin.unreachable(); return nil }
527+
528+
@available(*, unavailable, message:
529+
"use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.")
530+
public init<U>(_ from : UnsafePointer<U>) { Builtin.unreachable() }
531+
532+
@available(*, unavailable, message:
533+
"use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.")
534+
public init?<U>(_ from : UnsafePointer<U>?) { Builtin.unreachable(); return nil }
535+
536+
% if mutable:
537+
@available(*, unavailable, renamed: "init(mutating:)")
538+
public init(_ from : UnsafePointer<Pointee>) { Builtin.unreachable() }
539+
540+
@available(*, unavailable, renamed: "init(mutating:)")
541+
public init?(_ from : UnsafePointer<Pointee>?) { Builtin.unreachable(); return nil }
542+
% end
543+
520544
@available(*, unavailable, renamed: "Pointee")
521545
public typealias Memory = Pointee
522546

stdlib/public/core/UnsafeRawPointer.swift.gyb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,3 +549,16 @@ extension UInt {
549549

550550
% end # for mutable
551551

552+
extension UnsafeMutableRawPointer {
553+
@available(*, unavailable, renamed: "init(mutating:)")
554+
public init(_ from : UnsafeRawPointer) { Builtin.unreachable() }
555+
556+
@available(*, unavailable, renamed: "init(mutating:)")
557+
public init?(_ from : UnsafeRawPointer?) { Builtin.unreachable(); return nil }
558+
559+
@available(*, unavailable, renamed: "init(mutating:)")
560+
public init<T>(_ from : UnsafePointer<T>) { Builtin.unreachable() }
561+
562+
@available(*, unavailable, renamed: "init(mutating:)")
563+
public init?<T>(_ from : UnsafePointer<T>?) { Builtin.unreachable(); return nil }
564+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// RUN: %target-parse-verify-swift
2+
3+
// Test availability attributes on UnsafePointer initializers.
4+
// 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
9+
func unsafePointerConversionAvailability(
10+
mrp: UnsafeMutableRawPointer,
11+
rp: UnsafeRawPointer,
12+
umpv: UnsafeMutablePointer<Void>,
13+
upv: UnsafePointer<Void>,
14+
umpi: UnsafeMutablePointer<Int>,
15+
upi: UnsafePointer<Int>,
16+
umps: UnsafeMutablePointer<String>,
17+
ups: UnsafePointer<String>) {
18+
19+
_ = UnsafeMutableRawPointer(mrp)
20+
_ = UnsafeMutableRawPointer(rp) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
21+
_ = UnsafeMutableRawPointer(umpv)
22+
_ = UnsafeMutableRawPointer(upv) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
23+
_ = UnsafeMutableRawPointer(umpi)
24+
_ = UnsafeMutableRawPointer(upi) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
25+
_ = UnsafeMutableRawPointer(umps)
26+
_ = UnsafeMutableRawPointer(ups) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
27+
28+
// These all correctly pass with no error.
29+
_ = UnsafeRawPointer(mrp)
30+
_ = UnsafeRawPointer(rp)
31+
_ = UnsafeRawPointer(umpv)
32+
_ = UnsafeRawPointer(upv)
33+
_ = UnsafeRawPointer(umpi)
34+
_ = UnsafeRawPointer(upi)
35+
_ = UnsafeRawPointer(umps)
36+
_ = UnsafeRawPointer(ups)
37+
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 {{}}
42+
_ = UnsafeMutablePointer<Void>(umpv)
43+
_ = UnsafeMutablePointer<Void>(upv) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
44+
_ = UnsafeMutablePointer<Void>(umpi)
45+
_ = UnsafeMutablePointer<Void>(upi) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
46+
_ = UnsafeMutablePointer<Void>(umps)
47+
_ = UnsafeMutablePointer<Void>(ups) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
48+
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)
54+
_ = UnsafePointer<Void>(upv)
55+
_ = UnsafePointer<Void>(umpi)
56+
_ = UnsafePointer<Void>(upi)
57+
_ = UnsafePointer<Void>(umps)
58+
_ = UnsafePointer<Void>(ups)
59+
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 {{}}
65+
_ = UnsafeMutablePointer<Int>(umpv) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
66+
_ = UnsafeMutablePointer<Int>(upv) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
67+
_ = UnsafeMutablePointer<Int>(umpi)
68+
_ = UnsafeMutablePointer<Int>(upi) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
69+
_ = UnsafeMutablePointer<Int>(umps) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
70+
_ = UnsafeMutablePointer<Int>(ups) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
71+
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 {{}}
74+
_ = UnsafePointer<Int>(umpv) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
75+
_ = UnsafePointer<Int>(upv) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
76+
_ = UnsafePointer<Int>(umpi)
77+
_ = UnsafePointer<Int>(upi)
78+
_ = UnsafePointer<Int>(umps) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
79+
_ = UnsafePointer<Int>(ups) // expected-error {{'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.}}
80+
}

test/Sema/diag_init.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %target-parse-verify-swift
22

33
func foo(a : UnsafePointer<Void>)->UnsafeMutablePointer<Void> {
4-
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>?)}}
5-
}
4+
return UnsafeMutablePointer(a) // expected-error {{'init' has been renamed to 'init(mutating:)'}}
5+
}

0 commit comments

Comments
 (0)