swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.59k stars 10.36k forks source link

[SR-12818] Segfault on protocol method returning Self #55264

Closed swift-ci closed 2 years ago

swift-ci commented 4 years ago
Previous ID SR-12818
Radar None
Original Reporter kerrmarin (JIRA User)
Type Bug
Status Resolved
Resolution Done
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug, CompilerCrash, IRGen | |Assignee | None | |Priority | Medium | md5: 326a8b155e9973d739a0209db6a23700

Issue Description:

I have a protocol that allows view controllers to be instantiated from storyboards. It reads like this:

protocol StoryboardController where Self: UIViewController {    /// Creates a view controller using the name of the controller to load a storyboard
    ///
    ///
    /// - parameter named: _(optional)_ The name of the storyboard to load from. This defaults to `String(describing: Self)`
    /// - parameter bundle: _(optional)_ The bundle to load the storyboard from. This defaults to the main bundle.
    /// - returns: An instance of the controller implementing this method, instantiated from the storyboard with the same name.
    static func instanceFromStoryboard(named name: String?, bundle: Bundle?) throws -> Self
}

extension StoryboardController where Self: UIViewController {    

    static func instanceFromStoryboard(named name: String? = nil, bundle: Bundle? = nil) throws -> Self {
        let name = name ?? String(describing: self).components(separatedBy: ".").last!        
        let storyboard = UIStoryboard(name: name, bundle: bundle)
        guard let candidate = storyboard.instantiateInitialViewController() else {
            throw ViewControllerFromStoryboardError.failedToFindInitial(storyboard: storyboard)
        }
        guard let controller = candidate as? Self else {
            throw ViewControllerFromStoryboardError.initialViewControllerInvalidType(expected: Self.self, found: type(of: candidate))
        }
        return controller
    }
}

extension UIViewController: StoryboardController { }

It produces a segfault:

3.  While emitting IR SIL function "@$sSo16UIViewControllerC9WeProject010StoryboardB0A2cDP012instanceFromE05named6bundlexSSSg_So8NSBundleCSgtKFZTW".
 for 'instanceFromStoryboard(named:bundle:)' (at UIViewController+storyboard.swift:34:5)
0  swift                    0x000000010c3054ea PrintStackTraceSignalHandler(void*) + 42
1  swift                    0x000000010c304cc0 SignalHandler(int) + 352
2  libsystem_platform.dylib 0x00007fff6dcfc5fd _sigtramp + 29
3  libsystem_platform.dylib 0x00007fc8106b13f0 _sigtramp + 2728087056
4  swift                    0x0000000108293f5a swift::SILInstructionVisitor<(anonymous namespace)::IRGenSILFunction, void>::visit(swift::SILInstruction*) + 17898
5  swift                    0x000000010828c433 swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 8835
6  swift                    0x0000000108142716 swift::irgen::IRGenerator::emitLazyDefinitions() + 8790
7  swift                    0x000000010826aae4 performIRGeneration(swift::IRGenOptions&, swift::ModuleDecl*, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> >, llvm::StringRef, swift::PrimarySpecificPaths const&, llvm::LLVMContext&, swift::SourceFile*, llvm::GlobalVariable**) + 1284
8  swift                    0x0000000108061e3f performCompileStepsPostSILGen(swift::CompilerInstance&, swift::CompilerInvocation&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> >, bool, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, bool, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 4255
9  swift                    0x000000010805729a swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 48426
10 swift                    0x0000000107fcef53 main + 1283
11 libdyld.dylib            0x00007fff6db03cc9 start + 1
error: Segmentation fault: 11 (in target 'WeProject Dev' from project 'WeProject')
theblixguy commented 4 years ago

Here's a small reproducer which doesn't depend on UIKIt, etc:

class C {}

protocol P where Self: C {
  static func bar() throws -> Self
}

extension P where Self: C {    
  static func bar() throws -> Self {
    fatalError()
  }
}

extension C: P {}

One way to work around the crash is to get rid of the P where Self: C extension and put the implementation directly in the C: P extension instead.

theblixguy commented 4 years ago

Looks like this is fixed on master. kerrmarin (JIRA User) Could you verify using the latest trunk snapshot from swift.org?

swift-ci commented 2 years ago

Comment by Kerr Marin Miller (JIRA)

Can't reproduce any longer