Macro expansion often produces invalid Span
values #23480
Description
The span of many AST node types is pieced together from the spans of the node's children. Here is an example from Parser::parse_more_binops
:
let lhs_span = lhs.span;
let rhs_span = rhs.span;
let binary = self.mk_binary(codemap::respan(cur_op_span, cur_op), lhs, rhs);
let bin = self.mk_expr(lhs_span.lo, rhs_span.hi, binary);
Unfortunately, in the macro expansion phase, this can lead to undesirable results. Consider the following example:
add1!(3);
macro_rules! add1 { ($val:expr) => ( { 1 + $val } ) }
Here lhs
and rhs
come from completely different contexts. lhs_span
comes from the macro-definition-site (lo: 50, hi: 51
) while rhs_span
comes from the expansion-site (lo: 6, hi:7
). Taking lo
from lhs
and hi
from rhs
, as the above code does, we end up with a span of lo: 50, hi: 7
. This value can't be interpreted in any meaningful way.
A similar error can occur for any kind of AST node where a sub-node is located directly at the border of a parent:
// binary operators
$expr + $expr
// unary operators
! $expr
// closures
|x| $expr
// parameters
fn foo($expr: $ty) {}
// type parameters
fn bar<$ident: $ty>
// type ascription
$expr : $type
// C-style enums
enum Foo {
$ident = $expr,
}
// derived types
& &mut $ty
// where clauses
fn baz<T>() where T: $ty {}
// call expressions (?)
$e()
// path expressions (?)
$x::foo()
// ... probably others
This invalid Span
values may lead to strange error messages and caused at least one ICE (#23115).