Merge pull request #1255 from Manishearth/cov

Improve test coverage
This commit is contained in:
Manish Goregaokar
2016-10-03 22:15:23 +05:30
committed by GitHub
21 changed files with 194 additions and 46 deletions

View File

@@ -54,27 +54,16 @@ pub enum Constant {
}
impl Constant {
/// convert to u64 if possible
/// Convert to `u64` if possible.
///
/// # panics
///
/// if the constant could not be converted to u64 losslessly
/// If the constant could not be converted to `u64` losslessly.
fn as_u64(&self) -> u64 {
if let Constant::Int(val) = *self {
val.to_u64().expect("negative constant can't be casted to u64")
val.to_u64().expect("negative constant can't be casted to `u64`")
} else {
panic!("Could not convert a {:?} to u64", self);
}
}
/// convert this constant to a f64, if possible
#[allow(cast_precision_loss, cast_possible_wrap)]
pub fn as_float(&self) -> Option<f64> {
match *self {
Constant::Float(ref s, _) => s.parse().ok(),
Constant::Int(i) if i.is_negative() => Some(i.to_u64_unchecked() as i64 as f64),
Constant::Int(i) => Some(i.to_u64_unchecked() as f64),
_ => None,
panic!("Could not convert a `{:?}` to `u64`", self);
}
}
}

View File

@@ -81,7 +81,7 @@ pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Exp
let Some(NodeItem(decl)) = cx.tcx.map.find(decl.id),
decl.name.as_str() == "__STATIC_FMTSTR",
let ItemStatic(_, _, ref expr) = decl.node,
let ExprAddrOf(_, ref expr) = expr.node, // &[""]
let ExprAddrOf(_, ref expr) = expr.node, // &["…", "…", …]
let ExprVec(ref exprs) = expr.node,
], {
let mut result = Vec::new();
@@ -99,7 +99,7 @@ pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Exp
/// Checks if the expressions matches
/// ```rust
/// { static __STATIC_FMTSTR: &[""] = _; __STATIC_FMTSTR }
/// { static __STATIC_FMTSTR: … = &["…", "…", …]; __STATIC_FMTSTR }
/// ```
fn check_static_str(cx: &LateContext, expr: &Expr) -> bool {
if let Some(expr) = get_argument_fmtstr_parts(cx, expr) {

View File

@@ -262,7 +262,7 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span,
span_lint_and_then(cx,
SHADOW_UNRELATED,
span,
&format!("{} shadows a previous declaration", snippet(cx, pattern_span, "_")),
&format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")),
|db| { db.span_note(prev_span, "previous binding is here"); });
}
}

View File

@@ -37,8 +37,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
match (&left.node, &right.node) {
(&StmtDecl(ref l, _), &StmtDecl(ref r, _)) => {
if let (&DeclLocal(ref l), &DeclLocal(ref r)) = (&l.node, &r.node) {
// TODO: tys
l.ty.is_none() && r.ty.is_none() && both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) &&
both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
} else {
false
}
@@ -85,7 +85,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
(&ExprCall(ref l_fun, ref l_args), &ExprCall(ref r_fun, ref r_args)) => {
!self.ignore_fn && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args)
}
(&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) => self.eq_expr(lx, rx) && self.eq_ty(lt, rt),
(&ExprCast(ref lx, ref lt), &ExprCast(ref rx, ref rt)) |
(&ExprType(ref lx, ref lt), &ExprType(ref rx, ref rt)) => {
self.eq_expr(lx, rx) && self.eq_ty(lt, rt)
}
(&ExprField(ref l_f_exp, ref l_f_ident), &ExprField(ref r_f_exp, ref r_f_ident)) => {
l_f_ident.node == r_f_ident.node && self.eq_expr(l_f_exp, r_f_exp)
}
@@ -106,8 +109,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
}
(&ExprMethodCall(ref l_name, ref l_tys, ref l_args),
&ExprMethodCall(ref r_name, ref r_tys, ref r_args)) => {
// TODO: tys
!self.ignore_fn && l_name.node == r_name.node && l_tys.is_empty() && r_tys.is_empty() &&
!self.ignore_fn && l_name.node == r_name.node &&
over(l_tys, r_tys, |l, r| self.eq_ty(l, r)) &&
self.eq_exprs(l_args, r_args)
}
(&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl),
@@ -138,6 +141,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
left.name.node == right.name.node && self.eq_expr(&left.expr, &right.expr)
}
fn eq_lifetime(&self, left: &Lifetime, right: &Lifetime) -> bool {
left.name == right.name
}
/// Check whether two patterns are the same.
pub fn eq_pat(&self, left: &Pat, right: &Pat) -> bool {
match (&left.node, &right.node) {
@@ -169,12 +176,33 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
}
fn eq_path(&self, left: &Path, right: &Path) -> bool {
left.global == right.global &&
over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r))
}
fn eq_path_parameters(&self, left: &PathParameters, right: &PathParameters) -> bool {
match (left, right) {
(&AngleBracketedParameters(ref left), &AngleBracketedParameters(ref right)) => {
over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r)) &&
over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) &&
over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r))
}
(&ParenthesizedParameters(ref left), &ParenthesizedParameters(ref right)) => {
over(&left.inputs, &right.inputs, |l, r| self.eq_ty(l, r)) &&
both(&left.output, &right.output, |l, r| self.eq_ty(l, r))
}
(&AngleBracketedParameters(_), &ParenthesizedParameters(_)) |
(&ParenthesizedParameters(_), &AngleBracketedParameters(_)) => {
false
}
}
}
fn eq_path_segment(&self, left: &PathSegment, right: &PathSegment) -> bool {
// The == of idents doesn't work with different contexts,
// we have to be explicit about hygiene
left.global == right.global &&
over(&left.segments,
&right.segments,
|l, r| l.name.as_str() == r.name.as_str() && l.parameters == r.parameters)
left.name.as_str() == right.name.as_str() &&
self.eq_path_parameters(&left.parameters, &right.parameters)
}
fn eq_qself(&self, left: &QSelf, right: &QSelf) -> bool {
@@ -199,6 +227,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
_ => false,
}
}
fn eq_type_binding(&self, left: &TypeBinding, right: &TypeBinding) -> bool {
left.name == right.name && self.eq_ty(&left.ty, &right.ty)
}
}
fn swap_binop<'a>(binop: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(BinOp_, &'a Expr, &'a Expr)> {
@@ -445,10 +477,11 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
self.hash_expr(le);
li.node.hash(&mut self.s);
}
ExprType(_, _) => {
ExprType(ref e, ref _ty) => {
let c: fn(_, _) -> _ = ExprType;
c.hash(&mut self.s);
// whats an ExprType anyway?
self.hash_expr(e);
// TODO: _ty
}
ExprUnary(lop, ref le) => {
let c: fn(_, _) -> _ = ExprUnary;
@@ -495,10 +528,15 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
pub fn hash_stmt(&mut self, b: &Stmt) {
match b.node {
StmtDecl(ref _decl, _) => {
StmtDecl(ref decl, _) => {
let c: fn(_, _) -> _ = StmtDecl;
c.hash(&mut self.s);
// TODO: decl
if let DeclLocal(ref local) = decl.node {
if let Some(ref init) = local.init {
self.hash_expr(init);
}
}
}
StmtExpr(ref expr, _) => {
let c: fn(_, _) -> _ = StmtExpr;