exclude mutable references to !Unpin types from uniqueness guarantees
This commit is contained in:
parent
d307e6c197
commit
77cec811b4
2 changed files with 49 additions and 3 deletions
|
|
@ -9,7 +9,11 @@ use std::num::NonZeroU64;
|
|||
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 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
// 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…
Add table
Add a link
Reference in a new issue