Skip to content

Commit afe5d8c

Browse files
committed
Auto merge of rust-lang#16450 - Urhengulas:edition-aware-parser, r=Veykril
internal: Prepare parser interface for editions
2 parents 22a0801 + 1935700 commit afe5d8c

File tree

24 files changed

+140
-102
lines changed

24 files changed

+140
-102
lines changed

src/tools/rust-analyzer/Cargo.lock

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,11 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander {
316316
_: Span,
317317
_: Span,
318318
) -> Result<Subtree, ProcMacroExpansionError> {
319-
let (parse, _) =
320-
::mbe::token_tree_to_syntax_node(subtree, ::mbe::TopEntryPoint::MacroItems);
319+
let (parse, _) = ::mbe::token_tree_to_syntax_node(
320+
subtree,
321+
::mbe::TopEntryPoint::MacroItems,
322+
span::Edition::CURRENT,
323+
);
321324
if parse.errors().is_empty() {
322325
Ok(subtree.clone())
323326
} else {

src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,7 @@ impl DefCollector<'_> {
534534
Edition::Edition2015 => name![rust_2015],
535535
Edition::Edition2018 => name![rust_2018],
536536
Edition::Edition2021 => name![rust_2021],
537-
// FIXME: update this when rust_2024 exists
538-
Edition::Edition2024 => name![rust_2021],
537+
Edition::Edition2024 => name![rust_2024],
539538
};
540539

541540
let path_kind = match self.def_map.data.edition {

src/tools/rust-analyzer/crates/hir-expand/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ tt.workspace = true
3232
mbe.workspace = true
3333
limit.workspace = true
3434
span.workspace = true
35+
parser.workspace = true
3536

3637
[dev-dependencies]
3738
expect-test = "1.4.0"

src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,11 @@ struct BasicAdtInfo {
204204
}
205205

206206
fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandError> {
207-
let (parsed, tm) = &mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MacroItems);
207+
let (parsed, tm) = &mbe::token_tree_to_syntax_node(
208+
tt,
209+
mbe::TopEntryPoint::MacroItems,
210+
parser::Edition::CURRENT,
211+
);
208212
let macro_items = ast::MacroItems::cast(parsed.syntax_node())
209213
.ok_or_else(|| ExpandError::other("invalid item definition"))?;
210214
let item = macro_items.items().next().ok_or_else(|| ExpandError::other("no item found"))?;

src/tools/rust-analyzer/crates/hir-expand/src/db.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ fn token_tree_to_syntax_node(
676676
ExpandTo::Type => mbe::TopEntryPoint::Type,
677677
ExpandTo::Expr => mbe::TopEntryPoint::Expr,
678678
};
679-
mbe::token_tree_to_syntax_node(tt, entry_point)
679+
mbe::token_tree_to_syntax_node(tt, entry_point, parser::Edition::CURRENT)
680680
}
681681

682682
fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<()>> {

src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,11 @@ mod tests {
417417
expect.assert_eq(&actual);
418418

419419
// the fixed-up tree should be syntactically valid
420-
let (parse, _) = mbe::token_tree_to_syntax_node(&tt, ::mbe::TopEntryPoint::MacroItems);
420+
let (parse, _) = mbe::token_tree_to_syntax_node(
421+
&tt,
422+
::mbe::TopEntryPoint::MacroItems,
423+
parser::Edition::CURRENT,
424+
);
421425
assert!(
422426
parse.errors().is_empty(),
423427
"parse has syntax errors. parse tree:\n{:#?}",

src/tools/rust-analyzer/crates/hir-expand/src/name.rs

+1
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ pub mod known {
303303
rust_2015,
304304
rust_2018,
305305
rust_2021,
306+
rust_2024,
306307
v1,
307308
new_display,
308309
new_debug,

src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1157,7 +1157,7 @@ fn iterate_trait_method_candidates(
11571157
{
11581158
// FIXME: this should really be using the edition of the method name's span, in case it
11591159
// comes from a macro
1160-
if db.crate_graph()[krate].edition < Edition::Edition2021 {
1160+
if db.crate_graph()[krate].edition < Edition::CURRENT {
11611161
continue;
11621162
}
11631163
}

src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs

+22-18
Original file line numberDiff line numberDiff line change
@@ -743,9 +743,11 @@ fn match_meta_var(
743743
) -> ExpandResult<Option<Fragment>> {
744744
let fragment = match kind {
745745
MetaVarKind::Path => {
746-
return input.expect_fragment(parser::PrefixEntryPoint::Path).map(|it| {
747-
it.map(|it| tt::TokenTree::subtree_or_wrap(it, delim_span)).map(Fragment::Path)
748-
});
746+
return input
747+
.expect_fragment(parser::PrefixEntryPoint::Path, parser::Edition::CURRENT)
748+
.map(|it| {
749+
it.map(|it| tt::TokenTree::subtree_or_wrap(it, delim_span)).map(Fragment::Path)
750+
});
749751
}
750752
MetaVarKind::Ty => parser::PrefixEntryPoint::Ty,
751753
MetaVarKind::Pat => parser::PrefixEntryPoint::PatTop,
@@ -770,21 +772,23 @@ fn match_meta_var(
770772
}
771773
_ => {}
772774
};
773-
return input.expect_fragment(parser::PrefixEntryPoint::Expr).map(|tt| {
774-
tt.map(|tt| match tt {
775-
tt::TokenTree::Leaf(leaf) => tt::Subtree {
776-
delimiter: tt::Delimiter::invisible_spanned(*leaf.span()),
777-
token_trees: Box::new([leaf.into()]),
778-
},
779-
tt::TokenTree::Subtree(mut s) => {
780-
if s.delimiter.kind == tt::DelimiterKind::Invisible {
781-
s.delimiter.kind = tt::DelimiterKind::Parenthesis;
775+
return input
776+
.expect_fragment(parser::PrefixEntryPoint::Expr, parser::Edition::CURRENT)
777+
.map(|tt| {
778+
tt.map(|tt| match tt {
779+
tt::TokenTree::Leaf(leaf) => tt::Subtree {
780+
delimiter: tt::Delimiter::invisible_spanned(*leaf.span()),
781+
token_trees: Box::new([leaf.into()]),
782+
},
783+
tt::TokenTree::Subtree(mut s) => {
784+
if s.delimiter.kind == tt::DelimiterKind::Invisible {
785+
s.delimiter.kind = tt::DelimiterKind::Parenthesis;
786+
}
787+
s
782788
}
783-
s
784-
}
785-
})
786-
.map(Fragment::Expr)
787-
});
789+
})
790+
.map(Fragment::Expr)
791+
});
788792
}
789793
MetaVarKind::Ident | MetaVarKind::Tt | MetaVarKind::Lifetime | MetaVarKind::Literal => {
790794
let tt_result = match kind {
@@ -819,7 +823,7 @@ fn match_meta_var(
819823
return tt_result.map(|it| Some(Fragment::Tokens(it))).into();
820824
}
821825
};
822-
input.expect_fragment(fragment).map(|it| it.map(Fragment::Tokens))
826+
input.expect_fragment(fragment, parser::Edition::CURRENT).map(|it| it.map(Fragment::Tokens))
823827
}
824828

825829
fn collect_vars(collector_fun: &mut impl FnMut(SmolStr), pattern: &MetaTemplate) {

src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ where
119119
pub fn token_tree_to_syntax_node<Ctx>(
120120
tt: &tt::Subtree<SpanData<Ctx>>,
121121
entry_point: parser::TopEntryPoint,
122+
edition: parser::Edition,
122123
) -> (Parse<SyntaxNode>, SpanMap<Ctx>)
123124
where
124125
SpanData<Ctx>: Copy + fmt::Debug,
@@ -131,7 +132,7 @@ where
131132
_ => TokenBuffer::from_subtree(tt),
132133
};
133134
let parser_input = to_parser_input(&buffer);
134-
let parser_output = entry_point.parse(&parser_input);
135+
let parser_output = entry_point.parse(&parser_input, edition);
135136
let mut tree_sink = TtTreeSink::new(buffer.begin());
136137
for event in parser_output.iter() {
137138
match event {
@@ -194,7 +195,8 @@ where
194195
let mut res = Vec::new();
195196

196197
while iter.peek_n(0).is_some() {
197-
let expanded = iter.expect_fragment(parser::PrefixEntryPoint::Expr);
198+
let expanded =
199+
iter.expect_fragment(parser::PrefixEntryPoint::Expr, parser::Edition::CURRENT);
198200

199201
res.push(match expanded.value {
200202
None => break,

src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,11 @@ impl<'a, S: Copy + fmt::Debug> TtIter<'a, S> {
140140
pub(crate) fn expect_fragment(
141141
&mut self,
142142
entry_point: parser::PrefixEntryPoint,
143+
edition: parser::Edition,
143144
) -> ExpandResult<Option<tt::TokenTree<S>>> {
144145
let buffer = tt::buffer::TokenBuffer::from_tokens(self.inner.as_slice());
145146
let parser_input = to_parser_input(&buffer);
146-
let tree_traversal = entry_point.parse(&parser_input);
147+
let tree_traversal = entry_point.parse(&parser_input, edition);
147148
let mut cursor = buffer.begin();
148149
let mut error = false;
149150
for step in tree_traversal.iter() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//! The edition of the Rust language used in a crate.
2+
// Ideally this would be defined in the span crate, but the dependency chain is all over the place
3+
// wrt to span, parser and syntax.
4+
use std::fmt;
5+
6+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
7+
pub enum Edition {
8+
Edition2015,
9+
Edition2018,
10+
Edition2021,
11+
Edition2024,
12+
}
13+
14+
impl Edition {
15+
pub const CURRENT: Edition = Edition::Edition2021;
16+
pub const DEFAULT: Edition = Edition::Edition2015;
17+
}
18+
19+
#[derive(Debug)]
20+
pub struct ParseEditionError {
21+
invalid_input: String,
22+
}
23+
24+
impl std::error::Error for ParseEditionError {}
25+
impl fmt::Display for ParseEditionError {
26+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27+
write!(f, "invalid edition: {:?}", self.invalid_input)
28+
}
29+
}
30+
31+
impl std::str::FromStr for Edition {
32+
type Err = ParseEditionError;
33+
34+
fn from_str(s: &str) -> Result<Self, Self::Err> {
35+
let res = match s {
36+
"2015" => Edition::Edition2015,
37+
"2018" => Edition::Edition2018,
38+
"2021" => Edition::Edition2021,
39+
"2024" => Edition::Edition2024,
40+
_ => return Err(ParseEditionError { invalid_input: s.to_owned() }),
41+
};
42+
Ok(res)
43+
}
44+
}
45+
46+
impl fmt::Display for Edition {
47+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48+
f.write_str(match self {
49+
Edition::Edition2015 => "2015",
50+
Edition::Edition2018 => "2018",
51+
Edition::Edition2021 => "2021",
52+
Edition::Edition2024 => "2024",
53+
})
54+
}
55+
}

src/tools/rust-analyzer/crates/parser/src/lib.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extern crate ra_ap_rustc_lexer as rustc_lexer;
2626
#[cfg(feature = "in-rust-tree")]
2727
extern crate rustc_lexer;
2828

29+
mod edition;
2930
mod event;
3031
mod grammar;
3132
mod input;
@@ -42,6 +43,7 @@ mod tests;
4243
pub(crate) use token_set::TokenSet;
4344

4445
pub use crate::{
46+
edition::Edition,
4547
input::Input,
4648
lexed_str::LexedStr,
4749
output::{Output, Step},
@@ -86,7 +88,7 @@ pub enum TopEntryPoint {
8688
}
8789

8890
impl TopEntryPoint {
89-
pub fn parse(&self, input: &Input) -> Output {
91+
pub fn parse(&self, input: &Input, edition: Edition) -> Output {
9092
let _p = tracing::span!(tracing::Level::INFO, "TopEntryPoint::parse", ?self).entered();
9193
let entry_point: fn(&'_ mut parser::Parser<'_>) = match self {
9294
TopEntryPoint::SourceFile => grammar::entry::top::source_file,
@@ -98,7 +100,7 @@ impl TopEntryPoint {
98100
TopEntryPoint::MetaItem => grammar::entry::top::meta_item,
99101
TopEntryPoint::MacroEagerInput => grammar::entry::top::eager_macro_input,
100102
};
101-
let mut p = parser::Parser::new(input);
103+
let mut p = parser::Parser::new(input, edition);
102104
entry_point(&mut p);
103105
let events = p.finish();
104106
let res = event::process(events);
@@ -150,7 +152,7 @@ pub enum PrefixEntryPoint {
150152
}
151153

152154
impl PrefixEntryPoint {
153-
pub fn parse(&self, input: &Input) -> Output {
155+
pub fn parse(&self, input: &Input, edition: Edition) -> Output {
154156
let entry_point: fn(&'_ mut parser::Parser<'_>) = match self {
155157
PrefixEntryPoint::Vis => grammar::entry::prefix::vis,
156158
PrefixEntryPoint::Block => grammar::entry::prefix::block,
@@ -163,7 +165,7 @@ impl PrefixEntryPoint {
163165
PrefixEntryPoint::Item => grammar::entry::prefix::item,
164166
PrefixEntryPoint::MetaItem => grammar::entry::prefix::meta_item,
165167
};
166-
let mut p = parser::Parser::new(input);
168+
let mut p = parser::Parser::new(input, edition);
167169
entry_point(&mut p);
168170
let events = p.finish();
169171
event::process(events)
@@ -187,9 +189,9 @@ impl Reparser {
187189
///
188190
/// Tokens must start with `{`, end with `}` and form a valid brace
189191
/// sequence.
190-
pub fn parse(self, tokens: &Input) -> Output {
192+
pub fn parse(self, tokens: &Input, edition: Edition) -> Output {
191193
let Reparser(r) = self;
192-
let mut p = parser::Parser::new(tokens);
194+
let mut p = parser::Parser::new(tokens, edition);
193195
r(&mut p);
194196
let events = p.finish();
195197
event::process(events)

src/tools/rust-analyzer/crates/parser/src/parser.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use limit::Limit;
88
use crate::{
99
event::Event,
1010
input::Input,
11+
Edition,
1112
SyntaxKind::{self, EOF, ERROR, TOMBSTONE},
1213
TokenSet, T,
1314
};
@@ -26,13 +27,14 @@ pub(crate) struct Parser<'t> {
2627
pos: usize,
2728
events: Vec<Event>,
2829
steps: Cell<u32>,
30+
_edition: Edition,
2931
}
3032

3133
static PARSER_STEP_LIMIT: Limit = Limit::new(15_000_000);
3234

3335
impl<'t> Parser<'t> {
34-
pub(super) fn new(inp: &'t Input) -> Parser<'t> {
35-
Parser { inp, pos: 0, events: Vec::new(), steps: Cell::new(0) }
36+
pub(super) fn new(inp: &'t Input, edition: Edition) -> Parser<'t> {
37+
Parser { inp, pos: 0, events: Vec::new(), steps: Cell::new(0), _edition: edition }
3638
}
3739

3840
pub(crate) fn finish(self) -> Vec<Event> {

src/tools/rust-analyzer/crates/parser/src/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ fn parse_inline_err() {
8888
fn parse(entry: TopEntryPoint, text: &str) -> (String, bool) {
8989
let lexed = LexedStr::new(text);
9090
let input = lexed.to_input();
91-
let output = entry.parse(&input);
91+
let output = entry.parse(&input, crate::Edition::CURRENT);
9292

9393
let mut buf = String::new();
9494
let mut errors = Vec::new();

src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ fn check(entry: PrefixEntryPoint, input: &str, prefix: &str) {
8686
let input = lexed.to_input();
8787

8888
let mut n_tokens = 0;
89-
for step in entry.parse(&input).iter() {
89+
for step in entry.parse(&input, crate::Edition::CURRENT).iter() {
9090
match step {
9191
Step::Token { n_input_tokens, .. } => n_tokens += n_input_tokens as usize,
9292
Step::FloatSplit { .. } => n_tokens += 1,

src/tools/rust-analyzer/crates/span/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ la-arena.workspace = true
1414
salsa.workspace = true
1515
rustc-hash.workspace = true
1616
hashbrown.workspace = true
17+
text-size.workspace = true
1718

1819
# local deps
1920
vfs.workspace = true

0 commit comments

Comments
 (0)