提交 d21ec9b4 编写于 作者: B bors

Auto merge of #43582 - ivanbakel:unused_mut_ref, r=arielb1

Fixed mutable vars being marked used when they weren't

#### NB : bootstrapping is slow on my machine, even with `keep-stage` - fixes for occurances in the current codebase are <s>in the pipeline</s> done. This PR is being put up for review of the fix of the issue.

Fixes #43526, Fixes #30280, Fixes #25049

### Issue
Whenever the compiler detected a mutable deref being used mutably, it marked an associated value as being used mutably as well. In the case of derefencing local variables which were mutable references, this incorrectly marked the reference itself being used mutably, instead of its contents - with the consequence of making the following code emit no warnings
```
fn do_thing<T>(mut arg : &mut T) {
    ... // don't touch arg - just deref it to access the T
}
```

### Fix
Make dereferences not be counted as a mutable use, but only when they're on borrows on local variables.
#### Why not on things other than local variables?
  * Whenever you capture a variable in a closure, it gets turned into a hidden reference - when you use it in the closure, it gets dereferenced. If the closure uses the variable mutably, that is actually a mutable use of the thing being dereffed to, so it has to be counted.
  * If you deref a mutable `Box` to access the contents mutably, you are using the `Box` mutably - so it has to be counted.
......@@ -1037,7 +1037,7 @@ impl<'a, K: 'a, V: 'a, NodeType>
Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> {
pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
let (mut keys, mut vals) = self.node.into_slices_mut();
let (keys, vals) = self.node.into_slices_mut();
unsafe {
(keys.get_unchecked_mut(self.idx), vals.get_unchecked_mut(self.idx))
}
......@@ -1047,7 +1047,7 @@ pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
impl<'a, K, V, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> {
pub fn kv_mut(&mut self) -> (&mut K, &mut V) {
unsafe {
let (mut keys, mut vals) = self.node.reborrow_mut().into_slices_mut();
let (keys, vals) = self.node.reborrow_mut().into_slices_mut();
(keys.get_unchecked_mut(self.idx), vals.get_unchecked_mut(self.idx))
}
}
......
......@@ -1751,7 +1751,7 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;
fn into_iter(mut self) -> slice::IterMut<'a, T> {
fn into_iter(self) -> slice::IterMut<'a, T> {
self.iter_mut()
}
}
......
......@@ -2394,7 +2394,7 @@ impl<'a, T> IntoIterator for &'a mut VecDeque<T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
fn into_iter(mut self) -> IterMut<'a, T> {
fn into_iter(self) -> IterMut<'a, T> {
self.iter_mut()
}
}
......@@ -2558,7 +2558,7 @@ fn pointer(&mut self) -> *mut T {
impl<'a, T> InPlace<T> for PlaceBack<'a, T> {
type Owner = &'a mut T;
unsafe fn finalize(mut self) -> &'a mut T {
unsafe fn finalize(self) -> &'a mut T {
let head = self.vec_deque.head;
self.vec_deque.head = self.vec_deque.wrap_add(head, 1);
&mut *(self.vec_deque.ptr().offset(head as isize))
......@@ -2605,7 +2605,7 @@ fn pointer(&mut self) -> *mut T {
impl<'a, T> InPlace<T> for PlaceFront<'a, T> {
type Owner = &'a mut T;
unsafe fn finalize(mut self) -> &'a mut T {
unsafe fn finalize(self) -> &'a mut T {
self.vec_deque.tail = self.vec_deque.wrap_sub(self.vec_deque.tail, 1);
&mut *(self.vec_deque.ptr().offset(self.vec_deque.tail as isize))
}
......
......@@ -187,7 +187,7 @@ impl<'a,A,F:?Sized> FnOnce<A> for &'a mut F
where F : FnMut<A>
{
type Output = F::Output;
extern "rust-call" fn call_once(mut self, args: A) -> F::Output {
extern "rust-call" fn call_once(self, args: A) -> F::Output {
(*self).call_mut(args)
}
}
......
......@@ -872,7 +872,7 @@ impl<'a, T> IntoIterator for &'a mut Option<T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
fn into_iter(mut self) -> IterMut<'a, T> {
fn into_iter(self) -> IterMut<'a, T> {
self.iter_mut()
}
}
......
......@@ -909,7 +909,7 @@ impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
fn into_iter(mut self) -> IterMut<'a, T> {
fn into_iter(self) -> IterMut<'a, T> {
self.iter_mut()
}
}
......
......@@ -105,27 +105,27 @@ fn test_chunks_last() {
#[test]
fn test_chunks_mut_count() {
let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
let c = v.chunks_mut(3);
assert_eq!(c.count(), 2);
let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
let c2 = v2.chunks_mut(2);
assert_eq!(c2.count(), 3);
let mut v3: &mut [i32] = &mut [];
let v3: &mut [i32] = &mut [];
let c3 = v3.chunks_mut(2);
assert_eq!(c3.count(), 0);
}
#[test]
fn test_chunks_mut_nth() {
let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
let mut c = v.chunks_mut(2);
assert_eq!(c.nth(1).unwrap()[1], 3);
assert_eq!(c.next().unwrap()[0], 4);
let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
let mut c2 = v2.chunks_mut(3);
assert_eq!(c2.nth(1).unwrap()[1], 4);
assert_eq!(c2.next(), None);
......@@ -194,7 +194,7 @@ fn get_range() {
#[test]
fn get_mut_range() {
let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
assert_eq!(v.get_mut(..), Some(&mut [0, 1, 2, 3, 4, 5][..]));
assert_eq!(v.get_mut(..2), Some(&mut [0, 1][..]));
assert_eq!(v.get_mut(2..), Some(&mut [2, 3, 4, 5][..]));
......
......@@ -415,8 +415,8 @@ fn note_error_origin(&self,
/// -------- this type is the same as a type argument in the other type, not highlighted
/// ```
fn highlight_outer(&self,
mut value: &mut DiagnosticStyledString,
mut other_value: &mut DiagnosticStyledString,
value: &mut DiagnosticStyledString,
other_value: &mut DiagnosticStyledString,
name: String,
sub: &ty::subst::Substs<'tcx>,
pos: usize,
......
......@@ -560,7 +560,7 @@ pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
{
debug!("fully_normalize(value={:?})", value);
let mut selcx = &mut SelectionContext::new(infcx);
let selcx = &mut SelectionContext::new(infcx);
// FIXME (@jroesch) ISSUE 26721
// I'm not sure if this is a bug or not, needs further investigation.
// It appears that by reusing the fulfillment_cx here we incur more
......
......@@ -494,7 +494,7 @@ pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
never_obligation.predicate = never_obligation.predicate.map_bound(|mut trait_pred| {
// Swap out () with ! so we can check if the trait is impld for !
{
let mut trait_ref = &mut trait_pred.trait_ref;
let trait_ref = &mut trait_pred.trait_ref;
let unit_substs = trait_ref.substs;
let mut never_substs = Vec::with_capacity(unit_substs.len());
never_substs.push(From::from(tcx.types.never));
......
......@@ -171,7 +171,7 @@ fn uninhabited_from_inner(
match self.sty {
TyAdt(def, substs) => {
{
let mut substs_set = visited.entry(def.did).or_insert(FxHashSet::default());
let substs_set = visited.entry(def.did).or_insert(FxHashSet::default());
if !substs_set.insert(substs) {
// We are already calculating the inhabitedness of this type.
// The type must contain a reference to itself. Break the
......@@ -193,7 +193,7 @@ fn uninhabited_from_inner(
}
}
let ret = def.uninhabited_from(visited, tcx, substs);
let mut substs_set = visited.get_mut(&def.did).unwrap();
let substs_set = visited.get_mut(&def.did).unwrap();
substs_set.remove(substs);
ret
},
......
......@@ -188,7 +188,7 @@ fn attrs(&self) -> Vec<Attribute> {
fn arg_ty(&self,
ty: &AllocatorTy,
args: &mut Vec<Arg>,
mut ident: &mut FnMut() -> Ident) -> P<Expr> {
ident: &mut FnMut() -> Ident) -> P<Expr> {
match *ty {
AllocatorTy::Layout => {
let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
......@@ -263,7 +263,7 @@ fn arg_ty(&self,
fn ret_ty(&self,
ty: &AllocatorTy,
args: &mut Vec<Arg>,
mut ident: &mut FnMut() -> Ident,
ident: &mut FnMut() -> Ident,
expr: P<Expr>) -> (P<Ty>, P<Expr>)
{
match *ty {
......
......@@ -436,20 +436,40 @@ pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) {
//! For mutable loans of content whose mutability derives
//! from a local variable, mark the mutability decl as necessary.
match loan_path.kind {
LpVar(local_id) |
LpUpvar(ty::UpvarId{ var_id: local_id, closure_expr_id: _ }) => {
self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
}
LpDowncast(ref base, _) |
LpExtend(ref base, mc::McInherited, _) |
LpExtend(ref base, mc::McDeclared, _) => {
self.mark_loan_path_as_mutated(&base);
}
LpExtend(_, mc::McImmutable, _) => {
// Nothing to do.
let mut wrapped_path = Some(loan_path);
let mut through_borrow = false;
while let Some(current_path) = wrapped_path {
wrapped_path = match current_path.kind {
LpVar(local_id) => {
if !through_borrow {
self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
}
None
}
LpUpvar(ty::UpvarId{ var_id: local_id, closure_expr_id: _ }) => {
self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
None
}
LpExtend(ref base, mc::McInherited, LpDeref(pointer_kind)) |
LpExtend(ref base, mc::McDeclared, LpDeref(pointer_kind)) => {
if pointer_kind != mc::Unique {
through_borrow = true;
}
Some(base)
}
LpDowncast(ref base, _) |
LpExtend(ref base, mc::McInherited, _) |
LpExtend(ref base, mc::McDeclared, _) => {
Some(base)
}
LpExtend(_, mc::McImmutable, _) => {
// Nothing to do.
None
}
}
}
}
pub fn compute_gen_scope(&self,
......
......@@ -98,7 +98,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
let body_id = tcx.hir.body_owned_by(owner_id);
let tables = tcx.typeck_tables_of(owner_def_id);
let region_maps = tcx.region_maps(owner_def_id);
let mut bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id };
let bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id };
let body = bccx.tcx.hir.body(body_id);
......
......@@ -260,7 +260,7 @@ fn drop(&mut self) {
let start = source_array_vec.len();
let tail = self.tail_start;
{
let mut arr = &mut source_array_vec.values as &mut [ManuallyDrop<_>];
let arr = &mut source_array_vec.values as &mut [ManuallyDrop<_>];
let src = arr.as_ptr().offset(tail as isize);
let dst = arr.as_mut_ptr().offset(start as isize);
ptr::copy(src, dst, self.tail_len);
......
......@@ -166,7 +166,7 @@ fn range(&self, row: usize) -> (usize, usize) {
pub fn add(&mut self, source: usize, target: usize) -> bool {
let (start, _) = self.range(source);
let (word, mask) = word_mask(target);
let mut vector = &mut self.vector[..];
let vector = &mut self.vector[..];
let v1 = vector[start + word];
let v2 = v1 | mask;
vector[start + word] = v2;
......
......@@ -259,7 +259,7 @@ impl<'a, I: Idx, T> IntoIterator for &'a mut IndexVec<I, T> {
type IntoIter = slice::IterMut<'a, T>;
#[inline]
fn into_iter(mut self) -> slice::IterMut<'a, T> {
fn into_iter(self) -> slice::IterMut<'a, T> {
self.raw.iter_mut()
}
}
......
......@@ -422,7 +422,7 @@ fn show_content_with_pager(content: &String) {
match Command::new(pager_name).stdin(Stdio::piped()).spawn() {
Ok(mut pager) => {
if let Some(mut pipe) = pager.stdin.as_mut() {
if let Some(pipe) = pager.stdin.as_mut() {
if pipe.write_all(content.as_bytes()).is_err() {
fallback_to_println = true;
}
......
......@@ -479,7 +479,7 @@ fn visible_parent_map<'a>(&'a self, sess: &Session) -> ::std::cell::Ref<'a, DefI
_ => {},
}
let mut bfs_queue = &mut VecDeque::new();
let bfs_queue = &mut VecDeque::new();
let mut add_child = |bfs_queue: &mut VecDeque<_>, child: def::Export, parent: DefId| {
let child = child.def.def_id();
......
......@@ -206,7 +206,7 @@ pub fn schedule_drop_for_binding(&mut self, var: NodeId, span: Span) {
self.schedule_drop(span, extent, &Lvalue::Local(local_id), var_ty);
}
pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, mut f: &mut F)
pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, f: &mut F)
where F: FnMut(&mut Self, Mutability, Name, NodeId, Span, Ty<'tcx>)
{
match *pattern.kind {
......
......@@ -721,7 +721,7 @@ fn normalize<T>(&mut self, value: &T) -> T
value,
obligations);
let mut fulfill_cx = &mut self.fulfillment_cx;
let fulfill_cx = &mut self.fulfillment_cx;
for obligation in obligations {
fulfill_cx.register_predicate_obligation(self.infcx, obligation);
}
......
......@@ -781,7 +781,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
hir::ItemTrait(.., ref trait_item_refs) => {
self.check_item(item.id).generics().predicates();
for trait_item_ref in trait_item_refs {
let mut check = self.check_item(trait_item_ref.id.node_id);
let check = self.check_item(trait_item_ref.id.node_id);
check.generics().predicates();
if trait_item_ref.kind != hir::AssociatedItemKind::Type ||
trait_item_ref.defaultness.has_value() {
......@@ -814,7 +814,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
}
hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => {
{
let mut check = self.check_item(item.id);
let check = self.check_item(item.id);
check.ty().generics().predicates();
if trait_ref.is_some() {
check.impl_trait_ref();
......
......@@ -379,7 +379,7 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, ident: Ident, ns: Name
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
// during which the resolution might end up getting re-defined via a glob cycle.
let (binding, t) = {
let mut resolution = &mut *self.resolution(module, ident, ns).borrow_mut();
let resolution = &mut *self.resolution(module, ident, ns).borrow_mut();
let old_binding = resolution.binding();
let t = f(self, resolution);
......
......@@ -1464,7 +1464,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
let mut output = i.to_string(scx.tcx());
output.push_str(" @@");
let mut empty = Vec::new();
let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone());
cgus.dedup();
for &(ref cgu_name, (linkage, _)) in cgus.iter() {
......
......@@ -335,7 +335,7 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
CodegenUnit::empty(codegen_unit_name.clone())
};
let mut codegen_unit = codegen_units.entry(codegen_unit_name.clone())
let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
.or_insert_with(make_codegen_unit);
let (linkage, visibility) = match trans_item.explicit_linkage(tcx) {
......
......@@ -70,7 +70,7 @@ pub fn start(&self,
{
let mut table = self.data.lock().unwrap();
let mut data = table.entry(timeline).or_insert(PerThread {
let data = table.entry(timeline).or_insert(PerThread {
timings: Vec::new(),
open_work_package: None,
});
......@@ -90,7 +90,7 @@ fn end(&self, timeline: TimelineId) {
let end = Instant::now();
let mut table = self.data.lock().unwrap();
let mut data = table.get_mut(&timeline).unwrap();
let data = table.get_mut(&timeline).unwrap();
if let Some((start, work_package_kind)) = data.open_work_package {
data.timings.push(Timing {
......
......@@ -1204,7 +1204,7 @@ fn coerce_inner<'a>(&mut self,
}
}
if let Some(mut augment_error) = augment_error {
if let Some(augment_error) = augment_error {
augment_error(&mut db);
}
......
......@@ -556,7 +556,7 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
// We can't use normalize_associated_types_in as it will pollute the
// fcx's fulfillment context after this probe is over.
let cause = traits::ObligationCause::misc(self.span, self.body_id);
let mut selcx = &mut traits::SelectionContext::new(self.fcx);
let selcx = &mut traits::SelectionContext::new(self.fcx);
let traits::Normalized { value: xform_self_ty, obligations } =
traits::normalize(selcx, self.param_env, cause, &xform_self_ty);
debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
......@@ -765,7 +765,7 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
// as it will pollute the fcx's fulfillment context after this probe
// is over.
let cause = traits::ObligationCause::misc(self.span, self.body_id);
let mut selcx = &mut traits::SelectionContext::new(self.fcx);
let selcx = &mut traits::SelectionContext::new(self.fcx);
let traits::Normalized { value: xform_self_ty, obligations } =
traits::normalize(selcx, self.param_env, cause, &xform_self_ty);
......
......@@ -4183,8 +4183,8 @@ fn check_block_with_expected(&self,
let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
let mut ctxt = enclosing_breakables.find_breakable(blk.id);
let mut coerce = ctxt.coerce.as_mut().unwrap();
let ctxt = enclosing_breakables.find_breakable(blk.id);
let coerce = ctxt.coerce.as_mut().unwrap();
if let Some(tail_expr_ty) = tail_expr_ty {
let tail_expr = tail_expr.unwrap();
let cause = self.cause(tail_expr.span,
......
......@@ -300,7 +300,7 @@ fn check_str_addition(&self,
lhs_expr: &'gcx hir::Expr,
lhs_ty: Ty<'tcx>,
rhs_ty: Ty<'tcx>,
mut err: &mut errors::DiagnosticBuilder) -> bool {
err: &mut errors::DiagnosticBuilder) -> bool {
// If this function returns true it means a note was printed, so we don't need
// to print the normal "implementation of `std::ops::Add` might be missing" note
let mut is_string_addition = false;
......
......@@ -1618,7 +1618,7 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
fn into_iter(mut self) -> IterMut<'a, K, V> {
fn into_iter(self) -> IterMut<'a, K, V> {
self.iter_mut()
}
}
......
......@@ -563,7 +563,7 @@ impl<'t, K, V> FullBucket<K, V, &'t mut RawTable<K, V>> {
///
/// This works similarly to `put`, building an `EmptyBucket` out of the
/// taken bucket.
pub fn take(mut self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
pub fn take(self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
self.table.size -= 1;
unsafe {
......
......@@ -514,7 +514,7 @@ fn description(&self) -> &str { "A-desc" }
#[test]
fn downcasting() {
let mut a = A;
let mut a = &mut a as &mut (Error + 'static);
let a = &mut a as &mut (Error + 'static);
assert_eq!(a.downcast_ref::<A>(), Some(&A));
assert_eq!(a.downcast_ref::<B>(), None);
assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
......
......@@ -456,7 +456,7 @@ fn read_to_end() {
#[test]
fn test_slice_reader() {
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
let mut reader = &mut &in_buf[..];
let reader = &mut &in_buf[..];
let mut buf = [];
assert_eq!(reader.read(&mut buf).unwrap(), 0);
let mut buf = [0];
......
......@@ -267,7 +267,7 @@ pub fn call_once_force<F>(&'static self, f: F) where F: FnOnce(&OnceState) {
#[cold]
fn call_inner(&'static self,
ignore_poisoning: bool,
mut init: &mut FnMut(bool)) {
init: &mut FnMut(bool)) {
let mut state = self.state.load(Ordering::SeqCst);
'outer: loop {
......
......@@ -12,13 +12,13 @@
use mem;
fn next_u32(mut fill_buf: &mut FnMut(&mut [u8])) -> u32 {
fn next_u32(fill_buf: &mut FnMut(&mut [u8])) -> u32 {
let mut buf: [u8; 4] = [0; 4];
fill_buf(&mut buf);
unsafe { mem::transmute::<[u8; 4], u32>(buf) }
}
fn next_u64(mut fill_buf: &mut FnMut(&mut [u8])) -> u64 {
fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 {
let mut buf: [u8; 8] = [0; 8];
fill_buf(&mut buf);
unsafe { mem::transmute::<[u8; 8], u64>(buf) }
......
......@@ -768,8 +768,8 @@ fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> {
unsafe {
let mut data = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
let mut db = data.as_mut_ptr()
as *mut c::REPARSE_MOUNTPOINT_DATA_BUFFER;
let db = data.as_mut_ptr()
as *mut c::REPARSE_MOUNTPOINT_DATA_BUFFER;
let buf = &mut (*db).ReparseTarget as *mut _;
let mut i = 0;
// FIXME: this conversion is very hacky
......
......@@ -211,7 +211,7 @@ pub enum NamedMatch {
fn nameize<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, ms: &[TokenTree], mut res: I)
-> NamedParseResult {
fn n_rec<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, m: &TokenTree, mut res: &mut I,
fn n_rec<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, m: &TokenTree, res: &mut I,
ret_val: &mut HashMap<Ident, Rc<NamedMatch>>)
-> Result<(), (syntax_pos::Span, String)> {
match *m {
......@@ -445,7 +445,7 @@ pub fn parse(sess: &ParseSess,
/* error messages here could be improved with links to orig. rules */
if token_name_eq(&parser.token, &token::Eof) {
if eof_items.len() == 1 {
let matches = eof_items[0].matches.iter_mut().map(|mut dv| {
let matches = eof_items[0].matches.iter_mut().map(|dv| {
Rc::make_mut(dv).pop().unwrap()
});
return nameize(sess, ms, matches);
......
......@@ -86,7 +86,7 @@ fn expand<'cx>(&self,
fn trace_macros_note(cx: &mut ExtCtxt, sp: Span, message: String) {
let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp);
let mut values: &mut Vec<String> = cx.expansions.entry(sp).or_insert_with(Vec::new);
let values: &mut Vec<String> = cx.expansions.entry(sp).or_insert_with(Vec::new);
values.push(message);
}
......
......@@ -529,7 +529,7 @@ fn static_array(ecx: &mut ExtCtxt,
/// Actually builds the expression which the format_args! block will be
/// expanded to
fn into_expr(mut self) -> P<ast::Expr> {
fn into_expr(self) -> P<ast::Expr> {
let mut locals = Vec::new();
let mut counts = Vec::new();
let mut pats = Vec::new();
......
......@@ -47,6 +47,26 @@ fn main() {
let x = |mut y: isize| 10; //~ ERROR: variable does not need to be mutable
fn what(mut foo: isize) {} //~ ERROR: variable does not need to be mutable
let mut a = &mut 5; //~ ERROR: variable does not need to be mutable
*a = 4;
let mut a = 5;
let mut b = (&mut a,);
*b.0 = 4; //~^ ERROR: variable does not need to be mutable
let mut x = &mut 1; //~ ERROR: variable does not need to be mutable
let mut f = || {
*x += 1;
};
f();
fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
&mut arg[..] //~^ ERROR: variable does not need to be mutable
}
let mut v : &mut Vec<()> = &mut vec![]; //~ ERROR: variable does not need to be mutable
v.push(());
// positive cases
let mut a = 2;
a = 3;
......
Subproject commit 305bc25d5e105e84ffe261655b46cf74570f6e5b
Subproject commit 7704f7b1fd52607104cc7fdc435d636c9de1fe90
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册