File: moveonly_generics.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (120 lines) | stat: -rw-r--r-- 2,920 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// RUN: %target-run-simple-swift(-Xfrontend -sil-verify-all)
// RUN: %target-run-simple-swift(-O -Xfrontend -sil-verify-all)

// REQUIRES: executable_test
// REQUIRES: asserts

// UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: back_deployment_runtime

// Needed due to limitations of autoclosures and noncopyable types.
func eagerAssert(_ b: Bool, _ line: Int = #line) {
  guard b else { fatalError("assertion failure on line \(line)") }
}

///---------------------
/// MARK: a Swift x Haskell limited-edition stdlib
/// ---------------------



/// MARK: Ord aka 'Comparable'
protocol Ord: ~Copyable {
  func compare(_ other: borrowing Self) -> Ordering
}

enum Ordering {
  case LT
  case EQ
  case GT

  static func compare<T: Comparable>(_ a: borrowing T, _ b: borrowing T) -> Ordering {
    if (a < b) { return .LT }
    if (a > b) { return .GT }
    eagerAssert(a == b)
    return .EQ
  }
}

extension Ord where Self: ~Copyable {
  func less(_ b: borrowing Self) -> Bool {
    return compare(b) == .LT
  }
  func lessOrEq(_ b: borrowing Self) -> Bool {
    return !greater(b)
  }
  func greater(_ b: borrowing Self) -> Bool {
    return compare(b) == .GT
  }
  func greaterOrEq(_ b: borrowing Self) -> Bool {
    return !less(b)
  }
  func equal(_ b: borrowing Self) -> Bool {
    compare(b) == .EQ
  }
  func notEqual(_ b: borrowing Self) -> Bool {
    !equal(b)
  }
}

/// MARK: Maybe aka 'Optional'
enum Maybe<Val: ~Copyable>: ~Copyable {
  case just(Val)
  case none

  // NOTE: a 'consuming' version of the unfortunately 'borrowing' map from the stdlib.
  consuming func consumingMap<U: ~Copyable>(_ fn: (consuming Val) throws -> U) rethrows -> Maybe<U> {
    // rdar://117638878 (MoveOnlyAddressChecker crashes with generic associated value in enum)
    fatalError("need to fix rdar://117638878")
//     return switch consume self {
//       case let .just(val): .just(try fn(val))
//       case .none: .none
//     }
  }
}

// NOTE: temporary
extension Maybe: Copyable where Val: Copyable {}


/// MARK: beginning of tests

struct FileDescriptor: ~Copyable, Ord {
  let id: Int

  func compare(_ other: borrowing FileDescriptor) -> Ordering {
    return .compare(id, other.id)
  }

  deinit { print("calling deinit!") }
}

class Shared<T: ~Copyable> {
  let value: T
  init(_ val: consuming T) { self.value = val }
  func borrow<V>(_ f: (borrowing T) throws -> V) rethrows -> V {
    return try f(value)
  }
}

defer { testOrd() }
func testOrd() {
  let stderr = Shared(FileDescriptor(id: 1))
  let stdout = Shared(FileDescriptor(id: 0))
  stdout.borrow { out in
    stderr.borrow { err in
      eagerAssert(err.greater(out))
      eagerAssert(out.less(err))
      eagerAssert(out.notEqual(err))
    }
  }
}

defer { testMaybe() }
func testMaybe() {
  let mayb = Maybe.just(FileDescriptor(id: 0));
  switch consume mayb {
    case let .just(fd): eagerAssert(fd.id == 0)
    case .none: eagerAssert(false)
  }
}