fix handling of immutable variables
This commit is contained in:
parent
210f76816f
commit
82f3fc5dbc
1 changed files with 28 additions and 16 deletions
|
@ -655,8 +655,9 @@ enum WriteKind {
|
||||||
/// - Take flow state into consideration in `is_assignable()` for local variables
|
/// - Take flow state into consideration in `is_assignable()` for local variables
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
enum LocalMutationIsAllowed {
|
enum LocalMutationIsAllowed {
|
||||||
|
Move,
|
||||||
Yes,
|
Yes,
|
||||||
No,
|
No
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -946,7 +947,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
context,
|
context,
|
||||||
(place, span),
|
(place, span),
|
||||||
(Deep, Write(WriteKind::Move)),
|
(Deep, Write(WriteKind::Move)),
|
||||||
LocalMutationIsAllowed::Yes,
|
LocalMutationIsAllowed::Move,
|
||||||
flow_state,
|
flow_state,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1368,7 +1369,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let local = &self.mir.local_decls[local];
|
let local = &self.mir.local_decls[local];
|
||||||
match local.mutability {
|
match local.mutability {
|
||||||
Mutability::Not => match is_local_mutation_allowed {
|
Mutability::Not => match is_local_mutation_allowed {
|
||||||
LocalMutationIsAllowed::Yes => Ok(()),
|
LocalMutationIsAllowed::Yes |
|
||||||
|
LocalMutationIsAllowed::Move => Ok(()),
|
||||||
LocalMutationIsAllowed::No => Err(place),
|
LocalMutationIsAllowed::No => Err(place),
|
||||||
},
|
},
|
||||||
Mutability::Mut => Ok(()),
|
Mutability::Mut => Ok(()),
|
||||||
|
@ -1393,10 +1395,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// Mutably borrowed data is mutable, but only if we have a
|
// Mutably borrowed data is mutable, but only if we have a
|
||||||
// unique path to the `&mut`
|
// unique path to the `&mut`
|
||||||
hir::MutMutable => {
|
hir::MutMutable => {
|
||||||
if self.is_upvar_field_projection(&proj.base).is_some() {
|
match self.is_upvar_field_projection(&proj.base) {
|
||||||
self.is_mutable(&proj.base, is_local_mutation_allowed)
|
Some(field) if {
|
||||||
} else {
|
self.mir.upvar_decls[field.index()].by_ref
|
||||||
self.is_unique(&proj.base)
|
} => {
|
||||||
|
self.is_mutable(&proj.base,
|
||||||
|
is_local_mutation_allowed)
|
||||||
|
}
|
||||||
|
_ => self.is_unique(&proj.base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1412,7 +1418,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
// `Box<T>` owns its content, so mutable if its location is mutable
|
// `Box<T>` owns its content, so mutable if its location is mutable
|
||||||
_ if base_ty.is_box() => {
|
_ if base_ty.is_box() => {
|
||||||
self.is_mutable(&proj.base, LocalMutationIsAllowed::No)
|
self.is_mutable(&proj.base, is_local_mutation_allowed)
|
||||||
}
|
}
|
||||||
// Deref should only be for reference, pointers or boxes
|
// Deref should only be for reference, pointers or boxes
|
||||||
_ => bug!("Deref of unexpected type: {:?}", base_ty),
|
_ => bug!("Deref of unexpected type: {:?}", base_ty),
|
||||||
|
@ -1429,14 +1435,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
if let Some(field) = field_projection {
|
if let Some(field) = field_projection {
|
||||||
let decl = &self.mir.upvar_decls[field.index()];
|
let decl = &self.mir.upvar_decls[field.index()];
|
||||||
|
debug!("decl.mutability={:?} local_mutation_is_allowed={:?} place={:?}",
|
||||||
return match decl.mutability {
|
decl, is_local_mutation_allowed, place);
|
||||||
Mutability::Mut => self.is_unique(&proj.base),
|
return match (decl.mutability, is_local_mutation_allowed) {
|
||||||
Mutability::Not => Err(place),
|
(Mutability::Not, LocalMutationIsAllowed::No) |
|
||||||
|
(Mutability::Not, LocalMutationIsAllowed::Yes) => Err(place),
|
||||||
|
(Mutability::Not, LocalMutationIsAllowed::Move) |
|
||||||
|
(Mutability::Mut, _) => self.is_unique(&proj.base),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
self.is_mutable(&proj.base, LocalMutationIsAllowed::No)
|
self.is_mutable(&proj.base, is_local_mutation_allowed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1450,9 +1459,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// Local variables are unique
|
// Local variables are unique
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Place::Static(..) => {
|
Place::Static(ref static_) => {
|
||||||
// Static variables are not
|
if !self.tcx.is_static_mut(static_.def_id) {
|
||||||
Err(place)
|
Err(place)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Place::Projection(ref proj) => {
|
Place::Projection(ref proj) => {
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
|
|
Loading…
Reference in a new issue