Auto merge of #1952 - RalfJung:self-referential, r=RalfJung
exclude mutable references to !Unpin types from uniqueness guarantees
This basically works around https://github.com/rust-lang/unsafe-code-guidelines/issues/148 by not requiring uniqueness any more for mutable references to self-referential generators. That corresponds to [the same work-around that was applied in rustc itself](b815532674/compiler/rustc_middle/src/ty/layout.rs (L2482)
).
I am not entirely sure if this is a good idea since it might hide too many errors in case types are "accidentally" `!Unpin`. OTOH, our test suite still passes, and to my knowledge the vast majority of types is `Unpin`. (`place.layout.ty` is monomorphic, we should always exactly know which type this is.)
This commit is contained in:
commit
deb9bfd246
@ -9,7 +9,11 @@
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_hir::Mutability;
|
||||
use rustc_middle::mir::RetagKind;
|
||||
use rustc_middle::ty::{self, layout::LayoutOf};
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
layout::{HasParamEnv, LayoutOf},
|
||||
};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_target::abi::Size;
|
||||
|
||||
use crate::*;
|
||||
@ -657,8 +661,16 @@ fn reborrow(
|
||||
// Make sure that raw pointers and mutable shared references are reborrowed "weak":
|
||||
// There could be existing unique pointers reborrowed from them that should remain valid!
|
||||
let perm = match kind {
|
||||
RefKind::Unique { two_phase: false } => Permission::Unique,
|
||||
RefKind::Unique { two_phase: true } => Permission::SharedReadWrite,
|
||||
RefKind::Unique { two_phase: false }
|
||||
if place.layout.ty.is_unpin(this.tcx.at(DUMMY_SP), this.param_env()) =>
|
||||
{
|
||||
// Only if the type is unpin do we actually enforce uniqueness
|
||||
Permission::Unique
|
||||
}
|
||||
RefKind::Unique { .. } => {
|
||||
// Two-phase references and !Unpin references are treated as SharedReadWrite
|
||||
Permission::SharedReadWrite
|
||||
}
|
||||
RefKind::Raw { mutable: true } => Permission::SharedReadWrite,
|
||||
RefKind::Shared | RefKind::Raw { mutable: false } => {
|
||||
// Shared references and *const are a whole different kind of game, the
|
||||
|
@ -0,0 +1,34 @@
|
||||
// See https://github.com/rust-lang/unsafe-code-guidelines/issues/148:
|
||||
// this fails when Stacked Borrows is strictly applied even to `!Unpin` types.
|
||||
#![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;
|
||||
}
|
||||
assert_eq!(sum, 3);
|
||||
}
|
Loading…
Reference in New Issue
Block a user