File: inverse_casting_availability.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 (129 lines) | stat: -rw-r--r-- 6,552 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
121
122
123
124
125
126
127
128
129
// RUN: %target-typecheck-verify-swift \
// RUN:   -debug-diagnostic-names -target arm64-apple-macos14.4 \
// RUN:   -enable-experimental-feature NonescapableTypes

// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchOS || OS=xros

protocol P {}
struct NCG<T: ~Copyable> {}
extension NCG: P where T: Copyable {} // expected-note 2{{requirement_implied_by_conditional_conformance}}

struct NEG<T: ~Escapable> {}
extension NEG: P {} // expected-note {{requirement_implied_by_conditional_conformance}}

struct All {}
struct NoCopy: ~Copyable {}
struct NoEscape: ~Escapable {}



/// MARK: dynamic casts are gated by availability. Older runtimes don't check
/// for conformance to Copyable so they'll give bogus results.

// expected-note@+1 8{{availability_add_attribute}}
func dyn_cast_errors<T: ~Copyable, V: ~Escapable>(
                    _ generic: NCG<T>, _ concrete: NCG<NoCopy>,
                    _ genericEsc: NEG<V>, _ concreteEsc: NEG<NoEscape>) {
  _ = concrete as? any P // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}
  _ = generic as? any P // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}

  _ = concrete is any P // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}
  _ = generic is any P // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}

  _ = concrete as! any P // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}
  _ = generic as! any P // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}

  _ = genericEsc as? any P // expected-error {{availability_escapable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}
  _ = concreteEsc is any P // expected-error {{availability_escapable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}
}

@available(SwiftStdlib 6.0, *)
func FIXED_dyn_cast_errors<T: ~Copyable, V: ~Escapable>(
                          _ generic: NCG<T>, _ concrete: NCG<NoCopy>,
                          _ genericEsc: NEG<V>, _ concreteEsc: NEG<NoEscape>) {
  _ = concrete as? any P
  _ = generic as? any P

  _ = concrete is any P
  _ = generic is any P

  _ = concrete as! any P
  _ = generic as! any P

  _ = genericEsc as? any P
  _ = concreteEsc is any P
}

func noAvailabilityNeeded<T>(_ generic: NCG<T>, _ concrete: NCG<All>) {
  _ = concrete as? any P // expected-warning {{conditional_downcast_coercion}}
  _ = generic as? any P  // expected-warning {{conditional_downcast_coercion}}

  _ = concrete is any P  // expected-warning {{isa_is_always_true}}
  _ = generic is any P   // expected-warning {{isa_is_always_true}}

  _ = concrete as! any P // expected-warning {{forced_downcast_coercion}}
  _ = generic as! any P  // expected-warning {{forced_downcast_coercion}}

  _ = concrete as any P
  _ = generic as any P

  _ = concrete as Any
  _ = generic as Any
}

func expected_checked_cast_errors<T: ~Copyable>(_ generic: NCG<T>, _ concrete: NCG<NoCopy>,
                                                _ concreteEsc: NEG<NoEscape>) {
  _ = concrete as any P // expected-error {{type_does_not_conform_decl_owner}}
  _ = generic as any P  // expected-error {{type_does_not_conform_decl_owner}}
  _ = concreteEsc as any P // expected-error {{type_does_not_conform_decl_owner}}
}

/// MARK: existential erasure requires availability, because later dynamic casts
/// of that erased type will not correctly check for Copyable generic args.

func eraseImplicit(_ a: Any) {}

// expected-note@+1 9{{availability_add_attribute}}
func erasure_cast_disallowed<T: ~Copyable>(_ generic: NCG<T>, _ concrete: NCG<NoCopy>, _ concreteEsc: NEG<NoEscape>) -> Any {
  _ = concrete as Any // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}
  _ = concreteEsc as Any // expected-error {{availability_escapable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}
  _ = generic as Any // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}

  let _: Any = concrete // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}
  let _: Any = generic // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}

  let _: Any = { concreteEsc }() // expected-error {{availability_escapable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}

  eraseImplicit(concrete) // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}
  eraseImplicit(generic) // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}

  return concrete // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}
}

struct Box<Wrapped: ~Copyable>: ~Copyable { // expected-note {{availability_add_attribute}}
  private let _pointer: UnsafeMutablePointer<Wrapped>

  init(_ element: consuming Wrapped) { // expected-note {{availability_add_attribute}}
    _pointer = .allocate(capacity: 1)
    print("allocating",_pointer) // expected-error {{availability_copyable_generics_casting_only_version_newer}} // expected-note {{availability_guard_with_version_check}}
    _pointer.initialize(to: element)
  }
}

/// MARK: misc. operations that are permitted

public protocol Debatable: ~Copyable {}

public func asExistential(_ t: consuming any Debatable & ~Copyable) {}

public func hello<T: Debatable & ~Copyable>(_ t: consuming T) {
  asExistential(t)
}

extension UnsafeMutableRawPointer {
  public func blahInitializeMemory<T: ~Copyable>(
      as type: T.Type, from source: UnsafeMutablePointer<T>, count: Int
    ) {
      _ = UnsafeMutableRawPointer(source + count)
  }
}