This commit is contained in:
Tony Garnock-Jones 2023-09-29 09:42:12 +02:00
parent e6bc6d091f
commit dd69d5caaa
3 changed files with 33 additions and 14 deletions

3
Cargo.lock generated
View File

@ -1536,7 +1536,8 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.67"
source = "git+https://github.com/tonyg/proc-macro2?branch=repair_span_start_end#e1af85d3dd6ad595cedc0c344418ab0a60f1ce72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
dependencies = [
"unicode-ident",
]

View File

@ -26,8 +26,8 @@ strip = true
[profile.bench]
debug = true
[patch.crates-io]
# Unfortunately, until [1] is fixed (perhaps via [2]), we have to use a patched proc-macro2.
# [1]: https://github.com/dtolnay/proc-macro2/issues/402
# [2]: https://github.com/dtolnay/proc-macro2/pull/407
proc-macro2 = { git = "https://github.com/tonyg/proc-macro2", branch = "repair_span_start_end" }
# [patch.crates-io]
# # Unfortunately, until [1] is fixed (perhaps via [2]), we have to use a patched proc-macro2.
# # [1]: https://github.com/dtolnay/proc-macro2/issues/402
# # [2]: https://github.com/dtolnay/proc-macro2/pull/407
# proc-macro2 = { git = "https://github.com/tonyg/proc-macro2", branch = "repair_span_start_end" }

View File

@ -1,5 +1,6 @@
use proc_macro2::Delimiter;
use proc_macro2::LineColumn;
use proc_macro2::Span;
use proc_macro2::TokenStream;
use syn::ExprLit;
@ -70,24 +71,41 @@ fn punct_char(c: Cursor) -> Option<(char, Cursor)> {
c.punct().map(|(p, c)| (p.as_char(), c))
}
fn start_pos(s: Span) -> LineColumn {
// We would like to write
// s.start()
// here, but until [1] is fixed (perhaps via [2]), we have to go the unsafe route
// and assume we are in procedural macro context.
// [1]: https://github.com/dtolnay/proc-macro2/issues/402
// [2]: https://github.com/dtolnay/proc-macro2/pull/407
let u = s.unwrap().start();
LineColumn { column: u.column(), line: u.line() }
}
fn end_pos(s: Span) -> LineColumn {
// See start_pos
let u = s.unwrap().end();
LineColumn { column: u.column(), line: u.line() }
}
fn parse_id(mut c: Cursor) -> Result<(String, Cursor)> {
let mut id = String::new();
let mut prev_pos = c.span().start();
let mut prev_pos = start_pos(c.span());
loop {
if c.eof() || c.span().start() != prev_pos {
if c.eof() || start_pos(c.span()) != prev_pos {
return Ok((id, c));
} else if let Some((p, next)) = c.punct() {
match p.as_char() {
'<' | '>' | '(' | ')' | '{' | '}' | '[' | ']' | ',' | ':' => return Ok((id, c)),
ch => {
id.push(ch);
prev_pos = c.span().end();
prev_pos = end_pos(c.span());
c = next;
}
}
} else if let Some((i, next)) = c.ident() {
id.push_str(&i.to_string());
prev_pos = i.span().end();
prev_pos = end_pos(i.span());
c = next;
} else {
return Ok((id, c));
@ -153,7 +171,7 @@ fn parse_kv(c: Cursor) -> Result<((Stx, Stx), Cursor)> {
}
fn adjacent_ident(pos: LineColumn, c: Cursor) -> (Option<Ident>, Cursor) {
if c.span().start() != pos {
if start_pos(c.span()) != pos {
(None, c)
} else if let Some((id, next)) = c.ident() {
(Some(id), next)
@ -177,8 +195,8 @@ fn parse_generic<T: Parse>(mut c: Cursor) -> Option<(T, Cursor)> {
// OK, because parse2 checks for end-of-stream, let's chop
// the input at the position of the error and try again (!).
let mut collected = Vec::new();
let upto = e.span().start();
while !c.eof() && c.span().start() != upto {
let upto = start_pos(e.span());
while !c.eof() && start_pos(c.span()) != upto {
let (tt, next) = c.token_tree().unwrap();
collected.push(tt);
c = next;
@ -200,7 +218,7 @@ fn parse1(c: Cursor) -> Result<(Stx, Cursor)> {
Ok((Stx::Rec(Box::new(q.remove(0)), q), c))
}),
'$' => {
let (maybe_id, next) = adjacent_ident(p.span().end(), next);
let (maybe_id, next) = adjacent_ident(end_pos(p.span()), next);
let (maybe_type, next) = if let Some((':', next)) = punct_char(next) {
match parse_generic::<Type>(next) {
Some((t, next)) => (Some(t), next),