Fix a bug in MBE expansion that arose from incorrect fixing of an older bug in MBE

Specifically, #18744 was the PR that was supposed to fix the old bug, but it fixed it incorrectly (and didn't add a test!) The underlying reason was that we marked metavariables in expansions as joint if they were joint in the macro call, which is incorrect.

This wrong fix causes other bug, #19497, which this PR fixes by removing the old (incorrect) fix.
This commit is contained in:
Chayim Refael Friedman 2025-04-01 19:21:01 +03:00
parent df0174e988
commit 3953b604ce
7 changed files with 107 additions and 11 deletions

View file

@ -6,7 +6,7 @@ use std::fmt;
use arrayvec::ArrayVec;
use intern::sym;
use crate::{Ident, Leaf, Punct, Spacing, Subtree, TokenTree, TokenTreesView};
use crate::{Ident, Leaf, MAX_GLUED_PUNCT_LEN, Punct, Spacing, Subtree, TokenTree, TokenTreesView};
#[derive(Clone)]
pub struct TtIter<'a, S> {
@ -111,7 +111,7 @@ impl<'a, S: Copy> TtIter<'a, S> {
///
/// This method currently may return a single quotation, which is part of lifetime ident and
/// conceptually not a punct in the context of mbe. Callers should handle this.
pub fn expect_glued_punct(&mut self) -> Result<ArrayVec<Punct<S>, 3>, ()> {
pub fn expect_glued_punct(&mut self) -> Result<ArrayVec<Punct<S>, MAX_GLUED_PUNCT_LEN>, ()> {
let TtElement::Leaf(&Leaf::Punct(first)) = self.next().ok_or(())? else {
return Err(());
};
@ -145,7 +145,6 @@ impl<'a, S: Copy> TtIter<'a, S> {
}
('-' | '!' | '*' | '/' | '&' | '%' | '^' | '+' | '<' | '=' | '>' | '|', '=', _)
| ('-' | '=' | '>', '>', _)
| (_, _, Some(';'))
| ('<', '-', _)
| (':', ':', _)
| ('.', '.', _)

View file

@ -22,6 +22,8 @@ use stdx::{impl_from, itertools::Itertools as _};
pub use text_size::{TextRange, TextSize};
pub const MAX_GLUED_PUNCT_LEN: usize = 3;
#[derive(Clone, PartialEq, Debug)]
pub struct Lit {
pub kind: LitKind,
@ -243,6 +245,23 @@ impl<S: Copy> TopSubtreeBuilder<S> {
self.token_trees.extend(tt.0.iter().cloned());
}
/// Like [`Self::extend_with_tt()`], but makes sure the new tokens will never be
/// joint with whatever comes after them.
pub fn extend_with_tt_alone(&mut self, tt: TokenTreesView<'_, S>) {
if let Some((last, before_last)) = tt.0.split_last() {
self.token_trees.reserve(tt.0.len());
self.token_trees.extend(before_last.iter().cloned());
let last = if let TokenTree::Leaf(Leaf::Punct(last)) = last {
let mut last = *last;
last.spacing = Spacing::Alone;
TokenTree::Leaf(Leaf::Punct(last))
} else {
last.clone()
};
self.token_trees.push(last);
}
}
pub fn expected_delimiters(&self) -> impl Iterator<Item = &Delimiter<S>> {
self.unclosed_subtree_indices.iter().rev().map(|&subtree_idx| {
let TokenTree::Subtree(subtree) = &self.token_trees[subtree_idx] else {