Auto merge of #137908 - scottmcm:another-size-hint-attempt, r= · rust-lang/rust@272c07f (original) (raw)

`@@ -22,21 +22,39 @@ where

`

22

22

`// empty, but the loop in extend_desugared() is not going to see the

`

23

23

`// vector being full in the few subsequent loop iterations.

`

24

24

`// So we get better branch prediction.

`

25

``

`-

let mut vector = match iterator.next() {

`

26

``

`-

None => return Vec::new(),

`

27

``

`-

Some(element) => {

`

28

``

`-

let (lower, _) = iterator.size_hint();

`

29

``

`-

let initial_capacity =

`

30

``

`-

cmp::max(RawVec::::MIN_NON_ZERO_CAP, lower.saturating_add(1));

`

31

``

`-

let mut vector = Vec::with_capacity(initial_capacity);

`

32

``

`-

unsafe {

`

33

``

`-

// SAFETY: We requested capacity at least 1

`

34

``

`-

ptr::write(vector.as_mut_ptr(), element);

`

35

``

`-

vector.set_len(1);

`

36

``

`-

}

`

37

``

`-

vector

`

38

``

`-

}

`

``

25

`+

let (low, high) = iterator.size_hint();

`

``

26

`+

let Some(first) = iterator.next() else {

`

``

27

`+

return Vec::new();

`

39

28

`};

`

``

29

`` +

// push's growth strategy is (currently) to double the capacity if

``

``

30

`+

// there's no space available, so it can have up to 50% "wasted" space.

`

``

31

`+

// Thus if the upper-bound on the size_hint also wouldn't waste more

`

``

32

`+

// than that, just allocate it from the start. (After all, it's silly

`

``

33

`` +

// to allocate 254 for a hint of (254, Some(255).)

``

``

34

`+

let initial_capacity = {

`

``

35

`+

// This is written like this to not overflow on any well-behaved iterator,

`

``

36

`` +

// even things like repeat_n(val, isize::MAX as usize + 10)

``

``

37

`` +

// where low * 2 would need checking.

``

``

38

`` +

// A bad (but safe) iterator might have low > high, but if so it'll

``

``

39

`` +

// produce a huge extra that'll probably fail the following check.

``

``

40

`+

let hint = if let Some(high) = high

`

``

41

`+

&& let extra = high - low

`

``

42

`+

&& extra < low

`

``

43

`+

{

`

``

44

`+

high

`

``

45

`+

} else {

`

``

46

`+

low

`

``

47

`+

};

`

``

48

`+

cmp::max(RawVec::::MIN_NON_ZERO_CAP, hint)

`

``

49

`+

};

`

``

50

`+

let mut vector = Vec::with_capacity(initial_capacity);

`

``

51

`+

// SAFETY: We requested capacity at least MIN_NON_ZERO_CAP, which

`

``

52

`+

// is never zero, so there's space for at least one element.

`

``

53

`+

unsafe {

`

``

54

`+

ptr::write(vector.as_mut_ptr(), first);

`

``

55

`+

vector.set_len(1);

`

``

56

`+

}

`

``

57

+

40

58

`// must delegate to spec_extend() since extend() itself delegates

`

41

59

`// to spec_from for empty Vecs

`

42

60

` <Vec as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);

`