Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running into compiler errors when using generics

While trying to work on a small Swift project, I often ran into the following compiler error:

var item : T?
    ^
LLVM ERROR: unimplemented IRGen feature! non-fixed class layout

The code producing such an error is utterly simple:

class Foo<T> {
  var item : T?
}

Interestingly, if you change from a class to a struct, everything compiles fine.

Can anyone else verify this, so I can get back to blame it on a not-yet-complete compiler and not some strange mixup in my compiler toolchains?

Update:

Trying to outsmart the obviously buggy compiler with the following alternative implementation results in even more hilarious compiler errors. For example the following

class Foo<T> {
    // Let's try with an inner struct
    struct OptionalWrapper {
        var item: T?
    }
    var item : OptionalWrapper
    init(item: T?) { self.item = OptionalWrapper(item: item) }
}

gives

0  swift                    0x000000011075a608 llvm::sys::PrintStackTrace(__sFILE*) + 40
1  swift                    0x000000011075aaf4 SignalHandler(int) + 452
2  libsystem_platform.dylib 0x00007fff901095aa _sigtramp + 26
3  libsystem_platform.dylib 0x0000000111b5ba00 _sigtramp + 2175083632
4  swift                    0x0000000110a54a67 swift::BoundGenericType::getSubstitutions(swift::Module*, swift::LazyResolver*) + 55
5  swift                    0x000000010fb696a9 emitNominalMetadataRef(swift::irgen::IRGenFunction&, swift::NominalTypeDecl*, swift::CanType) + 537
6  swift                    0x000000010fb5841c llvm::Value* swift::CanTypeVisitor<(anonymous namespace)::EmitTypeMetadataRef, llvm::Value*>::visit<>(swift::CanType) + 124
7  swift                    0x000000010fb58395 swift::irgen::IRGenFunction::emitTypeMetadataRef(swift::CanType) + 21
8  swift                    0x000000010fb9b7e9 swift::irgen::WitnessSizedTypeInfo<(anonymous namespace)::NonFixedStructTypeInfo>::allocateStack(swift::irgen::IRGenFunction&, swift::CanType, llvm::Twine const&) const + 89
9  swift                    0x000000010fbc81a2 swift::SILVisitor<(anonymous namespace)::IRGenSILFunction, void>::visit(swift::ValueBase*) + 34626
10 swift                    0x000000010fbbf266 swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 8678
11 swift                    0x000000010fb406f8 swift::irgen::IRGenModule::emitGlobalTopLevel() + 184
12 swift                    0x000000010fbac6e3 performIRGeneration(swift::IRGenOptions&, swift::Module*, swift::SILModule*, llvm::StringRef, llvm::LLVMContext&, swift::SourceFile*, unsigned int) + 1859
13 swift                    0x000000010fbad033 swift::performIRGeneration(swift::IRGenOptions&, swift::SourceFile&, swift::SILModule*, llvm::StringRef, llvm::LLVMContext&, unsigned int) + 51
14 swift                    0x000000010fb1f65a frontend_main(llvm::ArrayRef<char const*>, char const*, void*) + 4842
15 swift                    0x000000010fb1e35d main + 1533
16 libdyld.dylib            0x00007fff8b2d05fd start + 1
17 libdyld.dylib            0x0000000000000040 start + 1959983684

and changing struct OptionalWrapper to struct OptionalWrapper<T> even makes the swift compiler being seemingly stuck in an endless loop (you still can cancel it with the stop button in XCode for example).

So my current recommendation is: stay clear of Swift generics in classes for now, this seems to be highly unstable terrain…

like image 309
punycode Avatar asked Oct 01 '22 15:10

punycode


1 Answers

I was able to get it to stop crashing and actually work by adding NSObject constraint to T:

class Widget<T:NSObject>
{
    var value : T?

    init(value:T?)
    {
        self.value = value
    }

    func description() -> String
    {
        let valueType = value?.self

        return "Widget is a \(valueType?.className)"
    }
}

let stringWidget = Widget(value:"Hello")
let numericWidget = Widget(value:9001)
let doubleWidget = Widget(value:3.14159)
let arrayWidget = Widget(value:[0xFEED, 0xBEEF, 0xCAFE])

stringWidget.description()
numericWidget.description()
doubleWidget.description()
arrayWidget.description()

That said, I do believe the playground and compiler have many bugs including the behavior you are experiencing.

I was also unable to make 'widgetception' by creating a Widget(value:Widget(value:x)).

like image 176
Erik Avatar answered Oct 03 '22 07:10

Erik