mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-28 10:39:45 +00:00
Merge pull request #20000 from tadeokondrak/lifetime-repeat-macro
Some checks failed
metrics / build_metrics (push) Waiting to run
metrics / other_metrics (diesel-1.4.8) (push) Blocked by required conditions
metrics / other_metrics (hyper-0.14.18) (push) Blocked by required conditions
metrics / other_metrics (ripgrep-13.0.0) (push) Blocked by required conditions
metrics / other_metrics (self) (push) Blocked by required conditions
metrics / other_metrics (webrender-2022) (push) Blocked by required conditions
metrics / generate_final_metrics (push) Blocked by required conditions
rustdoc / rustdoc (push) Waiting to run
autopublish / publish (push) Has been cancelled
release / dist (aarch64-apple-darwin) (push) Has been cancelled
release / dist (x86_64-apple-darwin) (push) Has been cancelled
release / dist (aarch64-unknown-linux-gnu) (push) Has been cancelled
release / dist (arm-unknown-linux-gnueabihf) (push) Has been cancelled
release / dist (x86_64-unknown-linux-gnu) (push) Has been cancelled
release / dist (aarch64-pc-windows-msvc) (push) Has been cancelled
release / dist (x86_64-pc-windows-msvc) (push) Has been cancelled
release / dist (i686-pc-windows-msvc) (push) Has been cancelled
release / dist (x86_64-unknown-linux-musl) (push) Has been cancelled
release / publish (push) Has been cancelled
Some checks failed
metrics / build_metrics (push) Waiting to run
metrics / other_metrics (diesel-1.4.8) (push) Blocked by required conditions
metrics / other_metrics (hyper-0.14.18) (push) Blocked by required conditions
metrics / other_metrics (ripgrep-13.0.0) (push) Blocked by required conditions
metrics / other_metrics (self) (push) Blocked by required conditions
metrics / other_metrics (webrender-2022) (push) Blocked by required conditions
metrics / generate_final_metrics (push) Blocked by required conditions
rustdoc / rustdoc (push) Waiting to run
autopublish / publish (push) Has been cancelled
release / dist (aarch64-apple-darwin) (push) Has been cancelled
release / dist (x86_64-apple-darwin) (push) Has been cancelled
release / dist (aarch64-unknown-linux-gnu) (push) Has been cancelled
release / dist (arm-unknown-linux-gnueabihf) (push) Has been cancelled
release / dist (x86_64-unknown-linux-gnu) (push) Has been cancelled
release / dist (aarch64-pc-windows-msvc) (push) Has been cancelled
release / dist (x86_64-pc-windows-msvc) (push) Has been cancelled
release / dist (i686-pc-windows-msvc) (push) Has been cancelled
release / dist (x86_64-unknown-linux-musl) (push) Has been cancelled
release / publish (push) Has been cancelled
Allow lifetime repeats in macros: $($x)'a*
This commit is contained in:
commit
a207299344
8 changed files with 63 additions and 14 deletions
|
|
@ -2029,3 +2029,25 @@ fn f() {
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lifetime_repeat() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
macro_rules! m {
|
||||||
|
($($x:expr)'a*) => (stringify!($($x)'b*));
|
||||||
|
}
|
||||||
|
fn f() {
|
||||||
|
let _ = m!(0 'a 1 'a 2);
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
macro_rules! m {
|
||||||
|
($($x:expr)'a*) => (stringify!($($x)'b*));
|
||||||
|
}
|
||||||
|
fn f() {
|
||||||
|
let _ = stringify!(0 'b 1 'b 2);
|
||||||
|
}
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ macro_rules! m {
|
||||||
($(x),*) => ();
|
($(x),*) => ();
|
||||||
($(x)_*) => ();
|
($(x)_*) => ();
|
||||||
($(x)i*) => ();
|
($(x)i*) => ();
|
||||||
|
($(x)'a*) => ();
|
||||||
|
($(x)'_*) => ();
|
||||||
($($i:ident)*) => ($_);
|
($($i:ident)*) => ($_);
|
||||||
($($true:ident)*) => ($true);
|
($($true:ident)*) => ($true);
|
||||||
($($false:ident)*) => ($false);
|
($($false:ident)*) => ($false);
|
||||||
|
|
@ -28,6 +30,8 @@ macro_rules! m {
|
||||||
($(x),*) => ();
|
($(x),*) => ();
|
||||||
($(x)_*) => ();
|
($(x)_*) => ();
|
||||||
($(x)i*) => ();
|
($(x)i*) => ();
|
||||||
|
($(x)'a*) => ();
|
||||||
|
($(x)'_*) => ();
|
||||||
($($i:ident)*) => ($_);
|
($($i:ident)*) => ($_);
|
||||||
($($true:ident)*) => ($true);
|
($($true:ident)*) => ($true);
|
||||||
($($false:ident)*) => ($false);
|
($($false:ident)*) => ($false);
|
||||||
|
|
|
||||||
|
|
@ -784,7 +784,7 @@ macro_rules! delegate_impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl <> Data for &'amut G where G: Data {}
|
impl <> Data for &'a mut G where G: Data {}
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -302,14 +302,15 @@ fn pretty_print_macro_expansion(
|
||||||
(_, T!['{']) => " ",
|
(_, T!['{']) => " ",
|
||||||
(T![;] | T!['{'] | T!['}'], _) => "\n",
|
(T![;] | T!['{'] | T!['}'], _) => "\n",
|
||||||
(_, T!['}']) => "\n",
|
(_, T!['}']) => "\n",
|
||||||
(IDENT | LIFETIME_IDENT, IDENT | LIFETIME_IDENT) => " ",
|
_ if (prev_kind.is_any_identifier()
|
||||||
_ if prev_kind.is_keyword(Edition::CURRENT)
|
|| prev_kind == LIFETIME_IDENT
|
||||||
&& curr_kind.is_keyword(Edition::CURRENT) =>
|
|| prev_kind.is_literal())
|
||||||
|
&& (curr_kind.is_any_identifier()
|
||||||
|
|| curr_kind == LIFETIME_IDENT
|
||||||
|
|| curr_kind.is_literal()) =>
|
||||||
{
|
{
|
||||||
" "
|
" "
|
||||||
}
|
}
|
||||||
(IDENT, _) if curr_kind.is_keyword(Edition::CURRENT) => " ",
|
|
||||||
(_, IDENT) if prev_kind.is_keyword(Edition::CURRENT) => " ",
|
|
||||||
(T![>], IDENT) => " ",
|
(T![>], IDENT) => " ",
|
||||||
(T![>], _) if curr_kind.is_keyword(Edition::CURRENT) => " ",
|
(T![>], _) if curr_kind.is_keyword(Edition::CURRENT) => " ",
|
||||||
(T![->], _) | (_, T![->]) => " ",
|
(T![->], _) | (_, T![->]) => " ",
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,10 @@ fn invocation_fixtures(
|
||||||
builder.push(tt::Leaf::Punct(*it))
|
builder.push(tt::Leaf::Punct(*it))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Separator::Lifetime(punct, ident) => {
|
||||||
|
builder.push(tt::Leaf::Punct(*punct));
|
||||||
|
builder.push(tt::Leaf::Ident(ident.clone()));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -823,7 +823,7 @@ fn match_meta_var<'t>(
|
||||||
"expected token tree",
|
"expected token tree",
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
MetaVarKind::Lifetime => expect_lifetime(input).map_err(|()| {
|
MetaVarKind::Lifetime => expect_lifetime(input).map(drop).map_err(|()| {
|
||||||
ExpandError::binding_error(
|
ExpandError::binding_error(
|
||||||
span.unwrap_or(delim_span.close),
|
span.unwrap_or(delim_span.close),
|
||||||
"expected lifetime",
|
"expected lifetime",
|
||||||
|
|
@ -963,6 +963,10 @@ fn expect_separator<S: Copy>(iter: &mut TtIter<'_, S>, separator: &Separator) ->
|
||||||
}
|
}
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
},
|
},
|
||||||
|
Separator::Lifetime(_punct, ident) => match expect_lifetime(&mut fork) {
|
||||||
|
Ok(lifetime) => lifetime.sym == ident.sym,
|
||||||
|
Err(_) => false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
if ok {
|
if ok {
|
||||||
*iter = fork;
|
*iter = fork;
|
||||||
|
|
@ -983,13 +987,12 @@ fn expect_tt<S: Copy>(iter: &mut TtIter<'_, S>) -> Result<(), ()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_lifetime<S: Copy>(iter: &mut TtIter<'_, S>) -> Result<(), ()> {
|
fn expect_lifetime<'a, S: Copy>(iter: &mut TtIter<'a, S>) -> Result<&'a tt::Ident<S>, ()> {
|
||||||
let punct = iter.expect_single_punct()?;
|
let punct = iter.expect_single_punct()?;
|
||||||
if punct.char != '\'' {
|
if punct.char != '\'' {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
iter.expect_ident_or_underscore()?;
|
iter.expect_ident_or_underscore()
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eat_char<S: Copy>(iter: &mut TtIter<'_, S>, c: char) {
|
fn eat_char<S: Copy>(iter: &mut TtIter<'_, S>, c: char) {
|
||||||
|
|
|
||||||
|
|
@ -497,6 +497,10 @@ fn expand_repeat(
|
||||||
builder.push(tt::Leaf::from(punct));
|
builder.push(tt::Leaf::from(punct));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Separator::Lifetime(punct, ident) => {
|
||||||
|
builder.push(tt::Leaf::from(*punct));
|
||||||
|
builder.push(tt::Leaf::from(ident.clone()));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,7 @@ pub(crate) enum Separator {
|
||||||
Literal(tt::Literal<Span>),
|
Literal(tt::Literal<Span>),
|
||||||
Ident(tt::Ident<Span>),
|
Ident(tt::Ident<Span>),
|
||||||
Puncts(ArrayVec<tt::Punct<Span>, MAX_GLUED_PUNCT_LEN>),
|
Puncts(ArrayVec<tt::Punct<Span>, MAX_GLUED_PUNCT_LEN>),
|
||||||
|
Lifetime(tt::Punct<Span>, tt::Ident<Span>),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that when we compare a Separator, we just care about its textual value.
|
// Note that when we compare a Separator, we just care about its textual value.
|
||||||
|
|
@ -170,6 +171,7 @@ impl PartialEq for Separator {
|
||||||
let b_iter = b.iter().map(|b| b.char);
|
let b_iter = b.iter().map(|b| b.char);
|
||||||
a_iter.eq(b_iter)
|
a_iter.eq(b_iter)
|
||||||
}
|
}
|
||||||
|
(Lifetime(_, a), Lifetime(_, b)) => a.sym == b.sym,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -350,10 +352,19 @@ fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option<Separator>, Repeat
|
||||||
_ => true,
|
_ => true,
|
||||||
};
|
};
|
||||||
match tt {
|
match tt {
|
||||||
tt::Leaf::Ident(_) | tt::Leaf::Literal(_) if has_sep => {
|
tt::Leaf::Ident(ident) => match separator {
|
||||||
return Err(ParseError::InvalidRepeat);
|
Separator::Puncts(puncts) if puncts.is_empty() => {
|
||||||
}
|
separator = Separator::Ident(ident.clone());
|
||||||
tt::Leaf::Ident(ident) => separator = Separator::Ident(ident.clone()),
|
}
|
||||||
|
Separator::Puncts(puncts) => match puncts.as_slice() {
|
||||||
|
[tt::Punct { char: '\'', .. }] => {
|
||||||
|
separator = Separator::Lifetime(puncts[0], ident.clone());
|
||||||
|
}
|
||||||
|
_ => return Err(ParseError::InvalidRepeat),
|
||||||
|
},
|
||||||
|
_ => return Err(ParseError::InvalidRepeat),
|
||||||
|
},
|
||||||
|
tt::Leaf::Literal(_) if has_sep => return Err(ParseError::InvalidRepeat),
|
||||||
tt::Leaf::Literal(lit) => separator = Separator::Literal(lit.clone()),
|
tt::Leaf::Literal(lit) => separator = Separator::Literal(lit.clone()),
|
||||||
tt::Leaf::Punct(punct) => {
|
tt::Leaf::Punct(punct) => {
|
||||||
let repeat_kind = match punct.char {
|
let repeat_kind = match punct.char {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue