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-6134] Incorrect error message when accessing @optional properties from a class/subtype existential #48689

Closed
swift-ci opened this issue Oct 12, 2017 · 3 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-6134
Radar rdar://problem/17498958
Original Reporter benasher44 (JIRA User)
Type Bug
Status Resolved
Resolution Duplicate
Environment

macOS 10.13

Xcode 9 (App Store version)

Swift 4 (not in Swift 3 compatibility mode)

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

md5: ec35d24fb9e531b65834eac5a629f857

duplicates:

  • SR-5475 Can't set property declared optional in protocol

Issue Description:

When dealing with protocols bridged from Objective-C and subtype existentials, Swift generates an error claiming that the instance is a let constant and var should be used. Consider the following code:

SampleProtocols.h

@import Foundation;

@protocol P <NSObject>

@optional
@property (readwrite, nonatomic) NSString *foo;

@end

test.swift

mport Foundation

class A: NSObject {
}

class B: A, P {
    var foo = ""
}

typealias AandP = A & P

let b: AandP = B()

b.foo = ""

Test-Bridging-Header.h

#import "SampleProtocols.h"

When building using the following commands:

swiftc -c test.swift -import-objc-header Test-Bridging-Header.h -F/System/Library/Frameworks/Foundation.framework
swiftc -o test test.o
./test

This generates the following error:

test.swift:14:7: error: cannot assign to property: 'b' is a 'let' constant
b.foo = ""
~ ^
test.swift:12:1: note: change 'let' to 'var' to make it mutable
let b: AandP = B()
^~~
var

This can be resolved by making the property in P required (i.e. removing @optional). This is mostly an issue when dealing with UIKit protocols, since many of their protocol requirements are optional.

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

This is pretty confusing to me. I'd be grateful to know if there's a workaround that doesn't involve modifying the protocol, since the protocol I'm dealing with in the real world lives in UIKit.

@belkadan
Copy link
Contributor

:-( I think the only workaround right now is to define an Objective-C function that does it (it can be static inline). We've put off dealing with this because it comes up fairly rarely.

@swift-ci
Copy link
Collaborator Author

Comment by Ben A (JIRA)

Darn okay. I've come up with another workaround that's slightly more verbose, but it helps when dealing with UIKit (or other one off cases where something like this is needed). In my real word case, I want to configure the UITextInputTraits keyboard properties the same way for both a UITextView and a UITextField. To accomplish that, I ended up with something like this:

protocol TextInputKeyboardConfiguration: class {
    var keyboardType: UIKeyboardType { get set }
    /* copy pattern here for other configuration you want to do */
}

extension UITextField: TextInputKeyboardConfiguration {}
extension UITextView: TextInputKeyboardConfiguration {}

// You can now use a subtype existential like this to manage their setup (add as subviews, configure layout, and configure UITextInputTraits properties that you add to this protocol):
typealias KeyboardConfigurableView = UIView & TextInputKeyboardConfiguration

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
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
Projects
None yet
Development

No branches or pull requests

2 participants