merge BorrowKind::Unique
into BorrowKind::Mut
This commit is contained in:
parent
6fc0273b5a
commit
8fb4c41f35
21 changed files with 109 additions and 105 deletions
|
@ -72,7 +72,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
|
||||||
let kind = match self.kind {
|
let kind = match self.kind {
|
||||||
mir::BorrowKind::Shared => "",
|
mir::BorrowKind::Shared => "",
|
||||||
mir::BorrowKind::Shallow => "shallow ",
|
mir::BorrowKind::Shallow => "shallow ",
|
||||||
mir::BorrowKind::Unique => "uniq ",
|
mir::BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture } => "uniq ",
|
||||||
mir::BorrowKind::Mut { .. } => "mut ",
|
mir::BorrowKind::Mut { .. } => "mut ",
|
||||||
};
|
};
|
||||||
write!(w, "&{:?} {}{:?}", self.region, kind, self.borrowed_place)
|
write!(w, "&{:?} {}{:?}", self.region, kind, self.borrowed_place)
|
||||||
|
|
|
@ -15,8 +15,9 @@ use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||||
use rustc_middle::mir::tcx::PlaceTy;
|
use rustc_middle::mir::tcx::PlaceTy;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
|
self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
|
||||||
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
|
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind, Operand, Place,
|
||||||
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
|
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
|
||||||
|
VarBindingForm,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
|
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
|
||||||
use rustc_middle::util::CallKind;
|
use rustc_middle::util::CallKind;
|
||||||
|
@ -926,7 +927,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
// FIXME: supply non-"" `opt_via` when appropriate
|
// FIXME: supply non-"" `opt_via` when appropriate
|
||||||
let first_borrow_desc;
|
let first_borrow_desc;
|
||||||
let mut err = match (gen_borrow_kind, issued_borrow.kind) {
|
let mut err = match (gen_borrow_kind, issued_borrow.kind) {
|
||||||
(BorrowKind::Shared, BorrowKind::Mut { .. }) => {
|
(
|
||||||
|
BorrowKind::Shared,
|
||||||
|
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||||
|
) => {
|
||||||
first_borrow_desc = "mutable ";
|
first_borrow_desc = "mutable ";
|
||||||
self.cannot_reborrow_already_borrowed(
|
self.cannot_reborrow_already_borrowed(
|
||||||
span,
|
span,
|
||||||
|
@ -940,7 +944,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(BorrowKind::Mut { .. }, BorrowKind::Shared) => {
|
(
|
||||||
|
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||||
|
BorrowKind::Shared,
|
||||||
|
) => {
|
||||||
first_borrow_desc = "immutable ";
|
first_borrow_desc = "immutable ";
|
||||||
let mut err = self.cannot_reborrow_already_borrowed(
|
let mut err = self.cannot_reborrow_already_borrowed(
|
||||||
span,
|
span,
|
||||||
|
@ -962,7 +969,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
|
||||||
(BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => {
|
(
|
||||||
|
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||||
|
BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
|
||||||
|
) => {
|
||||||
first_borrow_desc = "first ";
|
first_borrow_desc = "first ";
|
||||||
let mut err = self.cannot_mutably_borrow_multiply(
|
let mut err = self.cannot_mutably_borrow_multiply(
|
||||||
span,
|
span,
|
||||||
|
@ -985,12 +995,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
|
||||||
(BorrowKind::Unique, BorrowKind::Unique) => {
|
(
|
||||||
|
BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
|
||||||
|
BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
|
||||||
|
) => {
|
||||||
first_borrow_desc = "first ";
|
first_borrow_desc = "first ";
|
||||||
self.cannot_uniquely_borrow_by_two_closures(span, &desc_place, issued_span, None)
|
self.cannot_uniquely_borrow_by_two_closures(span, &desc_place, issued_span, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
(BorrowKind::Mut { .. } | BorrowKind::Unique, BorrowKind::Shallow) => {
|
(BorrowKind::Mut { .. }, BorrowKind::Shallow) => {
|
||||||
if let Some(immutable_section_description) =
|
if let Some(immutable_section_description) =
|
||||||
self.classify_immutable_section(issued_borrow.assigned_place)
|
self.classify_immutable_section(issued_borrow.assigned_place)
|
||||||
{
|
{
|
||||||
|
@ -1004,7 +1017,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
borrow_spans.var_subdiag(
|
borrow_spans.var_subdiag(
|
||||||
None,
|
None,
|
||||||
&mut err,
|
&mut err,
|
||||||
Some(BorrowKind::Unique),
|
Some(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }),
|
||||||
|kind, var_span| {
|
|kind, var_span| {
|
||||||
use crate::session_diagnostics::CaptureVarCause::*;
|
use crate::session_diagnostics::CaptureVarCause::*;
|
||||||
match kind {
|
match kind {
|
||||||
|
@ -1038,7 +1051,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(BorrowKind::Unique, _) => {
|
(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }, _) => {
|
||||||
first_borrow_desc = "first ";
|
first_borrow_desc = "first ";
|
||||||
self.cannot_uniquely_borrow_by_one_closure(
|
self.cannot_uniquely_borrow_by_one_closure(
|
||||||
span,
|
span,
|
||||||
|
@ -1052,7 +1065,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
(BorrowKind::Shared, BorrowKind::Unique) => {
|
(BorrowKind::Shared, BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }) => {
|
||||||
first_borrow_desc = "first ";
|
first_borrow_desc = "first ";
|
||||||
self.cannot_reborrow_already_uniquely_borrowed(
|
self.cannot_reborrow_already_uniquely_borrowed(
|
||||||
span,
|
span,
|
||||||
|
@ -1067,7 +1080,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
(BorrowKind::Mut { .. }, BorrowKind::Unique) => {
|
(BorrowKind::Mut { .. }, BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }) => {
|
||||||
first_borrow_desc = "first ";
|
first_borrow_desc = "first ";
|
||||||
self.cannot_reborrow_already_uniquely_borrowed(
|
self.cannot_reborrow_already_uniquely_borrowed(
|
||||||
span,
|
span,
|
||||||
|
@ -1085,10 +1098,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
(BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Shallow)
|
(BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Shallow)
|
||||||
| (
|
| (
|
||||||
BorrowKind::Shallow,
|
BorrowKind::Shallow,
|
||||||
BorrowKind::Mut { .. }
|
BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow,
|
||||||
| BorrowKind::Unique
|
|
||||||
| BorrowKind::Shared
|
|
||||||
| BorrowKind::Shallow,
|
|
||||||
) => unreachable!(),
|
) => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -629,9 +629,9 @@ impl UseSpans<'_> {
|
||||||
Some(kd) => match kd {
|
Some(kd) => match kd {
|
||||||
rustc_middle::mir::BorrowKind::Shared
|
rustc_middle::mir::BorrowKind::Shared
|
||||||
| rustc_middle::mir::BorrowKind::Shallow
|
| rustc_middle::mir::BorrowKind::Shallow
|
||||||
| rustc_middle::mir::BorrowKind::Unique => {
|
| rustc_middle::mir::BorrowKind::Mut {
|
||||||
CaptureVarKind::Immut { kind_span: capture_kind_span }
|
kind: rustc_middle::mir::MutBorrowKind::ClosureCapture,
|
||||||
}
|
} => CaptureVarKind::Immut { kind_span: capture_kind_span },
|
||||||
|
|
||||||
rustc_middle::mir::BorrowKind::Mut { .. } => {
|
rustc_middle::mir::BorrowKind::Mut { .. } => {
|
||||||
CaptureVarKind::Mut { kind_span: capture_kind_span }
|
CaptureVarKind::Mut { kind_span: capture_kind_span }
|
||||||
|
|
|
@ -234,7 +234,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
borrow_spans.var_subdiag(
|
borrow_spans.var_subdiag(
|
||||||
None,
|
None,
|
||||||
&mut err,
|
&mut err,
|
||||||
Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }),
|
Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }),
|
||||||
|_kind, var_span| {
|
|_kind, var_span| {
|
||||||
let place = self.describe_any_place(access_place.as_ref());
|
let place = self.describe_any_place(access_place.as_ref());
|
||||||
crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure {
|
crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure {
|
||||||
|
@ -300,7 +300,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
_,
|
_,
|
||||||
mir::Rvalue::Ref(
|
mir::Rvalue::Ref(
|
||||||
_,
|
_,
|
||||||
mir::BorrowKind::Mut { allow_two_phase_borrow: false },
|
mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
|
||||||
_,
|
_,
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -255,7 +255,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
||||||
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
|
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
|
||||||
}
|
}
|
||||||
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
|
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
|
||||||
BorrowKind::Unique | BorrowKind::Mut { .. } => {
|
BorrowKind::Mut { .. } => {
|
||||||
let wk = WriteKind::MutableBorrow(bk);
|
let wk = WriteKind::MutableBorrow(bk);
|
||||||
if allow_two_phase_borrow(bk) {
|
if allow_two_phase_borrow(bk) {
|
||||||
(Deep, Reservation(wk))
|
(Deep, Reservation(wk))
|
||||||
|
@ -273,7 +273,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
||||||
Mutability::Mut => (
|
Mutability::Mut => (
|
||||||
Deep,
|
Deep,
|
||||||
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
|
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
|
||||||
allow_two_phase_borrow: false,
|
kind: mir::MutBorrowKind::Default,
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
|
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
|
||||||
|
@ -376,14 +376,11 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
(Read(_), BorrowKind::Shallow | BorrowKind::Shared)
|
(Read(_), BorrowKind::Shallow | BorrowKind::Shared)
|
||||||
| (
|
| (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => {
|
||||||
Read(ReadKind::Borrow(BorrowKind::Shallow)),
|
|
||||||
BorrowKind::Unique | BorrowKind::Mut { .. },
|
|
||||||
) => {
|
|
||||||
// Reads don't invalidate shared or shallow borrows
|
// Reads don't invalidate shared or shallow borrows
|
||||||
}
|
}
|
||||||
|
|
||||||
(Read(_), BorrowKind::Unique | BorrowKind::Mut { .. }) => {
|
(Read(_), BorrowKind::Mut { .. }) => {
|
||||||
// Reading from mere reservations of mutable-borrows is OK.
|
// Reading from mere reservations of mutable-borrows is OK.
|
||||||
if !is_active(&this.dominators, borrow, location) {
|
if !is_active(&this.dominators, borrow, location) {
|
||||||
// If the borrow isn't active yet, reads don't invalidate it
|
// If the borrow isn't active yet, reads don't invalidate it
|
||||||
|
@ -425,7 +422,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
||||||
// only mutable borrows should be 2-phase
|
// only mutable borrows should be 2-phase
|
||||||
assert!(match borrow.kind {
|
assert!(match borrow.kind {
|
||||||
BorrowKind::Shared | BorrowKind::Shallow => false,
|
BorrowKind::Shared | BorrowKind::Shallow => false,
|
||||||
BorrowKind::Unique | BorrowKind::Mut { .. } => true,
|
BorrowKind::Mut { .. } => true,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.access_place(
|
self.access_place(
|
||||||
|
|
|
@ -29,8 +29,8 @@ use rustc_infer::infer::{
|
||||||
InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
|
InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
|
||||||
};
|
};
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand,
|
traversal, Body, ClearCrossCrate, Local, Location, MutBorrowKind, Mutability,
|
||||||
Place, PlaceElem, PlaceRef, VarDebugInfoContents,
|
NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, VarDebugInfoContents,
|
||||||
};
|
};
|
||||||
use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
||||||
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
||||||
|
@ -1071,10 +1071,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
(Read(_), BorrowKind::Shared | BorrowKind::Shallow)
|
(Read(_), BorrowKind::Shared | BorrowKind::Shallow)
|
||||||
| (
|
| (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => {
|
||||||
Read(ReadKind::Borrow(BorrowKind::Shallow)),
|
Control::Continue
|
||||||
BorrowKind::Unique | BorrowKind::Mut { .. },
|
}
|
||||||
) => Control::Continue,
|
|
||||||
|
|
||||||
(Reservation(_), BorrowKind::Shallow | BorrowKind::Shared) => {
|
(Reservation(_), BorrowKind::Shallow | BorrowKind::Shared) => {
|
||||||
// This used to be a future compatibility warning (to be
|
// This used to be a future compatibility warning (to be
|
||||||
|
@ -1087,7 +1086,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
Control::Continue
|
Control::Continue
|
||||||
}
|
}
|
||||||
|
|
||||||
(Read(kind), BorrowKind::Unique | BorrowKind::Mut { .. }) => {
|
(Read(kind), BorrowKind::Mut { .. }) => {
|
||||||
// Reading from mere reservations of mutable-borrows is OK.
|
// Reading from mere reservations of mutable-borrows is OK.
|
||||||
if !is_active(this.dominators(), borrow, location) {
|
if !is_active(this.dominators(), borrow, location) {
|
||||||
assert!(allow_two_phase_borrow(borrow.kind));
|
assert!(allow_two_phase_borrow(borrow.kind));
|
||||||
|
@ -1194,7 +1193,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
|
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
|
||||||
}
|
}
|
||||||
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
|
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
|
||||||
BorrowKind::Unique | BorrowKind::Mut { .. } => {
|
BorrowKind::Mut { .. } => {
|
||||||
let wk = WriteKind::MutableBorrow(bk);
|
let wk = WriteKind::MutableBorrow(bk);
|
||||||
if allow_two_phase_borrow(bk) {
|
if allow_two_phase_borrow(bk) {
|
||||||
(Deep, Reservation(wk))
|
(Deep, Reservation(wk))
|
||||||
|
@ -1231,7 +1230,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
Mutability::Mut => (
|
Mutability::Mut => (
|
||||||
Deep,
|
Deep,
|
||||||
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
|
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
|
||||||
allow_two_phase_borrow: false,
|
kind: MutBorrowKind::Default,
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
|
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
|
||||||
|
@ -1565,7 +1564,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
// only mutable borrows should be 2-phase
|
// only mutable borrows should be 2-phase
|
||||||
assert!(match borrow.kind {
|
assert!(match borrow.kind {
|
||||||
BorrowKind::Shared | BorrowKind::Shallow => false,
|
BorrowKind::Shared | BorrowKind::Shallow => false,
|
||||||
BorrowKind::Unique | BorrowKind::Mut { .. } => true,
|
BorrowKind::Mut { .. } => true,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.access_place(
|
self.access_place(
|
||||||
|
@ -1959,14 +1958,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
let the_place_err;
|
let the_place_err;
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
Reservation(WriteKind::MutableBorrow(
|
Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. }))
|
||||||
borrow_kind @ (BorrowKind::Unique | BorrowKind::Mut { .. }),
|
| Write(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. })) => {
|
||||||
))
|
|
||||||
| Write(WriteKind::MutableBorrow(
|
|
||||||
borrow_kind @ (BorrowKind::Unique | BorrowKind::Mut { .. }),
|
|
||||||
)) => {
|
|
||||||
let is_local_mutation_allowed = match borrow_kind {
|
let is_local_mutation_allowed = match borrow_kind {
|
||||||
BorrowKind::Unique => LocalMutationIsAllowed::Yes,
|
BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
|
||||||
|
LocalMutationIsAllowed::Yes
|
||||||
|
}
|
||||||
BorrowKind::Mut { .. } => is_local_mutation_allowed,
|
BorrowKind::Mut { .. } => is_local_mutation_allowed,
|
||||||
BorrowKind::Shared | BorrowKind::Shallow => unreachable!(),
|
BorrowKind::Shared | BorrowKind::Shallow => unreachable!(),
|
||||||
};
|
};
|
||||||
|
@ -2031,12 +2028,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Read(
|
Read(
|
||||||
ReadKind::Borrow(
|
ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow)
|
||||||
BorrowKind::Unique
|
|
||||||
| BorrowKind::Mut { .. }
|
|
||||||
| BorrowKind::Shared
|
|
||||||
| BorrowKind::Shallow,
|
|
||||||
)
|
|
||||||
| ReadKind::Copy,
|
| ReadKind::Copy,
|
||||||
) => {
|
) => {
|
||||||
// Access authorized
|
// Access authorized
|
||||||
|
|
|
@ -4,7 +4,9 @@ use crate::ArtificialField;
|
||||||
use crate::Overlap;
|
use crate::Overlap;
|
||||||
use crate::{AccessDepth, Deep, Shallow};
|
use crate::{AccessDepth, Deep, Shallow};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem};
|
use rustc_middle::mir::{
|
||||||
|
Body, BorrowKind, Local, MutBorrowKind, Place, PlaceElem, PlaceRef, ProjectionElem,
|
||||||
|
};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
@ -35,7 +37,7 @@ pub fn places_conflict<'tcx>(
|
||||||
tcx,
|
tcx,
|
||||||
body,
|
body,
|
||||||
borrow_place,
|
borrow_place,
|
||||||
BorrowKind::Mut { allow_two_phase_borrow: true },
|
BorrowKind::Mut { kind: MutBorrowKind::TwoPhaseBorrow },
|
||||||
access_place.as_ref(),
|
access_place.as_ref(),
|
||||||
AccessDepth::Deep,
|
AccessDepth::Deep,
|
||||||
bias,
|
bias,
|
||||||
|
|
|
@ -412,7 +412,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
BorrowKind::Shallow => {
|
BorrowKind::Shallow => {
|
||||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
|
||||||
}
|
}
|
||||||
BorrowKind::Unique => PlaceContext::MutatingUse(MutatingUseContext::Borrow),
|
|
||||||
BorrowKind::Mut { .. } => {
|
BorrowKind::Mut { .. } => {
|
||||||
PlaceContext::MutatingUse(MutatingUseContext::Borrow)
|
PlaceContext::MutatingUse(MutatingUseContext::Borrow)
|
||||||
}
|
}
|
||||||
|
@ -457,7 +456,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Ref(_, kind @ (BorrowKind::Mut { .. } | BorrowKind::Unique), place) => {
|
Rvalue::Ref(_, kind @ BorrowKind::Mut { .. }, place) => {
|
||||||
let ty = place.ty(self.body, self.tcx).ty;
|
let ty = place.ty(self.body, self.tcx).ty;
|
||||||
let is_allowed = match ty.kind() {
|
let is_allowed = match ty.kind() {
|
||||||
// Inside a `static mut`, `&mut [...]` is allowed.
|
// Inside a `static mut`, `&mut [...]` is allowed.
|
||||||
|
|
|
@ -103,7 +103,7 @@ where
|
||||||
fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool {
|
fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool {
|
||||||
match kind {
|
match kind {
|
||||||
mir::BorrowKind::Mut { .. } => true,
|
mir::BorrowKind::Mut { .. } => true,
|
||||||
mir::BorrowKind::Shared | mir::BorrowKind::Shallow | mir::BorrowKind::Unique => {
|
mir::BorrowKind::Shared | mir::BorrowKind::Shallow => {
|
||||||
self.shared_borrow_allows_mutation(place)
|
self.shared_borrow_allows_mutation(place)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -454,7 +454,9 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||||
match kind {
|
match kind {
|
||||||
// Reject these borrow types just to be safe.
|
// Reject these borrow types just to be safe.
|
||||||
// FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase.
|
// FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase.
|
||||||
BorrowKind::Shallow | BorrowKind::Unique => return Err(Unpromotable),
|
BorrowKind::Shallow | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
|
||||||
|
return Err(Unpromotable);
|
||||||
|
}
|
||||||
|
|
||||||
BorrowKind::Shared => {
|
BorrowKind::Shared => {
|
||||||
let has_mut_interior = self.qualif_local::<qualifs::HasMutInterior>(place.local);
|
let has_mut_interior = self.qualif_local::<qualifs::HasMutInterior>(place.local);
|
||||||
|
|
|
@ -2035,22 +2035,24 @@ impl<'tcx> Rvalue<'tcx> {
|
||||||
impl BorrowKind {
|
impl BorrowKind {
|
||||||
pub fn mutability(&self) -> Mutability {
|
pub fn mutability(&self) -> Mutability {
|
||||||
match *self {
|
match *self {
|
||||||
BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => Mutability::Not,
|
BorrowKind::Shared | BorrowKind::Shallow => Mutability::Not,
|
||||||
BorrowKind::Mut { .. } => Mutability::Mut,
|
BorrowKind::Mut { .. } => Mutability::Mut,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allows_two_phase_borrow(&self) -> bool {
|
pub fn allows_two_phase_borrow(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false,
|
BorrowKind::Shared | BorrowKind::Shallow => false,
|
||||||
BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow,
|
BorrowKind::Mut { kind } => kind == MutBorrowKind::TwoPhaseBorrow,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: won't be used after diagnostic migration
|
// FIXME: won't be used after diagnostic migration
|
||||||
pub fn describe_mutability(&self) -> &str {
|
pub fn describe_mutability(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => "immutable",
|
BorrowKind::Shared
|
||||||
|
| BorrowKind::Shallow
|
||||||
|
| BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => "immutable",
|
||||||
BorrowKind::Mut { .. } => "mutable",
|
BorrowKind::Mut { .. } => "mutable",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2090,7 +2092,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||||
let kind_str = match borrow_kind {
|
let kind_str = match borrow_kind {
|
||||||
BorrowKind::Shared => "",
|
BorrowKind::Shared => "",
|
||||||
BorrowKind::Shallow => "shallow ",
|
BorrowKind::Shallow => "shallow ",
|
||||||
BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ",
|
BorrowKind::Mut { .. } => "mut ",
|
||||||
};
|
};
|
||||||
|
|
||||||
// When printing regions, add trailing space if necessary.
|
// When printing regions, add trailing space if necessary.
|
||||||
|
|
|
@ -182,6 +182,16 @@ 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 is mutable and not aliasable.
|
||||||
|
Mut { kind: MutBorrowKind },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
|
||||||
|
#[derive(Hash, HashStable)]
|
||||||
|
pub enum MutBorrowKind {
|
||||||
|
Default,
|
||||||
|
/// this borrow arose from method-call auto-ref. (i.e., `adjustment::Adjust::Borrow`)
|
||||||
|
TwoPhaseBorrow,
|
||||||
/// Data must be immutable but not aliasable. This kind of borrow
|
/// Data must be immutable but not aliasable. This kind of borrow
|
||||||
/// cannot currently be expressed by the user and is used only in
|
/// cannot currently be expressed by the user and is used only in
|
||||||
/// implicit closure bindings. It is needed when the closure is
|
/// implicit closure bindings. It is needed when the closure is
|
||||||
|
@ -220,19 +230,7 @@ pub enum BorrowKind {
|
||||||
/// immutable, but not aliasable. This solves the problem. For
|
/// immutable, but not aliasable. This solves the problem. For
|
||||||
/// simplicity, we don't give users the way to express this
|
/// simplicity, we don't give users the way to express this
|
||||||
/// borrow, it's just used when translating closures.
|
/// borrow, it's just used when translating closures.
|
||||||
///
|
ClosureCapture,
|
||||||
// FIXME(#112072): This is wrong. Unique borrows are mutable borrows except
|
|
||||||
// that they do not require their pointee to be marked as a mutable.
|
|
||||||
// They should still be treated as mutable borrows in every other way,
|
|
||||||
// e.g. for variance or overlap checking.
|
|
||||||
Unique,
|
|
||||||
|
|
||||||
/// Data is mutable and not aliasable.
|
|
||||||
Mut {
|
|
||||||
/// `true` if this borrow arose from method-call auto-ref
|
|
||||||
/// (i.e., `adjustment::Adjust::Borrow`).
|
|
||||||
allow_two_phase_borrow: bool,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -269,11 +269,6 @@ impl BorrowKind {
|
||||||
BorrowKind::Mut { .. } => hir::Mutability::Mut,
|
BorrowKind::Mut { .. } => hir::Mutability::Mut,
|
||||||
BorrowKind::Shared => hir::Mutability::Not,
|
BorrowKind::Shared => hir::Mutability::Not,
|
||||||
|
|
||||||
// We have no type corresponding to a unique imm borrow, so
|
|
||||||
// use `&mut`. It gives all the capabilities of a `&uniq`
|
|
||||||
// and hence is a safe "over approximation".
|
|
||||||
BorrowKind::Unique => hir::Mutability::Mut,
|
|
||||||
|
|
||||||
// We have no type corresponding to a shallow borrow, so use
|
// We have no type corresponding to a shallow borrow, so use
|
||||||
// `&` as an approximation.
|
// `&` as an approximation.
|
||||||
BorrowKind::Shallow => hir::Mutability::Not,
|
BorrowKind::Shallow => hir::Mutability::Not,
|
||||||
|
|
|
@ -650,9 +650,6 @@ macro_rules! make_mir_visitor {
|
||||||
BorrowKind::Shallow => PlaceContext::NonMutatingUse(
|
BorrowKind::Shallow => PlaceContext::NonMutatingUse(
|
||||||
NonMutatingUseContext::ShallowBorrow
|
NonMutatingUseContext::ShallowBorrow
|
||||||
),
|
),
|
||||||
BorrowKind::Unique => PlaceContext::MutatingUse(
|
|
||||||
MutatingUseContext::Borrow
|
|
||||||
),
|
|
||||||
BorrowKind::Mut { .. } =>
|
BorrowKind::Mut { .. } =>
|
||||||
PlaceContext::MutatingUse(MutatingUseContext::Borrow),
|
PlaceContext::MutatingUse(MutatingUseContext::Borrow),
|
||||||
};
|
};
|
||||||
|
|
|
@ -442,7 +442,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
match upvar.kind {
|
match upvar.kind {
|
||||||
ExprKind::Borrow {
|
ExprKind::Borrow {
|
||||||
borrow_kind:
|
borrow_kind:
|
||||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||||
arg,
|
arg,
|
||||||
} => unpack!(
|
} => unpack!(
|
||||||
block = this.limit_capture_mutability(
|
block = this.limit_capture_mutability(
|
||||||
|
@ -795,8 +795,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let borrow_kind = match mutability {
|
let borrow_kind = match mutability {
|
||||||
Mutability::Not => BorrowKind::Unique,
|
Mutability::Not => BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
|
||||||
Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
|
Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||||
};
|
};
|
||||||
|
|
||||||
let arg_place = arg_place_builder.to_place(this);
|
let arg_place = arg_place_builder.to_place(this);
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::errors::*;
|
||||||
use rustc_middle::thir::visit::{self, Visitor};
|
use rustc_middle::thir::visit::{self, Visitor};
|
||||||
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::mir::BorrowKind;
|
use rustc_middle::mir::{BorrowKind, MutBorrowKind};
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
|
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
|
||||||
|
@ -254,7 +254,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
match borrow_kind {
|
match borrow_kind {
|
||||||
BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => {
|
BorrowKind::Shallow
|
||||||
|
| BorrowKind::Shared
|
||||||
|
| BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
|
||||||
if !ty.is_freeze(self.tcx, self.param_env) {
|
if !ty.is_freeze(self.tcx, self.param_env) {
|
||||||
self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField);
|
self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField);
|
||||||
}
|
}
|
||||||
|
@ -440,15 +442,19 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
||||||
visit::walk_expr(&mut visitor, expr);
|
visit::walk_expr(&mut visitor, expr);
|
||||||
if visitor.found {
|
if visitor.found {
|
||||||
match borrow_kind {
|
match borrow_kind {
|
||||||
BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique
|
BorrowKind::Shallow
|
||||||
|
| BorrowKind::Shared
|
||||||
|
| BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }
|
||||||
if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) =>
|
if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) =>
|
||||||
{
|
{
|
||||||
self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField)
|
self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField)
|
||||||
}
|
}
|
||||||
BorrowKind::Mut { .. } => {
|
BorrowKind::Mut {
|
||||||
self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField)
|
kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow,
|
||||||
}
|
} => self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField),
|
||||||
BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => {}
|
BorrowKind::Shallow
|
||||||
|
| BorrowKind::Shared
|
||||||
|
| BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1095,8 +1095,12 @@ impl<'tcx> Cx<'tcx> {
|
||||||
ty::UpvarCapture::ByRef(upvar_borrow) => {
|
ty::UpvarCapture::ByRef(upvar_borrow) => {
|
||||||
let borrow_kind = match upvar_borrow {
|
let borrow_kind = match upvar_borrow {
|
||||||
ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
|
ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
|
||||||
ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique,
|
ty::BorrowKind::UniqueImmBorrow => {
|
||||||
ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false },
|
BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture }
|
||||||
|
}
|
||||||
|
ty::BorrowKind::MutBorrow => {
|
||||||
|
BorrowKind::Mut { kind: mir::MutBorrowKind::Default }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Expr {
|
Expr {
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
|
@ -1132,9 +1136,9 @@ impl ToBorrowKind for AutoBorrowMutability {
|
||||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||||
match *self {
|
match *self {
|
||||||
AutoBorrowMutability::Mut { allow_two_phase_borrow } => BorrowKind::Mut {
|
AutoBorrowMutability::Mut { allow_two_phase_borrow } => BorrowKind::Mut {
|
||||||
allow_two_phase_borrow: match allow_two_phase_borrow {
|
kind: match allow_two_phase_borrow {
|
||||||
AllowTwoPhase::Yes => true,
|
AllowTwoPhase::Yes => mir::MutBorrowKind::TwoPhaseBorrow,
|
||||||
AllowTwoPhase::No => false,
|
AllowTwoPhase::No => mir::MutBorrowKind::Default,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
AutoBorrowMutability::Not => BorrowKind::Shared,
|
AutoBorrowMutability::Not => BorrowKind::Shared,
|
||||||
|
@ -1145,7 +1149,7 @@ impl ToBorrowKind for AutoBorrowMutability {
|
||||||
impl ToBorrowKind for hir::Mutability {
|
impl ToBorrowKind for hir::Mutability {
|
||||||
fn to_borrow_kind(&self) -> BorrowKind {
|
fn to_borrow_kind(&self) -> BorrowKind {
|
||||||
match *self {
|
match *self {
|
||||||
hir::Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
|
hir::Mutability::Mut => BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
|
||||||
hir::Mutability::Not => BorrowKind::Shared,
|
hir::Mutability::Not => BorrowKind::Shared,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,7 +287,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||||
ty::BindByValue(mutbl) => (mutbl, BindingMode::ByValue),
|
ty::BindByValue(mutbl) => (mutbl, BindingMode::ByValue),
|
||||||
ty::BindByReference(hir::Mutability::Mut) => (
|
ty::BindByReference(hir::Mutability::Mut) => (
|
||||||
Mutability::Not,
|
Mutability::Not,
|
||||||
BindingMode::ByRef(BorrowKind::Mut { allow_two_phase_borrow: false }),
|
BindingMode::ByRef(BorrowKind::Mut { kind: mir::MutBorrowKind::Default }),
|
||||||
),
|
),
|
||||||
ty::BindByReference(hir::Mutability::Not) => {
|
ty::BindByReference(hir::Mutability::Not) => {
|
||||||
(Mutability::Not, BindingMode::ByRef(BorrowKind::Shared))
|
(Mutability::Not, BindingMode::ByRef(BorrowKind::Shared))
|
||||||
|
|
|
@ -638,7 +638,7 @@ where
|
||||||
Place::from(ref_place),
|
Place::from(ref_place),
|
||||||
Rvalue::Ref(
|
Rvalue::Ref(
|
||||||
tcx.lifetimes.re_erased,
|
tcx.lifetimes.re_erased,
|
||||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||||
self.place,
|
self.place,
|
||||||
),
|
),
|
||||||
)],
|
)],
|
||||||
|
|
|
@ -522,7 +522,7 @@ impl<'tcx> Inliner<'tcx> {
|
||||||
trace!("creating temp for return destination");
|
trace!("creating temp for return destination");
|
||||||
let dest = Rvalue::Ref(
|
let dest = Rvalue::Ref(
|
||||||
self.tcx.lifetimes.re_erased,
|
self.tcx.lifetimes.re_erased,
|
||||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||||
destination,
|
destination,
|
||||||
);
|
);
|
||||||
let dest_ty = dest.ty(caller_body, self.tcx);
|
let dest_ty = dest.ty(caller_body, self.tcx);
|
||||||
|
|
|
@ -188,7 +188,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
||||||
// has been put into the body.
|
// has been put into the body.
|
||||||
let reborrow = Rvalue::Ref(
|
let reborrow = Rvalue::Ref(
|
||||||
tcx.lifetimes.re_erased,
|
tcx.lifetimes.re_erased,
|
||||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||||
tcx.mk_place_deref(dropee_ptr),
|
tcx.mk_place_deref(dropee_ptr),
|
||||||
);
|
);
|
||||||
let ref_ty = reborrow.ty(body.local_decls(), tcx);
|
let ref_ty = reborrow.ty(body.local_decls(), tcx);
|
||||||
|
@ -712,7 +712,7 @@ fn build_call_shim<'tcx>(
|
||||||
)
|
)
|
||||||
.immutable(),
|
.immutable(),
|
||||||
);
|
);
|
||||||
let borrow_kind = BorrowKind::Mut { allow_two_phase_borrow: false };
|
let borrow_kind = BorrowKind::Mut { kind: MutBorrowKind::Default };
|
||||||
statements.push(Statement {
|
statements.push(Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Assign(Box::new((
|
kind: StatementKind::Assign(Box::new((
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue