diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index ec197767259..fc77515b63b 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -572,6 +572,7 @@ dependencies = [ "chalk-recursive", "chalk-solve", "cov-mark", + "either", "ena", "expect-test", "hir-def", @@ -1714,6 +1715,7 @@ name = "syntax" version = "0.0.0" dependencies = [ "cov-mark", + "either", "expect-test", "indexmap", "itertools", diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs index 11f7b068ecb..accb14a51de 100644 --- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs +++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs @@ -76,7 +76,7 @@ impl fmt::Display for FlycheckConfig { #[derive(Debug)] pub struct FlycheckHandle { // XXX: drop order is significant - sender: Sender, + sender: Sender, _thread: jod_thread::JoinHandle, id: usize, } @@ -89,7 +89,7 @@ impl FlycheckHandle { workspace_root: AbsPathBuf, ) -> FlycheckHandle { let actor = FlycheckActor::new(id, sender, config, workspace_root); - let (sender, receiver) = unbounded::(); + let (sender, receiver) = unbounded::(); let thread = jod_thread::Builder::new() .name("Flycheck".to_owned()) .spawn(move || actor.run(receiver)) @@ -99,12 +99,12 @@ impl FlycheckHandle { /// Schedule a re-start of the cargo check worker. pub fn restart(&self) { - self.sender.send(Restart::Yes).unwrap(); + self.sender.send(StateChange::Restart).unwrap(); } /// Stop this cargo check worker. pub fn cancel(&self) { - self.sender.send(Restart::No).unwrap(); + self.sender.send(StateChange::Cancel).unwrap(); } pub fn id(&self) -> usize { @@ -149,9 +149,9 @@ pub enum Progress { DidFailToRestart(String), } -enum Restart { - Yes, - No, +enum StateChange { + Restart, + Cancel, } /// A [`FlycheckActor`] is a single check instance of a workspace. @@ -172,7 +172,7 @@ struct FlycheckActor { } enum Event { - Restart(Restart), + RequestStateChange(StateChange), CheckEvent(Option), } @@ -191,30 +191,31 @@ impl FlycheckActor { self.send(Message::Progress { id: self.id, progress }); } - fn next_event(&self, inbox: &Receiver) -> Option { + fn next_event(&self, inbox: &Receiver) -> Option { let check_chan = self.cargo_handle.as_ref().map(|cargo| &cargo.receiver); if let Ok(msg) = inbox.try_recv() { // give restarts a preference so check outputs don't block a restart or stop - return Some(Event::Restart(msg)); + return Some(Event::RequestStateChange(msg)); } select! { - recv(inbox) -> msg => msg.ok().map(Event::Restart), + recv(inbox) -> msg => msg.ok().map(Event::RequestStateChange), recv(check_chan.unwrap_or(&never())) -> msg => Some(Event::CheckEvent(msg.ok())), } } - fn run(mut self, inbox: Receiver) { + fn run(mut self, inbox: Receiver) { 'event: while let Some(event) = self.next_event(&inbox) { match event { - Event::Restart(Restart::No) => { + Event::RequestStateChange(StateChange::Cancel) => { + tracing::debug!(flycheck_id = self.id, "flycheck cancelled"); self.cancel_check_process(); } - Event::Restart(Restart::Yes) => { + Event::RequestStateChange(StateChange::Restart) => { // Cancel the previously spawned process self.cancel_check_process(); while let Ok(restart) = inbox.recv_timeout(Duration::from_millis(50)) { // restart chained with a stop, so just cancel - if let Restart::No = restart { + if let StateChange::Cancel = restart { continue 'event; } } @@ -255,10 +256,20 @@ impl FlycheckActor { } Event::CheckEvent(Some(message)) => match message { CargoMessage::CompilerArtifact(msg) => { + tracing::trace!( + flycheck_id = self.id, + artifact = msg.target.name, + "artifact received" + ); self.report_progress(Progress::DidCheckCrate(msg.target.name)); } CargoMessage::Diagnostic(msg) => { + tracing::trace!( + flycheck_id = self.id, + message = msg.message, + "diagnostic received" + ); self.send(Message::AddDiagnostic { id: self.id, workspace_root: self.root.clone(), @@ -445,42 +456,56 @@ impl CargoActor { // simply skip a line if it doesn't parse, which just ignores any // erroneous output. - let mut error = String::new(); - let mut read_at_least_one_message = false; + let mut stdout_errors = String::new(); + let mut stderr_errors = String::new(); + let mut read_at_least_one_stdout_message = false; + let mut read_at_least_one_stderr_message = false; + let process_line = |line: &str, error: &mut String| { + // Try to deserialize a message from Cargo or Rustc. + let mut deserializer = serde_json::Deserializer::from_str(line); + deserializer.disable_recursion_limit(); + if let Ok(message) = JsonMessage::deserialize(&mut deserializer) { + match message { + // Skip certain kinds of messages to only spend time on what's useful + JsonMessage::Cargo(message) => match message { + cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => { + self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap(); + } + cargo_metadata::Message::CompilerMessage(msg) => { + self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap(); + } + _ => (), + }, + JsonMessage::Rustc(message) => { + self.sender.send(CargoMessage::Diagnostic(message)).unwrap(); + } + } + return true; + } + + error.push_str(line); + error.push('\n'); + return false; + }; let output = streaming_output( self.stdout, self.stderr, &mut |line| { - read_at_least_one_message = true; - - // Try to deserialize a message from Cargo or Rustc. - let mut deserializer = serde_json::Deserializer::from_str(line); - deserializer.disable_recursion_limit(); - if let Ok(message) = JsonMessage::deserialize(&mut deserializer) { - match message { - // Skip certain kinds of messages to only spend time on what's useful - JsonMessage::Cargo(message) => match message { - cargo_metadata::Message::CompilerArtifact(artifact) - if !artifact.fresh => - { - self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap(); - } - cargo_metadata::Message::CompilerMessage(msg) => { - self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap(); - } - _ => (), - }, - JsonMessage::Rustc(message) => { - self.sender.send(CargoMessage::Diagnostic(message)).unwrap(); - } - } + if process_line(line, &mut stdout_errors) { + read_at_least_one_stdout_message = true; } }, &mut |line| { - error.push_str(line); - error.push('\n'); + if process_line(line, &mut stderr_errors) { + read_at_least_one_stderr_message = true; + } }, ); + + let read_at_least_one_message = + read_at_least_one_stdout_message || read_at_least_one_stderr_message; + let mut error = stdout_errors; + error.push_str(&stderr_errors); match output { Ok(_) => Ok((read_at_least_one_message, error)), Err(e) => Err(io::Error::new(e.kind(), format!("{e:?}: {error}"))), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index fcd92ad3385..200072c172e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -300,6 +300,7 @@ impl AttrsWithOwner { AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db), }, AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db), + AttrDefId::TraitAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), AttrDefId::MacroId(it) => match it { MacroId::Macro2Id(it) => attrs_from_item_tree(it.lookup(db).id, db), MacroId::MacroRulesId(it) => attrs_from_item_tree(it.lookup(db).id, db), @@ -315,26 +316,14 @@ impl AttrsWithOwner { let src = it.parent().child_source(db); RawAttrs::from_attrs_owner( db.upcast(), - src.with_value(src.value[it.local_id()].as_ref().either( - |it| match it { - ast::TypeOrConstParam::Type(it) => it as _, - ast::TypeOrConstParam::Const(it) => it as _, - }, - |it| it as _, - )), + src.with_value(&src.value[it.local_id()]), ) } GenericParamId::TypeParamId(it) => { let src = it.parent().child_source(db); RawAttrs::from_attrs_owner( db.upcast(), - src.with_value(src.value[it.local_id()].as_ref().either( - |it| match it { - ast::TypeOrConstParam::Type(it) => it as _, - ast::TypeOrConstParam::Const(it) => it as _, - }, - |it| it as _, - )), + src.with_value(&src.value[it.local_id()]), ) } GenericParamId::LifetimeParamId(it) => { @@ -404,6 +393,7 @@ impl AttrsWithOwner { AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), + AttrDefId::TraitAliasId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::TypeAliasId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::MacroId(id) => match id { MacroId::Macro2Id(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), @@ -412,28 +402,14 @@ impl AttrsWithOwner { }, AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new), AttrDefId::GenericParamId(id) => match id { - GenericParamId::ConstParamId(id) => { - id.parent().child_source(db).map(|source| match &source[id.local_id()] { - Either::Left(ast::TypeOrConstParam::Type(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Left(ast::TypeOrConstParam::Const(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Right(id) => ast::AnyHasAttrs::new(id.clone()), - }) - } - GenericParamId::TypeParamId(id) => { - id.parent().child_source(db).map(|source| match &source[id.local_id()] { - Either::Left(ast::TypeOrConstParam::Type(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Left(ast::TypeOrConstParam::Const(id)) => { - ast::AnyHasAttrs::new(id.clone()) - } - Either::Right(id) => ast::AnyHasAttrs::new(id.clone()), - }) - } + GenericParamId::ConstParamId(id) => id + .parent() + .child_source(db) + .map(|source| ast::AnyHasAttrs::new(source[id.local_id()].clone())), + GenericParamId::TypeParamId(id) => id + .parent() + .child_source(db) + .map(|source| ast::AnyHasAttrs::new(source[id.local_id()].clone())), GenericParamId::LifetimeParamId(id) => id .parent .child_source(db) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index 8fd9255b8b1..3be477d4877 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -24,7 +24,7 @@ use syntax::{ast, AstPtr, SyntaxNode, SyntaxNodePtr}; use crate::{ attr::Attrs, db::DefDatabase, - expr::{dummy_expr_id, Expr, ExprId, Label, LabelId, Pat, PatId}, + expr::{dummy_expr_id, Binding, BindingId, Expr, ExprId, Label, LabelId, Pat, PatId}, item_scope::BuiltinShadowMode, macro_id_to_def_id, nameres::DefMap, @@ -270,7 +270,7 @@ pub struct Mark { pub struct Body { pub exprs: Arena, pub pats: Arena, - pub or_pats: FxHashMap>, + pub bindings: Arena, pub labels: Arena