Skip to content

Mutable references vs self-referential structs #148

Open
@RalfJung

Description

@RalfJung

Turns out that stacked borrows and self-referential generators don't go well together. This code fails in Miri:

#![feature(generators, generator_trait)]

use std::{
    ops::{Generator, GeneratorState},
    pin::Pin,
};

fn firstn() -> impl Generator<Yield = u64, Return = ()> {
    static move || {
        let mut num = 0;
        let num = &mut num;

        yield *num;
        *num += 1; //~ ERROR: borrow stack

        yield *num;
        *num += 1;

        yield *num;
        *num += 1;
    }
}

fn main() {
    let mut generator_iterator = firstn();
    let mut pin = unsafe { Pin::new_unchecked(&mut generator_iterator) };
    let mut sum = 0;
    while let GeneratorState::Yielded(x) = pin.as_mut().resume() {
        sum += x;
    }
    println!("{}", sum);
}

The reason it fails is that each time through the loop, we call Pin::as_mut, which creates a fresh mutable reference to the generator. Since mutable references are unique, that invalidates the pointer that points from one field of the generator to another.

This is basically a particularly bad instance of #133.

Cc @cramertj @tmandry @nikomatsakis @arielb1

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-aliasing-modelTopic: Related to the aliasing model (e.g. Stacked/Tree Borrows)C-open-questionCategory: An open question that we should revisitS-pending-designStatus: Resolving this issue requires addressing some open design questions

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions