Merge pull request #19842 from Veykril/push-zunlmrzpnrzk
minor: Support `transmute_unchecked` intrinsic for mir-eval
diff --git a/Cargo.lock b/Cargo.lock
index 54f9dec..bd8146d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1750,9 +1750,9 @@
[[package]]
name = "ra-ap-rustc_abi"
-version = "0.110.0"
+version = "0.113.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "912228bd8ed3beff1f6f9e5e2d4b37c0827ba3e2070060bf3858a311d0e29e30"
+checksum = "c33b8fa229789975647ca5426be432c7c327ebde89ab15889928185dbcee3230"
dependencies = [
"bitflags 2.9.0",
"ra-ap-rustc_hashes",
@@ -1762,18 +1762,18 @@
[[package]]
name = "ra-ap-rustc_hashes"
-version = "0.110.0"
+version = "0.113.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba520764daf057a9d963fa769f4762eaf87ac5d4900ae76195eeead64cd35afd"
+checksum = "0d68a3e389927002f552938a90b04787f6435f55b46fc5691360470d1cb2e99d"
dependencies = [
"rustc-stable-hash",
]
[[package]]
name = "ra-ap-rustc_index"
-version = "0.110.0"
+version = "0.113.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b76b5f9ee55f2d0e5a65bea23f6d738893349ce8d3d17a6720933e647ab04978"
+checksum = "32502273df2838d0ca13f1c67e2a48feef940e591f9771869f07e2db2acede53"
dependencies = [
"ra-ap-rustc_index_macros",
"smallvec",
@@ -1781,9 +1781,9 @@
[[package]]
name = "ra-ap-rustc_index_macros"
-version = "0.110.0"
+version = "0.113.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddd972eb1face2fcaa0d94c01d97862fb955b5561d4f5932003bce8a6cadd8c6"
+checksum = "8a32f081864ae34c7ae6634edfa7a95ab9260ba85015e8b1d347580eda79d14f"
dependencies = [
"proc-macro2",
"quote",
@@ -1792,9 +1792,9 @@
[[package]]
name = "ra-ap-rustc_lexer"
-version = "0.110.0"
+version = "0.113.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba3a9876456fb2521097deef33ddeac1c18260c8eafb68054d986f8b9d6ce9fa"
+checksum = "ed34c51974718c5bd90d876d1364d9725159fc8030c2382b9cb837034152ed68"
dependencies = [
"memchr",
"unicode-properties",
@@ -1803,9 +1803,9 @@
[[package]]
name = "ra-ap-rustc_parse_format"
-version = "0.110.0"
+version = "0.113.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e85de58dfcc60a5f9d5ec0157a657e3f84abd8f22c8a0c4d707cfb42c9011f4"
+checksum = "ff0440e5d27facbf4ff13ea651e48c2f6e360b3dbfc56251b41d60719b965fb8"
dependencies = [
"ra-ap-rustc_lexer",
"rustc-literal-escaper",
@@ -1813,9 +1813,9 @@
[[package]]
name = "ra-ap-rustc_pattern_analysis"
-version = "0.110.0"
+version = "0.113.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ceadf9db550db67deff7eff2e2765109b860c9d7e5bdfca144863020289c823d"
+checksum = "a6056efa57aba3aa0cc69a0bf1a8281624c23ad25b05748d11ebcd4668037bfc"
dependencies = [
"ra-ap-rustc_index",
"rustc-hash 2.1.1",
diff --git a/Cargo.toml b/Cargo.toml
index c4c2fdf..07731ba 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -85,11 +85,11 @@
vfs = { path = "./crates/vfs", version = "0.0.0" }
edition = { path = "./crates/edition", version = "0.0.0" }
-ra-ap-rustc_lexer = { version = "0.110", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.110", default-features = false }
-ra-ap-rustc_index = { version = "0.110", default-features = false }
-ra-ap-rustc_abi = { version = "0.110", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.110", default-features = false }
+ra-ap-rustc_lexer = { version = "0.113", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.113", default-features = false }
+ra-ap-rustc_index = { version = "0.113", default-features = false }
+ra-ap-rustc_abi = { version = "0.113", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.113", default-features = false }
# local crates that aren't published to crates.io. These should not have versions.
@@ -132,7 +132,10 @@
pulldown-cmark = { version = "0.9.6", default-features = false }
rayon = "1.10.0"
rowan = "=0.15.15"
-salsa = { version = "0.21.1", default-features = false, features = ["rayon","salsa_unstable"] }
+salsa = { version = "0.21.1", default-features = false, features = [
+ "rayon",
+ "salsa_unstable",
+] }
salsa-macros = "0.21.1"
semver = "1.0.26"
serde = { version = "1.0.219" }
diff --git a/crates/hir-def/src/expr_store/lower/asm.rs b/crates/hir-def/src/expr_store/lower/asm.rs
index 9ef0306..d36e520 100644
--- a/crates/hir-def/src/expr_store/lower/asm.rs
+++ b/crates/hir-def/src/expr_store/lower/asm.rs
@@ -224,7 +224,7 @@
curarg = parser.curarg;
- let to_span = |inner_span: rustc_parse_format::InnerSpan| {
+ let to_span = |inner_span: std::ops::Range<usize>| {
is_direct_literal.then(|| {
TextRange::new(
inner_span.start.try_into().unwrap(),
diff --git a/crates/hir-def/src/hir/format_args.rs b/crates/hir-def/src/hir/format_args.rs
index 2fd21bb..271484d 100644
--- a/crates/hir-def/src/hir/format_args.rs
+++ b/crates/hir-def/src/hir/format_args.rs
@@ -214,7 +214,7 @@
};
}
- let to_span = |inner_span: parse::InnerSpan| {
+ let to_span = |inner_span: std::ops::Range<usize>| {
is_source_literal.then(|| {
TextRange::new(inner_span.start.try_into().unwrap(), inner_span.end.try_into().unwrap())
})
@@ -297,7 +297,8 @@
unfinished_literal.clear();
}
- let span = parser.arg_places.get(placeholder_index).and_then(|&s| to_span(s));
+ let span =
+ parser.arg_places.get(placeholder_index).and_then(|s| to_span(s.clone()));
placeholder_index += 1;
let position_span = to_span(position_span);
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 9a3c331..785277d 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -301,6 +301,7 @@
// ignore this issue.
Ref => PatKind::Deref { subpattern: subpatterns.next().unwrap() },
Slice(_) => unimplemented!(),
+ DerefPattern(_) => unimplemented!(),
&Str(void) => match void {},
Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild,
Never => PatKind::Never,
@@ -351,6 +352,7 @@
},
Ref => 1,
Slice(..) => unimplemented!(),
+ DerefPattern(..) => unimplemented!(),
Never | Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
| F128Range(..) | Str(..) | Opaque(..) | NonExhaustive | PrivateUninhabited
| Hidden | Missing | Wildcard => 0,
@@ -411,6 +413,7 @@
}
},
Slice(_) => unreachable!("Found a `Slice` constructor in match checking"),
+ DerefPattern(_) => unreachable!("Found a `DerefPattern` constructor in match checking"),
Never | Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
| F128Range(..) | Str(..) | Opaque(..) | NonExhaustive | PrivateUninhabited
| Hidden | Missing | Wildcard => {
diff --git a/crates/ide-db/src/generated/lints.rs b/crates/ide-db/src/generated/lints.rs
index 706d044..f9ff392 100644
--- a/crates/ide-db/src/generated/lints.rs
+++ b/crates/ide-db/src/generated/lints.rs
@@ -5789,7 +5789,7 @@
------------------------
-Add the methods `from_mins`, `from_hours` and `from_days` to `Duration`.
+Add the methods `from_days` and `from_weeks` to `Duration`.
"##,
default_severity: Severity::Allow,
warn_since: None,
diff --git a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index 364bead..6bd5417 100644
--- a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -915,4 +915,47 @@
"#,
);
}
+
+ #[test]
+ fn regression_19823() {
+ check_diagnostics(
+ r#"
+pub trait FooTrait {
+ unsafe fn method1();
+ unsafe fn method2();
+}
+
+unsafe fn some_unsafe_fn() {}
+
+macro_rules! impl_foo {
+ () => {
+ unsafe fn method1() {
+ some_unsafe_fn();
+ }
+ unsafe fn method2() {
+ some_unsafe_fn();
+ }
+ };
+}
+
+pub struct S1;
+#[allow(unsafe_op_in_unsafe_fn)]
+impl FooTrait for S1 {
+ unsafe fn method1() {
+ some_unsafe_fn();
+ }
+
+ unsafe fn method2() {
+ some_unsafe_fn();
+ }
+}
+
+pub struct S2;
+#[allow(unsafe_op_in_unsafe_fn)]
+impl FooTrait for S2 {
+ impl_foo!();
+}
+ "#,
+ );
+ }
}
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 2af14ca..72bd66d 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -83,12 +83,11 @@
#[cfg(test)]
mod tests;
-use std::{collections::hash_map, iter, sync::LazyLock};
+use std::{iter, sync::LazyLock};
use either::Either;
use hir::{
- Crate, DisplayTarget, HirFileId, InFile, Semantics, db::ExpandDatabase,
- diagnostics::AnyDiagnostic,
+ Crate, DisplayTarget, InFile, Semantics, db::ExpandDatabase, diagnostics::AnyDiagnostic,
};
use ide_db::{
EditionedFileId, FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, Severity, SnippetCap,
@@ -513,13 +512,7 @@
// The edition isn't accurate (each diagnostics may have its own edition due to macros),
// but it's okay as it's only being used for error recovery.
- handle_lints(
- &ctx.sema,
- &mut FxHashMap::default(),
- &mut lints,
- &mut Vec::new(),
- editioned_file_id.edition(db),
- );
+ handle_lints(&ctx.sema, &mut lints, editioned_file_id.edition(db));
res.retain(|d| d.severity != Severity::Allow);
@@ -584,8 +577,6 @@
true
}
-// `__RA_EVERY_LINT` is a fake lint group to allow every lint in proc macros
-
struct BuiltLint {
lint: &'static Lint,
groups: Vec<&'static str>,
@@ -629,9 +620,7 @@
fn handle_lints(
sema: &Semantics<'_, RootDatabase>,
- cache: &mut FxHashMap<HirFileId, FxHashMap<SmolStr, SeverityAttr>>,
diagnostics: &mut [(InFile<SyntaxNode>, &mut Diagnostic)],
- cache_stack: &mut Vec<HirFileId>,
edition: Edition,
) {
for (node, diag) in diagnostics {
@@ -645,7 +634,8 @@
diag.severity = default_severity;
}
- let mut diag_severity = fill_lint_attrs(sema, node, cache, cache_stack, diag, edition);
+ let mut diag_severity =
+ lint_severity_at(sema, node, &lint_groups(&diag.code, edition), edition);
if let outline_diag_severity @ Some(_) =
find_outline_mod_lint_severity(sema, node, diag, edition)
@@ -698,155 +688,22 @@
result
}
-#[derive(Debug, Clone, Copy)]
-struct SeverityAttr {
- severity: Severity,
- /// This field counts how far we are from the main node. Bigger values mean more far.
- ///
- /// Note this isn't accurate: there can be gaps between values (created when merging severity maps).
- /// The important thing is that if an attr is closer to the main node, it will have smaller value.
- ///
- /// This is necessary even though we take care to never overwrite a value from deeper nesting
- /// because of lint groups. For example, in the following code:
- /// ```
- /// #[warn(non_snake_case)]
- /// mod foo {
- /// #[allow(nonstandard_style)]
- /// mod bar {}
- /// }
- /// ```
- /// We want to not warn on non snake case inside `bar`. If we are traversing this for the first
- /// time, everything will be fine, because we will set `diag_severity` on the first matching group
- /// and never overwrite it since then. But if `bar` is cached, the cache will contain both
- /// `#[warn(non_snake_case)]` and `#[allow(nonstandard_style)]`, and without this field, we have
- /// no way of differentiating between the two.
- depth: u32,
-}
-
-fn fill_lint_attrs(
+fn lint_severity_at(
sema: &Semantics<'_, RootDatabase>,
node: &InFile<SyntaxNode>,
- cache: &mut FxHashMap<HirFileId, FxHashMap<SmolStr, SeverityAttr>>,
- cache_stack: &mut Vec<HirFileId>,
- diag: &Diagnostic,
+ lint_groups: &LintGroups,
edition: Edition,
) -> Option<Severity> {
- let mut collected_lint_attrs = FxHashMap::<SmolStr, SeverityAttr>::default();
- let mut diag_severity = None;
-
- let mut ancestors = node.value.ancestors().peekable();
- let mut depth = 0;
- loop {
- let ancestor = ancestors.next().expect("we always return from top-level nodes");
- depth += 1;
-
- if ancestors.peek().is_none() {
- // We don't want to insert too many nodes into cache, but top level nodes (aka. outline modules
- // or macro expansions) need to touch the database so they seem like a good fit to cache.
-
- if let Some(cached) = cache.get_mut(&node.file_id) {
- // This node (and everything above it) is already cached; the attribute is either here or nowhere.
-
- // Workaround for the borrow checker.
- let cached = std::mem::take(cached);
-
- cached.iter().for_each(|(lint, severity)| {
- for item in &*cache_stack {
- let node_cache_entry = cache
- .get_mut(item)
- .expect("we always insert cached nodes into the cache map");
- let lint_cache_entry = node_cache_entry.entry(lint.clone());
- if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry {
- // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs
- // overwrite top attrs.
- lint_cache_entry.insert(SeverityAttr {
- severity: severity.severity,
- depth: severity.depth + depth,
- });
- }
- }
- });
-
- let lints = lint_groups(&diag.code, edition);
- let all_matching_groups =
- lints.iter().filter_map(|lint_group| cached.get(lint_group));
- let cached_severity =
- all_matching_groups.min_by_key(|it| it.depth).map(|it| it.severity);
-
- cache.insert(node.file_id, cached);
-
- return diag_severity.or(cached_severity);
- }
-
- // Insert this node's descendants' attributes into any outline descendant, but not including this node.
- // This must come before inserting this node's own attributes to preserve order.
- collected_lint_attrs.drain().for_each(|(lint, severity)| {
- if diag_severity.is_none() && lint_groups(&diag.code, edition).contains(&lint) {
- diag_severity = Some(severity.severity);
- }
-
- for item in &*cache_stack {
- let node_cache_entry = cache
- .get_mut(item)
- .expect("we always insert cached nodes into the cache map");
- let lint_cache_entry = node_cache_entry.entry(lint.clone());
- if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry {
- // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs
- // overwrite top attrs.
- lint_cache_entry.insert(severity);
- }
- }
- });
-
- cache_stack.push(node.file_id);
- cache.insert(node.file_id, FxHashMap::default());
-
- if let Some(ancestor) = ast::AnyHasAttrs::cast(ancestor) {
- // Insert this node's attributes into any outline descendant, including this node.
- lint_attrs(sema, ancestor, edition).for_each(|(lint, severity)| {
- if diag_severity.is_none() && lint_groups(&diag.code, edition).contains(&lint) {
- diag_severity = Some(severity);
- }
-
- for item in &*cache_stack {
- let node_cache_entry = cache
- .get_mut(item)
- .expect("we always insert cached nodes into the cache map");
- let lint_cache_entry = node_cache_entry.entry(lint.clone());
- if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry {
- // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs
- // overwrite top attrs.
- lint_cache_entry.insert(SeverityAttr { severity, depth });
- }
- }
- });
- }
-
- let parent_node = sema.find_parent_file(node.file_id);
- if let Some(parent_node) = parent_node {
- let parent_severity =
- fill_lint_attrs(sema, &parent_node, cache, cache_stack, diag, edition);
- if diag_severity.is_none() {
- diag_severity = parent_severity;
- }
- }
- cache_stack.pop();
- return diag_severity;
- } else if let Some(ancestor) = ast::AnyHasAttrs::cast(ancestor) {
- lint_attrs(sema, ancestor, edition).for_each(|(lint, severity)| {
- if diag_severity.is_none() && lint_groups(&diag.code, edition).contains(&lint) {
- diag_severity = Some(severity);
- }
-
- let lint_cache_entry = collected_lint_attrs.entry(lint);
- if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry {
- // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs
- // overwrite top attrs.
- lint_cache_entry.insert(SeverityAttr { severity, depth });
- }
- });
- }
- }
+ node.value
+ .ancestors()
+ .filter_map(ast::AnyHasAttrs::cast)
+ .find_map(|ancestor| {
+ lint_attrs(sema, ancestor, edition)
+ .find_map(|(lint, severity)| lint_groups.contains(&lint).then_some(severity))
+ })
+ .or_else(|| {
+ lint_severity_at(sema, &sema.find_parent_file(node.file_id)?, lint_groups, edition)
+ })
}
fn lint_attrs<'a>(
@@ -945,10 +802,6 @@
fn contains(&self, group: &str) -> bool {
self.groups.contains(&group) || (self.inside_warnings && group == "warnings")
}
-
- fn iter(&self) -> impl Iterator<Item = &'static str> {
- self.groups.iter().copied().chain(self.inside_warnings.then_some("warnings"))
- }
}
fn lint_groups(lint: &DiagnosticCode, edition: Edition) -> LintGroups {
diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs
index 585e7ff..0fa9a26 100644
--- a/crates/parser/src/lexed_str.rs
+++ b/crates/parser/src/lexed_str.rs
@@ -179,6 +179,18 @@
COMMENT
}
+ rustc_lexer::TokenKind::Frontmatter {
+ has_invalid_preceding_whitespace,
+ invalid_infostring,
+ } => {
+ if *has_invalid_preceding_whitespace {
+ err = "invalid preceding whitespace for frontmatter opening"
+ } else if *invalid_infostring {
+ err = "invalid infostring for frontmatter"
+ }
+ FRONTMATTER
+ }
+
rustc_lexer::TokenKind::Whitespace => WHITESPACE,
rustc_lexer::TokenKind::Ident if token_text == "_" => UNDERSCORE,
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index e6f93a1..b172750 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -150,6 +150,7 @@
STRING,
COMMENT,
ERROR,
+ FRONTMATTER,
IDENT,
LIFETIME_IDENT,
NEWLINE,
@@ -483,6 +484,7 @@
| YIELD_EXPR
| COMMENT
| ERROR
+ | FRONTMATTER
| IDENT
| LIFETIME_IDENT
| NEWLINE
@@ -994,7 +996,7 @@
}
}
#[macro_export]
-macro_rules ! T_ { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [inlateout] => { $ crate :: SyntaxKind :: INLATEOUT_KW } ; [inout] => { $ crate :: SyntaxKind :: INOUT_KW } ; [label] => { $ crate :: SyntaxKind :: LABEL_KW } ; [lateout] => { $ crate :: SyntaxKind :: LATEOUT_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [may_unwind] => { $ crate :: SyntaxKind :: MAY_UNWIND_KW } ; [nomem] => { $ crate :: SyntaxKind :: NOMEM_KW } ; [noreturn] => { $ crate :: SyntaxKind :: NORETURN_KW } ; [nostack] => { $ crate :: SyntaxKind :: NOSTACK_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [options] => { $ crate :: SyntaxKind :: OPTIONS_KW } ; [out] => { $ crate :: SyntaxKind :: OUT_KW } ; [preserves_flags] => { $ crate :: SyntaxKind :: PRESERVES_FLAGS_KW } ; [pure] => { $ crate :: SyntaxKind :: PURE_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [readonly] => { $ crate :: SyntaxKind :: READONLY_KW } ; [safe] => { $ crate :: SyntaxKind :: SAFE_KW } ; [sym] => { $ crate :: SyntaxKind :: SYM_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
+macro_rules ! T_ { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [inlateout] => { $ crate :: SyntaxKind :: INLATEOUT_KW } ; [inout] => { $ crate :: SyntaxKind :: INOUT_KW } ; [label] => { $ crate :: SyntaxKind :: LABEL_KW } ; [lateout] => { $ crate :: SyntaxKind :: LATEOUT_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [may_unwind] => { $ crate :: SyntaxKind :: MAY_UNWIND_KW } ; [nomem] => { $ crate :: SyntaxKind :: NOMEM_KW } ; [noreturn] => { $ crate :: SyntaxKind :: NORETURN_KW } ; [nostack] => { $ crate :: SyntaxKind :: NOSTACK_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [options] => { $ crate :: SyntaxKind :: OPTIONS_KW } ; [out] => { $ crate :: SyntaxKind :: OUT_KW } ; [preserves_flags] => { $ crate :: SyntaxKind :: PRESERVES_FLAGS_KW } ; [pure] => { $ crate :: SyntaxKind :: PURE_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [readonly] => { $ crate :: SyntaxKind :: READONLY_KW } ; [safe] => { $ crate :: SyntaxKind :: SAFE_KW } ; [sym] => { $ crate :: SyntaxKind :: SYM_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; [frontmatter] => { $ crate :: SyntaxKind :: FRONTMATTER } ; }
impl ::core::marker::Copy for SyntaxKind {}
impl ::core::clone::Clone for SyntaxKind {
#[inline]
diff --git a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
index 64b40e7..e0c6e68 100644
--- a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
+++ b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
@@ -258,7 +258,9 @@
&mut self,
stream: Self::TokenStream,
) -> Vec<bridge::TokenTree<Self::TokenStream, Self::Span, Self::Symbol>> {
- stream.into_bridge()
+ stream.into_bridge(&mut |first, second| {
+ server::Span::join(self, first, second).unwrap_or(first)
+ })
}
}
diff --git a/crates/proc-macro-srv/src/server_impl/token_id.rs b/crates/proc-macro-srv/src/server_impl/token_id.rs
index 24a67bf..d55b269 100644
--- a/crates/proc-macro-srv/src/server_impl/token_id.rs
+++ b/crates/proc-macro-srv/src/server_impl/token_id.rs
@@ -238,7 +238,8 @@
&mut self,
stream: Self::TokenStream,
) -> Vec<bridge::TokenTree<Self::TokenStream, Self::Span, Self::Symbol>> {
- stream.into_bridge()
+ // Can't join with `TokenId`.
+ stream.into_bridge(&mut |first, _second| first)
}
}
diff --git a/crates/proc-macro-srv/src/server_impl/token_stream.rs b/crates/proc-macro-srv/src/server_impl/token_stream.rs
index 0725579..c5019a5 100644
--- a/crates/proc-macro-srv/src/server_impl/token_stream.rs
+++ b/crates/proc-macro-srv/src/server_impl/token_stream.rs
@@ -56,7 +56,10 @@
self.token_trees.is_empty()
}
- pub(crate) fn into_bridge(self) -> Vec<bridge::TokenTree<Self, S, intern::Symbol>> {
+ pub(crate) fn into_bridge(
+ self,
+ join_spans: &mut dyn FnMut(S, S) -> S,
+ ) -> Vec<bridge::TokenTree<Self, S, intern::Symbol>> {
let mut result = Vec::new();
let mut iter = self.token_trees.into_iter();
while let Some(tree) = iter.next() {
@@ -98,7 +101,11 @@
token_trees: iter.by_ref().take(subtree.usize_len()).collect(),
})
},
- span: bridge::DelimSpan::from_single(subtree.delimiter.open),
+ span: bridge::DelimSpan {
+ open: subtree.delimiter.open,
+ close: subtree.delimiter.close,
+ entire: join_spans(subtree.delimiter.open, subtree.delimiter.close),
+ },
}))
}
}
diff --git a/crates/proc-macro-srv/src/tests/mod.rs b/crates/proc-macro-srv/src/tests/mod.rs
index 36cd675..3a6ce63 100644
--- a/crates/proc-macro-srv/src/tests/mod.rs
+++ b/crates/proc-macro-srv/src/tests/mod.rs
@@ -144,7 +144,7 @@
SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
IDENT ident 42:2@0..5#ROOT2024
PUNCH , [alone] 42:2@5..6#ROOT2024
- SUBTREE [] 42:2@7..8#ROOT2024 42:2@7..8#ROOT2024"#]],
+ SUBTREE [] 42:2@7..9#ROOT2024 42:2@7..9#ROOT2024"#]],
);
}
@@ -173,7 +173,6 @@
}
#[test]
-#[cfg(not(bootstrap))]
fn test_fn_like_fn_like_span_join() {
assert_expand(
"fn_like_span_join",
@@ -200,7 +199,6 @@
}
#[test]
-#[cfg(not(bootstrap))]
fn test_fn_like_fn_like_span_ops() {
assert_expand(
"fn_like_span_ops",
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index a1e4adf..671e838 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -4,6 +4,7 @@
use std::{
env, fmt,
ops::AddAssign,
+ panic::{AssertUnwindSafe, catch_unwind},
time::{SystemTime, UNIX_EPOCH},
};
@@ -721,6 +722,7 @@
let mut num_pats_unknown = 0;
let mut num_pats_partially_unknown = 0;
let mut num_pat_type_mismatches = 0;
+ let mut panics = 0;
for &body_id in bodies {
let name = body_id.name(db).unwrap_or_else(Name::missing);
let module = body_id.module(db);
@@ -774,7 +776,20 @@
}
bar.set_message(msg);
let body = db.body(body_id.into());
- let inference_result = db.infer(body_id.into());
+ let inference_result = catch_unwind(AssertUnwindSafe(|| db.infer(body_id.into())));
+ let inference_result = match inference_result {
+ Ok(inference_result) => inference_result,
+ Err(p) => {
+ if let Some(s) = p.downcast_ref::<&str>() {
+ eprintln!("infer panicked for {}: {}", full_name(), s);
+ } else if let Some(s) = p.downcast_ref::<String>() {
+ eprintln!("infer panicked for {}: {}", full_name(), s);
+ }
+ panics += 1;
+ bar.inc(1);
+ continue;
+ }
+ };
// This query is LRU'd, so actually calling it will skew the timing results.
let sm = || db.body_with_source_map(body_id.into()).1;
@@ -1008,6 +1023,7 @@
percentage(num_pats_partially_unknown, num_pats),
num_pat_type_mismatches
);
+ eprintln!(" panics: {}", panics);
eprintln!("{:<20} {}", "Inference:", inference_time);
report_metric("unknown type", num_exprs_unknown, "#");
report_metric("type mismatches", num_expr_type_mismatches, "#");
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 1a31525..a870232 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -3,7 +3,11 @@
//!
//! Each tick provides an immutable snapshot of the state as `WorldSnapshot`.
-use std::{ops::Not as _, panic::AssertUnwindSafe, time::Instant};
+use std::{
+ ops::Not as _,
+ panic::AssertUnwindSafe,
+ time::{Duration, Instant},
+};
use crossbeam_channel::{Receiver, Sender, unbounded};
use hir::ChangeWithProcMacros;
@@ -41,6 +45,7 @@
test_runner::{CargoTestHandle, CargoTestMessage},
};
+#[derive(Debug)]
pub(crate) struct FetchWorkspaceRequest {
pub(crate) path: Option<AbsPathBuf>,
pub(crate) force_crate_graph_reload: bool,
@@ -116,6 +121,11 @@
pub(crate) discover_sender: Sender<discover::DiscoverProjectMessage>,
pub(crate) discover_receiver: Receiver<discover::DiscoverProjectMessage>,
+ // Debouncing channel for fetching the workspace
+ // we want to delay it until the VFS looks stable-ish (and thus is not currently in the middle
+ // of a VCS operation like `git switch`)
+ pub(crate) fetch_ws_receiver: Option<(Receiver<Instant>, FetchWorkspaceRequest)>,
+
// VFS
pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>,
pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
@@ -268,6 +278,8 @@
discover_sender,
discover_receiver,
+ fetch_ws_receiver: None,
+
vfs: Arc::new(RwLock::new((vfs::Vfs::default(), Default::default()))),
vfs_config_version: 0,
vfs_progress_config_version: 0,
@@ -519,11 +531,7 @@
if let Some((path, force_crate_graph_reload)) = workspace_structure_change {
let _p = span!(Level::INFO, "GlobalState::process_changes/ws_structure_change")
.entered();
-
- self.fetch_workspaces_queue.request_op(
- format!("workspace vfs file change: {path}"),
- FetchWorkspaceRequest { path: Some(path), force_crate_graph_reload },
- );
+ self.enqueue_workspace_fetch(path, force_crate_graph_reload);
}
}
@@ -671,6 +679,30 @@
None
})
}
+
+ fn enqueue_workspace_fetch(&mut self, path: AbsPathBuf, force_crate_graph_reload: bool) {
+ let already_requested = self.fetch_workspaces_queue.op_requested()
+ && !self.fetch_workspaces_queue.op_in_progress();
+ if self.fetch_ws_receiver.is_none() && already_requested {
+ // Don't queue up a new fetch request if we already have done so
+ // Otherwise we will re-fetch in quick succession which is unnecessary
+ // Note though, that if one is already in progress, we *want* to re-queue
+ // as the in-progress fetch might not have the latest changes in it anymore
+ // FIXME: We should cancel the in-progress fetch here
+ return;
+ }
+
+ self.fetch_ws_receiver = Some((
+ crossbeam_channel::after(Duration::from_millis(100)),
+ FetchWorkspaceRequest { path: Some(path), force_crate_graph_reload },
+ ));
+ }
+
+ pub(crate) fn debounce_workspace_fetch(&mut self) {
+ if let Some((fetch_receiver, _)) = &mut self.fetch_ws_receiver {
+ *fetch_receiver = crossbeam_channel::after(Duration::from_millis(100));
+ }
+ }
}
impl Drop for GlobalState {
diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs
index 49ebffa..84b7888 100644
--- a/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -147,7 +147,7 @@
let _it = stdx::timeit("change");
let mut text = host.analysis().file_text(file_id).unwrap().to_string();
let completion_offset =
- patch(&mut text, "db.struct_data(self.id)", "sel;\ndb.struct_data(self.id)")
+ patch(&mut text, "db.struct_signature(self.id)", "sel;\ndb.struct_signature(self.id)")
+ "sel".len();
let mut change = ChangeWithProcMacros::default();
change.change_file(file_id, Some(text));
@@ -197,9 +197,11 @@
let completion_offset = {
let _it = stdx::timeit("change");
let mut text = host.analysis().file_text(file_id).unwrap().to_string();
- let completion_offset =
- patch(&mut text, "sel;\ndb.struct_data(self.id)", ";sel;\ndb.struct_data(self.id)")
- + ";sel".len();
+ let completion_offset = patch(
+ &mut text,
+ "sel;\ndb.struct_signature(self.id)",
+ ";sel;\ndb.struct_signature(self.id)",
+ ) + ";sel".len();
let mut change = ChangeWithProcMacros::default();
change.change_file(file_id, Some(text));
host.apply_change(change);
@@ -247,9 +249,11 @@
let completion_offset = {
let _it = stdx::timeit("change");
let mut text = host.analysis().file_text(file_id).unwrap().to_string();
- let completion_offset =
- patch(&mut text, "sel;\ndb.struct_data(self.id)", "self.;\ndb.struct_data(self.id)")
- + "self.".len();
+ let completion_offset = patch(
+ &mut text,
+ "sel;\ndb.struct_signature(self.id)",
+ "self.;\ndb.struct_signature(self.id)",
+ ) + "self.".len();
let mut change = ChangeWithProcMacros::default();
change.change_file(file_id, Some(text));
host.apply_change(change);
@@ -366,7 +370,7 @@
{
let _it = stdx::timeit("change");
let mut text = host.analysis().file_text(file_id).unwrap().to_string();
- patch(&mut text, "db.struct_data(self.id)", "();\ndb.struct_data(self.id)");
+ patch(&mut text, "db.struct_signature(self.id)", "();\ndb.struct_signature(self.id)");
let mut change = ChangeWithProcMacros::default();
change.change_file(file_id, Some(text));
host.apply_change(change);
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index bd213ff..0c0438c 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -8,7 +8,7 @@
time::{Duration, Instant},
};
-use crossbeam_channel::{Receiver, select};
+use crossbeam_channel::{Receiver, never, select};
use ide_db::base_db::{SourceDatabase, VfsPath, salsa::Database as _};
use lsp_server::{Connection, Notification, Request};
use lsp_types::{TextDocumentIdentifier, notification::Notification as _};
@@ -71,6 +71,7 @@
Flycheck(FlycheckMessage),
TestResult(CargoTestMessage),
DiscoverProject(DiscoverProjectMessage),
+ FetchWorkspaces(FetchWorkspaceRequest),
}
impl fmt::Display for Event {
@@ -83,6 +84,7 @@
Event::QueuedTask(_) => write!(f, "Event::QueuedTask"),
Event::TestResult(_) => write!(f, "Event::TestResult"),
Event::DiscoverProject(_) => write!(f, "Event::DiscoverProject"),
+ Event::FetchWorkspaces(_) => write!(f, "Event::SwitchWorkspaces"),
}
}
}
@@ -150,6 +152,7 @@
}
_ => (),
}
+
match self {
Event::Lsp(it) => fmt::Debug::fmt(it, f),
Event::Task(it) => fmt::Debug::fmt(it, f),
@@ -158,6 +161,7 @@
Event::Flycheck(it) => fmt::Debug::fmt(it, f),
Event::TestResult(it) => fmt::Debug::fmt(it, f),
Event::DiscoverProject(it) => fmt::Debug::fmt(it, f),
+ Event::FetchWorkspaces(it) => fmt::Debug::fmt(it, f),
}
}
}
@@ -251,7 +255,7 @@
}
fn next_event(
- &self,
+ &mut self,
inbox: &Receiver<lsp_server::Message>,
) -> Result<Option<Event>, crossbeam_channel::RecvError> {
// Make sure we reply to formatting requests ASAP so the editor doesn't block
@@ -283,6 +287,10 @@
recv(self.discover_receiver) -> task =>
task.map(Event::DiscoverProject),
+
+ recv(self.fetch_ws_receiver.as_ref().map_or(&never(), |(chan, _)| chan)) -> _instant => {
+ Ok(Event::FetchWorkspaces(self.fetch_ws_receiver.take().unwrap().1))
+ },
}
.map(Some)
}
@@ -412,6 +420,9 @@
self.handle_discover_msg(message);
}
}
+ Event::FetchWorkspaces(req) => {
+ self.fetch_workspaces_queue.request_op("project structure change".to_owned(), req)
+ }
}
let event_handling_duration = loop_start.elapsed();
let (state_changed, memdocs_added_or_removed) = if self.vfs_done {
@@ -830,6 +841,7 @@
match message {
vfs::loader::Message::Changed { files } | vfs::loader::Message::Loaded { files } => {
let _p = tracing::info_span!("GlobalState::handle_vfs_msg{changed/load}").entered();
+ self.debounce_workspace_fetch();
let vfs = &mut self.vfs.write().0;
for (path, contents) in files {
let path = VfsPath::from(path);
diff --git a/crates/rust-analyzer/src/op_queue.rs b/crates/rust-analyzer/src/op_queue.rs
index 709d99b..7af5b48 100644
--- a/crates/rust-analyzer/src/op_queue.rs
+++ b/crates/rust-analyzer/src/op_queue.rs
@@ -36,7 +36,7 @@
}
}
-impl<Args, Output> OpQueue<Args, Output> {
+impl<Args: std::fmt::Debug, Output> OpQueue<Args, Output> {
/// Request an operation to start.
pub(crate) fn request_op(&mut self, reason: Cause, args: Args) {
self.op_requested = Some((reason, args));
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index d7c6aec..ae9e3e9 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -69,6 +69,7 @@
/// are ready to do semantic work.
pub(crate) fn is_quiescent(&self) -> bool {
self.vfs_done
+ && self.fetch_ws_receiver.is_none()
&& !self.fetch_workspaces_queue.op_in_progress()
&& !self.fetch_build_data_queue.op_in_progress()
&& !self.fetch_proc_macros_queue.op_in_progress()
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index a0ae0d6..10abca7 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -133,6 +133,7 @@
SourceFile =
'#shebang'?
+ '#frontmatter'?
Attr*
Item*
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 1243f64..cd9f4db 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -1525,6 +1525,10 @@
impl ast::HasModuleItem for SourceFile {}
impl SourceFile {
#[inline]
+ pub fn frontmatter_token(&self) -> Option<SyntaxToken> {
+ support::token(&self.syntax, T![frontmatter])
+ }
+ #[inline]
pub fn shebang_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![shebang]) }
}
pub struct Static {
diff --git a/rust-version b/rust-version
index 90e4d65..5b47d1b 100644
--- a/rust-version
+++ b/rust-version
@@ -1 +1 @@
-6e23095adf9209614a45f7f75fea36dad7b92afb
+a8e4c68dcb4dc1e48a0db294c5323cab0227fcb9
diff --git a/xtask/src/codegen/grammar.rs b/xtask/src/codegen/grammar.rs
index 4b9c6ed..824b38f 100644
--- a/xtask/src/codegen/grammar.rs
+++ b/xtask/src/codegen/grammar.rs
@@ -670,6 +670,7 @@
[ident] => { $crate::SyntaxKind::IDENT };
[string] => { $crate::SyntaxKind::STRING };
[shebang] => { $crate::SyntaxKind::SHEBANG };
+ [frontmatter] => { $crate::SyntaxKind::FRONTMATTER };
}
impl ::core::marker::Copy for SyntaxKind {}