Rebinding UnsafePointer makes it mutable


(Martin R) #1

I noticed that both UnsafePointer and UnsafeMutablePointer have the identical method

    public func withMemoryRebound<T, Result>(to: T.Type, capacity count: Int, _ body: (UnsafeMutablePointer<T>) throws -> Result) rethrows -> Result

so that rebinding an immutable pointer gives you a _mutable_ pointer. That is different from what

    Unsafe[Mutable]Pointer<Pointee> {
      func withMemoryRebound<T>(to: T.Type, capacity count: Int,
        _ body: (Unsafe[Mutable]Pointer<T>) throws -> ()) rethrows
    }

in https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md indicates. Perhaps I am misunderstanding something. Shouldn't rebinding an UnsafePointer result in an UnsafePointer again?

Martin


(Andrew Trick) #2

I think you’re right about that. I didn’t notice the discrepancy until source breaking changes were frozen and was concerned that fixing it would be more restrictive.

Some users may migrate their code to:

constPtr.withMemoryRebound(to: T.self, capacity: 1) {
takesMutablePointer($0)
}

We probably want them to be more explicit:

constPtr.withMemoryRebound(to: T.self, capacity: 1) {
takesMutablePointer(UnsafeMutablePointer(mutating: $0))
}

We could possibly justify correcting this in Swift 3 though on these grounds:

- It’s effectively a bug considering that the proposal and implementation are inconsistent.
- There is a correct way write the code that will continue to work before and after fixing the bug.
- A simple fixit will tell them to add the “mutating” label.

If not, it’s something I was already planning to roll into Swift 4.

-Andy

···

On Sep 19, 2016, at 1:24 AM, Martin R via swift-dev <swift-dev@swift.org> wrote:

I noticed that both UnsafePointer and UnsafeMutablePointer have the identical method

   public func withMemoryRebound<T, Result>(to: T.Type, capacity count: Int, _ body: (UnsafeMutablePointer<T>) throws -> Result) rethrows -> Result

so that rebinding an immutable pointer gives you a _mutable_ pointer. That is different from what

   Unsafe[Mutable]Pointer<Pointee> {
     func withMemoryRebound<T>(to: T.Type, capacity count: Int,
       _ body: (Unsafe[Mutable]Pointer<T>) throws -> ()) rethrows
   }

in https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md indicates. Perhaps I am misunderstanding something. Shouldn't rebinding an UnsafePointer result in an UnsafePointer again?

Martin


(Andrew Trick) #3

You’re right. There is an inconsistency between the proposal and Swift 3 implementation. I’ve been thinking about whether it makes more sense to correct this sooner or later. I responded in more detail on swift-evolution.

-Andy

···

On Sep 19, 2016, at 1:24 AM, Martin R via swift-dev <swift-dev@swift.org> wrote:

I noticed that both UnsafePointer and UnsafeMutablePointer have the identical method

   public func withMemoryRebound<T, Result>(to: T.Type, capacity count: Int, _ body: (UnsafeMutablePointer<T>) throws -> Result) rethrows -> Result

so that rebinding an immutable pointer gives you a _mutable_ pointer. That is different from what

   Unsafe[Mutable]Pointer<Pointee> {
     func withMemoryRebound<T>(to: T.Type, capacity count: Int,
       _ body: (Unsafe[Mutable]Pointer<T>) throws -> ()) rethrows
   }

in https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md indicates. Perhaps I am misunderstanding something. Shouldn't rebinding an UnsafePointer result in an UnsafePointer again?

Martin


(Dave Abrahams) #4

I noticed that both UnsafePointer and UnsafeMutablePointer have the identical method

   public func withMemoryRebound<T, Result>(to: T.Type, capacity count: Int, _ body: (UnsafeMutablePointer<T>) throws -> Result) rethrows -> Result

so that rebinding an immutable pointer gives you a _mutable_ pointer. That is different from what

   Unsafe[Mutable]Pointer<Pointee> {
     func withMemoryRebound<T>(to: T.Type, capacity count: Int,
       _ body: (Unsafe[Mutable]Pointer<T>) throws -> ()) rethrows
   }

in https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md indicates. Perhaps I am misunderstanding something. Shouldn't rebinding an UnsafePointer result in an UnsafePointer again?

Martin

I think you’re right about that. I didn’t notice the discrepancy until
source breaking changes were frozen and was concerned that fixing it
would be more restrictive.

Some users may migrate their code to:

constPtr.withMemoryRebound(to: T.self, capacity: 1) {
takesMutablePointer($0)
}

We probably want them to be more explicit:

constPtr.withMemoryRebound(to: T.self, capacity: 1) {
takesMutablePointer(UnsafeMutablePointer(mutating: $0))
}

We could possibly justify correcting this in Swift 3 though on these grounds:

- It’s effectively a bug considering that the proposal and
implementation are inconsistent.

It's definitely a bug, IMO.

···

on Mon Sep 19 2016, Andrew Trick <swift-evolution@swift.org> wrote:

On Sep 19, 2016, at 1:24 AM, Martin R via swift-dev <swift-dev@swift.org> wrote:

- There is a correct way write the code that will continue to work
before and after fixing the bug.
- A simple fixit will tell them to add the “mutating” label.

If not, it’s something I was already planning to roll into Swift 4.

-Andy

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
-Dave


(Andrew Trick) #5

If there’s no objection, I’ll just go ahead with a fix on the 3.0 branch since it was already covered by SE-0107.
-Andy

···

On Sep 19, 2016, at 11:44 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Mon Sep 19 2016, Andrew Trick <swift-evolution@swift.org> wrote:

On Sep 19, 2016, at 1:24 AM, Martin R via swift-dev <swift-dev@swift.org> wrote:

I noticed that both UnsafePointer and UnsafeMutablePointer have the identical method

  public func withMemoryRebound<T, Result>(to: T.Type, capacity count: Int, _ body: (UnsafeMutablePointer<T>) throws -> Result) rethrows -> Result

so that rebinding an immutable pointer gives you a _mutable_ pointer. That is different from what

  Unsafe[Mutable]Pointer<Pointee> {
    func withMemoryRebound<T>(to: T.Type, capacity count: Int,
      _ body: (Unsafe[Mutable]Pointer<T>) throws -> ()) rethrows
  }

in https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md indicates. Perhaps I am misunderstanding something. Shouldn't rebinding an UnsafePointer result in an UnsafePointer again?

Martin

I think you’re right about that. I didn’t notice the discrepancy until
source breaking changes were frozen and was concerned that fixing it
would be more restrictive.

Some users may migrate their code to:

constPtr.withMemoryRebound(to: T.self, capacity: 1) {
takesMutablePointer($0)
}

We probably want them to be more explicit:

constPtr.withMemoryRebound(to: T.self, capacity: 1) {
takesMutablePointer(UnsafeMutablePointer(mutating: $0))
}

We could possibly justify correcting this in Swift 3 though on these grounds:

- It’s effectively a bug considering that the proposal and
implementation are inconsistent.

It's definitely a bug, IMO.

- There is a correct way write the code that will continue to work
before and after fixing the bug.
- A simple fixit will tell them to add the “mutating” label.

If not, it’s something I was already planning to roll into Swift 4.