add notes for immutable inputs
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
#![allow(needless_lifetimes)]
|
#![allow(needless_lifetimes)]
|
||||||
|
|
||||||
extern crate syntax;
|
extern crate syntax;
|
||||||
|
extern crate syntax_pos;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rustc;
|
extern crate rustc;
|
||||||
extern crate rustc_data_structures;
|
extern crate rustc_data_structures;
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ use rustc::hir::map::NodeItem;
|
|||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use syntax::ast::NodeId;
|
use syntax::ast::NodeId;
|
||||||
use utils::{match_path, match_type, paths, span_lint};
|
use syntax::codemap::Span;
|
||||||
|
use syntax_pos::MultiSpan;
|
||||||
|
use utils::{match_path, match_type, paths, span_lint, span_lint_and_then};
|
||||||
|
|
||||||
/// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless
|
/// **What it does:** This lint checks for function arguments of type `&String` or `&Vec` unless
|
||||||
/// the references are mutable.
|
/// the references are mutable.
|
||||||
@@ -132,29 +134,31 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let FunctionRetTy::Return(ref ty) = decl.output {
|
if let FunctionRetTy::Return(ref ty) = decl.output {
|
||||||
if let Some((out, MutMutable)) = get_rptr_lm(ty) {
|
if let Some((out, MutMutable, _)) = get_rptr_lm(ty) {
|
||||||
if let Some(MutImmutable) =
|
let mut immutables = vec![];
|
||||||
decl.inputs
|
for (_, ref mutbl, ref argspan) in decl.inputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|ty| get_rptr_lm(ty))
|
.filter_map(|ty| get_rptr_lm(ty))
|
||||||
.filter(|&(lt, _)| lt.name == out.name)
|
.filter(|&(lt, _, _)| lt.name == out.name) {
|
||||||
.fold(None, |x, (_, m)| match (x, m) {
|
if *mutbl == MutMutable { return; }
|
||||||
(Some(MutMutable), _) |
|
immutables.push(*argspan);
|
||||||
(_, MutMutable) => Some(MutMutable),
|
|
||||||
(_, m) => Some(m),
|
|
||||||
}) {
|
|
||||||
span_lint(cx,
|
|
||||||
MUT_FROM_REF,
|
|
||||||
ty.span,
|
|
||||||
"this function takes an immutable ref to return a mutable one");
|
|
||||||
}
|
}
|
||||||
|
if immutables.is_empty() { return; }
|
||||||
|
span_lint_and_then(cx,
|
||||||
|
MUT_FROM_REF,
|
||||||
|
ty.span,
|
||||||
|
"mutable borrow from immutable input(s)",
|
||||||
|
|db| {
|
||||||
|
let ms = MultiSpan::from_spans(immutables);
|
||||||
|
db.span_note(ms, "immutable borrow here");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_rptr_lm(ty: &Ty) -> Option<(&Lifetime, Mutability)> {
|
fn get_rptr_lm(ty: &Ty) -> Option<(&Lifetime, Mutability, Span)> {
|
||||||
if let Ty_::TyRptr(ref lt, ref m) = ty.node {
|
if let Ty_::TyRptr(ref lt, ref m) = ty.node {
|
||||||
Some((lt, m.mutbl))
|
Some((lt, m.mutbl, ty.span))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 {
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fail_double<'a>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
// this is OK, because the result borrows y
|
// this is OK, because the result borrows y
|
||||||
fn works<'a>(x: &u32, y: &'a mut u32) -> &'a mut u32 {
|
fn works<'a>(x: &u32, y: &'a mut u32) -> &'a mut u32 {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
|||||||
@@ -1,32 +1,8 @@
|
|||||||
error: this function takes an immutable ref to return a mutable one
|
error[E0261]: use of undeclared lifetime name `'b`
|
||||||
--> $DIR/mut_from_ref.rs:9:39
|
--> $DIR/mut_from_ref.rs:32:48
|
||||||
|
|
|
||||||
9 | fn this_wont_hurt_a_bit(&self) -> &mut Foo {
|
|
||||||
| ^^^^^^^^
|
|
||||||
|
|
|
||||||
note: lint level defined here
|
|
||||||
--> $DIR/mut_from_ref.rs:4:9
|
|
||||||
|
|
|
||||||
4 | #![deny(mut_from_ref)]
|
|
||||||
| ^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: this function takes an immutable ref to return a mutable one
|
|
||||||
--> $DIR/mut_from_ref.rs:15:25
|
|
||||||
|
|
|
|
||||||
15 | fn ouch(x: &Foo) -> &mut Foo;
|
32 | fn fail_double<'a>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 {
|
||||||
| ^^^^^^^^
|
| ^^ undeclared lifetime
|
||||||
|
|
||||||
error: this function takes an immutable ref to return a mutable one
|
error: aborting due to previous error
|
||||||
--> $DIR/mut_from_ref.rs:24:21
|
|
||||||
|
|
|
||||||
24 | fn fail(x: &u32) -> &mut u16 {
|
|
||||||
| ^^^^^^^^
|
|
||||||
|
|
||||||
error: this function takes an immutable ref to return a mutable one
|
|
||||||
--> $DIR/mut_from_ref.rs:28:50
|
|
||||||
|
|
|
||||||
28 | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 {
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user