-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Document the behaviour of infinite iterators on potentially-computable methods #47547
Conversation
…e methods It’s not entirely clear from the current documentation what behaviour calling a method such as `min` on an infinite iterator like `RangeFrom` is. One might expect this to terminate, but in fact, for infinite iterators, `min` is always nonterminating (at least in the standard library). This adds a quick note about this behaviour for clarification.
r? @Kimundi (rust_highfive has picked a reviewer for you, use r? to override) |
src/libcore/iter/iterator.rs
Outdated
@@ -24,6 +24,10 @@ fn _assert_is_object_safe(_: &Iterator<Item=()>) {} | |||
/// This is the main iterator trait. For more about the concept of iterators | |||
/// generally, please see the [module-level documentation]. In particular, you | |||
/// may want to know how to [implement `Iterator`][impl]. | |||
/// | |||
/// Note: Methods on infinite iterators that generally require traversing every |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it was probably helpful to point this out in the trait documentation, but if this feels like too much of a niche case to mention here, the module-level documentation could be sufficient.
src/libcore/iter/mod.rs
Outdated
//! let least = positives.min().unwrap(); // Oh no! An infinite loop! | ||
//! // `positives.min` causes an infinite loop, so we won't reach this point! | ||
//! println!("The least positive number is {}.", least); | ||
//! ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block should be marked as ```no_run
, otherwise I don't think the CI will accept it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, of course!
src/libcore/iter/iterator.rs
Outdated
@@ -24,6 +24,10 @@ fn _assert_is_object_safe(_: &Iterator<Item=()>) {} | |||
/// This is the main iterator trait. For more about the concept of iterators | |||
/// generally, please see the [module-level documentation]. In particular, you | |||
/// may want to know how to [implement `Iterator`][impl]. | |||
/// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing white space.
[00:05:27] tidy error: /checkout/src/libcore/iter/mod.rs:300: trailing whitespace
[00:05:27] tidy error: /checkout/src/libcore/iter/mod.rs:306: trailing whitespace
[00:05:27] tidy error: /checkout/src/libcore/iter/iterator.rs:27: trailing whitespace
src/libcore/iter/iterator.rs
Outdated
@@ -25,6 +25,10 @@ fn _assert_is_object_safe(_: &Iterator<Item=()>) {} | |||
/// generally, please see the [module-level documentation]. In particular, you | |||
/// may want to know how to [implement `Iterator`][impl]. | |||
/// | |||
/// Note: Methods on infinite iterators that generally require traversing every | |||
/// element to produce a result may not terminate, even on traits for which a | |||
/// result is determinable in finite time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that the trait's doc-comment is essentially just a redirect to the module docs, I don't think this note needs to be here as well. Maybe mention diverging in fold
specifically, as the most general case of the methods that diverge when given infinite input?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was divided 50:50 on this one. I've taken it out and replaced it with a comment on fold
as you suggested.
src/libcore/iter/mod.rs
Outdated
@@ -298,7 +298,21 @@ | |||
//! | |||
//! This will print the numbers `0` through `4`, each on their own line. | |||
//! | |||
//! Bear in mind that methods on infinite iterators, even those for which a | |||
//! result can be computed in finite time, may not terminate. Specifically, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the words "can be computed" lead to a "well, how do I compute it then?" feeling. Perhaps it could be phrased along the lines of "even if a value for them could be determined mathematically", or something?
And instead of "may not terminate", what about being more explicit, with something like "will not return successfully"? (I don't know if talking about the different ways something could diverge would be useful.)
src/libcore/iter/mod.rs
Outdated
//! ```no_run | ||
//! let positives = 1..; | ||
//! let least = positives.min().unwrap(); // Oh no! An infinite loop! | ||
//! // `positives.min` causes an infinite loop, so we won't reach this point! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: in debug mode this panics due to overflow, and doesn't infinite-loop
https://play.rust-lang.org/?gist=bff007ce8e876616bbd965ec4c6dcba0&version=stable
Has there been discussion on whether or not to override methods like this, e.g. |
@abonander: There's been some quite extensive discussion about that very recently — check #47370 and #47362 out for some of the background. |
Small quibble!
Thus we can say it's not reasonable to use |
I think |
It is not infinite -- that leads to an argument that |
Yeah, that's a fair point. I'll rework the example to use (On a related, but off-topic point, is there a reason [other than backwards compatibility at this stage] that |
This was discussed before in #42315 (comment). It's "infinite" in the sense of "no matter how many times you call it, it will never return
It's hard, potentially impossible, to implement without either making the struct bigger or making it not return every possible number for the type (ie being |
@scottmcm That sounds fine in relation to that change, but saying it is infinite is not correct for all situations. I like my argument still. In your code, if the user knows their |
Ping from triage, @Kimundi ! |
Triage ping. Since @Kimundi haven't left any comments on this PR, could |
Coming from the previous discussion, I don't know if defining the current behaviour is the correct way. As soon as it's in the documentation, we can't change it as easily. Instead I still like the potential of optimizations for cases like Repeat, but as discussed previously, an RFC is needed. |
I'd like libs to take it, as we need to know what behavior is desired in order to document it. |
I think it is valuable to document this behavior, and I like the way @varkor has phrased this as an informative warning rather than as a firm commitment for the standard library to always preserve the behavior that certain methods loop infinitely. I really like the "determined mathematically" suggestion from @scottmcm and I am glad that was incorporated. Let's merge when someone from docs is okay with this as well. |
Could someone from @rust-lang/libs review this? |
@pietroalbini oh I think we're good on the libs front! @dtolnay mentioned above and I suspect many other @rust-lang/libs members would agree, so at this point I think we're looking for a sign-off from @rust-lang/docs. |
Looks good for me. |
@alexcrichton We have a sign-off from docs; is that sufficient? Or were you looking for entire team discussion? |
just read this over as well, and it seems reasonable to document this! one question i have is why @bors r+ rollup |
📌 Commit f129374 has been approved by |
…oc, r=frewsxcv Document the behaviour of infinite iterators on potentially-computable methods It’s not entirely clear from the current documentation what behaviour calling a method such as `min` on an infinite iterator like `RangeFrom` is. One might expect this to terminate, but in fact, for infinite iterators, `min` is always nonterminating (at least in the standard library). This adds a quick note about this behaviour for clarification.
It’s not entirely clear from the current documentation what behaviour
calling a method such as
min
on an infinite iterator likeRangeFrom
is. One might expect this to terminate, but in fact, for infinite
iterators,
min
is always nonterminating (at least in the standardlibrary). This adds a quick note about this behaviour for clarification.
cc @rkruppe