use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::get_parent_expr;
use clippy_utils::higher;
use clippy_utils::source::snippet_block_with_applicability;
use clippy_utils::ty::implements_trait;
-use clippy_utils::{differing_macro_contexts, get_parent_expr};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, Visitor};
if let Some(ex) = &block.expr {
// don't dig into the expression here, just suggest that they remove
// the block
- if expr.span.from_expansion() || differing_macro_contexts(expr.span, ex.span) {
+ if expr.span.from_expansion() || ex.span.from_expansion() {
return;
}
let mut applicability = Applicability::MachineApplicable;
}
} else {
let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
- if span.from_expansion() || differing_macro_contexts(expr.span, span) {
+ if span.from_expansion() || expr.span.from_expansion() {
return;
}
// move block higher
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note};
-use clippy_utils::differing_macro_contexts;
use clippy_utils::source::snippet_opt;
use if_chain::if_chain;
use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
/// Implementation of the `SUSPICIOUS_ASSIGNMENT_FORMATTING` lint.
fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) {
if let ExprKind::Assign(ref lhs, ref rhs, _) = expr.kind {
- if !differing_macro_contexts(lhs.span, rhs.span) && !lhs.span.from_expansion() {
+ if !lhs.span.from_expansion() && !rhs.span.from_expansion() {
let eq_span = lhs.span.between(rhs.span);
if let ExprKind::Unary(op, ref sub_rhs) = rhs.kind {
if let Some(eq_snippet) = snippet_opt(cx, eq_span) {
fn check_unop(cx: &EarlyContext<'_>, expr: &Expr) {
if_chain! {
if let ExprKind::Binary(ref binop, ref lhs, ref rhs) = expr.kind;
- if !differing_macro_contexts(lhs.span, rhs.span) && !lhs.span.from_expansion();
+ if !lhs.span.from_expansion() && !rhs.span.from_expansion();
// span between BinOp LHS and RHS
let binop_span = lhs.span.between(rhs.span);
// if RHS is an UnOp
if_chain! {
if let ExprKind::If(_, then, Some(else_)) = &expr.kind;
if is_block(else_) || is_if(else_);
- if !differing_macro_contexts(then.span, else_.span);
- if !then.span.from_expansion() && !in_external_macro(cx.sess(), expr.span);
+ if !then.span.from_expansion() && !else_.span.from_expansion();
+ if !in_external_macro(cx.sess(), expr.span);
// workaround for rust-lang/rust#43081
if expr.span.lo().0 != 0 && expr.span.hi().0 != 0;
for element in array {
if_chain! {
if let ExprKind::Binary(ref op, ref lhs, _) = element.kind;
- if has_unary_equivalent(op.node) && !differing_macro_contexts(lhs.span, op.span);
+ if has_unary_equivalent(op.node) && lhs.span.ctxt() == op.span.ctxt();
let space_span = lhs.span.between(op.span);
if let Some(space_snippet) = snippet_opt(cx, space_span);
let lint_span = lhs.span.with_lo(lhs.span.hi());
fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) {
if_chain! {
- if !differing_macro_contexts(first.span, second.span);
- if !first.span.from_expansion();
+ if !first.span.from_expansion() && !second.span.from_expansion();
if let ExprKind::If(cond_expr, ..) = &first.kind;
if is_block(second) || is_if(second);
use if_chain::if_chain;
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
-use clippy_utils::differing_macro_contexts;
use clippy_utils::source::{snippet, snippet_opt};
use clippy_utils::ty::is_type_diagnostic_item;
vis.visit_ty(impl_.self_ty);
for target in &vis.found {
- if differing_macro_contexts(item.span, target.span()) {
+ if item.span.ctxt() != target.span().ctxt() {
return;
}
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::differing_macro_contexts;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_copy;
use clippy_utils::ty::is_type_diagnostic_item;
}
}
- if differing_macro_contexts(unwrap_arg.span, map_span) {
+ if unwrap_arg.span.ctxt() != map_span.ctxt() {
return;
}
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{can_mut_borrow_both, differing_macro_contexts, eq_expr_value, std_or_core};
+use clippy_utils::{can_mut_borrow_both, eq_expr_value, std_or_core};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
if_chain! {
if let StmtKind::Semi(first) = w[0].kind;
if let StmtKind::Semi(second) = w[1].kind;
- if !differing_macro_contexts(first.span, second.span);
+ if first.span.ctxt() == second.span.ctxt();
if let ExprKind::Assign(lhs0, rhs0, _) = first.kind;
if let ExprKind::Assign(lhs1, rhs1, _) = second.kind;
if eq_expr_value(cx, lhs0, rhs1);
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{differing_macro_contexts, path_to_local, usage::is_potentially_mutated};
+use clippy_utils::{path_to_local, usage::is_potentially_mutated};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
if let Some(unwrappable) = self.unwrappables.iter()
.find(|u| u.local_id == id);
// Span contexts should not differ with the conditional branch
- if !differing_macro_contexts(unwrappable.branch.span, expr.span);
- if !differing_macro_contexts(unwrappable.branch.span, unwrappable.check.span);
+ let span_ctxt = expr.span.ctxt();
+ if unwrappable.branch.span.ctxt() == span_ctxt;
+ if unwrappable.check.span.ctxt() == span_ctxt;
then {
if call_to_unwrap == unwrappable.safe_to_unwrap {
let is_entire_condition = unwrappable.is_entire_condition;
use crate::consts::{constant_context, constant_simple};
-use crate::differing_macro_contexts;
use crate::source::snippet_opt;
use rustc_ast::ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxHasher;
#[allow(clippy::similar_names)]
pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
- if !self.inner.allow_side_effects && differing_macro_contexts(left.span, right.span) {
+ if !self.inner.allow_side_effects && left.span.ctxt() != right.span.ctxt() {
return false;
}
};
}
-/// Returns `true` if the two spans come from differing expansions (i.e., one is
-/// from a macro and one isn't).
-#[must_use]
-pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
- rhs.ctxt() != lhs.ctxt()
-}
-
/// If the given expression is a local binding, find the initializer expression.
/// If that initializer expression is another local binding, find its initializer again.
/// This process repeats as long as possible (but usually no more than once). Initializer
assert_eq!(in_external_macro(cx.sess(), match_span), true);
```
-- `differing_macro_contexts()`: returns true if the two given spans are not from the same context
+- `span.ctxt()`: the span's context represents whether it is from expansion, and if so, what expanded it
+
+One thing `SpanContext` is useful for is to check if two spans are in the same context. For example,
+in `a == b`, `a` and `b` have the same context. In a `macro_rules!` with `a == $b`, `$b` is expanded to some
+expression with a different context from `a`.
```rust
macro_rules! m {
// These spans are not from the same context
// x.is_some() is from inside the macro
// x.unwrap() is from outside the macro
- assert_eq!(differing_macro_contexts(x_is_some_span, x_unwrap_span), true);
+ assert_eq!(x_is_some_span.ctxt(), x_unwrap_span.ctxt());
```
[TyS]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyS.html