PredictableMemOpt: Don't try to diagnose recursive value types.

They're invalid, and we don't want to blow the stack trying to decompose a type with infinite elements. Fixes rdar://problem/17920535.

Swift SVN r23775
This commit is contained in:
Joe Groff
2014-12-08 01:58:19 +00:00
parent ee145a1ac6
commit 259dad38f2
4 changed files with 33 additions and 7 deletions

View File

@@ -155,6 +155,12 @@ public:
return !isAddressOnly(); return !isAddressOnly();
} }
/// True if the type was successfully lowered, false if there was an error
/// during type lowering.
virtual bool isValid() const {
return true;
}
/// isTrivial - Returns true if the type is trivial, meaning it is a loadable /// isTrivial - Returns true if the type is trivial, meaning it is a loadable
/// value type with no reference type members that require releasing. /// value type with no reference type members that require releasing.
bool isTrivial() const { bool isTrivial() const {

View File

@@ -895,7 +895,6 @@ namespace {
AddressOnlyTypeLowering(SILType type) AddressOnlyTypeLowering(SILType type)
: TypeLowering(type, IsNotTrivial, IsAddressOnly) {} : TypeLowering(type, IsNotTrivial, IsAddressOnly) {}
public:
void emitCopyInto(SILBuilder &B, SILLocation loc, void emitCopyInto(SILBuilder &B, SILLocation loc,
SILValue src, SILValue dest, IsTake_t isTake, SILValue src, SILValue dest, IsTake_t isTake,
IsInitialization_t isInit) const override { IsInitialization_t isInit) const override {
@@ -946,9 +945,15 @@ namespace {
} }
}; };
/// A class that acts as a stand-in for unimplemented types. /// A class that acts as a stand-in for improperly recursive types.
class UnimplementedTypeLowering : public AddressOnlyTypeLowering { class RecursiveErrorTypeLowering : public AddressOnlyTypeLowering {
using AddressOnlyTypeLowering::AddressOnlyTypeLowering; public:
RecursiveErrorTypeLowering(SILType type)
: AddressOnlyTypeLowering(type) {}
bool isValid() const override {
return false;
}
}; };
/// Build the appropriate TypeLowering subclass for the given type. /// Build the appropriate TypeLowering subclass for the given type.
@@ -1161,7 +1166,7 @@ const TypeLowering *TypeConverter::find(TypeKey k) {
nomTy->getDeclaredTypeInContext()); nomTy->getDeclaredTypeInContext());
} else } else
assert(false && "non-nominal types should not be recursive"); assert(false && "non-nominal types should not be recursive");
found->second = new (*this, k.isDependent()) UnimplementedTypeLowering( found->second = new (*this, k.isDependent()) RecursiveErrorTypeLowering(
SILType::getPrimitiveAddressType(k.SubstType)); SILType::getPrimitiveAddressType(k.SubstType));
} }
return found->second; return found->second;
@@ -1169,7 +1174,10 @@ const TypeLowering *TypeConverter::find(TypeKey k) {
void TypeConverter::insert(TypeKey k, const TypeLowering *tl) { void TypeConverter::insert(TypeKey k, const TypeLowering *tl) {
auto &Types = k.isDependent() ? DependentTypes : IndependentTypes; auto &Types = k.isDependent() ? DependentTypes : IndependentTypes;
Types[k] = tl; // TODO: Types[k] should always be null at this point, except that we
// rely on type lowering to discover recursive value types right now.
if (!Types[k])
Types[k] = tl;
} }
#ifndef NDEBUG #ifndef NDEBUG

View File

@@ -31,6 +31,9 @@ STATISTIC(NumAllocRemoved, "Number of allocations completely removed");
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
static unsigned getNumSubElements(SILType T, SILModule &M) { static unsigned getNumSubElements(SILType T, SILModule &M) {
if (!M.getTypeLowering(T).isValid())
return 0;
if (auto TT = T.getAs<TupleType>()) { if (auto TT = T.getAs<TupleType>()) {
unsigned NumElements = 0; unsigned NumElements = 0;
for (auto index : indices(TT.getElementTypes())) for (auto index : indices(TT.getElementTypes()))

View File

@@ -1,4 +1,4 @@
// RUN: %swift -emit-silgen -verify %s // RUN: %swift -emit-sil -verify %s
struct SelfRecursiveStruct { // expected-error{{recursive value type}} struct SelfRecursiveStruct { // expected-error{{recursive value type}}
let a: SelfRecursiveStruct let a: SelfRecursiveStruct
@@ -37,3 +37,12 @@ enum RecursiveByGenericSubstitutionEnum<T> {
struct RecursiveByGenericSubstitutionStruct { // expected-error{{recursive value type}} struct RecursiveByGenericSubstitutionStruct { // expected-error{{recursive value type}}
let a: RecursiveByGenericSubstitutionEnum<RecursiveByGenericSubstitutionStruct> let a: RecursiveByGenericSubstitutionEnum<RecursiveByGenericSubstitutionStruct>
} }
struct RecursiveWithLocal { // expected-error{{recursive value type 'RecursiveWithLocal' is not allowed}}
init(t: Local) { self.t = t }
struct Local {
init(s: RecursiveWithLocal) { self.s = s }
var s: RecursiveWithLocal
}
var t: Local
}