rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
96.69k stars 12.49k forks source link

Allow getting a mutable slice from `vec::Drain` #118043

Open mamins1376 opened 9 months ago

mamins1376 commented 9 months ago

Since Vec::drain() in a sense owns the selected range of vector items, it makes sense to be able to hand out a mutable slice pointing to them. This can happen through AsMut trait and vec::Drain::as_mut_slice(), as it is already the case for a immutable slice.

saethlin commented 9 months ago

You should submit an API change proposal: https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&projects=&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29

zachs18 commented 1 month ago

Note that Drain::as_mut_slice and Drain::keep_rest (which currenty exists unstably) cannot both exist soundly, since Drain<'_, T> is covariant in T. Otherwise, you could do something like this (playground link):

#![feature(drain_keep_rest)]
use std::vec::Drain;

fn evil(iter: Drain<'_, &'static str>, local: &str) {
    // rebind for lifetime coercion
    let mut iter = iter;
    iter.as_mut_slice()[0] = local;
    iter.keep_rest();
}

fn main() {
    let mut static_strs: Vec<&'static str> = vec!["hello", "my", "friend"];
    let local = String::from("evil");
    let iter = static_strs.drain(1..2);
    evil(iter, &local);
    drop(local);
    dbg!(static_strs); // use-after-free
}