Skip to content

Commit 26176cc

Browse files
committed
[stdlib] Allow metatypes of noncopyable/nonescapable types to get compared
1 parent eba0092 commit 26176cc

File tree

5 files changed

+78
-15
lines changed

5 files changed

+78
-15
lines changed

stdlib/public/core/Builtin.swift

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,69 @@ internal func != (lhs: Builtin.RawPointer, rhs: Builtin.RawPointer) -> Bool {
158158
return !(lhs == rhs)
159159
}
160160

161+
#if !$Embedded
162+
/// Returns a Boolean value indicating whether two types are identical.
163+
///
164+
/// - Parameters:
165+
/// - t0: A type to compare.
166+
/// - t1: Another type to compare.
167+
/// - Returns: `true` if both `t0` and `t1` are `nil` or if they represent the
168+
/// same type; otherwise, `false`.
169+
@_alwaysEmitIntoClient
170+
@_transparent
171+
public func == (
172+
t0: (any (~Copyable & ~Escapable).Type)?,
173+
t1: (any (~Copyable & ~Escapable).Type)?
174+
) -> Bool {
175+
switch (t0, t1) {
176+
case (.none, .none):
177+
return true
178+
case let (.some(ty0), .some(ty1)):
179+
// FIXME: this should read `Bool(Builtin.is_same_metatype(ty0, ty1))`,
180+
// but that currently requires copyability/escapability (rdar://145707064)
181+
let p1 = unsafeBitCast(ty0, to: UnsafeRawPointer.self)
182+
let p2 = unsafeBitCast(ty1, to: UnsafeRawPointer.self)
183+
return p1 == p2
184+
default:
185+
return false
186+
}
187+
}
188+
189+
/// Returns a Boolean value indicating whether two types are not identical.
190+
///
191+
/// - Parameters:
192+
/// - t0: A type to compare.
193+
/// - t1: Another type to compare.
194+
/// - Returns: `true` if one, but not both, of `t0` and `t1` are `nil`, or if
195+
/// they represent different types; otherwise, `false`.
196+
@_alwaysEmitIntoClient
197+
@_transparent
198+
public func != (
199+
t0: (any (~Copyable & ~Escapable).Type)?,
200+
t1: (any (~Copyable & ~Escapable).Type)?
201+
) -> Bool {
202+
!(t0 == t1)
203+
}
204+
205+
@usableFromInline
206+
@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1)
207+
internal func == (t0: Any.Type?, t1: Any.Type?) -> Bool {
208+
switch (t0, t1) {
209+
case (.none, .none): return true
210+
case let (.some(ty0), .some(ty1)):
211+
return Bool(Builtin.is_same_metatype(ty0, ty1))
212+
default: return false
213+
}
214+
}
215+
216+
@usableFromInline
217+
@_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1)
218+
internal func != (t0: Any.Type?, t1: Any.Type?) -> Bool {
219+
!(t0 == t1)
220+
}
221+
#else
222+
// FIXME: $Embedded doesn't grok `any (~Copyable & Escapable).Type` yet (rdar://145706221)
223+
161224
/// Returns a Boolean value indicating whether two types are identical.
162225
///
163226
/// - Parameters:
@@ -186,7 +249,7 @@ public func == (t0: Any.Type?, t1: Any.Type?) -> Bool {
186249
public func != (t0: Any.Type?, t1: Any.Type?) -> Bool {
187250
return !(t0 == t1)
188251
}
189-
252+
#endif
190253

191254
/// Tell the optimizer that this code is unreachable if condition is
192255
/// known at compile-time to be true. If condition is false, or true

test/Constraints/operator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ func rdar_60185506() {
277277
func rdar60727310() {
278278
func myAssertion<T>(_ a: T, _ op: ((T,T)->Bool), _ b: T) {}
279279
var e: Error? = nil
280-
myAssertion(e, ==, nil) // expected-error {{cannot convert value of type '(any Error)?' to expected argument type '(any Any.Type)?'}}
280+
myAssertion(e, ==, nil) // expected-error {{cannot convert value of type '(any Error)?' to expected argument type '(any (~Copyable & ~Escapable).Type)?'}}
281281
}
282282

283283
// https://github.com/apple/swift/issues/54877

test/IDE/complete_call_as_function.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ func testCallAsFunction(add: Adder, addTy: Adder.Type) {
4444
// METATYPE_NO_DOT-DAG: Decl[InstanceMethod]/CurrNominal: .callAsFunction({#(self): Adder#})[#(x: Int, y: Int) -> Int#];
4545
// METATYPE_NO_DOT-DAG: Decl[Constructor]/CurrNominal: .init({#base: Int#})[#Adder#];
4646
// METATYPE_NO_DOT-DAG: Keyword[self]/CurrNominal: .self[#Adder.Type#];
47-
// METATYPE_NO_DOT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: != {#(any Any.Type)?#}[#Bool#];
48-
// METATYPE_NO_DOT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: == {#(any Any.Type)?#}[#Bool#];
47+
// METATYPE_NO_DOT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: != {#(any (~Copyable & ~Escapable).Type)?#}[#Bool#];
48+
// METATYPE_NO_DOT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: == {#(any (~Copyable & ~Escapable).Type)?#}[#Bool#];
4949

5050
let _ = addTy.#^METATYPE_DOT^#;
5151
// METATYPE_DOT: Begin completions, 3 items

test/IDE/complete_operators.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ func testInfix15<T: P where T.T == S2>() {
212212
// INFIX_15-DAG: Decl[InstanceMethod]/CurrNominal: .foo({#(self): P#})[#() -> S2#]; name=foo(:)
213213
// INFIX_15-DAG: Keyword[self]/CurrNominal: .self[#T.Type#]; name=self
214214
// INFIX_15-DAG: Keyword/CurrNominal: .Type[#T.Type#]; name=Type
215-
// INFIX_15-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: != {#(any Any.Type)?#}[#Bool#];
216-
// INFIX_15-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: == {#(any Any.Type)?#}[#Bool#];
215+
// INFIX_15-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: != {#(any (~Copyable & ~Escapable).Type)?#}[#Bool#];
216+
// INFIX_15-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: == {#(any (~Copyable & ~Escapable).Type)?#}[#Bool#];
217217

218218
func testInfix16<T: P where T.T == S2>() {
219219
T.foo#^INFIX_16^#

test/expr/expressions.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -758,15 +758,15 @@ func invalidDictionaryLiteral() {
758758
//===----------------------------------------------------------------------===//
759759
// nil/metatype comparisons
760760
//===----------------------------------------------------------------------===//
761-
_ = Int.self == nil // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' always returns false}}
762-
_ = nil == Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' always returns false}}
763-
_ = Int.self != nil // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' always returns true}}
764-
_ = nil != Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' always returns true}}
765-
766-
_ = Int.self == .none // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'Optional.none' always returns false}}
767-
_ = .none == Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'Optional.none' always returns false}}
768-
_ = Int.self != .none // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'Optional.none' always returns true}}
769-
_ = .none != Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'Optional.none' always returns true}}
761+
_ = Int.self == nil // expected-warning {{comparing non-optional value of type 'any (~Copyable & ~Escapable).Type' to 'nil' always returns false}}
762+
_ = nil == Int.self // expected-warning {{comparing non-optional value of type 'any (~Copyable & ~Escapable).Type' to 'nil' always returns false}}
763+
_ = Int.self != nil // expected-warning {{comparing non-optional value of type 'any (~Copyable & ~Escapable).Type' to 'nil' always returns true}}
764+
_ = nil != Int.self // expected-warning {{comparing non-optional value of type 'any (~Copyable & ~Escapable).Type' to 'nil' always returns true}}
765+
766+
_ = Int.self == .none // expected-warning {{comparing non-optional value of type 'any (~Copyable & ~Escapable).Type' to 'Optional.none' always returns false}}
767+
_ = .none == Int.self // expected-warning {{comparing non-optional value of type 'any (~Copyable & ~Escapable).Type' to 'Optional.none' always returns false}}
768+
_ = Int.self != .none // expected-warning {{comparing non-optional value of type 'any (~Copyable & ~Escapable).Type' to 'Optional.none' always returns true}}
769+
_ = .none != Int.self // expected-warning {{comparing non-optional value of type 'any (~Copyable & ~Escapable).Type' to 'Optional.none' always returns true}}
770770

771771
// <rdar://problem/19032294> Disallow postfix ? when not chaining
772772
func testOptionalChaining(_ a : Int?, b : Int!, c : Int??) {

0 commit comments

Comments
 (0)