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-7335] Mutating struct when accessing read only member through subscript #49883

Closed
tadija opened this issue Apr 2, 2018 · 7 comments
Closed

Comments

@tadija
Copy link

tadija commented Apr 2, 2018

Previous ID SR-7335
Radar rdar://problem/38514252
Original Reporter @tadija
Type Bug
Status Resolved
Resolution Duplicate
Environment

Xcode Version 9.3 (9E145)

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

md5: 78561451a2a8a9235d0a2e2a55a8e184

duplicates:

  • SR-7212 Regression from 4.0: didSet {} called on property read if property type is protocol containing array

is duplicated by:

  • SR-7647 Property observer called when accessing optional property that conforms to a protocol

relates to:

  • SR-7423 Unexpected error: "setter for 'lines' is unavailable" on using subscript of array property that has setter marked as @available(*, unavailable)
  • SR-7647 Property observer called when accessing optional property that conforms to a protocol

Issue Description:

Please see related discussion in this forums thread.

This is probably a regression in Swift 4.1, because it's not reproducable in 4.0.

Here's a simplified example demonstrating this issue:

protocol Foo {
    var bars: [Bar] { get set }
}
protocol Bar {
    var id: String { get }
}

struct TheBar: Bar {
    var id: String
}
struct TheFoo: Foo {
    var bars: [Bar]
    init() {
        bars = [TheBar(id: "0"), TheBar(id: "1"), TheBar(id: "2")]
    }
}

class Test {
    var foo: Foo! {
        didSet {
            print("didSet")
        }
    }
}

let test = Test()
test.foo = TheFoo() // calls `didSet` on `foo` member (as expected)

let id0 = test.foo.bars[0].id // calls `didSet` on `foo` member (not expected)
let id1 = test.foo.bars[1].id // calls `didSet` on `foo` member (not expected)
let id2 = test.foo.bars[2].id // calls `didSet` on `foo` member (not expected)
@belkadan
Copy link
Contributor

belkadan commented Apr 3, 2018

Definitely sounds like a bug to me. cc @rjmccall, @slavapestov

@swift-ci create

@rjmccall
Copy link
Member

rjmccall commented Apr 4, 2018

Agreed.

@swift-ci
Copy link
Collaborator

swift-ci commented Apr 4, 2018

Comment by Jiri Chlum (JIRA)

If protocol is class protocol then it works.

@belkadan
Copy link
Contributor

belkadan commented Apr 4, 2018

Yes, that works as a workaround because the compiler can assume the reference doesn't change when you change a property.

@belkadan
Copy link
Contributor

belkadan commented Apr 14, 2018

In investigating SR-7423, it looks like we now always form an InOutExpr for any lvalue use of a settable property or subscript (see adjustSelfTypeForMember in CSApply.cpp). That seems…wrong. @rudkx, @xedin, why the change?

@swift-ci
Copy link
Collaborator

swift-ci commented May 29, 2018

Comment by Andrew Rahn (JIRA)

This looks like the same issue I reported earlier?

@belkadan
Copy link
Contributor

belkadan commented May 30, 2018

Ah, good call.

@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
Projects
None yet
Development

No branches or pull requests

4 participants