Comments (5)
Hi, @dtolnay Thank for you great work. I am trying to use proc_macro2 to parse the css content in the project I am working on. You can find it here.
The Problem
- Based on this documentation span.start() and span.end() should work on both inside proc_macro context and outside proc_macro context in the nightly version of the rust. This is is working as expected in the outside proc_macro context.
- The problem is the values are always 0 inside the proc_macro context.
This is the piece of code I am trying to use in both scenarios.
pub(crate) fn add_spaces( source: &mut String, span: proc_macro2::Span, pre_line: &mut usize, pre_col: &mut usize, ) { let start = span.start(); let end = span.end(); let cur_col = start.column; let cur_line = start.line; if *pre_line == cur_line && cur_col > *pre_col { source.push(' '); } *pre_col = end.column; *pre_line = end.line; }
Current Solution:
To resolve this problem I temporarily used following approach. The problem was the proc_macro2::span.start().column was not working inside proc_macro scope but it was working fine for normal(outside proc_macro scope) use cases. Also I can't use proc_macro::span.unwrap().start().column() outside proc_macro scope. So I conditionally switched between these two cases based on the function input attribute is_proc_macro: bool
. This resolved the problem for me. Now I can use this utility both inside and outside proc_macro scope. You can find the crate here.
pub(crate) fn add_spaces(
source: &mut String,
span: proc_macro2::Span,
pre_line: &mut usize,
pre_col: &mut usize,
is_proc_macro: bool,
) {
let mut start_col = span.start().column;
let mut start_line = span.start().line;
let mut end_col = span.end().column;
let mut end_line = span.end().line;
if is_proc_macro {
start_col = span.unwrap().start().column();
start_line = span.unwrap().start().line();
end_col = span.unwrap().end().column();
end_line = span.unwrap().end().line();
}
let cur_col = start_col;
let cur_line = start_line;
if *pre_line == cur_line && cur_col > *pre_col {
source.push(' ');
}
*pre_col = end_col;
*pre_line = end_line;
}
note: you have to add #![feature(proc_macro_span)]
in the top you lib.rs file to use span.unwrap()
from proc-macro2.
I have this problem too. I'm bisecting now. (I'm afraid I have to use nightly rather than stable for other reasons, so the bisection will be in terms of nightlies.)
- broken: rustc 1.74.0-nightly (5ae769f06 2023-09-26), proc_macro2 1.0.67
- working: rustc 1.71.0-nightly (7f94b314c 2023-04-23), proc_macro2 1.0.56
Version 1.0.56 doesn't build with 1.74.0, but luckily 1.0.67 builds with 1.71.0, and yields the broken results, so I'll stick with that and see where I get.
It looks like the change from 1.0.56 to 1.0.57 is where the breakage appears, at least for me!
Oh. Sure enough, from 1.0.57 and on to the current main revision, we have in wrapper.rs
#[cfg(span_locations)]
pub fn start(&self) -> LineColumn {
match self {
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
Span::Fallback(s) => s.start(),
}
}
Presumably this is because LineColumn
no longer exists in proc_macro
! This will have changed somewhere between 1.71.0-nightly and the current nightlies.
However, there are separate line()
and column()
functions. Patching proc_macro2 with the following implementations seems to work fine for my little tests so far:
#[cfg(span_locations)]
pub fn start(&self) -> LineColumn {
match self {
#[cfg(proc_macro_span)]
Span::Compiler(s) => LineColumn {
line: s.line(),
column: s.column(),
},
#[cfg(not(proc_macro_span))]
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
Span::Fallback(s) => s.start(),
}
}
#[cfg(span_locations)]
pub fn end(&self) -> LineColumn {
match self {
#[cfg(proc_macro_span)]
Span::Compiler(s) => LineColumn {
line: s.end().line(),
column: s.end().column(),
},
#[cfg(not(proc_macro_span))]
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
Span::Fallback(s) => s.end(),
}
Now, how to fix this properly? Easiest would be to alter proc_macro2 to include the implementations just above. However then proc_macro2 wouldn't be usable with older versions of the toolchain. Is that a problem (@dtolnay?)?
An alternative would be to expose line() and column() as new methods on Spans (with some kind of end().line() and end().column()), following the proc_macro approach. @dtolnay, your thoughts here would be very welcome.
from proc-macro2.
^ Here's the tiny crate I've been using to explore the problem.
Buggy rm -rf target; cargo build --example exercise
output:
Compiling proc-macro2 v1.0.67
Compiling unicode-ident v1.0.12
Compiling macro-provider v0.0.0 (/home/tonyg/src/span_start_bug)
SPAN START: LineColumn { line: 0, column: 0 } END: LineColumn { line: 0, column: 0 }
SPAN START: LineColumn { line: 0, column: 0 } END: LineColumn { line: 0, column: 0 }
SPAN START: LineColumn { line: 0, column: 0 } END: LineColumn { line: 0, column: 0 }
SPAN START: LineColumn { line: 0, column: 0 } END: LineColumn { line: 0, column: 0 }
SPAN START: LineColumn { line: 0, column: 0 } END: LineColumn { line: 0, column: 0 }
Finished dev [unoptimized + debuginfo] target(s) in 1.18s
Correct output:
Compiling proc-macro2 v1.0.67 (/home/tonyg/src/span_start_bug/scratch/proc-macro2)
Compiling unicode-ident v1.0.12
Compiling macro-provider v0.0.0 (/home/tonyg/src/span_start_bug)
SPAN START: LineColumn { line: 2, column: 40 } END: LineColumn { line: 2, column: 41 }
SPAN START: LineColumn { line: 2, column: 42 } END: LineColumn { line: 2, column: 43 }
SPAN START: LineColumn { line: 2, column: 44 } END: LineColumn { line: 2, column: 45 }
SPAN START: LineColumn { line: 2, column: 46 } END: LineColumn { line: 2, column: 47 }
SPAN START: LineColumn { line: 2, column: 48 } END: LineColumn { line: 2, column: 49 }
Finished dev [unoptimized + debuginfo] target(s) in 1.28s
from proc-macro2.
Unfortunately I wonder if this is going to be hard to write a test case for since it involves running in proc_macro context? There are existing test cases that check column/line values, but since they pass, presumably they use the Fallback
.
from proc-macro2.
(Here's the commit where the code for retrieving the LineColumn from proc_macro was removed: 5f9d3fe)
from proc-macro2.
Related Issues (20)
- `Span::source_text` panics with multibyte source HOT 1
- Issue with multibyte chars in source_text() computation HOT 1
- Consider recalibrating how bits are divided in Span HOT 3
- Consider an API to reset thread-local Span data HOT 2
- Make `proc_macro_span` optional with nightly HOT 4
- Enhance documentation with examples.
- panic in fallback.rs:817 HOT 3
- Build script fails when compiling with target-feature=+avx512bw HOT 2
- Linking failed after updating to 1.0.76 HOT 2
- Provide an API to access byte offsets for Spans
- Not compatible with 1.66-nightly HOT 2
- cannot find struct, variant or union type `LineColumn` in crate `proc_macro` HOT 1
- arm64-linux build error HOT 1
- bug?: Build script fails without `strip = "symbols"` HOT 1
- Missed nightly feature `proc_macro_byte_character` HOT 6
- Unsure if 100% the reason: Cargo Build issue for Arduino Uno (MCU= ATmega238p) HOT 3
- Help with debugging build command error HOT 1
- Looking for forks that make `proc_macro::Span` Send + Sync HOT 2
- Tokenize text with unbalanced delimiters HOT 2
- newly added test_size::test_proc_macro2_wrapper_size_without_locations test fails on i686 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from proc-macro2.