Skip to content

Commit 6a4bcb1

Browse files
author
ematejska
authored
Merge pull request #5563 from slavapestov/anyhashable-function-conversion-3.0
SILGen: Add AnyHashable erasure support for function conversions [3.0]
2 parents a29f9a1 + 9d9ddf3 commit 6a4bcb1

File tree

4 files changed

+62
-8
lines changed

4 files changed

+62
-8
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,23 +1326,34 @@ RValue RValueEmitter::visitErasureExpr(ErasureExpr *E, SGFContext C) {
13261326
return RValue(SGF, E, mv);
13271327
}
13281328

1329-
RValue RValueEmitter::visitAnyHashableErasureExpr(AnyHashableErasureExpr *E,
1330-
SGFContext C) {
1329+
RValue SILGenFunction::emitAnyHashableErasure(SILLocation loc,
1330+
ManagedValue value,
1331+
Type type,
1332+
ProtocolConformanceRef conformance,
1333+
SGFContext C) {
13311334
// Ensure that the intrinsic function exists.
1332-
auto convertFn = SGF.SGM.getConvertToAnyHashable(E);
1333-
if (!convertFn) return SGF.emitUndefRValue(E, E->getType());
1335+
auto convertFn = SGM.getConvertToAnyHashable(loc);
1336+
if (!convertFn)
1337+
return emitUndefRValue(
1338+
loc, getASTContext().getAnyHashableDecl()->getDeclaredType());
13341339

13351340
// Construct the substitution for T: Hashable.
1336-
ProtocolConformanceRef conformances[] = { E->getConformance() };
1337-
Substitution sub(E->getSubExpr()->getType(),
1338-
SGF.getASTContext().AllocateCopy(conformances));
1341+
ProtocolConformanceRef conformances[] = { conformance };
1342+
Substitution sub(type, getASTContext().AllocateCopy(conformances));
13391343

1344+
return emitApplyOfLibraryIntrinsic(loc, convertFn, sub, value, C);
1345+
}
1346+
1347+
RValue RValueEmitter::visitAnyHashableErasureExpr(AnyHashableErasureExpr *E,
1348+
SGFContext C) {
13401349
// Emit the source value into a temporary.
13411350
auto sourceOrigType = AbstractionPattern::getOpaque();
13421351
auto source =
13431352
SGF.emitMaterializedRValueAsOrig(E->getSubExpr(), sourceOrigType);
13441353

1345-
return SGF.emitApplyOfLibraryIntrinsic(E, convertFn, sub, source, C);
1354+
return SGF.emitAnyHashableErasure(E, source,
1355+
E->getSubExpr()->getType(),
1356+
E->getConformance(), C);
13461357
}
13471358

13481359
/// Treating this as a successful operation, turn a CMV into a +1 MV.

lib/SILGen/SILGenFunction.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,12 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
12031203

12041204
void emitReturnExpr(SILLocation loc, Expr *ret);
12051205

1206+
RValue emitAnyHashableErasure(SILLocation loc,
1207+
ManagedValue value,
1208+
Type type,
1209+
ProtocolConformanceRef conformance,
1210+
SGFContext C);
1211+
12061212
/// Turn a consumable managed value into a +1 managed value.
12071213
ManagedValue getManagedValue(SILLocation loc,
12081214
ConsumableManagedValue value);

lib/SILGen/SILGenPoly.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,21 @@ ManagedValue Transform::transform(ManagedValue v,
521521
ctxt);
522522
}
523523

524+
// - T : Hashable to AnyHashable
525+
if (isa<StructType>(outputSubstType) &&
526+
outputSubstType->getAnyNominal() ==
527+
SGF.getASTContext().getAnyHashableDecl()) {
528+
auto *protocol = SGF.getASTContext().getProtocol(
529+
KnownProtocolKind::Hashable);
530+
auto conformance = SGF.SGM.M.getSwiftModule()->lookupConformance(
531+
inputSubstType, protocol, nullptr);
532+
auto result = SGF.emitAnyHashableErasure(Loc, v, inputSubstType,
533+
*conformance, ctxt);
534+
if (result.isInContext())
535+
return ManagedValue::forInContext();
536+
return std::move(result).getAsSingleValue(SGF, Loc);
537+
}
538+
524539
// Should have handled the conversion in one of the cases above.
525540
llvm_unreachable("Unhandled transform?");
526541
}

test/SILGen/function_conversion.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,3 +429,25 @@ func convTupleScalar(_ f1: @escaping (Q) -> (),
429429
func convTupleScalarOpaque<T>(_ f: @escaping (T...) -> ()) -> ((_ args: T...) -> ())? {
430430
return f
431431
}
432+
433+
// ==== Make sure we support AnyHashable erasure
434+
435+
// CHECK-LABEL: sil hidden @_TF19function_conversion15convAnyHashableuRxs8HashablerFT1tx_T_
436+
// CHECK: function_ref @_TFF19function_conversion15convAnyHashableuRxs8HashablerFT1tx_T_U_FTVs11AnyHashableS1__Sb
437+
// CHECK: function_ref @_TTRGRxs8HashablerXFo_iVs11AnyHashableiS0__dSb_XFo_ixix_dSb_
438+
439+
// CHECK-LABEL: sil shared [transparent] [reabstraction_thunk] @_TTRGRxs8HashablerXFo_iVs11AnyHashableiS0__dSb_XFo_ixix_dSb_ : $@convention(thin) <T where T : Hashable> (@in T, @in T, @owned @callee_owned (@in AnyHashable, @in AnyHashable) -> Bool) -> Bool
440+
// CHECK: alloc_stack $AnyHashable
441+
// CHECK: function_ref @_swift_convertToAnyHashable
442+
// CHECK: apply {{.*}}<T>
443+
// CHECK: alloc_stack $AnyHashable
444+
// CHECK: function_ref @_swift_convertToAnyHashable
445+
// CHECK: apply {{.*}}<T>
446+
// CHECK: return
447+
448+
449+
func convAnyHashable<T : Hashable>(t: T) {
450+
let fn: (T, T) -> Bool = {
451+
(x: AnyHashable, y: AnyHashable) in x == y
452+
}
453+
}

0 commit comments

Comments
 (0)