Rustup to rustc 1.15.0-nightly (0ed951993 2016-11-14)

This commit is contained in:
mcarton 2016-11-16 21:57:56 +01:00
parent bad26a5aca
commit 19c5f5394b
No known key found for this signature in database
GPG key ID: 5E427C794CBA45E8
53 changed files with 237 additions and 246 deletions

View file

@ -59,7 +59,7 @@ impl LateLintPass for Arithmetic {
hir::BiShr | hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => return,
_ => (),
}
let (l_ty, r_ty) = (cx.tcx.expr_ty(l), cx.tcx.expr_ty(r));
let (l_ty, r_ty) = (cx.tcx.tables().expr_ty(l), cx.tcx.tables().expr_ty(r));
if l_ty.is_integral() && r_ty.is_integral() {
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
self.span = Some(expr.span);
@ -69,7 +69,7 @@ impl LateLintPass for Arithmetic {
}
}
hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
let ty = cx.tcx.expr_ty(arg);
let ty = cx.tcx.tables().expr_ty(arg);
if ty.is_integral() {
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
self.span = Some(expr.span);

View file

@ -59,7 +59,7 @@ impl LateLintPass for ArrayIndexing {
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
if let hir::ExprIndex(ref array, ref index) = e.node {
// Array with known size can be checked statically
let ty = cx.tcx.expr_ty(array);
let ty = cx.tcx.tables().expr_ty(array);
if let ty::TyArray(_, size) = ty.sty {
let size = ConstInt::Infer(size as u64);

View file

@ -81,11 +81,11 @@ impl LateLintPass for AssignOps {
if let hir::ExprBinary(binop, ref l, ref r) = rhs.node {
if op.node == binop.node {
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
let ty = cx.tcx.expr_ty(assignee);
let ty = cx.tcx.tables().expr_ty(assignee);
if ty.walk_shallow().next().is_some() {
return; // implements_trait does not work with generics
}
let rty = cx.tcx.expr_ty(rhs);
let rty = cx.tcx.tables().expr_ty(rhs);
if rty.walk_shallow().next().is_some() {
return; // implements_trait does not work with generics
}
@ -116,11 +116,11 @@ impl LateLintPass for AssignOps {
hir::ExprAssign(ref assignee, ref e) => {
if let hir::ExprBinary(op, ref l, ref r) = e.node {
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
let ty = cx.tcx.expr_ty(assignee);
let ty = cx.tcx.tables().expr_ty(assignee);
if ty.walk_shallow().next().is_some() {
return; // implements_trait does not work with generics
}
let rty = cx.tcx.expr_ty(rhs);
let rty = cx.tcx.tables().expr_ty(rhs);
if rty.walk_shallow().next().is_some() {
return; // implements_trait does not work with generics
}

View file

@ -152,8 +152,8 @@ impl LateLintPass for AttrPass {
}
fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
if let ItemFn(_, _, _, _, _, ref block) = item.node {
is_relevant_block(cx, block)
if let ItemFn(_, _, _, _, _, ref expr) = item.node {
is_relevant_expr(cx, expr)
} else {
false
}
@ -161,7 +161,7 @@ fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool {
match item.node {
ImplItemKind::Method(_, ref block) => is_relevant_block(cx, block),
ImplItemKind::Method(_, ref expr) => is_relevant_expr(cx, expr),
_ => false,
}
}
@ -169,7 +169,7 @@ fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool {
fn is_relevant_trait(cx: &LateContext, item: &TraitItem) -> bool {
match item.node {
MethodTraitItem(_, None) => true,
MethodTraitItem(_, Some(ref block)) => is_relevant_block(cx, block),
MethodTraitItem(_, Some(ref expr)) => is_relevant_expr(cx, expr),
_ => false,
}
}

View file

@ -55,17 +55,9 @@ struct ExVisitor<'v> {
impl<'v> Visitor<'v> for ExVisitor<'v> {
fn visit_expr(&mut self, expr: &'v Expr) {
if let ExprClosure(_, _, ref block, _) = expr.node {
if let ExprClosure(_, _, ref expr, _) = expr.node {
let complex = {
if block.stmts.is_empty() {
if let Some(ref ex) = block.expr {
matches!(ex.node, ExprBlock(_))
} else {
false
}
} else {
true
}
matches!(expr.node, ExprBlock(_))
};
if complex {
self.found_block = Some(expr);

View file

@ -392,7 +392,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
match e.node {
ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
ExprUnary(UnNot, ref inner) => {
if self.0.tcx.node_types()[&inner.id].is_bool() {
if self.0.tcx.tables.borrow().node_types[&inner.id].is_bool() {
self.bool_expr(e);
} else {
walk_expr(self, e);

View file

@ -120,8 +120,8 @@ impl LateLintPass for CopyAndPaste {
}
let (conds, blocks) = if_sequence(expr);
lint_same_then_else(cx, blocks.as_slice());
lint_same_cond(cx, conds.as_slice());
lint_same_then_else(cx, &blocks);
lint_same_cond(cx, &conds);
lint_match_arms(cx, expr);
}
}
@ -219,8 +219,8 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) {
/// Eg. would return `([a, b], [c, d, e])` for the expression
/// `if a { c } else if b { d } else { e }`.
fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
let mut conds = SmallVector::zero();
let mut blocks = SmallVector::zero();
let mut conds = SmallVector::new();
let mut blocks = SmallVector::new();
while let ExprIf(ref cond, ref then_block, ref else_expr) = expr.node {
conds.push(&**cond);
@ -256,7 +256,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned
}
PatKind::Binding(_, ref ident, ref as_pat) => {
if let Entry::Vacant(v) = map.entry(ident.node.as_str()) {
v.insert(cx.tcx.pat_ty(pat));
v.insert(cx.tcx.tables().pat_ty(pat));
}
if let Some(ref as_pat) = *as_pat {
bindings_impl(cx, as_pat, map);

View file

@ -42,12 +42,12 @@ impl LintPass for CyclomaticComplexity {
}
impl CyclomaticComplexity {
fn check<'a, 'tcx>(&mut self, cx: &'a LateContext<'a, 'tcx>, block: &Block, span: Span) {
fn check<'a, 'tcx>(&mut self, cx: &'a LateContext<'a, 'tcx>, expr: &Expr, span: Span) {
if in_macro(cx, span) {
return;
}
let cfg = CFG::new(cx.tcx, block);
let cfg = CFG::new(cx.tcx, expr);
let n = cfg.graph.len_nodes() as u64;
let e = cfg.graph.len_edges() as u64;
if e + 2 < n {
@ -62,9 +62,9 @@ impl CyclomaticComplexity {
returns: 0,
tcx: &cx.tcx,
};
helper.visit_block(block);
helper.visit_expr(expr);
let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper;
let ret_ty = cx.tcx.node_id_to_type(block.id);
let ret_ty = cx.tcx.tables().node_id_to_type(expr.id);
let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) {
returns
} else {
@ -92,22 +92,22 @@ impl CyclomaticComplexity {
impl LateLintPass for CyclomaticComplexity {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
if let ItemFn(_, _, _, _, _, ref block) = item.node {
if let ItemFn(_, _, _, _, _, ref expr) = item.node {
if !attr::contains_name(&item.attrs, "test") {
self.check(cx, block, item.span);
self.check(cx, expr, item.span);
}
}
}
fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
if let ImplItemKind::Method(_, ref block) = item.node {
self.check(cx, block, item.span);
if let ImplItemKind::Method(_, ref expr) = item.node {
self.check(cx, expr, item.span);
}
}
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
if let MethodTraitItem(_, Some(ref block)) = item.node {
self.check(cx, block, item.span);
if let MethodTraitItem(_, Some(ref expr)) = item.node {
self.check(cx, expr, item.span);
}
}
@ -139,7 +139,7 @@ impl<'a, 'b, 'tcx, 'gcx> Visitor<'a> for CCHelper<'b, 'gcx, 'tcx> {
}
ExprCall(ref callee, _) => {
walk_expr(self, e);
let ty = self.tcx.node_id_to_type(callee.id);
let ty = self.tcx.tables().node_id_to_type(callee.id);
match ty.sty {
ty::TyFnDef(_, _, ty) |
ty::TyFnPtr(ty) if ty.sig.skip_binder().output.sty == ty::TyNever => {

View file

@ -73,7 +73,7 @@ impl LintPass for Derive {
impl LateLintPass for Derive {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
if let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty;
let ty = cx.tcx.item_type(cx.tcx.map.local_def_id(item.id));
let is_automatically_derived = is_automatically_derived(&*item.attrs);
check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);

View file

@ -52,7 +52,7 @@ impl LateLintPass for Pass {
}
fn check_drop_arg(cx: &LateContext, call_span: Span, arg: &Expr) {
let arg_ty = cx.tcx.expr_ty(arg);
let arg_ty = cx.tcx.tables().expr_ty(arg);
if let ty::TyRef(..) = arg_ty.sty {
span_note_and_lint(cx,
DROP_REF,

View file

@ -86,7 +86,7 @@ fn check_cond<'a, 'tcx, 'b>(cx: &'a LateContext<'a, 'tcx>, check: &'b Expr) -> O
let ExprAddrOf(_, ref key) = params[1].node
], {
let map = &params[0];
let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map));
let obj_ty = walk_ptrs_ty(cx.tcx.tables().expr_ty(map));
return if match_type(cx, obj_ty, &paths::BTREEMAP) {
Some(("BTreeMap", map, key))

View file

@ -5,7 +5,6 @@ use rustc::infer::InferCtxt;
use rustc::lint::*;
use rustc::middle::expr_use_visitor::*;
use rustc::middle::mem_categorization::{cmt, Categorization};
use rustc::ty::adjustment::AutoAdjustment;
use rustc::ty;
use rustc::ty::layout::TargetDataLayout;
use rustc::util::nodemap::NodeSet;
@ -62,7 +61,7 @@ impl LintPass for Pass {
}
impl LateLintPass for Pass {
fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Block, _: Span, id: NodeId) {
fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Expr, _: Span, id: NodeId) {
let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id);
let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env);
@ -146,17 +145,19 @@ impl<'a, 'tcx: 'a+'gcx, 'gcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx, 'g
}
fn borrow(&mut self, borrow_id: NodeId, _: Span, cmt: cmt<'tcx>, _: &ty::Region, _: ty::BorrowKind,
loan_cause: LoanCause) {
use rustc::ty::adjustment::Adjust;
if let Categorization::Local(lid) = cmt.cat {
if self.set.contains(&lid) {
if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx
if let Some(&Adjust::DerefRef { autoderefs, .. }) = self.tcx
.tables
.borrow()
.adjustments
.get(&borrow_id) {
.get(&borrow_id)
.map(|a| &a.kind) {
if LoanCause::AutoRef == loan_cause {
// x.foo()
if adj.autoderefs == 0 {
if autoderefs == 0 {
self.set.remove(&lid); // Used without autodereffing (i.e. x.clone())
}
} else {
@ -164,14 +165,15 @@ impl<'a, 'tcx: 'a+'gcx, 'gcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx, 'g
}
} else if LoanCause::AddrOf == loan_cause {
// &x
if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx
if let Some(&Adjust::DerefRef { autoderefs, .. }) = self.tcx
.tables
.borrow()
.adjustments
.get(&self.tcx
.map
.get_parent_node(borrow_id)) {
if adj.autoderefs <= 1 {
.map
.get_parent_node(borrow_id))
.map(|a| &a.kind) {
if autoderefs <= 1 {
// foo(&x) where no extra autoreffing is happening
self.set.remove(&lid);
}

View file

@ -48,60 +48,53 @@ impl LateLintPass for EtaPass {
}
fn check_closure(cx: &LateContext, expr: &Expr) {
if let ExprClosure(_, ref decl, ref blk, _) = expr.node {
if !blk.stmts.is_empty() {
// || {foo(); bar()}; can't be reduced here
return;
}
if let Some(ref ex) = blk.expr {
if let ExprCall(ref caller, ref args) = ex.node {
if args.len() != decl.inputs.len() {
// Not the same number of arguments, there
// is no way the closure is the same as the function
return;
if let ExprClosure(_, ref decl, ref ex, _) = expr.node {
if let ExprCall(ref caller, ref args) = ex.node {
if args.len() != decl.inputs.len() {
// Not the same number of arguments, there
// is no way the closure is the same as the function
return;
}
if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) {
// Are the expression or the arguments type-adjusted? Then we need the closure
return;
}
let fn_ty = cx.tcx.tables().expr_ty(caller);
match fn_ty.sty {
// Is it an unsafe function? They don't implement the closure traits
ty::TyFnDef(_, _, fn_ty) |
ty::TyFnPtr(fn_ty) => {
if fn_ty.unsafety == Unsafety::Unsafe ||
fn_ty.sig.skip_binder().output.sty == ty::TyNever {
return;
}
}
if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) {
// Are the expression or the arguments type-adjusted? Then we need the closure
return;
}
let fn_ty = cx.tcx.expr_ty(caller);
match fn_ty.sty {
// Is it an unsafe function? They don't implement the closure traits
ty::TyFnDef(_, _, fn_ty) |
ty::TyFnPtr(fn_ty) => {
if fn_ty.unsafety == Unsafety::Unsafe ||
fn_ty.sig.skip_binder().output.sty == ty::TyNever {
_ => (),
}
for (a1, a2) in decl.inputs.iter().zip(args) {
if let PatKind::Binding(_, ident, _) = a1.pat.node {
// XXXManishearth Should I be checking the binding mode here?
if let ExprPath(None, ref p) = a2.node {
if p.segments.len() != 1 {
// If it's a proper path, it can't be a local variable
return;
}
}
_ => (),
}
for (a1, a2) in decl.inputs.iter().zip(args) {
if let PatKind::Binding(_, ident, _) = a1.pat.node {
// XXXManishearth Should I be checking the binding mode here?
if let ExprPath(None, ref p) = a2.node {
if p.segments.len() != 1 {
// If it's a proper path, it can't be a local variable
return;
}
if p.segments[0].name != ident.node {
// The two idents should be the same
return;
}
} else {
if p.segments[0].name != ident.node {
// The two idents should be the same
return;
}
} else {
return;
}
} else {
return;
}
span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| {
if let Some(snippet) = snippet_opt(cx, caller.span) {
db.span_suggestion(expr.span, "remove closure as shown:", snippet);
}
});
}
span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| {
if let Some(snippet) = snippet_opt(cx, caller.span) {
db.span_suggestion(expr.span, "remove closure as shown:", snippet);
}
});
}
}
}

View file

@ -126,7 +126,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DivergenceVisitor<'a, 'tcx> {
ExprAgain(_) |
ExprBreak(_) |
ExprRet(_) => self.report_diverging_sub_expr(e),
ExprCall(ref func, _) => match self.0.tcx.expr_ty(func).sty {
ExprCall(ref func, _) => match self.0.tcx.tables().expr_ty(func).sty {
ty::TyFnDef(_, _, fn_ty) |
ty::TyFnPtr(fn_ty) => if let ty::TyNever = self.0.tcx.erase_late_bound_regions(&fn_ty.sig).output.sty {
self.report_diverging_sub_expr(e);

View file

@ -132,7 +132,7 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
let Some(fun) = resolve_node(cx, args[1].id),
match_def_path(cx, fun.def_id(), &paths::DISPLAY_FMT_METHOD),
], {
let ty = walk_ptrs_ty(cx.tcx.pat_ty(&pat[0]));
let ty = walk_ptrs_ty(cx.tcx.tables().pat_ty(&pat[0]));
return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING);
}}

View file

@ -69,7 +69,7 @@ impl LintPass for Functions {
}
impl LateLintPass for Functions {
fn check_fn(&mut self, cx: &LateContext, kind: intravisit::FnKind, decl: &hir::FnDecl, block: &hir::Block, span: Span, nodeid: ast::NodeId) {
fn check_fn(&mut self, cx: &LateContext, kind: intravisit::FnKind, decl: &hir::FnDecl, expr: &hir::Expr, span: Span, nodeid: ast::NodeId) {
use rustc::hir::map::Node::*;
let is_impl = if let Some(NodeItem(item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) {
@ -94,18 +94,18 @@ impl LateLintPass for Functions {
}
}
self.check_raw_ptr(cx, unsafety, decl, block, nodeid);
self.check_raw_ptr(cx, unsafety, decl, expr, nodeid);
}
fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
if let hir::MethodTraitItem(ref sig, ref block) = item.node {
if let hir::MethodTraitItem(ref sig, ref expr) = item.node {
// don't lint extern functions decls, it's not their fault
if sig.abi == Abi::Rust {
self.check_arg_number(cx, &sig.decl, item.span);
}
if let Some(ref block) = *block {
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, block, item.id);
if let Some(ref expr) = *expr {
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, expr, item.id);
}
}
}
@ -122,7 +122,7 @@ impl Functions {
}
}
fn check_raw_ptr(&self, cx: &LateContext, unsafety: hir::Unsafety, decl: &hir::FnDecl, block: &hir::Block, nodeid: ast::NodeId) {
fn check_raw_ptr(&self, cx: &LateContext, unsafety: hir::Unsafety, decl: &hir::FnDecl, expr: &hir::Expr, nodeid: ast::NodeId) {
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(nodeid) {
let raw_ptrs = decl.inputs.iter().filter_map(|arg| raw_ptr_arg(cx, arg)).collect::<HashSet<_>>();
@ -132,7 +132,7 @@ impl Functions {
ptrs: raw_ptrs,
};
hir::intravisit::walk_block(&mut v, block);
hir::intravisit::walk_expr(&mut v, expr);
}
}
}
@ -155,7 +155,7 @@ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'v hir::Expr) {
match expr.node {
hir::ExprCall(ref f, ref args) => {
let ty = self.cx.tcx.expr_ty(f);
let ty = self.cx.tcx.tables().expr_ty(f);
if type_is_unsafe_function(ty) {
for arg in args {

View file

@ -1,6 +1,6 @@
use rustc::lint::*;
use rustc::hir::def_id::DefId;
use rustc::ty::{self, ImplOrTraitItem};
use rustc::ty;
use rustc::hir::*;
use syntax::ast::{Lit, LitKind, Name};
use syntax::codemap::{Span, Spanned};
@ -133,7 +133,8 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) {
if let Some(i) = impl_items.iter().find(|i| is_named_self(i, "len")) {
if cx.access_levels.is_exported(i.id) {
let ty = cx.tcx.node_id_to_type(item.id);
let def_id = cx.tcx.map.local_def_id(item.id);
let ty = cx.tcx.item_type(def_id);
span_lint(cx,
LEN_WITHOUT_IS_EMPTY,
@ -183,10 +184,15 @@ fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], l
/// Check if this type has an `is_empty` method.
fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
/// Get an `ImplOrTraitItem` and return true if it matches `is_empty(self)`.
fn is_is_empty(item: &ImplOrTraitItem) -> bool {
if let ty::MethodTraitItem(ref method) = *item {
method.name.as_str() == "is_empty" && method.fty.sig.skip_binder().inputs.len() == 1
/// Get an `AssociatedItem` and return true if it matches `is_empty(self)`.
fn is_is_empty(cx: &LateContext, item: &ty::AssociatedItem) -> bool {
if let ty::AssociatedKind::Method = item.kind {
if item.name.as_str() == "is_empty" {
let ty = cx.tcx.item_type(item.def_id).fn_sig().skip_binder();
ty.inputs.len() == 1
} else {
false
}
} else {
false
}
@ -195,19 +201,18 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
/// Check the inherent impl's items for an `is_empty(self)` method.
fn has_is_empty_impl(cx: &LateContext, id: DefId) -> bool {
cx.tcx.inherent_impls.borrow().get(&id).map_or(false, |impls| impls.iter().any(|imp| {
cx.tcx.impl_or_trait_items(*imp).iter().any(|item| {
is_is_empty(&cx.tcx.impl_or_trait_item(*item))
cx.tcx.associated_items(*imp).any(|item| {
is_is_empty(cx, &item)
})
}))
}
let ty = &walk_ptrs_ty(cx.tcx.expr_ty(expr));
let ty = &walk_ptrs_ty(cx.tcx.tables().expr_ty(expr));
match ty.sty {
ty::TyTrait(_) => {
cx.tcx
.impl_or_trait_items(ty.ty_to_def_id().expect("trait impl not found"))
.iter()
.any(|item| is_is_empty(&cx.tcx.impl_or_trait_item(*item)))
.associated_items(ty.ty_to_def_id().expect("trait impl not found"))
.any(|item| is_is_empty(cx, &item))
}
ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, id)),
ty::TyAdt(id, _) => has_is_empty_impl(cx, id.did),

View file

@ -3,7 +3,6 @@
#![feature(box_syntax)]
#![feature(collections)]
#![feature(custom_attribute)]
#![feature(dotdot_in_tuple_patterns)]
#![feature(rustc_private)]
#![feature(slice_patterns)]
#![feature(stmt_expr_attributes)]

View file

@ -247,8 +247,8 @@ impl<'v, 't> RefVisitor<'v, 't> {
match def {
Def::TyAlias(def_id) |
Def::Struct(def_id) => {
let type_scheme = self.cx.tcx.lookup_item_type(def_id);
for _ in type_scheme.generics.regions.as_slice() {
let generics = self.cx.tcx.item_generics(def_id);
for _ in generics.regions.as_slice() {
self.record(&None);
}
}

View file

@ -623,7 +623,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) {
/// Check for `for` loops over `Option`s and `Results`
fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) {
let ty = cx.tcx.expr_ty(arg);
let ty = cx.tcx.tables().expr_ty(arg);
if match_type(cx, ty, &paths::OPTION) {
span_help_and_lint(cx,
FOR_LOOP_OVER_OPTION,
@ -709,7 +709,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex
_ => (arg.span, arg),
};
let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg));
let ty = walk_ptrs_ty(cx.tcx.tables().expr_ty(arg));
if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP) {
span_lint_and_then(cx,
FOR_KV_MAP,
@ -854,7 +854,7 @@ impl<'v, 't> Visitor<'v> for VarUsedAfterLoopVisitor<'v, 't> {
fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool {
// no walk_ptrs_ty: calling iter() on a reference can make sense because it
// will allow further borrows afterwards
let ty = cx.tcx.expr_ty(e);
let ty = cx.tcx.tables().expr_ty(e);
is_iterable_array(ty) ||
match_type(cx, ty, &paths::VEC) ||
match_type(cx, ty, &paths::LINKED_LIST) ||

View file

@ -30,11 +30,8 @@ impl LateLintPass for Pass {
if let ExprMethodCall(name, _, ref args) = expr.node {
if name.node.as_str() == "map" && args.len() == 2 {
match args[1].node {
ExprClosure(_, ref decl, ref blk, _) => {
ExprClosure(_, ref decl, ref closure_expr, _) => {
if_let_chain! {[
// just one expression in the closure
blk.stmts.is_empty(),
let Some(ref closure_expr) = blk.expr,
// nothing special in the argument, besides reference bindings
// (e.g. .map(|&x| x) )
let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat),
@ -44,7 +41,7 @@ impl LateLintPass for Pass {
// look for derefs, for .map(|x| *x)
if only_derefs(cx, &*closure_expr, arg_ident) &&
// .cloned() only removes one level of indirection, don't lint on more
walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1
walk_ptrs_ty_depth(cx.tcx.tables().pat_ty(&*decl.inputs[0].pat)).1 == 1
{
span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
"you seem to be using .map() to clone the contents of an {}, consider \
@ -101,7 +98,7 @@ fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool {
fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> {
if match_trait_method(cx, expr, &paths::ITERATOR) {
Some("iterator")
} else if match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(arg)), &paths::OPTION) {
} else if match_type(cx, walk_ptrs_ty(cx.tcx.tables().expr_ty(arg)), &paths::OPTION) {
Some("Option")
} else {
None

View file

@ -159,7 +159,7 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
// allow match arms with just expressions
return;
};
let ty = cx.tcx.expr_ty(ex);
let ty = cx.tcx.tables().expr_ty(ex);
if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow {
check_single_match_single_pattern(cx, ex, arms, expr, els);
check_single_match_opt_like(cx, ex, arms, expr, ty, els);
@ -243,7 +243,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr:
fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
// type of expression == bool
if cx.tcx.expr_ty(ex).sty == ty::TyBool {
if cx.tcx.tables().expr_ty(ex).sty == ty::TyBool {
span_lint_and_then(cx,
MATCH_BOOL,
expr.span,
@ -296,7 +296,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
}
fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) {
if arms.len() >= 2 && cx.tcx.expr_ty(ex).is_integral() {
if arms.len() >= 2 && cx.tcx.tables().expr_ty(ex).is_integral() {
let ranges = all_ranges(cx, arms);
let type_ranges = type_ranges(&ranges);
if !type_ranges.is_empty() {

View file

@ -33,7 +33,7 @@ impl LateLintPass for MemForget {
if let ExprPath(None, _) = path_expr.node {
let def_id = cx.tcx.expect_def(path_expr.id).def_id();
if match_def_path(cx, def_id, &paths::MEM_FORGET) {
let forgot_ty = cx.tcx.expr_ty(&args[0]);
let forgot_ty = cx.tcx.tables().expr_ty(&args[0]);
if match forgot_ty.ty_adt_def() {
Some(def) => def.has_dtor(),

View file

@ -573,7 +573,7 @@ impl LateLintPass for Pass {
lint_or_fun_call(cx, expr, &name.node.as_str(), args);
let self_ty = cx.tcx.expr_ty_adjusted(&args[0]);
let self_ty = cx.tcx.tables().expr_ty_adjusted(&args[0]);
if args.len() == 1 && name.node.as_str() == "clone" {
lint_clone_on_copy(cx, expr, &args[0], self_ty);
}
@ -623,7 +623,7 @@ impl LateLintPass for Pass {
}
// check conventions w.r.t. conversion method names and predicates
let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty;
let ty = cx.tcx.item_type(cx.tcx.map.local_def_id(item.id));
let is_copy = is_copy(cx, ty, item.id);
for &(ref conv, self_kinds) in &CONVENTIONS {
if_let_chain! {[
@ -680,7 +680,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi
.as_str();
if ["default", "new"].contains(&path) {
let arg_ty = cx.tcx.expr_ty(arg);
let arg_ty = cx.tcx.tables().expr_ty(arg);
let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) {
default_trait_id
} else {
@ -724,7 +724,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi
"else"),
(&paths::RESULT, true, &["or", "unwrap_or"], "else")];
let self_ty = cx.tcx.expr_ty(self_expr);
let self_ty = cx.tcx.tables().expr_ty(self_expr);
let (fn_has_arguments, poss, suffix) = if let Some(&(_, fn_has_arguments, poss, suffix)) =
know_types.iter().find(|&&i| match_type(cx, self_ty, i.0)) {
@ -762,7 +762,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi
/// Checks for the `CLONE_ON_COPY` lint.
fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: ty::Ty) {
let ty = cx.tcx.expr_ty(expr);
let ty = cx.tcx.tables().expr_ty(expr);
let parent = cx.tcx.map.get_parent(expr.id);
let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent);
if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = arg_ty.sty {
@ -785,7 +785,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t
expr.span,
"using `clone` on a `Copy` type",
|db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
if let ty::TyRef(..) = cx.tcx.expr_ty(arg).sty {
if let ty::TyRef(..) = cx.tcx.tables().expr_ty(arg).sty {
db.span_suggestion(expr.span, "try dereferencing it", format!("{}", snip.deref()));
} else {
db.span_suggestion(expr.span, "try removing the `clone` call", format!("{}", snip));
@ -795,11 +795,11 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t
}
fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) {
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0]));
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(&args[0]));
if !match_type(cx, obj_ty, &paths::VEC) {
return;
}
let arg_ty = cx.tcx.expr_ty(&args[1]);
let arg_ty = cx.tcx.tables().expr_ty(&args[1]);
if let Some(slice) = derefs_to_slice(cx, &args[1], arg_ty) {
span_lint_and_then(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice", |db| {
db.span_suggestion(expr.span,
@ -831,13 +831,13 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr
// Type of MethodArgs is potentially a Vec
fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_mut: bool){
let mut_str = if is_mut { "_mut" } else {""};
let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tcx.expr_ty(&iter_args[0])).is_some() {
let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tcx.tables().expr_ty(&iter_args[0])).is_some() {
"slice"
}
else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC) {
else if match_type(cx, cx.tcx.tables().expr_ty(&iter_args[0]), &paths::VEC) {
"Vec"
}
else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC_DEQUE) {
else if match_type(cx, cx.tcx.tables().expr_ty(&iter_args[0]), &paths::VEC_DEQUE) {
"VecDeque"
}
else {
@ -856,7 +856,7 @@ fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_
fn lint_get_unwrap(cx: &LateContext, expr: &hir::Expr, get_args: &MethodArgs, is_mut: bool) {
// Note: we don't want to lint `get_mut().unwrap` for HashMap or BTreeMap,
// because they do not implement `IndexMut`
let expr_ty = cx.tcx.expr_ty(&get_args[0]);
let expr_ty = cx.tcx.tables().expr_ty(&get_args[0]);
let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() {
"slice"
} else if match_type(cx, expr_ty, &paths::VEC) {
@ -915,7 +915,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: ty::Ty) -> Option<sug
}
if let hir::ExprMethodCall(name, _, ref args) = expr.node {
if &name.node.as_str() == &"iter" && may_slice(cx, cx.tcx.expr_ty(&args[0])) {
if &name.node.as_str() == &"iter" && may_slice(cx, cx.tcx.tables().expr_ty(&args[0])) {
sugg::Sugg::hir_opt(cx, &*args[0]).map(|sugg| {
sugg.addr()
})
@ -942,7 +942,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: ty::Ty) -> Option<sug
// Type of MethodArgs is potentially a Vec
/// lint use of `unwrap()` for `Option`s and `Result`s
fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &MethodArgs) {
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&unwrap_args[0]));
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(&unwrap_args[0]));
let mess = if match_type(cx, obj_ty, &paths::OPTION) {
Some((OPTION_UNWRAP_USED, "an Option", "None"))
@ -969,8 +969,8 @@ fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &MethodArgs) {
/// lint use of `ok().expect()` for `Result`s
fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &MethodArgs) {
// lint if the caller of `ok()` is a `Result`
if match_type(cx, cx.tcx.expr_ty(&ok_args[0]), &paths::RESULT) {
let result_type = cx.tcx.expr_ty(&ok_args[0]);
if match_type(cx, cx.tcx.tables().expr_ty(&ok_args[0]), &paths::RESULT) {
let result_type = cx.tcx.tables().expr_ty(&ok_args[0]);
if let Some(error_type) = get_error_type(cx, result_type) {
if has_debug_impl(error_type, cx) {
span_lint(cx,
@ -987,7 +987,7 @@ fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &MethodArgs) {
/// lint use of `map().unwrap_or()` for `Option`s
fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) {
// lint if the caller of `map()` is an `Option`
if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) {
if match_type(cx, cx.tcx.tables().expr_ty(&map_args[0]), &paths::OPTION) {
// lint message
let msg = "called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling \
`map_or(a, f)` instead";
@ -1018,7 +1018,7 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs,
/// lint use of `map().unwrap_or_else()` for `Option`s
fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) {
// lint if the caller of `map()` is an `Option`
if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) {
if match_type(cx, cx.tcx.tables().expr_ty(&map_args[0]), &paths::OPTION) {
// lint message
let msg = "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \
`map_or_else(g, f)` instead";
@ -1147,7 +1147,7 @@ fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other:
let hir::ExprPath(None, ref path) = fun.node,
path.segments.len() == 1 && path.segments[0].name.as_str() == "Some"
], {
let self_ty = walk_ptrs_ty(cx.tcx.expr_ty_adjusted(&args[0][0]));
let self_ty = walk_ptrs_ty(cx.tcx.tables().expr_ty_adjusted(&args[0][0]));
if self_ty.sty != ty::TyStr {
return false;

View file

@ -168,7 +168,7 @@ impl LintPass for Pass {
}
impl LateLintPass for Pass {
fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Expr, _: Span, _: NodeId) {
if let FnKind::Closure(_) = k {
// Does not apply to closures
return;
@ -353,14 +353,14 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool {
}
fn is_float(cx: &LateContext, expr: &Expr) -> bool {
matches!(walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty, ty::TyFloat(_))
matches!(walk_ptrs_ty(cx.tcx.tables().expr_ty(expr)).sty, ty::TyFloat(_))
}
fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: Span) {
let (arg_ty, snip) = match expr.node {
ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) if args.len() == 1 => {
if name.as_str() == "to_string" || name.as_str() == "to_owned" && is_str_arg(cx, args) {
(cx.tcx.expr_ty(&args[0]), snippet(cx, args[0].span, ".."))
(cx.tcx.tables().expr_ty(&args[0]), snippet(cx, args[0].span, ".."))
} else {
return;
}
@ -368,7 +368,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S
ExprCall(ref path, ref v) if v.len() == 1 => {
if let ExprPath(None, ref path) = path.node {
if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) {
(cx.tcx.expr_ty(&v[0]), snippet(cx, v[0].span, ".."))
(cx.tcx.tables().expr_ty(&v[0]), snippet(cx, v[0].span, ".."))
} else {
return;
}
@ -379,7 +379,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S
_ => return,
};
let other_ty = cx.tcx.expr_ty(other);
let other_ty = cx.tcx.tables().expr_ty(other);
let partial_eq_trait_id = match cx.tcx.lang_items.eq_trait() {
Some(id) => id,
None => return,
@ -413,7 +413,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S
fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool {
args.len() == 1 &&
matches!(walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty, ty::TyStr)
matches!(walk_ptrs_ty(cx.tcx.tables().expr_ty(&args[0])).sty, ty::TyStr)
}
/// Heuristic to see if an expression is used. Should be compatible with `unused_variables`'s idea

View file

@ -239,7 +239,7 @@ impl EarlyLintPass for MiscEarly {
}
}
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: Span, _: NodeId) {
let mut registered_names: HashMap<String, Span> = HashMap::new();
for arg in &decl.inputs {

View file

@ -147,10 +147,7 @@ impl LateLintPass for MissingDoc {
fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
// If the method is an impl for a trait, don't doc.
let def_id = cx.tcx.map.local_def_id(impl_item.id);
match cx.tcx.impl_or_trait_items.borrow()
.get(&def_id)
.expect("missing method descriptor?!")
.container() {
match cx.tcx.associated_item(def_id).container {
ty::TraitContainer(_) => return,
ty::ImplContainer(cid) => {
if cx.tcx.impl_trait_ref(cid).is_some() {

View file

@ -65,7 +65,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> {
} else if let hir::ExprAddrOf(hir::MutMutable, ref e) = expr.node {
if let hir::ExprAddrOf(hir::MutMutable, _) = e.node {
span_lint(self.cx, MUT_MUT, expr.span, "generally you want to avoid `&mut &mut _` if possible");
} else if let TyRef(_, TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tcx.expr_ty(e).sty {
} else if let TyRef(_, TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tcx.tables().expr_ty(e).sty {
span_lint(self.cx,
MUT_MUT,
expr.span,

View file

@ -56,7 +56,7 @@ pub struct MutexAtomic;
impl LateLintPass for MutexAtomic {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
let ty = cx.tcx.expr_ty(expr);
let ty = cx.tcx.tables().expr_ty(expr);
if let ty::TyAdt(_, subst) = ty.sty {
if match_type(cx, ty, &paths::MUTEX) {
let mutex_param = &subst.type_at(0).sty;

View file

@ -4,9 +4,8 @@
use rustc::lint::*;
use rustc::hir::{ExprAddrOf, Expr, MutImmutable, Pat, PatKind, BindingMode};
use rustc::ty::TyRef;
use rustc::ty;
use utils::{span_lint, in_macro};
use rustc::ty::adjustment::AutoAdjustment::AdjustDerefRef;
/// **What it does:** Checks for address of operations (`&`) that are going to
/// be dereferenced immediately by the compiler.
@ -41,9 +40,9 @@ impl LateLintPass for NeedlessBorrow {
return;
}
if let ExprAddrOf(MutImmutable, ref inner) = e.node {
if let TyRef(..) = cx.tcx.expr_ty(inner).sty {
if let Some(&AdjustDerefRef(ref deref)) = cx.tcx.tables.borrow().adjustments.get(&e.id) {
if deref.autoderefs > 1 && deref.autoref.is_some() {
if let ty::TyRef(..) = cx.tcx.tables().expr_ty(inner).sty {
if let Some(&ty::adjustment::Adjust::DerefRef { autoderefs, autoref, .. }) = cx.tcx.tables.borrow().adjustments.get(&e.id).map(|a| &a.kind) {
if autoderefs > 1 && autoref.is_some() {
span_lint(cx,
NEEDLESS_BORROW,
e.span,
@ -59,9 +58,9 @@ impl LateLintPass for NeedlessBorrow {
return;
}
if let PatKind::Binding(BindingMode::BindByRef(MutImmutable), _, _) = pat.node {
if let TyRef(_, ref tam) = cx.tcx.pat_ty(pat).sty {
if let ty::TyRef(_, ref tam) = cx.tcx.tables().pat_ty(pat).sty {
if tam.mutbl == MutImmutable {
if let TyRef(..) = tam.ty.sty {
if let ty::TyRef(..) = tam.ty.sty {
span_lint(cx,
NEEDLESS_BORROW,
pat.span,

View file

@ -33,7 +33,7 @@ impl LintPass for Pass {
impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprStruct(_, ref fields, Some(ref base)) = expr.node {
let ty = cx.tcx.expr_ty(expr);
let ty = cx.tcx.tables().expr_ty(expr);
if let TyAdt(def, _) = ty.sty {
if fields.len() == def.struct_variant().fields.len() {
span_lint(cx,

View file

@ -50,7 +50,7 @@ fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) {
let Constant::Int(ref ci) = consts::lit_to_constant(&l.node),
let Some(val) = ci.to_u64(),
val == 1,
cx.tcx.expr_ty(exp).is_integral()
cx.tcx.tables().expr_ty(exp).is_integral()
], {
span_lint(cx,
NEG_MULTIPLY,

View file

@ -90,7 +90,7 @@ impl LintPass for NewWithoutDefault {
}
impl LateLintPass for NewWithoutDefault {
fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, id: ast::NodeId) {
fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Expr, span: Span, id: ast::NodeId) {
if in_external_macro(cx, span) {
return;
}
@ -102,8 +102,7 @@ impl LateLintPass for NewWithoutDefault {
}
if decl.inputs.is_empty() && name.as_str() == "new" && cx.access_levels.is_reachable(id) {
let self_ty = cx.tcx
.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id)))
.ty;
.item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id)));
if_let_chain!{[
self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics
same_tys(cx, self_ty, return_ty(cx, id), id),

View file

@ -50,7 +50,7 @@ impl LateLintPass for Pass {
method_chain_args(op, &["ok"]).is_some() //test to see if using ok() methoduse std::marker::Sized;
], {
let is_result_type = match_type(cx, cx.tcx.expr_ty(&result_types[0]), &paths::RESULT);
let is_result_type = match_type(cx, cx.tcx.tables().expr_ty(&result_types[0]), &paths::RESULT);
let some_expr_string = snippet(cx, y[0].span, "");
if print::path_to_string(x) == "Some" && is_result_type {
span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span,

View file

@ -35,7 +35,7 @@ impl LintPass for NonSensical {
impl LateLintPass for NonSensical {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let ExprMethodCall(ref name, _, ref arguments) = e.node {
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0]));
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(&arguments[0]));
if name.node.as_str() == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
let mut options = Vec::new();
get_open_options(cx, &arguments[0], &mut options);
@ -63,7 +63,7 @@ enum OpenOption {
fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) {
if let ExprMethodCall(ref name, _, ref arguments) = argument.node {
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0]));
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(&arguments[0]));
// Only proceed if this is a call on some object of type std::fs::OpenOptions
if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 {

View file

@ -39,8 +39,8 @@ impl LateLintPass for OverflowCheckConditional {
let Expr_::ExprPath(_, ref path2) = ident2.node,
let Expr_::ExprPath(_, ref path3) = second.node,
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
cx.tcx.expr_ty(ident1).is_integral(),
cx.tcx.expr_ty(ident2).is_integral()
cx.tcx.tables().expr_ty(ident1).is_integral(),
cx.tcx.tables().expr_ty(ident2).is_integral()
], {
if let BinOp_::BiLt = op.node {
if let BinOp_::BiAdd = op2.node {
@ -61,8 +61,8 @@ impl LateLintPass for OverflowCheckConditional {
let Expr_::ExprPath(_, ref path2) = ident2.node,
let Expr_::ExprPath(_, ref path3) = first.node,
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
cx.tcx.expr_ty(ident1).is_integral(),
cx.tcx.expr_ty(ident2).is_integral()
cx.tcx.tables().expr_ty(ident1).is_integral(),
cx.tcx.tables().expr_ty(ident2).is_integral()
], {
if let BinOp_::BiGt = op.node {
if let BinOp_::BiAdd = op2.node {

View file

@ -91,7 +91,8 @@ impl LateLintPass for PointerPass {
}
fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) {
let fn_ty = cx.tcx.node_id_to_type(fn_id).fn_sig().skip_binder();
let fn_def_id = cx.tcx.map.local_def_id(fn_id);
let fn_ty = cx.tcx.item_type(fn_def_id).fn_sig().skip_binder();
for (arg, ty) in decl.inputs.iter().zip(&fn_ty.inputs) {
if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty {

View file

@ -89,7 +89,7 @@ impl LateLintPass for StepByZero {
fn has_step_by(cx: &LateContext, expr: &Expr) -> bool {
// No need for walk_ptrs_ty here because step_by moves self, so it
// can't be called on a borrowed range.
let ty = cx.tcx.expr_ty(expr);
let ty = cx.tcx.tables().expr_ty(expr);
// Note: `RangeTo`, `RangeToInclusive` and `RangeFull` don't have step_by
match_type(cx, ty, &paths::RANGE)

View file

@ -91,7 +91,7 @@ impl LateLintPass for Pass {
if_let_chain!{[
self.last.is_none(),
let Some(ref expr) = block.expr,
match_type(cx, cx.tcx.expr_ty(expr), &paths::REGEX),
match_type(cx, cx.tcx.tables().expr_ty(expr), &paths::REGEX),
let Some(span) = is_expn_of(cx, expr.span, "regex"),
], {
if !self.spans.contains(&span) {

View file

@ -1,5 +1,5 @@
use rustc::lint::*;
use syntax::ast::*;
use syntax::ast;
use syntax::codemap::{Span, Spanned};
use syntax::visit::FnKind;
@ -45,10 +45,10 @@ pub struct ReturnPass;
impl ReturnPass {
// Check the final stmt or expr in a block for unnecessary return.
fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) {
fn check_block_return(&mut self, cx: &EarlyContext, block: &ast::Block) {
if let Some(stmt) = block.stmts.last() {
match stmt.node {
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => {
ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => {
self.check_final_expr(cx, expr, Some(stmt.span));
}
_ => (),
@ -57,25 +57,25 @@ impl ReturnPass {
}
// Check a the final expression in a block if it's a return.
fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr, span: Option<Span>) {
fn check_final_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr, span: Option<Span>) {
match expr.node {
// simple return is always "bad"
ExprKind::Ret(Some(ref inner)) => {
ast::ExprKind::Ret(Some(ref inner)) => {
self.emit_return_lint(cx, span.expect("`else return` is not possible"), inner.span);
}
// a whole block? check it!
ExprKind::Block(ref block) => {
ast::ExprKind::Block(ref block) => {
self.check_block_return(cx, block);
}
// an if/if let expr, check both exprs
// note, if without else is going to be a type checking error anyways
// (except for unit type functions) so we don't match it
ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => {
ast::ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => {
self.check_block_return(cx, ifblock);
self.check_final_expr(cx, elsexpr, None);
}
// a match expr, check all arms
ExprKind::Match(_, ref arms) => {
ast::ExprKind::Match(_, ref arms) => {
for arm in arms {
self.check_final_expr(cx, &arm.body, Some(arm.body.span));
}
@ -96,18 +96,18 @@ impl ReturnPass {
}
// Check for "let x = EXPR; x"
fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) {
fn check_let_return(&mut self, cx: &EarlyContext, block: &ast::Block) {
let mut it = block.stmts.iter();
// we need both a let-binding stmt and an expr
if_let_chain! {[
let Some(ref retexpr) = it.next_back(),
let StmtKind::Expr(ref retexpr) = retexpr.node,
let ast::StmtKind::Expr(ref retexpr) = retexpr.node,
let Some(stmt) = it.next_back(),
let StmtKind::Local(ref local) = stmt.node,
let ast::StmtKind::Local(ref local) = stmt.node,
let Some(ref initexpr) = local.init,
let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node,
let ExprKind::Path(_, ref path) = retexpr.node,
let ast::PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node,
let ast::ExprKind::Path(_, ref path) = retexpr.node,
match_path_ast(path, &[&id.name.as_str()]),
!in_external_macro(cx, initexpr.span),
], {
@ -129,11 +129,14 @@ impl LintPass for ReturnPass {
}
impl EarlyLintPass for ReturnPass {
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) {
self.check_block_return(cx, block);
fn check_fn(&mut self, cx: &EarlyContext, kind: FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) {
match kind {
FnKind::ItemFn(.., block) | FnKind::Method(.., block) => self.check_block_return(cx, block),
FnKind::Closure(body) => self.check_final_expr(cx, body, None),
}
}
fn check_block(&mut self, cx: &EarlyContext, block: &Block) {
fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) {
self.check_let_return(cx, block);
}
}

View file

@ -81,22 +81,22 @@ impl LintPass for Pass {
}
impl LateLintPass for Pass {
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, block: &Block, _: Span, _: NodeId) {
if in_external_macro(cx, block.span) {
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, expr: &Expr, _: Span, _: NodeId) {
if in_external_macro(cx, expr.span) {
return;
}
check_fn(cx, decl, block);
check_fn(cx, decl, expr);
}
}
fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) {
fn check_fn(cx: &LateContext, decl: &FnDecl, expr: &Expr) {
let mut bindings = Vec::new();
for arg in &decl.inputs {
if let PatKind::Binding(_, ident, _) = arg.pat.node {
bindings.push((ident.node, ident.span))
}
}
check_block(cx, block, &mut bindings);
check_expr(cx, expr, &mut bindings);
}
fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)>) {

View file

@ -114,7 +114,7 @@ impl LateLintPass for StringAdd {
}
fn is_string(cx: &LateContext, e: &Expr) -> bool {
match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(e)), &paths::STRING)
match_type(cx, walk_ptrs_ty(cx.tcx.tables().expr_ty(e)), &paths::STRING)
}
fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool {

View file

@ -85,7 +85,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) {
if let ExprIndex(ref lhs1, ref idx1) = lhs1.node {
if let ExprIndex(ref lhs2, ref idx2) = lhs2.node {
if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) {
let ty = walk_ptrs_ty(cx.tcx.expr_ty(lhs1));
let ty = walk_ptrs_ty(cx.tcx.tables().expr_ty(lhs1));
if matches!(ty.sty, ty::TySlice(_)) ||
matches!(ty.sty, ty::TyArray(_, _)) ||

View file

@ -91,8 +91,8 @@ impl LateLintPass for Transmute {
let def_id = cx.tcx.expect_def(path_expr.id).def_id();
if match_def_path(cx, def_id, &paths::TRANSMUTE) {
let from_ty = cx.tcx.expr_ty(&args[0]);
let to_ty = cx.tcx.expr_ty(e);
let from_ty = cx.tcx.tables().expr_ty(&args[0]);
let to_ty = cx.tcx.tables().expr_ty(e);
match (&from_ty.sty, &to_ty.sty) {
_ if from_ty == to_ty => span_lint(

View file

@ -126,7 +126,7 @@ declare_lint! {
fn check_let_unit(cx: &LateContext, decl: &Decl) {
if let DeclLocal(ref local) = decl.node {
let bindtype = &cx.tcx.pat_ty(&local.pat).sty;
let bindtype = &cx.tcx.tables().pat_ty(&local.pat).sty;
match *bindtype {
ty::TyTuple(slice) if slice.is_empty() => {
if in_external_macro(cx, decl.span) || in_macro(cx, local.pat.span) {
@ -197,7 +197,7 @@ impl LateLintPass for UnitCmp {
if let ExprBinary(ref cmp, ref left, _) = expr.node {
let op = cmp.node;
if op.is_comparison() {
let sty = &cx.tcx.expr_ty(left).sty;
let sty = &cx.tcx.tables().expr_ty(left).sty;
match *sty {
ty::TyTuple(slice) if slice.is_empty() => {
let result = match op {
@ -449,7 +449,7 @@ impl LintPass for CastPass {
impl LateLintPass for CastPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprCast(ref ex, _) = expr.node {
let (cast_from, cast_to) = (cx.tcx.expr_ty(ex), cx.tcx.expr_ty(expr));
let (cast_from, cast_to) = (cx.tcx.tables().expr_ty(ex), cx.tcx.tables().expr_ty(expr));
if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) {
match (cast_from.is_integral(), cast_to.is_integral()) {
(true, false) => {
@ -535,7 +535,7 @@ impl LintPass for TypeComplexityPass {
}
impl LateLintPass for TypeComplexityPass {
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Expr, _: Span, _: NodeId) {
self.check_fndecl(cx, decl);
}
@ -683,7 +683,7 @@ impl LateLintPass for CharLitAsU8 {
if let ExprCast(ref e, _) = expr.node {
if let ExprLit(ref l) = e.node {
if let LitKind::Char(_) = l.node {
if ty::TyUint(UintTy::U8) == cx.tcx.expr_ty(expr).sty && !in_macro(cx, expr.span) {
if ty::TyUint(UintTy::U8) == cx.tcx.tables().expr_ty(expr).sty && !in_macro(cx, expr.span) {
let msg = "casting character literal to u8. `char`s \
are 4 bytes wide in rust, so casting to u8 \
truncates them";
@ -791,7 +791,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
use rustc_const_eval::*;
use types::ExtremeType::*;
let ty = &cx.tcx.expr_ty(expr).sty;
let ty = &cx.tcx.tables().expr_ty(expr).sty;
match *ty {
ty::TyBool | ty::TyInt(_) | ty::TyUint(_) => (),
@ -953,7 +953,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(
use std::*;
if let ExprCast(ref cast_exp, _) = expr.node {
match cx.tcx.expr_ty(cast_exp).sty {
match cx.tcx.tables().expr_ty(cast_exp).sty {
TyInt(int_ty) => {
Some(match int_ty {
IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)),

View file

@ -47,7 +47,7 @@ impl LintPass for UnusedLabel {
}
impl LateLintPass for UnusedLabel {
fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, body: &hir::Block, span: Span, fn_id: ast::NodeId) {
fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, body: &hir::Expr, span: Span, fn_id: ast::NodeId) {
if in_macro(cx, span) {
return;
}

View file

@ -368,11 +368,11 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
self.hash_expr(e);
// TODO: _ty
}
ExprClosure(cap, _, ref b, _) => {
ExprClosure(cap, _, ref e, _) => {
let c: fn(_, _, _, _) -> _ = ExprClosure;
c.hash(&mut self.s);
cap.hash(&mut self.s);
self.hash_block(b);
self.hash_expr(e);
}
ExprField(ref e, ref f) => {
let c: fn(_, _) -> _ = ExprField;

View file

@ -135,7 +135,7 @@ fn has_attr(attrs: &[Attribute]) -> bool {
fn print_decl(cx: &LateContext, decl: &hir::Decl) {
match decl.node {
hir::DeclLocal(ref local) => {
println!("local variable of type {}", cx.tcx.node_id_to_type(local.id));
println!("local variable of type {}", cx.tcx.tables().node_id_to_type(local.id));
println!("pattern:");
print_pat(cx, &local.pat, 0);
if let Some(ref e) = local.init {
@ -149,7 +149,7 @@ fn print_decl(cx: &LateContext, decl: &hir::Decl) {
fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) {
let ind = " ".repeat(indent);
let ty = cx.tcx.node_id_to_type(expr.id);
let ty = cx.tcx.tables().node_id_to_type(expr.id);
println!("{}+", ind);
match expr.node {
hir::ExprBox(ref e) => {
@ -350,25 +350,25 @@ fn print_item(cx: &LateContext, item: &hir::Item) {
}
}
hir::ItemUse(ref path) => println!("{:?}", path.node),
hir::ItemStatic(..) => println!("static item: {:#?}", cx.tcx.opt_lookup_item_type(did)),
hir::ItemConst(..) => println!("const item: {:#?}", cx.tcx.opt_lookup_item_type(did)),
hir::ItemStatic(..) => (), //println!("static item: {:#?}", cx.tcx.opt_lookup_item_type(did)),
hir::ItemConst(..) => (), //println!("const item: {:#?}", cx.tcx.opt_lookup_item_type(did)),
hir::ItemFn(..) => {
let item_ty = cx.tcx.opt_lookup_item_type(did);
println!("function: {:#?}", item_ty);
//let item_ty = cx.tcx.opt_lookup_item_type(did);
//println!("function: {:#?}", item_ty);
},
hir::ItemMod(..) => println!("module"),
hir::ItemForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi),
hir::ItemTy(..) => {
println!("type alias: {:?}", cx.tcx.opt_lookup_item_type(did));
//println!("type alias: {:?}", cx.tcx.opt_lookup_item_type(did));
},
hir::ItemEnum(..) => {
println!("enum definition: {:?}", cx.tcx.opt_lookup_item_type(did));
//println!("enum definition: {:?}", cx.tcx.opt_lookup_item_type(did));
},
hir::ItemStruct(..) => {
println!("struct definition: {:?}", cx.tcx.opt_lookup_item_type(did));
//println!("struct definition: {:?}", cx.tcx.opt_lookup_item_type(did));
},
hir::ItemUnion(..) => {
println!("union definition: {:?}", cx.tcx.opt_lookup_item_type(did));
//println!("union definition: {:?}", cx.tcx.opt_lookup_item_type(did));
},
hir::ItemTrait(..) => {
println!("trait decl");

View file

@ -429,7 +429,12 @@ pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c
if let Some(node) = enclosing_node {
match node {
Node::NodeBlock(block) => Some(block),
Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block),
Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref expr), .. }) => {
match expr.node {
ExprBlock(ref block) => Some(block),
_ => None,
}
}
_ => None,
}
} else {
@ -696,8 +701,9 @@ pub fn camel_case_from(s: &str) -> usize {
/// Convenience function to get the return type of a function
pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> ty::Ty<'tcx> {
let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item);
let fn_sig = cx.tcx.node_id_to_type(fn_item).fn_sig().subst(cx.tcx, parameter_env.free_substs);
let fn_sig = cx.tcx.liberate_late_bound_regions(parameter_env.free_id_outlive, &fn_sig);
let fn_def_id = cx.tcx.map.local_def_id(fn_item);
let fn_sig = cx.tcx.item_type(fn_def_id).fn_sig();
let fn_sig = cx.tcx.liberate_late_bound_regions(parameter_env.free_id_outlive, fn_sig);
fn_sig.output
}

View file

@ -36,7 +36,7 @@ impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
// search for `&vec![_]` expressions where the adjusted type is `&[_]`
if_let_chain!{[
let ty::TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty,
let ty::TypeVariants::TyRef(_, ref ty) = cx.tcx.tables().expr_ty_adjusted(expr).sty,
let ty::TypeVariants::TySlice(..) = ty.ty.sty,
let ExprAddrOf(_, ref addressee) = expr.node,
let Some(vec_args) = higher::vec_macro(cx, addressee),
@ -48,7 +48,7 @@ impl LateLintPass for Pass {
if_let_chain!{[
let Some((_, arg, _)) = higher::for_loop(expr),
let Some(vec_args) = higher::vec_macro(cx, arg),
is_copy(cx, vec_type(cx.tcx.expr_ty_adjusted(arg)), cx.tcx.map.get_parent(expr.id)),
is_copy(cx, vec_type(cx.tcx.tables().expr_ty_adjusted(arg)), cx.tcx.map.get_parent(expr.id)),
], {
// report the error around the `vec!` not inside `<std macros>:`
let span = cx.sess().codemap().source_callsite(arg.span);

View file

@ -1,5 +1,4 @@
#![feature(plugin, inclusive_range_syntax)]
#![feature(dotdot_in_tuple_patterns)]
#![plugin(clippy)]
#![allow(dead_code, no_effect, unnecessary_operation)]

View file

@ -1,6 +1,7 @@
#![feature(plugin, never_type)]
#![plugin(clippy)]
#![deny(diverging_sub_expression)]
#![allow(match_same_arms, logic_bug)]
#[allow(empty_loop)]
fn diverge() -> ! { loop {} }
@ -16,8 +17,6 @@ fn main() {
let b = true;
b || diverge(); //~ ERROR sub-expression diverges
b || A.foo(); //~ ERROR sub-expression diverges
let y = (5, diverge(), 6); //~ ERROR sub-expression diverges
println!("{}", y.1);
}
#[allow(dead_code, unused_variables)]
@ -26,16 +25,16 @@ fn foobar() {
let x = match 5 {
4 => return,
5 => continue,
6 => (println!("foo"), return), //~ ERROR sub-expression diverges
7 => (println!("bar"), continue), //~ ERROR sub-expression diverges
6 => true || return, //~ ERROR sub-expression diverges
7 => true || continue, //~ ERROR sub-expression diverges
8 => break,
9 => diverge(),
3 => (println!("moo"), diverge()), //~ ERROR sub-expression diverges
3 => true || diverge(), //~ ERROR sub-expression diverges
10 => match 42 {
99 => return,
_ => ((), panic!("boo")),
_ => true || panic!("boo"),
},
_ => (println!("boo"), break), //~ ERROR sub-expression diverges
_ => true || break, //~ ERROR sub-expression diverges
};
}
}

View file

@ -43,8 +43,8 @@ fn main() {
true || true; //~ERROR equal expressions
//~|ERROR this boolean expression can be simplified
let a: u32 = unimplemented!();
let b: u32 = unimplemented!();
let a: u32 = 0;
let b: u32 = 0;
a == b && b == a; //~ERROR equal expressions
//~|ERROR this boolean expression can be simplified