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-7167] Extra retain or formIndex(...) should be removed #49715

Closed
dabrahams opened this issue Mar 10, 2018 · 11 comments
Closed

[SR-7167] Extra retain or formIndex(...) should be removed #49715

dabrahams opened this issue Mar 10, 2018 · 11 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself standard library Area: Standard library umbrella

Comments

@dabrahams
Copy link
Collaborator

Previous ID SR-7167
Radar None
Original Reporter @dabrahams
Type Bug
Status Closed
Resolution Invalid
Additional Detail from JIRA
Votes 0
Component/s Compiler, Standard Library
Labels Bug
Assignee None
Priority Medium

md5: fa6332a4759c24e5edbc8453c9a0f788

Issue Description:

The following program prints "true\nfalse". I conclude that either we should find a way to remove the extra retain caused when g is called from f, or if that is impossible for correctness reasons we should probably remove the formIndex([before|after]: ) methods from Collections, because g is an effective analogue for formIndex when used from such methods as dropFirst().

struct Test {
    final class Ref { init() { } }

    struct I {
        var ref: Ref
    }

    var i: I

    func g(_ j: inout I) {
        print(isKnownUniquelyReferenced(&j.ref))
    }
    
    mutating func f() {
        print(isKnownUniquelyReferenced(&i.ref))
        g(&i)
    }
}

var p = Test(i: Test.I(ref: Test.Ref()))
p.f()
@belkadan
Copy link
Contributor

This seems a lot like the Dictionary problem. I'm not sure this is bad enough to kill formIndex(before:), though. Indexes aren't supposed to be expensive to copy.

cc @rjmccall, @gottesmm

@dabrahams
Copy link
Collaborator Author

@belkadan That remark doesn't make any sense to me:

  1. What Dictionary problem?

  2. The only reason the formIndex methods exist in the first place is to improve performance in the rare cases when the index is expensive to copy

@belkadan
Copy link
Contributor

1. The problem that foo[bar][baz] = 2 ends up doing a CoW-copy of all of foo[bar], because we don't know how to "take-and-return" it.
2. Most uses of formIndex will still modify the index in place, just not all of them. In particular, usually the index is in its own variable, not part of a larger thing that's already being passed inout.

@rjmccall
Copy link
Member

We've talked about making non-mutating methods calls semantically borrow `self` instead of semantically copying. Note that that would make the call `g(&i)` ill-formed as an exclusivity violation.

@rjmccall
Copy link
Member

In general, I see no way that we can both remove the copy of `self` and allow `&self.i` to be passed off simultaneously, because obviously mutating `self.i` can invalidate parts of `self`. So is that just a convenience for your reduction, or is it core to the pattern you need? I wouldn't think that collections usually store indices into themselves, but if you tell me that's important, I will believe you.

@dabrahams
Copy link
Collaborator Author

@rjmccall This is a reduction of https://github.com/dabrahams/KillSequence/blob/master/GeneratorCollection.swift#L318 .

Most collections don't store indices, but slices do.

I'm afraid I don't understand what you mean about invalidation.

@dabrahams
Copy link
Collaborator Author

formIndex will still modify the index in place, just not all of them

Good point (reminds self not to file bugs while sick).

@rjmccall
Copy link
Member

But the slices you're talking about presumably also store their parent collection and could presumably advance the index using that instead.

The invalidation issue is just that there's a real exclusivity issue here: you want to pass a field of `self` by mutable reference while also passing all of `self` by immutable reference. The latter can observe changes made to the former.

@dabrahams
Copy link
Collaborator Author

The SubSequence in the code referenced does not store its parent collection. If it did, it would keep buffers alive longer than necessary.

I see what you mean about the exclusivity problem, now, thanks.

@rjmccall
Copy link
Member

> The SubSequence in the code referenced does not store its parent collection. If it did, it would keep buffers alive longer than necessary.

Oh, right, of course. But in this case you should be able to advance the index without needing the collection.

@dabrahams
Copy link
Collaborator Author

Yep, that's my fallback. So I think this bug is bogus and will close.

@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 standard library Area: Standard library umbrella
Projects
None yet
Development

No branches or pull requests

3 participants