-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
Conversation
There was a problem hiding this 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?
oh that was Atom whenever it saves a file it strips the trailing whitespace i’ll see if i can fix that |
There was a problem hiding this 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.
stdlib/public/core/Sequence.swift
Outdated
|
||
@inline(__always) | ||
public | ||
func _copyContents( buffer: UnsafeMutableBufferPointer<Element>, |
There was a problem hiding this comment.
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); placeelse
on the same line asguard
- Use no spaces before and after
..<
stdlib/public/core/StringCore.swift
Outdated
(tailStart + (growth &<< elementShift)).copyBytes( | ||
from: tailStart, count: tailCount &<< elementShift) | ||
(tailStart + (growth &<< elementShift)).copy( | ||
from: tailStart, bytes: tailCount &<< elementShift) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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), |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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
).
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() |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
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. |
For the files with whitespace only changes |
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 |
does it look better? |
stdlib/public/core/Sequence.swift
Outdated
public func _copyContents( | ||
buffer: UnsafeMutableBufferPointer<Element>, | ||
_ operation: (UnsafeMutablePointer<Element>, Element) -> ()) | ||
-> (Iterator, UnsafeMutableBufferPointer<Element>.Index) { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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>? |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again, wasn’t me
There was a problem hiding this 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))" |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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") } |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
}
There was a problem hiding this comment.
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()
}
) -> UnsafeMutablePointer<T> { | ||
public func initializeMemory<T>( | ||
as type: T.Type, at index:Int = 0, repeating repeatedValue:T, count: Int = 1) | ||
-> UnsafeMutablePointer<T> { |
There was a problem hiding this comment.
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> { |
There was a problem hiding this comment.
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> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...and here.
There was a problem hiding this 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") |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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>) { |
There was a problem hiding this comment.
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!
@Kelvin13 Please make sure to rebase the branch on master before merging! |
The implementation is now up to speed with the latest version of the draft proposal |
Implementation of SE-184