From 46311986f70a1a366c68eaf4c7260bdc006b884d Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Fri, 12 Dec 2025 12:29:40 -0800 Subject: [PATCH 1/4] Use the correct portion of a substring --- .../public/core/FloatingPointParsing.swift.gyb | 16 +++++++++++----- test/stdlib/ParseFloat64.swift | 8 ++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/stdlib/public/core/FloatingPointParsing.swift.gyb b/stdlib/public/core/FloatingPointParsing.swift.gyb index f65c8c2b7018b..aef8227f40b71 100644 --- a/stdlib/public/core/FloatingPointParsing.swift.gyb +++ b/stdlib/public/core/FloatingPointParsing.swift.gyb @@ -256,15 +256,21 @@ extension ${Self}: LosslessStringConvertible { // Use the all-Swift `parse_float${bits}()` implementation for Float16/32/64 @available(SwiftStdlib 5.3, *) public init?(_ text: Substring) { - // TODO: Someday, this whole function should simplify down to just: - // ${Self}(text.utf8.span) #if _pointerBitWidth(_16) // Always fail on 16-bit targets return nil #else - // Work around span availability limits - let parsed = unsafe text.base._guts.withFastUTF8 { chars -> ${Self}? in - unsafe parse_float${bits}(chars.span) + let parsed: ${Self}? + if text.base._guts.isFastUTF8 { + parsed = unsafe text.base._guts.withFastUTF8 { chars -> ${Self}? in + unsafe parse_float${bits}(chars.span.extracting(text._offsetRange)) + } + } else { + // Otherwise, make a copy so we have contiguous UTF8... + let string = String(text) + parsed = unsafe string._guts.withFastUTF8 { chars -> ${Self}? in + unsafe parse_float${bits}(chars.span) + } } if let parsed { diff --git a/test/stdlib/ParseFloat64.swift b/test/stdlib/ParseFloat64.swift index e39e5b3a0aeba..58d6e3dbf2d12 100644 --- a/test/stdlib/ParseFloat64.swift +++ b/test/stdlib/ParseFloat64.swift @@ -325,6 +325,14 @@ tests.test("Decimal Floats") { expectParse("999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999.999999999999999999999999999", Float64.infinity) } +tests.test("Substring") { + let s1 = "1.02.03.0" + let s1sub = s1[s1.firstIndex(of: "2")!..>, From 5d3e17ae5fd1d135b2fc4ff53dceca1c9b13b646 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Wed, 17 Dec 2025 15:34:49 -0800 Subject: [PATCH 2/4] Test short and long bridged strings Simplify the top-level initializer by using `Substring.withUTF8` to get a correct span over contiguous UTF8. --- .../core/FloatingPointParsing.swift.gyb | 13 +++-------- test/stdlib/ParseFloat64.swift | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/stdlib/public/core/FloatingPointParsing.swift.gyb b/stdlib/public/core/FloatingPointParsing.swift.gyb index aef8227f40b71..00174fdb5cef6 100644 --- a/stdlib/public/core/FloatingPointParsing.swift.gyb +++ b/stdlib/public/core/FloatingPointParsing.swift.gyb @@ -260,17 +260,10 @@ extension ${Self}: LosslessStringConvertible { // Always fail on 16-bit targets return nil #else + var mutableText = text let parsed: ${Self}? - if text.base._guts.isFastUTF8 { - parsed = unsafe text.base._guts.withFastUTF8 { chars -> ${Self}? in - unsafe parse_float${bits}(chars.span.extracting(text._offsetRange)) - } - } else { - // Otherwise, make a copy so we have contiguous UTF8... - let string = String(text) - parsed = unsafe string._guts.withFastUTF8 { chars -> ${Self}? in - unsafe parse_float${bits}(chars.span) - } + parsed = mutableText.withUTF8 { chars -> ${Self}? in + unsafe parse_float${bits}(chars.span) } if let parsed { diff --git a/test/stdlib/ParseFloat64.swift b/test/stdlib/ParseFloat64.swift index 58d6e3dbf2d12..882de1f817c42 100644 --- a/test/stdlib/ParseFloat64.swift +++ b/test/stdlib/ParseFloat64.swift @@ -9,6 +9,7 @@ // REQUIRES: swift_feature_Extern import StdlibUnittest +import Foundation let tests = TestSuite("FloatingPointParsing") @@ -333,6 +334,28 @@ tests.test("Substring") { expectEqual(parsed!.bitPattern, (2.0).bitPattern) } +tests.test("Bridged - short") { + let s1 = "1.02.03.0" + let nss1 = NSString(utf8String: s1)! + let bridged = String(nss1) + let range = bridged.firstIndex(of: "2")!..>, From 13529d01b24cf76654b2f293f828180ac5f8875c Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Wed, 17 Dec 2025 17:12:34 -0800 Subject: [PATCH 3/4] Comment out Bridged tests that cannot run on Linux --- test/stdlib/ParseFloat64.swift | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/stdlib/ParseFloat64.swift b/test/stdlib/ParseFloat64.swift index 882de1f817c42..adcf53be5efd5 100644 --- a/test/stdlib/ParseFloat64.swift +++ b/test/stdlib/ParseFloat64.swift @@ -9,7 +9,6 @@ // REQUIRES: swift_feature_Extern import StdlibUnittest -import Foundation let tests = TestSuite("FloatingPointParsing") @@ -326,7 +325,7 @@ tests.test("Decimal Floats") { expectParse("999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999.999999999999999999999999999", Float64.infinity) } -tests.test("Substring") { +tests.test("Substring - short") { let s1 = "1.02.03.0" let s1sub = s1[s1.firstIndex(of: "2")!.. Date: Wed, 17 Dec 2025 17:15:34 -0800 Subject: [PATCH 4/4] Break out bridging to a separate test source file --- test/stdlib/ParseFloat64-bridging.swift | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 test/stdlib/ParseFloat64-bridging.swift diff --git a/test/stdlib/ParseFloat64-bridging.swift b/test/stdlib/ParseFloat64-bridging.swift new file mode 100644 index 0000000000000..730a073ab049e --- /dev/null +++ b/test/stdlib/ParseFloat64-bridging.swift @@ -0,0 +1,39 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -g %s -o %t/a.out -enable-experimental-feature Extern +// RUN: %target-codesign %t/a.out +// RUN: %target-run %t/a.out + +// REQUIRES: executable_test +// REQUIRES: objc_interop + +// Needed to declare the ABI entry point +// REQUIRES: swift_feature_Extern + +import StdlibUnittest +import Foundation + +let tests = TestSuite("FloatingPointParsing") + +tests.test("Bridged - short") { + let s1 = "1.02.03.0" + let nss1 = NSString(utf8String: s1)! + let bridged = String(nss1) + let range = bridged.firstIndex(of: "2")!..