Skip to content

[string] Internalize many faux-testable declarations #18456

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

Merged
merged 3 commits into from
Aug 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions stdlib/public/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,14 @@ set(SWIFTLIB_ESSENTIAL
StringObject.swift
StringProtocol.swift
StringIndex.swift
StringIndexConversions.swift
StringInterpolation.swift
StringLegacy.swift
StringNormalization.swift
StringRangeReplaceableCollection.swift
StringStorage.swift
StringSwitch.swift
StringIndexConversions.swift
StringNormalization.swift
StringTesting.swift
StringUnicodeScalarView.swift
StringUTF16View.swift
StringUTF8View.swift
Expand Down
1 change: 1 addition & 0 deletions stdlib/public/core/GroupInfo.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"StringRangeReplaceableCollection.swift",
"StringStorage.swift",
"StringSwitch.swift",
"StringTesting.swift",
"StringUTF16View.swift",
"StringUTF8View.swift",
"StringUnicodeScalarView.swift",
Expand Down
14 changes: 6 additions & 8 deletions stdlib/public/core/SmallString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ func unsupportedOn32bit() -> Never { _conditionallyUnreachable() }

#else
@_fixed_layout
public // @testable
struct _SmallUTF8String {
@usableFromInline
internal struct _SmallUTF8String {
@usableFromInline
typealias _RawBitPattern = (low: UInt, high: UInt)

Expand Down Expand Up @@ -61,12 +61,11 @@ struct _SmallUTF8String {
//
extension _SmallUTF8String {
@inlinable
public // @testable
static var capacity: Int { return 15 }
static internal var capacity: Int { return 15 }

#if _runtime(_ObjC)
public // @testable
init?(_cocoaString cocoa: _CocoaString) {
@usableFromInline
internal init?(_cocoaString cocoa: _CocoaString) {
#if arch(i386) || arch(arm)
return nil // Never form small strings on 32-bit
#else
Expand All @@ -89,8 +88,7 @@ extension _SmallUTF8String {
#endif // _runtime(_ObjC)

@inlinable
public // @testable
init?<C: RandomAccessCollection>(_ codeUnits: C) where C.Element == UInt16 {
internal init?<C: RandomAccessCollection>(_ codeUnits: C) where C.Element == UInt16 {
#if arch(i386) || arch(arm)
return nil // Never form small strings on 32-bit
#else
Expand Down
6 changes: 3 additions & 3 deletions stdlib/public/core/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,8 @@ extension String {
/// [equivalence]: http://www.unicode.org/glossary/#canonical_equivalent
@_fixed_layout
public struct String {
public var _guts: _StringGuts
public // SPI(Foundation)
var _guts: _StringGuts

/// Creates an empty string.
///
Expand All @@ -555,8 +556,7 @@ public struct String {
}

@inlinable // FIXME(sil-serialize-all)
public // @testable
init(_ _guts: _StringGuts) {
internal init(_ _guts: _StringGuts) {
self._guts = _guts
}
}
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/StringBridge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ internal func _bridgeASCIICocoaString(
return length == numCharWritten ? count : nil
}

public // @testable
func _bridgeToCocoa(_ small: _SmallUTF8String) -> _CocoaString {
@usableFromInline
internal func _bridgeToCocoa(_ small: _SmallUTF8String) -> _CocoaString {
return small.withUTF8CodeUnits { bufPtr in
return _swift_stdlib_CFStringCreateWithBytes(
nil, bufPtr.baseAddress._unsafelyUnwrappedUnchecked,
Expand Down
45 changes: 15 additions & 30 deletions stdlib/public/core/StringGuts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ extension _StringGuts {

@inlinable
@inline(__always)
public // @testable
mutating func _isUniqueNative() -> Bool {
internal mutating func _isUniqueNative() -> Bool {
guard _isNative else { return false }
// Note that the isUnique test must be in a separate statement;
// `isNative && _isUnique` always evaluates to false in debug builds,
Expand All @@ -121,8 +120,7 @@ extension _StringGuts {

extension _StringGuts {
@inlinable
public // @testable
var isASCII: Bool {
internal var isASCII: Bool {
@inline(__always) get { return _object.isContiguousASCII }
}

Expand All @@ -135,40 +133,32 @@ extension _StringGuts {
}

@inlinable
public // @testable
var _isNative: Bool {
internal var _isNative: Bool {
return _object.isNative
}

#if _runtime(_ObjC)
@inlinable
public // @testable
var _isCocoa: Bool {
internal var _isCocoa: Bool {
return _object.isCocoa
}
#endif

@inlinable
public // @testable
var _isUnmanaged: Bool {
internal var _isUnmanaged: Bool {
return _object.isUnmanaged
}

@inlinable
public // @testable
var _isSmall: Bool {
internal var _isSmall: Bool {
return _object.isSmall
}

@inlinable
public // @testable
var _owner: AnyObject? {
internal var _owner: AnyObject? {
return _object.owner
}

@inlinable
public // @testable
var isSingleByte: Bool {
internal var isSingleByte: Bool {
// FIXME: Currently used to sometimes mean contiguous ASCII
return _object.isSingleByte
}
Expand All @@ -180,8 +170,7 @@ extension _StringGuts {
}

@inlinable
public // @testable
var byteWidth: Int {
internal var byteWidth: Int {
return _object.byteWidth
}

Expand Down Expand Up @@ -215,8 +204,7 @@ extension _StringGuts {
extension _StringGuts {
@inlinable
@inline(__always)
public // @testable
init() {
internal init() {
self.init(object: _StringObject(), otherBits: 0)
_invariantCheck()
}
Expand Down Expand Up @@ -474,8 +462,8 @@ extension _StringGuts {
/// Return the object identifier for the reference counted heap object
/// referred to by this string (if any). This is useful for testing allocation
/// behavior.
public // @testable
var _objectIdentifier: ObjectIdentifier? {
@usableFromInline
internal var _objectIdentifier: ObjectIdentifier? {
if _object.isNative {
return ObjectIdentifier(_object.nativeRawStorage)
}
Expand Down Expand Up @@ -793,8 +781,7 @@ extension _StringGuts {
}

@inlinable
public // @testable
var count: Int {
internal var count: Int {
if _slowPath(!_hasStoredCount) {
return _nonStoredCount
}
Expand Down Expand Up @@ -823,8 +810,7 @@ extension _StringGuts {
}

@inlinable
public // @testable
var capacity: Int {
internal var capacity: Int {
if _fastPath(_object.isNative) {
return _object.nativeRawStorage.capacity
}
Expand All @@ -839,8 +825,7 @@ extension _StringGuts {

/// Get the UTF-16 code unit stored at the specified position in this string.
@inlinable // FIXME(sil-serialize-all)
public // @testable
subscript(position: Int) -> UTF16.CodeUnit {
internal subscript(position: Int) -> UTF16.CodeUnit {
if _slowPath(_isOpaque) {
return _opaquePosition(position)
}
Expand Down
66 changes: 66 additions & 0 deletions stdlib/public/core/StringTesting.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

// Declarations to enable ease-of-testing

public // @testable
struct _StringRepresentation {
public var _isASCII: Bool
public var _count: Int
public var _capacity: Int

public enum _Form {
case _small
case _cocoa(object: AnyObject)
case _native(object: AnyObject)
case _immortal(address: UInt)
}
public var _form: _Form

public var _objectIdentifier: ObjectIdentifier? {
switch _form {
case ._cocoa(let object): return ObjectIdentifier(object)
case ._native(let object): return ObjectIdentifier(object)
default: return nil
}
}
}

extension String {
public // @testable
func _classify() -> _StringRepresentation {
var result = _StringRepresentation(
_isASCII: _guts._isASCIIOrSmallASCII,
_count: _guts.count,
_capacity: _guts.capacity,
_form: ._small
)
if _guts._isSmall {
return result
}
if _guts._isNative {
result._form = ._native(object: _guts._owner!)
return result
}
if _guts._isCocoa {
result._form = ._cocoa(object: _guts._owner!)
return result
}
if _guts._isUnmanaged {
result._form = ._immortal(
address: UInt(bitPattern: _guts._unmanagedRawStart))
return result
}
fatalError()
}
}

6 changes: 5 additions & 1 deletion test/stdlib/BridgedObjectDebuggerSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ func debugVal<T>(_ x: inout T) -> String {

// Check if @x uses the small-string or Cocoa representations.
func hasSmallStringOrCocoaVariant(_ x: String) -> Bool {
return x._guts._isCocoa || x._guts._isSmall
switch x._classify()._form {
case ._small: return true
case ._cocoa: return true
default: return false
}
}

StringForPrintObjectTests.test("Basic") {
Expand Down
3 changes: 2 additions & 1 deletion test/stdlib/Character.swift
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,9 @@ func checkUnicodeScalars(_ s: String) {
}

func checkRepresentation(_ s: String) {
let utf16 = Array(s.utf16)
let expectSmall
= s.utf16.count < 4 || s.utf16.count == 4 && s._guts[3] < 0x8000
= utf16.count < 4 || utf16.count == 4 && utf16[3] < 0x8000
let isSmall = isSmallRepresentation(s)

let expectedSize = expectSmall ? "small" : "large"
Expand Down
Loading