Skip to content

Commit 48ea837

Browse files
committed
Manually define _rawHashValue in compatibility libraries, AST fixes for builtin protocol conformance
Remember to use substituted type in builtin conformance substitution
1 parent 05cc4aa commit 48ea837

File tree

4 files changed

+59
-25
lines changed

4 files changed

+59
-25
lines changed

lib/AST/ProtocolConformance.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,9 +1170,24 @@ ProtocolConformance::subst(TypeSubstitutionFn subs,
11701170
const_cast<ProtocolConformance *>(this),
11711171
subMap);
11721172
}
1173-
case ProtocolConformanceKind::Self:
1174-
case ProtocolConformanceKind::Builtin:
1173+
case ProtocolConformanceKind::Self: {
11751174
return const_cast<ProtocolConformance*>(this);
1175+
}
1176+
case ProtocolConformanceKind::Builtin: {
1177+
auto origType = getType();
1178+
if (!origType->hasTypeParameter() &&
1179+
!origType->hasArchetype())
1180+
return const_cast<ProtocolConformance *>(this);
1181+
1182+
auto substType = origType.subst(subs, conformances, options);
1183+
if (substType->isEqual(origType))
1184+
return const_cast<ProtocolConformance *>(this);
1185+
1186+
// All builtin conformances are concrete at the moment, so it's safe to
1187+
// directly call getConcrete.
1188+
return getProtocol()->getModuleContext()
1189+
->lookupConformance(substType, getProtocol()).getConcrete();
1190+
}
11761191
case ProtocolConformanceKind::Inherited: {
11771192
// Substitute the base.
11781193
auto inheritedConformance

lib/AST/SubstitutionMap.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,19 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
420420
// For the second step, we're looking into the requirement signature for
421421
// this protocol.
422422
auto concrete = conformance.getConcrete();
423-
auto normal = concrete->getRootNormalConformance();
423+
auto root = concrete->getRootConformance();
424+
425+
// If we see a builtin conformance here as the root, simply lookup the
426+
// conformance for the substitute type.
427+
if (isa<BuiltinProtocolConformance>(root)) {
428+
auto substType = type.subst(*this);
429+
if (substType->hasError())
430+
return ProtocolConformanceRef(proto);
431+
432+
return proto->getParentModule()->lookupConformance(substType, proto);
433+
}
434+
435+
auto normal = cast<NormalProtocolConformance>(root);
424436

425437
// If we haven't set the signature conformances yet, force the issue now.
426438
if (normal->getSignatureConformances().empty()) {

stdlib/toolchain/Compatibility53/BuiltinProtocolConformances.cpp

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,27 @@ void _emplaceTupleHashableDescriptor() {
497497
*tupleHashableConf = intptr_t(hashable) - intptr_t(tupleHashableConf);
498498
}
499499

500+
using RawHashValueFn = SWIFT_CC(swift) intptr_t(intptr_t seed,
501+
const Metadata *Self,
502+
const WitnessTable *witnessTable,
503+
SWIFT_CONTEXT OpaqueValue *value);
504+
505+
static RawHashValueFn *get_rawHashValueDefaultImplFunc() {
506+
auto func = SWIFT_LAZY_CONSTANT(
507+
reinterpret_cast<RawHashValueFn *>(
508+
dlsym(RTLD_DEFAULT, "$sSHsE13_rawHashValue4seedS2i_tF")));
509+
return func;
510+
}
511+
512+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
513+
intptr_t _swift_tupleHashable_rawHashValue(intptr_t seed,
514+
SWIFT_CONTEXT OpaqueValue *tuple,
515+
const Metadata *Self,
516+
const WitnessTable *witnessTable) {
517+
auto _rawHashValue = get_rawHashValueDefaultImplFunc();
518+
return _rawHashValue(seed, Self, witnessTable, tuple);
519+
}
520+
500521
// The base Equatable protocol is itself a requirement, thus the requirement
501522
// count is 4 (Equatable + hashValue + hash(into:) + _rawHashValue) and the
502523
// witness is the tuple Equatable table.
@@ -507,24 +528,10 @@ _WitnessTable<4> _swift_tupleHashable_wt = {
507528
reinterpret_cast<const void *>(&_swift_tupleEquatable_wt),
508529
reinterpret_cast<void *>(_swift_tupleHashable_hashValue),
509530
reinterpret_cast<void *>(_swift_tupleHashable_hash),
510-
nullptr
531+
reinterpret_cast<void *>(_swift_tupleHashable_rawHashValue)
511532
}
512533
};
513534

514-
static void *get_rawHashValueDefaultImplFunc() {
515-
auto impl = SWIFT_LAZY_CONSTANT(
516-
dlsym(RTLD_DEFAULT, "$sSHsE13_rawHashValue4seedS2i_tF"));
517-
return impl;
518-
}
519-
520-
// Due to the fact that the compatibility libraries can't have a hard
521-
// dependency to libswiftCore (which is where the _rawHashValue default impl
522-
// lives), we have to manually implant this before calling any user code.
523-
__attribute__((constructor))
524-
void _emplaceTupleHashable_rawHashValueDefaultImpl() {
525-
_swift_tupleHashable_wt.Witnesses[3] = get_rawHashValueDefaultImplFunc();
526-
}
527-
528535
using HashValueFn = SWIFT_CC(swift) intptr_t(OpaqueValue *value, Metadata *Self,
529536
void *witnessTable);
530537
using HasherCombineFn = SWIFT_CC(swift) void(OpaqueValue *value,
@@ -533,17 +540,17 @@ using HasherCombineFn = SWIFT_CC(swift) void(OpaqueValue *value,
533540
SWIFT_CONTEXT OpaqueValue *hasher);
534541

535542
static HashValueFn *get_hashValueFunc() {
536-
auto descriptor = SWIFT_LAZY_CONSTANT(
543+
auto func = SWIFT_LAZY_CONSTANT(
537544
reinterpret_cast<HashValueFn *>(
538545
dlsym(RTLD_DEFAULT, XSTR(SWIFT_HASHVALUE_FUNC))));
539-
return descriptor;
546+
return func;
540547
}
541548

542549
static HasherCombineFn *getHashCombineFunc() {
543-
auto descriptor = SWIFT_LAZY_CONSTANT(
550+
auto func = SWIFT_LAZY_CONSTANT(
544551
reinterpret_cast<HasherCombineFn *>(
545552
dlsym(RTLD_DEFAULT, XSTR(SWIFT_HASHER_COMBINE_FUNC))));
546-
return descriptor;
553+
return func;
547554
}
548555

549556
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)

test/IRGen/builtin_conformances.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@ public func hashValue<T: Hashable>(for instance: T) -> Int {
7474

7575
public func useHashable<T: Hashable>(_ thing: T) -> Int {
7676
// CHECK: [[USE_HASHABLE_WT:%.*]] = call i8** @swift_getWitnessTable(%swift.protocol_conformance_descriptor* @_swift_tupleHashable_conf, %swift.type* {{%.*}}, i8*** {{%.*}})
77-
// CHECK-NEXT: {{%.*}} = call swiftcc i64 {{.*}}(%swift.opaque* noalias nocapture {{%.*}}, %swift.type* {{%.*}}, i8** [[USE_HASHABLE_WT]])
77+
// CHECK-NEXT: {{%.*}} = call swiftcc i{{.*}} {{.*}}(%swift.opaque* noalias nocapture {{%.*}}, %swift.type* {{%.*}}, i8** [[USE_HASHABLE_WT]])
7878
hashValue(for: (thing, thing))
7979
}
8080

8181
public func testTupleHashable() {
8282
// CHECK: [[TEST_TUPLE_HASHABLE_WT1:%.*]] = call i8** @swift_getWitnessTable(%swift.protocol_conformance_descriptor* @_swift_tupleHashable_conf, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @"$sytN", i32 0, i32 1), i8*** undef)
83-
// CHECK: {{%.*}} = call swiftcc i64 {{.*}}(%swift.opaque* noalias nocapture undef, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @"$sytN", i32 0, i32 1), i8** [[TEST_TUPLE_HASHABLE_WT1]])
83+
// CHECK: {{%.*}} = call swiftcc i{{.*}} {{.*}}(%swift.opaque* noalias nocapture undef, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @"$sytN", i32 0, i32 1), i8** [[TEST_TUPLE_HASHABLE_WT1]])
8484
let _ = hashValue(for: ())
8585

86-
// CHECK: {{%.*}} = call swiftcc i64 {{.*}}(%swift.type* {{%.*}}, i8** [[TEST_TUPLE_HASHABLE_WT1]], {{%.*}} noalias nocapture swiftself undef)
86+
// CHECK: {{%.*}} = call swiftcc i{{.*}} {{.*}}(%swift.type* {{%.*}}, i8** [[TEST_TUPLE_HASHABLE_WT1]], {{%.*}} noalias nocapture swiftself undef)
8787
let _ = Wrapper(value: ()).hashValue
8888
}

0 commit comments

Comments
 (0)