8
8
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9
9
//
10
10
11
- private import _TestingInternals
12
-
13
11
/// A type representing the context within a call to the `#expect()` and
14
12
/// `#require()` macros.
15
13
///
@@ -45,12 +43,20 @@ public struct __ExpectationContext: ~Copyable {
45
43
/// are evaluated, much like ``runtimeValues``.
46
44
var differences : [ __ExpressionID : ( ) -> CollectionDifference < Any > ? ]
47
45
48
- #if !SWT_NO_IMPLICIT_POINTER_CASTING
49
- /// Storage for any locally-created C strings and pointers.
46
+ /// Cleanup functions for any locally-created resources (such as pointers or
47
+ /// C strings.)
50
48
///
51
- /// For more information, see `__ImplicitlyPointerConvertible` below.
52
- fileprivate var temporaryPointerCleanup = [ ( ) -> ( ) ] ( )
53
- #endif
49
+ /// The closures in this array are called when this instance is deinitialized.
50
+ /// The effect of calling them elsewhere is undefined.
51
+ private var _cleanup = [ ( ) -> Void ] ( )
52
+
53
+ /// Register a callback to invoke when this instance is deinitialized.
54
+ ///
55
+ /// - Parameters:
56
+ /// - cleanup: The callback to invoke when `deinit` is called.
57
+ mutating func callWhenDeinitializing( _ cleanup: @escaping ( ) -> Void ) {
58
+ _cleanup. append ( cleanup)
59
+ }
54
60
55
61
init (
56
62
sourceCode: @escaping @autoclosure @Sendable ( ) -> [ __ExpressionID : String ] = [ : ] ,
@@ -63,11 +69,9 @@ public struct __ExpectationContext: ~Copyable {
63
69
}
64
70
65
71
deinit {
66
- #if !SWT_NO_IMPLICIT_POINTER_CASTING
67
- for temporaryPointerCleanup in temporaryPointerCleanup {
68
- temporaryPointerCleanup ( )
72
+ for cleanup in _cleanup {
73
+ cleanup ( )
69
74
}
70
- #endif
71
75
}
72
76
73
77
/// Collapse the given expression graph into one or more expressions with
@@ -448,140 +452,3 @@ extension __ExpectationContext {
448
452
return result
449
453
}
450
454
}
451
-
452
- #if !SWT_NO_IMPLICIT_POINTER_CASTING
453
- // MARK: - String-to-C-string handling and implicit pointer conversions
454
-
455
- extension __ExpectationContext {
456
- /// A protocol describing types that can be implicitly cast to C strings or
457
- /// pointers when passed to C functions.
458
- ///
459
- /// This protocol helps the compiler disambiguate string values when they need
460
- /// to be implicitly cast to C strings or other pointer types.
461
- ///
462
- /// - Warning: This protocol is used to implement the `#expect()` and
463
- /// `#require()` macros. Do not use it directly. Do not add conformances to
464
- /// this protocol outside of the testing library.
465
- public protocol __ImplicitlyPointerConvertible {
466
- /// The concrete type of the resulting pointer when an instance of this type
467
- /// is implicitly cast.
468
- associatedtype __ImplicitPointerConversionResult
469
-
470
- /// Perform an implicit cast of this instance to its corresponding pointer
471
- /// type.
472
- ///
473
- /// - Parameters:
474
- /// - expectationContext: The expectation context that needs to cast this
475
- /// instance.
476
- ///
477
- /// - Returns: A copy of this instance, cast to a pointer.
478
- ///
479
- /// The implementation of this method should register the resulting pointer
480
- /// with `expectationContext` so that it is not leaked.
481
- ///
482
- /// - Warning: This function is used to implement the `#expect()` and
483
- /// `#require()` macros. Do not call it directly.
484
- func __implicitlyCast( for expectationContext: inout __ExpectationContext ) -> __ImplicitPointerConversionResult
485
- }
486
-
487
- /// Capture information about a value for use if the expectation currently
488
- /// being evaluated fails.
489
- ///
490
- /// - Parameters:
491
- /// - value: The value to pass through.
492
- /// - id: A value that uniquely identifies the represented expression in the
493
- /// context of the expectation currently being evaluated.
494
- ///
495
- /// - Returns: `value`, cast to a C string.
496
- ///
497
- /// This overload of `callAsFunction(_:_:)` helps the compiler disambiguate
498
- /// string values when they need to be implicitly cast to C strings or other
499
- /// pointer types.
500
- ///
501
- /// - Warning: This function is used to implement the `#expect()` and
502
- /// `#require()` macros. Do not call it directly.
503
- @_disfavoredOverload
504
- @inlinable public mutating func callAsFunction< S> ( _ value: S , _ id: __ExpressionID ) -> S . __ImplicitPointerConversionResult where S: __ImplicitlyPointerConvertible {
505
- captureValue ( value, id) . __implicitlyCast ( for: & self )
506
- }
507
-
508
- /// Capture information about a value for use if the expectation currently
509
- /// being evaluated fails.
510
- ///
511
- /// - Parameters:
512
- /// - value: The value to pass through.
513
- /// - id: A value that uniquely identifies the represented expression in the
514
- /// context of the expectation currently being evaluated.
515
- ///
516
- /// - Returns: `value`, verbatim.
517
- ///
518
- /// This overload of `callAsFunction(_:_:)` helps the compiler disambiguate
519
- /// string values when they do _not_ need to be implicitly cast to C strings
520
- /// or other pointer types. Without this overload, all instances of conforming
521
- /// types end up being cast to pointers before being compared (etc.), which
522
- /// produces incorrect results.
523
- ///
524
- /// - Warning: This function is used to implement the `#expect()` and
525
- /// `#require()` macros. Do not call it directly.
526
- @inlinable public mutating func callAsFunction< S> ( _ value: S , _ id: __ExpressionID ) -> S where S: __ImplicitlyPointerConvertible {
527
- captureValue ( value, id)
528
- }
529
-
530
- /// Convert some pointer to another pointer type and capture information about
531
- /// it for use if the expectation currently being evaluated fails.
532
- ///
533
- /// - Parameters:
534
- /// - value: The pointer to cast.
535
- /// - id: A value that uniquely identifies the represented expression in the
536
- /// context of the expectation currently being evaluated.
537
- ///
538
- /// - Returns: `value`, cast to another type of pointer.
539
- ///
540
- /// This overload of `callAsFunction(_:_:)` handles the implicit conversions
541
- /// between various pointer types that are normally provided by the compiler.
542
- ///
543
- /// - Warning: This function is used to implement the `#expect()` and
544
- /// `#require()` macros. Do not call it directly.
545
- @inlinable public mutating func callAsFunction< P1, P2> ( _ value: P1 ? , _ id: __ExpressionID ) -> P2 ! where P1: _Pointer , P2: _Pointer {
546
- captureValue ( value, id) . flatMap { value in
547
- P2 ( bitPattern: Int ( bitPattern: value) )
548
- }
549
- }
550
- }
551
-
552
- extension __ExpectationContext . __ImplicitlyPointerConvertible where Self: Collection {
553
- public func __implicitlyCast( for expectationContext: inout __ExpectationContext ) -> UnsafeMutablePointer < Element > {
554
- // If `count` is 0, Swift may opt not to allocate any storage, and we'll
555
- // crash dereferencing the base address.
556
- let count = Swift . max ( 1 , count)
557
-
558
- // Create a copy of this collection. Note we don't automatically add a null
559
- // character at the end (for C strings) because that could mask bugs in test
560
- // code that should automatically be adding them.
561
- let resultPointer = UnsafeMutableBufferPointer< Element> . allocate( capacity: count)
562
- let initializedEnd = resultPointer. initialize ( fromContentsOf: self )
563
-
564
- expectationContext. temporaryPointerCleanup. append {
565
- resultPointer [ ..< initializedEnd] . deinitialize ( )
566
- resultPointer. deallocate ( )
567
- }
568
-
569
- return resultPointer. baseAddress!
570
- }
571
- }
572
-
573
- extension String : __ExpectationContext . __ImplicitlyPointerConvertible {
574
- @inlinable public func __implicitlyCast( for expectationContext: inout __ExpectationContext ) -> UnsafeMutablePointer < CChar > {
575
- utf8CString. __implicitlyCast ( for: & expectationContext)
576
- }
577
- }
578
-
579
- extension Optional : __ExpectationContext . __ImplicitlyPointerConvertible where Wrapped: __ExpectationContext . __ImplicitlyPointerConvertible {
580
- public func __implicitlyCast( for expectationContext: inout __ExpectationContext ) -> Wrapped . __ImplicitPointerConversionResult ? {
581
- flatMap { $0. __implicitlyCast ( for: & expectationContext) }
582
- }
583
- }
584
-
585
- extension Array : __ExpectationContext . __ImplicitlyPointerConvertible { }
586
- extension ContiguousArray : __ExpectationContext . __ImplicitlyPointerConvertible { }
587
- #endif
0 commit comments