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

remove Copy impls from remaining iterators #21809

Merged
merged 1 commit into from
Feb 1, 2015
Merged

Conversation

japaric
Copy link
Member

@japaric japaric commented Jan 31, 2015

Removes Copy from ops::Range (a..b) and ops::RangeFrom (a..)

[breaking-change]


I forgot about these two in #20790, this PR also adds Clone to the Peekable adapter which used to be Copyable.

r? @nikomatsakis or anyone

@alexcrichton
Copy link
Member

@bors: r+ c3841b9

bors added a commit that referenced this pull request Feb 1, 2015
Removes `Copy` from `ops::Range` (`a..b`) and `ops::RangeFrom` (`a..`)

[breaking-change]

---

I forgot about these two in #20790, this PR also adds `Clone` to the `Peekable` adapter which used to be `Copy`able.

r? @nikomatsakis or anyone
@bors
Copy link
Contributor

bors commented Feb 1, 2015

⌛ Testing commit c3841b9 with merge f1f9cb7...

@tbu-
Copy link
Contributor

tbu- commented Feb 1, 2015

@japaric Range and RangeFrom aren't only iterators, they're also used in indexing etc. The better solution for this is probably for Range to implement into_iterator.

@bluss
Copy link
Member

bluss commented Feb 1, 2015

This hurts the use of range in other APIs, as planned by std::rand (where it ends up) and collections.

@bors bors merged commit c3841b9 into rust-lang:master Feb 1, 2015
@ranma42
Copy link
Contributor

ranma42 commented Feb 1, 2015

Right now RangeTo and RangeFull are Copy, but Range and RangeFrom are not. Is this intentional?

@japaric
Copy link
Member Author

japaric commented Feb 1, 2015

@tbu-

Range and RangeFrom aren't only iterators, they're also used in indexing etc.

Yes, they are heavily used for slicing in the whole rust repo, and as evidenced by this PR, it wasn't necessary to explictly clone any range at all, which means that the implicitly copyable property of ranges wasn't used in the whole repository. (Of course, we can't extrapolate this to all the other existing libraries, but it's worth noting)

The better solution for this is probably for Range to implement into_iterator.

That would hurt the ergonomics of the Vec::from_elem replacement:

// from
let v = (a..b).map(f).collect::<Vec<_>>();
// to
use std::iter::IntoIterator;
let v = (a..b).into_iter().map(f).collect::<Vec<_>>();

@bluss

This hurts the use of range in other APIs, as planned by std::rand (where it ends up) and collections.

Could you show me an example on how non implictly copyable ranges would hurt the ergonomics of these planned APIs? I'd like to better understand the situation.

I don't know the exact API that will be added, but IIRC one of them was using range with Vec::remove. I can see this happen:

// with implicit copy
let range = a..b;
v1.remove(range);
v2.remove(range);
// without implict copy (today)
let range = a..b;
v1.remove(range.clone());
v2.remove(range);
// however, I think it would be clearer to do
v1.remove(a..b);
v2.remove(a..b);
// which doesn't require an implicit copy

@ranma42

Right now RangeTo and RangeFull are Copy, but Range and RangeFrom are not. Is this intentional?

Yes, structs that implement Iterator should not be implictly copyable.


To give some background. When I was implementing the new for-loops which take the iterator by value. The implictly copyability of iterators was causing several collections tests to SIGILL and broke some demangle function. I figured out what the problem was:

The new for-loops changed the semantics of the following pattern:

// original code
for x in it {  // a *copy* of the iterator is used here
    // ..
}

match it.next() {  // the original iterator is used here
    // ..
}

When the intended behaviour was:

for x in it.by_ref() {  // advance the iterator
    // ..
}

match it.next() {  // reuse the mutated iterator
    // ..
}

But I didn't know where the problems were. The fastest way to find the bugs was to make the iterators non-implictly copyable, that way the original code would error at compile time with it.next() error: it has been moved. After doing that, I managed to fix all the bugs.

My original plan was to fix the bugs, then make the iterators implicitly copyable again and defer the decision of whether iterators should be implictly copyable to a later date. But after discussing with the core devs, they told me that they wanted to make iterators non-implictly copyable anyways, so I went ahead with that.

@japaric japaric deleted the no-copy branch February 1, 2015 16:50
Manishearth added a commit to Manishearth/rust that referenced this pull request Apr 17, 2015
 This reverts commit c3841b9.

The commit made it impossible to copy the pretty fundamental data type `Range` and `RangeFrom`, which e.g. means that they can't be used in otherwise copyable structures anymore (or `Cell`s for that matter), where the reason for removal was that it can *also be used as an iterator*.

CC @japaric
rust-lang#21809
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants