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

perf: Let &mut T iterators forward for_each and friends #68472

Closed
wants to merge 1 commit into from

Conversation

Marwes
Copy link
Contributor

@Marwes Marwes commented Jan 22, 2020

Currently impl Iterator for &mut T does not forward for_each to the
inner T which means that it is easy to lose optimized implementations
of these methods. (See #68046)

By using specialization on T: Sized we can allow calls on non-trait
objects to still forward to the inner methods.

This isn't tested yet and there are more methods that should be
forwarded, just posting this as a POC and to see if it is something that
is wanted.

EDIT: I believe I were wrong in #68046 and I did not get the slow default implementation. by_ref called on a &mut T will just yield &mut T again, so you more or less have to use &mut iter on a &mut T to get the slow implementations which this fixes. Might warrant a clippy lint at least if this looks to heavy handed.

@rust-highfive
Copy link
Collaborator

r? @LukasKalbertodt

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 22, 2020
@Centril
Copy link
Contributor

Centril commented Jan 22, 2020

cc @matthewjasper re. specializations.

Copy link
Member

@LukasKalbertodt LukasKalbertodt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

I'm a bit confused though. Your PR comment doesn't quite seem to fit the changes ("specialization on T: Sized" -> that's not your code specializes on, right?). Also, I'm not sure how exactly this would improve things. Could you provide us with a minimal example code where this PR would improve the method implementation that is picked? That would be great!
Or does your edit imply that this PR is not required anymore at all?

I don't know a lot about the interaction of trait objects and specialization, so someone else would need to check regarding that.

where
T: Iterator,
{
default fn spec_try_fold<B, F, R>(&mut self, init: B, f: F) -> R
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This default is not necessary and should be removed. This implementation is overwriting another one, but we don't expect this implementation to be overwritten (right?). So we shouldn't put default here.

(**self).try_fold(init, f)
}

default fn spec_try_for_each<F, R>(&mut self, f: F) -> R
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

@@ -83,7 +83,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
on(
_Self = "{integral}",
note = "if you want to iterate between `start` until a value `end`, use the exclusive range \
syntax `start..end` or the inclusive range syntax `start..=end`"
syntax `start..end` or the inclusive range syntax `start..=end`"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please undo all formatting changes like this (which I assume your editor/rustfmt automatically did). At least I think stray formatting changes are not really great.

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator + ?Sized> Iterator for &mut I {
type Item = I::Item;

#[inline]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you measured the impact of these inline attributes you are adding? I'd prefer not to use #[inline] unless we are pretty sure it leads to faster code somewhere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought #[inline] is a sensible default because it lets LLVM decide whether to inline or not, and all iterator methods in libcore that I can find have this attribute.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK (we really need a de-facto standard guide on inline...) that they are not necessary on generic items as their definitions will be available in downstream crates anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is correct, but next itself isn't generic, so I believe here it does make a difference? And afaik for generic functions the attribute is ignored, so adding it shouldn't hurt.

@Marwes
Copy link
Contributor Author

Marwes commented Jan 23, 2020

Since impl Iterator for &mut T does not specify try_fold and friends, rust will instead call into the default methods specified on Iterator

fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Ok = B>,
{
let mut accum = init;
while let Some(x) = self.next() {
accum = f(accum, x)?;
}
Try::from_ok(accum)
}
. Some iterators such as chain specify optimized versions of these
fn try_fold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
where
Self: Sized,
F: FnMut(Acc, Self::Item) -> R,
R: Try<Ok = Acc>,
{
let mut accum = init;
match self.state {
ChainState::Both | ChainState::Front => {
accum = self.a.try_fold(accum, &mut f)?;
if let ChainState::Both = self.state {
self.state = ChainState::Back;
}
}
_ => {}
}
if let ChainState::Back = self.state {
accum = self.b.try_fold(accum, &mut f)?;
}
Try::from_ok(accum)
}
so if one accidentally adds one extra level of &mut we end up calling the slower, default implementation instead of the optimized one.

Originally I though that I got tripped by this but it turns out that it requires more work to trigger.

fn consume(iter: &mut impl Iterator<Item = i32>) {
    // Calls the optimized version
    iter.for_each(|x| println!("{}", x));

    // Calls the default
    (&mut iter).for_each(|x| println!("{}", x));

@Marwes
Copy link
Contributor Author

Marwes commented Jan 23, 2020

I'm a bit confused though. Your PR comment doesn't quite seem to fit the changes ("specialization on T: Sized" -> that's not your code specializes on, right?)

Might have done something wrong with specialization, but the idea is to specialize on impl<T> Iterator for &mut T where T: Sized while still allowing impl<T> Iterator for &mut T where T: ?Sized

Or does your edit imply that this PR is not required anymore at all?

It wasn't an issue in the PR I linked, but it could still happen otherwise.

Copy link
Member

@LukasKalbertodt LukasKalbertodt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since impl Iterator for &mut T does not specify try_fold and friends, rust will instead call into the default methods specified on Iterator.

That problem I understand. What I didn't understand initially is why the solution had to be so overly complicated. But I think I got it now:

The easiest would be to just overwrite the for_each method in the impl<I: Iterator + ?Sized> Iterator for &mut I and call (**self).for_each(f), right? But I assume you tried that and it didn't work because I is unsized while for_each requires Self: Sized. So your idea was to use specialization to be able to call the correct implementation if T is Sized. The next idea would be to add the specialization impl impl<I: Iterator> Iterator for &mut I (Sized this time!). But that doesn't currently work because default types are strange.

And that's why you added another trait and used specialization there, yes? If so, including the reasoning explaining your code in the PR description is very much appreciated. At least for someone like me who doesn't immediately understand why things are done the way they are.


Might have done something wrong with specialization, but the idea is to specialize on impl<T> Iterator for &mut T where T: Sized while still allowing impl<T> Iterator for &mut T where T: ?Sized

I was just confused as neither, the impl that is specialized and the specializing impl, had a Sized or ?Sized bound.

src/libcore/iter/traits/iterator.rs Outdated Show resolved Hide resolved
@LukasKalbertodt
Copy link
Member

In general, I'm still not sure if the potential speed gains are worth increasing the implementation complexity like that. A specific motivating example would probably help. I will talk to others about this!

@timvermeulen
Copy link
Contributor

This would be a big improvement for situations where you want to use an iterator adaptor without losing ownership of the original iterator. The by_ref docs give the following example:

let mut iter = [1, 2, 3].iter();
let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i);
assert_eq!(sum, 3);
assert_eq!(iter.next(), Some(&3));

At the moment the second line will use external iteration because &mut I doesn't forward for_each, so using specialization to fix this will just make a bunch of code automatically faster (and some other code easier to write without losing performance). I think the idea was always to eventually fix this using specialization.

@JohnCSimon
Copy link
Member

Ping from triage: @Marwes can you address the review comments?

@Marwes
Copy link
Contributor Author

Marwes commented Feb 6, 2020

Down prioritized this since it seemed like a lot of complexity for little gain, @timvermeulen s example is convincing however. Will try and simplify and do this over the weekend.

Currently `impl Iterator for &mut T` does not forward `try_fold` to the
inner `T` which means that it is easy to lose optimized implementations
of this method and methods that forward to it.

By using specialization on `T: Sized` we can allow calls on non-trait
objects to still forward to the inner methods.
@Marwes
Copy link
Contributor Author

Marwes commented Feb 8, 2020

Simplified this to not require an extra trait (mimicked Vecs specialization of Extend and didn't realize this didn't need that complexity).

This also only specializes try_fold and try_rfold which are the only iterators methods that are regularly implemented by iterator implementations. I think there is an argument to be made that Iterator for &mut T should forward all of the methods to make &mut &mut impl Iterator behave identical to &mut impl Iterator but I don't care enough to argue for that without a concrete argument for it. This will at least make any iterator that implements try_fold (or forwards to try_fold) use that optimized version.

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-7 of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
2020-02-08T19:43:26.0253999Z ========================== Starting Command Output ===========================
2020-02-08T19:43:26.0255705Z [command]/bin/bash --noprofile --norc /home/vsts/work/_temp/5be6cea0-8034-4c89-ac6b-edd8a37b0429.sh
2020-02-08T19:43:26.0255785Z 
2020-02-08T19:43:26.0257974Z ##[section]Finishing: Disable git automatic line ending conversion
2020-02-08T19:43:26.0263980Z ##[section]Starting: Checkout rust-lang/rust@refs/pull/68472/merge to s
2020-02-08T19:43:26.0265539Z Task         : Get sources
2020-02-08T19:43:26.0265621Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
2020-02-08T19:43:26.0265653Z Version      : 1.0.0
2020-02-08T19:43:26.0265683Z Author       : Microsoft
---
2020-02-08T19:43:27.0072439Z ##[command]git remote add origin https://github.com/rust-lang/rust
2020-02-08T19:43:27.0083888Z ##[command]git config gc.auto 0
2020-02-08T19:43:27.0086670Z ##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
2020-02-08T19:43:27.0088339Z ##[command]git config --get-all http.proxy
2020-02-08T19:43:27.0095598Z ##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/68472/merge:refs/remotes/pull/68472/merge
---
2020-02-08T20:41:31.0395897Z .................................................................................................... 1700/9611
2020-02-08T20:41:36.0948272Z .................................................................................................... 1800/9611
2020-02-08T20:41:48.0661238Z ...............................i.................................................................... 1900/9611
2020-02-08T20:41:55.7481496Z .................................................................................................... 2000/9611
2020-02-08T20:42:09.8335909Z .....................iiiii.......................................................................... 2100/9611
2020-02-08T20:42:19.6318784Z .................................................................................................... 2300/9611
2020-02-08T20:42:22.0907782Z .................................................................................................... 2400/9611
2020-02-08T20:42:26.8443711Z .................................................................................................... 2500/9611
2020-02-08T20:42:47.5839769Z .................................................................................................... 2600/9611
---
2020-02-08T20:45:25.3021968Z .........................................................................i...............i.......... 4900/9611
2020-02-08T20:45:32.9192163Z .................................................................................................... 5000/9611
2020-02-08T20:45:40.9925017Z .................................................................................................... 5100/9611
2020-02-08T20:45:45.5916119Z ................i................................................................................... 5200/9611
2020-02-08T20:45:56.3737484Z ..........................................................................................ii.ii..... 5300/9611
2020-02-08T20:46:00.7245267Z ...i...i............................................................................................ 5400/9611
2020-02-08T20:46:10.7055873Z .................................................................................................... 5600/9611
2020-02-08T20:46:21.2274291Z ..............................................................................i..................... 5700/9611
2020-02-08T20:46:28.9046092Z .................................................................................................... 5800/9611
2020-02-08T20:46:35.1642550Z .........................................F.......................................................... 5900/9611
2020-02-08T20:46:35.1642550Z .........................................F.......................................................... 5900/9611
2020-02-08T20:46:45.2697924Z ............................................F........................ii...i..ii...........i......... 6000/9611
2020-02-08T20:47:06.7373497Z .................................................................................................... 6200/9611
2020-02-08T20:47:14.4566742Z .................................................................................................... 6300/9611
2020-02-08T20:47:22.6721962Z .................................................................................................i.. 6400/9611
2020-02-08T20:47:36.0895755Z ii.................................................................................................. 6500/9611
---
2020-02-08T20:49:39.9664027Z .................................................................................................... 7600/9611
2020-02-08T20:49:45.0695674Z .................................................................................................... 7700/9611
2020-02-08T20:49:50.3853844Z .................................................................................................... 7800/9611
2020-02-08T20:50:00.0269108Z .................................................................................................... 7900/9611
2020-02-08T20:50:08.9849482Z .......................................................iiiiiii.i.................................... 8000/9611
2020-02-08T20:50:24.0940753Z ..i................................................................................................. 8200/9611
2020-02-08T20:50:29.7414045Z .................................................................................................... 8300/9611
2020-02-08T20:50:45.2751222Z .................................................................................................... 8400/9611
2020-02-08T20:50:53.8213436Z .................................................................................................... 8500/9611
---
2020-02-08T20:52:52.8623331Z 
2020-02-08T20:52:52.8624042Z ---- [ui] ui/issues/issue-31173.rs stdout ----
2020-02-08T20:52:52.8624342Z diff of stderr:
2020-02-08T20:52:52.8624579Z 
2020-02-08T20:52:52.8625186Z 14    |          ^^^^^^^ method not found in `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>`
2020-02-08T20:52:52.8625744Z 16    = note: the method `collect` exists but the following trait bounds were not satisfied:
2020-02-08T20:52:52.8625744Z 16    = note: the method `collect` exists but the following trait bounds were not satisfied:
2020-02-08T20:52:52.8626302Z -            `&mut std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`
2020-02-08T20:52:52.8626930Z 18            `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`
2020-02-08T20:52:52.8627460Z 20 error: aborting due to 2 previous errors
2020-02-08T20:52:52.8627652Z 
2020-02-08T20:52:52.8627840Z 
2020-02-08T20:52:52.8628070Z The actual stderr differed from the expected stderr.
2020-02-08T20:52:52.8628070Z The actual stderr differed from the expected stderr.
2020-02-08T20:52:52.8628654Z Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/issues/issue-31173/issue-31173.stderr
2020-02-08T20:52:52.8629226Z To update references, rerun the tests and pass the `--bless` flag
2020-02-08T20:52:52.8629796Z To only update this specific test, also pass `--test-args issues/issue-31173.rs`
2020-02-08T20:52:52.8630283Z error: 1 errors occurred comparing output.
2020-02-08T20:52:52.8630499Z status: exit code: 1
2020-02-08T20:52:52.8630499Z status: exit code: 1
2020-02-08T20:52:52.8631668Z command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/issues/issue-31173.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/issues/issue-31173" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/issues/issue-31173/auxiliary" "-A" "unused"
2020-02-08T20:52:52.8632783Z ------------------------------------------
2020-02-08T20:52:52.8633053Z 
2020-02-08T20:52:52.8633518Z ------------------------------------------
2020-02-08T20:52:52.8633779Z stderr:
2020-02-08T20:52:52.8633779Z stderr:
2020-02-08T20:52:52.8634185Z ------------------------------------------
2020-02-08T20:52:52.8634813Z error[E0271]: type mismatch resolving `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@/checkout/src/test/ui/issues/issue-31173.rs:6:39: 9:6 found_e:_]> as std::iter::Iterator>::Item == &_`
2020-02-08T20:52:52.8636269Z    |
2020-02-08T20:52:52.8636637Z LL |         .cloned()
2020-02-08T20:52:52.8636786Z    |          ^^^^^^ expected `u8`, found reference
2020-02-08T20:52:52.8637098Z    |
2020-02-08T20:52:52.8637098Z    |
2020-02-08T20:52:52.8637263Z    = note:   expected type `u8`
2020-02-08T20:52:52.8637403Z            found reference `&_`
2020-02-08T20:52:52.8637523Z 
2020-02-08T20:52:52.8638676Z error[E0599]: no method named `collect` found for struct `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@/checkout/src/test/ui/issues/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope
2020-02-08T20:52:52.8639278Z    |
2020-02-08T20:52:52.8639418Z LL |         .collect(); //~ ERROR no method named `collect`
2020-02-08T20:52:52.8639418Z LL |         .collect(); //~ ERROR no method named `collect`
2020-02-08T20:52:52.8641620Z    |          ^^^^^^^ method not found in `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@/checkout/src/test/ui/issues/issue-31173.rs:6:39: 9:6 found_e:_]>>`
2020-02-08T20:52:52.8642162Z    = note: the method `collect` exists but the following trait bounds were not satisfied:
2020-02-08T20:52:52.8642162Z    = note: the method `collect` exists but the following trait bounds were not satisfied:
2020-02-08T20:52:52.8642662Z            `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@/checkout/src/test/ui/issues/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`
2020-02-08T20:52:52.8642978Z error: aborting due to 2 previous errors
2020-02-08T20:52:52.8643103Z 
2020-02-08T20:52:52.8643262Z Some errors have detailed explanations: E0271, E0599.
2020-02-08T20:52:52.8643616Z For more information about an error, try `rustc --explain E0271`.
---
2020-02-08T20:52:52.8652355Z 36    |
2020-02-08T20:52:52.8652741Z -    = note: the method `take` exists but the following trait bounds were not satisfied:
2020-02-08T20:52:52.8653088Z -            `&mut Foo : std::iter::Iterator`
2020-02-08T20:52:52.8653257Z 39    = help: items from traits can only be used if the trait is implemented and in scope
2020-02-08T20:52:52.8653453Z 40    = note: the following traits define an item `take`, perhaps you need to implement one of them:
2020-02-08T20:52:52.8653599Z 41            candidate #1: `std::io::Read`
2020-02-08T20:52:52.8653846Z 
2020-02-08T20:52:52.8653979Z The actual stderr differed from the expected stderr.
2020-02-08T20:52:52.8653979Z The actual stderr differed from the expected stderr.
2020-02-08T20:52:52.8654390Z Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/methods/method-call-err-msg/method-call-err-msg.stderr
2020-02-08T20:52:52.8654773Z To update references, rerun the tests and pass the `--bless` flag
2020-02-08T20:52:52.8655277Z To only update this specific test, also pass `--test-args methods/method-call-err-msg.rs`
2020-02-08T20:52:52.8655586Z error: 1 errors occurred comparing output.
2020-02-08T20:52:52.8655720Z status: exit code: 1
2020-02-08T20:52:52.8655720Z status: exit code: 1
2020-02-08T20:52:52.8656750Z command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/methods/method-call-err-msg.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/methods/method-call-err-msg" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/methods/method-call-err-msg/auxiliary" "-A" "unused"
2020-02-08T20:52:52.8657445Z ------------------------------------------
2020-02-08T20:52:52.8657594Z 
2020-02-08T20:52:52.8657909Z ------------------------------------------
2020-02-08T20:52:52.8658094Z stderr:
2020-02-08T20:52:52.8658094Z stderr:
2020-02-08T20:52:52.8658403Z ------------------------------------------
2020-02-08T20:52:52.8658573Z error[E0061]: this function takes 0 parameters but 1 parameter was supplied
2020-02-08T20:52:52.8658930Z   --> /checkout/src/test/ui/methods/method-call-err-msg.rs:12:7
2020-02-08T20:52:52.8659116Z    |
2020-02-08T20:52:52.8659423Z LL |     fn zero(self) -> Foo { self }
2020-02-08T20:52:52.8659777Z    |     -------------------- defined here
2020-02-08T20:52:52.8659933Z ...
2020-02-08T20:52:52.8660089Z LL |     x.zero(0)   //~ ERROR this function takes 0 parameters but 1 parameter was supplied
2020-02-08T20:52:52.8660343Z 
2020-02-08T20:52:52.8660494Z error[E0061]: this function takes 1 parameter but 0 parameters were supplied
2020-02-08T20:52:52.8660833Z   --> /checkout/src/test/ui/methods/method-call-err-msg.rs:13:7
2020-02-08T20:52:52.8660991Z    |
2020-02-08T20:52:52.8660991Z    |
2020-02-08T20:52:52.8661317Z LL |     fn one(self, _: isize) -> Foo { self }
2020-02-08T20:52:52.8661836Z ...
2020-02-08T20:52:52.8661836Z ...
2020-02-08T20:52:52.8661994Z LL |      .one()     //~ ERROR this function takes 1 parameter but 0 parameters were supplied
2020-02-08T20:52:52.8662268Z 
2020-02-08T20:52:52.8662424Z error[E0061]: this function takes 2 parameters but 1 parameter was supplied
2020-02-08T20:52:52.8662765Z   --> /checkout/src/test/ui/methods/method-call-err-msg.rs:14:7
2020-02-08T20:52:52.8662926Z    |
2020-02-08T20:52:52.8662926Z    |
2020-02-08T20:52:52.8663258Z LL |     fn two(self, _: isize, _: isize) -> Foo { self }
2020-02-08T20:52:52.8663762Z ...
2020-02-08T20:52:52.8663762Z ...
2020-02-08T20:52:52.8663920Z LL |      .two(0);   //~ ERROR this function takes 2 parameters but 1 parameter was supplied
2020-02-08T20:52:52.8664170Z 
2020-02-08T20:52:52.8664321Z error[E0599]: no method named `take` found for struct `Foo` in the current scope
2020-02-08T20:52:52.8664657Z   --> /checkout/src/test/ui/methods/method-call-err-msg.rs:18:7
2020-02-08T20:52:52.8664831Z    |
2020-02-08T20:52:52.8664831Z    |
2020-02-08T20:52:52.8664962Z LL | pub struct Foo;
2020-02-08T20:52:52.8665304Z    | --------------- method `take` not found for this
2020-02-08T20:52:52.8665482Z ...
2020-02-08T20:52:52.8665618Z LL |      .take()    //~ ERROR no method named `take` found
2020-02-08T20:52:52.8665896Z    |
2020-02-08T20:52:52.8666076Z    = help: items from traits can only be used if the trait is implemented and in scope
2020-02-08T20:52:52.8666076Z    = help: items from traits can only be used if the trait is implemented and in scope
2020-02-08T20:52:52.8666234Z    = note: the following traits define an item `take`, perhaps you need to implement one of them:
2020-02-08T20:52:52.8666378Z            candidate #1: `std::io::Read`
2020-02-08T20:52:52.8666538Z            candidate #2: `std::iter::Iterator`
2020-02-08T20:52:52.8666822Z error: aborting due to 4 previous errors
2020-02-08T20:52:52.8666935Z 
2020-02-08T20:52:52.8667071Z Some errors have detailed explanations: E0061, E0599.
2020-02-08T20:52:52.8667448Z For more information about an error, try `rustc --explain E0061`.
2020-02-08T20:52:52.8667448Z For more information about an error, try `rustc --explain E0061`.
2020-02-08T20:52:52.8667721Z 
2020-02-08T20:52:52.8668175Z ------------------------------------------
2020-02-08T20:52:52.8668346Z 
2020-02-08T20:52:52.8668484Z 
2020-02-08T20:52:52.8668843Z ---- [ui] ui/mismatched_types/issue-36053-2.rs stdout ----
2020-02-08T20:52:52.8669010Z diff of stderr:
2020-02-08T20:52:52.8669127Z 
2020-02-08T20:52:52.8669612Z 5    |                                                       ^^^^^ method not found in `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>`
2020-02-08T20:52:52.8669949Z 7    = note: the method `count` exists but the following trait bounds were not satisfied:
2020-02-08T20:52:52.8669949Z 7    = note: the method `count` exists but the following trait bounds were not satisfied:
2020-02-08T20:52:52.8670370Z -            `&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator`
2020-02-08T20:52:52.8671067Z 9            `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator`
2020-02-08T20:52:52.8671410Z 11 error[E0631]: type mismatch in closure arguments
2020-02-08T20:52:52.8671530Z 
2020-02-08T20:52:52.8672019Z 
2020-02-08T20:52:52.8672337Z The actual stderr differed from the expected stderr.
2020-02-08T20:52:52.8672337Z The actual stderr differed from the expected stderr.
2020-02-08T20:52:52.8673076Z Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/mismatched_types/issue-36053-2/issue-36053-2.stderr
2020-02-08T20:52:52.8673496Z To update references, rerun the tests and pass the `--bless` flag
2020-02-08T20:52:52.8674127Z To only update this specific test, also pass `--test-args mismatched_types/issue-36053-2.rs`
2020-02-08T20:52:52.8674421Z error: 1 errors occurred comparing output.
2020-02-08T20:52:52.8674550Z status: exit code: 1
2020-02-08T20:52:52.8674550Z status: exit code: 1
2020-02-08T20:52:52.8675507Z command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/mismatched_types/issue-36053-2.rs" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/mismatched_types/issue-36053-2" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/mismatched_types/issue-36053-2/auxiliary" "-A" "unused"
2020-02-08T20:52:52.8676065Z ------------------------------------------
2020-02-08T20:52:52.8676204Z 
2020-02-08T20:52:52.8676504Z ------------------------------------------
2020-02-08T20:52:52.8676682Z stderr:
2020-02-08T20:52:52.8676682Z stderr:
2020-02-08T20:52:52.8677006Z ------------------------------------------
2020-02-08T20:52:52.8677499Z error[E0599]: no method named `count` found for struct `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@/checkout/src/test/ui/mismatched_types/issue-36053-2.rs:7:39: 7:53]>` in the current scope
2020-02-08T20:52:52.8679454Z    |
2020-02-08T20:52:52.8679454Z    |
2020-02-08T20:52:52.8681067Z LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
2020-02-08T20:52:52.8681609Z    |                                                       ^^^^^ method not found in `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@/checkout/src/test/ui/mismatched_types/issue-36053-2.rs:7:39: 7:53]>`
2020-02-08T20:52:52.8681750Z    = note: the method `count` exists but the following trait bounds were not satisfied:
2020-02-08T20:52:52.8681750Z    = note: the method `count` exists but the following trait bounds were not satisfied:
2020-02-08T20:52:52.8682122Z            `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@/checkout/src/test/ui/mismatched_types/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator`
2020-02-08T20:52:52.8682393Z error[E0631]: type mismatch in closure arguments
2020-02-08T20:52:52.8682812Z   --> /checkout/src/test/ui/mismatched_types/issue-36053-2.rs:7:32
2020-02-08T20:52:52.8682999Z    |
2020-02-08T20:52:52.8682999Z    |
2020-02-08T20:52:52.8683429Z LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
2020-02-08T20:52:52.8683897Z    |                                ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _`
2020-02-08T20:52:52.8683945Z    |                                |
2020-02-08T20:52:52.8684522Z    |                                expected signature of `for<'r> fn(&'r &str) -> _`
2020-02-08T20:52:52.8684594Z error: aborting due to 2 previous errors
2020-02-08T20:52:52.8684620Z 
2020-02-08T20:52:52.8684677Z Some errors have detailed explanations: E0599, E0631.
2020-02-08T20:52:52.8685075Z For more information about an error, try `rustc --explain E0599`.
---
2020-02-08T20:52:52.8687548Z thread 'main' panicked at 'Some tests failed', src/tools/compiletest/src/main.rs:348:22
2020-02-08T20:52:52.8687616Z note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
2020-02-08T20:52:52.8687646Z 
2020-02-08T20:52:52.8687669Z 
2020-02-08T20:52:52.8689482Z command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/ui" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "ui" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-7/bin/FileCheck" "--host-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--target-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "7.0.0\n" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
2020-02-08T20:52:52.8689684Z 
2020-02-08T20:52:52.8689720Z 
2020-02-08T20:52:52.8689789Z failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
2020-02-08T20:52:52.8689838Z Build completed unsuccessfully in 1:03:16
2020-02-08T20:52:52.8689838Z Build completed unsuccessfully in 1:03:16
2020-02-08T20:52:52.8705932Z == clock drift check ==
2020-02-08T20:52:52.8732151Z   local time: Sat Feb  8 20:52:52 UTC 2020
2020-02-08T20:52:53.1429399Z   network time: Sat, 08 Feb 2020 20:52:53 GMT
2020-02-08T20:52:53.1434848Z == end clock drift check ==
2020-02-08T20:52:53.6034823Z 
2020-02-08T20:52:53.6136021Z ##[error]Bash exited with code '1'.
2020-02-08T20:52:53.6147456Z ##[section]Finishing: Run build
2020-02-08T20:52:53.6174371Z ##[section]Starting: Checkout rust-lang/rust@refs/pull/68472/merge to s
2020-02-08T20:52:53.6176133Z Task         : Get sources
2020-02-08T20:52:53.6176177Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
2020-02-08T20:52:53.6176225Z Version      : 1.0.0
2020-02-08T20:52:53.6176417Z Author       : Microsoft
2020-02-08T20:52:53.6176417Z Author       : Microsoft
2020-02-08T20:52:53.6176461Z Help         : [More Information](https://go.microsoft.com/fwlink/?LinkId=798199)
2020-02-08T20:52:53.6176508Z ==============================================================================
2020-02-08T20:52:54.0473711Z Cleaning any cached credential from repository: rust-lang/rust (GitHub)
2020-02-08T20:52:54.0514484Z ##[section]Finishing: Checkout rust-lang/rust@refs/pull/68472/merge to s
2020-02-08T20:52:54.0624064Z Cleaning up task key
2020-02-08T20:52:54.0624945Z Start cleaning up orphan processes.
2020-02-08T20:52:54.0748378Z Terminate orphan process: pid (12302) (python)
2020-02-08T20:52:54.0997928Z ##[section]Finishing: Finalize Job

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@timvermeulen
Copy link
Contributor

try_fold is by far the most important one. The other methods with a Sized bound that are overridden fairly frequently are fold, count, and last, so I guess there's a case to be made for those as well, but I'm fairly indifferent on those.

@LukasKalbertodt LukasKalbertodt added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 9, 2020
@LukasKalbertodt
Copy link
Member

As you might have noticed, we had a bit of a problem with specialization in the standard library recently. So for now we don't accept any more changes which include specialization until we have some tests in place to ensure we do not accidentally expose that specialization. But this will likely take some time.

Since there is no activity in this PR for two weeks and because of that moratorium, I will close this PR for now. Thanks anyway!

@the8472
Copy link
Member

the8472 commented Dec 13, 2020

Now that min_specialization is available and Sized is a specialization trait this PR could probably be revived.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants