Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-12768] Typechecking @Published with a nested property wrapper leads to poor diagnostic #55213

Open
swift-ci opened this issue May 10, 2020 · 5 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself diagnostics QoI Bug: Diagnostics Quality of Implementation property wrappers Feature: property wrappers type checker Area → compiler: Semantic analysis

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-12768
Radar rdar://problem/77881309
Original Reporter noahsark769 (JIRA User)
Type Bug
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, DiagnosticsQoI, PropertyWrappers, TypeChecker
Assignee None
Priority Medium

md5: 63bf602a60242938e94b3c2e998c7f8e

Issue Description:

(Swift 5.2.2, Xcode 11.4.1)

$ swift --version
Apple Swift version 5.2.2 (swiftlang-1103.0.32.6 clang-1103.0.32.51)
Target: x86_64-apple-darwin19.3.0

Using Published (from Foundation) nested with another property wrapper reliably causes a segfault. The minimal reproduction example I've managed to find is:

import Foundation
@propertyWrapperstruct Wrapper {
    var wrappedValue: String {
        get { "" }
        set { }
    }
    init(wrappedValue: String) {
        // do nothing
    }
}

class Test {
    @Published
    @Wrapper
    var string: String = ""
}

This causes a segfault with the following stacktrace:

$ swift Test.swift
<unknown>:0: error: key path value type 'String' cannot be converted to contextual type 'Wrapper'
Stack dump:
0.  Program arguments: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret Test.swift -enable-objc-interop -stack-check -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -color-diagnostics -module-name Test
1.  Apple Swift version 5.2.2 (swiftlang-1103.0.32.6 clang-1103.0.32.51)
2.  While evaluating request TypeCheckSourceFileRequest(source_file "Test.swift", 0)
3.  While evaluating request TypeCheckFunctionBodyUntilRequest(Test.(file).Test._@Test.swift:18:9, )
4.  While type-checking getter for string (at Test.swift:18:9)
5.  While evaluating request ParseAbstractFunctionBodyRequest(Test.(file).Test._@Test.swift:18:9)
0  swift                    0x000000010fb924ea PrintStackTraceSignalHandler(void*) + 42
1  swift                    0x000000010fb91cc0 SignalHandler(int) + 352
2  libsystem_platform.dylib 0x00007fff6542842d _sigtramp + 29
3  swift                    0x000000010c528aaf unsigned int llvm::DenseMapInfo<swift::AnyRequest>::getHashValue<swift::AttachedPropertyWrappersRequest>(swift::AttachedPropertyWrappersRequest const&) + 63
4  swift                    0x000000010c599e26 synthesizeAccessorBody(swift::AbstractFunctionDecl*, void*) + 1702
5  swift                    0x000000010c7cd2c8 swift::SimpleRequest<swift::ParseAbstractFunctionBodyRequest, swift::BraceStmt* (swift::AbstractFunctionDecl*), (swift::CacheKind)2>::evaluateRequest(swift::ParseAbstractFunctionBodyRequest const&, swift::Evaluator&) + 168
6  swift                    0x000000010c8e4f5b swift::ParseAbstractFunctionBodyRequest::OutputType swift::evaluateOrDefault<swift::ParseAbstractFunctionBodyRequest>(swift::Evaluator&, swift::ParseAbstractFunctionBodyRequest, swift::ParseAbstractFunctionBodyRequest::OutputType) + 1211
7  swift                    0x000000010c587634 swift::SimpleRequest<swift::TypeCheckFunctionBodyUntilRequest, bool (swift::AbstractFunctionDecl*, swift::SourceLoc), (swift::CacheKind)1>::evaluateRequest(swift::TypeCheckFunctionBodyUntilRequest const&, swift::Evaluator&) + 756
8  swift                    0x000000010c58e6ee swift::TypeCheckFunctionBodyUntilRequest::OutputType swift::evaluateOrDefault<swift::TypeCheckFunctionBodyUntilRequest>(swift::Evaluator&, swift::TypeCheckFunctionBodyUntilRequest, swift::TypeCheckFunctionBodyUntilRequest::OutputType) + 718
9  swift                    0x000000010c5bd24e swift::TypeCheckSourceFileRequest::evaluate(swift::Evaluator&, swift::SourceFile*, unsigned int) const + 6270
10 swift                    0x000000010c58c6c7 swift::SimpleRequest<swift::TypeCheckSourceFileRequest, bool (swift::SourceFile*, unsigned int), (swift::CacheKind)2>::evaluateRequest(swift::TypeCheckSourceFileRequest const&, swift::Evaluator&) + 23
11 swift                    0x000000010c5bab4e swift::performTypeChecking(swift::SourceFile&, unsigned int) + 1006
12 swift                    0x000000010bbeebcb swift::CompilerInstance::performSemaUpTo(swift::SourceFile::ASTStage_t) + 5915
13 swift                    0x000000010b8dad99 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 10281
14 swift                    0x000000010b85bf53 main + 1283
15 libdyld.dylib            0x00007fff6522f7fd start + 1
16 libdyld.dylib            0x000000000000000b start + 2598176783
Segmentation fault: 11

Please let me know if I can provide more info! Happy to discuss further

@swift-ci
Copy link
Collaborator Author

Comment by Noah Gilmore (JIRA)

Interestingly, this seems to be localized to the Foundation version of Published. The following compiles just fine for me:

@propertyWrapper
struct Published<Value> {
  var wrappedValue: Value
  
  init(wrappedValue: Value) {
    self.wrappedValue = wrappedValue
  }
}

@propertyWrapper
struct Wrapper {
    var wrappedValue: String {
        get { "" }
        set { }
    }    init(wrappedValue: String) {
        // do nothing
    }
}

class Test {
    @Published
    @Wrapper
    var string: String = ""
}

@swift-ci
Copy link
Collaborator Author

Comment by Owen Voorhees (JIRA)

For anyone looking into this further, I was able to reproduce this without the Foundation import by adding an _enclosingInstance subscript to the outer wrapper:

@propertyWrapper struct Wrapper {
    var wrappedValue: String {
        get { "" }
        set { }
    }
    init(wrappedValue: String) {
        // do nothing
    }
}


@propertyWrapper struct Published<T> {
    var storage: T?
    var wrappedValue: T {
        get { storage! }
        set { }
    }
    init(wrappedValue: T) {
        // do nothing
    }
    
    static subscript<EnclosingSelf>(
                _enclosingInstance observed: EnclosingSelf,
                wrapped wrappedKeyPath: ReferenceWritableKeyPath<EnclosingSelf, T>,
                storage storageKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Self>
            ) -> T {
            get {
                observed[keyPath: storageKeyPath].storage!
            }
            set {
                observed[keyPath: storageKeyPath].storage! = newValue
            }
        }
}




class Test {
    @Published
    @Wrapper
    var string: String = ""
}

@LucianoPAlmeida
Copy link
Collaborator

cc @hborla@DougGregor

@theblixguy
Copy link
Collaborator

On master, I get an error: key path value type 'String' cannot be converted to contextual type 'Wrapper', although it has no source location and the code no longer crashes. So, I'd say the crash is fixed, but the diagnostic could probably be improved.

@typesanitizer
Copy link

We still have the poor diagnostic on main

@swift-ci create

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself diagnostics QoI Bug: Diagnostics Quality of Implementation property wrappers Feature: property wrappers type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

4 participants