Skip to content

[SR-10112] Runtime crash with lazy var and capture list compiled with optimization level -O #52514

@swift-ci

Description

@swift-ci
Previous ID SR-10112
Radar None
Original Reporter stunba (JIRA User)
Type Bug
Environment

swift 4.2

xcode 10.1

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, OptimizedOnly, RunTimeCrash
Assignee None
Priority Medium

md5: 7804a10e0964de8730beb7f68df9a73f

Issue Description:

Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0xe100000000000010

I'm not sure where the problem is but it seems like bug with lazy vars or capture list

It crashes with optimization level -O and it doesn't with -Onone

// can be fixed by "protocol TestMixArtworkService: class {"
protocol TestMixArtworkService {
    func artwork(for url: String) -> Data
}


enum Test {


    class SomeClass: NSObject {
        let id = UUID()
    }


    final class FirstImpl: TestMixArtworkService {
        func artwork(for url: String) -> Data {
            return Data()
        }
    }


    final class SecondImpl: TestMixArtworkService {


        // can be fixed by removing lazy
        private lazy var some: SomeClass = SomeClass()


        func artwork(for url: String) -> Data {
            _ = some
            return Data()
        }
    }


    final class ItemsProvider {
        private let artworkService: TestMixArtworkService


        init(artworkService: TestMixArtworkService) {
            self.artworkService = artworkService
        }


        private func customMap(_ items: [Int]) -> [(Int, Data)] {
            // can be fixed by create manual copy of var
//            let artworkService = self.artworkService
            return items.map { [artworkService] num in
                return (num, artworkService.artwork(for: "\(num)"))
            }
        }


        func getItems() -> [(Int, Data)] {
            let items = [Array(0..<10)].map(customMap).flatMap { $0 }
            return items
        }
    }


    static func test() {
        let provider1 = ItemsProvider(artworkService: FirstImpl())
        let x = provider1.getItems()
        print(x)


        let provider2 = ItemsProvider(artworkService: SecondImpl())
        let y = provider2.getItems()
        print(y)
    }
}

It crashes on line with accessing lazy var reference type

_ = some

I found 3 independent fixes:

  1. manual copy var instead of using capture list
let artworkService = self.artworkService
            return items.map { num in
                return (num, artworkService.artwork(for: "\(num)"))
            }
  1. add "class" constraint on protocol
protocol TestMixArtworkService: class {
  1. remove lazy modifier

I have reproducible test project https://github.com/Stunba/TestSwiftCrash

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.compilerThe Swift compiler itselfcrashBug: A crash, i.e., an abnormal termination of softwareoptimized onlyFlag: An issue whose reproduction requires optimized compilationrun-time crashBug → crash: Swift code crashed during execution

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions