Bump to 0.0.139
This commit is contained in:
@@ -385,9 +385,11 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
|||||||
e.span,
|
e.span,
|
||||||
"this boolean expression can be simplified",
|
"this boolean expression can be simplified",
|
||||||
|db| {
|
|db| {
|
||||||
db.span_suggestions(e.span, "try", improvements.into_iter().map(|suggestion| {
|
db.span_suggestions(e.span,
|
||||||
suggest(self.cx, suggestion, &h2q.terminals)
|
"try",
|
||||||
}).collect());
|
improvements.into_iter()
|
||||||
|
.map(|suggestion| suggest(self.cx, suggestion, &h2q.terminals))
|
||||||
|
.collect());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,11 +252,7 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
|
|||||||
|
|
||||||
/// Return the list of bindings in a pattern.
|
/// Return the list of bindings in a pattern.
|
||||||
fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, Ty<'tcx>> {
|
fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<InternedString, Ty<'tcx>> {
|
||||||
fn bindings_impl<'a, 'tcx>(
|
fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap<InternedString, Ty<'tcx>>) {
|
||||||
cx: &LateContext<'a, 'tcx>,
|
|
||||||
pat: &Pat,
|
|
||||||
map: &mut HashMap<InternedString, Ty<'tcx>>
|
|
||||||
) {
|
|
||||||
match pat.node {
|
match pat.node {
|
||||||
PatKind::Box(ref pat) |
|
PatKind::Box(ref pat) |
|
||||||
PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map),
|
PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map),
|
||||||
|
|||||||
@@ -98,17 +98,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||||||
let rsnip = snippet(cx, r.span, "...").to_string();
|
let rsnip = snippet(cx, r.span, "...").to_string();
|
||||||
multispan_sugg(db,
|
multispan_sugg(db,
|
||||||
"use the values directly".to_string(),
|
"use the values directly".to_string(),
|
||||||
vec![(left.span, lsnip),
|
vec![(left.span, lsnip), (right.span, rsnip)]);
|
||||||
(right.span, rsnip)]);
|
|
||||||
})
|
})
|
||||||
} else if lcpy && !rcpy &&
|
} else if lcpy && !rcpy && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)]) {
|
||||||
implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)]) {
|
|
||||||
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
|
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
|
||||||
let lsnip = snippet(cx, l.span, "...").to_string();
|
let lsnip = snippet(cx, l.span, "...").to_string();
|
||||||
db.span_suggestion(left.span, "use the left value directly", lsnip);
|
db.span_suggestion(left.span, "use the left value directly", lsnip);
|
||||||
})
|
})
|
||||||
} else if !lcpy && rcpy &&
|
} else if !lcpy && rcpy && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty]) {
|
||||||
implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty]) {
|
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
OP_REF,
|
OP_REF,
|
||||||
e.span,
|
e.span,
|
||||||
@@ -123,8 +120,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||||||
(&ExprAddrOf(_, ref l), _) => {
|
(&ExprAddrOf(_, ref l), _) => {
|
||||||
let lty = cx.tables.expr_ty(l);
|
let lty = cx.tables.expr_ty(l);
|
||||||
let lcpy = is_copy(cx, lty);
|
let lcpy = is_copy(cx, lty);
|
||||||
if (requires_ref || lcpy) &&
|
if (requires_ref || lcpy) && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)]) {
|
||||||
implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)]) {
|
|
||||||
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
|
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
|
||||||
let lsnip = snippet(cx, l.span, "...").to_string();
|
let lsnip = snippet(cx, l.span, "...").to_string();
|
||||||
db.span_suggestion(left.span, "use the left value directly", lsnip);
|
db.span_suggestion(left.span, "use the left value directly", lsnip);
|
||||||
@@ -135,8 +131,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
|
|||||||
(_, &ExprAddrOf(_, ref r)) => {
|
(_, &ExprAddrOf(_, ref r)) => {
|
||||||
let rty = cx.tables.expr_ty(r);
|
let rty = cx.tables.expr_ty(r);
|
||||||
let rcpy = is_copy(cx, rty);
|
let rcpy = is_copy(cx, rty);
|
||||||
if (requires_ref || rcpy) &&
|
if (requires_ref || rcpy) && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty]) {
|
||||||
implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty]) {
|
|
||||||
span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| {
|
span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| {
|
||||||
let rsnip = snippet(cx, r.span, "...").to_string();
|
let rsnip = snippet(cx, r.span, "...").to_string();
|
||||||
db.span_suggestion(right.span, "use the right value directly", rsnip);
|
db.span_suggestion(right.span, "use the right value directly", rsnip);
|
||||||
|
|||||||
@@ -71,8 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let region_maps = &cx.tcx.region_maps(fn_def_id);
|
let region_maps = &cx.tcx.region_maps(fn_def_id);
|
||||||
ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_maps, cx.tables)
|
ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_maps, cx.tables).consume_body(body);
|
||||||
.consume_body(body);
|
|
||||||
|
|
||||||
for node in v.set {
|
for node in v.set {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
@@ -134,15 +133,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
fn borrow(
|
fn borrow(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, loan_cause: LoanCause) {
|
||||||
&mut self,
|
|
||||||
_: NodeId,
|
|
||||||
_: Span,
|
|
||||||
cmt: cmt<'tcx>,
|
|
||||||
_: ty::Region,
|
|
||||||
_: ty::BorrowKind,
|
|
||||||
loan_cause: LoanCause
|
|
||||||
) {
|
|
||||||
if let Categorization::Local(lid) = cmt.cat {
|
if let Categorization::Local(lid) = cmt.cat {
|
||||||
match loan_cause {
|
match loan_cause {
|
||||||
// x.foo()
|
// x.foo()
|
||||||
|
|||||||
@@ -58,14 +58,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(cast_possible_wrap)]
|
||||||
fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) {
|
fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) {
|
||||||
if let Some(Constant::Int(v)) = constant_simple(cx, e) {
|
if let Some(Constant::Int(v)) = constant_simple(cx, e) {
|
||||||
if match m {
|
if match m {
|
||||||
0 => v.to_u128_unchecked() == 0,
|
0 => v.to_u128_unchecked() == 0,
|
||||||
-1 => match v.int_type() {
|
-1 => {
|
||||||
SignedInt(_) => #[allow(cast_possible_wrap)] (v.to_u128_unchecked() as i128 == -1),
|
match v.int_type() {
|
||||||
UnsignedInt(_) => false
|
SignedInt(_) => (v.to_u128_unchecked() as i128 == -1),
|
||||||
|
UnsignedInt(_) => false,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
1 => v.to_u128_unchecked() == 1,
|
1 => v.to_u128_unchecked() == 1,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ use rustc::lint::*;
|
|||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use utils::{is_adjusted, match_path, match_trait_method, match_type, remove_blocks, paths, snippet, span_help_and_lint,
|
use utils::{is_adjusted, match_path, match_trait_method, match_type, remove_blocks, paths, snippet,
|
||||||
walk_ptrs_ty, walk_ptrs_ty_depth, iter_input_pats};
|
span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, iter_input_pats};
|
||||||
|
|
||||||
/// **What it does:** Checks for mapping `clone()` over an iterator.
|
/// **What it does:** Checks for mapping `clone()` over an iterator.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -226,14 +226,7 @@ fn report_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm],
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_single_match_opt_like(
|
fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: Ty, els: Option<&Expr>) {
|
||||||
cx: &LateContext,
|
|
||||||
ex: &Expr,
|
|
||||||
arms: &[Arm],
|
|
||||||
expr: &Expr,
|
|
||||||
ty: Ty,
|
|
||||||
els: Option<&Expr>
|
|
||||||
) {
|
|
||||||
// list of candidate Enums we know will never get any more members
|
// list of candidate Enums we know will never get any more members
|
||||||
let candidates = &[(&paths::COW, "Borrowed"),
|
let candidates = &[(&paths::COW, "Borrowed"),
|
||||||
(&paths::COW, "Cow::Borrowed"),
|
(&paths::COW, "Cow::Borrowed"),
|
||||||
|
|||||||
@@ -1351,7 +1351,14 @@ enum SelfKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SelfKind {
|
impl SelfKind {
|
||||||
fn matches(self, ty: &hir::Ty, arg: &hir::Arg, self_ty: &hir::Ty, allow_value_for_ref: bool, generics: &hir::Generics) -> bool {
|
fn matches(
|
||||||
|
self,
|
||||||
|
ty: &hir::Ty,
|
||||||
|
arg: &hir::Arg,
|
||||||
|
self_ty: &hir::Ty,
|
||||||
|
allow_value_for_ref: bool,
|
||||||
|
generics: &hir::Generics
|
||||||
|
) -> bool {
|
||||||
// Self types in the HIR are desugared to explicit self types. So it will always be `self:
|
// Self types in the HIR are desugared to explicit self types. So it will always be `self:
|
||||||
// SomeType`,
|
// SomeType`,
|
||||||
// where SomeType can be `Self` or an explicit impl self type (e.g. `Foo` if the impl is on `Foo`)
|
// where SomeType can be `Self` or an explicit impl self type (e.g. `Foo` if the impl is on `Foo`)
|
||||||
@@ -1386,7 +1393,7 @@ impl SelfKind {
|
|||||||
SelfKind::Value => false,
|
SelfKind::Value => false,
|
||||||
SelfKind::Ref => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASREF_TRAIT),
|
SelfKind::Ref => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASREF_TRAIT),
|
||||||
SelfKind::RefMut => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASMUT_TRAIT),
|
SelfKind::RefMut => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASMUT_TRAIT),
|
||||||
SelfKind::No => true
|
SelfKind::No => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1404,19 +1411,18 @@ impl SelfKind {
|
|||||||
fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool {
|
fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool {
|
||||||
single_segment_ty(ty).map_or(false, |seg| {
|
single_segment_ty(ty).map_or(false, |seg| {
|
||||||
generics.ty_params.iter().any(|param| {
|
generics.ty_params.iter().any(|param| {
|
||||||
param.name == seg.name && param.bounds.iter().any(|bound| {
|
param.name == seg.name &&
|
||||||
if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound {
|
param.bounds.iter().any(|bound| if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound {
|
||||||
let path = &ptr.trait_ref.path;
|
let path = &ptr.trait_ref.path;
|
||||||
match_path_old(path, name) && path.segments.last().map_or(false, |s| {
|
match_path_old(path, name) &&
|
||||||
if let hir::PathParameters::AngleBracketedParameters(ref data) = s.parameters {
|
path.segments.last().map_or(false, |s| if let hir::PathParameters::AngleBracketedParameters(ref data) =
|
||||||
|
s.parameters {
|
||||||
data.types.len() == 1 && (is_self_ty(&data.types[0]) || is_ty(&*data.types[0], self_ty))
|
data.types.len() == 1 && (is_self_ty(&data.types[0]) || is_ty(&*data.types[0], self_ty))
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -1426,10 +1432,9 @@ fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool {
|
|||||||
match (&ty.node, &self_ty.node) {
|
match (&ty.node, &self_ty.node) {
|
||||||
(&hir::TyPath(hir::QPath::Resolved(_, ref ty_path)),
|
(&hir::TyPath(hir::QPath::Resolved(_, ref ty_path)),
|
||||||
&hir::TyPath(hir::QPath::Resolved(_, ref self_ty_path))) => {
|
&hir::TyPath(hir::QPath::Resolved(_, ref self_ty_path))) => {
|
||||||
ty_path.segments.iter().map(|seg| seg.name).eq(
|
ty_path.segments.iter().map(|seg| seg.name).eq(self_ty_path.segments.iter().map(|seg| seg.name))
|
||||||
self_ty_path.segments.iter().map(|seg| seg.name))
|
},
|
||||||
}
|
_ => false,
|
||||||
_ => false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -516,7 +516,9 @@ fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool {
|
|||||||
match *def {
|
match *def {
|
||||||
def::Def::Local(def_id) |
|
def::Def::Local(def_id) |
|
||||||
def::Def::Upvar(def_id, _, _) => {
|
def::Def::Upvar(def_id, _, _) => {
|
||||||
let id = cx.tcx.hir.as_local_node_id(def_id)
|
let id = cx.tcx
|
||||||
|
.hir
|
||||||
|
.as_local_node_id(def_id)
|
||||||
.expect("local variables should be found in the same crate");
|
.expect("local variables should be found in the same crate");
|
||||||
!in_macro(cx.tcx.hir.span(id))
|
!in_macro(cx.tcx.hir.span(id))
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -91,8 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
|
|||||||
let MovedVariablesCtxt { moved_vars, spans_need_deref, .. } = {
|
let MovedVariablesCtxt { moved_vars, spans_need_deref, .. } = {
|
||||||
let mut ctx = MovedVariablesCtxt::new(cx);
|
let mut ctx = MovedVariablesCtxt::new(cx);
|
||||||
let region_maps = &cx.tcx.region_maps(fn_def_id);
|
let region_maps = &cx.tcx.region_maps(fn_def_id);
|
||||||
euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_maps, cx.tables)
|
euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_maps, cx.tables).consume_body(body);
|
||||||
.consume_body(body);
|
|
||||||
ctx
|
ctx
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1107,6 +1107,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(cast_possible_wrap)]
|
||||||
fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> {
|
fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> {
|
||||||
use rustc::middle::const_val::ConstVal::*;
|
use rustc::middle::const_val::ConstVal::*;
|
||||||
use rustc_const_eval::ConstContext;
|
use rustc_const_eval::ConstContext;
|
||||||
@@ -1115,7 +1116,7 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option<FullInt> {
|
|||||||
Ok(val) => {
|
Ok(val) => {
|
||||||
if let Integral(const_int) = val {
|
if let Integral(const_int) = val {
|
||||||
match const_int.int_type() {
|
match const_int.int_type() {
|
||||||
IntType::SignedInt(_) => #[allow(cast_possible_wrap)] Some(FullInt::S(const_int.to_u128_unchecked() as i128)),
|
IntType::SignedInt(_) => Some(FullInt::S(const_int.to_u128_unchecked() as i128)),
|
||||||
IntType::UnsignedInt(_) => Some(FullInt::U(const_int.to_u128_unchecked())),
|
IntType::UnsignedInt(_) => Some(FullInt::U(const_int.to_u128_unchecked())),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -76,8 +76,7 @@ pub fn range(expr: &hir::Expr) -> Option<Range> {
|
|||||||
end: None,
|
end: None,
|
||||||
limits: ast::RangeLimits::HalfOpen,
|
limits: ast::RangeLimits::HalfOpen,
|
||||||
})
|
})
|
||||||
} else if match_path(path, &paths::RANGE_INCLUSIVE_STD) ||
|
} else if match_path(path, &paths::RANGE_INCLUSIVE_STD) || match_path(path, &paths::RANGE_INCLUSIVE) {
|
||||||
match_path(path, &paths::RANGE_INCLUSIVE) {
|
|
||||||
Some(Range {
|
Some(Range {
|
||||||
start: get_field("start", fields),
|
start: get_field("start", fields),
|
||||||
end: get_field("end", fields),
|
end: get_field("end", fields),
|
||||||
|
|||||||
@@ -314,11 +314,11 @@ pub fn implements_trait<'a, 'tcx>(
|
|||||||
ty_params: &[Ty<'tcx>]
|
ty_params: &[Ty<'tcx>]
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let ty = cx.tcx.erase_regions(&ty);
|
let ty = cx.tcx.erase_regions(&ty);
|
||||||
let obligation = cx.tcx.predicate_for_trait_def(
|
let obligation = cx.tcx
|
||||||
cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params);
|
.predicate_for_trait_def(cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params);
|
||||||
cx.tcx.infer_ctxt().enter(|infcx| {
|
cx.tcx
|
||||||
traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation)
|
.infer_ctxt()
|
||||||
})
|
.enter(|infcx| traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve the definition of a node from its `NodeId`.
|
/// Resolve the definition of a node from its `NodeId`.
|
||||||
@@ -575,7 +575,14 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>(
|
|||||||
/// replacement. In human-readable format though, it only appears once before the whole suggestion.
|
/// replacement. In human-readable format though, it only appears once before the whole suggestion.
|
||||||
pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: Vec<(Span, String)>) {
|
pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: Vec<(Span, String)>) {
|
||||||
let sugg = rustc_errors::CodeSuggestion {
|
let sugg = rustc_errors::CodeSuggestion {
|
||||||
substitution_parts: sugg.into_iter().map(|(span, sub)| rustc_errors::Substitution { span, substitutions: vec![sub] }).collect(),
|
substitution_parts: sugg.into_iter()
|
||||||
|
.map(|(span, sub)| {
|
||||||
|
rustc_errors::Substitution {
|
||||||
|
span: span,
|
||||||
|
substitutions: vec![sub],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
msg: help_msg,
|
msg: help_msg,
|
||||||
};
|
};
|
||||||
db.suggestions.push(sugg);
|
db.suggestions.push(sugg);
|
||||||
@@ -764,14 +771,8 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Ty<'t
|
|||||||
/// Check if two types are the same.
|
/// Check if two types are the same.
|
||||||
// FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for <'b> Foo<'b>` but
|
// FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for <'b> Foo<'b>` but
|
||||||
// not for type parameters.
|
// not for type parameters.
|
||||||
pub fn same_tys<'a, 'tcx>(
|
pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
|
||||||
cx: &LateContext<'a, 'tcx>,
|
cx.tcx.infer_ctxt().enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok())
|
||||||
a: Ty<'tcx>,
|
|
||||||
b: Ty<'tcx>
|
|
||||||
) -> bool {
|
|
||||||
cx.tcx.infer_ctxt().enter(|infcx| {
|
|
||||||
infcx.can_eq(cx.param_env, a, b).is_ok()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return whether the given type is an `unsafe` function.
|
/// Return whether the given type is an `unsafe` function.
|
||||||
|
|||||||
Reference in New Issue
Block a user