Skip to content

Commit 9dd9e96

Browse files
Allow Hashable: ~Copyable (#85748)
Builds on #85746 which covers Equatable.
1 parent b8e3e4b commit 9dd9e96

File tree

11 files changed

+135
-21
lines changed

11 files changed

+135
-21
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#include "swift/AST/Expr.h"
3838
#include "swift/AST/ForeignErrorConvention.h"
3939
#include "swift/AST/GenericEnvironment.h"
40+
#include "swift/AST/InFlightSubstitution.h"
41+
#include "swift/AST/KnownProtocols.h"
4042
#include "swift/AST/ParameterList.h"
4143
#include "swift/AST/ProtocolConformance.h"
4244
#include "swift/AST/SubstitutionMap.h"
@@ -2430,8 +2432,20 @@ RValue SILGenFunction::emitAnyHashableErasure(SILLocation loc,
24302432
return emitUndefRValue(loc, getASTContext().getAnyHashableType());
24312433

24322434
// Construct the substitution for T: Hashable.
2433-
auto subMap = SubstitutionMap::getProtocolSubstitutions(
2434-
conformance.getProtocol(), type, conformance);
2435+
auto subMap = SubstitutionMap::get(convertFn->getGenericSignature(), type,
2436+
[&](InFlightSubstitution &ifs,
2437+
Type ty,
2438+
ProtocolDecl *proto) -> ProtocolConformanceRef {
2439+
switch (*proto->getKnownProtocolKind()) {
2440+
case KnownProtocolKind::Hashable:
2441+
return conformance;
2442+
case KnownProtocolKind::Copyable:
2443+
case KnownProtocolKind::Escapable:
2444+
return lookupConformance(type, proto);
2445+
default:
2446+
llvm_unreachable("no other conformances should be involved");
2447+
}
2448+
});
24352449

24362450
return emitApplyOfLibraryIntrinsic(loc, convertFn, subMap, value, C);
24372451
}

stdlib/public/core/Hashable.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
/// print("New tap detected at (\(nextTap.x), \(nextTap.y)).")
102102
/// }
103103
/// // Prints "New tap detected at (0, 1).")
104-
public protocol Hashable: Equatable {
104+
public protocol Hashable: Equatable & ~Copyable {
105105
/// The hash value.
106106
///
107107
/// Hash values are not guaranteed to be equal across different executions of
@@ -135,9 +135,10 @@ public protocol Hashable: Equatable {
135135
func _rawHashValue(seed: Int) -> Int
136136
}
137137

138-
extension Hashable {
138+
extension Hashable where Self: ~Copyable {
139139
@inlinable
140140
@inline(__always)
141+
@_preInverseGenerics
141142
public func _rawHashValue(seed: Int) -> Int {
142143
var hasher = Hasher(_seed: seed)
143144
hasher.combine(self)
@@ -148,7 +149,8 @@ extension Hashable {
148149
// Called by synthesized `hashValue` implementations.
149150
@inlinable
150151
@inline(__always)
151-
public func _hashValue<H: Hashable>(for value: H) -> Int {
152+
@_preInverseGenerics
153+
public func _hashValue<H: Hashable & ~Copyable>(for value: borrowing H) -> Int {
152154
return value._rawHashValue(seed: 0)
153155
}
154156

stdlib/public/core/Hasher.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ public struct Hasher {
350350
/// - Parameter value: A value to add to the hasher.
351351
@inlinable
352352
@inline(__always)
353-
public mutating func combine<H: Hashable>(_ value: H) {
353+
@_preInverseGenerics
354+
public mutating func combine<H: Hashable & ~Copyable>(_ value: borrowing H) {
354355
value.hash(into: &self)
355356
}
356357

test/Frontend/dump-parse.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ enum TrailingSemi {
5858
// CHECK-AST-LABEL: (func_decl{{.*}}"generic(_:)" "<T : Hashable>" interface_type="<T where T : Hashable> (T) -> ()" access=internal captures=(<generic> {{.*}})
5959
func generic<T: Hashable>(_: T) {}
6060
// CHECK-AST: (pattern_binding_decl
61-
// CHECK-AST: (processed_init=declref_expr type="(Int) -> ()" location={{.*}} range={{.*}} decl="main.(file).generic@{{.*}} [with (substitution_map generic_signature=<T where T : Hashable> T -> Int)]" function_ref=unapplied))
61+
// CHECK-AST: (processed_init=declref_expr type="(Int) -> ()" location={{.*}} range={{.*}} decl="main.(file).generic@{{.*}} [with (substitution_map generic_signature=<T where T : Copyable, T : Hashable> T -> Int)]" function_ref=unapplied))
6262
let _: (Int) -> () = generic
6363

6464
// Closures should be marked as escaping or not.

test/Parse/inverses.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ public struct MoveOnlyS1<T> : ~Copyable { /*deinit {}*/ }
5252
public struct MoveOnlyS2<T: Equatable> : ~Copyable { /*deinit {}*/ }
5353
public struct MoveOnlyS3<T: ~Copyable> : ~Copyable { /*deinit {}*/ }
5454

55-
protocol Rope<Element>: Hashable, ~Copyable { // expected-error {{'Self' required to be 'Copyable' but is marked with '~Copyable'}}
55+
protocol CopyHashable { }
56+
57+
protocol Rope<Element>: CopyHashable, ~Copyable { // expected-error {{'Self' required to be 'Copyable' but is marked with '~Copyable'}}
5658
associatedtype Element: ~Copyable
5759
}
5860

@@ -102,8 +104,8 @@ typealias Z4 = ~Rope<Int> // expected-error {{type 'Rope<Int>' cannot be suppres
102104
typealias Z5 = (~Int) -> Void // expected-error {{type 'Int' cannot be suppressed}}
103105
typealias Z6 = ~() -> () // expected-error {{single argument function types require parentheses}}
104106
// expected-error@-1 {{type '()' cannot be suppressed}}
105-
typealias Z7 = ~(Copyable & Hashable) // expected-error {{type 'Hashable' cannot be suppressed}}
106-
typealias Z8 = ~Copyable & Hashable // expected-error {{composition cannot contain '~Copyable' when another member requires 'Copyable'}}
107+
typealias Z7 = ~(Copyable & CopyHashable) // expected-error {{type 'CopyHashable' cannot be suppressed}}
108+
typealias Z8 = ~Copyable & CopyHashable // expected-error {{composition cannot contain '~Copyable' when another member requires 'Copyable'}}
107109

108110
struct NotAProtocol {}
109111

test/SILGen/synthesized_conformance_enum.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ extension NoValues: Codable {}
8383

8484
// CHECK-LABEL: sil_witness_table hidden <T where T : Hashable> Enum<T>: Hashable module synthesized_conformance_enum {
8585
// CHECK-DAG: base_protocol Equatable: <T where T : Equatable> Enum<T>: Equatable module synthesized_conformance_enum
86-
// CHECK-DAG: method #Hashable.hashValue!getter: <Self where Self : Hashable> (Self) -> () -> Int : @$s28synthesized_conformance_enum4EnumOyxGSHAASHRzlSH9hashValueSivgTW // protocol witness for Hashable.hashValue.getter in conformance <A> Enum<A>
87-
// CHECK-DAG: method #Hashable.hash: <Self where Self : Hashable> (Self) -> (inout Hasher) -> () : @$s28synthesized_conformance_enum4EnumOyxGSHAASHRzlSH4hash4intoys6HasherVz_tFTW // protocol witness for Hashable.hash(into:) in conformance <A> Enum<A>
88-
// CHECK-DAG: method #Hashable._rawHashValue: <Self where Self : Hashable> (Self) -> (Int) -> Int : @$s28synthesized_conformance_enum4EnumOyxGSHAASHRzlSH13_rawHashValue4seedS2i_tFTW // protocol witness for Hashable._rawHashValue(seed:) in conformance <A> Enum<A>
86+
// CHECK-DAG: method #Hashable.hashValue!getter: <Self where Self : Hashable, Self : ~Copyable> (Self) -> () -> Int : @$s28synthesized_conformance_enum4EnumOyxGSHAASHRzlSH9hashValueSivgTW // protocol witness for Hashable.hashValue.getter in conformance <A> Enum<A>
87+
// CHECK-DAG: method #Hashable.hash: <Self where Self : Hashable, Self : ~Copyable> (Self) -> (inout Hasher) -> () : @$s28synthesized_conformance_enum4EnumOyxGSHAASHRzlSH4hash4intoys6HasherVz_tFTW // protocol witness for Hashable.hash(into:) in conformance <A> Enum<A>
88+
// CHECK-DAG: method #Hashable._rawHashValue: <Self where Self : Hashable, Self : ~Copyable> (Self) -> (Int) -> Int : @$s28synthesized_conformance_enum4EnumOyxGSHAASHRzlSH13_rawHashValue4seedS2i_tFTW // protocol witness for Hashable._rawHashValue(seed:) in conformance <A> Enum<A>
8989
// CHECK-DAG: conditional_conformance (T: Hashable): dependent
9090
// CHECK: }
9191

test/SILGen/synthesized_conformance_struct.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ extension Struct: Codable where T: Codable {}
6969

7070
// CHECK-LABEL: sil_witness_table hidden <T where T : Hashable> Struct<T>: Hashable module synthesized_conformance_struct {
7171
// CHECK-DAG: base_protocol Equatable: <T where T : Equatable> Struct<T>: Equatable module synthesized_conformance_struct
72-
// CHECK-DAG: method #Hashable.hashValue!getter: <Self where Self : Hashable> (Self) -> () -> Int : @$s30synthesized_conformance_struct6StructVyxGSHAASHRzlSH9hashValueSivgTW // protocol witness for Hashable.hashValue.getter in conformance <A> Struct<A>
73-
// CHECK-DAG: method #Hashable.hash: <Self where Self : Hashable> (Self) -> (inout Hasher) -> () : @$s30synthesized_conformance_struct6StructVyxGSHAASHRzlSH4hash4intoys6HasherVz_tFTW // protocol witness for Hashable.hash(into:) in conformance <A> Struct<A>
74-
// CHECK-DAG: method #Hashable._rawHashValue: <Self where Self : Hashable> (Self) -> (Int) -> Int : @$s30synthesized_conformance_struct6StructVyxGSHAASHRzlSH13_rawHashValue4seedS2i_tFTW // protocol witness for Hashable._rawHashValue(seed:) in conformance <A> Struct<A>
72+
// CHECK-DAG: method #Hashable.hashValue!getter: <Self where Self : Hashable, Self : ~Copyable> (Self) -> () -> Int : @$s30synthesized_conformance_struct6StructVyxGSHAASHRzlSH9hashValueSivgTW // protocol witness for Hashable.hashValue.getter in conformance <A> Struct<A>
73+
// CHECK-DAG: method #Hashable.hash: <Self where Self : Hashable, Self : ~Copyable> (Self) -> (inout Hasher) -> () : @$s30synthesized_conformance_struct6StructVyxGSHAASHRzlSH4hash4intoys6HasherVz_tFTW // protocol witness for Hashable.hash(into:) in conformance <A> Struct<A>
74+
// CHECK-DAG: method #Hashable._rawHashValue: <Self where Self : Hashable, Self : ~Copyable> (Self) -> (Int) -> Int : @$s30synthesized_conformance_struct6StructVyxGSHAASHRzlSH13_rawHashValue4seedS2i_tFTW // protocol witness for Hashable._rawHashValue(seed:) in conformance <A> Struct<A>
7575
// CHECK-DAG: conditional_conformance (T: Hashable): dependent
7676
// CHECK: }
7777

test/Sema/moveonly_illegal_types.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ func basic_vararg(_ va: MO...) {} // expected-error {{noncopyable type 'MO' cann
5252
func illegalTypes<T>(_ t: T) {
5353
let _: Array<MO> // expected-error {{type 'MO' does not conform to protocol 'Copyable'}}
5454
let _: Maybe<MO> // expected-error {{type 'MO' does not conform to protocol 'Copyable'}}
55-
let _: Dictionary<MO, String> // expected-error {{type 'MO' does not conform to protocol 'Hashable'}}
55+
let _: Dictionary<MO, String> // expected-error {{type 'MO' does not conform to protocol 'Copyable'}}
5656
let _: [MO] // expected-error {{type 'MO' does not conform to protocol 'Copyable'}}
5757
let _: [String : MO] // expected-error {{type 'MO' does not conform to protocol 'Copyable'}}
58-
let _: [MO : MO] // expected-error {{type 'MO' does not conform to protocol 'Hashable'}}
59-
let _: [MO : T] // expected-error {{type 'MO' does not conform to protocol 'Hashable'}}
58+
let _: [MO : MO] // expected-error {{type 'MO' does not conform to protocol 'Copyable'}}
59+
let _: [MO : T] // expected-error {{type 'MO' does not conform to protocol 'Copyable'}}
6060

6161
_ = t as! ValBox<MO> // expected-error {{type 'MO' does not conform to protocol 'Copyable'}}
6262

test/api-digester/Outputs/stability-stdlib-source-base.swift.expected

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ Protocol FixedWidthInteger has added inherited protocol Copyable
114114
Protocol FixedWidthInteger has added inherited protocol Escapable
115115
Protocol FloatingPoint has added inherited protocol Copyable
116116
Protocol FloatingPoint has added inherited protocol Escapable
117-
Protocol Hashable has added inherited protocol Copyable
118117
Protocol Hashable has added inherited protocol Escapable
119118
Protocol Identifiable has added inherited protocol Copyable
120119
Protocol Identifiable has added inherited protocol Escapable
@@ -399,3 +398,10 @@ Func Comparable.>(_:_:) has parameter 1 changing from Default to Shared
399398
Func Comparable.>=(_:_:) has generic signature change from <Self where Self : Swift.Comparable> to <Self where Self : Swift.Comparable, Self : ~Copyable>
400399
Func Comparable.>=(_:_:) has parameter 0 changing from Default to Shared
401400
Func Comparable.>=(_:_:) has parameter 1 changing from Default to Shared
401+
402+
// Hashable: ~Copyable
403+
Protocol Hashable has generic signature change from <Self : Swift.Equatable> to <Self : Swift.Equatable, Self : ~Copyable>
404+
Accessor Hashable.hashValue.Get() has generic signature change from <Self where Self : Swift.Hashable> to <Self where Self : Swift.Hashable, Self : ~Copyable>
405+
Func Hashable.hash(into:) has generic signature change from <Self where Self : Swift.Hashable> to <Self where Self : Swift.Hashable, Self : ~Copyable>
406+
Func Hasher.combine(_:) has generic signature change from <H where H : Swift.Hashable> to <H where H : Swift.Hashable, H : ~Copyable>
407+
Func Hasher.combine(_:) has parameter 0 changing from Default to Shared

test/api-digester/stability-stdlib-abi-without-asserts.test

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,6 @@ Protocol FixedWidthInteger has added inherited protocol Copyable
232232
Protocol FixedWidthInteger has added inherited protocol Escapable
233233
Protocol FloatingPoint has added inherited protocol Copyable
234234
Protocol FloatingPoint has added inherited protocol Escapable
235-
Protocol Hashable has added inherited protocol Copyable
236235
Protocol Hashable has added inherited protocol Escapable
237236
Protocol Identifiable has added inherited protocol Copyable
238237
Protocol Identifiable has added inherited protocol Escapable
@@ -911,5 +910,20 @@ Func Comparable.>=(_:_:) has parameter 0 changing from Default to Shared
911910
Func Comparable.>=(_:_:) has parameter 1 changing from Default to Shared
912911
Func Comparable.>=(_:_:) is now with @_preInverseGenerics
913912

913+
// Hashable: ~Copyable
914+
Protocol Hashable has generic signature change from <Self : Swift.Equatable> to <Self : Swift.Equatable, Self : ~Copyable>
915+
Accessor Hashable.hashValue.Get() has generic signature change from <Self where Self : Swift.Hashable> to <Self where Self : Swift.Hashable, Self : ~Copyable>
916+
Func Hashable._rawHashValue(seed:) has generic signature change from <Self where Self : Swift.Hashable> to <Self where Self : Swift.Hashable, Self : ~Copyable>
917+
Func Hashable._rawHashValue(seed:) has mangled name changing from '(extension in Swift):Swift.Hashable._rawHashValue(seed: Swift.Int) -> Swift.Int' to '(extension in Swift):Swift.Hashable< where A: ~Swift.Copyable>._rawHashValue(seed: Swift.Int) -> Swift.Int'
918+
Func Hashable._rawHashValue(seed:) is now with @_preInverseGenerics
919+
Func Hashable.hash(into:) has generic signature change from <Self where Self : Swift.Hashable> to <Self where Self : Swift.Hashable, Self : ~Copyable>
920+
Func Hasher.combine(_:) has generic signature change from <H where H : Swift.Hashable> to <H where H : Swift.Hashable, H : ~Copyable>
921+
Func Hasher.combine(_:) has mangled name changing from 'Swift.Hasher.combine<A where A: Swift.Hashable>(A) -> ()' to 'Swift.Hasher.combine<A where A: Swift.Hashable, A: ~Swift.Copyable>(A) -> ()'
922+
Func Hasher.combine(_:) has parameter 0 changing from Default to Shared
923+
Func Hasher.combine(_:) is now with @_preInverseGenerics
924+
Func _hashValue(for:) has generic signature change from <H where H : Swift.Hashable> to <H where H : Swift.Hashable, H : ~Copyable>
925+
Func _hashValue(for:) has mangled name changing from 'Swift._hashValue<A where A: Swift.Hashable>(for: A) -> Swift.Int' to 'Swift._hashValue<A where A: Swift.Hashable, A: ~Swift.Copyable>(for: A) -> Swift.Int'
926+
Func _hashValue(for:) has parameter 0 changing from Default to Shared
927+
Func _hashValue(for:) is now with @_preInverseGenerics
914928

915929
// *** DO NOT DISABLE OR XFAIL THIS TEST. *** (See comment above.)

0 commit comments

Comments
 (0)