Auto merge of #16669 - ShoyuVanilla:merge-borrow-kind-unique, r=Veykril
Merge `BorrowKind::Unique` into `BorrowKind::Mut` Resolves #15170
This commit is contained in:
commit
e1983d2b90
@ -23,7 +23,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
db::{HirDatabase, InternedClosure},
|
db::{HirDatabase, InternedClosure},
|
||||||
from_placeholder_idx, make_binders,
|
from_placeholder_idx, make_binders,
|
||||||
mir::{BorrowKind, MirSpan, ProjectionElem},
|
mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem},
|
||||||
static_lifetime, to_chalk_trait_id,
|
static_lifetime, to_chalk_trait_id,
|
||||||
traits::FnTrait,
|
traits::FnTrait,
|
||||||
utils::{self, generics, Generics},
|
utils::{self, generics, Generics},
|
||||||
@ -142,9 +142,13 @@ fn capture_kind_of_truncated_place(
|
|||||||
mut current_capture: CaptureKind,
|
mut current_capture: CaptureKind,
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> CaptureKind {
|
) -> CaptureKind {
|
||||||
if let CaptureKind::ByRef(BorrowKind::Mut { .. }) = current_capture {
|
if let CaptureKind::ByRef(BorrowKind::Mut {
|
||||||
|
kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow,
|
||||||
|
}) = current_capture
|
||||||
|
{
|
||||||
if self.projections[len..].iter().any(|it| *it == ProjectionElem::Deref) {
|
if self.projections[len..].iter().any(|it| *it == ProjectionElem::Deref) {
|
||||||
current_capture = CaptureKind::ByRef(BorrowKind::Unique);
|
current_capture =
|
||||||
|
CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_capture
|
current_capture
|
||||||
@ -377,7 +381,7 @@ fn mutate_expr(&mut self, expr: ExprId) {
|
|||||||
if let Some(place) = self.place_of_expr(expr) {
|
if let Some(place) = self.place_of_expr(expr) {
|
||||||
self.add_capture(
|
self.add_capture(
|
||||||
place,
|
place,
|
||||||
CaptureKind::ByRef(BorrowKind::Mut { allow_two_phase_borrow: false }),
|
CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::Default }),
|
||||||
expr.into(),
|
expr.into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -426,9 +430,7 @@ fn walk_expr_with_adjust(&mut self, tgt_expr: ExprId, adjustment: &[Adjustment])
|
|||||||
|
|
||||||
fn ref_capture_with_adjusts(&mut self, m: Mutability, tgt_expr: ExprId, rest: &[Adjustment]) {
|
fn ref_capture_with_adjusts(&mut self, m: Mutability, tgt_expr: ExprId, rest: &[Adjustment]) {
|
||||||
let capture_kind = match m {
|
let capture_kind = match m {
|
||||||
Mutability::Mut => {
|
Mutability::Mut => CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::Default }),
|
||||||
CaptureKind::ByRef(BorrowKind::Mut { allow_two_phase_borrow: false })
|
|
||||||
}
|
|
||||||
Mutability::Not => CaptureKind::ByRef(BorrowKind::Shared),
|
Mutability::Not => CaptureKind::ByRef(BorrowKind::Shared),
|
||||||
};
|
};
|
||||||
if let Some(place) = self.place_of_expr_without_adjust(tgt_expr) {
|
if let Some(place) = self.place_of_expr_without_adjust(tgt_expr) {
|
||||||
@ -648,7 +650,7 @@ fn walk_pat(&mut self, result: &mut Option<CaptureKind>, pat: PatId) {
|
|||||||
self.walk_pat_inner(
|
self.walk_pat_inner(
|
||||||
pat,
|
pat,
|
||||||
&mut update_result,
|
&mut update_result,
|
||||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,7 +701,7 @@ fn walk_pat_inner(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
if self.result.pat_adjustments.get(&p).map_or(false, |it| !it.is_empty()) {
|
if self.result.pat_adjustments.get(&p).map_or(false, |it| !it.is_empty()) {
|
||||||
for_mut = BorrowKind::Unique;
|
for_mut = BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture };
|
||||||
}
|
}
|
||||||
self.body.walk_pats_shallow(p, |p| self.walk_pat_inner(p, update_result, for_mut));
|
self.body.walk_pats_shallow(p, |p| self.walk_pat_inner(p, update_result, for_mut));
|
||||||
}
|
}
|
||||||
@ -880,7 +882,7 @@ fn consume_with_pat(&mut self, mut place: HirPlace, pat: PatId) {
|
|||||||
}
|
}
|
||||||
BindingMode::Ref(Mutability::Not) => BorrowKind::Shared,
|
BindingMode::Ref(Mutability::Not) => BorrowKind::Shared,
|
||||||
BindingMode::Ref(Mutability::Mut) => {
|
BindingMode::Ref(Mutability::Mut) => {
|
||||||
BorrowKind::Mut { allow_two_phase_borrow: false }
|
BorrowKind::Mut { kind: MutBorrowKind::Default }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.add_capture(place, CaptureKind::ByRef(capture_kind), pat.into());
|
self.add_capture(place, CaptureKind::ByRef(capture_kind), pat.into());
|
||||||
@ -930,9 +932,7 @@ fn closure_kind(&self) -> FnTrait {
|
|||||||
r = cmp::min(
|
r = cmp::min(
|
||||||
r,
|
r,
|
||||||
match &it.kind {
|
match &it.kind {
|
||||||
CaptureKind::ByRef(BorrowKind::Unique | BorrowKind::Mut { .. }) => {
|
CaptureKind::ByRef(BorrowKind::Mut { .. }) => FnTrait::FnMut,
|
||||||
FnTrait::FnMut
|
|
||||||
}
|
|
||||||
CaptureKind::ByRef(BorrowKind::Shallow | BorrowKind::Shared) => FnTrait::Fn,
|
CaptureKind::ByRef(BorrowKind::Shallow | BorrowKind::Shared) => FnTrait::Fn,
|
||||||
CaptureKind::ByValue => FnTrait::FnOnce,
|
CaptureKind::ByValue => FnTrait::FnOnce,
|
||||||
},
|
},
|
||||||
@ -949,8 +949,12 @@ fn analyze_closure(&mut self, closure: ClosureId) -> FnTrait {
|
|||||||
};
|
};
|
||||||
self.consume_expr(*body);
|
self.consume_expr(*body);
|
||||||
for item in &self.current_captures {
|
for item in &self.current_captures {
|
||||||
if matches!(item.kind, CaptureKind::ByRef(BorrowKind::Mut { .. }))
|
if matches!(
|
||||||
&& !item.place.projections.contains(&ProjectionElem::Deref)
|
item.kind,
|
||||||
|
CaptureKind::ByRef(BorrowKind::Mut {
|
||||||
|
kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow
|
||||||
|
})
|
||||||
|
) && !item.place.projections.contains(&ProjectionElem::Deref)
|
||||||
{
|
{
|
||||||
// FIXME: remove the `mutated_bindings_in_closure` completely and add proper fake reads in
|
// FIXME: remove the `mutated_bindings_in_closure` completely and add proper fake reads in
|
||||||
// MIR. I didn't do that due duplicate diagnostics.
|
// MIR. I didn't do that due duplicate diagnostics.
|
||||||
|
@ -659,66 +659,33 @@ pub enum BorrowKind {
|
|||||||
/// We can also report errors with this kind of borrow differently.
|
/// We can also report errors with this kind of borrow differently.
|
||||||
Shallow,
|
Shallow,
|
||||||
|
|
||||||
/// Data must be immutable but not aliasable. This kind of borrow
|
|
||||||
/// cannot currently be expressed by the user and is used only in
|
|
||||||
/// implicit closure bindings. It is needed when the closure is
|
|
||||||
/// borrowing or mutating a mutable referent, e.g.:
|
|
||||||
/// ```
|
|
||||||
/// let mut z = 3;
|
|
||||||
/// let x: &mut isize = &mut z;
|
|
||||||
/// let y = || *x += 5;
|
|
||||||
/// ```
|
|
||||||
/// If we were to try to translate this closure into a more explicit
|
|
||||||
/// form, we'd encounter an error with the code as written:
|
|
||||||
/// ```compile_fail,E0594
|
|
||||||
/// struct Env<'a> { x: &'a &'a mut isize }
|
|
||||||
/// let mut z = 3;
|
|
||||||
/// let x: &mut isize = &mut z;
|
|
||||||
/// let y = (&mut Env { x: &x }, fn_ptr); // Closure is pair of env and fn
|
|
||||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
|
||||||
/// ```
|
|
||||||
/// This is then illegal because you cannot mutate an `&mut` found
|
|
||||||
/// in an aliasable location. To solve, you'd have to translate with
|
|
||||||
/// an `&mut` borrow:
|
|
||||||
/// ```compile_fail,E0596
|
|
||||||
/// struct Env<'a> { x: &'a mut &'a mut isize }
|
|
||||||
/// let mut z = 3;
|
|
||||||
/// let x: &mut isize = &mut z;
|
|
||||||
/// let y = (&mut Env { x: &mut x }, fn_ptr); // changed from &x to &mut x
|
|
||||||
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
|
|
||||||
/// ```
|
|
||||||
/// Now the assignment to `**env.x` is legal, but creating a
|
|
||||||
/// mutable pointer to `x` is not because `x` is not mutable. We
|
|
||||||
/// could fix this by declaring `x` as `let mut x`. This is ok in
|
|
||||||
/// user code, if awkward, but extra weird for closures, since the
|
|
||||||
/// borrow is hidden.
|
|
||||||
///
|
|
||||||
/// So we introduce a "unique imm" borrow -- the referent is
|
|
||||||
/// immutable, but not aliasable. This solves the problem. For
|
|
||||||
/// simplicity, we don't give users the way to express this
|
|
||||||
/// borrow, it's just used when translating closures.
|
|
||||||
Unique,
|
|
||||||
|
|
||||||
/// Data is mutable and not aliasable.
|
/// Data is mutable and not aliasable.
|
||||||
Mut {
|
Mut { kind: MutBorrowKind },
|
||||||
/// `true` if this borrow arose from method-call auto-ref
|
}
|
||||||
/// (i.e., `adjustment::Adjust::Borrow`).
|
|
||||||
allow_two_phase_borrow: bool,
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
|
||||||
},
|
pub enum MutBorrowKind {
|
||||||
|
Default,
|
||||||
|
/// This borrow arose from method-call auto-ref
|
||||||
|
/// (i.e., adjustment::Adjust::Borrow).
|
||||||
|
TwoPhasedBorrow,
|
||||||
|
/// Data must be immutable but not aliasable. This kind of borrow cannot currently
|
||||||
|
/// be expressed by the user and is used only in implicit closure bindings.
|
||||||
|
ClosureCapture,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BorrowKind {
|
impl BorrowKind {
|
||||||
fn from_hir(m: hir_def::type_ref::Mutability) -> Self {
|
fn from_hir(m: hir_def::type_ref::Mutability) -> Self {
|
||||||
match m {
|
match m {
|
||||||
hir_def::type_ref::Mutability::Shared => BorrowKind::Shared,
|
hir_def::type_ref::Mutability::Shared => BorrowKind::Shared,
|
||||||
hir_def::type_ref::Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
|
hir_def::type_ref::Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_chalk(m: Mutability) -> Self {
|
fn from_chalk(m: Mutability) -> Self {
|
||||||
match m {
|
match m {
|
||||||
Mutability::Not => BorrowKind::Shared,
|
Mutability::Not => BorrowKind::Shared,
|
||||||
Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
|
Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
BasicBlockId, BorrowKind, LocalId, MirBody, MirLowerError, MirSpan, Place, ProjectionElem,
|
BasicBlockId, BorrowKind, LocalId, MirBody, MirLowerError, MirSpan, MutBorrowKind, Place,
|
||||||
Rvalue, StatementKind, TerminatorKind,
|
ProjectionElem, Rvalue, StatementKind, TerminatorKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@ -540,7 +540,13 @@ fn mutability_of_locals(
|
|||||||
}
|
}
|
||||||
Rvalue::ShallowInitBox(_, _) | Rvalue::ShallowInitBoxWithAlloc(_) => (),
|
Rvalue::ShallowInitBox(_, _) | Rvalue::ShallowInitBoxWithAlloc(_) => (),
|
||||||
}
|
}
|
||||||
if let Rvalue::Ref(BorrowKind::Mut { .. }, p) = value {
|
if let Rvalue::Ref(
|
||||||
|
BorrowKind::Mut {
|
||||||
|
kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow,
|
||||||
|
},
|
||||||
|
p,
|
||||||
|
) = value
|
||||||
|
{
|
||||||
if place_case(db, body, p) != ProjectionCase::Indirect {
|
if place_case(db, body, p) != ProjectionCase::Indirect {
|
||||||
push_mut_span(p.local, statement.span, &mut result);
|
push_mut_span(p.local, statement.span, &mut result);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
//! MIR lowering for places
|
//! MIR lowering for places
|
||||||
|
|
||||||
|
use crate::mir::MutBorrowKind;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use hir_def::FunctionId;
|
use hir_def::FunctionId;
|
||||||
use hir_expand::name;
|
use hir_expand::name;
|
||||||
@ -328,7 +330,7 @@ fn lower_overloaded_deref(
|
|||||||
Mutability::Mut,
|
Mutability::Mut,
|
||||||
LangItem::DerefMut,
|
LangItem::DerefMut,
|
||||||
name![deref_mut],
|
name![deref_mut],
|
||||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let ty_ref = TyKind::Ref(chalk_mut, static_lifetime(), source_ty.clone()).intern(Interner);
|
let ty_ref = TyKind::Ref(chalk_mut, static_lifetime(), source_ty.clone()).intern(Interner);
|
||||||
|
@ -3,12 +3,15 @@
|
|||||||
use hir_def::{hir::LiteralOrConst, resolver::HasResolver, AssocItemId};
|
use hir_def::{hir::LiteralOrConst, resolver::HasResolver, AssocItemId};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mir::lower::{
|
mir::{
|
||||||
BasicBlockId, BinOp, BindingId, BorrowKind, Either, Expr, FieldId, Idx, Interner,
|
lower::{
|
||||||
MemoryMap, MirLowerCtx, MirLowerError, MirSpan, Mutability, Operand, Pat, PatId, Place,
|
BasicBlockId, BinOp, BindingId, BorrowKind, Either, Expr, FieldId, Idx, Interner,
|
||||||
PlaceElem, ProjectionElem, RecordFieldPat, ResolveValueResult, Result, Rvalue,
|
MemoryMap, MirLowerCtx, MirLowerError, MirSpan, Mutability, Operand, Pat, PatId, Place,
|
||||||
Substitution, SwitchTargets, TerminatorKind, TupleFieldId, TupleId, TyBuilder, TyKind,
|
PlaceElem, ProjectionElem, RecordFieldPat, ResolveValueResult, Result, Rvalue,
|
||||||
ValueNs, VariantData, VariantId,
|
Substitution, SwitchTargets, TerminatorKind, TupleFieldId, TupleId, TyBuilder, TyKind,
|
||||||
|
ValueNs, VariantData, VariantId,
|
||||||
|
},
|
||||||
|
MutBorrowKind,
|
||||||
},
|
},
|
||||||
BindingMode,
|
BindingMode,
|
||||||
};
|
};
|
||||||
@ -450,7 +453,7 @@ fn pattern_match_binding(
|
|||||||
BindingMode::Move => Operand::Copy(cond_place).into(),
|
BindingMode::Move => Operand::Copy(cond_place).into(),
|
||||||
BindingMode::Ref(Mutability::Not) => Rvalue::Ref(BorrowKind::Shared, cond_place),
|
BindingMode::Ref(Mutability::Not) => Rvalue::Ref(BorrowKind::Shared, cond_place),
|
||||||
BindingMode::Ref(Mutability::Mut) => {
|
BindingMode::Ref(Mutability::Mut) => {
|
||||||
Rvalue::Ref(BorrowKind::Mut { allow_two_phase_borrow: false }, cond_place)
|
Rvalue::Ref(BorrowKind::Mut { kind: MutBorrowKind::Default }, cond_place)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
span,
|
span,
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AggregateKind, BasicBlockId, BorrowKind, LocalId, MirBody, Operand, Place, Rvalue, UnOp,
|
AggregateKind, BasicBlockId, BorrowKind, LocalId, MirBody, MutBorrowKind, Operand, Place,
|
||||||
|
Rvalue, UnOp,
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! w {
|
macro_rules! w {
|
||||||
@ -366,8 +367,10 @@ fn rvalue(&mut self, r: &Rvalue) {
|
|||||||
match r {
|
match r {
|
||||||
BorrowKind::Shared => w!(self, "&"),
|
BorrowKind::Shared => w!(self, "&"),
|
||||||
BorrowKind::Shallow => w!(self, "&shallow "),
|
BorrowKind::Shallow => w!(self, "&shallow "),
|
||||||
BorrowKind::Unique => w!(self, "&uniq "),
|
BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => w!(self, "&uniq "),
|
||||||
BorrowKind::Mut { .. } => w!(self, "&mut "),
|
BorrowKind::Mut {
|
||||||
|
kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow,
|
||||||
|
} => w!(self, "&mut "),
|
||||||
}
|
}
|
||||||
self.place(p);
|
self.place(p);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
known_const_to_ast,
|
known_const_to_ast,
|
||||||
layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
|
layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
|
||||||
method_resolution::{self, TyFingerprint},
|
method_resolution::{self, TyFingerprint},
|
||||||
mir::interpret_mir,
|
mir::{interpret_mir, MutBorrowKind},
|
||||||
primitive::UintTy,
|
primitive::UintTy,
|
||||||
traits::FnTrait,
|
traits::FnTrait,
|
||||||
AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
|
AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
|
||||||
@ -3754,12 +3754,12 @@ pub fn kind(&self) -> CaptureKind {
|
|||||||
hir_ty::CaptureKind::ByRef(
|
hir_ty::CaptureKind::ByRef(
|
||||||
hir_ty::mir::BorrowKind::Shallow | hir_ty::mir::BorrowKind::Shared,
|
hir_ty::mir::BorrowKind::Shallow | hir_ty::mir::BorrowKind::Shared,
|
||||||
) => CaptureKind::SharedRef,
|
) => CaptureKind::SharedRef,
|
||||||
hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Unique) => {
|
hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Mut {
|
||||||
CaptureKind::UniqueSharedRef
|
kind: MutBorrowKind::ClosureCapture,
|
||||||
}
|
}) => CaptureKind::UniqueSharedRef,
|
||||||
hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Mut { .. }) => {
|
hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Mut {
|
||||||
CaptureKind::MutableRef
|
kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow,
|
||||||
}
|
}) => CaptureKind::MutableRef,
|
||||||
hir_ty::CaptureKind::ByValue => CaptureKind::Move,
|
hir_ty::CaptureKind::ByValue => CaptureKind::Move,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user