Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[do not merge] [stdlib] Improved pointers #11464

Closed
wants to merge 0 commits into from
Closed

[do not merge] [stdlib] Improved pointers #11464

wants to merge 0 commits into from

Conversation

tayloraswift
Copy link
Member

@harlanhaskins harlanhaskins requested review from atrick and airspeedswift and removed request for atrick August 16, 2017 17:12
Copy link
Contributor

@CodaFi CodaFi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking this for visibility:

Throughout this diff there's a bunch of little whitespace changes. As a general policy, we like to have diffs as clean as possible. Could you go through and scrub the whitespace changes?

@tayloraswift
Copy link
Member Author

oh that was Atom whenever it saves a file it strips the trailing whitespace i’ll see if i can fix that

Copy link
Collaborator

@xwu xwu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excited about these improvements! I've left some style notes below.


@inline(__always)
public
func _copyContents( buffer: UnsafeMutableBufferPointer<Element>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and elsewhere, can you make sure to follow prevailing stdlib convention, specifically:

  • Place access modifiers on the same line as func
  • Use no space after the opening parenthesis
  • Use no space before colon and one space after colon (unless stating conformances or inheritance, in which case use one space before and after)
  • Use two-space tabs and 80-character columns
  • Place braces on the same line as else, for, etc. (including on the same line as the function return type); place else on the same line as guard
  • Use no spaces before and after ..<

(tailStart + (growth &<< elementShift)).copyBytes(
from: tailStart, count: tailCount &<< elementShift)
(tailStart + (growth &<< elementShift)).copy(
from: tailStart, bytes: tailCount &<< elementShift)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and below, please restore the original spacing, which indents two spaces when breaking after an opening parenthesis.

public
init(_ other:UnsafeMutableBufferPointer<Element>)
{
self._position = UnsafePointer<Element>(other._position)
Copy link
Collaborator

@xwu xwu Aug 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and below, please follow prevailing style as discussed above; besides the style notes already mentioned (public on same line as init, space after :, { on same line as arguments), set internal members without prefixing self and do not align _end = with spaces.

% end # !mutable

% if Mutable:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this be simply % else: after eliminating the % end above?

{
let size = MemoryLayout<Element>.stride * capacity
let raw = Builtin.allocRaw(size._builtinWordValue, Builtin.alignof(Element.self))
Builtin.bindMemory(raw, capacity._builtinWordValue, Element.self)
Copy link
Collaborator

@xwu xwu Aug 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides other style notes already mentioned above (including not using additional spaces in raw =), please indent only two spaces here.

let size = MemoryLayout<Element>.stride * capacity
let raw = Builtin.allocRaw(size._builtinWordValue, Builtin.alignof(Element.self))
Builtin.bindMemory(raw, capacity._builtinWordValue, Element.self)
return UnsafeMutableBufferPointer(start: UnsafeMutablePointer(raw),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, stdlib style is to line-break after the opening parenthesis and increase indent by two spaces on the next line.

count: capacity)
}

// this is more efficient than the generic Sequence-based implementation
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In comments, stdlib style is to capitalize and punctuate like a sentence.

public
func assign(from source:UnsafeBufferPointer<Element>)
{
_debugPrecondition(source.count >= self.count,
Copy link
Collaborator

@xwu xwu Aug 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto here about stdlib style and parentheses; I'll not repeat earlier comments about the styling of guard...else statements, which also apply here.

public
func initialize(repeating repeatedValue:Element)
{
guard let dst_start:UnsafeMutablePointer<Element> = self._position
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where type annotations are not necessary, stdlib style is to leave them off. Also, stdlib style is for camel-casing even local variables (i.e. dstStart).

@atrick
Copy link
Contributor

atrick commented Aug 19, 2017

I know, the whitespace thing is terribly annoying! I used to open/close a file to fix the whitespace then commit that separately before editing the file. Pure whitespace changes are also discouraged in Swift, but it's probably fine if it's limited to a file that you're already making large changes to.


@_inlineable
public
func deinitialize()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a scary warning comment to UnsafeMutableBufferPointer.deinitialize(). Something like:

Warning: All buffer elements must be initialized before calling this. Note that invoking initialize(from:) may not initialize all elements. Deinitializing part of the buffer must be done using the UnsafeMutablePointer API: baseAddress.deinitialize(count: n)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@tayloraswift
Copy link
Member Author

I found out how to disable whitespace stripping in Atom but I have no idea how to restore the whitespace that was already there before Atom stripped it since it’s all mixed with the actual changes.

@CodaFi
Copy link
Contributor

CodaFi commented Aug 19, 2017

For the files with whitespace only changes git checkout master path/to/file will reset them. For the files with actual code changes you may have to do it by hand

@tayloraswift
Copy link
Member Author

i only saved files i made changes to, which was about 20 or so because of function and argument renaming to make the tests compile

@tayloraswift
Copy link
Member Author

does it look better?

public func _copyContents(
buffer: UnsafeMutableBufferPointer<Element>,
_ operation: (UnsafeMutablePointer<Element>, Element) -> ())
-> (Iterator, UnsafeMutableBufferPointer<Element>.Index) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more stdlib-specific style note: the prevailing convention is to put the closing parenthesis, deindented, next to the return arrow: ) ->.

where S.Element == Element {
@discardableResult
public func initialize<S>(from source: S) -> (S.Iterator, Index)
where S:Sequence, S.Element == Element {
Copy link
Collaborator

@xwu xwu Aug 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: missing spaces here (and below); should be S : Sequence.

_debugPrecondition(source.count >= count,
"${Self}.moveAssign(from:) source does not have enough elements")
guard let dstStart = _position,
let srcStart = source._position else {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think this now all fits on one line :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a stdlib convention for this? my own convention is to always put guard and if comma statements on their own lines

Copy link
Collaborator

@xwu xwu Aug 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the stdlib, if the whole thing fits in 80 characters, you'll see everything in one line:

guard let foo = _foo, let bar = _bar else { return }

(Which is not to say, of course, that your style is inferior in any way.)

@_inlineable
public
func withMemoryRebound<T, Result>(
to type: T.Type, _ body: (${Self}<T>) throws -> Result) rethrows -> Result {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: This one's tricky, but public func should be one line, then probably to balance out the opening (, you could line break and deindent before )--although I'm not sure about this one; check elsewhere in the codebase.

Below, where you've got body(${Self}<T>( and count: on a separate line, line return after the opening parenthesis and indent two spaces, then put everything else on that line.

/// a buffer can have a `count` of zero even with a non-`nil` base address.
@_inlineable
public var count: Int {
switch(_position, _end) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nits: space after switch; default instead of case _ (which isn't used in stdlib unless i'm mistaken).

More generally, though, isn't this more idiomatically just:

guard let position = _position, let end = _end else { return 0 }
return end - position

Copy link
Member Author

@tayloraswift tayloraswift Aug 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don’t think i ever touched this part of the code, the diff is probably because a method near it got moved

Copy link
Collaborator

@xwu xwu Aug 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair; since the diff now points to you, it could still stand a little stylistic tidying though :)

}

@_versioned
let _position, _end: Unsafe${Mutable}Pointer<Element>?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: I believe stdlib always explicitly marks internal members as internal.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, wasn’t me

Copy link
Collaborator

@xwu xwu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more style nits (sorry!).

/// A textual representation of the buffer, suitable for debugging.
public var debugDescription: String {
return "Unsafe${Mutable}BufferPointer"
+ "(start: \(_position.map(String.init(describing:)) ?? "nil"), count: \(count))"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good place for a multiline string literal?

Copy link
Member Author

@tayloraswift tayloraswift Aug 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, wasn’t me
(also i never did learn how to use those things after the argument over trailing newlines after \ went south lol)

public static func allocate(
bytes size: Int, alignedTo: Int
) -> UnsafeMutableRawPointer {
public static func allocate(bytes: Int, alignedTo alignment: Int)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the original line breaking here was consistent with prevailing stdlib convention.

public func bindMemory<T>(
to type: T.Type, capacity count: Int
) -> Unsafe${Mutable}Pointer<T> {
public func bindMemory<T>(to type: T.Type, capacity count: Int = 1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: ditto here.

@@ -835,6 +838,10 @@ public struct Unsafe${Mutable}RawPointer : Strideable, Hashable, _Pointer {
}
}

@available(*, unavailable, renamed: "copy(from:bytes:)")
public func copyBytes(from source: UnsafeRawPointer, count: Int)
{ fatalError("unreachable") }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: move { to previous line and } into a separate line.

Copy link
Member Author

@tayloraswift tayloraswift Aug 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i thought mini blocks weren’t to be formatted like “real” function bodies, like a.map{ $0.foo } instead of

a.map {
    $0.foo 
}

Copy link
Collaborator

@xwu xwu Aug 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All function bodies have the following format (unless it all fits in 80 characters):

public func foo() {
  fatalError()
}

See: https://github.com/apple/swift/blob/f6f3ed0fe7e3c0d8d6af85bb238e039041ac0d42/validation-test/stdlib/CollectionDiagnostics.swift#L15

) -> UnsafeMutablePointer<T> {
public func initializeMemory<T>(
as type: T.Type, at index:Int = 0, repeating repeatedValue:T, count: Int = 1)
-> UnsafeMutablePointer<T> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: as before, ) -> is the prevailing style.

as type: T.Type, from source: UnsafePointer<T>, count: Int
) -> UnsafeMutablePointer<T> {
as type: T.Type, from source: UnsafePointer<T>, count: Int = 1)
-> UnsafeMutablePointer<T> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: ditto here.

as type: T.Type, from source: UnsafeMutablePointer<T>, count: Int
) -> UnsafeMutablePointer<T> {
as type: T.Type, from source: UnsafeMutablePointer<T>, count: Int = 1)
-> UnsafeMutablePointer<T> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and here.

Copy link
Member

@natecook1000 natecook1000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking great! I've added a few notes about where we need to make sure we're keeping documentation in line with the changes.

@@ -429,6 +429,11 @@ public struct ${Self}<Pointee>
return UnsafeMutablePointer(rawPtr)
}

@available(*, unavailable, message: "Swift currently only supports freeing entire heap blocks, use deallocate() instead")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using unavailable in these changes will break existing code. Should this be something like @available(swift, deprecated: 4.1, obsoleted: 5, message: "...")? Do we have the machinery in place for those versions yet?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as explained in the proposal we are preferring a hard unavailable over a soft deprecation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that, but using unavailable causes source breakage of Swift 4 code, not just code that is migrated to Swift 5.

@@ -488,14 +494,14 @@ public struct ${Self}<Pointee>
/// - count: The number of consecutive copies of `newValue` to initialize.
/// `count` must not be negative. The default is `1`.
@_inlineable
public func initialize(to newValue: Pointee, count: Int = 1) {
public func initialize(repeating repeatedValue: Pointee, count: Int = 1) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update docs when the API changes—in this case, the name of the method is now intialize(repeating:count) and the first parameter name has changed from newValue to repeatedValue.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking care of these!

public func assign(from source: UnsafePointer<Pointee>, count: Int) {
_debugPrecondition(
count >= 0, "${Self}.assign with negative count")
public func assign(from source: UnsafePointer<Pointee>, count: Int = 1) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default parameter values need to be specified in the docs for the parameter: "The default value is 1". Noted here and 4–5 other places below.

Copy link
Member Author

@tayloraswift tayloraswift Aug 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

% end # !mutable

@_inlineable
public init(_ other: UnsafeMutableBufferPointer<Element>) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure any new public APIs have documentation before this gets merged—thanks!

@gottesmm
Copy link
Contributor

@Kelvin13 Please make sure to rebase the branch on master before merging!

@tayloraswift
Copy link
Member Author

The implementation is now up to speed with the latest version of the draft proposal

@natecook1000 natecook1000 changed the title Improved pointers (do not merge) [do not merge] [stdlib] Improved pointers Aug 26, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants