Repository navigation
Tracking issue for proc_macro::Span inspection APIs #54725
Copy link
Copy link
Open
Labels
A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-proc-macrosArea: Procedural macrosArea: Procedural macrosB-unstableBlocker: Implemented in the nightly compiler and unstable.Blocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCI-libs-radarLibs issues that are tracked on the team's radar.Libs issues that are tracked on the team's radar.S-tracking-design-concernsStatus: There are blocking design concerns.Status: There are blocking design concerns.T-langRelevant to the language teamRelevant to the language teamT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Description
This issue is intended to track a number of unstable APIs which are used to inspect the contents of a Span for information like the file name, byte position, manufacturing new spans, combining them, etc.
This issue tracks the proc_macro_span unstable feature.
Public API
Already stabilized:
impl Span {
// as `proc_macro_source_text`
pub fn source_text(&self) -> Option<String>;
// as `proc_macro_span_location`
pub fn start(&self) -> Span;
pub fn end(&self) -> Span;
pub fn line(&self) -> usize;
pub fn column(&self) -> usize;
// as `proc_macro_span_file`
pub fn file(&self) -> String; // Mapped file name, for display purposes.
pub fn local_file(&self) -> Option<PathBuf>; // Real file name as it exists on disk.
}
impl Group {
// as `proc_macro_group_span`
pub fn span_open(&self) -> Span;
pub fn span_close(&self) -> Span;
}Close to stabilization, pending some bikeshedding:
impl Span {
pub fn byte_range(&self) -> Range<usize>;
// Open question: Do we want to use the old or new Range type?
}Things that require more discussion:
impl Span {
pub fn eq(&self, other: &Span) -> bool;
pub fn join(&self, other: Span) -> Option<Span>;
pub fn parent(&self) -> Option<Span>;
pub fn source(&self) -> Span;
}
impl Literal {
pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span>;
}History:
- Implementation
- Stabilization of
proc_macro_source_textStabilize proc_macro::Span::source_text #103197 - Stabilization of
proc_macro_group_spanStabilize span_open() and span_close(). #86136 - Stabilization of
proc_macro_span_locationStabilize proc_macro::Span::{start,end,line,column}. #139865 - Stabilization of
proc_macro_span_fileStabilize proc_macro::Span::{file, local_file}. #140514
Unresolved questions
- API returning ranges should use the new
Rangetype, orimpl RangeBounds
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-proc-macrosArea: Procedural macrosArea: Procedural macrosB-unstableBlocker: Implemented in the nightly compiler and unstable.Blocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCI-libs-radarLibs issues that are tracked on the team's radar.Libs issues that are tracked on the team's radar.S-tracking-design-concernsStatus: There are blocking design concerns.Status: There are blocking design concerns.T-langRelevant to the language teamRelevant to the language teamT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Activity
softprops commentedon Oct 10, 2018
I wanted to shed some pain this is causing with tarpaulin.
Tarpaulin has worked amazingly well for me and my company as a replacement for kcov which historically been a pain to get accurate, reliable and correct results. At the moment tarpaulin stands as the most promising goto option for codecoverage in rust and just feels more like the only first class tooling option.
Having one of those when choosing to invest in a technology is important for many company's adoption story for checking off code quantity checkmarks. When they see that rust doesn't have a reasonable code quality story that works on stable rust, that's can result in a "pass" rather than "I'll take it". There are currently some work arounds for making this work-ish on stable but it feels very much like the story serde was in a year or so ago when you wanted to show all your friends how amazing serde was but then was embarrassed to show what it took to make work on stable because of a macro stabilization blocker.
JakeTherston commentedon Oct 28, 2018
With procedural macros having reached a point where they're very useful on stable, I expect many users will find themselves needing access to this information. Would it be reasonable to only stabilize parts of the
SpanAPI that are not too risky? Perhaps exposing a function that optionally returns the path of the file where a macro is invoked if such a file exists?Drop dependency on #![feature(proc_macro_span)]
matklad commentedon Feb 1, 2019
I have a concern about exposing
LineColuminformation. It looks like it could play badly with incremental compilation, especially in the IDE context.My understanding is that, if one adds a blank line to the start of the file, the line_column information of the input spans to proc macro changes. That means that IDE would have to re-expand procedural macros even after insignificant white space changes.
I would feel more confident if proc-macros were strictly a pure function from the input token stream to output token stream. This can be achieved, for example, by making line-column infocation relative to the start of macro invocation (as opposed to relative to the start of the file).
I don't feel that exposing absolute position is necessary the end of the world: IDE can track if a macro actually makes use of the info, or it can supply macro with some fake line/columns. But it's hard to tell if such hacks would work well in practice, and it's hard to experiment with them for the lack of IDE which handled proc-macros incrementally....
davidlattimore commentedon Feb 2, 2019
If the parser allocated IDs to every AST node, then, and this is the hard part, when an edit was made to the source, the parser tried to keep those IDs the same in all the non-edited code and only allocate new IDs for new nodes, that would allow spans to be kept completely separate from the AST. Those IDs could be passed through macro expansion without causing unnecessary invalidations. If something needed a span later on, it could then go back and ask the parser for the span for that particular AST node ID. I feel like having an incremental parser is important, not because parsing is the bottleneck, but because it underpins everything else.
matklad commentedon Feb 2, 2019
@davidlattimore this is fascinating, but slightly off-topic for the issue. I've created a thread on internals: https://internals.rust-lang.org/t/macros-vs-incremental-parsing/9323
est31 commentedon May 30, 2019
The column!() macro as well as std::panic::Location::column are returning 1-based columns while the span available from the proc-macro crate is 0-based according to its docs. Is this inconsistency intended?
est31 commentedon May 30, 2019
This thread has more discussion about 1-based columns: #46762 (comment)
166 remaining items
Rollup merge of rust-lang#139865 - m-ou-se:stabilize-proc-macro-span-…
fix: swap Span::source_file -> Span::file
fix: swap Span::source_file -> Span::file
Auto merge of #140514 - m-ou-se:proc-macro-span-file, r=Amanieu
Auto merge of rust-lang#140514 - m-ou-se:proc-macro-span-file, r=Amanieu
Auto merge of #140514 - m-ou-se:proc-macro-span-file, r=Amanieu
VictorArcium commentedon Jul 19, 2025
This should be updated now that
proc_macro_span_filehas been stabilized (in 1.88).andrewdavidmackenzie commentedon Jul 19, 2025
I hadn't noticed that had been stabalized - so thanks.
I was able to move my project (finally!) to stable.
Bee4Queer commentedon Oct 30, 2025
What's the status of the
joinmethod? In other words, what still needs to be discussed about it?rust: proc-macro2: enable `proc_macro_span` feature
rust: proc-macro2: enable `proc_macro_span` feature
clarfonthey commentedon Oct 20, 2026
Worth mentioning here as it came up with #164645: if
Span::byte_offsetis stabilized, it may be prudent to stabilize some form ofbyte_offset!()macro equivalent for libstd.rust: proc-macro2: enable `proc_macro_span` feature