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:
Joe Groff
2014-07-05 17:48:05 +00:00
parent 6b45c481eb
commit af160e9c7b
4 changed files with 87 additions and 6 deletions

View File

@@ -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());
} }

View File

@@ -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

View File

@@ -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 &param : 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);
} }

View 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>):
}