mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
fix: Fix concat_bytes!
expansion
This commit is contained in:
parent
143203b713
commit
71337f6682
4 changed files with 61 additions and 7 deletions
|
@ -468,12 +468,12 @@ macro_rules! concat_bytes {}
|
||||||
|
|
||||||
fn main() { concat_bytes!(b'A', b"BC", [68, b'E', 70]); }
|
fn main() { concat_bytes!(b'A', b"BC", [68, b'E', 70]); }
|
||||||
"##,
|
"##,
|
||||||
expect![[r##"
|
expect![[r#"
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
macro_rules! concat_bytes {}
|
macro_rules! concat_bytes {}
|
||||||
|
|
||||||
fn main() { [b'A', 66, 67, 68, b'E', 70]; }
|
fn main() { [b'A', 66, 67, 68, b'E', 70]; }
|
||||||
"##]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1004,3 +1004,29 @@ fn main() {
|
||||||
"##]],
|
"##]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eager_concat_bytes_panic() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! concat_bytes {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = concat_bytes!(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! concat_bytes {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = /* error: unexpected token in input */[];
|
||||||
|
}
|
||||||
|
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use base_db::{
|
||||||
};
|
};
|
||||||
use cfg::CfgExpr;
|
use cfg::CfgExpr;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
|
use itertools::Itertools;
|
||||||
use mbe::{parse_exprs_with_sep, parse_to_token_tree};
|
use mbe::{parse_exprs_with_sep, parse_to_token_tree};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AstToken},
|
ast::{self, AstToken},
|
||||||
|
@ -491,8 +492,25 @@ fn concat_bytes_expand(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let ident = tt::Ident { text: bytes.join(", ").into(), span };
|
let value = tt::Subtree {
|
||||||
ExpandResult { value: quote!(span =>[#ident]), err }
|
delimiter: tt::Delimiter { open: span, close: span, kind: tt::DelimiterKind::Bracket },
|
||||||
|
token_trees: {
|
||||||
|
Itertools::intersperse_with(
|
||||||
|
bytes.into_iter().map(|it| {
|
||||||
|
tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { text: it.into(), span }))
|
||||||
|
}),
|
||||||
|
|| {
|
||||||
|
tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
|
||||||
|
char: ',',
|
||||||
|
spacing: tt::Spacing::Alone,
|
||||||
|
span,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
ExpandResult { value, err }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn concat_bytes_expand_subtree(
|
fn concat_bytes_expand_subtree(
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use stdx::itertools::Itertools;
|
use stdx::{always, itertools::Itertools};
|
||||||
use syntax::{TextRange, TextSize};
|
use syntax::{TextRange, TextSize};
|
||||||
use tt::Span;
|
use tt::Span;
|
||||||
|
|
||||||
|
@ -21,13 +21,23 @@ impl<S: Span> SpanMap<S> {
|
||||||
/// Finalizes the [`SpanMap`], shrinking its backing storage and validating that the offsets are
|
/// Finalizes the [`SpanMap`], shrinking its backing storage and validating that the offsets are
|
||||||
/// in order.
|
/// in order.
|
||||||
pub fn finish(&mut self) {
|
pub fn finish(&mut self) {
|
||||||
assert!(self.spans.iter().tuple_windows().all(|(a, b)| a.0 < b.0));
|
always!(
|
||||||
|
self.spans.iter().tuple_windows().all(|(a, b)| a.0 < b.0),
|
||||||
|
"spans are not in order"
|
||||||
|
);
|
||||||
self.spans.shrink_to_fit();
|
self.spans.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes a new span onto the [`SpanMap`].
|
/// Pushes a new span onto the [`SpanMap`].
|
||||||
pub fn push(&mut self, offset: TextSize, span: S) {
|
pub fn push(&mut self, offset: TextSize, span: S) {
|
||||||
debug_assert!(self.spans.last().map_or(true, |&(last_offset, _)| last_offset < offset));
|
if cfg!(debug_assertions) {
|
||||||
|
if let Some(&(last_offset, _)) = self.spans.last() {
|
||||||
|
assert!(
|
||||||
|
last_offset < offset,
|
||||||
|
"last_offset({last_offset:?}) must be smaller than offset({offset:?})"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
self.spans.push((offset, span));
|
self.spans.push((offset, span));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue