mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
SIL: Lower dependent member types when substituted into context.
AST context substitution may produce a metatype, function type, or other type that requires lowering. Handle this special case to fix a crash when emitting protocol conformances with metatypes or functions as associated types. <rdar://problem/17501507> Swift SVN r19580
This commit is contained in:
@@ -2305,7 +2305,8 @@ public:
|
|||||||
|
|
||||||
/// Transform this SILResultInfo by applying the user-provided
|
/// Transform this SILResultInfo by applying the user-provided
|
||||||
/// function to its type.
|
/// function to its type.
|
||||||
SILResultInfo transform(const std::function<Type(Type)> &fn) const {
|
template <typename F>
|
||||||
|
SILResultInfo transform(F &&fn) const {
|
||||||
return SILResultInfo(fn(getType())->getCanonicalType(), getConvention());
|
return SILResultInfo(fn(getType())->getCanonicalType(), getConvention());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -254,11 +254,7 @@ public:
|
|||||||
/// Map the given type, which is based on an interface SILFunctionType and may
|
/// Map the given type, which is based on an interface SILFunctionType and may
|
||||||
/// therefore be dependent, to a type based on the context archetypes of this
|
/// therefore be dependent, to a type based on the context archetypes of this
|
||||||
/// SILFunction.
|
/// SILFunction.
|
||||||
SILType mapTypeIntoContext(SILType type) const {
|
SILType mapTypeIntoContext(SILType type) const;
|
||||||
return SILType::getPrimitiveType(
|
|
||||||
mapTypeIntoContext(type.getSwiftRValueType())->getCanonicalType(),
|
|
||||||
type.getCategory());
|
|
||||||
}
|
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Block List Access
|
// Block List Access
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "llvm/Support/GraphWriter.h"
|
#include "llvm/Support/GraphWriter.h"
|
||||||
|
|
||||||
using namespace swift;
|
using namespace swift;
|
||||||
|
using namespace Lowering;
|
||||||
|
|
||||||
SILFunction *SILFunction::create(SILModule &M, SILLinkage linkage,
|
SILFunction *SILFunction::create(SILModule &M, SILLinkage linkage,
|
||||||
StringRef name,
|
StringRef name,
|
||||||
@@ -122,6 +123,68 @@ Type SILFunction::mapTypeIntoContext(Type type) const {
|
|||||||
type);
|
type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct MapSILTypeIntoContext : CanTypeVisitor<MapSILTypeIntoContext, CanType> {
|
||||||
|
const SILFunction *ContextFn;
|
||||||
|
|
||||||
|
MapSILTypeIntoContext(const SILFunction *ContextFn) : ContextFn(ContextFn) {}
|
||||||
|
|
||||||
|
CanType visitDependentMemberType(CanDependentMemberType t) {
|
||||||
|
// If a dependent member type appears in lowered position, we need to lower
|
||||||
|
// its context substitution against the associated type's abstraction
|
||||||
|
// pattern.
|
||||||
|
CanType astTy = ContextFn->mapTypeIntoContext(t)->getCanonicalType();
|
||||||
|
AbstractionPattern origTy(t->getAssocType()->getArchetype());
|
||||||
|
|
||||||
|
return ContextFn->getModule().Types.getLoweredType(origTy, astTy)
|
||||||
|
.getSwiftRValueType();
|
||||||
|
}
|
||||||
|
|
||||||
|
CanType visitTupleType(CanTupleType t) {
|
||||||
|
// Dependent members can appear in lowered position inside tuples.
|
||||||
|
|
||||||
|
SmallVector<TupleTypeElt, 4> elements;
|
||||||
|
|
||||||
|
for (auto &elt : t->getFields())
|
||||||
|
elements.push_back(elt.getWithType(visit(CanType(elt.getType()))));
|
||||||
|
|
||||||
|
return TupleType::get(elements, t->getASTContext())
|
||||||
|
->getCanonicalType();
|
||||||
|
}
|
||||||
|
|
||||||
|
CanType visitSILFunctionType(CanSILFunctionType t) {
|
||||||
|
// Dependent members can appear in lowered position inside SIL functions.
|
||||||
|
|
||||||
|
SmallVector<SILParameterInfo, 4> params;
|
||||||
|
for (auto ¶m : t->getInterfaceParameters())
|
||||||
|
params.push_back(param.transform([&](CanType pt) -> CanType {
|
||||||
|
return visit(pt);
|
||||||
|
}));
|
||||||
|
|
||||||
|
SILResultInfo result = t->getInterfaceResult()
|
||||||
|
.transform([&](CanType elt) -> CanType {
|
||||||
|
return visit(elt);
|
||||||
|
});
|
||||||
|
|
||||||
|
return SILFunctionType::get(t->getGenericSignature(),
|
||||||
|
t->getExtInfo(),
|
||||||
|
t->getCalleeConvention(),
|
||||||
|
params, result,
|
||||||
|
t->getASTContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
CanType visitType(CanType t) {
|
||||||
|
// Other types get substituted into context normally.
|
||||||
|
return ContextFn->mapTypeIntoContext(t)->getCanonicalType();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
SILType SILFunction::mapTypeIntoContext(SILType type) const {
|
||||||
|
CanType astTy = MapSILTypeIntoContext(this).visit(type.getSwiftRValueType());
|
||||||
|
return SILType::getPrimitiveType(astTy, type.getCategory());
|
||||||
|
}
|
||||||
|
|
||||||
SILBasicBlock *SILFunction::createBasicBlock() {
|
SILBasicBlock *SILFunction::createBasicBlock() {
|
||||||
return new (getModule()) SILBasicBlock(this);
|
return new (getModule()) SILBasicBlock(this);
|
||||||
}
|
}
|
||||||
|
|||||||
21
test/SILGen/dependent_member_lowering.swift
Normal file
21
test/SILGen/dependent_member_lowering.swift
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// RUN: %swift -emit-silgen %s | FileCheck %s
|
||||||
|
|
||||||
|
protocol P {
|
||||||
|
typealias A
|
||||||
|
|
||||||
|
func f(x: A)
|
||||||
|
}
|
||||||
|
struct Foo<T>: P {
|
||||||
|
typealias A = T.Type
|
||||||
|
|
||||||
|
func f(t: T.Type) {}
|
||||||
|
// CHECK-LABEL: sil @_TTWV25dependent_member_lowering3FooS_1PFS1_1fUS1__U__fRQPS1_FQS2_1AT_ : $@cc(witness_method) @thin <T> (@in Foo<T>.A, @inout Foo<T>) -> ()
|
||||||
|
// CHECK: bb0(%0 : $*@thick T.Type, %1 : $*Foo<T>):
|
||||||
|
}
|
||||||
|
struct Bar<T>: P {
|
||||||
|
typealias A = Int -> T
|
||||||
|
|
||||||
|
func f(t: Int -> T) {}
|
||||||
|
// CHECK-LABEL: sil @_TTWV25dependent_member_lowering3BarS_1PFS1_1fUS1__U__fRQPS1_FQS2_1AT_ : $@cc(witness_method) @thin <T> (@in Bar<T>.A, @inout Bar<T>) -> ()
|
||||||
|
// CHECK: bb0(%0 : $*@callee_owned (@out T, @in Int) -> (), %1 : $*Bar<T>):
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user