refactor transmute lints into a single match

This commit is contained in:
Oliver Schneider 2016-06-27 13:46:21 +02:00
parent 60cc87baba
commit 083c57867a
No known key found for this signature in database
GPG key ID: 56D6EEA0FC67AC46

View file

@ -1,6 +1,5 @@
use rustc::lint::*;
use rustc::ty::TypeVariants::{TyRawPtr, TyRef};
use rustc::ty;
use rustc::hir::*;
use utils::{match_def_path, paths, snippet_opt, span_lint, span_lint_and_then};
@ -66,66 +65,59 @@ impl LateLintPass for Transmute {
let from_ty = cx.tcx.expr_ty(&args[0]);
let to_ty = cx.tcx.expr_ty(e);
if from_ty == to_ty {
span_lint(cx,
USELESS_TRANSMUTE,
e.span,
&format!("transmute from a type (`{}`) to itself", from_ty));
} else if is_ptr_to(to_ty, from_ty) {
span_lint(cx,
CROSSPOINTER_TRANSMUTE,
e.span,
&format!("transmute from a type (`{}`) to a pointer to that type (`{}`)",
from_ty,
to_ty));
} else if is_ptr_to(from_ty, to_ty) {
span_lint(cx,
CROSSPOINTER_TRANSMUTE,
e.span,
&format!("transmute from a type (`{}`) to the type that it points to (`{}`)",
from_ty,
to_ty));
} else {
check_ptr_to_ref(cx, from_ty, to_ty, e, &args[0]);
}
match (&from_ty.sty, &to_ty.sty) {
_ if from_ty == to_ty => span_lint(
cx,
USELESS_TRANSMUTE,
e.span,
&format!("transmute from a type (`{}`) to itself", from_ty),
),
(&TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint(
cx,
CROSSPOINTER_TRANSMUTE,
e.span,
&format!("transmute from a type (`{}`) to the type that it points to (`{}`)",
from_ty,
to_ty),
),
(_, &TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint(
cx,
CROSSPOINTER_TRANSMUTE,
e.span,
&format!("transmute from a type (`{}`) to a pointer to that type (`{}`)",
from_ty,
to_ty),
),
(&TyRawPtr(from_pty), &TyRef(_, to_rty)) => span_lint_and_then(
cx,
TRANSMUTE_PTR_TO_REF,
e.span,
&format!("transmute from a pointer type (`{}`) to a reference type (`{}`)",
from_ty,
to_ty),
|db| {
if let Some(arg) = snippet_opt(cx, args[0].span) {
let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable {
("&mut *", "*mut")
} else {
("&*", "*const")
};
let sugg = if from_pty.ty == to_rty.ty {
format!("{}{}", deref, arg)
} else {
format!("{}({} as {} {})", deref, arg, cast, to_rty.ty)
};
db.span_suggestion(e.span, "try", sugg);
}
},
),
_ => return,
};
}
}
}
}
}
fn is_ptr_to(from: ty::Ty, to: ty::Ty) -> bool {
if let TyRawPtr(from_ptr) = from.sty {
from_ptr.ty == to
} else {
false
}
}
fn check_ptr_to_ref<'tcx>(cx: &LateContext, from_ty: ty::Ty<'tcx>, to_ty: ty::Ty<'tcx>, e: &Expr, arg: &Expr) {
if let TyRawPtr(ref from_pty) = from_ty.sty {
if let TyRef(_, ref to_rty) = to_ty.sty {
let mess = format!("transmute from a pointer type (`{}`) to a reference type (`{}`)",
from_ty,
to_ty);
span_lint_and_then(cx, TRANSMUTE_PTR_TO_REF, e.span, &mess, |db| {
if let Some(arg) = snippet_opt(cx, arg.span) {
let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable {
("&mut *", "*mut")
} else {
("&*", "*const")
};
let sugg = if from_pty.ty == to_rty.ty {
format!("{}{}", deref, arg)
} else {
format!("{}({} as {} {})", deref, arg, cast, to_rty.ty)
};
db.span_suggestion(e.span, "try", sugg);
}
});
}
}
}