Skip to content

Commit 8e29494

Browse files
committed
Allow Hashable: ~Copyable
1 parent 8243dfa commit 8e29494

File tree

11 files changed

+134
-19
lines changed

11 files changed

+134
-19
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"
@@ -2401,8 +2403,20 @@ RValue SILGenFunction::emitAnyHashableErasure(SILLocation loc,
24012403
return emitUndefRValue(loc, getASTContext().getAnyHashableType());
24022404

24032405
// Construct the substitution for T: Hashable.
2404-
auto subMap = SubstitutionMap::getProtocolSubstitutions(
2405-
conformance.getProtocol(), type, conformance);
2406+
auto subMap = SubstitutionMap::get(convertFn->getGenericSignature(), type,
2407+
[&](InFlightSubstitution &ifs,
2408+
Type ty,
2409+
ProtocolDecl *proto) -> ProtocolConformanceRef {
2410+
switch (*proto->getKnownProtocolKind()) {
2411+
case KnownProtocolKind::Hashable:
2412+
return conformance;
2413+
case KnownProtocolKind::Copyable:
2414+
case KnownProtocolKind::Escapable:
2415+
return lookupConformance(type, proto);
2416+
default:
2417+
llvm_unreachable("no other conformances should be involved");
2418+
}
2419+
});
24062420

24072421
return emitApplyOfLibraryIntrinsic(loc, convertFn, subMap, value, C);
24082422
}

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/IRGen/keypaths.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ sil_vtable C2 {}
311311
// CHECK-SAME: <i32 0x3fffffe>
312312

313313
// CHECK-LABEL: @"generic environment SHRzSHR_r0_l" = linkonce_odr hidden constant
314-
// CHECK-SAME: i32 8193, i16 2, i8 -128, i8 -128, i32 128
314+
// CHECK-SAME: i32 16385, i16 2, i8 -128, i8 -128, i32 128
315315

316316
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @stored_property_fixed_offsets()
317317
sil @stored_property_fixed_offsets : $@convention(thin) () -> () {

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/api-digester/Outputs/stability-stdlib-source-base.swift.expected

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ Protocol FixedWidthInteger has added inherited protocol Copyable
116116
Protocol FixedWidthInteger has added inherited protocol Escapable
117117
Protocol FloatingPoint has added inherited protocol Copyable
118118
Protocol FloatingPoint has added inherited protocol Escapable
119-
Protocol Hashable has added inherited protocol Copyable
120119
Protocol Hashable has added inherited protocol Escapable
121120
Protocol Identifiable has added inherited protocol Copyable
122121
Protocol Identifiable has added inherited protocol Escapable
@@ -387,3 +386,9 @@ Func Equatable.==(_:_:) has generic signature change from <Self where Self : Swi
387386
Func Equatable.==(_:_:) has parameter 0 changing from Default to Shared
388387
Func Equatable.==(_:_:) has parameter 1 changing from Default to Shared
389388

389+
// Hashable: ~Copyable
390+
Protocol Hashable has generic signature change from <Self : Swift.Equatable> to <Self : Swift.Equatable, Self : ~Copyable>
391+
Accessor Hashable.hashValue.Get() has generic signature change from <Self where Self : Swift.Hashable> to <Self where Self : Swift.Hashable, Self : ~Copyable>
392+
Func Hashable.hash(into:) has generic signature change from <Self where Self : Swift.Hashable> to <Self where Self : Swift.Hashable, Self : ~Copyable>
393+
Func Hasher.combine(_:) has generic signature change from <H where H : Swift.Hashable> to <H where H : Swift.Hashable, H : ~Copyable>
394+
Func Hasher.combine(_:) has parameter 0 changing from Default to Shared

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ Protocol FixedWidthInteger has added inherited protocol Copyable
234234
Protocol FixedWidthInteger has added inherited protocol Escapable
235235
Protocol FloatingPoint has added inherited protocol Copyable
236236
Protocol FloatingPoint has added inherited protocol Escapable
237-
Protocol Hashable has added inherited protocol Copyable
238237
Protocol Hashable has added inherited protocol Escapable
239238
Protocol Identifiable has added inherited protocol Copyable
240239
Protocol Identifiable has added inherited protocol Escapable
@@ -888,4 +887,21 @@ Func Equatable.==(_:_:) has generic signature change from <Self where Self : Swi
888887
Func Equatable.==(_:_:) has parameter 0 changing from Default to Shared
889888
Func Equatable.==(_:_:) has parameter 1 changing from Default to Shared
890889

890+
// Hashable: ~Copyable
891+
Protocol Hashable has generic signature change from <Self : Swift.Equatable> to <Self : Swift.Equatable, Self : ~Copyable>
892+
Accessor Hashable.hashValue.Get() has generic signature change from <Self where Self : Swift.Hashable> to <Self where Self : Swift.Hashable, Self : ~Copyable>
893+
Func Hashable._rawHashValue(seed:) has generic signature change from <Self where Self : Swift.Hashable> to <Self where Self : Swift.Hashable, Self : ~Copyable>
894+
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'
895+
Func Hashable._rawHashValue(seed:) is now with @_preInverseGenerics
896+
Func Hashable.hash(into:) has generic signature change from <Self where Self : Swift.Hashable> to <Self where Self : Swift.Hashable, Self : ~Copyable>
897+
Func Hasher.combine(_:) has generic signature change from <H where H : Swift.Hashable> to <H where H : Swift.Hashable, H : ~Copyable>
898+
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) -> ()'
899+
Func Hasher.combine(_:) has parameter 0 changing from Default to Shared
900+
Func Hasher.combine(_:) is now with @_preInverseGenerics
901+
Func _hashValue(for:) has generic signature change from <H where H : Swift.Hashable> to <H where H : Swift.Hashable, H : ~Copyable>
902+
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'
903+
Func _hashValue(for:) has parameter 0 changing from Default to Shared
904+
Func _hashValue(for:) is now with @_preInverseGenerics
905+
906+
891907
// *** DO NOT DISABLE OR XFAIL THIS TEST. *** (See comment above.)

0 commit comments

Comments
 (0)