Skip to content

Commit 5243ea5

Browse files
committed
Auto merge of rust-lang#108260 - lnicola:rust-analyzer-2023-02-20, r=lnicola
⬆️ rust-analyzer r? `@ghost`
2 parents 8973049 + 03288eb commit 5243ea5

File tree

98 files changed

+1800
-942
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+1800
-942
lines changed

src/tools/rust-analyzer/Cargo.lock

+4-2
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,7 @@ dependencies = [
711711
"limit",
712712
"memchr",
713713
"once_cell",
714+
"oorandom",
714715
"parser",
715716
"profile",
716717
"rayon",
@@ -932,9 +933,9 @@ dependencies = [
932933

933934
[[package]]
934935
name = "lsp-types"
935-
version = "0.93.2"
936+
version = "0.94.0"
936937
source = "registry+https://github.com/rust-lang/crates.io-index"
937-
checksum = "9be6e9c7e2d18f651974370d7aff703f9513e0df6e464fd795660edc77e6ca51"
938+
checksum = "0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237"
938939
dependencies = [
939940
"bitflags",
940941
"serde",
@@ -1173,6 +1174,7 @@ dependencies = [
11731174
"limit",
11741175
"rustc-ap-rustc_lexer",
11751176
"sourcegen",
1177+
"stdx",
11761178
]
11771179

11781180
[[package]]

src/tools/rust-analyzer/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,5 @@ toolchain = { path = "./crates/toolchain", version = "0.0.0" }
7474
tt = { path = "./crates/tt", version = "0.0.0" }
7575
vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
7676
vfs = { path = "./crates/vfs", version = "0.0.0" }
77+
# non-local crates
78+
smallvec = { version = "1.10.0", features = ["const_new", "union", "const_generics"] }

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ itertools = "0.10.5"
2727
la-arena = { version = "0.3.0", path = "../../lib/la-arena" }
2828
once_cell = "1.17.0"
2929
rustc-hash = "1.1.0"
30-
smallvec = "1.10.0"
30+
smallvec.workspace = true
3131
tracing = "0.1.35"
3232

3333
rustc_abi = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_abi", default-features = false }

src/tools/rust-analyzer/crates/hir-def/src/adt.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
33
use std::sync::Arc;
44

5-
use crate::tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
65
use base_db::CrateId;
6+
use cfg::CfgOptions;
77
use either::Either;
8+
89
use hir_expand::{
910
name::{AsName, Name},
1011
HirFileId, InFile,
@@ -24,12 +25,12 @@ use crate::{
2425
src::HasChildSource,
2526
src::HasSource,
2627
trace::Trace,
28+
tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
2729
type_ref::TypeRef,
2830
visibility::RawVisibility,
2931
EnumId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId, UnionId,
3032
VariantId,
3133
};
32-
use cfg::CfgOptions;
3334

3435
/// Note that we use `StructData` for unions as well!
3536
#[derive(Debug, Clone, PartialEq, Eq)]

src/tools/rust-analyzer/crates/hir-def/src/body.rs

+91-49
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use la_arena::{Arena, ArenaMap};
1919
use limit::Limit;
2020
use profile::Count;
2121
use rustc_hash::FxHashMap;
22-
use syntax::{ast, AstPtr, SyntaxNodePtr};
22+
use syntax::{ast, AstPtr, SyntaxNode, SyntaxNodePtr};
2323

2424
use crate::{
2525
attr::Attrs,
@@ -51,7 +51,8 @@ pub struct Expander {
5151
def_map: Arc<DefMap>,
5252
current_file_id: HirFileId,
5353
module: LocalModuleId,
54-
recursion_limit: usize,
54+
/// `recursion_depth == usize::MAX` indicates that the recursion limit has been reached.
55+
recursion_depth: usize,
5556
}
5657

5758
impl CfgExpander {
@@ -84,7 +85,7 @@ impl Expander {
8485
def_map,
8586
current_file_id,
8687
module: module.local_id,
87-
recursion_limit: 0,
88+
recursion_depth: 0,
8889
}
8990
}
9091

@@ -93,47 +94,52 @@ impl Expander {
9394
db: &dyn DefDatabase,
9495
macro_call: ast::MacroCall,
9596
) -> Result<ExpandResult<Option<(Mark, T)>>, UnresolvedMacro> {
96-
if self.recursion_limit(db).check(self.recursion_limit + 1).is_err() {
97-
cov_mark::hit!(your_stack_belongs_to_me);
98-
return Ok(ExpandResult::only_err(ExpandError::Other(
99-
"reached recursion limit during macro expansion".into(),
100-
)));
97+
let mut unresolved_macro_err = None;
98+
99+
let result = self.within_limit(db, |this| {
100+
let macro_call = InFile::new(this.current_file_id, &macro_call);
101+
102+
let resolver =
103+
|path| this.resolve_path_as_macro(db, &path).map(|it| macro_id_to_def_id(db, it));
104+
105+
let mut err = None;
106+
let call_id = match macro_call.as_call_id_with_errors(
107+
db,
108+
this.def_map.krate(),
109+
resolver,
110+
&mut |e| {
111+
err.get_or_insert(e);
112+
},
113+
) {
114+
Ok(call_id) => call_id,
115+
Err(resolve_err) => {
116+
unresolved_macro_err = Some(resolve_err);
117+
return ExpandResult { value: None, err: None };
118+
}
119+
};
120+
ExpandResult { value: call_id.ok(), err }
121+
});
122+
123+
if let Some(err) = unresolved_macro_err {
124+
Err(err)
125+
} else {
126+
Ok(result)
101127
}
102-
103-
let macro_call = InFile::new(self.current_file_id, &macro_call);
104-
105-
let resolver =
106-
|path| self.resolve_path_as_macro(db, &path).map(|it| macro_id_to_def_id(db, it));
107-
108-
let mut err = None;
109-
let call_id =
110-
macro_call.as_call_id_with_errors(db, self.def_map.krate(), resolver, &mut |e| {
111-
err.get_or_insert(e);
112-
})?;
113-
let call_id = match call_id {
114-
Ok(it) => it,
115-
Err(_) => {
116-
return Ok(ExpandResult { value: None, err });
117-
}
118-
};
119-
120-
Ok(self.enter_expand_inner(db, call_id, err))
121128
}
122129

123130
pub fn enter_expand_id<T: ast::AstNode>(
124131
&mut self,
125132
db: &dyn DefDatabase,
126133
call_id: MacroCallId,
127134
) -> ExpandResult<Option<(Mark, T)>> {
128-
self.enter_expand_inner(db, call_id, None)
135+
self.within_limit(db, |_this| ExpandResult::ok(Some(call_id)))
129136
}
130137

131-
fn enter_expand_inner<T: ast::AstNode>(
132-
&mut self,
138+
fn enter_expand_inner(
133139
db: &dyn DefDatabase,
134140
call_id: MacroCallId,
135141
mut err: Option<ExpandError>,
136-
) -> ExpandResult<Option<(Mark, T)>> {
142+
) -> ExpandResult<Option<(HirFileId, SyntaxNode)>> {
137143
if err.is_none() {
138144
err = db.macro_expand_error(call_id);
139145
}
@@ -154,29 +160,21 @@ impl Expander {
154160
}
155161
};
156162

157-
let node = match T::cast(raw_node) {
158-
Some(it) => it,
159-
None => {
160-
// This can happen without being an error, so only forward previous errors.
161-
return ExpandResult { value: None, err };
162-
}
163-
};
164-
165-
tracing::debug!("macro expansion {:#?}", node.syntax());
166-
167-
self.recursion_limit += 1;
168-
let mark =
169-
Mark { file_id: self.current_file_id, bomb: DropBomb::new("expansion mark dropped") };
170-
self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
171-
self.current_file_id = file_id;
172-
173-
ExpandResult { value: Some((mark, node)), err }
163+
ExpandResult { value: Some((file_id, raw_node)), err }
174164
}
175165

176166
pub fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
177167
self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id);
178168
self.current_file_id = mark.file_id;
179-
self.recursion_limit -= 1;
169+
if self.recursion_depth == usize::MAX {
170+
// Recursion limit has been reached somewhere in the macro expansion tree. Reset the
171+
// depth only when we get out of the tree.
172+
if !self.current_file_id.is_macro() {
173+
self.recursion_depth = 0;
174+
}
175+
} else {
176+
self.recursion_depth -= 1;
177+
}
180178
mark.bomb.defuse();
181179
}
182180

@@ -215,6 +213,50 @@ impl Expander {
215213
#[cfg(test)]
216214
return Limit::new(std::cmp::min(32, limit));
217215
}
216+
217+
fn within_limit<F, T: ast::AstNode>(
218+
&mut self,
219+
db: &dyn DefDatabase,
220+
op: F,
221+
) -> ExpandResult<Option<(Mark, T)>>
222+
where
223+
F: FnOnce(&mut Self) -> ExpandResult<Option<MacroCallId>>,
224+
{
225+
if self.recursion_depth == usize::MAX {
226+
// Recursion limit has been reached somewhere in the macro expansion tree. We should
227+
// stop expanding other macro calls in this tree, or else this may result in
228+
// exponential number of macro expansions, leading to a hang.
229+
//
230+
// The overflow error should have been reported when it occurred (see the next branch),
231+
// so don't return overflow error here to avoid diagnostics duplication.
232+
cov_mark::hit!(overflow_but_not_me);
233+
return ExpandResult::only_err(ExpandError::RecursionOverflowPosioned);
234+
} else if self.recursion_limit(db).check(self.recursion_depth + 1).is_err() {
235+
self.recursion_depth = usize::MAX;
236+
cov_mark::hit!(your_stack_belongs_to_me);
237+
return ExpandResult::only_err(ExpandError::Other(
238+
"reached recursion limit during macro expansion".into(),
239+
));
240+
}
241+
242+
let ExpandResult { value, err } = op(self);
243+
let Some(call_id) = value else {
244+
return ExpandResult { value: None, err };
245+
};
246+
247+
Self::enter_expand_inner(db, call_id, err).map(|value| {
248+
value.and_then(|(new_file_id, node)| {
249+
let node = T::cast(node)?;
250+
251+
self.recursion_depth += 1;
252+
self.cfg_expander.hygiene = Hygiene::new(db.upcast(), new_file_id);
253+
let old_file_id = std::mem::replace(&mut self.current_file_id, new_file_id);
254+
let mark =
255+
Mark { file_id: old_file_id, bomb: DropBomb::new("expansion mark dropped") };
256+
Some((mark, node))
257+
})
258+
})
259+
}
218260
}
219261

220262
#[derive(Debug)]

src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs

+6
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,10 @@ impl ExprCollector<'_> {
624624
krate: *krate,
625625
});
626626
}
627+
Some(ExpandError::RecursionOverflowPosioned) => {
628+
// Recursion limit has been reached in the macro expansion tree, but not in
629+
// this very macro call. Don't add diagnostics to avoid duplication.
630+
}
627631
Some(err) => {
628632
self.source_map.diagnostics.push(BodyDiagnostic::MacroError {
629633
node: InFile::new(outer_file, syntax_ptr),
@@ -636,6 +640,8 @@ impl ExprCollector<'_> {
636640

637641
match res.value {
638642
Some((mark, expansion)) => {
643+
// Keep collecting even with expansion errors so we can provide completions and
644+
// other services in incomplete macro expressions.
639645
self.source_map.expansions.insert(macro_call_ptr, self.expander.current_file_id);
640646
let prev_ast_id_map = mem::replace(
641647
&mut self.ast_id_map,

src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs

+13
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,19 @@ fn main() { n_nuple!(1,2,3); }
6161
);
6262
}
6363

64+
#[test]
65+
fn your_stack_belongs_to_me2() {
66+
cov_mark::check!(overflow_but_not_me);
67+
lower(
68+
r#"
69+
macro_rules! foo {
70+
() => {{ foo!(); foo!(); }}
71+
}
72+
fn main() { foo!(); }
73+
"#,
74+
);
75+
}
76+
6477
#[test]
6578
fn recursion_limit() {
6679
cov_mark::check!(your_stack_belongs_to_me);

src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -659,15 +659,16 @@ fn desugar_future_path(orig: TypeRef) -> Path {
659659
let path = path![core::future::Future];
660660
let mut generic_args: Vec<_> =
661661
std::iter::repeat(None).take(path.segments().len() - 1).collect();
662-
let mut last = GenericArgs::empty();
663662
let binding = AssociatedTypeBinding {
664663
name: name![Output],
665664
args: None,
666665
type_ref: Some(orig),
667-
bounds: Vec::new(),
666+
bounds: Box::default(),
668667
};
669-
last.bindings.push(binding);
670-
generic_args.push(Some(Interned::new(last)));
668+
generic_args.push(Some(Interned::new(GenericArgs {
669+
bindings: Box::new([binding]),
670+
..GenericArgs::empty()
671+
})));
671672

672673
Path::from_known_path(path, generic_args)
673674
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1476,7 +1476,7 @@ macro_rules! m {
14761476
/* parse error: expected identifier */
14771477
/* parse error: expected SEMICOLON */
14781478
/* parse error: expected SEMICOLON */
1479-
/* parse error: expected expression */
1479+
/* parse error: expected expression, item or let statement */
14801480
fn f() {
14811481
K::(C("0"));
14821482
}

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

+10-11
Original file line numberDiff line numberDiff line change
@@ -830,8 +830,7 @@ macro_rules! rgb_color {
830830
/* parse error: expected COMMA */
831831
/* parse error: expected R_ANGLE */
832832
/* parse error: expected SEMICOLON */
833-
/* parse error: expected SEMICOLON */
834-
/* parse error: expected expression */
833+
/* parse error: expected expression, item or let statement */
835834
pub fn new() {
836835
let _ = 0as u32<<(8+8);
837836
}
@@ -848,21 +847,21 @@ pub fn new() {
848847
849848
850849
851-
// LET_STMT@11..27
850+
// LET_STMT@11..28
852851
853852
854853
855854
856-
// CAST_EXPR@16..27
855+
// CAST_EXPR@16..28
857856
858857
859858
860-
// PATH_TYPE@19..27
861-
// PATH@19..27
862-
// PATH_SEGMENT@19..27
859+
// PATH_TYPE@19..28
860+
// PATH@19..28
861+
// PATH_SEGMENT@19..28
863862
864863
865-
// GENERIC_ARG_LIST@22..27
864+
// GENERIC_ARG_LIST@22..28
866865
867866
868867
@@ -877,9 +876,9 @@ pub fn new() {
877876
878877
879878
880-
// EXPR_STMT@27..28
881-
882-
879+
// CONST_ARG@27..28
880+
881+
883882
884883
885884

0 commit comments

Comments
 (0)