Closed
Description
#![crate_type = "lib"]
struct R {
start: i32,
end: i32
}
impl Iterator for R
{
type Item = i32;
fn next(&mut self) -> Option<i32> {
if self.start < self.end {
let old = self.start;
self.start += 1;
Some(old)
} else {
None
}
}
}
pub fn test() -> usize {
R { start: 0, end: 100000}.count()
}
Compiles to:
_ZN4test20h08046f2c32b9b146kaaE:
.cfi_startproc
xorl %ecx, %ecx
movq $-1, %rax
.align 16, 0x90
.LBB0_1:
cmpl $100000, %ecx
setl %dl
movzbl %dl, %edx
addl %ecx, %edx
incq %rax
cmpl $100000, %ecx
movl %edx, %ecx
jl .LBB0_1
retq
It should at least look something like:
xorl %eax, %eax
movl $100000, %ecx
.LBB0_1:
incl %eax
decl %ecx
jne .LBB0_1
But really that case should be constant folded (clang folds the equivalent C for
loop).
(NB. count
is currently implemented as self.fold(0, |c, _| c + 1)
, and the bad codegen occurs if that is definition is used directly, and also if one uses the mutating for loop: let mut c = 0; for _ in ... { c += 1 }
.)
This previously affected std::ops::Range
(i.e. x..y
), but #24705 implemented a work-around.