Skip to content

Commit 2557183

Browse files
authored
Merge pull request #69771 from DougGregor/typed-throws-map
Replace rethrowing map with generic typed throws
2 parents a3286c5 + 9bfca45 commit 2557183

13 files changed

+189
-47
lines changed

stdlib/public/core/Collection.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,9 +1190,10 @@ extension Collection {
11901190
/// - Returns: An array containing the transformed elements of this
11911191
/// sequence.
11921192
@inlinable
1193-
public func map<T>(
1194-
_ transform: (Element) throws -> T
1195-
) rethrows -> [T] {
1193+
@_alwaysEmitIntoClient
1194+
public func map<T, E>(
1195+
_ transform: (Element) throws(E) -> T
1196+
) throws(E) -> [T] {
11961197
// TODO: swift-3-indexing-model - review the following
11971198
let n = self.count
11981199
if n == 0 {
@@ -1213,6 +1214,17 @@ extension Collection {
12131214
return Array(result)
12141215
}
12151216

1217+
// ABI-only entrypoint for the rethrows version of map, which has been
1218+
// superseded by the typed-throws version. Expressed as "throws", which is
1219+
// ABI-compatible with "rethrows".
1220+
@usableFromInline
1221+
@_silgen_name("$sSlsE3mapySayqd__Gqd__7ElementQzKXEKlF")
1222+
func __rethrows_map<T>(
1223+
_ transform: (Element) throws -> T
1224+
) throws -> [T] {
1225+
try map(transform)
1226+
}
1227+
12161228
/// Returns a subsequence containing all but the given number of initial
12171229
/// elements.
12181230
///

stdlib/public/core/ExistentialCollection.swift

Lines changed: 85 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ internal class _AnySequenceBox<Element> {
175175
@inlinable
176176
internal func _map<T>(
177177
_ transform: (Element) throws -> T
178-
) rethrows -> [T] {
178+
) throws -> [T] {
179179
_abstract()
180180
}
181181

@@ -525,8 +525,8 @@ internal final class _SequenceBox<S: Sequence>: _AnySequenceBox<S.Element> {
525525
@inlinable
526526
internal override func _map<T>(
527527
_ transform: (Element) throws -> T
528-
) rethrows -> [T] {
529-
return try _base.map(transform)
528+
) throws -> [T] {
529+
try _base.map(transform)
530530
}
531531
@inlinable
532532
internal override func _filter(
@@ -618,8 +618,8 @@ internal final class _CollectionBox<S: Collection>: _AnyCollectionBox<S.Element>
618618
@inlinable
619619
internal override func _map<T>(
620620
_ transform: (Element) throws -> T
621-
) rethrows -> [T] {
622-
return try _base.map(transform)
621+
) throws -> [T] {
622+
try _base.map(transform)
623623
}
624624
@inlinable
625625
internal override func _filter(
@@ -813,8 +813,8 @@ internal final class _BidirectionalCollectionBox<S: BidirectionalCollection>
813813
@inlinable
814814
internal override func _map<T>(
815815
_ transform: (Element) throws -> T
816-
) rethrows -> [T] {
817-
return try _base.map(transform)
816+
) throws -> [T] {
817+
try _base.map(transform)
818818
}
819819
@inlinable
820820
internal override func _filter(
@@ -1026,8 +1026,8 @@ internal final class _RandomAccessCollectionBox<S: RandomAccessCollection>
10261026
@inlinable
10271027
internal override func _map<T>(
10281028
_ transform: (Element) throws -> T
1029-
) rethrows -> [T] {
1030-
return try _base.map(transform)
1029+
) throws -> [T] {
1030+
try _base.map(transform)
10311031
}
10321032
@inlinable
10331033
internal override func _filter(
@@ -1308,10 +1308,26 @@ extension AnySequence {
13081308
}
13091309

13101310
@inlinable
1311-
public func map<T>(
1311+
@_alwaysEmitIntoClient
1312+
public func map<T, E>(
1313+
_ transform: (Element) throws(E) -> T
1314+
) throws(E) -> [T] {
1315+
do {
1316+
return try _box._map(transform)
1317+
} catch {
1318+
throw error as! E
1319+
}
1320+
}
1321+
1322+
// ABI-only entrypoint for the rethrows version of map, which has been
1323+
// superseded by the typed-throws version. Expressed as "throws", which is
1324+
// ABI-compatible with "rethrows".
1325+
@usableFromInline
1326+
@_silgen_name("$ss11AnySequenceV3mapySayqd__Gqd__xKXEKlF")
1327+
func __rethrows_map<T>(
13121328
_ transform: (Element) throws -> T
1313-
) rethrows -> [T] {
1314-
return try _box._map(transform)
1329+
) throws -> [T] {
1330+
try map(transform)
13151331
}
13161332

13171333
@inlinable
@@ -1395,10 +1411,26 @@ extension AnyCollection {
13951411
}
13961412

13971413
@inlinable
1398-
public func map<T>(
1414+
@_alwaysEmitIntoClient
1415+
public func map<T, E>(
1416+
_ transform: (Element) throws(E) -> T
1417+
) throws(E) -> [T] {
1418+
do {
1419+
return try _box._map(transform)
1420+
} catch {
1421+
throw error as! E
1422+
}
1423+
}
1424+
1425+
// ABI-only entrypoint for the rethrows version of map, which has been
1426+
// superseded by the typed-throws version. Expressed as "throws", which is
1427+
// ABI-compatible with "rethrows".
1428+
@usableFromInline
1429+
@_silgen_name("$ss13AnyCollectionV3mapySayqd__Gqd__xKXEKlF")
1430+
func __rethrows_map<T>(
13991431
_ transform: (Element) throws -> T
1400-
) rethrows -> [T] {
1401-
return try _box._map(transform)
1432+
) throws -> [T] {
1433+
try map(transform)
14021434
}
14031435

14041436
@inlinable
@@ -1488,10 +1520,26 @@ extension AnyBidirectionalCollection {
14881520
}
14891521

14901522
@inlinable
1491-
public func map<T>(
1523+
@_alwaysEmitIntoClient
1524+
public func map<T, E>(
1525+
_ transform: (Element) throws(E) -> T
1526+
) throws(E) -> [T] {
1527+
do {
1528+
return try _box._map(transform)
1529+
} catch {
1530+
throw error as! E
1531+
}
1532+
}
1533+
1534+
// ABI-only entrypoint for the rethrows version of map, which has been
1535+
// superseded by the typed-throws version. Expressed as "throws", which is
1536+
// ABI-compatible with "rethrows".
1537+
@usableFromInline
1538+
@_silgen_name("$ss26AnyBidirectionalCollectionV3mapySayqd__Gqd__xKXEKlF")
1539+
func __rethrows_map<T>(
14921540
_ transform: (Element) throws -> T
1493-
) rethrows -> [T] {
1494-
return try _box._map(transform)
1541+
) throws -> [T] {
1542+
try map(transform)
14951543
}
14961544

14971545
@inlinable
@@ -1583,10 +1631,26 @@ extension AnyRandomAccessCollection {
15831631
}
15841632

15851633
@inlinable
1586-
public func map<T>(
1634+
@_alwaysEmitIntoClient
1635+
public func map<T, E>(
1636+
_ transform: (Element) throws(E) -> T
1637+
) throws(E) -> [T] {
1638+
do {
1639+
return try _box._map(transform)
1640+
} catch {
1641+
throw error as! E
1642+
}
1643+
}
1644+
1645+
// ABI-only entrypoint for the rethrows version of map, which has been
1646+
// superseded by the typed-throws version. Expressed as "throws", which is
1647+
// ABI-compatible with "rethrows".
1648+
@usableFromInline
1649+
@_silgen_name("$ss25AnyRandomAccessCollectionV3mapySayqd__Gqd__xKXEKlF")
1650+
func __rethrows_map<T>(
15871651
_ transform: (Element) throws -> T
1588-
) rethrows -> [T] {
1589-
return try _box._map(transform)
1652+
) throws -> [T] {
1653+
try map(transform)
15901654
}
15911655

15921656
@inlinable

stdlib/public/core/Misc.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,16 @@ public func _unsafePerformance<T>(_ c: () -> T) -> T {
159159
return c()
160160
}
161161

162+
// Helper function that exploits a bug in rethrows checking to
163+
// allow us to call rethrows functions from generic typed-throws functions
164+
// and vice-versa.
165+
@usableFromInline
166+
@_alwaysEmitIntoClient
167+
@inline(__always)
168+
func _rethrowsViaClosure(_ fn: () throws -> ()) rethrows {
169+
try fn()
170+
}
171+
162172
#if $NoncopyableGenerics && $NonescapableTypes
163173
@_marker public protocol Copyable: ~Escapable {}
164174
@_marker public protocol Escapable: ~Copyable {}

stdlib/public/core/Sequence.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,9 +670,10 @@ extension Sequence {
670670
///
671671
/// - Complexity: O(*n*), where *n* is the length of the sequence.
672672
@inlinable
673-
public func map<T>(
674-
_ transform: (Element) throws -> T
675-
) rethrows -> [T] {
673+
@_alwaysEmitIntoClient
674+
public func map<T, E>(
675+
_ transform: (Element) throws(E) -> T
676+
) throws(E) -> [T] {
676677
let initialCapacity = underestimatedCount
677678
var result = ContiguousArray<T>()
678679
result.reserveCapacity(initialCapacity)
@@ -690,6 +691,17 @@ extension Sequence {
690691
return Array(result)
691692
}
692693

694+
// ABI-only entrypoint for the rethrows version of map, which has been
695+
// superseded by the typed-throws version. Expressed as "throws", which is
696+
// ABI-compatible with "rethrows".
697+
@usableFromInline
698+
@_silgen_name("$sSTsE3mapySayqd__Gqd__7ElementQzKXEKlF")
699+
func __rethrows_map<T>(
700+
_ transform: (Element) throws -> T
701+
) throws -> [T] {
702+
try map(transform)
703+
}
704+
693705
/// Returns an array containing, in order, the elements of the sequence
694706
/// that satisfy the given predicate.
695707
///

test/Constraints/closures.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,11 +1143,11 @@ struct R_76250381<Result, Failure: Error> {
11431143

11441144
// https://github.com/apple/swift/issues/55926
11451145
(0..<10).map { x, y in }
1146-
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) throws -> ()' (aka '(Int) throws -> ()') expects 1 argument, but 2 were used in closure body}}
1146+
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) -> ()' (aka '(Int) -> ()') expects 1 argument, but 2 were used in closure body}}
11471147
(0..<10).map { x, y, z in }
1148-
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) throws -> ()' (aka '(Int) throws -> ()') expects 1 argument, but 3 were used in closure body}}
1148+
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) -> ()' (aka '(Int) -> ()') expects 1 argument, but 3 were used in closure body}}
11491149
(0..<10).map { x, y, z, w in }
1150-
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) throws -> ()' (aka '(Int) throws -> ()') expects 1 argument, but 4 were used in closure body}}
1150+
// expected-error@-1 {{contextual closure type '(Range<Int>.Element) -> ()' (aka '(Int) -> ()') expects 1 argument, but 4 were used in closure body}}
11511151

11521152
// rdar://77022842 - crash due to a missing argument to a ternary operator
11531153
func rdar77022842(argA: Bool? = nil, argB: Bool? = nil) {
@@ -1171,6 +1171,7 @@ func rdar76058892() {
11711171
test { // expected-error {{contextual closure type '() -> String' expects 0 arguments, but 1 was used in closure body}}
11721172
if let arr = arr {
11731173
arr.map($0.test) // expected-note {{anonymous closure parameter '$0' is used here}} // expected-error {{generic parameter 'T' could not be inferred}}
1174+
// expected-error@-1 {{generic parameter 'E' could not be inferred}}
11741175
}
11751176
}
11761177
}

test/Constraints/enum_cases.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ enum G_E<T> {
1919
let arr: [String] = []
2020
let _ = arr.map(E.foo) // Ok
2121
let _ = arr.map(E.bar) // Ok
22-
let _ = arr.map(E.two) // expected-error {{cannot convert value of type '(Int, Int) -> E' to expected argument type '(String) throws -> E'}}
22+
let _ = arr.map(E.two) // expected-error {{cannot convert value of type '(Int, Int) -> E' to expected argument type '(String) -> E'}}
2323

24-
let _ = arr.map(E.tuple) // expected-error {{cannot convert value of type '((x: Int, y: Int)) -> E' to expected argument type '(String) throws -> E'}}
24+
let _ = arr.map(E.tuple) // expected-error {{cannot convert value of type '((x: Int, y: Int)) -> E' to expected argument type '(String) -> E'}}
2525

2626
let _ = arr.map(G_E<String>.foo) // Ok
2727
let _ = arr.map(G_E<String>.bar) // Ok
28-
let _ = arr.map(G_E<String>.two) // expected-error {{cannot convert value of type '(String, String) -> G_E<String>' to expected argument type '(String) throws -> G_E<String>'}}
29-
let _ = arr.map(G_E<Int>.tuple) // expected-error {{cannot convert value of type '((x: Int, y: Int)) -> G_E<Int>' to expected argument type '(String) throws -> G_E<Int>'}}
28+
let _ = arr.map(G_E<String>.two) // expected-error {{cannot convert value of type '(String, String) -> G_E<String>' to expected argument type '(String) -> G_E<String>'}}
29+
let _ = arr.map(G_E<Int>.tuple) // expected-error {{cannot convert value of type '((x: Int, y: Int)) -> G_E<Int>' to expected argument type '(String) -> G_E<Int>'}}
3030

3131
let _ = E.foo("hello") // expected-error {{missing argument label 'bar:' in call}}
3232
let _ = E.bar("hello") // Ok

test/Constraints/tuple_arguments.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1726,7 +1726,7 @@ do {
17261726
do {
17271727
func f(_: Int...) {}
17281728
let _ = [(1, 2, 3)].map(f) // expected-error {{no exact matches in call to instance method 'map'}}
1729-
// expected-note@-1 {{found candidate with type '(((Int, Int, Int)) throws -> _) throws -> Array<_>'}}
1729+
// expected-note@-1 {{found candidate with type '(((Int, Int, Int)) -> _) -> Array<_>'}}
17301730
}
17311731

17321732
// rdar://problem/48443263 - cannot convert value of type '() -> Void' to expected argument type '(_) -> Void'

test/IDE/complete_from_stdlib.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,30 @@ func protocolExtCollection1a<C : Collection>(_ a: C) {
2020
a.#^PRIVATE_NOMINAL_MEMBERS_2A?check=PRIVATE_NOMINAL_MEMBERS_2A;check=NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2A;check=NO_STDLIB_PRIVATE^#
2121
}
2222

23-
// PRIVATE_NOMINAL_MEMBERS_2A-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: map({#(transform): (C.Element) throws -> T##(C.Element) throws -> T#})[' rethrows'][#[T]#];
23+
// PRIVATE_NOMINAL_MEMBERS_2A-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: map({#(transform): (C.Element) throws(Error) -> T##(C.Element) throws(Error) -> T#})[' throws'][#[T]#];
2424
// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2A-NOT: Decl{{.*}}: index({#before: any Comparable#})
2525

2626
func protocolExtCollection1b(_ a: Collection) {
2727
a.#^PRIVATE_NOMINAL_MEMBERS_2B?check=PRIVATE_NOMINAL_MEMBERS_2B;check=NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2B;check=NO_STDLIB_PRIVATE^#
2828
}
2929

3030
// FIXME(https://github.com/apple/swift/issues/65696): We should not be showing this because (1) it cannot be accessed on the existential (2) we don't have the syntax and features to represent the projected type sig anyway.
31-
// PRIVATE_NOMINAL_MEMBERS_2B-DAG: map({#(transform): (any Collection.Element) throws -> T##(any Collection.Element) throws -> T#})[' rethrows'][#[T]#]{{; name=.+}}
31+
// PRIVATE_NOMINAL_MEMBERS_2B-DAG: map({#(transform): (any Collection.Element) throws(Error) -> T##(any Collection.Element) throws(Error) -> T#})[' throws'][#[T]#]{{; name=.+}}
3232
// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_2B-NOT: Decl{{.*}}: index({#before: any Comparable#})
3333

3434
func protocolExtCollection2<C : Collection where C.Index : BidirectionalIndex>(_ a: C) {
3535
a.#^PRIVATE_NOMINAL_MEMBERS_3?check=PRIVATE_NOMINAL_MEMBERS_3;check=NEGATIVE_PRIVATE_NOMINAL_MEMBERS_3;check=NO_STDLIB_PRIVATE^#
3636
}
3737

38-
// PRIVATE_NOMINAL_MEMBERS_3-DAG: Decl[InstanceMethod]/Super/IsSystem: map({#(transform): (C.Element) throws -> T##(C.Element) throws -> T#})[' rethrows'][#[T]#]{{; name=.+}}
38+
// PRIVATE_NOMINAL_MEMBERS_3-DAG: Decl[InstanceMethod]/Super/IsSystem: map({#(transform): (C.Element) throws(Error) -> T##(C.Element) throws(Error) -> T#})[' throws'][#[T]#]{{; name=.+}}
3939
// PRIVATE_NOMINAL_MEMBERS_3-DAG: Decl[InstanceVar]/Super/IsSystem: lazy[#LazySequence<Collection>#]{{; name=.+}}
4040
// PRIVATE_NOMINAL_MEMBERS_3-DAG: firstIndex({#where: (C.Element) throws -> Bool##(C.Element) throws -> Bool#})[' rethrows'][#Comparable?#]{{; name=.+}}
4141
// NEGATIVE_PRIVATE_NOMINAL_MEMBERS_3-NOT: Decl{{.*}}: firstIndex({#({{.*}}): Self.Iterator.Element
4242

4343
func protocolExtArray<T : Equatable>(_ a: [T]) {
4444
a.#^PRIVATE_NOMINAL_MEMBERS_4?check=PRIVATE_NOMINAL_MEMBERS_4;check=NO_STDLIB_PRIVATE^#
4545
}
46-
// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super/IsSystem: map({#(transform): (Equatable) throws -> T##(Equatable) throws -> T#})[' rethrows'][#[T]#]{{; name=.+}}
46+
// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super/IsSystem: map({#(transform): (Equatable) throws(Error) -> T##(Equatable) throws(Error) -> T#})[' throws'][#[T]#]{{; name=.+}}
4747
// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceVar]/Super/IsSystem: last[#Equatable?#]{{; name=.+}}
4848
// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super/IsSystem: firstIndex({#of: Equatable#})[#Int?#]{{; name=.+}}
4949
// PRIVATE_NOMINAL_MEMBERS_4-DAG: Decl[InstanceMethod]/Super/IsSystem: firstIndex({#where: (Equatable) throws -> Bool##(Equatable) throws -> Bool#})[' rethrows'][#Int?#]{{; name=.+}}
@@ -85,7 +85,7 @@ func testArchetypeReplacement3 (_ a : [Int]) {
8585
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: append({#(newElement): Int#})[#Void#]
8686
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super/IsSystem: removeLast()[#Int#]
8787
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceVar]/Super/IsSystem: first[#Int?#]
88-
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super/IsSystem: map({#(transform): (Int) throws -> T##(Int) throws -> T#})[' rethrows'][#[T]#]
88+
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super/IsSystem: map({#(transform): (Int) throws(Error) -> T##(Int) throws(Error) -> T#})[' throws'][#[T]#]
8989
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super/IsSystem: dropLast({#(k): Int#})[#ArraySlice<Int>#]
9090
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super/IsSystem: elementsEqual({#(other): Sequence#}, {#by: (Int, Sequence.Element) throws -> Bool##(Int, Sequence.Element) throws -> Bool#})[' rethrows'][#Bool#]; name=elementsEqual(:by:)
9191
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super/IsSystem: elementsEqual({#(other): Sequence#})[#Bool#]; name=elementsEqual(:)

test/SILGen/function_conversion.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,14 +660,14 @@ struct FunctionConversionParameterSubstToOrigReabstractionTest {
660660
}
661661
}
662662

663-
// CHECK: sil {{.*}} [ossa] @$sS4SIgggoo_S2Ss11AnyHashableVyps5Error_pIegggrrzo_TR
663+
// CHECK: sil {{.*}} [ossa] @$sS4SIgggoo_S2Ss11AnyHashableVypIegggrr_TR
664664
// CHECK: [[TUPLE:%.*]] = apply %4(%2, %3) : $@noescape @callee_guaranteed (@guaranteed String, @guaranteed String) -> (@owned String, @owned String)
665665
// CHECK: ([[LHS:%.*]], [[RHS:%.*]]) = destructure_tuple [[TUPLE]]
666666
// CHECK: [[ADDR:%.*]] = alloc_stack $String
667667
// CHECK: store [[LHS]] to [init] [[ADDR]] : $*String
668668
// CHECK: [[CVT:%.*]] = function_ref @$ss21_convertToAnyHashableys0cD0VxSHRzlF : $@convention(thin) <τ_0_0 where τ_0_0 : Hashable> (@in_guaranteed τ_0_0) -> @out AnyHashable
669669
// CHECK: apply [[CVT]]<String>(%0, [[ADDR]])
670-
// CHECK: } // end sil function '$sS4SIgggoo_S2Ss11AnyHashableVyps5Error_pIegggrrzo_TR'
670+
// CHECK: } // end sil function '$sS4SIgggoo_S2Ss11AnyHashableVypIegggrr_TR'
671671

672672
func dontCrash() {
673673
let userInfo = ["hello": "world"]

test/SILGen/opaque_values_silgen.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,16 @@ public struct EnumSeq<Base : Seq> : Seq {
365365
}
366366

367367
extension Collection {
368+
func myMap<T>(_ body: (Element) -> T) -> [T] {
369+
var result = [T]()
370+
for element in self {
371+
result.append(body(element))
372+
}
373+
return result
374+
}
375+
368376
func transformEachElement<U>(_ cl: (Element) -> U) -> [U] {
369-
return map(cl)
377+
return myMap(cl)
370378
}
371379
}
372380

0 commit comments

Comments
 (0)