Skip to content

Commit 4db3509

Browse files
author
Dave Abrahams
committed
[stdlib] A Character's buffer should only contain 1 grapheme
This speeds up construction of a String from large Character representations, and various other operations that would otherwise require additional grapheme breaking just to interpret the Character.
1 parent 91e46b2 commit 4db3509

File tree

3 files changed

+19
-12
lines changed

3 files changed

+19
-12
lines changed

stdlib/public/core/Character.swift

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,6 @@ public struct Character :
7676
// should be represented as such.
7777
@_versioned
7878
internal enum Representation {
79-
// A _StringBuffer whose first grapheme cluster is self.
80-
// NOTE: may be more than 1 Character long.
8179
case large(_StringBuffer._Storage)
8280
case small(Builtin.Int63)
8381
}
@@ -137,15 +135,16 @@ public struct Character :
137135
}
138136
// For anything that doesn't fit in 63 bits, build the large
139137
// representation.
140-
self = Character(_largeRepresentationString: String(
141-
_builtinExtendedGraphemeClusterLiteral: start,
142-
utf8CodeUnitCount: utf8CodeUnitCount,
143-
isASCII: isASCII))
138+
self = Character(_largeRepresentationString:
139+
String(
140+
_builtinExtendedGraphemeClusterLiteral: start,
141+
utf8CodeUnitCount: utf8CodeUnitCount,
142+
isASCII: isASCII))
144143
}
145144

146145
/// Creates a character with the specified value.
147146
///
148-
/// Do not call this initializer directly. It is used by the compiler when
147+
/// Do not call this initalizer directly. It is used by the compiler when
149148
/// you use a string literal to initialize a `Character` instance. For
150149
/// example:
151150
///
@@ -200,10 +199,14 @@ public struct Character :
200199

201200
/// Creates a Character from a String that is already known to require the
202201
/// large representation.
202+
///
203+
/// - Requires: s contains only a single grapheme
203204
@_versioned
204205
internal init(_largeRepresentationString s: String) {
206+
_sanityCheck(s.index(after: s.startIndex) == s.endIndex)
205207
if let native = s._core.nativeBuffer,
206-
native.start == s._core._baseAddress! {
208+
native.start == s._core._baseAddress!,
209+
native.usedCount == s._core.count {
207210
_representation = .large(native._storage)
208211
return
209212
}
@@ -399,8 +402,7 @@ extension String {
399402
self = String._fromWellFormedCodeUnitSequence(
400403
UTF8.self, input: smallUTF8)
401404
case let .large(value):
402-
let buf = String(_StringCore(_StringBuffer(value)))
403-
self = buf[buf.startIndex..<buf.index(after: buf.startIndex)]
405+
self = String(_StringCore(_StringBuffer(value)))
404406
}
405407
}
406408
}

validation-test/compiler_crashers_fixed/28666-conformingreplacementtype-is-substitutabletype-conformingreplacementtype-is-depe.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

88
// RUN: not %target-swift-frontend %s -emit-ir
9-
// XFAIL: *
9+
10+
// REQUIRES: deterministic-compiler
11+
// see https://bugs.swift.org/browse/SR-4896
12+
1013
struct A:RangeReplaceableCollection{var f=max

validation-test/compiler_crashers_fixed/28670-reftype-hastypeparameter-cannot-have-a-dependent-type-here.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

88
// RUN: not %target-swift-frontend %s -emit-ir
9-
// XFAIL: *
9+
10+
// REQUIRES: deterministic-compiler
11+
// see https://bugs.swift.org/browse/SR-4894
1012
struct A:RangeReplaceableCollection{let c{{a f{}}var f=max

0 commit comments

Comments
 (0)