Skip to content

Commit 000e907

Browse files
committed
Span::resolved_at and Span::located_at to combine behavior of two spans
Proc macro spans serve two mostly unrelated purposes: controlling name resolution and controlling error messages. It can be useful to mix the name resolution behavior of one span with the line/column error message locations of a different span. In particular, consider the case of a trait brought into scope within the def_site of a custom derive. I want to invoke trait methods on the fields of the user's struct. If the field type does not implement the right trait, I want the error message to underline the corresponding struct field. Generating the method call with the def_site span is not ideal -- it compiles and runs but error messages sadly always point to the derive attribute like we saw with Macros 1.1. ``` | 4 | #[derive(HeapSize)] | ^^^^^^^^ ``` Generating the method call with the same span as the struct field's ident or type is not correct -- it shows the right underlines but fails to resolve to the trait in scope at the def_site. ``` | 7 | bad: std::thread::Thread, | ^^^^^^^^^^^^^^^^^^^^^^^^ ``` The correct span for the method call is one that combines the def_site's name resolution with the struct field's line/column. ``` field.span.resolved_at(Span::def_site()) // equivalently Span::def_site().located_at(field.span) ``` Adding both because which one is more natural will depend on context.
1 parent 0f4ebf9 commit 000e907

File tree

1 file changed

+14
-0
lines changed

1 file changed

+14
-0
lines changed

src/libproc_macro/lib.rs

+14
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,20 @@ impl Span {
254254
Some(Span(self.0.to(other.0)))
255255
}
256256

257+
/// Creates a new span with the same line/column information as `self` but
258+
/// that resolves symbols as though it were at `other`.
259+
#[unstable(feature = "proc_macro", issue = "38356")]
260+
pub fn resolved_at(&self, other: Span) -> Span {
261+
Span(self.0.with_ctxt(other.0.ctxt()))
262+
}
263+
264+
/// Creates a new span with the same name resolution behavior as `self` but
265+
/// with the line/column information of `other`.
266+
#[unstable(feature = "proc_macro", issue = "38356")]
267+
pub fn located_at(&self, other: Span) -> Span {
268+
other.resolved_at(*self)
269+
}
270+
257271
diagnostic_method!(error, Level::Error);
258272
diagnostic_method!(warning, Level::Warning);
259273
diagnostic_method!(note, Level::Note);

0 commit comments

Comments
 (0)