Rollup merge of #144711 - compiler-errors:op-span, r=petrochenkov
Consider operator's span when computing binop expr span When computing the span of a binop consisting of `lhs` and `rhs`, we previously just took the spans of `lhs.span.to(rhs.span)`. In the case that both `lhs` and `rhs` are both arguments to a macro, this can produce a wildly incorrect span. To fix this, first compute the span between `lhs` and the binary operator, which will cause `lhs` to possibly be adjusted to a relevant macro metavar, and then compute that span extended to `rhs`, which will cause it to also be adjusted to a relevant macro metavar. This coincidentally fixes a FIXME in `tests/ui/lint/wide_pointer_comparisons.rs` and suppresses a nonsense suggestion.
This commit is contained in:
commit
edd2574848
4 changed files with 20 additions and 17 deletions
|
|
@ -263,10 +263,11 @@ impl<'a> Parser<'a> {
|
|||
continue;
|
||||
}
|
||||
|
||||
let op_span = op.span;
|
||||
let op = op.node;
|
||||
// Special cases:
|
||||
if op == AssocOp::Cast {
|
||||
lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
|
||||
lhs = self.parse_assoc_op_cast(lhs, lhs_span, op_span, ExprKind::Cast)?;
|
||||
continue;
|
||||
} else if let AssocOp::Range(limits) = op {
|
||||
// If we didn't have to handle `x..`/`x..=`, it would be pretty easy to
|
||||
|
|
@ -284,7 +285,7 @@ impl<'a> Parser<'a> {
|
|||
this.parse_expr_assoc_with(min_prec, attrs)
|
||||
})?;
|
||||
|
||||
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
|
||||
let span = self.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span);
|
||||
lhs = match op {
|
||||
AssocOp::Binary(ast_op) => {
|
||||
let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
|
||||
|
|
@ -429,7 +430,7 @@ impl<'a> Parser<'a> {
|
|||
None
|
||||
};
|
||||
let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
|
||||
let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
|
||||
let span = self.mk_expr_sp(&lhs, lhs.span, cur_op_span, rhs_span);
|
||||
let range = self.mk_range(Some(lhs), rhs, limits);
|
||||
Ok(self.mk_expr(span, range))
|
||||
}
|
||||
|
|
@ -654,10 +655,11 @@ impl<'a> Parser<'a> {
|
|||
&mut self,
|
||||
lhs: P<Expr>,
|
||||
lhs_span: Span,
|
||||
op_span: Span,
|
||||
expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| {
|
||||
this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs))
|
||||
this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span), expr_kind(lhs, rhs))
|
||||
};
|
||||
|
||||
// Save the state of the parser before parsing type normally, in case there is a
|
||||
|
|
@ -4005,11 +4007,12 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Create expression span ensuring the span of the parent node
|
||||
/// is larger than the span of lhs and rhs, including the attributes.
|
||||
fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span {
|
||||
fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, op_span: Span, rhs_span: Span) -> Span {
|
||||
lhs.attrs
|
||||
.iter()
|
||||
.find(|a| a.style == AttrStyle::Outer)
|
||||
.map_or(lhs_span, |a| a.span)
|
||||
.to(op_span)
|
||||
.to(rhs_span)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met
|
|||
res
|
||||
} else {
|
||||
// Example cases:
|
||||
// - `#[foo = 1+1]`: results in `ast::ExprKind::BinOp`.
|
||||
// - `#[foo = 1+1]`: results in `ast::ExprKind::Binary`.
|
||||
// - `#[foo = include_str!("nonexistent-file.rs")]`:
|
||||
// results in `ast::ExprKind::Err`. In that case we delay
|
||||
// the error because an earlier error will have already
|
||||
|
|
|
|||
|
|
@ -146,12 +146,10 @@ fn main() {
|
|||
{
|
||||
macro_rules! cmp {
|
||||
($a:tt, $b:tt) => { $a == $b }
|
||||
//~^ WARN ambiguous wide pointer comparison
|
||||
}
|
||||
|
||||
// FIXME: This lint uses some custom span combination logic.
|
||||
// Rewrite it to adapt to the new metavariable span rules.
|
||||
cmp!(a, b);
|
||||
//~^ WARN ambiguous wide pointer comparison
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -720,18 +720,20 @@ LL + std::ptr::eq(*a, *b)
|
|||
|
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:153:14
|
||||
--> $DIR/wide_pointer_comparisons.rs:148:33
|
||||
|
|
||||
LL | ($a:tt, $b:tt) => { $a == $b }
|
||||
| ^^^^^^^^
|
||||
...
|
||||
LL | cmp!(a, b);
|
||||
| ^^^^
|
||||
| ---------- in this macro invocation
|
||||
|
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | cmp!(std::ptr::addr_eq(a, b));
|
||||
| ++++++++++++++++++ +
|
||||
= help: use explicit `std::ptr::eq` method to compare metadata and addresses
|
||||
= help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
= note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:159:39
|
||||
--> $DIR/wide_pointer_comparisons.rs:157:39
|
||||
|
|
||||
LL | ($a:ident, $b:ident) => { $a == $b }
|
||||
| ^^^^^^^^
|
||||
|
|
@ -747,7 +749,7 @@ LL + ($a:ident, $b:ident) => { std::ptr::addr_eq($a, $b) }
|
|||
|
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:169:37
|
||||
--> $DIR/wide_pointer_comparisons.rs:167:37
|
||||
|
|
||||
LL | ($a:expr, $b:expr) => { $a == $b }
|
||||
| ^^^^^^^^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue