Why doesn't ops::Range implement Copy, even if T is Copy?

后端 未结 1 459
别那么骄傲
别那么骄傲 2021-02-13 09:08

Recently, I wanted to write a type holding parameters for a 3D projection:

use std::ops::Range;

#[derive(Clone, Copy)]
struct CamProj {
    /// Near and far pla         


        
相关标签:
1条回答
  • 2021-02-13 09:54

    Because Range<T> is often used as an iterator, and having iterators be Copy was discovered to be a footgun. One specific example had to do with thinking that an iterator was advanced, when in reality it was a copy that was advanced:

    for x in it {  // a *copy* of the iterator is used here
        // ..
    }
    
    match it.next() {  // the original iterator is used here
        // ..
    }
    

    Another example:

    fn main() {
        let stream = "Hello, world!".chars().cycle();
        for _ in 0..10 {
            let chunk: String = stream.take(3).collect();
            println!("{}", chunk);
        }
    }
    

    And another that prompted a question: Using the same iterator multiple times in Rust

    It was believed that having iterators be explicitly copied via clone helped prevent these cases


    Specifically re-adding Copy to Range was proposed and rejected. A potential workaround was suggested:

    Range fields are public, you can repack them into a copyable tuple (or equivalent) at the constructor/function boundary

    See also:

    • Why are iterators not copyable?
    • Re-using a range for iteration
    0 讨论(0)
提交回复
热议问题