Skip to content

Commit cb95ee3

Browse files
committed
IRGen: Don't crash when emitting a capture descriptor containing an opened existential
1 parent 743aaa7 commit cb95ee3

File tree

4 files changed

+67
-9
lines changed

4 files changed

+67
-9
lines changed

lib/IRGen/GenReflection.cpp

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
601601
CanSILFunctionType SubstCalleeType;
602602
SubstitutionList Subs;
603603
const HeapLayout &Layout;
604+
604605
public:
605606
CaptureDescriptorBuilder(IRGenModule &IGM,
606607
SILFunction &Caller,
@@ -630,6 +631,35 @@ class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
630631
}
631632
}
632633

634+
/// Give up if we captured an opened existential type. Eventually we
635+
/// should figure out how to represent this.
636+
static bool hasOpenedExistential(CanSILFunctionType OrigCalleeType,
637+
const HeapLayout &Layout) {
638+
if (!OrigCalleeType->isPolymorphic() ||
639+
OrigCalleeType->isPseudogeneric())
640+
return false;
641+
642+
auto &Bindings = Layout.getBindings();
643+
for (unsigned i = 0; i < Bindings.size(); ++i) {
644+
// Skip protocol requirements (FIXME: for now?)
645+
if (Bindings[i].Protocol != nullptr)
646+
continue;
647+
648+
if (Bindings[i].TypeParameter->hasOpenedExistential())
649+
return true;
650+
}
651+
652+
auto ElementTypes = Layout.getElementTypes().slice(
653+
Layout.hasBindings() ? 1 : 0);
654+
for (auto ElementType : ElementTypes) {
655+
auto SwiftType = ElementType.getSwiftRValueType();
656+
if (SwiftType->hasOpenedExistential())
657+
return true;
658+
}
659+
660+
return false;
661+
}
662+
633663
/// Slice off the NecessaryBindings struct at the beginning, if it's there.
634664
/// We'll keep track of how many things are in the bindings struct with its
635665
/// own count in the capture descriptor.
@@ -660,8 +690,9 @@ class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
660690
continue;
661691

662692
auto Source = SourceBuilder.createClosureBinding(i);
663-
auto BindingType = Caller.mapTypeOutOfContext(Bindings[i].TypeParameter);
664-
SourceMap.push_back({BindingType->getCanonicalType(), Source});
693+
auto BindingType = Bindings[i].TypeParameter;
694+
auto InterfaceType = Caller.mapTypeOutOfContext(BindingType);
695+
SourceMap.push_back({InterfaceType->getCanonicalType(), Source});
665696
}
666697

667698
// Check if any requirements were fulfilled by metadata stored inside a
@@ -701,10 +732,9 @@ class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
701732
// parameters.
702733
auto Src = Path.getMetadataSource(SourceBuilder, Root);
703734

704-
auto SubstType =
705-
Caller.mapTypeOutOfContext(
706-
GenericParam.subst(SubstMap, None));
707-
SourceMap.push_back({SubstType->getCanonicalType(), Src});
735+
auto SubstType = GenericParam.subst(SubstMap);
736+
auto InterfaceType = Caller.mapTypeOutOfContext(SubstType);
737+
SourceMap.push_back({InterfaceType->getCanonicalType(), Src});
708738
});
709739

710740
return SourceMap;
@@ -872,11 +902,13 @@ IRGenModule::getAddrOfCaptureDescriptor(SILFunction &Caller,
872902
if (!IRGen.Opts.EnableReflectionMetadata)
873903
return llvm::Constant::getNullValue(CaptureDescriptorPtrTy);
874904

905+
if (CaptureDescriptorBuilder::hasOpenedExistential(OrigCalleeType, Layout))
906+
return llvm::Constant::getNullValue(CaptureDescriptorPtrTy);
907+
875908
CaptureDescriptorBuilder builder(*this, Caller,
876909
OrigCalleeType, SubstCalleeType, Subs,
877910
Layout);
878911
auto var = builder.emit();
879-
880912
return llvm::ConstantExpr::getBitCast(var, CaptureDescriptorPtrTy);
881913
}
882914

test/Reflection/capture_descriptors.sil

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,27 @@ bb0(%thin: $@convention(thin) () -> (), %c: $@convention(c) () -> (), %block: $@
241241
// CHECK-NEXT: (function convention=thin
242242
// CHECK-NEXT: (tuple))
243243
// CHECK-NEXT: - Metadata sources:
244+
245+
// Capturing opened existentials
246+
//
247+
// Not supported yet -- make sure we bail out instead of crashing.
248+
//
249+
// FIXME: Eventually, we should emit a useful capture descriptor
250+
// for this case.
251+
252+
sil @existential_callee : $@convention(thin) <τ_0_0 where τ_0_0 : P> () -> @out P {
253+
bb0(%0 : $*P):
254+
unreachable
255+
}
256+
257+
258+
sil @existential_caller : $@convention(thin) (@in P) -> () {
259+
bb0(%0 : $*P):
260+
%payload = open_existential_addr immutable_access %0 : $*P to $*@opened("2D7A8F84-2973-11E7-838D-34363BD08DA0") P
261+
%f = function_ref @existential_callee : $@convention(thin) <τ_0_0 where τ_0_0 : P> () -> @out P
262+
%result = partial_apply %f<@opened("2D7A8F84-2973-11E7-838D-34363BD08DA0") P>() : $@convention(thin) <τ_0_0 where τ_0_0 : P> () -> @out P
263+
destroy_value %result : $@callee_owned () -> @out P
264+
destroy_addr %0 : $*P
265+
%tuple = tuple ()
266+
return %tuple : $()
267+
}

test/SILGen/function_conversion.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
1+
// RUN: %target-swift-frontend -emit-silgen -primary-file %s | %FileCheck %s
2+
// RUN: %target-swift-frontend -emit-ir -primary-file %s
23

34
// Check SILGen against various FunctionConversionExprs emitted by Sema.
45

test/SILGen/partial_apply_protocol.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
1+
// RUN: %target-swift-frontend -emit-silgen -primary-file %s | %FileCheck %s
2+
// RUN: %target-swift-frontend -emit-ir -primary-file %s
23

34
protocol Clonable {
45
func clone() -> Self

0 commit comments

Comments
 (0)