From dba167592ee67748d2f24c8f646cbe193c95da14 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Thu, 16 Nov 2023 17:22:53 +0800 Subject: [PATCH 01/69] feat: add hover display for trait assoc items --- crates/hir/src/display.rs | 24 ++++++++ crates/ide/src/hover/tests.rs | 113 +++++++++++++++++++++++++++++++--- 2 files changed, 127 insertions(+), 10 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 30f402a79f3db..d76eb873bf4ef 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -595,6 +595,30 @@ impl HirDisplay for Trait { let def_id = GenericDefId::TraitId(self.id); write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; + + let assoc_items = self.items(f.db); + if assoc_items.is_empty() { + f.write_str(" {}")?; + } else { + f.write_str(" {\n")?; + for item in assoc_items { + f.write_str(" ")?; + match item { + AssocItem::Function(func) => { + func.hir_fmt(f)?; + } + AssocItem::Const(cst) => { + cst.hir_fmt(f)?; + } + AssocItem::TypeAlias(type_alias) => { + type_alias.hir_fmt(f)?; + } + }; + f.write_str(",\n")?; + } + f.write_str("}")?; + } + Ok(()) } } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index ead4f91595f0e..73d9339a229e7 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -2685,7 +2685,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -2719,7 +2719,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -2886,7 +2886,7 @@ fn foo(ar$0g: &impl Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -2988,7 +2988,7 @@ pub mod future { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future", + description: "pub trait Future {}", }, }, HoverGotoTypeData { @@ -3033,7 +3033,7 @@ fn foo(ar$0g: &impl Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -3096,7 +3096,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -3127,7 +3127,7 @@ fn foo(ar$0g: &dyn Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -3159,7 +3159,7 @@ fn foo(ar$0g: &dyn Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -3288,7 +3288,7 @@ fn main() { let s$0t = test().get(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {\n type Item,\n fn get(self) -> Self::Item,\n}", }, }, ], @@ -3353,7 +3353,7 @@ fn foo(t: T$0){} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -6252,6 +6252,99 @@ impl T for () { ); } +#[test] +fn hover_trait_show_assoc_items() { + check( + r#" +trait T {} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T {} + ``` + "#]], + ); + + check( + r#" +trait T { + fn func() {} +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(), + } + ``` + "#]], + ); + + check( + r#" +trait T { + fn func() {} + const FLAG: i32 = 34; +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(), + const FLAG: i32, + } + ``` + "#]], + ); + + check( + r#" +trait T { + fn func() {} + const FLAG: i32 = 34; + type Bar; +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(), + const FLAG: i32, + type Bar, + } + ``` + "#]], + ); +} + #[test] fn hover_ranged_macro_call() { check_hover_range( From 00358b1fe078bc4d702375203f79b088d2b9a5f6 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sun, 18 Feb 2024 15:29:45 +0800 Subject: [PATCH 02/69] rebase on lastest master --- crates/hir/src/display.rs | 5 +---- crates/ide/src/hover/tests.rs | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index d76eb873bf4ef..010c3537574cc 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -17,10 +17,7 @@ use hir_ty::{ }; use crate::{ - Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, - Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam, - Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam, - TypeParam, Union, Variant, + Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant }; impl HirDisplay for Function { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 73d9339a229e7..e845ef668948f 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -411,7 +411,7 @@ fn main() { name: "FnOnce", kind: Trait, container_name: "function", - description: "pub trait FnOnce\nwhere\n Args: Tuple,", + description: "pub trait FnOnce\nwhere\n Args: Tuple, {\n pub type Output,\n pub extern \"rust-call\" fn call_once(self, args: Args) -> Self::Output,\n}", }, }, ], @@ -2766,7 +2766,7 @@ fn main() { let s$0t = foo(); } focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar", + description: "trait Bar {}", }, }, HoverGotoTypeData { @@ -2779,7 +2779,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -2816,7 +2816,7 @@ fn main() { let s$0t = foo(); } focus_range: 22..25, name: "Bar", kind: Trait, - description: "trait Bar", + description: "trait Bar {}", }, }, HoverGotoTypeData { @@ -2829,7 +2829,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -2920,7 +2920,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar", + description: "trait Bar {}", }, }, HoverGotoTypeData { @@ -2933,7 +2933,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -3220,7 +3220,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 28..36, name: "DynTrait", kind: Trait, - description: "trait DynTrait", + description: "trait DynTrait {}", }, }, HoverGotoTypeData { @@ -3233,7 +3233,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 6..15, name: "ImplTrait", kind: Trait, - description: "trait ImplTrait", + description: "trait ImplTrait {}", }, }, HoverGotoTypeData { @@ -7456,7 +7456,7 @@ impl Iterator for S { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future", + description: "pub trait Future {\n pub type Output,\n pub fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll,\n}", }, }, HoverGotoTypeData { @@ -7470,7 +7470,7 @@ impl Iterator for S { name: "Iterator", kind: Trait, container_name: "iterator", - description: "pub trait Iterator", + description: "pub trait Iterator {\n pub type Item,\n pub fn next(&mut self) -> Option,\n pub fn nth(&mut self, n: usize) -> Option,\n pub fn by_ref(&mut self) -> &mut Self\nwhere\n Self: Sized,,\n}", }, }, HoverGotoTypeData { @@ -7483,7 +7483,7 @@ impl Iterator for S { focus_range: 49..56, name: "Notable", kind: Trait, - description: "trait Notable", + description: "trait Notable {}", }, }, HoverGotoTypeData { From 35ec5955eb607c17d72621fab8cf59242d6bac84 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sun, 18 Feb 2024 17:43:22 +0800 Subject: [PATCH 03/69] add config item for hover display --- crates/hir-ty/src/display.rs | 2 +- crates/hir/src/display.rs | 9 ++++++++- crates/ide-db/src/defs.rs | 4 ++-- crates/ide/src/hover.rs | 1 + crates/ide/src/hover/render.rs | 2 +- crates/ide/src/hover/tests.rs | 1 + crates/ide/src/static_index.rs | 3 ++- crates/rust-analyzer/src/config.rs | 5 ++++- docs/user/generated_config.adoc | 5 +++++ editors/code/package.json | 9 +++++++++ 10 files changed, 34 insertions(+), 7 deletions(-) diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index fe51ec3f82108..f7e396de2d6b7 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -62,7 +62,7 @@ pub struct HirFormatter<'a> { fmt: &'a mut dyn HirWrite, buf: String, curr_size: usize, - pub(crate) max_size: Option, + pub max_size: Option, omit_verbose_types: bool, closure_style: ClosureStyle, display_target: DisplayTarget, diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 010c3537574cc..0e221a2149ae2 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -593,12 +593,14 @@ impl HirDisplay for Trait { write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; + let mut display_size = 0; + let max_display_size = f.max_size.unwrap_or(7); let assoc_items = self.items(f.db); if assoc_items.is_empty() { f.write_str(" {}")?; } else { f.write_str(" {\n")?; - for item in assoc_items { + for (index, item) in assoc_items.iter().enumerate() { f.write_str(" ")?; match item { AssocItem::Function(func) => { @@ -612,6 +614,11 @@ impl HirDisplay for Trait { } }; f.write_str(",\n")?; + display_size += 1; + if display_size == max_display_size && index != assoc_items.len() - 1{ + f.write_str(" ...\n")?; + break; + } } f.write_str("}")?; } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 1b6ff8bad53c5..8de885f49948b 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -213,7 +213,7 @@ impl Definition { }) } - pub fn label(&self, db: &RootDatabase) -> String { + pub fn label(&self, db: &RootDatabase, max_size: Option) -> String { match *self { Definition::Macro(it) => it.display(db).to_string(), Definition::Field(it) => it.display(db).to_string(), @@ -224,7 +224,7 @@ impl Definition { Definition::Variant(it) => it.display(db).to_string(), Definition::Const(it) => it.display(db).to_string(), Definition::Static(it) => it.display(db).to_string(), - Definition::Trait(it) => it.display(db).to_string(), + Definition::Trait(it) => it.display_truncated(db, max_size).to_string(), Definition::TraitAlias(it) => it.display(db).to_string(), Definition::TypeAlias(it) => it.display(db).to_string(), Definition::BuiltinType(it) => it.name().display(db).to_string(), diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 4a7350feb385e..4b3fdaff0b346 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -32,6 +32,7 @@ pub struct HoverConfig { pub documentation: bool, pub keywords: bool, pub format: HoverDocFormat, + pub trait_item_display_on_hover: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 563e78253a8ae..c955f46bc454a 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -406,7 +406,7 @@ pub(super) fn definition( config: &HoverConfig, ) -> Markup { let mod_path = definition_mod_path(db, &def); - let label = def.label(db); + let label = def.label(db, config.trait_item_display_on_hover); let docs = def.docs(db, famous_defs); let value = (|| match def { Definition::Variant(it) => { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index e845ef668948f..2df4ca5810b24 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -17,6 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { documentation: true, format: HoverDocFormat::Markdown, keywords: true, + trait_item_display_on_hover: Some(7), }; fn check_hover_no_result(ra_fixture: &str) { diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 2929a7522e591..8d5f5e1bf6777 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -166,6 +166,7 @@ impl StaticIndex<'_> { documentation: true, keywords: true, format: crate::HoverDocFormat::Markdown, + trait_item_display_on_hover: Some(7) }; let tokens = tokens.filter(|token| { matches!( @@ -196,7 +197,7 @@ impl StaticIndex<'_> { enclosing_moniker: current_crate .zip(def.enclosing_definition(self.db)) .and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)), - signature: Some(def.label(self.db)), + signature: Some(def.label(self.db, hover_config.trait_item_display_on_hover)), kind: def_to_kind(self.db, def), }); self.def_map.insert(def, it); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 16e1a2f544907..230a0385cdb3b 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -511,7 +511,6 @@ config_data! { /// Exclude tests from find-all-references. references_excludeTests: bool = "false", - /// Command to be executed instead of 'cargo' for runnables. runnables_command: Option = "null", /// Additional arguments to be passed to cargo for runnables such as @@ -591,6 +590,9 @@ config_data! { /// Show documentation. signatureInfo_documentation_enable: bool = "true", + /// How many trait item display on hover. + trait_item_display_on_hover: Option = "7", + /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list. typing_autoClosingAngleBrackets_enable: bool = "false", @@ -1683,6 +1685,7 @@ impl Config { } }, keywords: self.data.hover_documentation_keywords_enable, + trait_item_display_on_hover: self.data.trait_item_display_on_hover, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index da7654b0f6447..9f3ab4513294e 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -927,6 +927,11 @@ Show full signature of the callable. Only shows parameters if disabled. -- Show documentation. -- +[[rust-analyzer.trait.item.display.on.hover]]rust-analyzer.trait.item.display.on.hover (default: `7`):: ++ +-- +How many trait item display on hover. +-- [[rust-analyzer.typing.autoClosingAngleBrackets.enable]]rust-analyzer.typing.autoClosingAngleBrackets.enable (default: `false`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 3a1df5a2f901c..a4f54ae4f4587 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1648,6 +1648,15 @@ "default": true, "type": "boolean" }, + "rust-analyzer.trait.item.display.on.hover": { + "markdownDescription": "How many trait item display on hover.", + "default": 7, + "type": [ + "null", + "integer" + ], + "minimum": 0 + }, "rust-analyzer.typing.autoClosingAngleBrackets.enable": { "markdownDescription": "Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.", "default": false, From 2e87f31fe9f9a147d7a19202e5c4f918b8c975ac Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Thu, 22 Feb 2024 17:37:40 +0800 Subject: [PATCH 04/69] add HoverDisplayConfig --- crates/hir/src/display.rs | 12 +++++++----- crates/ide-db/src/defs.rs | 12 ++++++++++-- crates/ide/src/hover.rs | 2 +- crates/ide/src/hover/render.rs | 5 +++-- crates/ide/src/hover/tests.rs | 2 +- crates/ide/src/static_index.rs | 6 +++--- crates/rust-analyzer/src/config.rs | 4 ++-- docs/user/generated_config.adoc | 2 +- editors/code/package.json | 2 +- 9 files changed, 29 insertions(+), 18 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 0e221a2149ae2..08e0c6e752473 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -17,7 +17,10 @@ use hir_ty::{ }; use crate::{ - Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant + Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, + Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, + SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, + TypeOrConstParam, TypeParam, Union, Variant, }; impl HirDisplay for Function { @@ -593,9 +596,9 @@ impl HirDisplay for Trait { write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; - let mut display_size = 0; - let max_display_size = f.max_size.unwrap_or(7); let assoc_items = self.items(f.db); + let assoc_items_size = assoc_items.len(); + let max_display_size = f.max_size.unwrap_or(assoc_items_size); if assoc_items.is_empty() { f.write_str(" {}")?; } else { @@ -614,8 +617,7 @@ impl HirDisplay for Trait { } }; f.write_str(",\n")?; - display_size += 1; - if display_size == max_display_size && index != assoc_items.len() - 1{ + if index + 1 == max_display_size && index + 1 != assoc_items_size { f.write_str(" ...\n")?; break; } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 8de885f49948b..35aaf864696af 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -24,6 +24,12 @@ use crate::documentation::{Documentation, HasDocs}; use crate::famous_defs::FamousDefs; use crate::RootDatabase; +#[derive(Default)] +pub struct HoverDisplayConfig { + pub trait_item_display_num: Option, + // todo: add config for struct & enum +} + // FIXME: a more precise name would probably be `Symbol`? #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] pub enum Definition { @@ -213,7 +219,7 @@ impl Definition { }) } - pub fn label(&self, db: &RootDatabase, max_size: Option) -> String { + pub fn label(&self, db: &RootDatabase, hover_display_config: HoverDisplayConfig) -> String { match *self { Definition::Macro(it) => it.display(db).to_string(), Definition::Field(it) => it.display(db).to_string(), @@ -224,7 +230,9 @@ impl Definition { Definition::Variant(it) => it.display(db).to_string(), Definition::Const(it) => it.display(db).to_string(), Definition::Static(it) => it.display(db).to_string(), - Definition::Trait(it) => it.display_truncated(db, max_size).to_string(), + Definition::Trait(it) => { + it.display_truncated(db, hover_display_config.trait_item_display_num).to_string() + } Definition::TraitAlias(it) => it.display(db).to_string(), Definition::TypeAlias(it) => it.display(db).to_string(), Definition::BuiltinType(it) => it.name().display(db).to_string(), diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 4b3fdaff0b346..64346a59b77fb 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -32,7 +32,7 @@ pub struct HoverConfig { pub documentation: bool, pub keywords: bool, pub format: HoverDocFormat, - pub trait_item_display_on_hover: Option, + pub trait_item_display_num: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index c955f46bc454a..6d7886feec338 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -8,7 +8,7 @@ use hir::{ }; use ide_db::{ base_db::SourceDatabase, - defs::Definition, + defs::{Definition, HoverDisplayConfig}, documentation::HasDocs, famous_defs::FamousDefs, generated::lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, @@ -406,7 +406,8 @@ pub(super) fn definition( config: &HoverConfig, ) -> Markup { let mod_path = definition_mod_path(db, &def); - let label = def.label(db, config.trait_item_display_on_hover); + let hover_config = HoverDisplayConfig { trait_item_display_num: config.trait_item_display_num }; + let label = def.label(db, hover_config); let docs = def.docs(db, famous_defs); let value = (|| match def { Definition::Variant(it) => { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 2df4ca5810b24..e2278fe4b3abc 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -17,7 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { documentation: true, format: HoverDocFormat::Markdown, keywords: true, - trait_item_display_on_hover: Some(7), + trait_item_display_num: Some(7), }; fn check_hover_no_result(ra_fixture: &str) { diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 8d5f5e1bf6777..8d6e161c1b971 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -4,7 +4,7 @@ use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics}; use ide_db::{ base_db::{FileId, FileRange, SourceDatabaseExt}, - defs::Definition, + defs::{Definition, HoverDisplayConfig}, documentation::Documentation, famous_defs::FamousDefs, helpers::get_definition, @@ -166,7 +166,7 @@ impl StaticIndex<'_> { documentation: true, keywords: true, format: crate::HoverDocFormat::Markdown, - trait_item_display_on_hover: Some(7) + trait_item_display_num: None, }; let tokens = tokens.filter(|token| { matches!( @@ -197,7 +197,7 @@ impl StaticIndex<'_> { enclosing_moniker: current_crate .zip(def.enclosing_definition(self.db)) .and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)), - signature: Some(def.label(self.db, hover_config.trait_item_display_on_hover)), + signature: Some(def.label(self.db, HoverDisplayConfig::default())), kind: def_to_kind(self.db, def), }); self.def_map.insert(def, it); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 230a0385cdb3b..40a2077cb1855 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -591,7 +591,7 @@ config_data! { signatureInfo_documentation_enable: bool = "true", /// How many trait item display on hover. - trait_item_display_on_hover: Option = "7", + traitItemDisplayNum: Option = "7", /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list. typing_autoClosingAngleBrackets_enable: bool = "false", @@ -1685,7 +1685,7 @@ impl Config { } }, keywords: self.data.hover_documentation_keywords_enable, - trait_item_display_on_hover: self.data.trait_item_display_on_hover, + trait_item_display_num: self.data.traitItemDisplayNum, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 9f3ab4513294e..7d005828b8c60 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -927,7 +927,7 @@ Show full signature of the callable. Only shows parameters if disabled. -- Show documentation. -- -[[rust-analyzer.trait.item.display.on.hover]]rust-analyzer.trait.item.display.on.hover (default: `7`):: +[[rust-analyzer.traitItemDisplayNum]]rust-analyzer.traitItemDisplayNum (default: `7`):: + -- How many trait item display on hover. diff --git a/editors/code/package.json b/editors/code/package.json index a4f54ae4f4587..b68ab66cdab67 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1648,7 +1648,7 @@ "default": true, "type": "boolean" }, - "rust-analyzer.trait.item.display.on.hover": { + "rust-analyzer.traitItemDisplayNum": { "markdownDescription": "How many trait item display on hover.", "default": 7, "type": [ From ce4ae41605f8a049afee8b013121496aa9950e9f Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 12:21:05 +0800 Subject: [PATCH 05/69] internal: simplify the process of inserting spaces after mut --- .../ide-assists/src/handlers/inline_call.rs | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index 11b22b65205b8..7531dd5c035de 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -415,24 +415,16 @@ fn inline( let expr: &ast::Expr = expr; let mut insert_let_stmt = || { - let param_ty = match param_ty { - None => None, - Some(param_ty) => { - if sema.hir_file_for(param_ty.syntax()).is_macro() { - if let Some(param_ty) = - ast::Type::cast(insert_ws_into(param_ty.syntax().clone())) - { - Some(param_ty) - } else { - Some(param_ty.clone_for_update()) - } - } else { - Some(param_ty.clone_for_update()) - } + let param_ty = param_ty.clone().map(|param_ty| { + if sema.hir_file_for(param_ty.syntax()).is_macro() { + ast::Type::cast(insert_ws_into(param_ty.syntax().clone())) + .unwrap_or_else(|| param_ty) + } else { + param_ty } - }; - let ty: Option = - sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty); + }); + + let ty = sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty); let is_self = param .name(sema.db) From 48966268fcf560d8c132edea3b1028fa177d78b8 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 12:22:17 +0800 Subject: [PATCH 06/69] fix: use 4 spaces for indentation in macro expansion --- .../src/syntax_helpers/insert_whitespace_into_node.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs index 0b0fc6693526f..97b6d4a572a21 100644 --- a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs +++ b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs @@ -20,7 +20,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode { let after = Position::after; let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| { - (pos(token.clone()), make::tokens::whitespace(&" ".repeat(2 * indent))) + (pos(token.clone()), make::tokens::whitespace(&" ".repeat(4 * indent))) }; let do_ws = |pos: fn(_) -> Position, token: &SyntaxToken| { (pos(token.clone()), make::tokens::single_space()) @@ -41,7 +41,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode { if indent > 0 { mods.push(( Position::after(node.clone()), - make::tokens::whitespace(&" ".repeat(2 * indent)), + make::tokens::whitespace(&" ".repeat(4 * indent)), )); } if node.parent().is_some() { @@ -91,10 +91,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode { LIFETIME_IDENT if is_next(is_text, true) => { mods.push(do_ws(after, tok)); } - MUT_KW if is_next(|it| it == SELF_KW, false) => { - mods.push(do_ws(after, tok)); - } - AS_KW | DYN_KW | IMPL_KW | CONST_KW => { + AS_KW | DYN_KW | IMPL_KW | CONST_KW | MUT_KW => { mods.push(do_ws(after, tok)); } T![;] if is_next(|it| it != R_CURLY, true) => { From ec5236f3a8f9ea29abe36e173d9b087f5ede629c Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 12:23:15 +0800 Subject: [PATCH 07/69] test: use 4 spaces for indetation in macro expansion --- .../ide-assists/src/handlers/inline_call.rs | 8 +-- .../ide-assists/src/handlers/inline_macro.rs | 10 ++-- crates/ide/src/expand_macro.rs | 58 +++++++++---------- crates/ide/src/hover/tests.rs | 6 +- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index 7531dd5c035de..ab19779f4e843 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -1348,8 +1348,8 @@ macro_rules! define_foo { define_foo!(); fn bar() -> u32 { { - let x = 0; - x + let x = 0; + x } } "#, @@ -1662,7 +1662,7 @@ fn main() { let a: A = A{}; let b = { let a = a; - a as A + a as A }; } "#, @@ -1781,7 +1781,7 @@ fn _hash2(self_: &u64, state: &mut u64) { { let inner_self_: &u64 = &self_; let state: &mut u64 = state; - _write_u64(state, *inner_self_) + _write_u64(state, *inner_self_) }; } "#, diff --git a/crates/ide-assists/src/handlers/inline_macro.rs b/crates/ide-assists/src/handlers/inline_macro.rs index 0c9e971dd23ca..4708be616964f 100644 --- a/crates/ide-assists/src/handlers/inline_macro.rs +++ b/crates/ide-assists/src/handlers/inline_macro.rs @@ -288,11 +288,11 @@ macro_rules! foo { } fn main() { cfg_if!{ - if #[cfg(test)]{ - 1; - }else { - 1; - } + if #[cfg(test)]{ + 1; + }else { + 1; + } }; } "#, diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 17c701ad03591..9eb5a9db6250e 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -308,8 +308,8 @@ f$0oo!(); expect![[r#" foo! fn some_thing() -> u32 { - let a = 0; - a+10 + let a = 0; + a+10 }"#]], ); } @@ -342,13 +342,13 @@ fn main() { expect![[r#" match_ast! { - if let Some(it) = ast::TraitDef::cast(container.clone()){} - else if let Some(it) = ast::ImplDef::cast(container.clone()){} - else { - { - continue + if let Some(it) = ast::TraitDef::cast(container.clone()){} + else if let Some(it) = ast::ImplDef::cast(container.clone()){} + else { + { + continue + } } - } }"#]], ); } @@ -397,12 +397,12 @@ fn main() { expect![[r#" foo! { - macro_rules! bar { - () => { - 42 + macro_rules! bar { + () => { + 42 + } } - } - 42 + 42 }"#]], ); } @@ -482,16 +482,16 @@ struct Foo {} expect![[r#" Clone impl < >$crate::clone::Clone for Foo< >where { - fn clone(&self) -> Self { - match self { - Foo{} - => Foo{} - , + fn clone(&self) -> Self { + match self { + Foo{} + => Foo{} + , - } - } + } + } - }"#]], + }"#]], ); } @@ -534,16 +534,16 @@ struct Foo {} expect![[r#" Clone impl < >$crate::clone::Clone for Foo< >where { - fn clone(&self) -> Self { - match self { - Foo{} - => Foo{} - , + fn clone(&self) -> Self { + match self { + Foo{} + => Foo{} + , - } - } + } + } - }"#]], + }"#]], ); } } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index ead4f91595f0e..7ecfdfb1942f5 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -6341,8 +6341,8 @@ fn main() { $0V; } ```rust pub const V: i8 = { - let e = 123; - f(e) + let e = 123; + f(e) } ``` "#]], @@ -6368,7 +6368,7 @@ fn main() { $0V; } ```rust pub static V: i8 = { - let e = 123; + let e = 123; } ``` "#]], From 76b86b24bd38e53ee8a3555608339803ecb5cbb9 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 13:54:52 +0800 Subject: [PATCH 08/69] fix: clippy and format --- crates/ide-assists/src/handlers/inline_call.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index ab19779f4e843..9c4f3bb93708c 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -417,8 +417,7 @@ fn inline( let mut insert_let_stmt = || { let param_ty = param_ty.clone().map(|param_ty| { if sema.hir_file_for(param_ty.syntax()).is_macro() { - ast::Type::cast(insert_ws_into(param_ty.syntax().clone())) - .unwrap_or_else(|| param_ty) + ast::Type::cast(insert_ws_into(param_ty.syntax().clone())).unwrap_or(param_ty) } else { param_ty } From 6112ddfabbc27cfa3c6d68a93d37f161cf7b5caa Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Wed, 28 Feb 2024 10:13:31 +0100 Subject: [PATCH 09/69] Add prefix `file_` to `Semantics`'s `to_module_defs()`/`to_module_def()` methods --- crates/hir/src/semantics.rs | 10 +++++----- crates/hir/src/semantics/source_to_def.rs | 2 +- .../src/handlers/generate_delegate_trait.rs | 2 +- crates/ide-assists/src/handlers/move_from_mod_rs.rs | 2 +- crates/ide-assists/src/handlers/move_to_mod_rs.rs | 2 +- crates/ide-db/src/helpers.rs | 2 +- crates/ide-diagnostics/src/handlers/missing_fields.rs | 2 +- crates/ide-diagnostics/src/lib.rs | 2 +- crates/ide/src/parent_module.rs | 2 +- crates/ide/src/rename.rs | 2 +- crates/ide/src/runnables.rs | 2 +- crates/ide/src/syntax_highlighting.rs | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 1fb6570b6a407..6aa053b5ac6e7 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -223,12 +223,12 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.resolve_variant(record_lit).map(VariantDef::from) } - pub fn to_module_def(&self, file: FileId) -> Option { - self.imp.to_module_def(file).next() + pub fn file_to_module_def(&self, file: FileId) -> Option { + self.imp.file_to_module_defs(file).next() } - pub fn to_module_defs(&self, file: FileId) -> impl Iterator { - self.imp.to_module_def(file) + pub fn file_to_module_defs(&self, file: FileId) -> impl Iterator { + self.imp.file_to_module_defs(file) } pub fn to_struct_def(&self, s: &ast::Struct) -> Option { @@ -1237,7 +1237,7 @@ impl<'db> SemanticsImpl<'db> { T::to_def(self, src) } - fn to_module_def(&self, file: FileId) -> impl Iterator { + fn file_to_module_defs(&self, file: FileId) -> impl Iterator { self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from) } diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index ef4ed90ce35f5..4733ea5a35b92 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -118,7 +118,7 @@ pub(super) struct SourceToDefCtx<'a, 'b> { impl SourceToDefCtx<'_, '_> { pub(super) fn file_to_def(&self, file: FileId) -> SmallVec<[ModuleId; 1]> { - let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::to_module_def"); + let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::file_to_module_def"); let mut mods = SmallVec::new(); for &crate_id in self.db.relevant_crates(file).iter() { // FIXME: inner items diff --git a/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/crates/ide-assists/src/handlers/generate_delegate_trait.rs index 7a60287f923f0..e0bcd78c99ba4 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -116,7 +116,7 @@ impl Field { ) -> Option { let db = ctx.sema.db; - let module = ctx.sema.to_module_def(ctx.file_id())?; + let module = ctx.sema.file_to_module_def(ctx.file_id())?; let (name, range, ty) = match f { Either::Left(f) => { diff --git a/crates/ide-assists/src/handlers/move_from_mod_rs.rs b/crates/ide-assists/src/handlers/move_from_mod_rs.rs index 917d0b3671e8e..a256f60c421c3 100644 --- a/crates/ide-assists/src/handlers/move_from_mod_rs.rs +++ b/crates/ide-assists/src/handlers/move_from_mod_rs.rs @@ -25,7 +25,7 @@ use crate::{ // ``` pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let source_file = ctx.find_node_at_offset::()?; - let module = ctx.sema.to_module_def(ctx.file_id())?; + let module = ctx.sema.file_to_module_def(ctx.file_id())?; // Enable this assist if the user select all "meaningful" content in the source file let trimmed_selected_range = trimmed_text_range(&source_file, ctx.selection_trimmed()); let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range()); diff --git a/crates/ide-assists/src/handlers/move_to_mod_rs.rs b/crates/ide-assists/src/handlers/move_to_mod_rs.rs index b73270cd05fb5..a8a124eebb68d 100644 --- a/crates/ide-assists/src/handlers/move_to_mod_rs.rs +++ b/crates/ide-assists/src/handlers/move_to_mod_rs.rs @@ -25,7 +25,7 @@ use crate::{ // ``` pub(crate) fn move_to_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let source_file = ctx.find_node_at_offset::()?; - let module = ctx.sema.to_module_def(ctx.file_id())?; + let module = ctx.sema.file_to_module_def(ctx.file_id())?; // Enable this assist if the user select all "meaningful" content in the source file let trimmed_selected_range = trimmed_text_range(&source_file, ctx.selection_trimmed()); let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range()); diff --git a/crates/ide-db/src/helpers.rs b/crates/ide-db/src/helpers.rs index 0b5ad7060e043..4ac8a7c4c4aa3 100644 --- a/crates/ide-db/src/helpers.rs +++ b/crates/ide-db/src/helpers.rs @@ -64,7 +64,7 @@ pub fn visit_file_defs( cb: &mut dyn FnMut(Definition), ) { let db = sema.db; - let module = match sema.to_module_def(file_id) { + let module = match sema.file_to_module_def(file_id) { Some(it) => it, None => return, }; diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs index 09daefd084dc2..f92ba576d3ab5 100644 --- a/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -200,7 +200,7 @@ fn get_default_constructor( } } - let krate = ctx.sema.to_module_def(d.file.original_file(ctx.sema.db))?.krate(); + let krate = ctx.sema.file_to_module_def(d.file.original_file(ctx.sema.db))?.krate(); let module = krate.root_module(); // Look for a ::new() associated function diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 9f4368b04e79b..6c72dbb5edf96 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -315,7 +315,7 @@ pub fn diagnostics( handlers::json_is_not_rust::json_in_items(&sema, &mut res, file_id, &node, config); } - let module = sema.to_module_def(file_id); + let module = sema.file_to_module_def(file_id); let ctx = DiagnosticsContext { config, sema, resolve }; if module.is_none() { diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs index f67aea2d5b9c1..ce7a6779e27c2 100644 --- a/crates/ide/src/parent_module.rs +++ b/crates/ide/src/parent_module.rs @@ -48,7 +48,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec sema - .to_module_defs(position.file_id) + .file_to_module_defs(position.file_id) .flat_map(|module| NavigationTarget::from_module_to_decl(db, module)) .collect(), } diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs index f78153df38bd6..8c2ae327c7fc0 100644 --- a/crates/ide/src/rename.rs +++ b/crates/ide/src/rename.rs @@ -156,7 +156,7 @@ pub(crate) fn will_rename_file( new_name_stem: &str, ) -> Option { let sema = Semantics::new(db); - let module = sema.to_module_def(file_id)?; + let module = sema.file_to_module_def(file_id)?; let def = Definition::Module(module); let mut change = if is_raw_identifier(new_name_stem) { def.rename(&sema, &SmolStr::from_iter(["r#", new_name_stem])).ok()? diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index ae107a96040dc..5fe46444ff41c 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -178,7 +178,7 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec { } }); - sema.to_module_defs(file_id) + sema.file_to_module_defs(file_id) .map(|it| runnable_mod_outline_definition(&sema, it)) .for_each(|it| add_opt(it, None)); diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index dfcbaf54d4f92..d2bd3bab14e48 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -223,7 +223,7 @@ fn traverse( krate: hir::Crate, range_to_highlight: TextRange, ) { - let is_unlinked = sema.to_module_def(file_id).is_none(); + let is_unlinked = sema.file_to_module_def(file_id).is_none(); let mut bindings_shadow_count: FxHashMap = FxHashMap::default(); enum AttrOrDerive { From fac8a14de874d36aed74e3e29022342f77b0c01d Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Wed, 28 Feb 2024 10:25:01 +0100 Subject: [PATCH 10/69] Add a more methods for resolving definitions from AST to their corresponding HIR types --- crates/hir/src/semantics.rs | 61 +++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 6aa053b5ac6e7..ccbc0f8346848 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -38,10 +38,11 @@ use crate::{ db::HirDatabase, semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, source_analyzer::{resolve_hir_path, SourceAnalyzer}, - Access, Adjust, Adjustment, AutoBorrow, BindingMode, BuiltinAttr, Callable, ConstParam, Crate, - DeriveHelper, Field, Function, HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local, - Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, Struct, ToolModule, Trait, - TupleField, Type, TypeAlias, TypeParam, VariantDef, + Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, + ConstParam, Crate, DeriveHelper, Enum, Field, Function, HasSource, HirFileId, Impl, InFile, + Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, + Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union, + Variant, VariantDef, }; pub enum DescendPreference { @@ -231,13 +232,61 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.file_to_module_defs(file) } - pub fn to_struct_def(&self, s: &ast::Struct) -> Option { - self.imp.to_def(s).map(Struct::from) + pub fn to_adt_def(&self, a: &ast::Adt) -> Option { + self.imp.to_def(a).map(Adt::from) + } + + pub fn to_const_def(&self, c: &ast::Const) -> Option { + self.imp.to_def(c).map(Const::from) + } + + pub fn to_enum_def(&self, e: &ast::Enum) -> Option { + self.imp.to_def(e).map(Enum::from) + } + + pub fn to_enum_variant_def(&self, v: &ast::Variant) -> Option { + self.imp.to_def(v).map(Variant::from) + } + + pub fn to_fn_def(&self, f: &ast::Fn) -> Option { + self.imp.to_def(f).map(Function::from) } pub fn to_impl_def(&self, i: &ast::Impl) -> Option { self.imp.to_def(i).map(Impl::from) } + + pub fn to_macro_def(&self, m: &ast::Macro) -> Option { + self.imp.to_def(m).map(Macro::from) + } + + pub fn to_module_def(&self, m: &ast::Module) -> Option { + self.imp.to_def(m).map(Module::from) + } + + pub fn to_static_def(&self, s: &ast::Static) -> Option { + self.imp.to_def(s).map(Static::from) + } + + pub fn to_struct_def(&self, s: &ast::Struct) -> Option { + self.imp.to_def(s).map(Struct::from) + } + + pub fn to_trait_alias_def(&self, t: &ast::TraitAlias) -> Option { + self.imp.to_def(t).map(TraitAlias::from) + } + + pub fn to_trait_def(&self, t: &ast::Trait) -> Option { + self.imp.to_def(t).map(Trait::from) + } + + pub fn to_type_alias_def(&self, t: &ast::TypeAlias) -> Option { + self.imp.to_def(t).map(TypeAlias::from) + } + + pub fn to_union_def(&self, u: &ast::Union) -> Option { + self.imp.to_def(u).map(Union::from) + } } impl<'db> SemanticsImpl<'db> { From 03b02e6bd0c61fc800c0694e1156690e9e2a142c Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 28 Feb 2024 16:17:44 +0100 Subject: [PATCH 11/69] internal: Move ide-assists codegen tests into an xtask codegen command --- .cargo/config.toml | 1 + .github/workflows/ci.yaml | 3 + Cargo.lock | 2 +- crates/ide-assists/Cargo.toml | 1 - crates/ide-assists/src/tests.rs | 2 - xtask/Cargo.toml | 3 +- xtask/src/codegen.rs | 211 ++++++++++++++++++ .../src/codegen/assists_doc_tests.rs | 26 ++- xtask/src/flags.rs | 29 +++ xtask/src/main.rs | 18 +- xtask/src/release.rs | 6 +- 11 files changed, 273 insertions(+), 29 deletions(-) create mode 100644 xtask/src/codegen.rs rename crates/ide-assists/src/tests/sourcegen.rs => xtask/src/codegen/assists_doc_tests.rs (89%) diff --git a/.cargo/config.toml b/.cargo/config.toml index c3cfda85517e4..070560dfbc316 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,6 +3,7 @@ xtask = "run --package xtask --bin xtask --" tq = "test -- -q" qt = "tq" lint = "clippy --all-targets -- --cap-lints warn" +codegen = "run --package xtask --bin xtask -- codegen" [target.x86_64-pc-windows-msvc] linker = "rust-lld" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5a8b18e3fe1b3..2d8946520d5e7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -79,6 +79,9 @@ jobs: if: matrix.os == 'ubuntu-latest' run: sed -i '/\[profile.dev]/a opt-level=1' Cargo.toml + - name: Codegen checks (rust-analyzer) + run: cargo codegen --check + - name: Compile (tests) run: cargo test --no-run --locked ${{ env.USE_SYSROOT_ABI }} diff --git a/Cargo.lock b/Cargo.lock index 3c87291dbadb4..0bdd4821139cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -676,7 +676,6 @@ dependencies = [ "itertools", "profile", "smallvec", - "sourcegen", "stdx", "syntax", "test-fixture", @@ -2502,6 +2501,7 @@ version = "0.1.0" dependencies = [ "anyhow", "flate2", + "stdx", "time", "write-json", "xflags", diff --git a/crates/ide-assists/Cargo.toml b/crates/ide-assists/Cargo.toml index 98961a18de257..d84fa7dffc545 100644 --- a/crates/ide-assists/Cargo.toml +++ b/crates/ide-assists/Cargo.toml @@ -33,7 +33,6 @@ expect-test = "1.4.0" # local deps test-utils.workspace = true test-fixture.workspace = true -sourcegen.workspace = true [features] in-rust-tree = [] diff --git a/crates/ide-assists/src/tests.rs b/crates/ide-assists/src/tests.rs index 9b6f7d018ee37..32d6984102081 100644 --- a/crates/ide-assists/src/tests.rs +++ b/crates/ide-assists/src/tests.rs @@ -1,6 +1,4 @@ mod generated; -#[cfg(not(feature = "in-rust-tree"))] -mod sourcegen; use expect_test::expect; use hir::Semantics; diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 863a63ac82e72..5e758e0190ce2 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -14,7 +14,8 @@ xshell.workspace = true xflags = "0.3.0" time = { version = "0.3", default-features = false } zip = { version = "0.6", default-features = false, features = ["deflate", "time"] } +stdx.workspace = true # Avoid adding more dependencies to this crate [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs new file mode 100644 index 0000000000000..e579660ac9b13 --- /dev/null +++ b/xtask/src/codegen.rs @@ -0,0 +1,211 @@ +use std::{ + fmt, fs, mem, + path::{Path, PathBuf}, +}; + +use xshell::{cmd, Shell}; + +use crate::{flags, project_root}; + +pub(crate) mod assists_doc_tests; + +impl flags::Codegen { + pub(crate) fn run(self, _sh: &Shell) -> anyhow::Result<()> { + match self.codegen_type.unwrap_or_default() { + flags::CodegenType::All => { + assists_doc_tests::generate(self.check); + } + flags::CodegenType::AssistsDocTests => assists_doc_tests::generate(self.check), + } + Ok(()) + } +} + +fn list_rust_files(dir: &Path) -> Vec { + let mut res = list_files(dir); + res.retain(|it| { + it.file_name().unwrap_or_default().to_str().unwrap_or_default().ends_with(".rs") + }); + res +} + +fn list_files(dir: &Path) -> Vec { + let mut res = Vec::new(); + let mut work = vec![dir.to_path_buf()]; + while let Some(dir) = work.pop() { + for entry in dir.read_dir().unwrap() { + let entry = entry.unwrap(); + let file_type = entry.file_type().unwrap(); + let path = entry.path(); + let is_hidden = + path.file_name().unwrap_or_default().to_str().unwrap_or_default().starts_with('.'); + if !is_hidden { + if file_type.is_dir() { + work.push(path); + } else if file_type.is_file() { + res.push(path); + } + } + } + } + res +} + +#[derive(Clone)] +pub(crate) struct CommentBlock { + pub(crate) id: String, + pub(crate) line: usize, + pub(crate) contents: Vec, + is_doc: bool, +} + +impl CommentBlock { + fn extract(tag: &str, text: &str) -> Vec { + assert!(tag.starts_with(char::is_uppercase)); + + let tag = format!("{tag}:"); + let mut blocks = CommentBlock::extract_untagged(text); + blocks.retain_mut(|block| { + let first = block.contents.remove(0); + let Some(id) = first.strip_prefix(&tag) else { + return false; + }; + + if block.is_doc { + panic!("Use plain (non-doc) comments with tags like {tag}:\n {first}"); + } + + block.id = id.trim().to_owned(); + true + }); + blocks + } + + fn extract_untagged(text: &str) -> Vec { + let mut res = Vec::new(); + + let lines = text.lines().map(str::trim_start); + + let dummy_block = + CommentBlock { id: String::new(), line: 0, contents: Vec::new(), is_doc: false }; + let mut block = dummy_block.clone(); + for (line_num, line) in lines.enumerate() { + match line.strip_prefix("//") { + Some(mut contents) => { + if let Some('/' | '!') = contents.chars().next() { + contents = &contents[1..]; + block.is_doc = true; + } + if let Some(' ') = contents.chars().next() { + contents = &contents[1..]; + } + block.contents.push(contents.to_owned()); + } + None => { + if !block.contents.is_empty() { + let block = mem::replace(&mut block, dummy_block.clone()); + res.push(block); + } + block.line = line_num + 2; + } + } + } + if !block.contents.is_empty() { + res.push(block); + } + res + } +} + +#[derive(Debug)] +pub(crate) struct Location { + pub(crate) file: PathBuf, + pub(crate) line: usize, +} + +impl fmt::Display for Location { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let path = self.file.strip_prefix(project_root()).unwrap().display().to_string(); + let path = path.replace('\\', "/"); + let name = self.file.file_name().unwrap(); + write!( + f, + "https://github.com/rust-lang/rust-analyzer/blob/master/{}#L{}[{}]", + path, + self.line, + name.to_str().unwrap() + ) + } +} + +fn ensure_rustfmt(sh: &Shell) { + let version = cmd!(sh, "rustup run stable rustfmt --version").read().unwrap_or_default(); + if !version.contains("stable") { + panic!( + "Failed to run rustfmt from toolchain 'stable'. \ + Please run `rustup component add rustfmt --toolchain stable` to install it.", + ); + } +} + +fn reformat(text: String) -> String { + let sh = Shell::new().unwrap(); + ensure_rustfmt(&sh); + let rustfmt_toml = project_root().join("rustfmt.toml"); + let mut stdout = cmd!( + sh, + "rustup run stable rustfmt --config-path {rustfmt_toml} --config fn_single_line=true" + ) + .stdin(text) + .read() + .unwrap(); + if !stdout.ends_with('\n') { + stdout.push('\n'); + } + stdout +} + +fn add_preamble(generator: &'static str, mut text: String) -> String { + let preamble = format!("//! Generated by `{generator}`, do not edit by hand.\n\n"); + text.insert_str(0, &preamble); + text +} + +/// Checks that the `file` has the specified `contents`. If that is not the +/// case, updates the file and then fails the test. +#[allow(clippy::print_stderr)] +fn ensure_file_contents(file: &Path, contents: &str, check: bool) { + if let Ok(old_contents) = fs::read_to_string(file) { + if normalize_newlines(&old_contents) == normalize_newlines(contents) { + // File is already up to date. + return; + } + } + + let display_path = file.strip_prefix(project_root()).unwrap_or(file); + if check { + panic!( + "{} was not up-to-date{}", + file.display(), + if std::env::var("CI").is_ok() { + "\n NOTE: run `cargo codegen` locally and commit the updated files\n" + } else { + "" + } + ); + } else { + eprintln!( + "\n\x1b[31;1merror\x1b[0m: {} was not up-to-date, updating\n", + display_path.display() + ); + + if let Some(parent) = file.parent() { + let _ = fs::create_dir_all(parent); + } + fs::write(file, contents).unwrap(); + } +} + +fn normalize_newlines(s: &str) -> String { + s.replace("\r\n", "\n") +} diff --git a/crates/ide-assists/src/tests/sourcegen.rs b/xtask/src/codegen/assists_doc_tests.rs similarity index 89% rename from crates/ide-assists/src/tests/sourcegen.rs rename to xtask/src/codegen/assists_doc_tests.rs index 847cb1af51e06..b2d89dde76592 100644 --- a/crates/ide-assists/src/tests/sourcegen.rs +++ b/xtask/src/codegen/assists_doc_tests.rs @@ -3,10 +3,15 @@ use std::{fmt, fs, path::Path}; use stdx::format_to_acc; -use test_utils::project_root; -#[test] -fn sourcegen_assists_docs() { +use crate::{ + codegen::{ + add_preamble, ensure_file_contents, list_rust_files, reformat, CommentBlock, Location, + }, + project_root, +}; + +pub(crate) fn generate(check: bool) { let assists = Assist::collect(); { @@ -40,10 +45,11 @@ r#####" buf.push_str(&test) } } - let buf = sourcegen::add_preamble("sourcegen_assists_docs", sourcegen::reformat(buf)); - sourcegen::ensure_file_contents( + let buf = add_preamble("sourcegen_assists_docs", reformat(buf)); + ensure_file_contents( &project_root().join("crates/ide-assists/src/tests/generated.rs"), &buf, + check, ); } @@ -52,7 +58,7 @@ r#####" // git repo. Instead, `cargo xtask release` runs this test before making // a release. - let contents = sourcegen::add_preamble( + let contents = add_preamble( "sourcegen_assists_docs", assists.into_iter().map(|it| it.to_string()).collect::>().join("\n\n"), ); @@ -71,7 +77,7 @@ struct Section { #[derive(Debug)] struct Assist { id: String, - location: sourcegen::Location, + location: Location, sections: Vec
, } @@ -80,7 +86,7 @@ impl Assist { let handlers_dir = project_root().join("crates/ide-assists/src/handlers"); let mut res = Vec::new(); - for path in sourcegen::list_rust_files(&handlers_dir) { + for path in list_rust_files(&handlers_dir) { collect_file(&mut res, path.as_path()); } res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id)); @@ -88,7 +94,7 @@ impl Assist { fn collect_file(acc: &mut Vec, path: &Path) { let text = fs::read_to_string(path).unwrap(); - let comment_blocks = sourcegen::CommentBlock::extract("Assist", &text); + let comment_blocks = CommentBlock::extract("Assist", &text); for block in comment_blocks { let id = block.id; @@ -97,7 +103,7 @@ impl Assist { "invalid assist id: {id:?}" ); let mut lines = block.contents.iter().peekable(); - let location = sourcegen::Location { file: path.to_path_buf(), line: block.line }; + let location = Location { file: path.to_path_buf(), line: block.line }; let mut assist = Assist { id, location, sections: Vec::new() }; while lines.peek().is_some() { diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs index e234090a07cea..f5827170b6519 100644 --- a/xtask/src/flags.rs +++ b/xtask/src/flags.rs @@ -52,6 +52,11 @@ xflags::xflags! { cmd bb { required suffix: String } + + cmd codegen { + optional codegen_type: CodegenType + optional --check + } } } @@ -73,8 +78,32 @@ pub enum XtaskCmd { PublishReleaseNotes(PublishReleaseNotes), Metrics(Metrics), Bb(Bb), + Codegen(Codegen), +} + +#[derive(Debug)] +pub struct Codegen { + pub check: bool, + pub codegen_type: Option, +} + +#[derive(Debug, Default)] +pub enum CodegenType { + #[default] + All, + AssistsDocTests, } +impl FromStr for CodegenType { + type Err = String; + fn from_str(s: &str) -> Result { + match s { + "all" => Ok(Self::All), + "assists-doc-tests" => Ok(Self::AssistsDocTests), + _ => Err("Invalid option".to_owned()), + } + } +} #[derive(Debug)] pub struct Install { pub client: bool, diff --git a/xtask/src/main.rs b/xtask/src/main.rs index df4d9810e6f16..9418675a348cc 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -13,6 +13,7 @@ mod flags; +mod codegen; mod dist; mod install; mod metrics; @@ -20,10 +21,7 @@ mod publish; mod release; use anyhow::bail; -use std::{ - env, - path::{Path, PathBuf}, -}; +use std::{env, path::PathBuf}; use xshell::{cmd, Shell}; fn main() -> anyhow::Result<()> { @@ -40,6 +38,7 @@ fn main() -> anyhow::Result<()> { flags::XtaskCmd::Dist(cmd) => cmd.run(sh), flags::XtaskCmd::PublishReleaseNotes(cmd) => cmd.run(sh), flags::XtaskCmd::Metrics(cmd) => cmd.run(sh), + flags::XtaskCmd::Codegen(cmd) => cmd.run(sh), flags::XtaskCmd::Bb(cmd) => { { let _d = sh.push_dir("./crates/rust-analyzer"); @@ -54,14 +53,11 @@ fn main() -> anyhow::Result<()> { } } +/// Returns the path to the root directory of `rust-analyzer` project. fn project_root() -> PathBuf { - Path::new( - &env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()), - ) - .ancestors() - .nth(1) - .unwrap() - .to_path_buf() + let dir = + env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()); + PathBuf::from(dir).parent().unwrap().to_owned() } fn run_fuzzer(sh: &Shell) -> anyhow::Result<()> { diff --git a/xtask/src/release.rs b/xtask/src/release.rs index 4a30691477857..f99f9ecbc39d9 100644 --- a/xtask/src/release.rs +++ b/xtask/src/release.rs @@ -2,7 +2,7 @@ mod changelog; use xshell::{cmd, Shell}; -use crate::{date_iso, flags, is_release_tag, project_root}; +use crate::{codegen, date_iso, flags, is_release_tag, project_root}; impl flags::Release { pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> { @@ -23,8 +23,8 @@ impl flags::Release { } // Generates bits of manual.adoc. - cmd!(sh, "cargo test -p ide-assists -p ide-diagnostics -p rust-analyzer -- sourcegen_") - .run()?; + cmd!(sh, "cargo test -p ide-diagnostics -p rust-analyzer -- sourcegen_").run()?; + codegen::assists_doc_tests::generate(false); let website_root = project_root().join("../rust-analyzer.github.io"); { From a01e4f8b72ccea318e5fb98c8f0cc2cab2c212b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 29 Feb 2024 16:00:29 +0200 Subject: [PATCH 12/69] Add basic support for Native Debug --- editors/code/src/debug.ts | 60 ++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts index d9c6b6ac45664..3fc63fc7d81a8 100644 --- a/editors/code/src/debug.ts +++ b/editors/code/src/debug.ts @@ -81,8 +81,9 @@ async function getDebugConfiguration( if (!editor) return; const knownEngines: Record = { - "vadimcn.vscode-lldb": getLldbDebugConfig, - "ms-vscode.cpptools": getCppvsDebugConfig, + "ms-vscode.cpptools": getCCppDebugConfig, + "vadimcn.vscode-lldb": getCodeLldbDebugConfig, + "webfreak.debug": getNativeDebugConfig, }; const debugOptions = ctx.config.debug; @@ -97,12 +98,14 @@ async function getDebugConfiguration( } if (!debugEngine) { + const commandCCpp: string = createCommandLink("ms-vscode.cpptools"); const commandCodeLLDB: string = createCommandLink("vadimcn.vscode-lldb"); - const commandCpp: string = createCommandLink("ms-vscode.cpptools"); + const commandNativeDebug: string = createCommandLink("webfreak.debug"); await vscode.window.showErrorMessage( `Install [CodeLLDB](command:${commandCodeLLDB} "Open CodeLLDB")` + - ` or [C/C++](command:${commandCpp} "Open C/C++") extension for debugging.`, + `, [C/C++](command:${commandCCpp} "Open C/C++") ` + + `or [Native Debug](command:${commandNativeDebug} "Open Native Debug") for debugging.`, ); return; } @@ -184,7 +187,7 @@ async function getDebugExecutableInfo( return executableInfo; } -function getLldbDebugConfig( +function getCCppDebugConfig( runnable: ra.Runnable, executable: string, cargoWorkspace: string, @@ -192,19 +195,18 @@ function getLldbDebugConfig( sourceFileMap?: Record, ): vscode.DebugConfiguration { return { - type: "lldb", + type: os.platform() === "win32" ? "cppvsdbg" : "cppdbg", request: "launch", name: runnable.label, program: executable, args: runnable.args.executableArgs, cwd: cargoWorkspace || runnable.args.workspaceRoot, - sourceMap: sourceFileMap, - sourceLanguages: ["rust"], + sourceFileMap, env, }; } -function getCppvsDebugConfig( +function getCodeLldbDebugConfig( runnable: ra.Runnable, executable: string, cargoWorkspace: string, @@ -212,13 +214,49 @@ function getCppvsDebugConfig( sourceFileMap?: Record, ): vscode.DebugConfiguration { return { - type: os.platform() === "win32" ? "cppvsdbg" : "cppdbg", + type: "lldb", request: "launch", name: runnable.label, program: executable, args: runnable.args.executableArgs, cwd: cargoWorkspace || runnable.args.workspaceRoot, - sourceFileMap, + sourceMap: sourceFileMap, + sourceLanguages: ["rust"], env, }; } + +function getNativeDebugConfig( + runnable: ra.Runnable, + executable: string, + cargoWorkspace: string, + env: Record, + _sourceFileMap?: Record, +): vscode.DebugConfiguration { + return { + type: "gdb", + request: "launch", + name: runnable.label, + target: executable, + // See https://github.com/WebFreak001/code-debug/issues/359 + arguments: quote(runnable.args.executableArgs), + cwd: cargoWorkspace || runnable.args.workspaceRoot, + env, + valuesFormatting: "prettyPrinters", + }; +} + +// Based on https://github.com/ljharb/shell-quote/blob/main/quote.js +function quote(xs: string[]) { + return xs + .map(function (s) { + if (/["\s]/.test(s) && !/'/.test(s)) { + return "'" + s.replace(/(['\\])/g, "\\$1") + "'"; + } + if (/["'\s]/.test(s)) { + return '"' + s.replace(/(["\\$`!])/g, "\\$1") + '"'; + } + return s.replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2"); + }) + .join(" "); +} From 06a883e32f097398ec3348524555c0fde45fe24a Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 29 Feb 2024 16:05:26 +0100 Subject: [PATCH 13/69] Take a reference instead of cloning --- lib/lsp-server/src/req_queue.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/lsp-server/src/req_queue.rs b/lib/lsp-server/src/req_queue.rs index 7b47f5388b5ea..347a9fb6fb98a 100644 --- a/lib/lsp-server/src/req_queue.rs +++ b/lib/lsp-server/src/req_queue.rs @@ -37,7 +37,7 @@ impl Incoming { } pub fn cancel(&mut self, id: RequestId) -> Option { - let _data = self.complete(id.clone())?; + let _data = self.complete(&id)?; let error = ResponseError { code: ErrorCode::RequestCanceled as i32, message: "canceled by client".to_owned(), @@ -46,8 +46,8 @@ impl Incoming { Some(Response { id, result: None, error: Some(error) }) } - pub fn complete(&mut self, id: RequestId) -> Option { - self.pending.remove(&id) + pub fn complete(&mut self, id: &RequestId) -> Option { + self.pending.remove(id) } pub fn is_completed(&self, id: &RequestId) -> bool { From 748f57c16da357eb1df6e129170354a7d3851130 Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 29 Feb 2024 16:28:59 +0100 Subject: [PATCH 14/69] Only clone when required --- crates/rust-analyzer/src/cli/analysis_stats.rs | 12 ++++++------ crates/rust-analyzer/src/global_state.rs | 8 ++++---- crates/rust-analyzer/src/handlers/request.rs | 4 ++-- crates/vfs/src/lib.rs | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 186b65692ecb8..b500db77d950e 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -1075,12 +1075,12 @@ fn location_csv_pat(db: &RootDatabase, vfs: &Vfs, sm: &BodySourceMap, pat_id: Pa format!("{path},{}:{},{}:{}", start.line + 1, start.col, end.line + 1, end.col) } -fn expr_syntax_range( +fn expr_syntax_range<'a>( db: &RootDatabase, - vfs: &Vfs, + vfs: &'a Vfs, sm: &BodySourceMap, expr_id: ExprId, -) -> Option<(VfsPath, LineCol, LineCol)> { +) -> Option<(&'a VfsPath, LineCol, LineCol)> { let src = sm.expr_syntax(expr_id); if let Ok(src) = src { let root = db.parse_or_expand(src.file_id); @@ -1096,12 +1096,12 @@ fn expr_syntax_range( None } } -fn pat_syntax_range( +fn pat_syntax_range<'a>( db: &RootDatabase, - vfs: &Vfs, + vfs: &'a Vfs, sm: &BodySourceMap, pat_id: PatId, -) -> Option<(VfsPath, LineCol, LineCol)> { +) -> Option<(&'a VfsPath, LineCol, LineCol)> { let src = sm.pat_syntax(pat_id); if let Ok(src) = src { let root = db.parse_or_expand(src.file_id); diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index b2d507491b177..9bcee6465ab7f 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -297,7 +297,7 @@ impl GlobalState { let mut bytes = vec![]; let mut modified_rust_files = vec![]; for file in changed_files { - let vfs_path = &vfs.file_path(file.file_id); + let vfs_path = vfs.file_path(file.file_id); if let Some(path) = vfs_path.as_path() { let path = path.to_path_buf(); if reload::should_refresh_for_change(&path, file.kind()) { @@ -481,7 +481,7 @@ impl GlobalStateSnapshot { } pub(crate) fn anchored_path(&self, path: &AnchoredPathBuf) -> Url { - let mut base = self.vfs_read().file_path(path.anchor); + let mut base = self.vfs_read().file_path(path.anchor).clone(); base.pop(); let path = base.join(&path.path).unwrap(); let path = path.as_path().unwrap(); @@ -489,7 +489,7 @@ impl GlobalStateSnapshot { } pub(crate) fn file_id_to_file_path(&self, file_id: FileId) -> vfs::VfsPath { - self.vfs_read().file_path(file_id) + self.vfs_read().file_path(file_id).clone() } pub(crate) fn cargo_target_for_crate_root( @@ -497,7 +497,7 @@ impl GlobalStateSnapshot { crate_id: CrateId, ) -> Option<(&CargoWorkspace, Target)> { let file_id = self.analysis.crate_root(crate_id).ok()?; - let path = self.vfs_read().file_path(file_id); + let path = self.vfs_read().file_path(file_id).clone(); let path = path.as_path()?; self.workspaces.iter().find_map(|ws| match ws { ProjectWorkspace::Cargo { cargo, .. } => { diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 04a043954299a..0e005975fbae5 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -2097,7 +2097,7 @@ pub(crate) fn fetch_dependency_list( .into_iter() .filter_map(|it| { let root_file_path = state.file_id_to_file_path(it.root_file_id); - crate_path(root_file_path).and_then(to_url).map(|path| CrateInfoResult { + crate_path(&root_file_path).and_then(to_url).map(|path| CrateInfoResult { name: it.name, version: it.version, path, @@ -2118,7 +2118,7 @@ pub(crate) fn fetch_dependency_list( /// An `Option` value representing the path to the directory of the crate with the given /// name, if such a crate is found. If no crate with the given name is found, this function /// returns `None`. -fn crate_path(root_file_path: VfsPath) -> Option { +fn crate_path(root_file_path: &VfsPath) -> Option { let mut current_dir = root_file_path.parent(); while let Some(path) = current_dir { let cargo_toml_path = path.join("../Cargo.toml")?; diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs index 34a85818eb84b..824ce39870330 100644 --- a/crates/vfs/src/lib.rs +++ b/crates/vfs/src/lib.rs @@ -163,8 +163,8 @@ impl Vfs { /// # Panics /// /// Panics if the id is not present in the `Vfs`. - pub fn file_path(&self, file_id: FileId) -> VfsPath { - self.interner.lookup(file_id).clone() + pub fn file_path(&self, file_id: FileId) -> &VfsPath { + self.interner.lookup(file_id) } /// Returns an iterator over the stored ids and their corresponding paths. From 4aab2d5cb4c3380665d27c80d2789ed0ac4e5bf6 Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 29 Feb 2024 16:29:15 +0100 Subject: [PATCH 15/69] Remove unneeded to_owned --- crates/rust-analyzer/src/cli/analysis_stats.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index b500db77d950e..f17a7eee43a9f 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -369,7 +369,7 @@ impl flags::AnalysisStats { let parse = sema.parse(file_id); let file_txt = db.file_text(file_id); - let path = vfs.file_path(file_id).as_path().unwrap().to_owned(); + let path = vfs.file_path(file_id).as_path().unwrap(); for node in parse.syntax().descendants() { let expr = match syntax::ast::Expr::cast(node.clone()) { @@ -444,7 +444,7 @@ impl flags::AnalysisStats { edit.apply(&mut txt); if self.validate_term_search { - std::fs::write(&path, txt).unwrap(); + std::fs::write(path, txt).unwrap(); let res = ws.run_build_scripts(&cargo_config, &|_| ()).unwrap(); if let Some(err) = res.error() { @@ -493,7 +493,7 @@ impl flags::AnalysisStats { } // Revert file back to original state if self.validate_term_search { - std::fs::write(&path, file_txt.to_string()).unwrap(); + std::fs::write(path, file_txt.to_string()).unwrap(); } bar.inc(1); From 9df73c6cb048fc28598ad0cbfb228444a4e9a553 Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 29 Feb 2024 16:53:48 +0100 Subject: [PATCH 16/69] Convert directly into an Arc --- crates/test-fixture/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index e118262b4edd9..68324cfeab8bf 100644 --- a/crates/test-fixture/src/lib.rs +++ b/crates/test-fixture/src/lib.rs @@ -149,15 +149,15 @@ impl ChangeFixture { for entry in fixture { let text = if entry.text.contains(CURSOR_MARKER) { if entry.text.contains(ESCAPED_CURSOR_MARKER) { - entry.text.replace(ESCAPED_CURSOR_MARKER, CURSOR_MARKER) + entry.text.replace(ESCAPED_CURSOR_MARKER, CURSOR_MARKER).into() } else { let (range_or_offset, text) = extract_range_or_offset(&entry.text); assert!(file_position.is_none()); file_position = Some((file_id, range_or_offset)); - text + text.into() } } else { - entry.text.clone() + entry.text.as_str().into() }; let meta = FileMeta::from_fixture(entry, current_source_root_kind); @@ -206,7 +206,7 @@ impl ChangeFixture { default_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned()))); } - source_change.change_file(file_id, Some(text.into())); + source_change.change_file(file_id, Some(text)); let path = VfsPath::new_virtual_path(meta.path); file_set.insert(file_id, path); files.push(file_id); From 00a049b585554320d49e20d549530cf87df2fe02 Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 29 Feb 2024 17:01:32 +0100 Subject: [PATCH 17/69] Avoid cloning deps --- crates/test-fixture/src/lib.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index 68324cfeab8bf..58a0e48bc49e6 100644 --- a/crates/test-fixture/src/lib.rs +++ b/crates/test-fixture/src/lib.rs @@ -195,7 +195,10 @@ impl ChangeFixture { let prev = crates.insert(crate_name.clone(), crate_id); assert!(prev.is_none(), "multiple crates with same name: {}", crate_name); for dep in meta.deps { - let prelude = meta.extern_prelude.contains(&dep); + let prelude = match &meta.extern_prelude { + Some(v) => v.contains(&dep), + None => true, + }; let dep = CrateName::normalize_dashes(&dep); crate_deps.push((crate_name.clone(), dep, prelude)) } @@ -443,7 +446,7 @@ struct FileMeta { path: String, krate: Option<(String, CrateOrigin, Option)>, deps: Vec, - extern_prelude: Vec, + extern_prelude: Option>, cfg: CfgOptions, edition: Edition, env: Env, @@ -473,7 +476,7 @@ impl FileMeta { Self { path: f.path, krate: f.krate.map(|it| parse_crate(it, current_source_root_kind, f.library)), - extern_prelude: f.extern_prelude.unwrap_or_else(|| deps.clone()), + extern_prelude: f.extern_prelude, deps, cfg, edition: f.edition.map_or(Edition::CURRENT, |v| Edition::from_str(&v).unwrap()), From 1d28aecd13a3a19c3a9fdce81e0c50f0b74caf6b Mon Sep 17 00:00:00 2001 From: Vladislav Mamon Date: Thu, 29 Feb 2024 20:10:30 +0300 Subject: [PATCH 18/69] fix: autocomplete constants inside format strings --- .../src/completions/format_string.rs | 95 ++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/crates/ide-completion/src/completions/format_string.rs b/crates/ide-completion/src/completions/format_string.rs index cecbe75391d14..5512ac2153460 100644 --- a/crates/ide-completion/src/completions/format_string.rs +++ b/crates/ide-completion/src/completions/format_string.rs @@ -1,6 +1,7 @@ //! Completes identifiers in format string literals. -use ide_db::syntax_helpers::format_string::is_format_string; +use hir::{ModuleDef, ScopeDef}; +use ide_db::{syntax_helpers::format_string::is_format_string, SymbolKind}; use itertools::Itertools; use syntax::{ast, AstToken, TextRange, TextSize}; @@ -33,7 +34,23 @@ pub(crate) fn format_string( ctx.locals.iter().for_each(|(name, _)| { CompletionItem::new(CompletionItemKind::Binding, source_range, name.to_smol_str()) .add_to(acc, ctx.db); - }) + }); + ctx.scope.process_all_names(&mut |name, scope| { + if let ScopeDef::ModuleDef(module_def) = scope { + let symbol_kind = match module_def { + ModuleDef::Const(..) => SymbolKind::Const, + ModuleDef::Static(..) => SymbolKind::Static, + _ => return, + }; + + CompletionItem::new( + CompletionItemKind::SymbolKind(symbol_kind), + source_range, + name.to_smol_str(), + ) + .add_to(acc, ctx.db); + } + }); } #[cfg(test)] @@ -110,6 +127,80 @@ fn main() { let foobar = 1; format_args!("{foobar"); } +"#, + ); + } + + #[test] + fn completes_constants() { + check_edit( + "FOOBAR", + r#" +//- minicore: fmt +fn main() { + const FOOBAR: usize = 42; + format_args!("{f$0"); +} +"#, + r#" +fn main() { + const FOOBAR: usize = 42; + format_args!("{FOOBAR"); +} +"#, + ); + + check_edit( + "FOOBAR", + r#" +//- minicore: fmt +fn main() { + const FOOBAR: usize = 42; + format_args!("{$0"); +} +"#, + r#" +fn main() { + const FOOBAR: usize = 42; + format_args!("{FOOBAR"); +} +"#, + ); + } + + #[test] + fn completes_static_constants() { + check_edit( + "FOOBAR", + r#" +//- minicore: fmt +fn main() { + static FOOBAR: usize = 42; + format_args!("{f$0"); +} +"#, + r#" +fn main() { + static FOOBAR: usize = 42; + format_args!("{FOOBAR"); +} +"#, + ); + + check_edit( + "FOOBAR", + r#" +//- minicore: fmt +fn main() { + static FOOBAR: usize = 42; + format_args!("{$0"); +} +"#, + r#" +fn main() { + static FOOBAR: usize = 42; + format_args!("{FOOBAR"); +} "#, ); } From dba67b46a118b6a0e58c6aa87c63f7d96a837888 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sat, 2 Mar 2024 10:01:04 +0800 Subject: [PATCH 19/69] update for review --- crates/hir-ty/src/display.rs | 32 +++++++++++++++++++++++++++++- crates/hir/src/display.rs | 4 ++-- crates/ide-db/src/defs.rs | 12 ++--------- crates/ide/src/hover.rs | 2 +- crates/ide/src/hover/render.rs | 10 +++++++--- crates/ide/src/hover/tests.rs | 2 +- crates/ide/src/static_index.rs | 6 +++--- crates/rust-analyzer/src/config.rs | 8 ++++---- docs/user/generated_config.adoc | 10 +++++----- editors/code/package.json | 18 ++++++++--------- 10 files changed, 65 insertions(+), 39 deletions(-) diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index f7e396de2d6b7..328dea87ac112 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -62,7 +62,8 @@ pub struct HirFormatter<'a> { fmt: &'a mut dyn HirWrite, buf: String, curr_size: usize, - pub max_size: Option, + pub(crate) max_size: Option, + pub limited_size: Option, omit_verbose_types: bool, closure_style: ClosureStyle, display_target: DisplayTarget, @@ -86,6 +87,7 @@ pub trait HirDisplay { &'a self, db: &'a dyn HirDatabase, max_size: Option, + limited_size: Option, omit_verbose_types: bool, display_target: DisplayTarget, closure_style: ClosureStyle, @@ -101,6 +103,7 @@ pub trait HirDisplay { db, t: self, max_size, + limited_size, omit_verbose_types, display_target, closure_style, @@ -117,6 +120,7 @@ pub trait HirDisplay { db, t: self, max_size: None, + limited_size: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, display_target: DisplayTarget::Diagnostics, @@ -137,6 +141,28 @@ pub trait HirDisplay { db, t: self, max_size, + limited_size: None, + omit_verbose_types: true, + closure_style: ClosureStyle::ImplFn, + display_target: DisplayTarget::Diagnostics, + } + } + + /// Returns a `Display`able type that is human-readable and tries to limit the item inside this type. + /// Use this for showing types which may contain two many item when user hover on, like `trait`, `struct`, `enum` + fn display_limited<'a>( + &'a self, + db: &'a dyn HirDatabase, + limited_size: Option, + ) -> HirDisplayWrapper<'a, Self> + where + Self: Sized, + { + HirDisplayWrapper { + db, + t: self, + max_size: None, + limited_size, omit_verbose_types: true, closure_style: ClosureStyle::ImplFn, display_target: DisplayTarget::Diagnostics, @@ -158,6 +184,7 @@ pub trait HirDisplay { buf: String::with_capacity(20), curr_size: 0, max_size: None, + limited_size: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, display_target: DisplayTarget::SourceCode { module_id, allow_opaque }, @@ -178,6 +205,7 @@ pub trait HirDisplay { db, t: self, max_size: None, + limited_size: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, display_target: DisplayTarget::Test, @@ -295,6 +323,7 @@ pub struct HirDisplayWrapper<'a, T> { db: &'a dyn HirDatabase, t: &'a T, max_size: Option, + limited_size: Option, omit_verbose_types: bool, closure_style: ClosureStyle, display_target: DisplayTarget, @@ -323,6 +352,7 @@ impl HirDisplayWrapper<'_, T> { buf: String::with_capacity(20), curr_size: 0, max_size: self.max_size, + limited_size: self.limited_size, omit_verbose_types: self.omit_verbose_types, display_target: self.display_target, closure_style: self.closure_style, diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 08e0c6e752473..20ba72d998c31 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -598,7 +598,7 @@ impl HirDisplay for Trait { let assoc_items = self.items(f.db); let assoc_items_size = assoc_items.len(); - let max_display_size = f.max_size.unwrap_or(assoc_items_size); + let limited_size = f.limited_size.unwrap_or(assoc_items_size); if assoc_items.is_empty() { f.write_str(" {}")?; } else { @@ -617,7 +617,7 @@ impl HirDisplay for Trait { } }; f.write_str(",\n")?; - if index + 1 == max_display_size && index + 1 != assoc_items_size { + if index + 1 == limited_size && index + 1 != assoc_items_size { f.write_str(" ...\n")?; break; } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 35aaf864696af..1b6ff8bad53c5 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -24,12 +24,6 @@ use crate::documentation::{Documentation, HasDocs}; use crate::famous_defs::FamousDefs; use crate::RootDatabase; -#[derive(Default)] -pub struct HoverDisplayConfig { - pub trait_item_display_num: Option, - // todo: add config for struct & enum -} - // FIXME: a more precise name would probably be `Symbol`? #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] pub enum Definition { @@ -219,7 +213,7 @@ impl Definition { }) } - pub fn label(&self, db: &RootDatabase, hover_display_config: HoverDisplayConfig) -> String { + pub fn label(&self, db: &RootDatabase) -> String { match *self { Definition::Macro(it) => it.display(db).to_string(), Definition::Field(it) => it.display(db).to_string(), @@ -230,9 +224,7 @@ impl Definition { Definition::Variant(it) => it.display(db).to_string(), Definition::Const(it) => it.display(db).to_string(), Definition::Static(it) => it.display(db).to_string(), - Definition::Trait(it) => { - it.display_truncated(db, hover_display_config.trait_item_display_num).to_string() - } + Definition::Trait(it) => it.display(db).to_string(), Definition::TraitAlias(it) => it.display(db).to_string(), Definition::TypeAlias(it) => it.display(db).to_string(), Definition::BuiltinType(it) => it.name().display(db).to_string(), diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 64346a59b77fb..b6877c5e8ce95 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -32,7 +32,7 @@ pub struct HoverConfig { pub documentation: bool, pub keywords: bool, pub format: HoverDocFormat, - pub trait_item_display_num: Option, + pub trait_assoc_items_size: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 6d7886feec338..f528bd512ccee 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -8,7 +8,7 @@ use hir::{ }; use ide_db::{ base_db::SourceDatabase, - defs::{Definition, HoverDisplayConfig}, + defs::Definition, documentation::HasDocs, famous_defs::FamousDefs, generated::lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, @@ -406,8 +406,12 @@ pub(super) fn definition( config: &HoverConfig, ) -> Markup { let mod_path = definition_mod_path(db, &def); - let hover_config = HoverDisplayConfig { trait_item_display_num: config.trait_item_display_num }; - let label = def.label(db, hover_config); + let label = match def { + Definition::Trait(trait_) => { + trait_.display_limited(db, config.trait_assoc_items_size).to_string() + } + _ => def.label(db), + }; let docs = def.docs(db, famous_defs); let value = (|| match def { Definition::Variant(it) => { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index e2278fe4b3abc..70f4068478d8d 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -17,7 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { documentation: true, format: HoverDocFormat::Markdown, keywords: true, - trait_item_display_num: Some(7), + trait_assoc_items_size: None, }; fn check_hover_no_result(ra_fixture: &str) { diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 8d6e161c1b971..0f19da0ac5fba 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -4,7 +4,7 @@ use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics}; use ide_db::{ base_db::{FileId, FileRange, SourceDatabaseExt}, - defs::{Definition, HoverDisplayConfig}, + defs::Definition, documentation::Documentation, famous_defs::FamousDefs, helpers::get_definition, @@ -166,7 +166,7 @@ impl StaticIndex<'_> { documentation: true, keywords: true, format: crate::HoverDocFormat::Markdown, - trait_item_display_num: None, + trait_assoc_items_size: None, }; let tokens = tokens.filter(|token| { matches!( @@ -197,7 +197,7 @@ impl StaticIndex<'_> { enclosing_moniker: current_crate .zip(def.enclosing_definition(self.db)) .and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)), - signature: Some(def.label(self.db, HoverDisplayConfig::default())), + signature: Some(def.label(self.db)), kind: def_to_kind(self.db, def), }); self.def_map.insert(def, it); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 40a2077cb1855..259ee3ea8c20e 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -368,6 +368,9 @@ config_data! { /// How to render the size information in a memory layout hover. hover_memoryLayout_size: Option = "\"both\"", + /// How many associated items of a trait to display when hovering a trait. + hover_show_traitAssocItems: Option = "null", + /// Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file. imports_granularity_enforce: bool = "false", /// How imports should be grouped into use statements. @@ -590,9 +593,6 @@ config_data! { /// Show documentation. signatureInfo_documentation_enable: bool = "true", - /// How many trait item display on hover. - traitItemDisplayNum: Option = "7", - /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list. typing_autoClosingAngleBrackets_enable: bool = "false", @@ -1685,7 +1685,7 @@ impl Config { } }, keywords: self.data.hover_documentation_keywords_enable, - trait_item_display_num: self.data.traitItemDisplayNum, + trait_assoc_items_size: self.data.hover_show_traitAssocItems, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 7d005828b8c60..7b292fc78f76b 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -505,6 +505,11 @@ How to render the offset information in a memory layout hover. -- How to render the size information in a memory layout hover. -- +[[rust-analyzer.hover.show.traitAssocItems]]rust-analyzer.hover.show.traitAssocItems (default: `null`):: ++ +-- +How many associated items of a trait to display when hovering a trait. +-- [[rust-analyzer.imports.granularity.enforce]]rust-analyzer.imports.granularity.enforce (default: `false`):: + -- @@ -927,11 +932,6 @@ Show full signature of the callable. Only shows parameters if disabled. -- Show documentation. -- -[[rust-analyzer.traitItemDisplayNum]]rust-analyzer.traitItemDisplayNum (default: `7`):: -+ --- -How many trait item display on hover. --- [[rust-analyzer.typing.autoClosingAngleBrackets.enable]]rust-analyzer.typing.autoClosingAngleBrackets.enable (default: `false`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index b68ab66cdab67..719521a224eca 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1119,6 +1119,15 @@ } ] }, + "rust-analyzer.hover.show.traitAssocItems": { + "markdownDescription": "How many associated items of a trait to display when hovering a trait.", + "default": null, + "type": [ + "null", + "integer" + ], + "minimum": 0 + }, "rust-analyzer.imports.granularity.enforce": { "markdownDescription": "Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file.", "default": false, @@ -1648,15 +1657,6 @@ "default": true, "type": "boolean" }, - "rust-analyzer.traitItemDisplayNum": { - "markdownDescription": "How many trait item display on hover.", - "default": 7, - "type": [ - "null", - "integer" - ], - "minimum": 0 - }, "rust-analyzer.typing.autoClosingAngleBrackets.enable": { "markdownDescription": "Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.", "default": false, From 7c6f7b2c49cb4f4cfbad15d0f44a2ce69918a512 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 3 Mar 2024 00:34:27 +0100 Subject: [PATCH 20/69] Update rustc_pattern_analysis --- Cargo.lock | 16 ++++++++-------- Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9acace2fb3313..982468765b4fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1470,12 +1470,12 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index" -version = "0.37.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df5a0ba0d08af366cf235dbe8eb7226cced7a4fe502c98aa434ccf416defd746" +checksum = "371db64f1be25aae96650b5528c76066ac325f0fe23efec0aab1179d75eea5c3" dependencies = [ "arrayvec", - "ra-ap-rustc_index_macros 0.37.0", + "ra-ap-rustc_index_macros 0.40.0", "smallvec", ] @@ -1493,9 +1493,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index_macros" -version = "0.37.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1971ebf9a701e0e68387c264a32517dcb4861ad3a4862f2e2803c1121ade20d5" +checksum = "fa4a454193807f557a991f52157250fd2db95abfb96da65e85355e6949802a98" dependencies = [ "proc-macro2", "quote", @@ -1525,11 +1525,11 @@ dependencies = [ [[package]] name = "ra-ap-rustc_pattern_analysis" -version = "0.37.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3c0e7ca9c5bdc66e3b590688e237a22ac47a48e4eac7f46b05b2abbfaf0abd" +checksum = "c9cb49490fadb58e6b8cc825f73157a33730495bfd5c6e9eef067a4b50ad1836" dependencies = [ - "ra-ap-rustc_index 0.37.0", + "ra-ap-rustc_index 0.40.0", "rustc-hash", "rustc_apfloat", "smallvec", diff --git a/Cargo.toml b/Cargo.toml index 16dd510389988..e68613c6d3840 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,7 +88,7 @@ ra-ap-rustc_lexer = { version = "0.35.0", default-features = false } ra-ap-rustc_parse_format = { version = "0.35.0", default-features = false } ra-ap-rustc_index = { version = "0.35.0", default-features = false } ra-ap-rustc_abi = { version = "0.35.0", default-features = false } -ra-ap-rustc_pattern_analysis = { version = "0.37.0", default-features = false } +ra-ap-rustc_pattern_analysis = { version = "0.40.0", default-features = false } # local crates that aren't published to crates.io. These should not have versions. sourcegen = { path = "./crates/sourcegen" } From 4303e741de62ec9e1ebbcfbafee0ed52a92f0f2a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 11:10:06 +0100 Subject: [PATCH 21/69] Cleanup --- Cargo.lock | 11 +- crates/base-db/Cargo.toml | 1 - crates/hir-def/src/body.rs | 4 - crates/hir-def/src/body/lower.rs | 2 - crates/hir-def/src/item_tree.rs | 49 ++- crates/hir-def/src/nameres.rs | 334 +++++++++--------- crates/hir-def/src/nameres/collector.rs | 175 ++++----- crates/hir-def/src/nameres/diagnostics.rs | 24 +- crates/hir-def/src/nameres/mod_resolution.rs | 18 +- crates/hir-def/src/nameres/path_resolution.rs | 43 ++- crates/hir-expand/Cargo.toml | 3 +- crates/hir-expand/src/builtin_attr_macro.rs | 25 +- crates/hir-expand/src/builtin_derive_macro.rs | 30 +- crates/hir-expand/src/builtin_fn_macro.rs | 54 +-- crates/hir-expand/src/change.rs | 4 +- crates/hir-expand/src/mod_path.rs | 6 + crates/hir-ty/Cargo.toml | 1 - crates/hir/Cargo.toml | 1 - crates/hir/src/lib.rs | 2 +- crates/ide-assists/Cargo.toml | 1 - crates/ide-completion/Cargo.toml | 1 - crates/ide-db/src/apply_change.rs | 4 +- crates/ide-db/src/lib.rs | 2 +- crates/ide-diagnostics/Cargo.toml | 1 - crates/ide/src/lib.rs | 6 +- crates/load-cargo/src/lib.rs | 4 +- crates/parser/Cargo.toml | 2 + crates/parser/src/lexed_str.rs | 1 + crates/parser/src/lib.rs | 1 + crates/parser/src/shortcuts.rs | 1 + crates/proc-macro-api/Cargo.toml | 1 - crates/profile/src/lib.rs | 23 -- crates/project-model/Cargo.toml | 3 +- crates/rust-analyzer/src/cli/rustc_tests.rs | 4 +- crates/rust-analyzer/src/global_state.rs | 4 +- .../src/integrated_benchmarks.rs | 14 +- crates/rust-analyzer/src/reload.rs | 6 +- crates/syntax/Cargo.toml | 1 - crates/syntax/src/lib.rs | 1 + crates/syntax/src/parsing.rs | 2 + crates/syntax/src/validation.rs | 1 + crates/test-fixture/src/lib.rs | 6 +- 42 files changed, 421 insertions(+), 456 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9acace2fb3313..f074bb4e30eca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,6 @@ version = "0.0.0" dependencies = [ "cfg", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "profile", "rustc-hash", "salsa", "semver", @@ -501,7 +500,6 @@ dependencies = [ "hir-ty", "itertools", "once_cell", - "profile", "rustc-hash", "smallvec", "span", @@ -565,7 +563,6 @@ dependencies = [ "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "limit", "mbe", - "profile", "rustc-hash", "smallvec", "span", @@ -601,7 +598,6 @@ dependencies = [ "nohash-hasher", "once_cell", "oorandom", - "profile", "project-model", "ra-ap-rustc_abi", "ra-ap-rustc_index 0.35.0", @@ -673,7 +669,6 @@ dependencies = [ "hir", "ide-db", "itertools", - "profile", "smallvec", "sourcegen", "stdx", @@ -695,7 +690,6 @@ dependencies = [ "ide-db", "itertools", "once_cell", - "profile", "smallvec", "stdx", "syntax", @@ -753,7 +747,6 @@ dependencies = [ "ide-db", "itertools", "once_cell", - "profile", "serde_json", "sourcegen", "stdx", @@ -1233,6 +1226,7 @@ dependencies = [ "ra-ap-rustc_lexer", "sourcegen", "stdx", + "tracing", ] [[package]] @@ -1302,7 +1296,6 @@ dependencies = [ "memmap2", "object 0.32.0", "paths", - "profile", "rustc-hash", "serde", "serde_json", @@ -1386,7 +1379,6 @@ dependencies = [ "itertools", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "paths", - "profile", "rustc-hash", "semver", "serde", @@ -1925,7 +1917,6 @@ dependencies = [ "once_cell", "parser", "proc-macro2", - "profile", "quote", "ra-ap-rustc_lexer", "rayon", diff --git a/crates/base-db/Cargo.toml b/crates/base-db/Cargo.toml index 801ba2d1f6c85..118abf5d6eb8b 100644 --- a/crates/base-db/Cargo.toml +++ b/crates/base-db/Cargo.toml @@ -21,7 +21,6 @@ tracing.workspace = true # local deps cfg.workspace = true -profile.workspace = true stdx.workspace = true syntax.workspace = true vfs.workspace = true diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index ce8a9eab14a9d..37d37fd331158 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -13,7 +13,6 @@ use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_expand::{name::Name, HirFileId, InFile}; use la_arena::{Arena, ArenaMap}; -use profile::Count; use rustc_hash::FxHashMap; use syntax::{ast, AstPtr, SyntaxNodePtr}; use triomphe::Arc; @@ -51,7 +50,6 @@ pub struct Body { pub body_expr: ExprId, /// Block expressions in this body that may contain inner items. block_scopes: Vec, - _c: Count, } pub type ExprPtr = AstPtr; @@ -216,7 +214,6 @@ impl Body { fn shrink_to_fit(&mut self) { let Self { - _c: _, body_expr: _, block_scopes, exprs, @@ -300,7 +297,6 @@ impl Default for Body { params: Default::default(), block_scopes: Default::default(), binding_owners: Default::default(), - _c: Default::default(), } } } diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index ad8782d3d1e30..c9300898b386c 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -10,7 +10,6 @@ use hir_expand::{ ExpandError, InFile, }; use intern::Interned; -use profile::Count; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::AstIdMap; @@ -76,7 +75,6 @@ pub(super) fn lower( params: Vec::new(), body_expr: dummy_expr_id(), block_scopes: Vec::new(), - _c: Count::new(), }, expander, current_try_block_label: None, diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index c7cf611589b0d..008fa7ef13afd 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -50,7 +50,6 @@ use either::Either; use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile}; use intern::Interned; use la_arena::{Arena, Idx, IdxRange, RawIdx}; -use profile::Count; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::{AstIdNode, FileAstId, Span}; @@ -94,8 +93,6 @@ impl fmt::Debug for RawVisibilityId { /// The item tree of a source file. #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { - _c: Count, - top_level: SmallVec<[ModItem; 1]>, attrs: FxHashMap, @@ -263,14 +260,6 @@ impl ItemVisibilities { } } -static VIS_PUB: RawVisibility = RawVisibility::Public; -static VIS_PRIV_IMPLICIT: RawVisibility = - RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Implicit); -static VIS_PRIV_EXPLICIT: RawVisibility = - RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Explicit); -static VIS_PUB_CRATE: RawVisibility = - RawVisibility::Module(ModPath::from_kind(PathKind::Crate), VisibilityExplicitness::Explicit); - #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { uses: Arena, @@ -562,6 +551,20 @@ impl_index!(fields: Field, variants: Variant, params: Param); impl Index for ItemTree { type Output = RawVisibility; fn index(&self, index: RawVisibilityId) -> &Self::Output { + static VIS_PUB: RawVisibility = RawVisibility::Public; + static VIS_PRIV_IMPLICIT: RawVisibility = RawVisibility::Module( + ModPath::from_kind(PathKind::Super(0)), + VisibilityExplicitness::Implicit, + ); + static VIS_PRIV_EXPLICIT: RawVisibility = RawVisibility::Module( + ModPath::from_kind(PathKind::Super(0)), + VisibilityExplicitness::Explicit, + ); + static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module( + ModPath::from_kind(PathKind::Crate), + VisibilityExplicitness::Explicit, + ); + match index { RawVisibilityId::PRIV_IMPLICIT => &VIS_PRIV_IMPLICIT, RawVisibilityId::PRIV_EXPLICIT => &VIS_PRIV_EXPLICIT, @@ -871,25 +874,19 @@ impl UseTree { prefix: Option, path: &ModPath, ) -> Option<(ModPath, ImportKind)> { - match (prefix, &path.kind) { + match (prefix, path.kind) { (None, _) => Some((path.clone(), ImportKind::Plain)), (Some(mut prefix), PathKind::Plain) => { - for segment in path.segments() { - prefix.push_segment(segment.clone()); - } + prefix.extend(path.segments().iter().cloned()); Some((prefix, ImportKind::Plain)) } - (Some(mut prefix), PathKind::Super(n)) - if *n > 0 && prefix.segments().is_empty() => - { + (Some(mut prefix), PathKind::Super(n)) if n > 0 && prefix.segments().is_empty() => { // `super::super` + `super::rest` match &mut prefix.kind { PathKind::Super(m) => { cov_mark::hit!(concat_super_mod_paths); - *m += *n; - for segment in path.segments() { - prefix.push_segment(segment.clone()); - } + *m += n; + prefix.extend(path.segments().iter().cloned()); Some((prefix, ImportKind::Plain)) } _ => None, @@ -963,10 +960,10 @@ impl ModItem { | ModItem::Mod(_) | ModItem::MacroRules(_) | ModItem::Macro2(_) => None, - ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), - ModItem::Const(konst) => Some(AssocItem::Const(*konst)), - ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), - ModItem::Function(func) => Some(AssocItem::Function(*func)), + &ModItem::MacroCall(call) => Some(AssocItem::MacroCall(call)), + &ModItem::Const(konst) => Some(AssocItem::Const(konst)), + &ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(alias)), + &ModItem::Function(func) => Some(AssocItem::Function(func)), } } diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 270468ad0a622..764617eafb7bb 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -65,7 +65,6 @@ use hir_expand::{ }; use itertools::Itertools; use la_arena::Arena; -use profile::Count; use rustc_hash::{FxHashMap, FxHashSet}; use span::FileAstId; use stdx::format_to; @@ -95,7 +94,6 @@ use crate::{ /// is computed by the `block_def_map` query. #[derive(Debug, PartialEq, Eq)] pub struct DefMap { - _c: Count, /// When this is a block def map, this will hold the block id of the block and module that /// contains this block. block: Option, @@ -154,6 +152,23 @@ struct DefMapCrateData { } impl DefMapCrateData { + fn new(edition: Edition) -> Self { + Self { + extern_prelude: FxHashMap::default(), + exported_derives: FxHashMap::default(), + fn_proc_macro_mapping: FxHashMap::default(), + proc_macro_loading_error: None, + registered_attrs: Vec::new(), + registered_tools: Vec::new(), + unstable_features: FxHashSet::default(), + rustc_coherence_is_core: false, + no_core: false, + no_std: false, + edition, + recursion_limit: None, + } + } + fn shrink_to_fit(&mut self) { let Self { extern_prelude, @@ -305,67 +320,67 @@ impl DefMap { /// The module id of a crate or block root. pub const ROOT: LocalModuleId = LocalModuleId::from_raw(la_arena::RawIdx::from_u32(0)); - pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc { + pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: CrateId) -> Arc { let crate_graph = db.crate_graph(); - let krate_name = crate_graph[krate].display_name.as_deref().unwrap_or_default(); - - let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?krate_name).entered(); + let krate = &crate_graph[crate_id]; + let name = krate.display_name.as_deref().unwrap_or_default(); + let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?name).entered(); - let crate_graph = db.crate_graph(); + let module_data = ModuleData::new( + ModuleOrigin::CrateRoot { definition: krate.root_file_id }, + Visibility::Public, + ); - let edition = crate_graph[krate].edition; - let origin = ModuleOrigin::CrateRoot { definition: crate_graph[krate].root_file_id }; - let def_map = DefMap::empty(krate, edition, ModuleData::new(origin, Visibility::Public)); - let def_map = collector::collect_defs( - db, - def_map, - TreeId::new(crate_graph[krate].root_file_id.into(), None), + let def_map = DefMap::empty( + crate_id, + Arc::new(DefMapCrateData::new(krate.edition)), + module_data, + None, ); + let def_map = + collector::collect_defs(db, def_map, TreeId::new(krate.root_file_id.into(), None)); Arc::new(def_map) } pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc { - let block: BlockLoc = block_id.lookup(db); - - let parent_map = block.module.def_map(db); - let krate = block.module.krate; - let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0)); - // NB: we use `None` as block here, which would be wrong for implicit - // modules declared by blocks with items. At the moment, we don't use - // this visibility for anything outside IDE, so that's probably OK. + let BlockLoc { ast_id, module } = block_id.lookup(db); + let visibility = Visibility::Module( - ModuleId { krate, local_id, block: None }, + ModuleId { krate: module.krate, local_id: Self::ROOT, block: module.block }, VisibilityExplicitness::Implicit, ); - let module_data = ModuleData::new( - ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id }, - visibility, + let module_data = + ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility); + + let parent_map = module.def_map(db); + let def_map = DefMap::empty( + module.krate, + parent_map.data.clone(), + module_data, + Some(BlockInfo { + block: block_id, + parent: BlockRelativeModuleId { block: module.block, local_id: module.local_id }, + }), ); - let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data); - def_map.data = parent_map.data.clone(); - def_map.block = Some(BlockInfo { - block: block_id, - parent: BlockRelativeModuleId { - block: block.module.block, - local_id: block.module.local_id, - }, - }); - let def_map = - collector::collect_defs(db, def_map, TreeId::new(block.ast_id.file_id, Some(block_id))); + collector::collect_defs(db, def_map, TreeId::new(ast_id.file_id, Some(block_id))); Arc::new(def_map) } - fn empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap { + fn empty( + krate: CrateId, + crate_data: Arc, + module_data: ModuleData, + block: Option, + ) -> DefMap { let mut modules: Arena = Arena::default(); let root = modules.alloc(module_data); assert_eq!(root, Self::ROOT); DefMap { - _c: Count::new(), - block: None, + block, modules, krate, prelude: None, @@ -373,23 +388,36 @@ impl DefMap { derive_helpers_in_scope: FxHashMap::default(), diagnostics: Vec::new(), enum_definitions: FxHashMap::default(), - data: Arc::new(DefMapCrateData { - extern_prelude: FxHashMap::default(), - exported_derives: FxHashMap::default(), - fn_proc_macro_mapping: FxHashMap::default(), - proc_macro_loading_error: None, - registered_attrs: Vec::new(), - registered_tools: Vec::new(), - unstable_features: FxHashSet::default(), - rustc_coherence_is_core: false, - no_core: false, - no_std: false, - edition, - recursion_limit: None, - }), + data: crate_data, + } + } + fn shrink_to_fit(&mut self) { + // Exhaustive match to require handling new fields. + let Self { + macro_use_prelude, + diagnostics, + modules, + derive_helpers_in_scope, + block: _, + krate: _, + prelude: _, + data: _, + enum_definitions, + } = self; + + macro_use_prelude.shrink_to_fit(); + diagnostics.shrink_to_fit(); + modules.shrink_to_fit(); + derive_helpers_in_scope.shrink_to_fit(); + enum_definitions.shrink_to_fit(); + for (_, module) in modules.iter_mut() { + module.children.shrink_to_fit(); + module.scope.shrink_to_fit(); } } +} +impl DefMap { pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator + '_ { self.modules .iter() @@ -440,26 +468,6 @@ impl DefMap { self.krate } - pub(crate) fn block_id(&self) -> Option { - self.block.map(|block| block.block) - } - - pub(crate) fn prelude(&self) -> Option<(ModuleId, Option)> { - self.prelude - } - - pub(crate) fn extern_prelude( - &self, - ) -> impl Iterator))> + '_ { - self.data.extern_prelude.iter().map(|(name, &def)| (name, def)) - } - - pub(crate) fn macro_use_prelude( - &self, - ) -> impl Iterator))> + '_ { - self.macro_use_prelude.iter().map(|(name, &def)| (name, def)) - } - pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId { let block = self.block.map(|b| b.block); ModuleId { krate: self.krate, local_id, block } @@ -475,68 +483,6 @@ impl DefMap { self.module_id(Self::ROOT) } - pub(crate) fn resolve_path( - &self, - db: &dyn DefDatabase, - original_module: LocalModuleId, - path: &ModPath, - shadow: BuiltinShadowMode, - expected_macro_subns: Option, - ) -> (PerNs, Option) { - let res = self.resolve_path_fp_with_macro( - db, - ResolveMode::Other, - original_module, - path, - shadow, - expected_macro_subns, - ); - (res.resolved_def, res.segment_index) - } - - pub(crate) fn resolve_path_locally( - &self, - db: &dyn DefDatabase, - original_module: LocalModuleId, - path: &ModPath, - shadow: BuiltinShadowMode, - ) -> (PerNs, Option) { - let res = self.resolve_path_fp_with_macro_single( - db, - ResolveMode::Other, - original_module, - path, - shadow, - None, // Currently this function isn't used for macro resolution. - ); - (res.resolved_def, res.segment_index) - } - - /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module. - /// - /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns - /// `None`, iteration continues. - pub(crate) fn with_ancestor_maps( - &self, - db: &dyn DefDatabase, - local_mod: LocalModuleId, - f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option, - ) -> Option { - if let Some(it) = f(self, local_mod) { - return Some(it); - } - let mut block = self.block; - while let Some(block_info) = block { - let parent = block_info.parent.def_map(db, self.krate); - if let Some(it) = f(&parent, block_info.parent.local_id) { - return Some(it); - } - block = parent.block; - } - - None - } - /// If this `DefMap` is for a block expression, returns the module containing the block (which /// might again be a block, or a module inside a block). pub fn parent(&self) -> Option { @@ -559,6 +505,16 @@ impl DefMap { } } + /// Get a reference to the def map's diagnostics. + pub fn diagnostics(&self) -> &[DefDiagnostic] { + self.diagnostics.as_slice() + } + + pub fn recursion_limit(&self) -> u32 { + // 128 is the default in rustc + self.data.recursion_limit.unwrap_or(128) + } + // FIXME: this can use some more human-readable format (ideally, an IR // even), as this should be a great debugging aid. pub fn dump(&self, db: &dyn DefDatabase) -> String { @@ -608,41 +564,89 @@ impl DefMap { format_to!(buf, "crate scope\n"); buf } +} - fn shrink_to_fit(&mut self) { - // Exhaustive match to require handling new fields. - let Self { - _c: _, - macro_use_prelude, - diagnostics, - modules, - derive_helpers_in_scope, - block: _, - krate: _, - prelude: _, - data: _, - enum_definitions, - } = self; +impl DefMap { + pub(crate) fn block_id(&self) -> Option { + self.block.map(|block| block.block) + } - macro_use_prelude.shrink_to_fit(); - diagnostics.shrink_to_fit(); - modules.shrink_to_fit(); - derive_helpers_in_scope.shrink_to_fit(); - enum_definitions.shrink_to_fit(); - for (_, module) in modules.iter_mut() { - module.children.shrink_to_fit(); - module.scope.shrink_to_fit(); - } + pub(crate) fn prelude(&self) -> Option<(ModuleId, Option)> { + self.prelude } - /// Get a reference to the def map's diagnostics. - pub fn diagnostics(&self) -> &[DefDiagnostic] { - self.diagnostics.as_slice() + pub(crate) fn extern_prelude( + &self, + ) -> impl Iterator))> + '_ { + self.data.extern_prelude.iter().map(|(name, &def)| (name, def)) } - pub fn recursion_limit(&self) -> u32 { - // 128 is the default in rustc - self.data.recursion_limit.unwrap_or(128) + pub(crate) fn macro_use_prelude( + &self, + ) -> impl Iterator))> + '_ { + self.macro_use_prelude.iter().map(|(name, &def)| (name, def)) + } + + pub(crate) fn resolve_path( + &self, + db: &dyn DefDatabase, + original_module: LocalModuleId, + path: &ModPath, + shadow: BuiltinShadowMode, + expected_macro_subns: Option, + ) -> (PerNs, Option) { + let res = self.resolve_path_fp_with_macro( + db, + ResolveMode::Other, + original_module, + path, + shadow, + expected_macro_subns, + ); + (res.resolved_def, res.segment_index) + } + + pub(crate) fn resolve_path_locally( + &self, + db: &dyn DefDatabase, + original_module: LocalModuleId, + path: &ModPath, + shadow: BuiltinShadowMode, + ) -> (PerNs, Option) { + let res = self.resolve_path_fp_with_macro_single( + db, + ResolveMode::Other, + original_module, + path, + shadow, + None, // Currently this function isn't used for macro resolution. + ); + (res.resolved_def, res.segment_index) + } + + /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module. + /// + /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns + /// `None`, iteration continues. + pub(crate) fn with_ancestor_maps( + &self, + db: &dyn DefDatabase, + local_mod: LocalModuleId, + f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option, + ) -> Option { + if let Some(it) = f(self, local_mod) { + return Some(it); + } + let mut block = self.block; + while let Some(block_info) = block { + let parent = block_info.parent.def_map(db, self.krate); + if let Some(it) = f(&parent, block_info.parent.local_id) { + return Some(it); + } + block = parent.block; + } + + None } } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 538e735688bab..18aefbf332c8d 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -64,19 +64,18 @@ static FIXED_POINT_LIMIT: Limit = Limit::new(8192); pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeId) -> DefMap { let crate_graph = db.crate_graph(); - let mut deps = FxHashMap::default(); - // populate external prelude and dependency list let krate = &crate_graph[def_map.krate]; + + // populate external prelude and dependency list + let mut deps = + FxHashMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default()); for dep in &krate.dependencies { tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); deps.insert(dep.as_name(), dep.clone()); } - let cfg_options = &krate.cfg_options; - - let is_proc_macro = krate.is_proc_macro; - let proc_macros = if is_proc_macro { + let proc_macros = if krate.is_proc_macro { match db.proc_macros().get(&def_map.krate) { Some(Ok(proc_macros)) => { Ok(proc_macros @@ -124,11 +123,11 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI indeterminate_imports: Vec::new(), unresolved_macros: Vec::new(), mod_dirs: FxHashMap::default(), - cfg_options, + cfg_options: &krate.cfg_options, proc_macros, from_glob_import: Default::default(), skip_attrs: Default::default(), - is_proc_macro, + is_proc_macro: krate.is_proc_macro, }; if tree_id.is_block() { collector.seed_with_inner(tree_id); @@ -302,71 +301,50 @@ impl DefCollector<'_> { return; } } - let attr_name = match attr.path.as_ident() { - Some(name) => name, - None => continue, - }; + let Some(attr_name) = attr.path.as_ident() else { continue }; - if *attr_name == hir_expand::name![recursion_limit] { - if let Some(limit) = attr.string_value() { - if let Ok(limit) = limit.parse() { - crate_data.recursion_limit = Some(limit); + match () { + () if *attr_name == hir_expand::name![recursion_limit] => { + if let Some(limit) = attr.string_value() { + if let Ok(limit) = limit.parse() { + crate_data.recursion_limit = Some(limit); + } } } - continue; - } - - if *attr_name == hir_expand::name![crate_type] { - if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) { - self.is_proc_macro = true; + () if *attr_name == hir_expand::name![crate_type] => { + if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) { + self.is_proc_macro = true; + } } - continue; - } - - if *attr_name == hir_expand::name![no_core] { - crate_data.no_core = true; - continue; - } - - if *attr_name == hir_expand::name![no_std] { - crate_data.no_std = true; - continue; - } - - if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") { - crate_data.rustc_coherence_is_core = true; - continue; - } - - if *attr_name == hir_expand::name![feature] { - let features = attr - .parse_path_comma_token_tree(self.db.upcast()) - .into_iter() - .flatten() - .filter_map(|(feat, _)| match feat.segments() { - [name] => Some(name.to_smol_str()), - _ => None, - }); - crate_data.unstable_features.extend(features); - } - - let attr_is_register_like = *attr_name == hir_expand::name![register_attr] - || *attr_name == hir_expand::name![register_tool]; - if !attr_is_register_like { - continue; - } - - let registered_name = match attr.single_ident_value() { - Some(ident) => ident.as_name(), - _ => continue, - }; - - if *attr_name == hir_expand::name![register_attr] { - crate_data.registered_attrs.push(registered_name.to_smol_str()); - cov_mark::hit!(register_attr); - } else { - crate_data.registered_tools.push(registered_name.to_smol_str()); - cov_mark::hit!(register_tool); + () if *attr_name == hir_expand::name![no_core] => crate_data.no_core = true, + () if *attr_name == hir_expand::name![no_std] => crate_data.no_std = true, + () if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") => { + crate_data.rustc_coherence_is_core = true; + } + () if *attr_name == hir_expand::name![feature] => { + let features = attr + .parse_path_comma_token_tree(self.db.upcast()) + .into_iter() + .flatten() + .filter_map(|(feat, _)| match feat.segments() { + [name] => Some(name.to_smol_str()), + _ => None, + }); + crate_data.unstable_features.extend(features); + } + () if *attr_name == hir_expand::name![register_attr] => { + if let Some(ident) = attr.single_ident_value() { + crate_data.registered_attrs.push(ident.text.clone()); + cov_mark::hit!(register_attr); + } + } + () if *attr_name == hir_expand::name![register_tool] => { + if let Some(ident) = attr.single_ident_value() { + crate_data.registered_tools.push(ident.text.clone()); + cov_mark::hit!(register_tool); + } + } + () => (), } } @@ -409,6 +387,7 @@ impl DefCollector<'_> { // main name resolution fixed-point loop. let mut i = 0; 'resolve_attr: loop { + let _p = tracing::span!(tracing::Level::INFO, "resolve_macros loop").entered(); 'resolve_macros: loop { self.db.unwind_if_cancelled(); @@ -466,9 +445,8 @@ impl DefCollector<'_> { // Additionally, while the proc macro entry points must be `pub`, they are not publicly // exported in type/value namespace. This function reduces the visibility of all items // in the crate root that aren't proc macros. - let root = DefMap::ROOT; - let module_id = self.def_map.module_id(root); - let root = &mut self.def_map.modules[root]; + let module_id = self.def_map.module_id(DefMap::ROOT); + let root = &mut self.def_map.modules[DefMap::ROOT]; root.scope.censor_non_proc_macros(module_id); } } @@ -828,12 +806,10 @@ impl DefCollector<'_> { return PartialResolvedImport::Unresolved; } - if let Some(krate) = res.krate { - if krate != self.def_map.krate { - return PartialResolvedImport::Resolved( - def.filter_visibility(|v| matches!(v, Visibility::Public)), - ); - } + if res.from_differing_crate { + return PartialResolvedImport::Resolved( + def.filter_visibility(|v| matches!(v, Visibility::Public)), + ); } // Check whether all namespaces are resolved. @@ -1920,7 +1896,7 @@ impl ModCollector<'_, '_> { } fn collect_module(&mut self, module_id: FileItemTreeId, attrs: &Attrs) { - let path_attr = attrs.by_key("path").string_value(); + let path_attr = attrs.by_key("path").string_value().map(SmolStr::as_str); let is_macro_use = attrs.by_key("macro_use").exists(); let module = &self.item_tree[module_id]; match &module.kind { @@ -1934,25 +1910,26 @@ impl ModCollector<'_, '_> { module_id, ); - if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr) - { - ModCollector { - def_collector: &mut *self.def_collector, - macro_depth: self.macro_depth, - module_id, - tree_id: self.tree_id, - item_tree: self.item_tree, - mod_dir, - } - .collect_in_top_module(items); - if is_macro_use { - self.import_all_legacy_macros(module_id); - } + let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr) + else { + return; + }; + ModCollector { + def_collector: &mut *self.def_collector, + macro_depth: self.macro_depth, + module_id, + tree_id: self.tree_id, + item_tree: self.item_tree, + mod_dir, + } + .collect_in_top_module(items); + if is_macro_use { + self.import_all_legacy_macros(module_id); } } // out of line module, resolve, parse and recurse ModKind::Outline => { - let ast_id = AstId::new(self.tree_id.file_id(), module.ast_id); + let ast_id = AstId::new(self.file_id(), module.ast_id); let db = self.def_collector.db; match self.mod_dir.resolve_declaration(db, self.file_id(), &module.name, path_attr) { @@ -2445,7 +2422,7 @@ mod tests { use base_db::SourceDatabase; use test_fixture::WithFixture; - use crate::test_db::TestDB; + use crate::{nameres::DefMapCrateData, test_db::TestDB}; use super::*; @@ -2476,8 +2453,12 @@ mod tests { let edition = db.crate_graph()[krate].edition; let module_origin = ModuleOrigin::CrateRoot { definition: file_id }; - let def_map = - DefMap::empty(krate, edition, ModuleData::new(module_origin, Visibility::Public)); + let def_map = DefMap::empty( + krate, + Arc::new(DefMapCrateData::new(edition)), + ModuleData::new(module_origin, Visibility::Public), + None, + ); do_collect_defs(&db, def_map) } diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs index 161b2c0599099..b5a302dbcaf64 100644 --- a/crates/hir-def/src/nameres/diagnostics.rs +++ b/crates/hir-def/src/nameres/diagnostics.rs @@ -1,5 +1,7 @@ //! Diagnostics emitted during DefMap construction. +use std::ops::Not; + use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind}; @@ -16,27 +18,16 @@ use crate::{ #[derive(Debug, PartialEq, Eq)] pub enum DefDiagnosticKind { UnresolvedModule { ast: AstId, candidates: Box<[String]> }, - UnresolvedExternCrate { ast: AstId }, - UnresolvedImport { id: ItemTreeId, index: Idx }, - UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions }, - UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId }, - UnresolvedMacroCall { ast: MacroCallKind, path: ModPath }, - MacroError { ast: MacroCallKind, message: String }, - MacroExpansionParseError { ast: MacroCallKind, errors: Box<[SyntaxError]> }, - UnimplementedBuiltinMacro { ast: AstId }, - InvalidDeriveTarget { ast: AstId, id: usize }, - MalformedDerive { ast: AstId, id: usize }, - MacroDefError { ast: AstId, message: String }, } @@ -45,11 +36,12 @@ pub struct DefDiagnostics(Option>>); impl DefDiagnostics { pub fn new(diagnostics: Vec) -> Self { - Self(if diagnostics.is_empty() { - None - } else { - Some(triomphe::Arc::new(diagnostics.into_boxed_slice())) - }) + Self( + diagnostics + .is_empty() + .not() + .then(|| triomphe::Arc::new(diagnostics.into_boxed_slice())), + ) } pub fn iter(&self) -> impl Iterator { diff --git a/crates/hir-def/src/nameres/mod_resolution.rs b/crates/hir-def/src/nameres/mod_resolution.rs index c45200e2de9df..696fb6a961cd7 100644 --- a/crates/hir-def/src/nameres/mod_resolution.rs +++ b/crates/hir-def/src/nameres/mod_resolution.rs @@ -3,7 +3,6 @@ use arrayvec::ArrayVec; use base_db::{AnchoredPath, FileId}; use hir_expand::{name::Name, HirFileIdExt, MacroFileIdExt}; use limit::Limit; -use syntax::SmolStr; use crate::{db::DefDatabase, HirFileId}; @@ -29,9 +28,9 @@ impl ModDir { pub(super) fn descend_into_definition( &self, name: &Name, - attr_path: Option<&SmolStr>, + attr_path: Option<&str>, ) -> Option { - let path = match attr_path.map(SmolStr::as_str) { + let path = match attr_path { None => { let mut path = self.dir_path.clone(); path.push(&name.unescaped().to_smol_str()); @@ -63,10 +62,9 @@ impl ModDir { db: &dyn DefDatabase, file_id: HirFileId, name: &Name, - attr_path: Option<&SmolStr>, + attr_path: Option<&str>, ) -> Result<(FileId, bool, ModDir), Box<[String]>> { let name = name.unescaped(); - let orig_file_id = file_id.original_file_respecting_includes(db.upcast()); let mut candidate_files = ArrayVec::<_, 2>::new(); match attr_path { @@ -91,17 +89,19 @@ impl ModDir { } }; + let orig_file_id = file_id.original_file_respecting_includes(db.upcast()); for candidate in candidate_files.iter() { let path = AnchoredPath { anchor: orig_file_id, path: candidate.as_str() }; if let Some(file_id) = db.resolve_path(path) { let is_mod_rs = candidate.ends_with("/mod.rs"); - let (dir_path, root_non_dir_owner) = if is_mod_rs || attr_path.is_some() { - (DirPath::empty(), false) + let root_dir_owner = is_mod_rs || attr_path.is_some(); + let dir_path = if root_dir_owner { + DirPath::empty() } else { - (DirPath::new(format!("{}/", name.display(db.upcast()))), true) + DirPath::new(format!("{}/", name.display(db.upcast()))) }; - if let Some(mod_dir) = self.child(dir_path, root_non_dir_owner) { + if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) { return Ok((file_id, is_mod_rs, mod_dir)); } } diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 1e13f7f8fd018..9e53b03728304 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -22,7 +22,7 @@ use crate::{ path::{ModPath, PathKind}, per_ns::PerNs, visibility::{RawVisibility, Visibility}, - AdtId, CrateId, LocalModuleId, ModuleDefId, + AdtId, LocalModuleId, ModuleDefId, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -42,21 +42,21 @@ pub(super) struct ResolvePathResult { pub(super) resolved_def: PerNs, pub(super) segment_index: Option, pub(super) reached_fixedpoint: ReachedFixedPoint, - pub(super) krate: Option, + pub(super) from_differing_crate: bool, } impl ResolvePathResult { fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult { - ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None, None) + ResolvePathResult::new(PerNs::none(), reached_fixedpoint, None, false) } - fn with( + fn new( resolved_def: PerNs, reached_fixedpoint: ReachedFixedPoint, segment_index: Option, - krate: Option, + from_differing_crate: bool, ) -> ResolvePathResult { - ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, krate } + ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, from_differing_crate } } } @@ -134,7 +134,19 @@ impl DefMap { // resolving them to. Pass `None` otherwise, e.g. when we're resolving import paths. expected_macro_subns: Option, ) -> ResolvePathResult { - let mut result = ResolvePathResult::empty(ReachedFixedPoint::No); + let mut result = self.resolve_path_fp_with_macro_single( + db, + mode, + original_module, + path, + shadow, + expected_macro_subns, + ); + + if self.block.is_none() { + // If we're in the root `DefMap`, we can resolve the path directly. + return result; + } let mut arc; let mut current_map = self; @@ -153,8 +165,7 @@ impl DefMap { if result.reached_fixedpoint == ReachedFixedPoint::No { result.reached_fixedpoint = new.reached_fixedpoint; } - // FIXME: this doesn't seem right; what if the different namespace resolutions come from different crates? - result.krate = result.krate.or(new.krate); + result.from_differing_crate |= new.from_differing_crate; result.segment_index = match (result.segment_index, new.segment_index) { (Some(idx), None) => Some(idx), (Some(old), Some(new)) => Some(old.max(new)), @@ -333,11 +344,11 @@ impl DefMap { // expectation is discarded. let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow, None); - return ResolvePathResult::with( + return ResolvePathResult::new( def, ReachedFixedPoint::Yes, s.map(|s| s + i), - Some(module.krate), + true, ); } @@ -385,11 +396,11 @@ impl DefMap { match res { Some(res) => res, None => { - return ResolvePathResult::with( + return ResolvePathResult::new( PerNs::types(e.into(), vis, imp), ReachedFixedPoint::Yes, Some(i), - Some(self.krate), + false, ) } } @@ -403,11 +414,11 @@ impl DefMap { curr, ); - return ResolvePathResult::with( + return ResolvePathResult::new( PerNs::types(s, vis, imp), ReachedFixedPoint::Yes, Some(i), - Some(self.krate), + false, ); } }; @@ -416,7 +427,7 @@ impl DefMap { .filter_visibility(|vis| vis.is_visible_from_def_map(db, self, original_module)); } - ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate)) + ResolvePathResult::new(curr_per_ns, ReachedFixedPoint::Yes, None, false) } fn resolve_name_in_module( diff --git a/crates/hir-expand/Cargo.toml b/crates/hir-expand/Cargo.toml index 506a188a211dc..4f3080801565d 100644 --- a/crates/hir-expand/Cargo.toml +++ b/crates/hir-expand/Cargo.toml @@ -28,7 +28,6 @@ intern.workspace = true base-db.workspace = true cfg.workspace = true syntax.workspace = true -profile.workspace = true tt.workspace = true mbe.workspace = true limit.workspace = true @@ -38,4 +37,4 @@ span.workspace = true expect-test = "1.4.0" [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/hir-expand/src/builtin_attr_macro.rs b/crates/hir-expand/src/builtin_attr_macro.rs index 903b0d4807008..a0102f36aff51 100644 --- a/crates/hir-expand/src/builtin_attr_macro.rs +++ b/crates/hir-expand/src/builtin_attr_macro.rs @@ -4,23 +4,17 @@ use span::{MacroCallId, Span}; use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallKind}; macro_rules! register_builtin { - ($expand_fn:ident: $(($name:ident, $variant:ident) => $expand:ident),* ) => { + ($(($name:ident, $variant:ident) => $expand:ident),* ) => { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum BuiltinAttrExpander { $($variant),* } impl BuiltinAttrExpander { - pub fn $expand_fn( - &self, - db: &dyn ExpandDatabase, - id: MacroCallId, - tt: &tt::Subtree, - ) -> ExpandResult { - let expander = match *self { + pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree) -> ExpandResult { + match *self { $( BuiltinAttrExpander::$variant => $expand, )* - }; - expander(db, id, tt) + } } fn find_by_name(name: &name::Name) -> Option { @@ -35,6 +29,15 @@ macro_rules! register_builtin { } impl BuiltinAttrExpander { + pub fn expand( + &self, + db: &dyn ExpandDatabase, + id: MacroCallId, + tt: &tt::Subtree, + ) -> ExpandResult { + self.expander()(db, id, tt) + } + pub fn is_derive(self) -> bool { matches!(self, BuiltinAttrExpander::Derive | BuiltinAttrExpander::DeriveConst) } @@ -46,7 +49,7 @@ impl BuiltinAttrExpander { } } -register_builtin! { expand: +register_builtin! { (bench, Bench) => dummy_attr_expand, (cfg, Cfg) => dummy_attr_expand, (cfg_attr, CfgAttr) => dummy_attr_expand, diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs index 2795487514349..f36f48baaee1a 100644 --- a/crates/hir-expand/src/builtin_derive_macro.rs +++ b/crates/hir-expand/src/builtin_derive_macro.rs @@ -25,20 +25,10 @@ macro_rules! register_builtin { } impl BuiltinDeriveExpander { - pub fn expand( - &self, - db: &dyn ExpandDatabase, - id: MacroCallId, - tt: &ast::Adt, - token_map: SpanMapRef<'_>, - ) -> ExpandResult { - let expander = match *self { + pub fn expander(&self) -> fn(Span, &ast::Adt, SpanMapRef<'_>) -> ExpandResult { + match *self { $( BuiltinDeriveExpander::$trait => $expand, )* - }; - - let span = db.lookup_intern_macro_call(id).call_site; - let span = span_with_def_site_ctxt(db, span, id); - expander(span, tt, token_map) + } } fn find_by_name(name: &name::Name) -> Option { @@ -52,6 +42,20 @@ macro_rules! register_builtin { }; } +impl BuiltinDeriveExpander { + pub fn expand( + &self, + db: &dyn ExpandDatabase, + id: MacroCallId, + tt: &ast::Adt, + token_map: SpanMapRef<'_>, + ) -> ExpandResult { + let span = db.lookup_intern_macro_call(id).call_site; + let span = span_with_def_site_ctxt(db, span, id); + self.expander()(span, tt, token_map) + } +} + register_builtin! { Copy => copy_expand, Clone => clone_expand, diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs index 90cd3af75783d..0fd0c25dcce25 100644 --- a/crates/hir-expand/src/builtin_fn_macro.rs +++ b/crates/hir-expand/src/builtin_fn_macro.rs @@ -31,36 +31,18 @@ macro_rules! register_builtin { } impl BuiltinFnLikeExpander { - pub fn expand( - &self, - db: &dyn ExpandDatabase, - id: MacroCallId, - tt: &tt::Subtree, - ) -> ExpandResult { - let expander = match *self { + pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult { + match *self { $( BuiltinFnLikeExpander::$kind => $expand, )* - }; - - let span = db.lookup_intern_macro_call(id).call_site; - let span = span_with_def_site_ctxt(db, span, id); - expander(db, id, tt, span) + } } } impl EagerExpander { - pub fn expand( - &self, - db: &dyn ExpandDatabase, - id: MacroCallId, - tt: &tt::Subtree, - ) -> ExpandResult { - let expander = match *self { + pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult { + match *self { $( EagerExpander::$e_kind => $e_expand, )* - }; - - let span = db.lookup_intern_macro_call(id).call_site; - let span = span_with_def_site_ctxt(db, span, id); - expander(db, id, tt, span) + } } } @@ -74,7 +56,31 @@ macro_rules! register_builtin { }; } +impl BuiltinFnLikeExpander { + pub fn expand( + &self, + db: &dyn ExpandDatabase, + id: MacroCallId, + tt: &tt::Subtree, + ) -> ExpandResult { + let span = db.lookup_intern_macro_call(id).call_site; + let span = span_with_def_site_ctxt(db, span, id); + self.expander()(db, id, tt, span) + } +} + impl EagerExpander { + pub fn expand( + &self, + db: &dyn ExpandDatabase, + id: MacroCallId, + tt: &tt::Subtree, + ) -> ExpandResult { + let span = db.lookup_intern_macro_call(id).call_site; + let span = span_with_def_site_ctxt(db, span, id); + self.expander()(db, id, tt, span) + } + pub fn is_include(&self) -> bool { matches!(self, EagerExpander::Include) } diff --git a/crates/hir-expand/src/change.rs b/crates/hir-expand/src/change.rs index c6611438e64d8..8b9e5a59df8f0 100644 --- a/crates/hir-expand/src/change.rs +++ b/crates/hir-expand/src/change.rs @@ -11,14 +11,14 @@ use triomphe::Arc; use crate::{db::ExpandDatabase, proc_macro::ProcMacros}; #[derive(Debug, Default)] -pub struct Change { +pub struct ChangeWithProcMacros { pub source_change: FileChange, pub proc_macros: Option, pub toolchains: Option>>, pub target_data_layouts: Option>, } -impl Change { +impl ChangeWithProcMacros { pub fn new() -> Self { Self::default() } diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 0cf1fadec9721..ae10ad2f8019a 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -144,6 +144,12 @@ impl ModPath { } } +impl Extend for ModPath { + fn extend>(&mut self, iter: T) { + self.segments.extend(iter); + } +} + struct Display<'a> { db: &'a dyn ExpandDatabase, path: &'a ModPath, diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml index 1f8f8744f9ebe..41e2f7ad73c33 100644 --- a/crates/hir-ty/Cargo.toml +++ b/crates/hir-ty/Cargo.toml @@ -45,7 +45,6 @@ intern.workspace = true hir-def.workspace = true hir-expand.workspace = true base-db.workspace = true -profile.workspace = true syntax.workspace = true limit.workspace = true diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml index 7fea8372876ee..190722075a202 100644 --- a/crates/hir/Cargo.toml +++ b/crates/hir/Cargo.toml @@ -27,7 +27,6 @@ cfg.workspace = true hir-def.workspace = true hir-expand.workspace = true hir-ty.workspace = true -profile.workspace = true stdx.workspace = true syntax.workspace = true tt.workspace = true diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 5c607030167f4..1e16f78ca2d37 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -126,7 +126,7 @@ pub use { }, hir_expand::{ attrs::{Attr, AttrId}, - change::Change, + change::ChangeWithProcMacros, hygiene::{marks_rev, SyntaxContextExt}, name::{known, Name}, proc_macro::ProcMacros, diff --git a/crates/ide-assists/Cargo.toml b/crates/ide-assists/Cargo.toml index 98961a18de257..e1375f9c3ee87 100644 --- a/crates/ide-assists/Cargo.toml +++ b/crates/ide-assists/Cargo.toml @@ -23,7 +23,6 @@ tracing.workspace = true stdx.workspace = true syntax.workspace = true text-edit.workspace = true -profile.workspace = true ide-db.workspace = true hir.workspace = true diff --git a/crates/ide-completion/Cargo.toml b/crates/ide-completion/Cargo.toml index f2a11276ba2b8..6a4c70d460f2c 100644 --- a/crates/ide-completion/Cargo.toml +++ b/crates/ide-completion/Cargo.toml @@ -23,7 +23,6 @@ smallvec.workspace = true # local deps base-db.workspace = true ide-db.workspace = true -profile.workspace = true stdx.workspace = true syntax.workspace = true text-edit.workspace = true diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs index 2b2df144d6dd1..f769f72d462d8 100644 --- a/crates/ide-db/src/apply_change.rs +++ b/crates/ide-db/src/apply_change.rs @@ -11,7 +11,7 @@ use profile::{memory_usage, Bytes}; use rustc_hash::FxHashSet; use triomphe::Arc; -use crate::{symbol_index::SymbolsDatabase, Change, RootDatabase}; +use crate::{symbol_index::SymbolsDatabase, ChangeWithProcMacros, RootDatabase}; impl RootDatabase { pub fn request_cancellation(&mut self) { @@ -20,7 +20,7 @@ impl RootDatabase { self.synthetic_write(Durability::LOW); } - pub fn apply_change(&mut self, change: Change) { + pub fn apply_change(&mut self, change: ChangeWithProcMacros) { let _p = tracing::span!(tracing::Level::INFO, "RootDatabase::apply_change").entered(); self.request_cancellation(); tracing::trace!("apply_change {:?}", change); diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index 3e6cb7476bbb4..a9f7e58de951a 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -44,7 +44,7 @@ pub mod syntax_helpers { pub use parser::LexedStr; } -pub use hir::Change; +pub use hir::ChangeWithProcMacros; use std::{fmt, mem::ManuallyDrop}; diff --git a/crates/ide-diagnostics/Cargo.toml b/crates/ide-diagnostics/Cargo.toml index 69768041389ac..509c5a152f724 100644 --- a/crates/ide-diagnostics/Cargo.toml +++ b/crates/ide-diagnostics/Cargo.toml @@ -20,7 +20,6 @@ tracing.workspace = true once_cell = "1.17.0" # local deps -profile.workspace = true stdx.workspace = true syntax.workspace = true text-edit.workspace = true diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index a076c7ca9fa43..4eb4acdf183c4 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -61,7 +61,7 @@ use std::ffi::OsStr; use cfg::CfgOptions; use fetch_crates::CrateInfo; -use hir::Change; +use hir::ChangeWithProcMacros; use ide_db::{ base_db::{ salsa::{self, ParallelDatabase}, @@ -184,7 +184,7 @@ impl AnalysisHost { /// Applies changes to the current state of the world. If there are /// outstanding snapshots, they will be canceled. - pub fn apply_change(&mut self, change: Change) { + pub fn apply_change(&mut self, change: ChangeWithProcMacros) { self.db.apply_change(change); } @@ -239,7 +239,7 @@ impl Analysis { file_set.insert(file_id, VfsPath::new_virtual_path("/main.rs".to_owned())); let source_root = SourceRoot::new_local(file_set); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.set_roots(vec![source_root]); let mut crate_graph = CrateGraph::default(); // FIXME: cfg options diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs index 2b5f515c3ad5b..29c1251cceee7 100644 --- a/crates/load-cargo/src/lib.rs +++ b/crates/load-cargo/src/lib.rs @@ -11,7 +11,7 @@ use hir_expand::proc_macro::{ }; use ide_db::{ base_db::{CrateGraph, Env, SourceRoot}, - prime_caches, Change, FxHashMap, RootDatabase, + prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase, }; use itertools::Itertools; use proc_macro_api::{MacroDylib, ProcMacroServer}; @@ -314,7 +314,7 @@ fn load_crate_graph( let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::().ok()); let mut db = RootDatabase::new(lru_cap); - let mut analysis_change = Change::new(); + let mut analysis_change = ChangeWithProcMacros::new(); db.enable_proc_attr_macros(); diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml index e74b340126c0a..1f84e3f3af3f0 100644 --- a/crates/parser/Cargo.toml +++ b/crates/parser/Cargo.toml @@ -15,6 +15,7 @@ doctest = false drop_bomb = "0.1.5" ra-ap-rustc_lexer.workspace = true limit.workspace = true +tracing = { workspace = true, optional = true } [dev-dependencies] expect-test = "1.4.0" @@ -23,6 +24,7 @@ stdx.workspace = true sourcegen.workspace = true [features] +default = ["tracing"] in-rust-tree = [] [lints] diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index 2da9184693d97..48e4c8a6225c4 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -31,6 +31,7 @@ struct LexError { impl<'a> LexedStr<'a> { pub fn new(text: &'a str) -> LexedStr<'a> { + let _p = tracing::span!(tracing::Level::INFO, "LexedStr::new").entered(); let mut conv = Converter::new(text); if let Some(shebang_len) = rustc_lexer::strip_shebang(text) { conv.res.push(SHEBANG, conv.offset); diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 3ca285e787e81..86c771c00085c 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -87,6 +87,7 @@ pub enum TopEntryPoint { impl TopEntryPoint { pub fn parse(&self, input: &Input) -> Output { + let _p = tracing::span!(tracing::Level::INFO, "TopEntryPoint::parse", ?self).entered(); let entry_point: fn(&'_ mut parser::Parser<'_>) = match self { TopEntryPoint::SourceFile => grammar::entry::top::source_file, TopEntryPoint::MacroStmts => grammar::entry::top::macro_stmts, diff --git a/crates/parser/src/shortcuts.rs b/crates/parser/src/shortcuts.rs index 57005a6834c90..680a70997d4b0 100644 --- a/crates/parser/src/shortcuts.rs +++ b/crates/parser/src/shortcuts.rs @@ -26,6 +26,7 @@ pub enum StrStep<'a> { impl LexedStr<'_> { pub fn to_input(&self) -> crate::Input { + let _p = tracing::span!(tracing::Level::INFO, "LexedStr::to_input").entered(); let mut res = crate::Input::default(); let mut was_joint = false; for i in 0..self.len() { diff --git a/crates/proc-macro-api/Cargo.toml b/crates/proc-macro-api/Cargo.toml index cf01b94c0a2cb..e98d70776c95d 100644 --- a/crates/proc-macro-api/Cargo.toml +++ b/crates/proc-macro-api/Cargo.toml @@ -32,7 +32,6 @@ indexmap = "2.1.0" paths.workspace = true tt.workspace = true stdx.workspace = true -profile.workspace = true text-size.workspace = true span.workspace = true # Ideally this crate would not depend on salsa things, but we need span information here which wraps diff --git a/crates/profile/src/lib.rs b/crates/profile/src/lib.rs index 3639981560635..a3fdb72a6d1d2 100644 --- a/crates/profile/src/lib.rs +++ b/crates/profile/src/lib.rs @@ -23,29 +23,6 @@ pub use countme::Count; thread_local!(static IN_SCOPE: RefCell = const { RefCell::new(false) }); -/// Allows to check if the current code is within some dynamic scope, can be -/// useful during debugging to figure out why a function is called. -pub struct Scope { - prev: bool, -} - -impl Scope { - #[must_use] - pub fn enter() -> Scope { - let prev = IN_SCOPE.with(|slot| std::mem::replace(&mut *slot.borrow_mut(), true)); - Scope { prev } - } - pub fn is_active() -> bool { - IN_SCOPE.with(|slot| *slot.borrow()) - } -} - -impl Drop for Scope { - fn drop(&mut self) { - IN_SCOPE.with(|slot| *slot.borrow_mut() = self.prev); - } -} - /// A wrapper around google_cpu_profiler. /// /// Usage: diff --git a/crates/project-model/Cargo.toml b/crates/project-model/Cargo.toml index 3552ed191628e..924a4a89e216a 100644 --- a/crates/project-model/Cargo.toml +++ b/crates/project-model/Cargo.toml @@ -27,7 +27,6 @@ itertools.workspace = true base-db.workspace = true cfg.workspace = true paths.workspace = true -profile.workspace = true stdx.workspace = true toolchain.workspace = true @@ -35,4 +34,4 @@ toolchain.workspace = true expect-test = "1.4.0" [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/rust-analyzer/src/cli/rustc_tests.rs b/crates/rust-analyzer/src/cli/rustc_tests.rs index 9276d241affd9..7ad87ab97fc65 100644 --- a/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -5,7 +5,7 @@ use std::thread::Builder; use std::time::{Duration, Instant}; use std::{cell::RefCell, fs::read_to_string, panic::AssertUnwindSafe, path::PathBuf}; -use hir::{Change, Crate}; +use hir::{ChangeWithProcMacros, Crate}; use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig}; use itertools::Either; use profile::StopWatch; @@ -122,7 +122,7 @@ impl Tester { FxHashMap::default() }; let text = read_to_string(&p).unwrap(); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); // Ignore unstable tests, since they move too fast and we do not intend to support all of them. let mut ignore_test = text.contains("#![feature"); // Ignore test with extern crates, as this infra don't support them yet. diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index b2d507491b177..eb4727920533d 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -7,7 +7,7 @@ use std::{collections::hash_map::Entry, time::Instant}; use crossbeam_channel::{unbounded, Receiver, Sender}; use flycheck::FlycheckHandle; -use hir::Change; +use hir::ChangeWithProcMacros; use ide::{Analysis, AnalysisHost, Cancellable, FileId}; use ide_db::base_db::{CrateId, ProcMacroPaths}; use load_cargo::SourceRootConfig; @@ -238,7 +238,7 @@ impl GlobalState { let mut file_changes = FxHashMap::<_, (bool, ChangedFile)>::default(); let (change, modified_rust_files, workspace_structure_change) = { - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); let mut guard = self.vfs.write(); let changed_files = guard.0.take_changes(); if changed_files.is_empty() { diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs index 9d692175203d9..008c63c35a6de 100644 --- a/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -10,7 +10,7 @@ //! in release mode in VS Code. There's however "rust-analyzer: Copy Run Command Line" //! which you can use to paste the command in terminal and add `--release` manually. -use hir::Change; +use hir::ChangeWithProcMacros; use ide::{AnalysisHost, CallableSnippets, CompletionConfig, FilePosition, TextSize}; use ide_db::{ imports::insert_use::{ImportGranularity, InsertUseConfig}, @@ -55,19 +55,19 @@ fn integrated_highlighting_benchmark() { vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}")) }; + crate::tracing::hprof::init("*>100"); + { let _it = stdx::timeit("initial"); let analysis = host.analysis(); analysis.highlight_as_html(file_id, false).unwrap(); } - crate::tracing::hprof::init("*>100"); - { let _it = stdx::timeit("change"); let mut text = host.analysis().file_text(file_id).unwrap().to_string(); text.push_str("\npub fn _dummy() {}\n"); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.change_file(file_id, Some(Arc::from(text))); host.apply_change(change); } @@ -120,7 +120,7 @@ fn integrated_completion_benchmark() { let completion_offset = patch(&mut text, "db.struct_data(self.id)", "sel;\ndb.struct_data(self.id)") + "sel".len(); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.change_file(file_id, Some(Arc::from(text))); host.apply_change(change); completion_offset @@ -163,7 +163,7 @@ fn integrated_completion_benchmark() { let completion_offset = patch(&mut text, "sel;\ndb.struct_data(self.id)", ";sel;\ndb.struct_data(self.id)") + ";sel".len(); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.change_file(file_id, Some(Arc::from(text))); host.apply_change(change); completion_offset @@ -205,7 +205,7 @@ fn integrated_completion_benchmark() { let completion_offset = patch(&mut text, "sel;\ndb.struct_data(self.id)", "self.;\ndb.struct_data(self.id)") + "self.".len(); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.change_file(file_id, Some(Arc::from(text))); host.apply_change(change); completion_offset diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index f6bc032c01986..95d51baab3877 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -16,7 +16,7 @@ use std::{iter, mem}; use flycheck::{FlycheckConfig, FlycheckHandle}; -use hir::{db::DefDatabase, Change, ProcMacros}; +use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros}; use ide::CrateId; use ide_db::{ base_db::{salsa::Durability, CrateGraph, ProcMacroPaths, Version}, @@ -357,7 +357,7 @@ impl GlobalState { } pub(crate) fn set_proc_macros(&mut self, proc_macros: ProcMacros) { - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.set_proc_macros(proc_macros); self.analysis_host.apply_change(change); } @@ -548,7 +548,7 @@ impl GlobalState { ws_to_crate_graph(&self.workspaces, self.config.extra_env(), load) }; - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); if self.config.expand_proc_macros() { change.set_proc_macros( crate_graph diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index a0fd73ee13f57..9a8d73cf7ff47 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml @@ -27,7 +27,6 @@ tracing.workspace = true ra-ap-rustc_lexer.workspace = true parser.workspace = true -profile.workspace = true stdx.workspace = true text-edit.workspace = true diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index b755de86d32c5..e8bb9ee938f9e 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -168,6 +168,7 @@ pub use crate::ast::SourceFile; impl SourceFile { pub fn parse(text: &str) -> Parse { + let _p = tracing::span!(tracing::Level::INFO, "SourceFile::parse").entered(); let (green, mut errors) = parsing::parse_text(text); let root = SyntaxNode::new_root(green.clone()); diff --git a/crates/syntax/src/parsing.rs b/crates/syntax/src/parsing.rs index 1250b5274c189..d750476f63cb5 100644 --- a/crates/syntax/src/parsing.rs +++ b/crates/syntax/src/parsing.rs @@ -10,6 +10,7 @@ use crate::{syntax_node::GreenNode, SyntaxError, SyntaxTreeBuilder}; pub(crate) use crate::parsing::reparsing::incremental_reparse; pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec) { + let _p = tracing::span!(tracing::Level::INFO, "parse_text").entered(); let lexed = parser::LexedStr::new(text); let parser_input = lexed.to_input(); let parser_output = parser::TopEntryPoint::SourceFile.parse(&parser_input); @@ -21,6 +22,7 @@ pub(crate) fn build_tree( lexed: parser::LexedStr<'_>, parser_output: parser::Output, ) -> (GreenNode, Vec, bool) { + let _p = tracing::span!(tracing::Level::INFO, "build_tree").entered(); let mut builder = SyntaxTreeBuilder::default(); let is_eof = lexed.intersperse_trivia(&parser_output, &mut |step| match step { diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 5c5b26f525f66..5b3f449eeeb32 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -16,6 +16,7 @@ use crate::{ }; pub(crate) fn validate(root: &SyntaxNode) -> Vec { + let _p = tracing::span!(tracing::Level::INFO, "parser::validate").entered(); // FIXME: // * Add unescape validation of raw string literals and raw byte string literals // * Add validation of doc comments are being attached to nodes diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index e118262b4edd9..ca3007d437044 100644 --- a/crates/test-fixture/src/lib.rs +++ b/crates/test-fixture/src/lib.rs @@ -7,7 +7,7 @@ use base_db::{ }; use cfg::CfgOptions; use hir_expand::{ - change::Change, + change::ChangeWithProcMacros, db::ExpandDatabase, proc_macro::{ ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacros, @@ -103,7 +103,7 @@ impl WithFixture for pub struct ChangeFixture { pub file_position: Option<(FileId, RangeOrOffset)>, pub files: Vec, - pub change: Change, + pub change: ChangeWithProcMacros, } const SOURCE_ROOT_PREFIX: &str = "/"; @@ -317,7 +317,7 @@ impl ChangeFixture { }; roots.push(root); - let mut change = Change { + let mut change = ChangeWithProcMacros { source_change, proc_macros: proc_macros.is_empty().not().then_some(proc_macros), toolchains: Some(iter::repeat(toolchain).take(crate_graph.len()).collect()), From c3c9f5ffe11af3a3be91734b3254eeaad283be8b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 11:39:38 +0100 Subject: [PATCH 22/69] internal: Compute syntax validation errors on demand --- crates/hir-def/src/data.rs | 5 ++-- crates/hir-def/src/nameres/collector.rs | 6 ++-- crates/hir-def/src/nameres/diagnostics.rs | 7 ++--- crates/hir-expand/src/db.rs | 4 +-- crates/hir-expand/src/files.rs | 2 +- crates/ide-diagnostics/src/lib.rs | 2 +- .../src/integrated_benchmarks.rs | 4 ++- crates/rust-analyzer/src/tracing/hprof.rs | 4 +-- crates/syntax/src/lib.rs | 21 ++++++------- crates/syntax/src/tests.rs | 4 +-- crates/syntax/src/validation.rs | 30 +++++++++---------- 11 files changed, 45 insertions(+), 44 deletions(-) diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index f506864902c47..d4c1db8b95b48 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -788,11 +788,12 @@ impl<'a> AssocItemCollector<'a> { }; self.diagnostics.push(diag); } - if let errors @ [_, ..] = parse.errors() { + let errors = parse.errors(); + if !errors.is_empty() { self.diagnostics.push(DefDiagnostic::macro_expansion_parse_error( self.module_id.local_id, error_call_kind(), - errors, + errors.into_boxed_slice(), )); } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 18aefbf332c8d..f9fe6d3b903b3 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -1384,7 +1384,9 @@ impl DefCollector<'_> { // First, fetch the raw expansion result for purposes of error reporting. This goes through // `parse_macro_expansion_error` to avoid depending on the full expansion result (to improve // incrementality). - let ExpandResult { value, err } = self.db.parse_macro_expansion_error(macro_call_id); + // FIXME: This kind of error fetching feels a bit odd? + let ExpandResult { value: errors, err } = + self.db.parse_macro_expansion_error(macro_call_id); if let Some(err) = err { let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id); let diag = match err { @@ -1398,7 +1400,7 @@ impl DefCollector<'_> { self.def_map.diagnostics.push(diag); } - if let errors @ [_, ..] = &*value { + if !errors.is_empty() { let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id); let diag = DefDiagnostic::macro_expansion_parse_error(module_id, loc.kind, errors); self.def_map.diagnostics.push(diag); diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs index b5a302dbcaf64..8c7fdaaf58b32 100644 --- a/crates/hir-def/src/nameres/diagnostics.rs +++ b/crates/hir-def/src/nameres/diagnostics.rs @@ -117,14 +117,11 @@ impl DefDiagnostic { pub(crate) fn macro_expansion_parse_error( container: LocalModuleId, ast: MacroCallKind, - errors: &[SyntaxError], + errors: Box<[SyntaxError]>, ) -> Self { Self { in_module: container, - kind: DefDiagnosticKind::MacroExpansionParseError { - ast, - errors: errors.to_vec().into_boxed_slice(), - }, + kind: DefDiagnosticKind::MacroExpansionParseError { ast, errors }, } } diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index f1f0d8990f1cd..3a65bc7c6ea2d 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -303,7 +303,7 @@ fn parse_macro_expansion_error( macro_call_id: MacroCallId, ) -> ExpandResult> { db.parse_macro_expansion(MacroFileId { macro_call_id }) - .map(|it| it.0.errors().to_vec().into_boxed_slice()) + .map(|it| it.0.errors().into_boxed_slice()) } pub(crate) fn parse_with_map( @@ -445,7 +445,7 @@ fn macro_arg( if matches!(loc.def.kind, MacroDefKind::BuiltInEager(..)) { match parse.errors() { - [] => ValueResult::ok((Arc::new(tt), undo_info)), + errors if errors.is_empty() => ValueResult::ok((Arc::new(tt), undo_info)), errors => ValueResult::new( (Arc::new(tt), undo_info), // Box::<[_]>::from(res.errors()), not stable yet diff --git a/crates/hir-expand/src/files.rs b/crates/hir-expand/src/files.rs index 66ceb1b7d4206..a500c24ce8811 100644 --- a/crates/hir-expand/src/files.rs +++ b/crates/hir-expand/src/files.rs @@ -252,7 +252,7 @@ impl InFile<&SyntaxNode> { map_node_range_up(db, &db.expansion_span_map(file_id), self.value.text_range())?; // FIXME: Figure out an API that makes proper use of ctx, this only exists to - // keep pre-token map rewrite behaviour. + // keep pre-token map rewrite behavior. if !ctx.is_root() { return None; } diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 9f4368b04e79b..486bf6f95c45f 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -299,7 +299,7 @@ pub fn diagnostics( let mut res = Vec::new(); // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily. - res.extend(parse.errors().iter().take(128).map(|err| { + res.extend(parse.errors().into_iter().take(128).map(|err| { Diagnostic::new( DiagnosticCode::RustcHardError("syntax-error"), format!("Syntax Error: {err}"), diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs index 008c63c35a6de..28eae6079c54f 100644 --- a/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -55,7 +55,7 @@ fn integrated_highlighting_benchmark() { vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}")) }; - crate::tracing::hprof::init("*>100"); + let _g = crate::tracing::hprof::init("*>150"); { let _it = stdx::timeit("initial"); @@ -72,6 +72,8 @@ fn integrated_highlighting_benchmark() { host.apply_change(change); } + let _g = crate::tracing::hprof::init("*>50"); + { let _it = stdx::timeit("after change"); let _span = profile::cpu_span(); diff --git a/crates/rust-analyzer/src/tracing/hprof.rs b/crates/rust-analyzer/src/tracing/hprof.rs index 9064987329778..5fcda6ba136a7 100644 --- a/crates/rust-analyzer/src/tracing/hprof.rs +++ b/crates/rust-analyzer/src/tracing/hprof.rs @@ -52,7 +52,7 @@ use tracing_subscriber::{ use crate::tracing::hprof; -pub fn init(spec: &str) { +pub fn init(spec: &str) -> tracing::subscriber::DefaultGuard { let (write_filter, allowed_names) = WriteFilter::from_spec(spec); // this filter the first pass for `tracing`: these are all the "profiling" spans, but things like @@ -76,7 +76,7 @@ pub fn init(spec: &str) { .with_filter(profile_filter); let subscriber = Registry::default().with(layer); - tracing::subscriber::set_global_default(subscriber).unwrap(); + tracing::subscriber::set_default(subscriber) } #[derive(Default, Debug)] diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index e8bb9ee938f9e..1bb82cc191ffc 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -97,8 +97,11 @@ impl Parse { pub fn syntax_node(&self) -> SyntaxNode { SyntaxNode::new_root(self.green.clone()) } - pub fn errors(&self) -> &[SyntaxError] { - self.errors.as_deref().unwrap_or_default() + + pub fn errors(&self) -> Vec { + let mut errors = if let Some(e) = self.errors.as_deref() { e.to_vec() } else { vec![] }; + validation::validate(&self.syntax_node(), &mut errors); + errors } } @@ -111,10 +114,10 @@ impl Parse { T::cast(self.syntax_node()).unwrap() } - pub fn ok(self) -> Result> { - match self.errors { - Some(e) => Err(e), - None => Ok(self.tree()), + pub fn ok(self) -> Result> { + match self.errors() { + errors if !errors.is_empty() => Err(errors), + _ => Ok(self.tree()), } } } @@ -132,7 +135,7 @@ impl Parse { impl Parse { pub fn debug_dump(&self) -> String { let mut buf = format!("{:#?}", self.tree().syntax()); - for err in self.errors.as_deref().into_iter().flat_map(<[_]>::iter) { + for err in self.errors() { format_to!(buf, "error {:?}: {}\n", err.range(), err); } buf @@ -169,11 +172,9 @@ pub use crate::ast::SourceFile; impl SourceFile { pub fn parse(text: &str) -> Parse { let _p = tracing::span!(tracing::Level::INFO, "SourceFile::parse").entered(); - let (green, mut errors) = parsing::parse_text(text); + let (green, errors) = parsing::parse_text(text); let root = SyntaxNode::new_root(green.clone()); - errors.extend(validation::validate(&root)); - assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE); Parse { green, diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs index 4c0a538f712f5..5400071c4b678 100644 --- a/crates/syntax/src/tests.rs +++ b/crates/syntax/src/tests.rs @@ -39,7 +39,7 @@ fn benchmark_parser() { let tree = { let _b = bench("parsing"); let p = SourceFile::parse(&data); - assert!(p.errors.is_none()); + assert!(p.errors().is_empty()); assert_eq!(p.tree().syntax.text_range().len(), 352474.into()); p.tree() }; @@ -57,7 +57,7 @@ fn validation_tests() { dir_tests(&test_data_dir(), &["parser/validation"], "rast", |text, path| { let parse = SourceFile::parse(text); let errors = parse.errors(); - assert_errors_are_present(errors, path); + assert_errors_are_present(&errors, path); parse.debug_dump() }); } diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 5b3f449eeeb32..dbfab537fe58b 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -15,34 +15,32 @@ use crate::{ SyntaxNode, SyntaxToken, TextSize, T, }; -pub(crate) fn validate(root: &SyntaxNode) -> Vec { +pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec) { let _p = tracing::span!(tracing::Level::INFO, "parser::validate").entered(); // FIXME: // * Add unescape validation of raw string literals and raw byte string literals // * Add validation of doc comments are being attached to nodes - let mut errors = Vec::new(); for node in root.descendants() { match_ast! { match node { - ast::Literal(it) => validate_literal(it, &mut errors), - ast::Const(it) => validate_const(it, &mut errors), - ast::BlockExpr(it) => block::validate_block_expr(it, &mut errors), - ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), &mut errors), - ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), &mut errors), - ast::Visibility(it) => validate_visibility(it, &mut errors), - ast::RangeExpr(it) => validate_range_expr(it, &mut errors), - ast::PathSegment(it) => validate_path_keywords(it, &mut errors), - ast::RefType(it) => validate_trait_object_ref_ty(it, &mut errors), - ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors), - ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors), - ast::MacroRules(it) => validate_macro_rules(it, &mut errors), - ast::LetExpr(it) => validate_let_expr(it, &mut errors), + ast::Literal(it) => validate_literal(it, errors), + ast::Const(it) => validate_const(it, errors), + ast::BlockExpr(it) => block::validate_block_expr(it, errors), + ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), errors), + ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), errors), + ast::Visibility(it) => validate_visibility(it, errors), + ast::RangeExpr(it) => validate_range_expr(it, errors), + ast::PathSegment(it) => validate_path_keywords(it, errors), + ast::RefType(it) => validate_trait_object_ref_ty(it, errors), + ast::PtrType(it) => validate_trait_object_ptr_ty(it, errors), + ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, errors), + ast::MacroRules(it) => validate_macro_rules(it, errors), + ast::LetExpr(it) => validate_let_expr(it, errors), _ => (), } } } - errors } fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> (&'static str, bool) { From 6e802a0b5652934fe367224c26a2d8809e33d503 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 16:35:33 +0100 Subject: [PATCH 23/69] minor: Mark remove_unnecessary_else as experimental --- crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs b/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs index 47844876dc540..f68e698238562 100644 --- a/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs +++ b/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs @@ -30,6 +30,7 @@ pub(crate) fn remove_unnecessary_else( "remove unnecessary else block", display_range, ) + .experimental() .with_fixes(fixes(ctx, d)) } From 0964374274a64ad15c640d57982d74ce66c58b84 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 16:49:03 +0100 Subject: [PATCH 24/69] Move diagnostics docs generation into xtask/codegen --- Cargo.lock | 1 - crates/ide-assists/Cargo.toml | 3 -- crates/ide-diagnostics/Cargo.toml | 4 --- crates/ide/Cargo.toml | 3 -- crates/rust-analyzer/Cargo.toml | 1 - xtask/src/codegen.rs | 1 + .../src/codegen/diagnostics_docs.rs | 28 +++++++++++-------- 7 files changed, 17 insertions(+), 24 deletions(-) rename crates/ide-diagnostics/src/tests/sourcegen.rs => xtask/src/codegen/diagnostics_docs.rs (71%) diff --git a/Cargo.lock b/Cargo.lock index 9b431d85a6476..45f4aa89117f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -747,7 +747,6 @@ dependencies = [ "itertools", "once_cell", "serde_json", - "sourcegen", "stdx", "syntax", "test-fixture", diff --git a/crates/ide-assists/Cargo.toml b/crates/ide-assists/Cargo.toml index a78129fc47efb..b1e7609afef41 100644 --- a/crates/ide-assists/Cargo.toml +++ b/crates/ide-assists/Cargo.toml @@ -33,8 +33,5 @@ expect-test = "1.4.0" test-utils.workspace = true test-fixture.workspace = true -[features] -in-rust-tree = [] - [lints] workspace = true diff --git a/crates/ide-diagnostics/Cargo.toml b/crates/ide-diagnostics/Cargo.toml index 509c5a152f724..8ccea99e9e13d 100644 --- a/crates/ide-diagnostics/Cargo.toml +++ b/crates/ide-diagnostics/Cargo.toml @@ -33,10 +33,6 @@ expect-test = "1.4.0" # local deps test-utils.workspace = true test-fixture.workspace = true -sourcegen.workspace = true - -[features] -in-rust-tree = [] [lints] workspace = true diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml index bb06d614450fb..eab3925aab65c 100644 --- a/crates/ide/Cargo.toml +++ b/crates/ide/Cargo.toml @@ -51,8 +51,5 @@ expect-test = "1.4.0" test-utils.workspace = true test-fixture.workspace = true -[features] -in-rust-tree = ["ide-assists/in-rust-tree", "ide-diagnostics/in-rust-tree"] - [lints] workspace = true diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index a212041e66b46..766606be7bea6 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -85,7 +85,6 @@ force-always-assert = ["always-assert/force"] sysroot-abi = [] in-rust-tree = [ "sysroot-abi", - "ide/in-rust-tree", "syntax/in-rust-tree", "parser/in-rust-tree", "hir/in-rust-tree", diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index e579660ac9b13..d51daa3395733 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -8,6 +8,7 @@ use xshell::{cmd, Shell}; use crate::{flags, project_root}; pub(crate) mod assists_doc_tests; +pub(crate) mod diagnostics_docs; impl flags::Codegen { pub(crate) fn run(self, _sh: &Shell) -> anyhow::Result<()> { diff --git a/crates/ide-diagnostics/src/tests/sourcegen.rs b/xtask/src/codegen/diagnostics_docs.rs similarity index 71% rename from crates/ide-diagnostics/src/tests/sourcegen.rs rename to xtask/src/codegen/diagnostics_docs.rs index 9e7fcfc590b70..a45b412fda59a 100644 --- a/crates/ide-diagnostics/src/tests/sourcegen.rs +++ b/xtask/src/codegen/diagnostics_docs.rs @@ -2,22 +2,26 @@ use std::{fmt, fs, io, path::PathBuf}; -use sourcegen::project_root; +use crate::{ + codegen::{add_preamble, list_rust_files, CommentBlock, Location}, + project_root, +}; -#[test] -fn sourcegen_diagnostic_docs() { +fn generate(check: bool) { let diagnostics = Diagnostic::collect().unwrap(); - let contents = - diagnostics.into_iter().map(|it| it.to_string()).collect::>().join("\n\n"); - let contents = sourcegen::add_preamble("sourcegen_diagnostic_docs", contents); - let dst = project_root().join("docs/user/generated_diagnostic.adoc"); - fs::write(dst, contents).unwrap(); + if !check { + let contents = + diagnostics.into_iter().map(|it| it.to_string()).collect::>().join("\n\n"); + let contents = add_preamble("sourcegen_diagnostic_docs", contents); + let dst = project_root().join("docs/user/generated_diagnostic.adoc"); + fs::write(dst, contents).unwrap(); + } } #[derive(Debug)] struct Diagnostic { id: String, - location: sourcegen::Location, + location: Location, doc: String, } @@ -26,7 +30,7 @@ impl Diagnostic { let handlers_dir = project_root().join("crates/ide-diagnostics/src/handlers"); let mut res = Vec::new(); - for path in sourcegen::list_rust_files(&handlers_dir) { + for path in list_rust_files(&handlers_dir) { collect_file(&mut res, path)?; } res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id)); @@ -34,7 +38,7 @@ impl Diagnostic { fn collect_file(acc: &mut Vec, path: PathBuf) -> io::Result<()> { let text = fs::read_to_string(&path)?; - let comment_blocks = sourcegen::CommentBlock::extract("Diagnostic", &text); + let comment_blocks = CommentBlock::extract("Diagnostic", &text); for block in comment_blocks { let id = block.id; @@ -42,7 +46,7 @@ impl Diagnostic { panic!("invalid diagnostic name: {id:?}:\n {msg}") } let doc = block.contents.join("\n"); - let location = sourcegen::Location { file: path.clone(), line: block.line }; + let location = Location { file: path.clone(), line: block.line }; acc.push(Diagnostic { id, location, doc }) } From 76463eee48a0b6dcaac5cd95aff91251a1abf475 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 17:02:28 +0100 Subject: [PATCH 25/69] Move lint definition generation into xtask/codegen --- Cargo.lock | 4 +- crates/ide-db/Cargo.toml | 3 -- crates/ide-db/src/lib.rs | 6 --- crates/ide-db/src/tests/line_index.rs | 49 ----------------- crates/ide-diagnostics/src/tests.rs | 2 - lib/line-index/Cargo.toml | 5 +- lib/line-index/src/tests.rs | 53 +++++++++++++++++++ xtask/src/codegen.rs | 6 +++ xtask/src/codegen/diagnostics_docs.rs | 2 +- .../src/codegen/lints.rs | 40 +++++++------- xtask/src/flags.rs | 4 ++ xtask/src/release.rs | 2 +- 12 files changed, 90 insertions(+), 86 deletions(-) delete mode 100644 crates/ide-db/src/tests/line_index.rs rename crates/ide-db/src/tests/sourcegen_lints.rs => xtask/src/codegen/lints.rs (93%) diff --git a/Cargo.lock b/Cargo.lock index 45f4aa89117f7..89a1f68cce0fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -717,12 +717,10 @@ dependencies = [ "memchr", "nohash-hasher", "once_cell", - "oorandom", "parser", "profile", "rayon", "rustc-hash", - "sourcegen", "span", "stdx", "syntax", @@ -731,7 +729,6 @@ dependencies = [ "text-edit", "tracing", "triomphe", - "xshell", ] [[package]] @@ -916,6 +913,7 @@ name = "line-index" version = "0.1.1" dependencies = [ "nohash-hasher", + "oorandom", "text-size", ] diff --git a/crates/ide-db/Cargo.toml b/crates/ide-db/Cargo.toml index b487b138fc0e7..071e1b471793d 100644 --- a/crates/ide-db/Cargo.toml +++ b/crates/ide-db/Cargo.toml @@ -44,13 +44,10 @@ line-index.workspace = true [dev-dependencies] expect-test = "1.4.0" -oorandom = "11.1.3" -xshell.workspace = true # local deps test-utils.workspace = true test-fixture.workspace = true -sourcegen.workspace = true [lints] workspace = true diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index a9f7e58de951a..0d11858ed7f4f 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -412,9 +412,3 @@ impl SnippetCap { } } } - -#[cfg(test)] -mod tests { - mod line_index; - mod sourcegen_lints; -} diff --git a/crates/ide-db/src/tests/line_index.rs b/crates/ide-db/src/tests/line_index.rs deleted file mode 100644 index 6b49bb2631c19..0000000000000 --- a/crates/ide-db/src/tests/line_index.rs +++ /dev/null @@ -1,49 +0,0 @@ -use line_index::{LineCol, LineIndex, WideEncoding}; -use test_utils::skip_slow_tests; - -#[test] -fn test_every_chars() { - if skip_slow_tests() { - return; - } - - let text: String = { - let mut chars: Vec = ((0 as char)..char::MAX).collect(); // Neat! - chars.extend("\n".repeat(chars.len() / 16).chars()); - let mut rng = oorandom::Rand32::new(stdx::rand::seed()); - stdx::rand::shuffle(&mut chars, |i| rng.rand_range(0..i as u32) as usize); - chars.into_iter().collect() - }; - assert!(text.contains('💩')); // Sanity check. - - let line_index = LineIndex::new(&text); - - let mut lin_col = LineCol { line: 0, col: 0 }; - let mut col_utf16 = 0; - let mut col_utf32 = 0; - for (offset, c) in text.char_indices() { - let got_offset = line_index.offset(lin_col).unwrap(); - assert_eq!(usize::from(got_offset), offset); - - let got_lin_col = line_index.line_col(got_offset); - assert_eq!(got_lin_col, lin_col); - - for (enc, col) in [(WideEncoding::Utf16, col_utf16), (WideEncoding::Utf32, col_utf32)] { - let wide_lin_col = line_index.to_wide(enc, lin_col).unwrap(); - let got_lin_col = line_index.to_utf8(enc, wide_lin_col).unwrap(); - assert_eq!(got_lin_col, lin_col); - assert_eq!(wide_lin_col.col, col) - } - - if c == '\n' { - lin_col.line += 1; - lin_col.col = 0; - col_utf16 = 0; - col_utf32 = 0; - } else { - lin_col.col += c.len_utf8() as u32; - col_utf16 += c.len_utf16() as u32; - col_utf32 += 1; - } - } -} diff --git a/crates/ide-diagnostics/src/tests.rs b/crates/ide-diagnostics/src/tests.rs index 901ceffbb266d..dcaa212089233 100644 --- a/crates/ide-diagnostics/src/tests.rs +++ b/crates/ide-diagnostics/src/tests.rs @@ -1,6 +1,4 @@ #![allow(clippy::print_stderr)] -#[cfg(not(feature = "in-rust-tree"))] -mod sourcegen; use ide_db::{ assists::AssistResolveStrategy, base_db::SourceDatabaseExt, LineIndexDatabase, RootDatabase, diff --git a/lib/line-index/Cargo.toml b/lib/line-index/Cargo.toml index 77e187de1ed80..8ae4954dd0de9 100644 --- a/lib/line-index/Cargo.toml +++ b/lib/line-index/Cargo.toml @@ -10,5 +10,8 @@ edition = "2021" text-size = "1.1.1" nohash-hasher = "0.2.0" +[dev-dependencies] +oorandom = "11.1.3" + [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/lib/line-index/src/tests.rs b/lib/line-index/src/tests.rs index 981008e346ba4..57fad1dfc0571 100644 --- a/lib/line-index/src/tests.rs +++ b/lib/line-index/src/tests.rs @@ -142,3 +142,56 @@ fn test_to_wide() { let wide_line_col = line_index.to_wide(WideEncoding::Utf16, line_col.unwrap()); assert_eq!(wide_line_col, Some(WideLineCol { line: 5, col: 4 })); } + +#[test] +fn test_every_chars() { + let text: String = { + let mut chars: Vec = ((0 as char)..char::MAX).collect(); // Neat! + chars.extend("\n".repeat(chars.len() / 16).chars()); + let seed = std::hash::Hasher::finish(&std::hash::BuildHasher::build_hasher( + #[allow(clippy::disallowed_types)] + &std::collections::hash_map::RandomState::new(), + )); + let mut rng = oorandom::Rand32::new(seed); + let mut rand_index = |i| rng.rand_range(0..i as u32) as usize; + let mut remaining = chars.len() - 1; + while remaining > 0 { + let index = rand_index(remaining); + chars.swap(remaining, index); + remaining -= 1; + } + chars.into_iter().collect() + }; + assert!(text.contains('💩')); // Sanity check. + + let line_index = LineIndex::new(&text); + + let mut lin_col = LineCol { line: 0, col: 0 }; + let mut col_utf16 = 0; + let mut col_utf32 = 0; + for (offset, c) in text.char_indices() { + let got_offset = line_index.offset(lin_col).unwrap(); + assert_eq!(usize::from(got_offset), offset); + + let got_lin_col = line_index.line_col(got_offset); + assert_eq!(got_lin_col, lin_col); + + for (enc, col) in [(WideEncoding::Utf16, col_utf16), (WideEncoding::Utf32, col_utf32)] { + let wide_lin_col = line_index.to_wide(enc, lin_col).unwrap(); + let got_lin_col = line_index.to_utf8(enc, wide_lin_col).unwrap(); + assert_eq!(got_lin_col, lin_col); + assert_eq!(wide_lin_col.col, col) + } + + if c == '\n' { + lin_col.line += 1; + lin_col.col = 0; + col_utf16 = 0; + col_utf32 = 0; + } else { + lin_col.col += c.len_utf8() as u32; + col_utf16 += c.len_utf16() as u32; + col_utf32 += 1; + } + } +} diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index d51daa3395733..40f872a24ab31 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -9,14 +9,20 @@ use crate::{flags, project_root}; pub(crate) mod assists_doc_tests; pub(crate) mod diagnostics_docs; +mod lints; impl flags::Codegen { pub(crate) fn run(self, _sh: &Shell) -> anyhow::Result<()> { match self.codegen_type.unwrap_or_default() { flags::CodegenType::All => { + diagnostics_docs::generate(self.check); assists_doc_tests::generate(self.check); + // lints::generate(self.check) Updating clones the rust repo, so don't run it unless + // explicitly asked for } flags::CodegenType::AssistsDocTests => assists_doc_tests::generate(self.check), + flags::CodegenType::DiagnosticsDocs => diagnostics_docs::generate(self.check), + flags::CodegenType::LintDefinitions => lints::generate(self.check), } Ok(()) } diff --git a/xtask/src/codegen/diagnostics_docs.rs b/xtask/src/codegen/diagnostics_docs.rs index a45b412fda59a..cf30531e7f9f4 100644 --- a/xtask/src/codegen/diagnostics_docs.rs +++ b/xtask/src/codegen/diagnostics_docs.rs @@ -7,7 +7,7 @@ use crate::{ project_root, }; -fn generate(check: bool) { +pub(crate) fn generate(check: bool) { let diagnostics = Diagnostic::collect().unwrap(); if !check { let contents = diff --git a/crates/ide-db/src/tests/sourcegen_lints.rs b/xtask/src/codegen/lints.rs similarity index 93% rename from crates/ide-db/src/tests/sourcegen_lints.rs rename to xtask/src/codegen/lints.rs index 86ed01c8e748b..63abcfc09041c 100644 --- a/crates/ide-db/src/tests/sourcegen_lints.rs +++ b/xtask/src/codegen/lints.rs @@ -2,18 +2,18 @@ //! and lints from rustc, rustdoc, and clippy. use std::{borrow::Cow, fs, path::Path}; -use itertools::Itertools; use stdx::format_to; -use test_utils::project_root; use xshell::{cmd, Shell}; +use crate::{ + codegen::{add_preamble, ensure_file_contents, list_files, reformat}, + project_root, +}; + const DESTINATION: &str = "crates/ide-db/src/generated/lints.rs"; -/// This clones rustc repo, and so is not worth to keep up-to-date. We update -/// manually by un-ignoring the test from time to time. -#[test] -#[ignore] -fn sourcegen_lint_completions() { +/// This clones rustc repo, and so is not worth to keep up-to-date on a constant basis. +pub(crate) fn generate(check: bool) { let sh = &Shell::new().unwrap(); let rust_repo = project_root().join("./target/rust"); @@ -73,10 +73,10 @@ pub struct LintGroup { .unwrap(); generate_descriptor_clippy(&mut contents, &lints_json); - let contents = sourcegen::add_preamble("sourcegen_lints", sourcegen::reformat(contents)); + let contents = add_preamble("sourcegen_lints", reformat(contents)); let destination = project_root().join(DESTINATION); - sourcegen::ensure_file_contents(destination.as_path(), &contents); + ensure_file_contents(destination.as_path(), &contents, check); } /// Parses the output of `rustdoc -Whelp` and prints `Lint` and `LintGroup` constants into `buf`. @@ -130,10 +130,9 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { ) }); - let lints = lints - .chain(lint_groups) - .sorted_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2)) - .collect::>(); + let mut lints = lints.chain(lint_groups).collect::>(); + lints.sort_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2)); + for (name, description, ..) in &lints { push_lint_completion(buf, &name.replace('-', "_"), description); } @@ -177,10 +176,8 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { ) }); - let lints_rustdoc = lints_rustdoc - .chain(lint_groups_rustdoc) - .sorted_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2)) - .collect::>(); + let mut lints_rustdoc = lints_rustdoc.chain(lint_groups_rustdoc).collect::>(); + lints_rustdoc.sort_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2)); for (name, description, ..) in &lints_rustdoc { push_lint_completion(buf, &name.replace('-', "_"), description) @@ -212,7 +209,7 @@ fn find_and_slice<'a>(i: &'a str, p: &str) -> &'a str { fn generate_feature_descriptor(buf: &mut String, src_dir: &Path) { let mut features = ["language-features", "library-features"] .into_iter() - .flat_map(|it| sourcegen::list_files(&src_dir.join(it))) + .flat_map(|it| list_files(&src_dir.join(it))) // Get all `.md` files .filter(|path| path.extension() == Some("md".as_ref())) .map(|path| { @@ -302,7 +299,7 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) { let children = children.iter().map(|id| format!("clippy::{id}")).collect::>(); if !children.is_empty() { let lint_ident = format!("clippy::{id}"); - let description = format!("lint group for: {}", children.iter().join(", ")); + let description = format!("lint group for: {}", children.join(", ")); push_lint_group(buf, &lint_ident, &description, &children); } } @@ -331,7 +328,10 @@ fn push_lint_group(buf: &mut String, label: &str, description: &str, children: & push_lint_completion(buf, label, description); - let children = format!("&[{}]", children.iter().map(|it| format!("\"{it}\"")).join(", ")); + let children = format!( + "&[{}]", + children.iter().map(|it| format!("\"{it}\"")).collect::>().join(", ") + ); format_to!( buf, r###" diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs index f5827170b6519..681c588bd01b5 100644 --- a/xtask/src/flags.rs +++ b/xtask/src/flags.rs @@ -92,6 +92,8 @@ pub enum CodegenType { #[default] All, AssistsDocTests, + DiagnosticsDocs, + LintDefinitions, } impl FromStr for CodegenType { @@ -100,6 +102,8 @@ impl FromStr for CodegenType { match s { "all" => Ok(Self::All), "assists-doc-tests" => Ok(Self::AssistsDocTests), + "diagnostics-docs" => Ok(Self::DiagnosticsDocs), + "lints-definitions" => Ok(Self::LintDefinitions), _ => Err("Invalid option".to_owned()), } } diff --git a/xtask/src/release.rs b/xtask/src/release.rs index f99f9ecbc39d9..1a5e6dfb4ccfd 100644 --- a/xtask/src/release.rs +++ b/xtask/src/release.rs @@ -23,7 +23,7 @@ impl flags::Release { } // Generates bits of manual.adoc. - cmd!(sh, "cargo test -p ide-diagnostics -p rust-analyzer -- sourcegen_").run()?; + codegen::diagnostics_docs::generate(false); codegen::assists_doc_tests::generate(false); let website_root = project_root().join("../rust-analyzer.github.io"); From b9dbb8afd9903b481f6902a1171d87a104b2e540 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 17:12:08 +0100 Subject: [PATCH 26/69] Regenerate lints table --- crates/ide-db/src/generated/lints.rs | 420 +++++++++++++++++++++------ crates/ide/src/hover/tests.rs | 54 +++- 2 files changed, 383 insertions(+), 91 deletions(-) diff --git a/crates/ide-db/src/generated/lints.rs b/crates/ide-db/src/generated/lints.rs index 2fc0793320039..d50088e6cf1d9 100644 --- a/crates/ide-db/src/generated/lints.rs +++ b/crates/ide-db/src/generated/lints.rs @@ -22,6 +22,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"detects certain glob imports that require reporting an ambiguity error"##, }, Lint { label: "ambiguous_glob_reexports", description: r##"ambiguous glob re-exports"## }, + Lint { + label: "ambiguous_wide_pointer_comparisons", + description: r##"detects ambiguous wide pointer comparisons"##, + }, Lint { label: "anonymous_parameters", description: r##"detects anonymous parameters"## }, Lint { label: "arithmetic_overflow", description: r##"arithmetic operation overflows"## }, Lint { @@ -66,10 +70,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "coherence_leak_check", description: r##"distinct impls distinguished only by the leak-check code"##, }, - Lint { - label: "coinductive_overlap_in_coherence", - description: r##"impls that are not considered to overlap may be considered to overlap in the future"##, - }, Lint { label: "conflicting_repr_hints", description: r##"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice"##, @@ -86,10 +86,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "const_item_mutation", description: r##"detects attempts to mutate a `const` item"##, }, - Lint { - label: "const_patterns_without_partial_eq", - description: r##"constant in pattern does not implement `PartialEq`"##, - }, Lint { label: "dead_code", description: r##"detect unused, unexported items"## }, Lint { label: "deprecated", description: r##"detects use of deprecated items"## }, Lint { @@ -176,7 +172,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, Lint { label: "future_incompatible", - description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##, }, Lint { label: "fuzzy_provenance_casts", @@ -190,14 +186,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "ill_formed_attribute_input", description: r##"ill-formed attribute inputs that were previously accepted and used in practice"##, }, - Lint { - label: "illegal_floating_point_literal_pattern", - description: r##"floating-point literals cannot be used in patterns"##, - }, - Lint { - label: "implied_bounds_entailment", - description: r##"impl method assumes more implied bounds than its corresponding trait method"##, - }, Lint { label: "improper_ctypes", description: r##"proper use of libc types in foreign modules"##, @@ -372,6 +360,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "non_fmt_panics", description: r##"detect single-argument panic!() invocations in which the argument is not a format string"##, }, + Lint { label: "non_local_definitions", description: r##"checks for non-local definitions"## }, Lint { label: "non_shorthand_field_patterns", description: r##"using `Struct { x: x }` instead of `Struct { x }` in a pattern"##, @@ -388,10 +377,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "nonstandard_style", description: r##"lint group for: non-camel-case-types, non-snake-case, non-upper-case-globals"##, }, - Lint { - label: "nontrivial_structural_match", - description: r##"constant used in pattern of non-structural-match type and the constant's initializer expression contains values of non-structural-match types"##, - }, Lint { label: "noop_method_call", description: r##"detects the use of well-known noop methods"##, @@ -482,6 +467,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "rust_2021_prelude_collisions", description: r##"detects the usage of trait methods which are ambiguous with traits added to the prelude in future editions"##, }, + Lint { + label: "rust_2024_compatibility", + description: r##"lint group for: static-mut-refs, unsafe-op-in-unsafe-fn"##, + }, Lint { label: "semicolon_in_expressions_from_macros", description: r##"trailing semicolon in macro body used as expression"##, @@ -503,8 +492,8 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"stable features found in `#[feature]` directive"##, }, Lint { - label: "suspicious_auto_trait_impls", - description: r##"the rules governing auto traits have recently changed resulting in potential breakage"##, + label: "static_mut_refs", + description: r##"shared references or mutable references of mutable static is discouraged"##, }, Lint { label: "suspicious_double_ref_op", @@ -579,6 +568,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"enabling track_caller on an async fn is a no-op unless the async_fn_track_caller feature is enabled"##, }, Lint { label: "uninhabited_static", description: r##"uninhabited static"## }, + Lint { + label: "unit_bindings", + description: r##"binding is useless because it has the unit `()` type"##, + }, Lint { label: "unknown_crate_types", description: r##"unknown crate type found in `#[crate_type]` directive"##, @@ -610,10 +603,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unsafe_op_in_unsafe_fn", description: r##"unsafe operations in unsafe functions without an explicit unsafe block are deprecated"##, }, - Lint { - label: "unstable_features", - description: r##"enabling unstable features (deprecated. do not use)"##, - }, + Lint { label: "unstable_features", description: r##"enabling unstable features"## }, Lint { label: "unstable_name_collisions", description: r##"detects name collision with an existing but unstable method"##, @@ -699,10 +689,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unused_results", description: r##"unused result of an expression in a statement"##, }, - Lint { - label: "unused_tuple_struct_fields", - description: r##"detects tuple struct fields that are never read"##, - }, Lint { label: "unused_unsafe", description: r##"unnecessary use of an `unsafe` block"## }, Lint { label: "unused_variables", @@ -736,13 +722,17 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "while_true", description: r##"suggest using `loop { }` instead of `while true { }`"##, }, + Lint { + label: "writes_through_immutable_pointer", + description: r##"shared references are immutable, and pointers derived from them must not be written to"##, + }, ]; pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "future_incompatible", - description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##, }, children: &[ "deref_into_dyn_supertrait", @@ -751,16 +741,12 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "byte_slice_in_packed_struct_with_derive", "cenum_impl_drop_cast", "coherence_leak_check", - "coinductive_overlap_in_coherence", "conflicting_repr_hints", "const_evaluatable_unchecked", - "const_patterns_without_partial_eq", "deprecated_cfg_attr_crate_type_name", "elided_lifetimes_in_associated_constant", "forbidden_lint_groups", "ill_formed_attribute_input", - "illegal_floating_point_literal_pattern", - "implied_bounds_entailment", "indirect_structural_match", "invalid_doc_attributes", "invalid_type_param_default", @@ -768,7 +754,6 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "legacy_derive_helpers", "macro_expanded_macro_exports_accessed_by_absolute_paths", "missing_fragment_specifier", - "nontrivial_structural_match", "order_dependent_trait_objects", "patterns_in_fns_without_body", "pointer_structural_match", @@ -778,12 +763,12 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "repr_transparent_external_private_fields", "semicolon_in_expressions_from_macros", "soft_unstable", - "suspicious_auto_trait_impls", "uninhabited_static", "unstable_name_collisions", "unstable_syntax_pre_expansion", "unsupported_calling_conventions", "where_clauses_object_safety", + "writes_through_immutable_pointer", ], }, LintGroup { @@ -841,6 +826,13 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "non_fmt_panics", ], }, + LintGroup { + lint: Lint { + label: "rust_2024_compatibility", + description: r##"lint group for: static-mut-refs, unsafe-op-in-unsafe-fn"##, + }, + children: &["static_mut_refs", "unsafe_op_in_unsafe_fn"], + }, LintGroup { lint: Lint { label: "unused", @@ -1735,9 +1727,17 @@ The tracking issue for this feature is: [#110011] label: "async_fn_traits", description: r##"# `async_fn_traits` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +See Also: [`fn_traits`](../library-features/fn-traits.md) ------------------------- +---- + +The `async_fn_traits` feature allows for implementation of the [`AsyncFn*`] traits +for creating custom closure-like types that return futures. + +[`AsyncFn*`]: ../../std/ops/trait.AsyncFn.html + +The main difference to the `Fn*` family of traits is that `AsyncFn` can return a future +that borrows from itself (`FnOnce::Output` has no lifetime parameters, while `AsyncFn::CallFuture` does). "##, }, Lint { @@ -2377,17 +2377,6 @@ The tracking issue for this feature is: [#89653] [#89653]: https://github.com/rust-lang/rust/issues/89653 ------------------------- -"##, - }, - Lint { - label: "cfg_target_abi", - description: r##"# `cfg_target_abi` - -The tracking issue for this feature is: [#80970] - -[#80970]: https://github.com/rust-lang/rust/issues/80970 - ------------------------ "##, }, @@ -3133,6 +3122,17 @@ The tracking issue for this feature is: [#90603] This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + }, + Lint { + label: "const_intrinsic_copy", + description: r##"# `const_intrinsic_copy` + +The tracking issue for this feature is: [#80697] + +[#80697]: https://github.com/rust-lang/rust/issues/80697 + ------------------------ "##, }, @@ -3301,6 +3301,17 @@ The tracking issue for this feature is: [#110840] [#110840]: https://github.com/rust-lang/rust/issues/110840 +------------------------ +"##, + }, + Lint { + label: "const_ops", + description: r##"# `const_ops` + +The tracking issue for this feature is: [#90080] + +[#90080]: https://github.com/rust-lang/rust/issues/90080 + ------------------------ "##, }, @@ -3444,6 +3455,17 @@ The tracking issue for this feature is: [#80384] [#80384]: https://github.com/rust-lang/rust/issues/80384 +------------------------ +"##, + }, + Lint { + label: "const_refs_to_static", + description: r##"# `const_refs_to_static` + +The tracking issue for this feature is: [#119618] + +[#119618]: https://github.com/rust-lang/rust/issues/119618 + ------------------------ "##, }, @@ -4256,6 +4278,15 @@ The tracking issue for this feature is: [#27336] [#27336]: https://github.com/rust-lang/rust/issues/27336 +------------------------ +"##, + }, + Lint { + label: "delayed_debug_assertions", + description: r##"# `delayed_debug_assertions` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -4637,6 +4668,19 @@ The tracking issue for this feature is: [#57391] [#57391]: https://github.com/rust-lang/rust/issues/57391 ------------------------ +"##, + }, + Lint { + label: "duration_constructors", + description: r##"# `duration_constructors` + +The tracking issue for this feature is: [#120301] + +[#120301]: https://github.com/rust-lang/rust/issues/120301 + +------------------------ + +Add the methods `from_mins`, `from_hours` and `from_days` to `Duration`. "##, }, Lint { @@ -4647,6 +4691,17 @@ The tracking issue for this feature is: [#72440] [#72440]: https://github.com/rust-lang/rust/issues/72440 +------------------------ +"##, + }, + Lint { + label: "duration_units", + description: r##"# `duration_units` + +The tracking issue for this feature is: [#120301] + +[#120301]: https://github.com/rust-lang/rust/issues/120301 + ------------------------ "##, }, @@ -5659,13 +5714,62 @@ raw pointers in intra-doc links are unstable until it does. The tracking issue for this feature is: None. -Intrinsics are never intended to be stable directly, but intrinsics are often +Intrinsics are rarely intended to be stable directly, but are usually exported in some sort of stable manner. Prefer using the stable interfaces to the intrinsic directly when you can. ------------------------ +## Intrinsics with fallback logic + +Many intrinsics can be written in pure rust, albeit inefficiently or without supporting +some features that only exist on some backends. Backends can simply not implement those +intrinsics without causing any code miscompilations or failures to compile. +All intrinsic fallback bodies are automatically made cross-crate inlineable (like `#[inline]`) +by the codegen backend, but not the MIR inliner. + +```rust +#![feature(rustc_attrs, effects)] +#![allow(internal_features)] + +#[rustc_intrinsic] +const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} +``` + +Since these are just regular functions, it is perfectly ok to create the intrinsic twice: + +```rust +#![feature(rustc_attrs, effects)] +#![allow(internal_features)] + +#[rustc_intrinsic] +const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} + +mod foo { + #[rustc_intrinsic] + const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) { + panic!("noisy const dealloc") + } +} + +``` + +The behaviour on backends that override the intrinsic is exactly the same. On other +backends, the intrinsic behaviour depends on which implementation is called, just like +with any regular function. + +## Intrinsics lowered to MIR instructions + +Various intrinsics have native MIR operations that they correspond to. Instead of requiring +backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass +will convert the calls to the MIR operation. Backends do not need to know about these intrinsics +at all. + +## Intrinsics without fallback logic + +These must be implemented by all backends. + These are imported as if they were FFI functions, with the special `rust-intrinsic` ABI. For example, if one was in a freestanding context, but wished to be able to `transmute` between types, and @@ -5684,7 +5788,8 @@ extern "rust-intrinsic" { } ``` -As with any other FFI functions, these are always `unsafe` to call. +As with any other FFI functions, these are by default always `unsafe` to call. +You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call. "##, }, Lint { @@ -5759,6 +5864,17 @@ The tracking issue for this feature is: [#101288] [#101288]: https://github.com/rust-lang/rust/issues/101288 +------------------------ +"##, + }, + Lint { + label: "is_riscv_feature_detected", + description: r##"# `is_riscv_feature_detected` + +The tracking issue for this feature is: [#111192] + +[#111192]: https://github.com/rust-lang/rust/issues/111192 + ------------------------ "##, }, @@ -5937,6 +6053,17 @@ The tracking issue for this feature is: [#87053] [#87053]: https://github.com/rust-lang/rust/issues/87053 +------------------------ +"##, + }, + Lint { + label: "lahfsahf_target_feature", + description: r##"# `lahfsahf_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + ------------------------ "##, }, @@ -6260,6 +6387,17 @@ The tracking issue for this feature is: [#82971] [#82971]: https://github.com/rust-lang/rust/issues/82971 +------------------------ +"##, + }, + Lint { + label: "local_waker", + description: r##"# `local_waker` + +The tracking issue for this feature is: [#118959] + +[#118959]: https://github.com/rust-lang/rust/issues/118959 + ------------------------ "##, }, @@ -6326,6 +6464,17 @@ The tracking issue for this feature is: [#82766] [#82766]: https://github.com/rust-lang/rust/issues/82766 +------------------------ +"##, + }, + Lint { + label: "mapped_lock_guards", + description: r##"# `mapped_lock_guards` + +The tracking issue for this feature is: [#117108] + +[#117108]: https://github.com/rust-lang/rust/issues/117108 + ------------------------ "##, }, @@ -6539,17 +6688,6 @@ The tracking issue for this feature is: [#83310] [#83310]: https://github.com/rust-lang/rust/issues/83310 ------------------------- -"##, - }, - Lint { - label: "mutex_unlock", - description: r##"# `mutex_unlock` - -The tracking issue for this feature is: [#81872] - -[#81872]: https://github.com/rust-lang/rust/issues/81872 - ------------------------ "##, }, @@ -6977,6 +7115,17 @@ The tracking issue for this feature is: [#70086] [#70086]: https://github.com/rust-lang/rust/issues/70086 +------------------------ +"##, + }, + Lint { + label: "os_str_display", + description: r##"# `os_str_display` + +The tracking issue for this feature is: [#120048] + +[#120048]: https://github.com/rust-lang/rust/issues/120048 + ------------------------ "##, }, @@ -7107,6 +7256,15 @@ The tracking issue for this feature is: [#27721] [#27721]: https://github.com/rust-lang/rust/issues/27721 +------------------------ +"##, + }, + Lint { + label: "pattern_complexity", + description: r##"# `pattern_complexity` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -7129,17 +7287,6 @@ The tracking issue for this feature is: [#86918] [#86918]: https://github.com/rust-lang/rust/issues/86918 ------------------------- -"##, - }, - Lint { - label: "platform_intrinsics", - description: r##"# `platform_intrinsics` - -The tracking issue for this feature is: [#27731] - -[#27731]: https://github.com/rust-lang/rust/issues/27731 - ------------------------ "##, }, @@ -7189,7 +7336,9 @@ The tracking issue for this feature is: [#44839] label: "prelude_2024", description: r##"# `prelude_2024` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +The tracking issue for this feature is: [#121042] + +[#121042]: https://github.com/rust-lang/rust/issues/121042 ------------------------ "##, @@ -7200,6 +7349,17 @@ This feature has no tracking issue, and is therefore likely internal to the comp This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + }, + Lint { + label: "prfchw_target_feature", + description: r##"# `prfchw_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + ------------------------ "##, }, @@ -7512,6 +7672,17 @@ The tracking issue for this feature is: [#101196] This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + }, + Lint { + label: "reentrant_lock", + description: r##"# `reentrant_lock` + +The tracking issue for this feature is: [#121440] + +[#121440]: https://github.com/rust-lang/rust/issues/121440 + ------------------------ "##, }, @@ -8186,23 +8357,45 @@ This feature has no tracking issue, and is therefore likely internal to the comp "##, }, Lint { - label: "stdio_makes_pipe", - description: r##"# `stdio_makes_pipe` + label: "stdarch_arm_feature_detection", + description: r##"# `stdarch_arm_feature_detection` -The tracking issue for this feature is: [#98288] +The tracking issue for this feature is: [#111190] -[#98288]: https://github.com/rust-lang/rust/issues/98288 +[#111190]: https://github.com/rust-lang/rust/issues/111190 + +------------------------ +"##, + }, + Lint { + label: "stdarch_mips_feature_detection", + description: r##"# `stdarch_mips_feature_detection` + +The tracking issue for this feature is: [#111188] + +[#111188]: https://github.com/rust-lang/rust/issues/111188 + +------------------------ +"##, + }, + Lint { + label: "stdarch_powerpc_feature_detection", + description: r##"# `stdarch_powerpc_feature_detection` + +The tracking issue for this feature is: [#111191] + +[#111191]: https://github.com/rust-lang/rust/issues/111191 ------------------------ "##, }, Lint { - label: "stdsimd", - description: r##"# `stdsimd` + label: "stdio_makes_pipe", + description: r##"# `stdio_makes_pipe` -The tracking issue for this feature is: [#48556] +The tracking issue for this feature is: [#98288] -[#48556]: https://github.com/rust-lang/rust/issues/48556 +[#98288]: https://github.com/rust-lang/rust/issues/98288 ------------------------ "##, @@ -8464,6 +8657,17 @@ The tracking issue for this feature is: [#44839] [#44839]: https://github.com/rust-lang/rust/issues/44839 +------------------------ +"##, + }, + Lint { + label: "tcp_deferaccept", + description: r##"# `tcp_deferaccept` + +The tracking issue for this feature is: [#119639] + +[#119639]: https://github.com/rust-lang/rust/issues/119639 + ------------------------ "##, }, @@ -10156,7 +10360,7 @@ table: }, Lint { label: "clippy::blocks_in_conditions", - description: r##"Checks for `if` conditions that use blocks containing an + description: r##"Checks for `if` and `match` conditions that use blocks containing an expression, statements or conditions that use closures with blocks."##, }, Lint { @@ -10458,6 +10662,12 @@ See [RFC0212](https://github.com/rust-lang/rfcs/blob/master/text/0212-restore-in label: "clippy::deprecated_cfg_attr", description: r##"Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it with `#[rustfmt::skip]`."##, + }, + Lint { + label: "clippy::deprecated_clippy_cfg_attr", + description: r##"Checks for `#[cfg_attr(feature = cargo-clippy, ...)]` and for +`#[cfg(feature = cargo-clippy)]` and suggests to replace it with +`#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`."##, }, Lint { label: "clippy::deprecated_semver", @@ -10601,6 +10811,7 @@ eagerly (e.g. using `bool::then_some`)."##, description: r##"Checks for usage of if expressions with an `else if` branch, but without a final `else` branch."##, }, + Lint { label: "clippy::empty_docs", description: r##"Detects documentation that is empty."## }, Lint { label: "clippy::empty_drop", description: r##"Checks for empty `Drop` implementations."##, @@ -11357,6 +11568,7 @@ cannot be represented as the underlying type without loss."##, description: r##"Checks for usage of `std::mem::size_of::() * 8` when `T::BITS` is available."##, }, + Lint { label: "clippy::manual_c_str_literals", description: r##""## }, Lint { label: "clippy::manual_clamp", description: r##"Identifies good opportunities for a clamp function from std or core, and suggests using it."##, @@ -11731,6 +11943,10 @@ rather than globally."##, label: "clippy::mistyped_literal_suffixes", description: r##"Warns for mistyped suffix in literals"##, }, + Lint { + label: "clippy::mixed_attributes_style", + description: r##"Checks that an item has only one kind of attributes."##, + }, Lint { label: "clippy::mixed_case_hex_literals", description: r##"Warns on hexadecimal literals with mixed-case letter @@ -11763,6 +11979,10 @@ containing module's name."##, one."##, }, Lint { label: "clippy::multi_assignments", description: r##"Checks for nested assignments."## }, + Lint { + label: "clippy::multiple_bound_locations", + description: r##"Check if a generic is defined both in the bound predicate and in the `where` clause."##, + }, Lint { label: "clippy::multiple_crate_versions", description: r##"Checks to see if multiple versions of a crate are being @@ -12336,8 +12556,8 @@ in `vec![elem; len]`"##, Lint { label: "clippy::read_line_without_trim", description: r##"Looks for calls to [`Stdin::read_line`] to read a line from the standard input -into a string, then later attempting to parse this string into a type without first trimming it, which will -always fail because the string has a trailing newline in it."##, +into a string, then later attempting to use that string for an operation that will never +work for strings with a trailing newline character in it (e.g. parsing into a `i32`)."##, }, Lint { label: "clippy::read_zero_byte_vec", @@ -12444,6 +12664,11 @@ do not change the type."##, label: "clippy::redundant_type_annotations", description: r##"Warns about needless / redundant type annotations."##, }, + Lint { + label: "clippy::ref_as_ptr", + description: r##"Checks for casts of references to pointer using `as` +and suggests `std::ptr::from_ref` and `std::ptr::from_mut` instead."##, + }, Lint { label: "clippy::ref_binding_to_reference", description: r##"Checks for `ref` bindings which create a reference to a reference."##, @@ -13095,6 +13320,11 @@ as returning a large `T` directly may be detrimental to performance."##, label: "clippy::unnecessary_cast", description: r##"Checks for casts to the same type, casts of int literals to integer types, casts of float literals to float types and casts between raw pointers without changing type or constness."##, + }, + Lint { + label: "clippy::unnecessary_clippy_cfg", + description: r##"Checks for `#[cfg_attr(clippy, allow(clippy::lint))]` +and suggests to replace it with `#[allow(clippy::lint)]`."##, }, Lint { label: "clippy::unnecessary_fallible_conversions", @@ -13119,6 +13349,10 @@ find or map operations and suggests the appropriate option."##, Specifically, this checks for `fold`s which could be replaced by `any`, `all`, `sum` or `product`."##, }, + Lint { + label: "clippy::unnecessary_get_then_check", + description: r##"Checks the usage of `.get().is_some()` or `.get().is_none()` on std map types."##, + }, Lint { label: "clippy::unnecessary_join", description: r##"Checks for usage of `.collect::>().join()` on iterators."##, @@ -13830,7 +14064,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::pedantic", - description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_filter_is_ok, clippy::iter_filter_is_some, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_is_variant_and, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_as_ref_cloned, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::pub_underscore_fields, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::str_split_at_newline, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, + description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_filter_is_ok, clippy::iter_filter_is_some, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_c_str_literals, clippy::manual_instant_elapsed, clippy::manual_is_variant_and, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_as_ref_cloned, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::pub_underscore_fields, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_as_ptr, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::str_split_at_newline, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, }, children: &[ "clippy::bool_to_int_with_if", @@ -13881,6 +14115,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::linkedlist", "clippy::macro_use_imports", "clippy::manual_assert", + "clippy::manual_c_str_literals", "clippy::manual_instant_elapsed", "clippy::manual_is_variant_and", "clippy::manual_let_else", @@ -13918,6 +14153,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::range_plus_one", "clippy::redundant_closure_for_method_calls", "clippy::redundant_else", + "clippy::ref_as_ptr", "clippy::ref_binding_to_reference", "clippy::ref_option_ref", "clippy::return_self_not_must_use", @@ -14262,7 +14498,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::suspicious", - description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::incompatible_msrv, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_open_options, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion, clippy::unnecessary_result_map_or_else"##, + description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::deprecated_clippy_cfg_attr, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_docs, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::incompatible_msrv, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::mixed_attributes_style, clippy::multi_assignments, clippy::multiple_bound_locations, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_open_options, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion, clippy::unnecessary_clippy_cfg, clippy::unnecessary_get_then_check, clippy::unnecessary_result_map_or_else"##, }, children: &[ "clippy::almost_complete_range", @@ -14277,8 +14513,10 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::cast_nan_to_int", "clippy::cast_slice_from_raw_parts", "clippy::crate_in_macro_def", + "clippy::deprecated_clippy_cfg_attr", "clippy::drop_non_drop", "clippy::duplicate_mod", + "clippy::empty_docs", "clippy::empty_loop", "clippy::float_equality_without_abs", "clippy::forget_non_drop", @@ -14293,7 +14531,9 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::maybe_misused_cfg", "clippy::misnamed_getters", "clippy::misrefactored_assign_op", + "clippy::mixed_attributes_style", "clippy::multi_assignments", + "clippy::multiple_bound_locations", "clippy::mut_range_bound", "clippy::mutable_key_type", "clippy::no_effect_replace", @@ -14321,6 +14561,8 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::test_attr_in_doctest", "clippy::type_id_on_box", "clippy::unconditional_recursion", + "clippy::unnecessary_clippy_cfg", + "clippy::unnecessary_get_then_check", "clippy::unnecessary_result_map_or_else", ], }, diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 3411133f50e36..e63717e35a3be 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -5434,13 +5434,62 @@ fn hover_feature() { The tracking issue for this feature is: None. - Intrinsics are never intended to be stable directly, but intrinsics are often + Intrinsics are rarely intended to be stable directly, but are usually exported in some sort of stable manner. Prefer using the stable interfaces to the intrinsic directly when you can. ------------------------ + ## Intrinsics with fallback logic + + Many intrinsics can be written in pure rust, albeit inefficiently or without supporting + some features that only exist on some backends. Backends can simply not implement those + intrinsics without causing any code miscompilations or failures to compile. + All intrinsic fallback bodies are automatically made cross-crate inlineable (like `#[inline]`) + by the codegen backend, but not the MIR inliner. + + ```rust + #![feature(rustc_attrs, effects)] + #![allow(internal_features)] + + #[rustc_intrinsic] + const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} + ``` + + Since these are just regular functions, it is perfectly ok to create the intrinsic twice: + + ```rust + #![feature(rustc_attrs, effects)] + #![allow(internal_features)] + + #[rustc_intrinsic] + const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} + + mod foo { + #[rustc_intrinsic] + const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) { + panic!("noisy const dealloc") + } + } + + ``` + + The behaviour on backends that override the intrinsic is exactly the same. On other + backends, the intrinsic behaviour depends on which implementation is called, just like + with any regular function. + + ## Intrinsics lowered to MIR instructions + + Various intrinsics have native MIR operations that they correspond to. Instead of requiring + backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass + will convert the calls to the MIR operation. Backends do not need to know about these intrinsics + at all. + + ## Intrinsics without fallback logic + + These must be implemented by all backends. + These are imported as if they were FFI functions, with the special `rust-intrinsic` ABI. For example, if one was in a freestanding context, but wished to be able to `transmute` between types, and @@ -5459,7 +5508,8 @@ fn hover_feature() { } ``` - As with any other FFI functions, these are always `unsafe` to call. + As with any other FFI functions, these are by default always `unsafe` to call. + You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call. "#]], ) From ac641a19e7da1df98a95a9c4b7d57df2208d1722 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 21:40:57 +0000 Subject: [PATCH 27/69] Bump mio from 0.8.5 to 0.8.11 Bumps [mio](https://github.com/tokio-rs/mio) from 0.8.5 to 0.8.11. - [Release notes](https://github.com/tokio-rs/mio/releases) - [Changelog](https://github.com/tokio-rs/mio/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/mio/compare/v0.8.5...v0.8.11) --- updated-dependencies: - dependency-name: mio dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Cargo.lock | 91 ++++++++++-------------------------------------------- 1 file changed, 17 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89a1f68cce0fe..3667dec23a6f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -296,7 +296,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" dependencies = [ "nix 0.27.1", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -390,7 +390,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall 0.3.5", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -622,7 +622,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -891,7 +891,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1073,14 +1073,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.5" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -1089,7 +1089,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "359f76430b20a79f9e20e115b3428614e654f04fab314482fc0fda0ebd3c6044" dependencies = [ - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1137,7 +1137,7 @@ dependencies = [ "log", "mio", "walkdir", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1146,7 +1146,7 @@ version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" dependencies = [ - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -2325,21 +2325,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -2355,93 +2340,51 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" From 2a4ba4295b3bb53e672cb2dded2247a5553cf089 Mon Sep 17 00:00:00 2001 From: Niklas Lindorfer Date: Mon, 4 Mar 2024 18:14:25 +0000 Subject: [PATCH 28/69] fix: hide destructure_struct_binding assist if no public fields --- .../handlers/destructure_struct_binding.rs | 27 +++++++++++++------ crates/syntax/src/ast/make.rs | 5 +++- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/crates/ide-assists/src/handlers/destructure_struct_binding.rs index 4edc52b614ab1..c1a3f9302650e 100644 --- a/crates/ide-assists/src/handlers/destructure_struct_binding.rs +++ b/crates/ide-assists/src/handlers/destructure_struct_binding.rs @@ -107,6 +107,10 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option ast::RecordPatFieldList { let mut fields = fields.into_iter().join(", "); if let Some(rest_pat) = rest_pat { - format_to!(fields, ", {rest_pat}"); + if !fields.is_empty() { + fields.push_str(", "); + } + format_to!(fields, "{rest_pat}"); } ast_from_text(&format!("fn f(S {{ {fields} }}: ()))")) } From fe0daa7be3437766ac70422fb9df8c20523fd64a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 09:37:25 +0100 Subject: [PATCH 29/69] Revert "prioritise rustup sysroots over system ones" This reverts commit 9f1d4aa4b9e4a1572c1210b3bd7c7490778b6112. --- crates/toolchain/src/lib.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/toolchain/src/lib.rs b/crates/toolchain/src/lib.rs index 793138588a3f6..ae71b6700c0b2 100644 --- a/crates/toolchain/src/lib.rs +++ b/crates/toolchain/src/lib.rs @@ -63,17 +63,21 @@ fn get_path_for_executable(executable_name: &'static str) -> PathBuf { // The current implementation checks three places for an executable to use: // 1) Appropriate environment variable (erroring if this is set but not a usable executable) // example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc - // 2) `$CARGO_HOME/bin/` + // 2) `` + // example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH + // 3) `$CARGO_HOME/bin/` // where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html) // example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. // It seems that this is a reasonable place to try for cargo, rustc, and rustup - // 3) `` - // example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH let env_var = executable_name.to_ascii_uppercase(); if let Some(path) = env::var_os(env_var) { return path.into(); } + if lookup_in_path(executable_name) { + return executable_name.into(); + } + if let Some(mut path) = get_cargo_home() { path.push("bin"); path.push(executable_name); @@ -82,10 +86,6 @@ fn get_path_for_executable(executable_name: &'static str) -> PathBuf { } } - if lookup_in_path(executable_name) { - return executable_name.into(); - } - executable_name.into() } From c310aee8d670c4436ef2e1a8bdf8727cf8abbfac Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 10:16:30 +0100 Subject: [PATCH 30/69] For toolchain binaries ue the full path found in $PATH --- Cargo.lock | 1 - crates/ide/src/expand_macro.rs | 2 +- .../proc-macro-srv/proc-macro-test/Cargo.toml | 3 - .../proc-macro-srv/proc-macro-test/build.rs | 14 +-- crates/project-model/src/sysroot.rs | 6 +- crates/rust-analyzer/src/handlers/request.rs | 2 +- crates/toolchain/src/lib.rs | 102 +++++++++--------- 7 files changed, 63 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3667dec23a6f6..c6df491596ace 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1336,7 +1336,6 @@ name = "proc-macro-test" version = "0.0.0" dependencies = [ "cargo_metadata", - "toolchain", ] [[package]] diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 9eb5a9db6250e..4b0961cbbebaf 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -189,7 +189,7 @@ fn _format( let &crate_id = db.relevant_crates(file_id).iter().next()?; let edition = db.crate_graph()[crate_id].edition; - let mut cmd = std::process::Command::new(toolchain::rustfmt()); + let mut cmd = std::process::Command::new(toolchain::Tool::Rustfmt.path()); cmd.arg("--edition"); cmd.arg(edition.to_string()); diff --git a/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/crates/proc-macro-srv/proc-macro-test/Cargo.toml index 7977afb1cbd23..7c6a1ba46b5fa 100644 --- a/crates/proc-macro-srv/proc-macro-test/Cargo.toml +++ b/crates/proc-macro-srv/proc-macro-test/Cargo.toml @@ -11,6 +11,3 @@ doctest = false [build-dependencies] cargo_metadata = "0.18.1" - -# local deps -toolchain.workspace = true diff --git a/crates/proc-macro-srv/proc-macro-test/build.rs b/crates/proc-macro-srv/proc-macro-test/build.rs index ff62980e4ffe3..c76c201d69e87 100644 --- a/crates/proc-macro-srv/proc-macro-test/build.rs +++ b/crates/proc-macro-srv/proc-macro-test/build.rs @@ -18,12 +18,12 @@ use cargo_metadata::Message; fn main() { println!("cargo:rerun-if-changed=imp"); + let cargo = env::var_os("CARGO").unwrap_or_else(|| "cargo".into()); + let has_features = env::var_os("RUSTC_BOOTSTRAP").is_some() - || String::from_utf8( - Command::new(toolchain::cargo()).arg("--version").output().unwrap().stdout, - ) - .unwrap() - .contains("nightly"); + || String::from_utf8(Command::new(&cargo).arg("--version").output().unwrap().stdout) + .unwrap() + .contains("nightly"); let out_dir = env::var_os("OUT_DIR").unwrap(); let out_dir = Path::new(&out_dir); @@ -66,7 +66,7 @@ fn main() { let target_dir = out_dir.join("target"); - let mut cmd = Command::new(toolchain::cargo()); + let mut cmd = Command::new(&cargo); cmd.current_dir(&staging_dir) .args(["build", "-p", "proc-macro-test-impl", "--message-format", "json"]) // Explicit override the target directory to avoid using the same one which the parent @@ -96,7 +96,7 @@ fn main() { let repr = format!("{name} {version}"); // New Package Id Spec since rust-lang/cargo#13311 let pkgid = String::from_utf8( - Command::new(toolchain::cargo()) + Command::new(cargo) .current_dir(&staging_dir) .args(["pkgid", name]) .output() diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs index ea24393ed8a29..a486a38510a8c 100644 --- a/crates/project-model/src/sysroot.rs +++ b/crates/project-model/src/sysroot.rs @@ -12,7 +12,7 @@ use itertools::Itertools; use la_arena::{Arena, Idx}; use paths::{AbsPath, AbsPathBuf}; use rustc_hash::FxHashMap; -use toolchain::probe_for_binary; +use toolchain::{probe_for_binary, Tool}; use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath}; @@ -411,7 +411,7 @@ fn discover_sysroot_dir( current_dir: &AbsPath, extra_env: &FxHashMap, ) -> Result { - let mut rustc = Command::new(toolchain::rustc()); + let mut rustc = Command::new(Tool::Rustc.path()); rustc.envs(extra_env); rustc.current_dir(current_dir).args(["--print", "sysroot"]); tracing::debug!("Discovering sysroot by {:?}", rustc); @@ -443,7 +443,7 @@ fn discover_sysroot_src_dir_or_add_component( ) -> Result { discover_sysroot_src_dir(sysroot_path) .or_else(|| { - let mut rustup = Command::new(toolchain::rustup()); + let mut rustup = Command::new(Tool::Rustup.prefer_proxy()); rustup.envs(extra_env); rustup.current_dir(current_dir).args(["component", "add", "rust-src"]); tracing::info!("adding rust-src component by {:?}", rustup); diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 0e005975fbae5..091f485db0060 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -1937,7 +1937,7 @@ fn run_rustfmt( let mut command = match snap.config.rustfmt() { RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => { // FIXME: Set RUSTUP_TOOLCHAIN - let mut cmd = process::Command::new(toolchain::rustfmt()); + let mut cmd = process::Command::new(toolchain::Tool::Rustfmt.path()); cmd.envs(snap.config.extra_env()); cmd.args(extra_args); diff --git a/crates/toolchain/src/lib.rs b/crates/toolchain/src/lib.rs index ae71b6700c0b2..e65a060672eec 100644 --- a/crates/toolchain/src/lib.rs +++ b/crates/toolchain/src/lib.rs @@ -16,8 +16,42 @@ pub enum Tool { } impl Tool { + pub fn proxy(self) -> Option { + cargo_proxy(self.name()) + } + + /// Return a `PathBuf` to use for the given executable. + /// + /// The current implementation checks three places for an executable to use: + /// 1) `$CARGO_HOME/bin/` + /// where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html) + /// example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. + /// It seems that this is a reasonable place to try for cargo, rustc, and rustup + /// 2) Appropriate environment variable (erroring if this is set but not a usable executable) + /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc + /// 3) $PATH/`` + /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the + /// first that exists + /// 4) If all else fails, we just try to use the executable name directly + pub fn prefer_proxy(self) -> PathBuf { + invoke(&[cargo_proxy, lookup_as_env_var, lookup_in_path], self.name()) + } + + /// Return a `PathBuf` to use for the given executable. + /// + /// The current implementation checks three places for an executable to use: + /// 1) Appropriate environment variable (erroring if this is set but not a usable executable) + /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc + /// 2) $PATH/`` + /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the + /// first that exists + /// 3) `$CARGO_HOME/bin/` + /// where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html) + /// example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. + /// It seems that this is a reasonable place to try for cargo, rustc, and rustup + /// 4) If all else fails, we just try to use the executable name directly pub fn path(self) -> PathBuf { - get_path_for_executable(self.name()) + invoke(&[lookup_as_env_var, lookup_in_path, cargo_proxy], self.name()) } pub fn path_in(self, path: &Path) -> Option { @@ -38,60 +72,21 @@ impl Tool { } } -pub fn cargo() -> PathBuf { - get_path_for_executable("cargo") -} - -pub fn rustc() -> PathBuf { - get_path_for_executable("rustc") +fn invoke(list: &[fn(&str) -> Option], executable: &str) -> PathBuf { + list.iter().find_map(|it| it(executable)).unwrap_or_else(|| executable.into()) } -pub fn rustup() -> PathBuf { - get_path_for_executable("rustup") +/// Looks up the binary as its SCREAMING upper case in the env variables. +fn lookup_as_env_var(executable_name: &str) -> Option { + env::var_os(executable_name.to_ascii_uppercase()).map(Into::into) } -pub fn rustfmt() -> PathBuf { - get_path_for_executable("rustfmt") -} - -/// Return a `PathBuf` to use for the given executable. -/// -/// E.g., `get_path_for_executable("cargo")` may return just `cargo` if that -/// gives a valid Cargo executable; or it may return a full path to a valid -/// Cargo. -fn get_path_for_executable(executable_name: &'static str) -> PathBuf { - // The current implementation checks three places for an executable to use: - // 1) Appropriate environment variable (erroring if this is set but not a usable executable) - // example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc - // 2) `` - // example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH - // 3) `$CARGO_HOME/bin/` - // where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html) - // example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. - // It seems that this is a reasonable place to try for cargo, rustc, and rustup - let env_var = executable_name.to_ascii_uppercase(); - if let Some(path) = env::var_os(env_var) { - return path.into(); - } - - if lookup_in_path(executable_name) { - return executable_name.into(); - } - - if let Some(mut path) = get_cargo_home() { - path.push("bin"); - path.push(executable_name); - if let Some(path) = probe_for_binary(path) { - return path; - } - } - - executable_name.into() -} - -fn lookup_in_path(exec: &str) -> bool { - let paths = env::var_os("PATH").unwrap_or_default(); - env::split_paths(&paths).map(|path| path.join(exec)).find_map(probe_for_binary).is_some() +/// Looks up the binary in the cargo home directory if it exists. +fn cargo_proxy(executable_name: &str) -> Option { + let mut path = get_cargo_home()?; + path.push("bin"); + path.push(executable_name); + probe_for_binary(path) } fn get_cargo_home() -> Option { @@ -107,6 +102,11 @@ fn get_cargo_home() -> Option { None } +fn lookup_in_path(exec: &str) -> Option { + let paths = env::var_os("PATH").unwrap_or_default(); + env::split_paths(&paths).map(|path| path.join(exec)).find_map(probe_for_binary) +} + pub fn probe_for_binary(path: PathBuf) -> Option { let with_extension = match env::consts::EXE_EXTENSION { "" => None, From 6b48133e9acd360004f4a193238ba493d18bf921 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 10:44:17 +0100 Subject: [PATCH 31/69] Prefer cargo proxies when setting RUSTUP_TOOLCHAIN --- crates/project-model/src/build_scripts.rs | 8 ++-- crates/project-model/src/cargo_workspace.rs | 17 ++++---- crates/project-model/src/rustc_cfg.rs | 9 ++--- crates/project-model/src/sysroot.rs | 33 ++++++++------- .../project-model/src/target_data_layout.rs | 7 ++-- crates/project-model/src/workspace.rs | 40 +++++++++---------- crates/toolchain/src/lib.rs | 4 -- 7 files changed, 54 insertions(+), 64 deletions(-) diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs index 27a8db40a9989..709fc03717471 100644 --- a/crates/project-model/src/build_scripts.rs +++ b/crates/project-model/src/build_scripts.rs @@ -71,8 +71,7 @@ impl WorkspaceBuildScripts { cmd } _ => { - let mut cmd = Command::new(Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Cargo); cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]); cmd.args(&config.extra_args); @@ -430,8 +429,7 @@ impl WorkspaceBuildScripts { } let res = (|| { let target_libdir = (|| { - let mut cargo_config = Command::new(Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot); + let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo); cargo_config.envs(extra_env); cargo_config .current_dir(current_dir) @@ -440,7 +438,7 @@ impl WorkspaceBuildScripts { if let Ok(it) = utf8_stdout(cargo_config) { return Ok(it); } - let mut cmd = Sysroot::rustc(sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Rustc); cmd.envs(extra_env); cmd.args(["--print", "target-libdir"]); utf8_stdout(cmd) diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs index 609b1f67b57db..53b41ea1e87b6 100644 --- a/crates/project-model/src/cargo_workspace.rs +++ b/crates/project-model/src/cargo_workspace.rs @@ -1,8 +1,8 @@ //! See [`CargoWorkspace`]. +use std::ops; use std::path::PathBuf; use std::str::from_utf8; -use std::{ops, process::Command}; use anyhow::Context; use base_db::Edition; @@ -243,8 +243,11 @@ impl CargoWorkspace { ) -> anyhow::Result { let targets = find_list_of_build_targets(config, cargo_toml, sysroot); + let cargo = Sysroot::tool(sysroot, Tool::Cargo); let mut meta = MetadataCommand::new(); - meta.cargo_path(Tool::Cargo.path()); + meta.cargo_path(cargo.get_program()); + cargo.get_envs().for_each(|(var, val)| _ = meta.env(var, val.unwrap_or_default())); + config.extra_env.iter().for_each(|(var, val)| _ = meta.env(var, val)); meta.manifest_path(cargo_toml.to_path_buf()); match &config.features { CargoFeatures::All => { @@ -291,10 +294,7 @@ impl CargoWorkspace { progress("metadata".to_owned()); (|| -> Result { - let mut command = meta.cargo_command(); - Sysroot::set_rustup_toolchain_env(&mut command, sysroot); - command.envs(&config.extra_env); - let output = command.output()?; + let output = meta.cargo_command().output()?; if !output.status.success() { return Err(cargo_metadata::Error::CargoMetadata { stderr: String::from_utf8(output.stderr)?, @@ -501,7 +501,7 @@ fn rustc_discover_host_triple( extra_env: &FxHashMap, sysroot: Option<&Sysroot>, ) -> Option { - let mut rustc = Sysroot::rustc(sysroot); + let mut rustc = Sysroot::tool(sysroot, Tool::Rustc); rustc.envs(extra_env); rustc.current_dir(cargo_toml.parent()).arg("-vV"); tracing::debug!("Discovering host platform by {:?}", rustc); @@ -529,8 +529,7 @@ fn cargo_config_build_target( extra_env: &FxHashMap, sysroot: Option<&Sysroot>, ) -> Vec { - let mut cargo_config = Command::new(Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot); + let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo); cargo_config.envs(extra_env); cargo_config .current_dir(cargo_toml.parent()) diff --git a/crates/project-model/src/rustc_cfg.rs b/crates/project-model/src/rustc_cfg.rs index 001296fb0002f..501b1fdc8c5b5 100644 --- a/crates/project-model/src/rustc_cfg.rs +++ b/crates/project-model/src/rustc_cfg.rs @@ -1,9 +1,8 @@ //! Runs `rustc --print cfg` to get built-in cfg flags. -use std::process::Command; - use anyhow::Context; use rustc_hash::FxHashMap; +use toolchain::Tool; use crate::{cfg_flag::CfgFlag, utf8_stdout, ManifestPath, Sysroot}; @@ -69,8 +68,8 @@ fn get_rust_cfgs( ) -> anyhow::Result { let sysroot = match config { RustcCfgConfig::Cargo(sysroot, cargo_toml) => { - let mut cmd = Command::new(toolchain::Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Cargo); + cmd.envs(extra_env); cmd.current_dir(cargo_toml.parent()) .args(["rustc", "-Z", "unstable-options", "--print", "cfg"]) @@ -90,7 +89,7 @@ fn get_rust_cfgs( RustcCfgConfig::Rustc(sysroot) => sysroot, }; - let mut cmd = Sysroot::rustc(sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Rustc); cmd.envs(extra_env); cmd.args(["--print", "cfg", "-O"]); if let Some(target) = target { diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs index a486a38510a8c..3127bae8b0c9e 100644 --- a/crates/project-model/src/sysroot.rs +++ b/crates/project-model/src/sysroot.rs @@ -193,23 +193,26 @@ impl Sysroot { Ok(Sysroot::load(sysroot_dir, Some(sysroot_src_dir), metadata)) } - pub fn set_rustup_toolchain_env(cmd: &mut Command, sysroot: Option<&Self>) { - if let Some(sysroot) = sysroot { - cmd.env("RUSTUP_TOOLCHAIN", AsRef::::as_ref(&sysroot.root)); - } - } - - /// Returns a `Command` that is configured to run `rustc` from the sysroot if it exists, - /// otherwise returns what [toolchain::Tool::Rustc] returns. - pub fn rustc(sysroot: Option<&Self>) -> Command { - let mut cmd = Command::new(match sysroot { + /// Returns a command to run a tool preferring the cargo proxies if the sysroot exists. + pub fn tool(sysroot: Option<&Self>, tool: Tool) -> Command { + match sysroot { Some(sysroot) => { - toolchain::Tool::Rustc.path_in_or_discover(sysroot.root.join("bin").as_ref()) + // special case rustc, we can look that up directly in the sysroot's bin folder + // as it should never invoke another cargo binary + if let Tool::Rustc = tool { + if let Some(path) = + probe_for_binary(sysroot.root.join("bin").join(Tool::Rustc.name()).into()) + { + return Command::new(path); + } + } + + let mut cmd = Command::new(tool.prefer_proxy()); + cmd.env("RUSTUP_TOOLCHAIN", AsRef::::as_ref(&sysroot.root)); + cmd } - None => toolchain::Tool::Rustc.path(), - }); - Self::set_rustup_toolchain_env(&mut cmd, sysroot); - cmd + _ => Command::new(tool.path()), + } } pub fn discover_proc_macro_srv(&self) -> anyhow::Result { diff --git a/crates/project-model/src/target_data_layout.rs b/crates/project-model/src/target_data_layout.rs index df77541762d9e..4e810a0232ea9 100644 --- a/crates/project-model/src/target_data_layout.rs +++ b/crates/project-model/src/target_data_layout.rs @@ -1,7 +1,7 @@ //! Runs `rustc --print target-spec-json` to get the target_data_layout. -use std::process::Command; use rustc_hash::FxHashMap; +use toolchain::Tool; use crate::{utf8_stdout, ManifestPath, Sysroot}; @@ -28,8 +28,7 @@ pub fn get( }; let sysroot = match config { RustcDataLayoutConfig::Cargo(sysroot, cargo_toml) => { - let mut cmd = Command::new(toolchain::Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Cargo); cmd.envs(extra_env); cmd.current_dir(cargo_toml.parent()) .args([ @@ -57,7 +56,7 @@ pub fn get( RustcDataLayoutConfig::Rustc(sysroot) => sysroot, }; - let mut cmd = Sysroot::rustc(sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Rustc); cmd.envs(extra_env) .args(["-Z", "unstable-options", "--print", "target-spec-json"]) .env("RUSTC_BOOTSTRAP", "1"); diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index adf15d45fc626..1a138b17bad41 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -2,7 +2,7 @@ //! metadata` or `rust-project.json`) into representation stored in the salsa //! database -- `CrateGraph`. -use std::{collections::VecDeque, fmt, fs, iter, process::Command, str::FromStr, sync}; +use std::{collections::VecDeque, fmt, fs, iter, str::FromStr, sync}; use anyhow::{format_err, Context}; use base_db::{ @@ -172,11 +172,13 @@ impl fmt::Debug for ProjectWorkspace { fn get_toolchain_version( current_dir: &AbsPath, - mut cmd: Command, + sysroot: Option<&Sysroot>, + tool: Tool, extra_env: &FxHashMap, prefix: &str, ) -> Result, anyhow::Error> { let cargo_version = utf8_stdout({ + let mut cmd = Sysroot::tool(sysroot, tool); cmd.envs(extra_env); cmd.arg("--version").current_dir(current_dir); cmd @@ -297,11 +299,8 @@ impl ProjectWorkspace { let toolchain = get_toolchain_version( cargo_toml.parent(), - { - let mut cmd = Command::new(toolchain::Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot_ref); - cmd - }, + sysroot_ref, + Tool::Cargo, &config.extra_env, "cargo ", )?; @@ -386,7 +385,8 @@ impl ProjectWorkspace { let data_layout_config = RustcDataLayoutConfig::Rustc(sysroot_ref); let toolchain = match get_toolchain_version( project_json.path(), - Sysroot::rustc(sysroot_ref), + sysroot_ref, + Tool::Rustc, extra_env, "rustc ", ) { @@ -433,18 +433,15 @@ impl ProjectWorkspace { }; let sysroot_ref = sysroot.as_ref().ok(); - let toolchain = match get_toolchain_version( - dir, - Sysroot::rustc(sysroot_ref), - &config.extra_env, - "rustc ", - ) { - Ok(it) => it, - Err(e) => { - tracing::error!("{e}"); - None - } - }; + let toolchain = + match get_toolchain_version(dir, sysroot_ref, Tool::Rustc, &config.extra_env, "rustc ") + { + Ok(it) => it, + Err(e) => { + tracing::error!("{e}"); + None + } + }; let rustc_cfg = rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(sysroot_ref)); let data_layout = target_data_layout::get( @@ -1573,8 +1570,7 @@ fn cargo_config_env( extra_env: &FxHashMap, sysroot: Option<&Sysroot>, ) -> FxHashMap { - let mut cargo_config = Command::new(Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot); + let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo); cargo_config.envs(extra_env); cargo_config .current_dir(cargo_toml.parent()) diff --git a/crates/toolchain/src/lib.rs b/crates/toolchain/src/lib.rs index e65a060672eec..a77fed585af77 100644 --- a/crates/toolchain/src/lib.rs +++ b/crates/toolchain/src/lib.rs @@ -58,10 +58,6 @@ impl Tool { probe_for_binary(path.join(self.name())) } - pub fn path_in_or_discover(self, path: &Path) -> PathBuf { - probe_for_binary(path.join(self.name())).unwrap_or_else(|| self.path()) - } - pub fn name(self) -> &'static str { match self { Tool::Cargo => "cargo", From b20e46737301157a484518e2a56adaf996fe77c8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 11:06:36 +0100 Subject: [PATCH 32/69] internal: Adjust a few things for trait assoc item hovers --- crates/hir-ty/src/display.rs | 10 +- crates/hir/src/display.rs | 49 ++- crates/ide/src/hover.rs | 2 +- crates/ide/src/hover/render.rs | 2 +- crates/ide/src/hover/tests.rs | 622 ++++++++++++++++------------- crates/ide/src/static_index.rs | 2 +- crates/rust-analyzer/src/config.rs | 2 +- 7 files changed, 381 insertions(+), 308 deletions(-) diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 328dea87ac112..fe191a456a9a1 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -63,7 +63,7 @@ pub struct HirFormatter<'a> { buf: String, curr_size: usize, pub(crate) max_size: Option, - pub limited_size: Option, + pub entity_limit: Option, omit_verbose_types: bool, closure_style: ClosureStyle, display_target: DisplayTarget, @@ -148,8 +148,8 @@ pub trait HirDisplay { } } - /// Returns a `Display`able type that is human-readable and tries to limit the item inside this type. - /// Use this for showing types which may contain two many item when user hover on, like `trait`, `struct`, `enum` + /// Returns a `Display`able type that is human-readable and tries to limit the number of items inside. + /// Use this for showing definitions which may contain too many items, like `trait`, `struct`, `enum` fn display_limited<'a>( &'a self, db: &'a dyn HirDatabase, @@ -184,7 +184,7 @@ pub trait HirDisplay { buf: String::with_capacity(20), curr_size: 0, max_size: None, - limited_size: None, + entity_limit: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, display_target: DisplayTarget::SourceCode { module_id, allow_opaque }, @@ -352,7 +352,7 @@ impl HirDisplayWrapper<'_, T> { buf: String::with_capacity(20), curr_size: 0, max_size: self.max_size, - limited_size: self.limited_size, + entity_limit: self.limited_size, omit_verbose_types: self.omit_verbose_types, display_target: self.display_target, closure_style: self.closure_style, diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 20ba72d998c31..cdc0db8653c11 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -596,33 +596,32 @@ impl HirDisplay for Trait { write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; - let assoc_items = self.items(f.db); - let assoc_items_size = assoc_items.len(); - let limited_size = f.limited_size.unwrap_or(assoc_items_size); - if assoc_items.is_empty() { - f.write_str(" {}")?; - } else { - f.write_str(" {\n")?; - for (index, item) in assoc_items.iter().enumerate() { - f.write_str(" ")?; - match item { - AssocItem::Function(func) => { - func.hir_fmt(f)?; - } - AssocItem::Const(cst) => { - cst.hir_fmt(f)?; - } - AssocItem::TypeAlias(type_alias) => { - type_alias.hir_fmt(f)?; - } - }; - f.write_str(",\n")?; - if index + 1 == limited_size && index + 1 != assoc_items_size { - f.write_str(" ...\n")?; - break; + if let Some(limit) = f.entity_limit { + let assoc_items = self.items(f.db); + let count = assoc_items.len().min(limit); + if count == 0 { + if assoc_items.is_empty() { + f.write_str(" {}")?; + } else { + f.write_str(" { /* … */ }")?; } + } else { + f.write_str(" {\n")?; + for item in &assoc_items[..count] { + f.write_str(" ")?; + match item { + AssocItem::Function(func) => func.hir_fmt(f), + AssocItem::Const(cst) => cst.hir_fmt(f), + AssocItem::TypeAlias(type_alias) => type_alias.hir_fmt(f), + }?; + f.write_str(";\n")?; + } + + if assoc_items.len() > count { + f.write_str(" /* … */\n")?; + } + f.write_str("}")?; } - f.write_str("}")?; } Ok(()) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index b6877c5e8ce95..8f4c629b58130 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -32,7 +32,7 @@ pub struct HoverConfig { pub documentation: bool, pub keywords: bool, pub format: HoverDocFormat, - pub trait_assoc_items_size: Option, + pub max_trait_assoc_items_count: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index f528bd512ccee..d1d039534d51e 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -408,7 +408,7 @@ pub(super) fn definition( let mod_path = definition_mod_path(db, &def); let label = match def { Definition::Trait(trait_) => { - trait_.display_limited(db, config.trait_assoc_items_size).to_string() + trait_.display_limited(db, config.max_trait_assoc_items_count).to_string() } _ => def.label(db), }; diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index cec1375271e62..c3cd6513dc616 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -17,7 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { documentation: true, format: HoverDocFormat::Markdown, keywords: true, - trait_assoc_items_size: None, + max_trait_assoc_items_count: None, }; fn check_hover_no_result(ra_fixture: &str) { @@ -49,6 +49,28 @@ fn check(ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual) } +#[track_caller] +fn check_assoc_count(count: usize, ra_fixture: &str, expect: Expect) { + let (analysis, position) = fixture::position(ra_fixture); + let hover = analysis + .hover( + &HoverConfig { + links_in_hover: true, + max_trait_assoc_items_count: Some(count), + ..HOVER_BASE_CONFIG + }, + FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) }, + ) + .unwrap() + .unwrap(); + + let content = analysis.db.file_text(position.file_id); + let hovered_element = &content[hover.range]; + + let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup); + expect.assert_eq(&actual) +} + fn check_hover_no_links(ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis @@ -412,7 +434,7 @@ fn main() { name: "FnOnce", kind: Trait, container_name: "function", - description: "pub trait FnOnce\nwhere\n Args: Tuple, {\n pub type Output,\n pub extern \"rust-call\" fn call_once(self, args: Args) -> Self::Output,\n}", + description: "pub trait FnOnce\nwhere\n Args: Tuple,", }, }, ], @@ -2673,26 +2695,26 @@ fn foo() -> impl Foo {} fn main() { let s$0t = foo(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -2707,39 +2729,39 @@ fn foo() -> impl Foo {} fn main() { let s$0t = foo(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..15, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..15, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - HoverGotoTypeData { - mod_path: "test::S", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 16..25, - focus_range: 23..24, - name: "S", - kind: Struct, - description: "struct S", - }, + }, + HoverGotoTypeData { + mod_path: "test::S", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 16..25, + focus_range: 23..24, + name: "S", + kind: Struct, + description: "struct S", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -2767,7 +2789,7 @@ fn main() { let s$0t = foo(); } focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar {}", + description: "trait Bar", }, }, HoverGotoTypeData { @@ -2780,7 +2802,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo {}", + description: "trait Foo", }, }, ], @@ -2817,7 +2839,7 @@ fn main() { let s$0t = foo(); } focus_range: 22..25, name: "Bar", kind: Trait, - description: "trait Bar {}", + description: "trait Bar", }, }, HoverGotoTypeData { @@ -2830,7 +2852,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo {}", + description: "trait Foo", }, }, HoverGotoTypeData { @@ -2874,26 +2896,26 @@ trait Foo {} fn foo(ar$0g: &impl Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -2921,7 +2943,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar {}", + description: "trait Bar", }, }, HoverGotoTypeData { @@ -2934,7 +2956,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo {}", + description: "trait Foo", }, }, HoverGotoTypeData { @@ -2989,7 +3011,7 @@ pub mod future { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future {}", + description: "pub trait Future", }, }, HoverGotoTypeData { @@ -3021,39 +3043,39 @@ struct S {} fn foo(ar$0g: &impl Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..15, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..15, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - HoverGotoTypeData { - mod_path: "test::S", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 16..27, - focus_range: 23..24, - name: "S", - kind: Struct, - description: "struct S {}", - }, + }, + HoverGotoTypeData { + mod_path: "test::S", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 16..27, + focus_range: 23..24, + name: "S", + kind: Struct, + description: "struct S {}", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3071,39 +3093,39 @@ fn foo() -> B {} fn main() { let s$0t = foo(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::B", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 42..55, - focus_range: 49..50, - name: "B", - kind: Struct, - description: "struct B {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::B", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 42..55, + focus_range: 49..50, + name: "B", + kind: Struct, + description: "struct B {}", }, - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + }, + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3115,26 +3137,26 @@ trait Foo {} fn foo(ar$0g: &dyn Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3147,39 +3169,39 @@ struct S {} fn foo(ar$0g: &dyn Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..15, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..15, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - HoverGotoTypeData { - mod_path: "test::S", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 16..27, - focus_range: 23..24, - name: "S", - kind: Struct, - description: "struct S {}", - }, + }, + HoverGotoTypeData { + mod_path: "test::S", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 16..27, + focus_range: 23..24, + name: "S", + kind: Struct, + description: "struct S {}", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3221,7 +3243,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 28..36, name: "DynTrait", kind: Trait, - description: "trait DynTrait {}", + description: "trait DynTrait", }, }, HoverGotoTypeData { @@ -3234,7 +3256,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 6..15, name: "ImplTrait", kind: Trait, - description: "trait ImplTrait {}", + description: "trait ImplTrait", }, }, HoverGotoTypeData { @@ -3276,26 +3298,26 @@ fn test() -> impl Foo { S {} } fn main() { let s$0t = test().get(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..62, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {\n type Item,\n fn get(self) -> Self::Item,\n}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..62, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3341,26 +3363,26 @@ trait Foo {} fn foo(t: T$0){} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -6330,71 +6352,96 @@ impl T for () { #[test] fn hover_trait_show_assoc_items() { - check( + check_assoc_count( + 0, r#" trait T {} impl T$0 for () {} "#, expect![[r#" - *T* + *T* - ```rust - test - ``` + ```rust + test + ``` - ```rust - trait T {} - ``` + ```rust + trait T {} + ``` "#]], ); - check( + check_assoc_count( + 1, + r#" +trait T {} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T {} + ``` + "#]], + ); + + check_assoc_count( + 0, r#" trait T { fn func() {} + const FLAG: i32 = 34; + type Bar; } impl T$0 for () {} "#, expect![[r#" - *T* + *T* - ```rust - test - ``` + ```rust + test + ``` - ```rust - trait T { - fn func(), - } - ``` + ```rust + trait T { /* … */ } + ``` "#]], ); - check( + check_assoc_count( + 2, r#" trait T { fn func() {} const FLAG: i32 = 34; + type Bar; } impl T$0 for () {} "#, expect![[r#" - *T* + *T* - ```rust - test - ``` + ```rust + test + ``` - ```rust - trait T { - fn func(), - const FLAG: i32, - } - ``` + ```rust + trait T { + fn func(); + const FLAG: i32; + /* … */ + } + ``` "#]], ); - check( + check_assoc_count( + 3, r#" trait T { fn func() {} @@ -6404,19 +6451,46 @@ trait T { impl T$0 for () {} "#, expect![[r#" - *T* + *T* - ```rust - test - ``` + ```rust + test + ``` - ```rust - trait T { - fn func(), - const FLAG: i32, - type Bar, - } - ``` + ```rust + trait T { + fn func(); + const FLAG: i32; + type Bar; + } + ``` + "#]], + ); + + check_assoc_count( + 4, + r#" +trait T { + fn func() {} + const FLAG: i32 = 34; + type Bar; +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(); + const FLAG: i32; + type Bar; + } + ``` "#]], ); } @@ -7532,7 +7606,7 @@ impl Iterator for S { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future {\n pub type Output,\n pub fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll,\n}", + description: "pub trait Future", }, }, HoverGotoTypeData { @@ -7546,7 +7620,7 @@ impl Iterator for S { name: "Iterator", kind: Trait, container_name: "iterator", - description: "pub trait Iterator {\n pub type Item,\n pub fn next(&mut self) -> Option,\n pub fn nth(&mut self, n: usize) -> Option,\n pub fn by_ref(&mut self) -> &mut Self\nwhere\n Self: Sized,,\n}", + description: "pub trait Iterator", }, }, HoverGotoTypeData { @@ -7559,7 +7633,7 @@ impl Iterator for S { focus_range: 49..56, name: "Notable", kind: Trait, - description: "trait Notable {}", + description: "trait Notable", }, }, HoverGotoTypeData { diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 0f19da0ac5fba..fe063081f7999 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -166,7 +166,7 @@ impl StaticIndex<'_> { documentation: true, keywords: true, format: crate::HoverDocFormat::Markdown, - trait_assoc_items_size: None, + max_trait_assoc_items_count: None, }; let tokens = tokens.filter(|token| { matches!( diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 21a106bc77091..ad3721a995484 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -1682,7 +1682,7 @@ impl Config { } }, keywords: self.data.hover_documentation_keywords_enable, - trait_assoc_items_size: self.data.hover_show_traitAssocItems, + max_trait_assoc_items_count: self.data.hover_show_traitAssocItems, } } From 8844640c6f28bc4459ed8c0b466a20ecf39baa07 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 11:41:46 +0100 Subject: [PATCH 33/69] fix: Put style lints behind disabled-by-default config --- crates/hir-ty/src/diagnostics/expr.rs | 19 ++++++- crates/hir/src/lib.rs | 49 ++++++++++++------- crates/ide-diagnostics/src/lib.rs | 4 +- .../rust-analyzer/src/cli/analysis_stats.rs | 1 + crates/rust-analyzer/src/config.rs | 3 ++ docs/user/generated_config.adoc | 5 ++ editors/code/package.json | 5 ++ 7 files changed, 66 insertions(+), 20 deletions(-) diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index 1a134e6d780e4..dfc0a25bf4654 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -60,12 +60,17 @@ pub enum BodyValidationDiagnostic { } impl BodyValidationDiagnostic { - pub fn collect(db: &dyn HirDatabase, owner: DefWithBodyId) -> Vec { + pub fn collect( + db: &dyn HirDatabase, + owner: DefWithBodyId, + validate_lints: bool, + ) -> Vec { let _p = tracing::span!(tracing::Level::INFO, "BodyValidationDiagnostic::collect").entered(); let infer = db.infer(owner); let body = db.body(owner); - let mut validator = ExprValidator { owner, body, infer, diagnostics: Vec::new() }; + let mut validator = + ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints }; validator.validate_body(db); validator.diagnostics } @@ -76,6 +81,7 @@ struct ExprValidator { body: Arc, infer: Arc, diagnostics: Vec, + validate_lints: bool, } impl ExprValidator { @@ -139,6 +145,9 @@ impl ExprValidator { expr: &Expr, filter_map_next_checker: &mut Option, ) { + if !self.validate_lints { + return; + } // Check that the number of arguments matches the number of parameters. if self.infer.expr_type_mismatches().next().is_some() { @@ -308,6 +317,9 @@ impl ExprValidator { } fn check_for_trailing_return(&mut self, body_expr: ExprId, body: &Body) { + if !self.validate_lints { + return; + } match &body.exprs[body_expr] { Expr::Block { statements, tail, .. } => { let last_stmt = tail.or_else(|| match statements.last()? { @@ -340,6 +352,9 @@ impl ExprValidator { } fn check_for_unnecessary_else(&mut self, id: ExprId, expr: &Expr, db: &dyn HirDatabase) { + if !self.validate_lints { + return; + } if let Expr::If { condition: _, then_branch, else_branch } = expr { if else_branch.is_none() { return; diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 1e16f78ca2d37..4872c47c31d03 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -365,7 +365,7 @@ impl ModuleDef { Some(name) } - pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec { + pub fn diagnostics(self, db: &dyn HirDatabase, style_lints: bool) -> Vec { let id = match self { ModuleDef::Adt(it) => match it { Adt::Struct(it) => it.id.into(), @@ -387,7 +387,7 @@ impl ModuleDef { match self.as_def_with_body() { Some(def) => { - def.diagnostics(db, &mut acc); + def.diagnostics(db, &mut acc, style_lints); } None => { for diag in hir_ty::diagnostics::incorrect_case(db, id) { @@ -541,7 +541,12 @@ impl Module { } /// Fills `acc` with the module's diagnostics. - pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec) { + pub fn diagnostics( + self, + db: &dyn HirDatabase, + acc: &mut Vec, + style_lints: bool, + ) { let name = self.name(db); let _p = tracing::span!(tracing::Level::INFO, "Module::diagnostics", ?name); let def_map = self.id.def_map(db.upcast()); @@ -558,9 +563,9 @@ impl Module { ModuleDef::Module(m) => { // Only add diagnostics from inline modules if def_map[m.id.local_id].origin.is_inline() { - m.diagnostics(db, acc) + m.diagnostics(db, acc, style_lints) } - acc.extend(def.diagnostics(db)) + acc.extend(def.diagnostics(db, style_lints)) } ModuleDef::Trait(t) => { for diag in db.trait_data_with_diagnostics(t.id).1.iter() { @@ -568,10 +573,10 @@ impl Module { } for item in t.items(db) { - item.diagnostics(db, acc); + item.diagnostics(db, acc, style_lints); } - acc.extend(def.diagnostics(db)) + acc.extend(def.diagnostics(db, style_lints)) } ModuleDef::Adt(adt) => { match adt { @@ -587,17 +592,17 @@ impl Module { } Adt::Enum(e) => { for v in e.variants(db) { - acc.extend(ModuleDef::Variant(v).diagnostics(db)); + acc.extend(ModuleDef::Variant(v).diagnostics(db, style_lints)); for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() { emit_def_diagnostic(db, acc, diag); } } } } - acc.extend(def.diagnostics(db)) + acc.extend(def.diagnostics(db, style_lints)) } ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m), - _ => acc.extend(def.diagnostics(db)), + _ => acc.extend(def.diagnostics(db, style_lints)), } } self.legacy_macros(db).into_iter().for_each(|m| emit_macro_def_diagnostics(db, acc, m)); @@ -738,7 +743,7 @@ impl Module { } for &item in &db.impl_data(impl_def.id).items { - AssocItem::from(item).diagnostics(db, acc); + AssocItem::from(item).diagnostics(db, acc, style_lints); } } } @@ -1616,14 +1621,19 @@ impl DefWithBody { } } - pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec) { + pub fn diagnostics( + self, + db: &dyn HirDatabase, + acc: &mut Vec, + style_lints: bool, + ) { db.unwind_if_cancelled(); let krate = self.module(db).id.krate(); let (body, source_map) = db.body_with_source_map(self.into()); for (_, def_map) in body.blocks(db.upcast()) { - Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc); + Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints); } for diag in source_map.diagnostics() { @@ -1784,7 +1794,7 @@ impl DefWithBody { } } - for diagnostic in BodyValidationDiagnostic::collect(db, self.into()) { + for diagnostic in BodyValidationDiagnostic::collect(db, self.into(), style_lints) { acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, &source_map)); } @@ -2897,13 +2907,18 @@ impl AssocItem { } } - pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec) { + pub fn diagnostics( + self, + db: &dyn HirDatabase, + acc: &mut Vec, + style_lints: bool, + ) { match self { AssocItem::Function(func) => { - DefWithBody::from(func).diagnostics(db, acc); + DefWithBody::from(func).diagnostics(db, acc, style_lints); } AssocItem::Const(const_) => { - DefWithBody::from(const_).diagnostics(db, acc); + DefWithBody::from(const_).diagnostics(db, acc, style_lints); } AssocItem::TypeAlias(type_alias) => { for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) { diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 9a7e1a2ae6d61..0df6f0e0373c8 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -227,6 +227,7 @@ pub struct DiagnosticsConfig { pub disable_experimental: bool, pub disabled: FxHashSet, pub expr_fill_default: ExprFillDefaultMode, + pub style_lints: bool, // FIXME: We may want to include a whole `AssistConfig` here pub insert_use: InsertUseConfig, pub prefer_no_std: bool, @@ -245,6 +246,7 @@ impl DiagnosticsConfig { disable_experimental: Default::default(), disabled: Default::default(), expr_fill_default: Default::default(), + style_lints: true, insert_use: InsertUseConfig { granularity: ImportGranularity::Preserve, enforce_granularity: false, @@ -324,7 +326,7 @@ pub fn diagnostics( let mut diags = Vec::new(); if let Some(m) = module { - m.diagnostics(db, &mut diags); + m.diagnostics(db, &mut diags, config.style_lints); } for diag in diags { diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 7e027c9f92844..ef184032bfb09 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -982,6 +982,7 @@ impl flags::AnalysisStats { }, prefer_no_std: false, prefer_prelude: true, + style_lints: false, }, ide::AssistResolveStrategy::All, file_id, diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 21a106bc77091..906b000829e29 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -311,6 +311,8 @@ config_data! { /// Map of prefixes to be substituted when parsing diagnostic file paths. /// This should be the reverse mapping of what is passed to `rustc` as `--remap-path-prefix`. diagnostics_remapPrefix: FxHashMap = "{}", + /// Whether to run additional style lints. + diagnostics_styleLints_enable: bool = "false", /// List of warnings that should be displayed with hint severity. /// /// The warnings will be indicated by faded text or three dots in code @@ -1162,6 +1164,7 @@ impl Config { insert_use: self.insert_use_config(), prefer_no_std: self.data.imports_preferNoStd, prefer_prelude: self.data.imports_preferPrelude, + style_lints: self.data.diagnostics_styleLints_enable, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 0fb275961bef0..5e782b7831111 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -386,6 +386,11 @@ have more false positives than usual. Map of prefixes to be substituted when parsing diagnostic file paths. This should be the reverse mapping of what is passed to `rustc` as `--remap-path-prefix`. -- +[[rust-analyzer.diagnostics.styleLints.enable]]rust-analyzer.diagnostics.styleLints.enable (default: `false`):: ++ +-- +Whether to run additional style lints. +-- [[rust-analyzer.diagnostics.warningsAsHint]]rust-analyzer.diagnostics.warningsAsHint (default: `[]`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 3a276409fb6be..16d3dcbab6fef 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -948,6 +948,11 @@ "default": {}, "type": "object" }, + "rust-analyzer.diagnostics.styleLints.enable": { + "markdownDescription": "Whether to run additional style lints.", + "default": false, + "type": "boolean" + }, "rust-analyzer.diagnostics.warningsAsHint": { "markdownDescription": "List of warnings that should be displayed with hint severity.\n\nThe warnings will be indicated by faded text or three dots in code\nand will not show up in the `Problems Panel`.", "default": [], From 00a6cc06642d6dc0cf27bd0d3cf7dae20cd28030 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 12:00:21 +0100 Subject: [PATCH 34/69] Update Cargo.lock --- Cargo.lock | 616 +++++++++--------- Cargo.toml | 20 +- crates/ide-db/src/prime_caches.rs | 2 +- crates/ide/Cargo.toml | 10 +- crates/proc-macro-api/Cargo.toml | 8 +- crates/proc-macro-srv/Cargo.toml | 8 +- crates/salsa/Cargo.toml | 1 - crates/salsa/src/runtime.rs | 2 +- crates/salsa/tests/cycles.rs | 1 - .../parallel/parallel_cycle_all_recover.rs | 1 - .../parallel/parallel_cycle_mid_recover.rs | 1 - .../parallel/parallel_cycle_none_recover.rs | 1 - .../parallel/parallel_cycle_one_recovers.rs | 1 - 13 files changed, 332 insertions(+), 340 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3667dec23a6f6..9c26f6648dd1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "arbitrary" @@ -52,16 +52,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", "cfg-if", "libc", - "miniz_oxide 0.6.2", - "object 0.30.4", + "miniz_oxide", + "object 0.32.2", "rustc-demangle", ] @@ -90,30 +90,30 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "camino" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" dependencies = [ "serde", ] @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723" [[package]] name = "cfg" @@ -176,7 +176,7 @@ version = "0.96.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff550c2cdd63ff74394214dce03d06386928a641c0f08837535f04af573a966d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "chalk-derive", "lazy_static", ] @@ -216,7 +216,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5080df6b0f0ecb76cab30808f00d937ba725cebe266a3da8cd89dff92f2a9916" dependencies = [ - "nix 0.26.2", + "nix 0.26.4", "winapi", ] @@ -239,64 +239,55 @@ checksum = "0d48d8f76bd9331f19fe2aaf3821a9f9fb32c3963e1e3d6ce82a8c09cef7444a" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "ctrlc" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" +checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" dependencies = [ "nix 0.27.1", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -312,6 +303,15 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derive_arbitrary" version = "1.3.2" @@ -343,9 +343,9 @@ checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "ena" @@ -356,20 +356,11 @@ dependencies = [ "log", ] -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "log", -] - [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "expect-test" @@ -383,14 +374,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", - "windows-sys", + "redox_syscall", + "windows-sys 0.52.0", ] [[package]] @@ -401,12 +392,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -427,9 +418,9 @@ dependencies = [ [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -462,9 +453,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "hashbrown" @@ -480,12 +471,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hir" @@ -516,7 +504,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.4.1", + "bitflags 2.4.2", "cfg", "cov-mark", "dashmap", @@ -579,7 +567,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.4.1", + "bitflags 2.4.2", "chalk-derive", "chalk-ir", "chalk-recursive", @@ -600,7 +588,7 @@ dependencies = [ "oorandom", "project-model", "ra-ap-rustc_abi", - "ra-ap-rustc_index 0.35.0", + "ra-ap-rustc_index", "ra-ap-rustc_pattern_analysis", "rustc-hash", "scoped-tls", @@ -618,11 +606,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -773,9 +761,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -783,9 +771,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown", @@ -823,18 +811,18 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jod-thread" @@ -844,9 +832,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "kqueue" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" dependencies = [ "kqueue-sys", "libc", @@ -854,9 +842,9 @@ dependencies = [ [[package]] name = "kqueue-sys" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" dependencies = [ "bitflags 1.3.2", "libc", @@ -880,25 +868,25 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" +checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164" dependencies = [ "cfg-if", - "windows-sys", + "windows-targets 0.52.4", ] [[package]] name = "libmimalloc-sys" -version = "0.1.33" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e" +checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664" dependencies = [ "cc", "libc", @@ -953,9 +941,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -963,9 +951,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lsp-server" @@ -1046,27 +1034,18 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98" +checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c" dependencies = [ "libmimalloc-sys", ] [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -1080,7 +1059,7 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1089,19 +1068,18 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "359f76430b20a79f9e20e115b3428614e654f04fab314482fc0fda0ebd3c6044" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "nix" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", - "static_assertions", ] [[package]] @@ -1110,7 +1088,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cfg-if", "libc", ] @@ -1127,7 +1105,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "crossbeam-channel", "filetime", "fsevent-sys", @@ -1137,7 +1115,7 @@ dependencies = [ "log", "mio", "walkdir", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1146,14 +1124,20 @@ version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", @@ -1161,27 +1145,27 @@ dependencies = [ [[package]] name = "object" -version = "0.30.4" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "object" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" @@ -1207,9 +1191,9 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -1227,9 +1211,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "paths" @@ -1237,9 +1221,9 @@ version = "0.0.0" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "perf-event" @@ -1272,9 +1256,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" @@ -1290,7 +1280,7 @@ dependencies = [ "indexmap", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "memmap2", - "object 0.32.0", + "object 0.33.0", "paths", "rustc-hash", "serde", @@ -1313,7 +1303,7 @@ dependencies = [ "libloading", "mbe", "memmap2", - "object 0.32.0", + "object 0.33.0", "paths", "proc-macro-api", "proc-macro-test", @@ -1341,9 +1331,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -1407,11 +1397,11 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "memchr", "unicase", ] @@ -1427,35 +1417,24 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "ra-ap-rustc_abi" -version = "0.35.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0baa423a2c2bfd6e4bd40e7215f7ddebd12a649ce0b65078a38b91068895aa" +checksum = "2548746ce549476a7aa982099dfe5139f939099d83077b3393baf5e920292f64" dependencies = [ - "bitflags 2.4.1", - "ra-ap-rustc_index 0.35.0", + "bitflags 2.4.2", + "ra-ap-rustc_index", "tracing", ] -[[package]] -name = "ra-ap-rustc_index" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322b751895cc4a0a2ee0c6ab36ec80bc8abf5f8d76254c482f96f03c27c92ebe" -dependencies = [ - "arrayvec", - "ra-ap-rustc_index_macros 0.35.0", - "smallvec", -] - [[package]] name = "ra-ap-rustc_index" version = "0.40.0" @@ -1463,22 +1442,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "371db64f1be25aae96650b5528c76066ac325f0fe23efec0aab1179d75eea5c3" dependencies = [ "arrayvec", - "ra-ap-rustc_index_macros 0.40.0", + "ra-ap-rustc_index_macros", "smallvec", ] -[[package]] -name = "ra-ap-rustc_index_macros" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054e25eac52f0506c1309ca4317c11ad4925d7b99eb897f71aa7c3cbafb46c2b" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "ra-ap-rustc_index_macros" version = "0.40.0" @@ -1493,9 +1460,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.35.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8da0fa51a1a97ba4296a1c78fa454815a153b472e2546b6338a0902ad59e015" +checksum = "4f346eb8d73041fd48280373f929803c4650771da631b1d076d5ed0ca4216b48" dependencies = [ "unicode-properties", "unicode-xid", @@ -1503,11 +1470,11 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.35.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3851f930a54adcb76889983dcd5c00a0c4e206e190e1384dbc00d49b82dfb45e" +checksum = "85f8a94cf47d86b93e7c2440de4308de74e1d5cb71ed3a9df7dcde2550742e6e" dependencies = [ - "ra-ap-rustc_index 0.35.0", + "ra-ap-rustc_index", "ra-ap-rustc_lexer", ] @@ -1517,7 +1484,7 @@ version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9cb49490fadb58e6b8cc825f73157a33730495bfd5c6e9eef067a4b50ad1836" dependencies = [ - "ra-ap-rustc_index 0.40.0", + "ra-ap-rustc_index", "rustc-hash", "rustc_apfloat", "smallvec", @@ -1556,9 +1523,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" dependencies = [ "either", "rayon-core", @@ -1566,23 +1533,14 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -1685,9 +1643,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "salsa" @@ -1705,7 +1663,6 @@ dependencies = [ "rustc-hash", "salsa-macros", "smallvec", - "test-log", "tracing", "triomphe", ] @@ -1746,33 +1703,33 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.17" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", @@ -1781,9 +1738,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "indexmap", "itoa", @@ -1793,9 +1750,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", @@ -1804,18 +1761,18 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "smallvec" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "smol_str" @@ -1828,9 +1785,9 @@ dependencies = [ [[package]] name = "snap" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "sourcegen" @@ -1858,12 +1815,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "stdx" version = "0.0.0" @@ -1880,9 +1831,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -1891,14 +1842,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", "syn", - "unicode-xid", ] [[package]] @@ -1942,27 +1892,6 @@ dependencies = [ "tt", ] -[[package]] -name = "test-log" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6159ab4116165c99fc88cce31f99fa2c9dbe08d3691cb38da02fc3b45f357d2b" -dependencies = [ - "env_logger", - "test-log-macros", -] - -[[package]] -name = "test-log-macros" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba277e77219e9eea169e8508942db1bf5d8a41ff2db9b20aab5a5aadc9fa25d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "test-utils" version = "0.0.0" @@ -1991,18 +1920,18 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", @@ -2011,9 +1940,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -2021,9 +1950,9 @@ dependencies = [ [[package]] name = "tikv-jemalloc-ctl" -version = "0.5.0" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37706572f4b151dff7a0146e040804e9c26fe3a3118591112f05cf12a4216c1" +checksum = "619bfed27d807b54f7f776b9430d4f8060e66ee138a28632ca898584d462c31c" dependencies = [ "libc", "paste", @@ -2032,9 +1961,9 @@ dependencies = [ [[package]] name = "tikv-jemalloc-sys" -version = "0.5.3+5.3.0-patched" +version = "0.5.4+5.3.0-patched" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a678df20055b43e57ef8cddde41cdfda9a3c1a060b67f4c5836dfb1d78543ba8" +checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1" dependencies = [ "cc", "libc", @@ -2042,9 +1971,9 @@ dependencies = [ [[package]] name = "tikv-jemallocator" -version = "0.5.0" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20612db8a13a6c06d57ec83953694185a367e16945f66565e8028d2c0bd76979" +checksum = "965fe0c26be5c56c94e38ba547249074803efd52adfb66de62107d95aab3eaca" dependencies = [ "libc", "tikv-jemalloc-sys", @@ -2052,19 +1981,22 @@ dependencies = [ [[package]] name = "time" -version = "0.3.22" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ + "deranged", + "num-conv", + "powerfmt", "serde", "time-core", ] [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "tinyvec" @@ -2189,39 +2121,39 @@ checksum = "a3e5df347f0bf3ec1d670aad6ca5c6a1859cd9ea61d2113125794654ccced68f" [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f91c8b21fbbaa18853c3d0801c78f4fc94cdb976699bb03e832e75f7fd22f0" +checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" [[package]] name = "unicode-xid" @@ -2231,9 +2163,9 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "url" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -2280,9 +2212,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -2312,9 +2244,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -2331,86 +2263,152 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "write-json" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3" +checksum = "23f6174b2566cc4a74f95e1367ec343e7fa80c93cc8087f5c4a3d6a1088b2118" [[package]] name = "xflags" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4554b580522d0ca238369c16b8f6ce34524d61dafe7244993754bbd05f2c2ea" +checksum = "7d9e15fbb3de55454b0106e314b28e671279009b363e6f1d8e39fdc3bf048944" dependencies = [ "xflags-macros", ] [[package]] name = "xflags-macros" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58e7b3ca8977093aae6b87b6a7730216fc4c53a6530bab5c43a783cd810c1a8" +checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155" [[package]] name = "xshell" diff --git a/Cargo.toml b/Cargo.toml index e68613c6d3840..e8e82914c7c4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,10 +84,10 @@ tt = { path = "./crates/tt", version = "0.0.0" } vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } -ra-ap-rustc_lexer = { version = "0.35.0", default-features = false } -ra-ap-rustc_parse_format = { version = "0.35.0", default-features = false } -ra-ap-rustc_index = { version = "0.35.0", default-features = false } -ra-ap-rustc_abi = { version = "0.35.0", default-features = false } +ra-ap-rustc_lexer = { version = "0.40.0", default-features = false } +ra-ap-rustc_parse_format = { version = "0.40.0", default-features = false } +ra-ap-rustc_index = { version = "0.40.0", default-features = false } +ra-ap-rustc_abi = { version = "0.40.0", default-features = false } ra-ap-rustc_pattern_analysis = { version = "0.40.0", default-features = false } # local crates that aren't published to crates.io. These should not have versions. @@ -108,6 +108,7 @@ cargo_metadata = "0.18.1" command-group = "2.0.1" crossbeam-channel = "0.5.8" dissimilar = "1.0.7" +dot = "0.1.4" either = "1.9.0" expect-test = "1.4.0" hashbrown = { version = "0.14", features = [ @@ -117,6 +118,16 @@ indexmap = "2.1.0" itertools = "0.12.0" libc = "0.2.150" nohash-hasher = "0.2.0" +oorandom = "11.1.3" +object = { version = "0.33.0", default-features = false, features = [ + "std", + "read_core", + "elf", + "macho", + "pe", +] } +pulldown-cmark-to-cmark = "10.0.4" +pulldown-cmark = { version = "0.9.0", default-features = false } rayon = "1.8.0" rustc-hash = "1.1.0" semver = "1.0.14" @@ -137,6 +148,7 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features = "tracing-log", ] } triomphe = { version = "0.1.10", default-features = false, features = ["std"] } +url = "2.3.1" xshell = "0.2.5" diff --git a/crates/ide-db/src/prime_caches.rs b/crates/ide-db/src/prime_caches.rs index ef15f585fa2db..024e8f6ae39d2 100644 --- a/crates/ide-db/src/prime_caches.rs +++ b/crates/ide-db/src/prime_caches.rs @@ -129,7 +129,7 @@ pub fn parallel_prime_caches( crates_currently_indexing.insert(crate_id, crate_name); } ParallelPrimeCacheWorkerProgress::EndCrate { crate_id } => { - crates_currently_indexing.remove(&crate_id); + crates_currently_indexing.swap_remove(&crate_id); crates_to_prime.mark_done(crate_id); crates_done += 1; } diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml index eab3925aab65c..006fd222c6162 100644 --- a/crates/ide/Cargo.toml +++ b/crates/ide/Cargo.toml @@ -17,11 +17,11 @@ arrayvec.workspace = true either.workspace = true itertools.workspace = true tracing.workspace = true -oorandom = "11.1.3" -pulldown-cmark-to-cmark = "10.0.4" -pulldown-cmark = { version = "0.9.1", default-features = false } -url = "2.3.1" -dot = "0.1.4" +oorandom.workspace = true +pulldown-cmark-to-cmark.workspace = true +pulldown-cmark.workspace = true +url.workspace = true +dot.workspace = true smallvec.workspace = true triomphe.workspace = true nohash-hasher.workspace = true diff --git a/crates/proc-macro-api/Cargo.toml b/crates/proc-macro-api/Cargo.toml index e98d70776c95d..978ad155609d5 100644 --- a/crates/proc-macro-api/Cargo.toml +++ b/crates/proc-macro-api/Cargo.toml @@ -12,13 +12,7 @@ rust-version.workspace = true doctest = false [dependencies] -object = { version = "0.32.0", default-features = false, features = [ - "std", - "read_core", - "elf", - "macho", - "pe", -] } +object.workspace = true serde.workspace = true serde_json = { workspace = true, features = ["unbounded_depth"] } tracing.workspace = true diff --git a/crates/proc-macro-srv/Cargo.toml b/crates/proc-macro-srv/Cargo.toml index bd7a31654584f..f8db1c6a30b49 100644 --- a/crates/proc-macro-srv/Cargo.toml +++ b/crates/proc-macro-srv/Cargo.toml @@ -12,13 +12,7 @@ rust-version.workspace = true doctest = false [dependencies] -object = { version = "0.32.0", default-features = false, features = [ - "std", - "read_core", - "elf", - "macho", - "pe", -] } +object.workspace = true libloading = "0.8.0" memmap2 = "0.5.4" diff --git a/crates/salsa/Cargo.toml b/crates/salsa/Cargo.toml index 9eec21f6a15ff..0d3e1197b5c67 100644 --- a/crates/salsa/Cargo.toml +++ b/crates/salsa/Cargo.toml @@ -28,7 +28,6 @@ salsa-macros = { version = "0.0.0", path = "salsa-macros" } [dev-dependencies] linked-hash-map = "0.5.6" rand = "0.8.5" -test-log = "0.2.14" expect-test = "1.4.0" dissimilar = "1.0.7" diff --git a/crates/salsa/src/runtime.rs b/crates/salsa/src/runtime.rs index a7d5a2457823f..e11cabfe11edc 100644 --- a/crates/salsa/src/runtime.rs +++ b/crates/salsa/src/runtime.rs @@ -595,7 +595,7 @@ impl ActiveQuery { fn remove_cycle_participants(&mut self, cycle: &Cycle) { if let Some(my_dependencies) = &mut self.dependencies { for p in cycle.participant_keys() { - my_dependencies.remove(&p); + my_dependencies.swap_remove(&p); } } } diff --git a/crates/salsa/tests/cycles.rs b/crates/salsa/tests/cycles.rs index 00ca5332440ef..2be167bd8d3b5 100644 --- a/crates/salsa/tests/cycles.rs +++ b/crates/salsa/tests/cycles.rs @@ -2,7 +2,6 @@ use std::panic::UnwindSafe; use expect_test::expect; use salsa::{Durability, ParallelDatabase, Snapshot}; -use test_log::test; // Axes: // diff --git a/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs b/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs index cee51b4db75e6..a13ae3418f20b 100644 --- a/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs +++ b/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs @@ -4,7 +4,6 @@ use crate::setup::{Knobs, ParDatabaseImpl}; use salsa::ParallelDatabase; -use test_log::test; // Recover cycle test: // diff --git a/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs b/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs index f78c05c5593c8..971fe7ab12079 100644 --- a/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs +++ b/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs @@ -4,7 +4,6 @@ use crate::setup::{Knobs, ParDatabaseImpl}; use salsa::ParallelDatabase; -use test_log::test; // Recover cycle test: // diff --git a/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs b/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs index 35fe3791182ea..e94982f513c52 100644 --- a/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs +++ b/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs @@ -5,7 +5,6 @@ use crate::setup::{Knobs, ParDatabaseImpl}; use expect_test::expect; use salsa::ParallelDatabase; -use test_log::test; #[test] fn parallel_cycle_none_recover() { diff --git a/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs b/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs index 7d3944714aef2..025fbf37477f6 100644 --- a/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs +++ b/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs @@ -4,7 +4,6 @@ use crate::setup::{Knobs, ParDatabaseImpl}; use salsa::ParallelDatabase; -use test_log::test; // Recover cycle test: // From ece18fecfabdc3583a3f38436682296e652161a2 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 5 Mar 2024 19:29:49 +0800 Subject: [PATCH 35/69] fix: resolve sub-patterns inside range pattern --- crates/hir-def/src/body/lower.rs | 12 +++--------- crates/hir-def/src/body/pretty.rs | 2 +- crates/hir-def/src/hir.rs | 2 +- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index c9300898b386c..18a6c5c2cdc2b 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -1413,16 +1413,10 @@ impl ExprCollector<'_> { ast::Pat::LiteralPat(it) => { Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0))) } - ast::Pat::IdentPat(p) => { - let name = - p.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); - Some(Box::new(LiteralOrConst::Const(name.into()))) + pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => { + let subpat = self.collect_pat(pat.clone(), binding_list); + Some(Box::new(LiteralOrConst::Const(subpat))) } - ast::Pat::PathPat(p) => p - .path() - .and_then(|path| self.expander.parse_path(self.db, path)) - .map(LiteralOrConst::Const) - .map(Box::new), _ => None, }) }; diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs index cd14f7b855a81..b2aab55a6a89a 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -635,7 +635,7 @@ impl Printer<'_> { fn print_literal_or_const(&mut self, literal_or_const: &LiteralOrConst) { match literal_or_const { LiteralOrConst::Literal(l) => self.print_literal(l), - LiteralOrConst::Const(c) => self.print_path(c), + LiteralOrConst::Const(c) => self.print_pat(*c), } } diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index 34b2910b4f5e5..ac0caaf0dc898 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -101,7 +101,7 @@ pub enum Literal { /// Used in range patterns. pub enum LiteralOrConst { Literal(Literal), - Const(Path), + Const(PatId), } impl Literal { From 96a7c6ae3cc69ace6c2e77cc4a4c7f453c07998c Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 5 Mar 2024 19:30:41 +0800 Subject: [PATCH 36/69] fix: mir for range pattern --- crates/hir-ty/src/mir/lower.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index ed316f972689f..577a01aee7826 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -1364,10 +1364,14 @@ impl<'ctx> MirLowerCtx<'ctx> { match loc { LiteralOrConst::Literal(l) => self.lower_literal_to_operand(ty, l), LiteralOrConst::Const(c) => { - let unresolved_name = || MirLowerError::unresolved_path(self.db, c); + let c = match &self.body.pats[*c] { + Pat::Path(p) => p, + _ => not_supported!("only `char` and numeric types are allowed in range patterns"), + }; + let unresolved_name = || MirLowerError::unresolved_path(self.db, c.as_ref()); let resolver = self.owner.resolver(self.db.upcast()); let pr = resolver - .resolve_path_in_value_ns(self.db.upcast(), c) + .resolve_path_in_value_ns(self.db.upcast(), c.as_ref()) .ok_or_else(unresolved_name)?; match pr { ResolveValueResult::ValueNs(v, _) => { From 16995ceda94b68f2bf667e1f7eff022ea795de50 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 5 Mar 2024 19:31:01 +0800 Subject: [PATCH 37/69] test: add tests for constants inside range pattern --- crates/ide/src/goto_definition.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 41148db614606..aac01384cbdbc 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -532,6 +532,24 @@ fn bar() { $0foo!() => {} } } +"#, + ); + } + + #[test] + fn goto_definition_works_for_consts_inside_range_pattern() { + check( + r#" +//- /lib.rs +const A: u32 = 0; + //^ + +fn bar(v: u32) { + match v { + 0..=$0A => {} + _ => {} + } +} "#, ); } From 9cc3a9cfc25ea36ceb0474011d51de4fc7d42f7a Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 5 Mar 2024 19:55:31 +0800 Subject: [PATCH 38/69] fix: formatting --- crates/hir-ty/src/mir/lower.rs | 4 +++- crates/ide/src/goto_definition.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 577a01aee7826..d0f739e6ac66f 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -1366,7 +1366,9 @@ impl<'ctx> MirLowerCtx<'ctx> { LiteralOrConst::Const(c) => { let c = match &self.body.pats[*c] { Pat::Path(p) => p, - _ => not_supported!("only `char` and numeric types are allowed in range patterns"), + _ => not_supported!( + "only `char` and numeric types are allowed in range patterns" + ), }; let unresolved_name = || MirLowerError::unresolved_path(self.db, c.as_ref()); let resolver = self.owner.resolver(self.db.upcast()); diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index aac01384cbdbc..1bda15255dcd0 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -536,7 +536,7 @@ fn bar() { ); } - #[test] + #[test] fn goto_definition_works_for_consts_inside_range_pattern() { check( r#" From b06726bebe82ab965068a33e122317f3e3d5c10b Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Tue, 5 Mar 2024 20:16:32 +0800 Subject: [PATCH 39/69] remove `ignore-hidden = false` --- .typos.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/.typos.toml b/.typos.toml index 98dbe3a5d9d36..c2e8b265218fb 100644 --- a/.typos.toml +++ b/.typos.toml @@ -5,7 +5,6 @@ extend-exclude = [ "crates/parser/test_data/lexer/err/", "crates/project-model/test_data/", ] -ignore-hidden = false [default] extend-ignore-re = [ From 1afeea85ffa65d0b9c6cc784542ba1716cb721db Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 5 Mar 2024 16:01:01 +0100 Subject: [PATCH 40/69] Add `fn parent_fn()` accessors for `hir::Param` & `hir::SelfParam` --- crates/hir/src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 4872c47c31d03..ffdf169bbb58a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2108,6 +2108,10 @@ pub struct Param { } impl Param { + pub fn parent_fn(&self) -> Function { + self.func + } + pub fn ty(&self) -> &Type { &self.ty } @@ -2172,6 +2176,10 @@ impl SelfParam { .map(|value| InFile { file_id, value }) } + pub fn parent_fn(&self) -> Function { + Function::from(self.func) + } + pub fn ty(&self, db: &dyn HirDatabase) -> Type { let substs = TyBuilder::placeholder_subst(db, self.func); let callable_sig = From bf141310f8602a679b8cc3d6318cb9ef5be61c89 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 5 Mar 2024 16:02:22 +0100 Subject: [PATCH 41/69] Add `fn index()` accessor for `hir::Param` --- crates/hir/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index ffdf169bbb58a..5eed7ecd5b21d 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2112,6 +2112,10 @@ impl Param { self.func } + pub fn index(&self) -> usize { + self.idx + } + pub fn ty(&self) -> &Type { &self.ty } From 44be2432f50be8d7476f65b18220027110d7bd99 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Fri, 1 Mar 2024 13:40:29 +0330 Subject: [PATCH 42/69] Add test explorer --- Cargo.toml | 1 + crates/flycheck/src/command.rs | 156 ++++++++++++++ crates/flycheck/src/lib.rs | 201 ++++-------------- crates/flycheck/src/test_runner.rs | 75 +++++++ crates/ide/src/lib.rs | 14 ++ crates/ide/src/test_explorer.rs | 135 ++++++++++++ crates/rust-analyzer/src/global_state.rs | 5 + .../src/hack_recover_crate_name.rs | 25 +++ .../src/handlers/notification.rs | 9 +- crates/rust-analyzer/src/handlers/request.rs | 65 ++++++ crates/rust-analyzer/src/lib.rs | 1 + crates/rust-analyzer/src/lsp/ext.rs | 102 +++++++++ crates/rust-analyzer/src/lsp/to_proto.rs | 26 +++ crates/rust-analyzer/src/main_loop.rs | 115 +++++++++- crates/stdx/src/process.rs | 5 + docs/dev/lsp-extensions.md | 102 ++++++++- editors/code/src/ctx.ts | 10 +- editors/code/src/lsp_ext.ts | 31 +++ editors/code/src/test_explorer.ts | 169 +++++++++++++++ 19 files changed, 1079 insertions(+), 168 deletions(-) create mode 100644 crates/flycheck/src/command.rs create mode 100644 crates/flycheck/src/test_runner.rs create mode 100644 crates/ide/src/test_explorer.rs create mode 100644 crates/rust-analyzer/src/hack_recover_crate_name.rs create mode 100644 editors/code/src/test_explorer.ts diff --git a/Cargo.toml b/Cargo.toml index e8e82914c7c4a..eb3be72396c23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -158,6 +158,7 @@ dashmap = { version = "=5.5.3", features = ["raw-api"] } [workspace.lints.rust] rust_2018_idioms = "warn" unused_lifetimes = "warn" +unreachable_pub = "warn" semicolon_in_expressions_from_macros = "warn" [workspace.lints.clippy] diff --git a/crates/flycheck/src/command.rs b/crates/flycheck/src/command.rs new file mode 100644 index 0000000000000..091146a0010a5 --- /dev/null +++ b/crates/flycheck/src/command.rs @@ -0,0 +1,156 @@ +//! Utilities for running a cargo command like `cargo check` or `cargo test` in a separate thread and +//! parse its stdout/stderr. + +use std::{ + ffi::OsString, + fmt, io, + path::PathBuf, + process::{ChildStderr, ChildStdout, Command, Stdio}, +}; + +use command_group::{CommandGroup, GroupChild}; +use crossbeam_channel::{unbounded, Receiver, Sender}; +use stdx::process::streaming_output; + +/// Cargo output is structured as a one JSON per line. This trait abstracts parsing one line of +/// cargo output into a Rust data type. +pub(crate) trait ParseFromLine: Sized + Send + 'static { + fn from_line(line: &str, error: &mut String) -> Option; + fn from_eof() -> Option; +} + +struct CargoActor { + sender: Sender, + stdout: ChildStdout, + stderr: ChildStderr, +} + +impl CargoActor { + fn new(sender: Sender, stdout: ChildStdout, stderr: ChildStderr) -> Self { + CargoActor { sender, stdout, stderr } + } + + fn run(self) -> io::Result<(bool, String)> { + // We manually read a line at a time, instead of using serde's + // stream deserializers, because the deserializer cannot recover + // from an error, resulting in it getting stuck, because we try to + // be resilient against failures. + // + // Because cargo only outputs one JSON object per line, we can + // simply skip a line if it doesn't parse, which just ignores any + // erroneous output. + + 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. + if let Some(t) = T::from_line(line, error) { + self.sender.send(t).unwrap(); + true + } else { + false + } + }; + let output = streaming_output( + self.stdout, + self.stderr, + &mut |line| { + if process_line(line, &mut stdout_errors) { + read_at_least_one_stdout_message = true; + } + }, + &mut |line| { + if process_line(line, &mut stderr_errors) { + read_at_least_one_stderr_message = true; + } + }, + &mut || { + if let Some(t) = T::from_eof() { + self.sender.send(t).unwrap(); + } + }, + ); + + 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}"))), + } + } +} + +struct JodGroupChild(GroupChild); + +impl Drop for JodGroupChild { + fn drop(&mut self) { + _ = self.0.kill(); + _ = self.0.wait(); + } +} + +/// A handle to a cargo process used for fly-checking. +pub(crate) struct CommandHandle { + /// The handle to the actual cargo process. As we cannot cancel directly from with + /// a read syscall dropping and therefore terminating the process is our best option. + child: JodGroupChild, + thread: stdx::thread::JoinHandle>, + pub(crate) receiver: Receiver, + program: OsString, + arguments: Vec, + current_dir: Option, +} + +impl fmt::Debug for CommandHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CommandHandle") + .field("program", &self.program) + .field("arguments", &self.arguments) + .field("current_dir", &self.current_dir) + .finish() + } +} + +impl CommandHandle { + pub(crate) fn spawn(mut command: Command) -> std::io::Result { + command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null()); + let mut child = command.group_spawn().map(JodGroupChild)?; + + let program = command.get_program().into(); + let arguments = command.get_args().map(|arg| arg.into()).collect::>(); + let current_dir = command.get_current_dir().map(|arg| arg.to_path_buf()); + + let stdout = child.0.inner().stdout.take().unwrap(); + let stderr = child.0.inner().stderr.take().unwrap(); + + let (sender, receiver) = unbounded(); + let actor = CargoActor::::new(sender, stdout, stderr); + let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) + .name("CommandHandle".to_owned()) + .spawn(move || actor.run()) + .expect("failed to spawn thread"); + Ok(CommandHandle { program, arguments, current_dir, child, thread, receiver }) + } + + pub(crate) fn cancel(mut self) { + let _ = self.child.0.kill(); + let _ = self.child.0.wait(); + } + + pub(crate) fn join(mut self) -> io::Result<()> { + let _ = self.child.0.kill(); + let exit_status = self.child.0.wait()?; + let (read_at_least_one_message, error) = self.thread.join()?; + if read_at_least_one_message || exit_status.success() { + Ok(()) + } else { + Err(io::Error::new(io::ErrorKind::Other, format!( + "Cargo watcher failed, the command produced no valid metadata (exit code: {exit_status:?}):\n{error}" + ))) + } + } +} diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 8bcdca5bb828f..f8efb52022205 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -2,22 +2,18 @@ //! another compatible command (f.x. clippy) in a background thread and provide //! LSP diagnostics based on the output of the command. +// FIXME: This crate now handles running `cargo test` needed in the test explorer in +// addition to `cargo check`. Either split it into 3 crates (one for test, one for check +// and one common utilities) or change its name and docs to reflect the current state. + #![warn(rust_2018_idioms, unused_lifetimes)] -use std::{ - ffi::OsString, - fmt, io, - path::PathBuf, - process::{ChildStderr, ChildStdout, Command, Stdio}, - time::Duration, -}; +use std::{fmt, io, path::PathBuf, process::Command, time::Duration}; -use command_group::{CommandGroup, GroupChild}; use crossbeam_channel::{never, select, unbounded, Receiver, Sender}; use paths::{AbsPath, AbsPathBuf}; use rustc_hash::FxHashMap; use serde::Deserialize; -use stdx::process::streaming_output; pub use cargo_metadata::diagnostic::{ Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan, @@ -25,6 +21,12 @@ pub use cargo_metadata::diagnostic::{ }; use toolchain::Tool; +mod command; +mod test_runner; + +use command::{CommandHandle, ParseFromLine}; +pub use test_runner::{CargoTestHandle, CargoTestMessage, TestState}; + #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub enum InvocationStrategy { Once, @@ -181,12 +183,12 @@ struct FlycheckActor { /// doesn't provide a way to read sub-process output without blocking, so we /// have to wrap sub-processes output handling in a thread and pass messages /// back over a channel. - command_handle: Option, + command_handle: Option>, } enum Event { RequestStateChange(StateChange), - CheckEvent(Option), + CheckEvent(Option), } const SAVED_FILE_PLACEHOLDER: &str = "$saved_file"; @@ -282,7 +284,7 @@ impl FlycheckActor { self.report_progress(Progress::DidFinish(res)); } Event::CheckEvent(Some(message)) => match message { - CargoMessage::CompilerArtifact(msg) => { + CargoCheckMessage::CompilerArtifact(msg) => { tracing::trace!( flycheck_id = self.id, artifact = msg.target.name, @@ -291,7 +293,7 @@ impl FlycheckActor { self.report_progress(Progress::DidCheckCrate(msg.target.name)); } - CargoMessage::Diagnostic(msg) => { + CargoCheckMessage::Diagnostic(msg) => { tracing::trace!( flycheck_id = self.id, message = msg.message, @@ -448,161 +450,42 @@ impl FlycheckActor { } } -struct JodGroupChild(GroupChild); - -impl Drop for JodGroupChild { - fn drop(&mut self) { - _ = self.0.kill(); - _ = self.0.wait(); - } -} - -/// A handle to a cargo process used for fly-checking. -struct CommandHandle { - /// The handle to the actual cargo process. As we cannot cancel directly from with - /// a read syscall dropping and therefore terminating the process is our best option. - child: JodGroupChild, - thread: stdx::thread::JoinHandle>, - receiver: Receiver, - program: OsString, - arguments: Vec, - current_dir: Option, -} - -impl fmt::Debug for CommandHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CommandHandle") - .field("program", &self.program) - .field("arguments", &self.arguments) - .field("current_dir", &self.current_dir) - .finish() - } +#[allow(clippy::large_enum_variant)] +enum CargoCheckMessage { + CompilerArtifact(cargo_metadata::Artifact), + Diagnostic(Diagnostic), } -impl CommandHandle { - fn spawn(mut command: Command) -> std::io::Result { - command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null()); - let mut child = command.group_spawn().map(JodGroupChild)?; - - let program = command.get_program().into(); - let arguments = command.get_args().map(|arg| arg.into()).collect::>(); - let current_dir = command.get_current_dir().map(|arg| arg.to_path_buf()); - - let stdout = child.0.inner().stdout.take().unwrap(); - let stderr = child.0.inner().stderr.take().unwrap(); - - let (sender, receiver) = unbounded(); - let actor = CargoActor::new(sender, stdout, stderr); - let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .name("CommandHandle".to_owned()) - .spawn(move || actor.run()) - .expect("failed to spawn thread"); - Ok(CommandHandle { program, arguments, current_dir, child, thread, receiver }) - } - - fn cancel(mut self) { - let _ = self.child.0.kill(); - let _ = self.child.0.wait(); - } - - fn join(mut self) -> io::Result<()> { - let _ = self.child.0.kill(); - let exit_status = self.child.0.wait()?; - let (read_at_least_one_message, error) = self.thread.join()?; - if read_at_least_one_message || exit_status.success() { - Ok(()) - } else { - Err(io::Error::new(io::ErrorKind::Other, format!( - "Cargo watcher failed, the command produced no valid metadata (exit code: {exit_status:?}):\n{error}" - ))) +impl ParseFromLine for CargoCheckMessage { + fn from_line(line: &str, error: &mut String) -> Option { + let mut deserializer = serde_json::Deserializer::from_str(line); + deserializer.disable_recursion_limit(); + if let Ok(message) = JsonMessage::deserialize(&mut deserializer) { + return 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 => { + Some(CargoCheckMessage::CompilerArtifact(artifact)) + } + cargo_metadata::Message::CompilerMessage(msg) => { + Some(CargoCheckMessage::Diagnostic(msg.message)) + } + _ => None, + }, + JsonMessage::Rustc(message) => Some(CargoCheckMessage::Diagnostic(message)), + }; } - } -} -struct CargoActor { - sender: Sender, - stdout: ChildStdout, - stderr: ChildStderr, -} - -impl CargoActor { - fn new(sender: Sender, stdout: ChildStdout, stderr: ChildStderr) -> CargoActor { - CargoActor { sender, stdout, stderr } + error.push_str(line); + error.push('\n'); + None } - fn run(self) -> io::Result<(bool, String)> { - // We manually read a line at a time, instead of using serde's - // stream deserializers, because the deserializer cannot recover - // from an error, resulting in it getting stuck, because we try to - // be resilient against failures. - // - // Because cargo only outputs one JSON object per line, we can - // simply skip a line if it doesn't parse, which just ignores any - // erroneous output. - - 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'); - false - }; - let output = streaming_output( - self.stdout, - self.stderr, - &mut |line| { - if process_line(line, &mut stdout_errors) { - read_at_least_one_stdout_message = true; - } - }, - &mut |line| { - 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}"))), - } + fn from_eof() -> Option { + None } } -#[allow(clippy::large_enum_variant)] -enum CargoMessage { - CompilerArtifact(cargo_metadata::Artifact), - Diagnostic(Diagnostic), -} - #[derive(Deserialize)] #[serde(untagged)] enum JsonMessage { diff --git a/crates/flycheck/src/test_runner.rs b/crates/flycheck/src/test_runner.rs new file mode 100644 index 0000000000000..b7d966989b9bd --- /dev/null +++ b/crates/flycheck/src/test_runner.rs @@ -0,0 +1,75 @@ +//! This module provides the functionality needed to run `cargo test` in a background +//! thread and report the result of each test in a channel. + +use std::process::Command; + +use crossbeam_channel::Receiver; +use serde::Deserialize; +use toolchain::Tool; + +use crate::command::{CommandHandle, ParseFromLine}; + +#[derive(Debug, Deserialize)] +#[serde(tag = "event", rename_all = "camelCase")] +pub enum TestState { + Started, + Ok, + Failed { stdout: String }, +} + +#[derive(Debug, Deserialize)] +#[serde(tag = "type", rename_all = "camelCase")] +pub enum CargoTestMessage { + Test { + name: String, + #[serde(flatten)] + state: TestState, + }, + Suite, + Finished, +} + +impl ParseFromLine for CargoTestMessage { + fn from_line(line: &str, error: &mut String) -> Option { + let mut deserializer = serde_json::Deserializer::from_str(line); + deserializer.disable_recursion_limit(); + if let Ok(message) = CargoTestMessage::deserialize(&mut deserializer) { + return Some(message); + } + + error.push_str(line); + error.push('\n'); + None + } + + fn from_eof() -> Option { + Some(CargoTestMessage::Finished) + } +} + +#[derive(Debug)] +pub struct CargoTestHandle { + handle: CommandHandle, +} + +// Example of a cargo test command: +// cargo test -- module::func -Z unstable-options --format=json + +impl CargoTestHandle { + pub fn new(path: Option<&str>) -> std::io::Result { + let mut cmd = Command::new(Tool::Cargo.path()); + cmd.env("RUSTC_BOOTSTRAP", "1"); + cmd.arg("test"); + cmd.arg("--"); + if let Some(path) = path { + cmd.arg(path); + } + cmd.args(["-Z", "unstable-options"]); + cmd.arg("--format=json"); + Ok(Self { handle: CommandHandle::spawn(cmd)? }) + } + + pub fn receiver(&self) -> &Receiver { + &self.handle.receiver + } +} diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 4eb4acdf183c4..59a7df14fd53e 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -50,6 +50,7 @@ mod static_index; mod status; mod syntax_highlighting; mod syntax_tree; +mod test_explorer; mod typing; mod view_crate_graph; mod view_hir; @@ -108,6 +109,7 @@ pub use crate::{ tags::{Highlight, HlMod, HlMods, HlOperator, HlPunct, HlTag}, HighlightConfig, HlRange, }, + test_explorer::{TestItem, TestItemKind}, }; pub use hir::Semantics; pub use ide_assists::{ @@ -340,6 +342,18 @@ impl Analysis { self.with_db(|db| view_item_tree::view_item_tree(db, file_id)) } + pub fn discover_test_roots(&self) -> Cancellable> { + self.with_db(test_explorer::discover_test_roots) + } + + pub fn discover_tests_in_crate_by_test_id(&self, crate_id: &str) -> Cancellable> { + self.with_db(|db| test_explorer::discover_tests_in_crate_by_test_id(db, crate_id)) + } + + pub fn discover_tests_in_crate(&self, crate_id: CrateId) -> Cancellable> { + self.with_db(|db| test_explorer::discover_tests_in_crate(db, crate_id)) + } + /// Renders the crate graph to GraphViz "dot" syntax. pub fn view_crate_graph(&self, full: bool) -> Cancellable> { self.with_db(|db| view_crate_graph::view_crate_graph(db, full)) diff --git a/crates/ide/src/test_explorer.rs b/crates/ide/src/test_explorer.rs new file mode 100644 index 0000000000000..2e741021ea8bb --- /dev/null +++ b/crates/ide/src/test_explorer.rs @@ -0,0 +1,135 @@ +//! Discovers tests + +use hir::{Crate, Module, ModuleDef, Semantics}; +use ide_db::{ + base_db::{CrateGraph, CrateId, FileId, SourceDatabase}, + RootDatabase, +}; +use syntax::TextRange; + +use crate::{navigation_target::ToNav, runnables::runnable_fn, Runnable, TryToNav}; + +#[derive(Debug)] +pub enum TestItemKind { + Crate, + Module, + Function, +} + +#[derive(Debug)] +pub struct TestItem { + pub id: String, + pub kind: TestItemKind, + pub label: String, + pub parent: Option, + pub file: Option, + pub text_range: Option, + pub runnable: Option, +} + +pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec { + let crate_graph = db.crate_graph(); + crate_graph + .iter() + .filter(|&id| crate_graph[id].origin.is_local()) + .filter_map(|id| Some(crate_graph[id].display_name.as_ref()?.to_string())) + .map(|id| TestItem { + kind: TestItemKind::Crate, + label: id.clone(), + id, + parent: None, + file: None, + text_range: None, + runnable: None, + }) + .collect() +} + +fn find_crate_by_id(crate_graph: &CrateGraph, crate_id: &str) -> Option { + // here, we use display_name as the crate id. This is not super ideal, but it works since we + // only show tests for the local crates. + crate_graph.iter().find(|&id| { + crate_graph[id].origin.is_local() + && crate_graph[id].display_name.as_ref().is_some_and(|x| x.to_string() == crate_id) + }) +} + +fn discover_tests_in_module(db: &RootDatabase, module: Module, prefix_id: String) -> Vec { + let sema = Semantics::new(db); + + let mut r = vec![]; + for c in module.children(db) { + let module_name = + c.name(db).as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]").to_owned(); + let module_id = format!("{prefix_id}::{module_name}"); + let module_children = discover_tests_in_module(db, c, module_id.clone()); + if !module_children.is_empty() { + let nav = c.to_nav(db).call_site; + r.push(TestItem { + id: module_id, + kind: TestItemKind::Module, + label: module_name, + parent: Some(prefix_id.clone()), + file: Some(nav.file_id), + text_range: Some(nav.focus_or_full_range()), + runnable: None, + }); + r.extend(module_children); + } + } + for def in module.declarations(db) { + let ModuleDef::Function(f) = def else { + continue; + }; + if !f.is_test(db) { + continue; + } + let nav = f.try_to_nav(db).map(|r| r.call_site); + let fn_name = f.name(db).as_str().unwrap_or("[function without name]").to_owned(); + r.push(TestItem { + id: format!("{prefix_id}::{fn_name}"), + kind: TestItemKind::Function, + label: fn_name, + parent: Some(prefix_id.clone()), + file: nav.as_ref().map(|n| n.file_id), + text_range: nav.as_ref().map(|n| n.focus_or_full_range()), + runnable: runnable_fn(&sema, f), + }); + } + r +} + +pub(crate) fn discover_tests_in_crate_by_test_id( + db: &RootDatabase, + crate_test_id: &str, +) -> Vec { + let crate_graph = db.crate_graph(); + let Some(crate_id) = find_crate_by_id(&crate_graph, crate_test_id) else { + return vec![]; + }; + discover_tests_in_crate(db, crate_id) +} + +pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> Vec { + let crate_graph = db.crate_graph(); + if !crate_graph[crate_id].origin.is_local() { + return vec![]; + } + let Some(crate_test_id) = &crate_graph[crate_id].display_name else { + return vec![]; + }; + let crate_test_id = crate_test_id.to_string(); + let crate_id: Crate = crate_id.into(); + let module = crate_id.root_module(); + let mut r = vec![TestItem { + id: crate_test_id.clone(), + kind: TestItemKind::Crate, + label: crate_test_id.clone(), + parent: None, + file: None, + text_range: None, + runnable: None, + }]; + r.extend(discover_tests_in_module(db, module, crate_test_id)); + r +} diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 8b8d0ebcb9894..560410e3325df 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -83,6 +83,9 @@ pub(crate) struct GlobalState { pub(crate) flycheck_receiver: Receiver, pub(crate) last_flycheck_error: Option, + // Test explorer + pub(crate) test_run_session: Option, + // VFS pub(crate) loader: Handle, Receiver>, pub(crate) vfs: Arc)>>, @@ -212,6 +215,8 @@ impl GlobalState { flycheck_receiver, last_flycheck_error: None, + test_run_session: None, + vfs: Arc::new(RwLock::new((vfs::Vfs::default(), IntMap::default()))), vfs_config_version: 0, vfs_progress_config_version: 0, diff --git a/crates/rust-analyzer/src/hack_recover_crate_name.rs b/crates/rust-analyzer/src/hack_recover_crate_name.rs new file mode 100644 index 0000000000000..d7285653c5fa5 --- /dev/null +++ b/crates/rust-analyzer/src/hack_recover_crate_name.rs @@ -0,0 +1,25 @@ +//! Currently cargo does not emit crate name in the `cargo test --format=json`, which needs to be changed. This +//! module contains a way to recover crate names in a very hacky and wrong way. + +// FIXME(hack_recover_crate_name): Remove this module. + +use std::sync::{Mutex, MutexGuard, OnceLock}; + +use ide_db::FxHashMap; + +static STORAGE: OnceLock>> = OnceLock::new(); + +fn get_storage() -> MutexGuard<'static, FxHashMap> { + STORAGE.get_or_init(|| Mutex::new(FxHashMap::default())).lock().unwrap() +} + +pub(crate) fn insert_name(name_with_crate: String) { + let Some((_, name_without_crate)) = name_with_crate.split_once("::") else { + return; + }; + get_storage().insert(name_without_crate.to_owned(), name_with_crate); +} + +pub(crate) fn lookup_name(name_without_crate: String) -> Option { + get_storage().get(&name_without_crate).cloned() +} diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs index cf646a2e28282..ff213748b4ff0 100644 --- a/crates/rust-analyzer/src/handlers/notification.rs +++ b/crates/rust-analyzer/src/handlers/notification.rs @@ -16,7 +16,7 @@ use crate::{ config::Config, global_state::GlobalState, lsp::{from_proto, utils::apply_document_changes}, - lsp_ext::RunFlycheckParams, + lsp_ext::{self, RunFlycheckParams}, mem_docs::DocumentData, reload, }; @@ -373,3 +373,10 @@ pub(crate) fn handle_run_flycheck( } Ok(()) } + +pub(crate) fn handle_abort_run_test(state: &mut GlobalState, _: ()) -> anyhow::Result<()> { + if state.test_run_session.take().is_some() { + state.send_notification::(()); + } + Ok(()) +} diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 0e005975fbae5..cc4333bd1dbd2 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -39,6 +39,7 @@ use crate::{ config::{Config, RustfmtConfig, WorkspaceSymbolConfig}, diff::diff, global_state::{GlobalState, GlobalStateSnapshot}, + hack_recover_crate_name, line_index::LineEndings, lsp::{ from_proto, to_proto, @@ -192,6 +193,70 @@ pub(crate) fn handle_view_item_tree( Ok(res) } +pub(crate) fn handle_run_test( + state: &mut GlobalState, + params: lsp_ext::RunTestParams, +) -> anyhow::Result<()> { + if let Some(_session) = state.test_run_session.take() { + state.send_notification::(()); + } + // We detect the lowest common ansector of all included tests, and + // run it. We ignore excluded tests for now, the client will handle + // it for us. + let lca = match params.include { + Some(tests) => tests + .into_iter() + .reduce(|x, y| { + let mut common_prefix = "".to_owned(); + for (xc, yc) in x.chars().zip(y.chars()) { + if xc != yc { + break; + } + common_prefix.push(xc); + } + common_prefix + }) + .unwrap_or_default(), + None => "".to_owned(), + }; + let handle = if lca.is_empty() { + flycheck::CargoTestHandle::new(None) + } else if let Some((_, path)) = lca.split_once("::") { + flycheck::CargoTestHandle::new(Some(path)) + } else { + flycheck::CargoTestHandle::new(None) + }; + state.test_run_session = Some(handle?); + Ok(()) +} + +pub(crate) fn handle_discover_test( + snap: GlobalStateSnapshot, + params: lsp_ext::DiscoverTestParams, +) -> anyhow::Result { + let _p = tracing::span!(tracing::Level::INFO, "handle_discover_test").entered(); + let (tests, scope) = match params.test_id { + Some(id) => { + let crate_id = id.split_once("::").map(|it| it.0).unwrap_or(&id); + (snap.analysis.discover_tests_in_crate_by_test_id(crate_id)?, vec![crate_id.to_owned()]) + } + None => (snap.analysis.discover_test_roots()?, vec![]), + }; + for t in &tests { + hack_recover_crate_name::insert_name(t.id.clone()); + } + Ok(lsp_ext::DiscoverTestResults { + tests: tests + .into_iter() + .map(|t| { + let line_index = t.file.and_then(|f| snap.file_line_index(f).ok()); + to_proto::test_item(&snap, t, line_index.as_ref()) + }) + .collect(), + scope, + }) +} + pub(crate) fn handle_view_crate_graph( snap: GlobalStateSnapshot, params: ViewCrateGraphParams, diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs index 473ca991ad9b0..175ffa622ff70 100644 --- a/crates/rust-analyzer/src/lib.rs +++ b/crates/rust-analyzer/src/lib.rs @@ -19,6 +19,7 @@ mod diagnostics; mod diff; mod dispatch; mod global_state; +mod hack_recover_crate_name; mod line_index; mod main_loop; mod mem_docs; diff --git a/crates/rust-analyzer/src/lsp/ext.rs b/crates/rust-analyzer/src/lsp/ext.rs index aa40728ce6cb8..842e765d9d155 100644 --- a/crates/rust-analyzer/src/lsp/ext.rs +++ b/crates/rust-analyzer/src/lsp/ext.rs @@ -163,6 +163,108 @@ impl Request for ViewItemTree { const METHOD: &'static str = "rust-analyzer/viewItemTree"; } +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct DiscoverTestParams { + pub test_id: Option, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub enum TestItemIcon { + Package, + Module, + Test, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TestItem { + pub id: String, + pub label: String, + pub icon: TestItemIcon, + pub can_resolve_children: bool, + pub parent: Option, + pub text_document: Option, + pub range: Option, + pub runnable: Option, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct DiscoverTestResults { + pub tests: Vec, + pub scope: Vec, +} + +pub enum DiscoverTest {} + +impl Request for DiscoverTest { + type Params = DiscoverTestParams; + type Result = DiscoverTestResults; + const METHOD: &'static str = "experimental/discoverTest"; +} + +pub enum DiscoveredTests {} + +impl Notification for DiscoveredTests { + type Params = DiscoverTestResults; + const METHOD: &'static str = "experimental/discoveredTests"; +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct RunTestParams { + pub include: Option>, + pub exclude: Option>, +} + +pub enum RunTest {} + +impl Request for RunTest { + type Params = RunTestParams; + type Result = (); + const METHOD: &'static str = "experimental/runTest"; +} + +pub enum EndRunTest {} + +impl Notification for EndRunTest { + type Params = (); + const METHOD: &'static str = "experimental/endRunTest"; +} + +pub enum AbortRunTest {} + +impl Notification for AbortRunTest { + type Params = (); + const METHOD: &'static str = "experimental/abortRunTest"; +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase", tag = "tag")] +pub enum TestState { + Passed, + Failed { message: String }, + Skipped, + Started, + Enqueued, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct ChangeTestStateParams { + pub test_id: String, + pub state: TestState, +} + +pub enum ChangeTestState {} + +impl Notification for ChangeTestState { + type Params = ChangeTestStateParams; + const METHOD: &'static str = "experimental/changeTestState"; +} + pub enum ExpandMacro {} impl Request for ExpandMacro { diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index 481ebfefd4eed..f0bb7d8af3ab1 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -1498,6 +1498,32 @@ pub(crate) fn code_lens( Ok(()) } +pub(crate) fn test_item( + snap: &GlobalStateSnapshot, + test_item: ide::TestItem, + line_index: Option<&LineIndex>, +) -> lsp_ext::TestItem { + lsp_ext::TestItem { + id: test_item.id, + label: test_item.label, + icon: match test_item.kind { + ide::TestItemKind::Crate => lsp_ext::TestItemIcon::Package, + ide::TestItemKind::Module => lsp_ext::TestItemIcon::Module, + ide::TestItemKind::Function => lsp_ext::TestItemIcon::Test, + }, + can_resolve_children: matches!( + test_item.kind, + ide::TestItemKind::Crate | ide::TestItemKind::Module + ), + parent: test_item.parent, + text_document: test_item + .file + .map(|f| lsp_types::TextDocumentIdentifier { uri: url(snap, f) }), + range: line_index.and_then(|l| Some(range(l, test_item.text_range?))), + runnable: test_item.runnable.and_then(|r| runnable(snap, r).ok()), + } +} + pub(crate) mod command { use ide::{FileRange, NavigationTarget}; use serde_json::to_value; diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 72f6d0fde5fe7..87da95c87e32a 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -1,14 +1,15 @@ //! The main loop of `rust-analyzer` responsible for dispatching LSP //! requests/replies and notifications back to the client. -use crate::lsp::ext; + use std::{ fmt, time::{Duration, Instant}, }; use always_assert::always; -use crossbeam_channel::{select, Receiver}; +use crossbeam_channel::{never, select, Receiver}; use ide_db::base_db::{SourceDatabase, SourceDatabaseExt, VfsPath}; +use itertools::Itertools; use lsp_server::{Connection, Notification, Request}; use lsp_types::notification::Notification as _; use stdx::thread::ThreadIntent; @@ -19,8 +20,9 @@ use crate::{ diagnostics::fetch_native_diagnostics, dispatch::{NotificationDispatcher, RequestDispatcher}, global_state::{file_id_to_url, url_to_file_id, GlobalState}, + hack_recover_crate_name, lsp::{ - from_proto, + from_proto, to_proto, utils::{notification_is, Progress}, }, lsp_ext, @@ -58,6 +60,7 @@ enum Event { QueuedTask(QueuedTask), Vfs(vfs::loader::Message), Flycheck(flycheck::Message), + TestResult(flycheck::CargoTestMessage), } impl fmt::Display for Event { @@ -68,6 +71,7 @@ impl fmt::Display for Event { Event::Vfs(_) => write!(f, "Event::Vfs"), Event::Flycheck(_) => write!(f, "Event::Flycheck"), Event::QueuedTask(_) => write!(f, "Event::QueuedTask"), + Event::TestResult(_) => write!(f, "Event::TestResult"), } } } @@ -81,9 +85,10 @@ pub(crate) enum QueuedTask { #[derive(Debug)] pub(crate) enum Task { Response(lsp_server::Response), - ClientNotification(ext::UnindexedProjectParams), + ClientNotification(lsp_ext::UnindexedProjectParams), Retry(lsp_server::Request), Diagnostics(Vec<(FileId, Vec)>), + DiscoverTest(lsp_ext::DiscoverTestResults), PrimeCaches(PrimeCachesProgress), FetchWorkspace(ProjectWorkspaceProgress), FetchBuildData(BuildDataProgress), @@ -127,6 +132,7 @@ impl fmt::Debug for Event { Event::QueuedTask(it) => fmt::Debug::fmt(it, f), Event::Vfs(it) => fmt::Debug::fmt(it, f), Event::Flycheck(it) => fmt::Debug::fmt(it, f), + Event::TestResult(it) => fmt::Debug::fmt(it, f), } } } @@ -214,6 +220,10 @@ impl GlobalState { recv(self.flycheck_receiver) -> task => Some(Event::Flycheck(task.unwrap())), + + recv(self.test_run_session.as_ref().map(|s| s.receiver()).unwrap_or(&never())) -> task => + Some(Event::TestResult(task.unwrap())), + } } @@ -322,6 +332,18 @@ impl GlobalState { self.handle_flycheck_msg(message); } } + Event::TestResult(message) => { + let _p = + tracing::span!(tracing::Level::INFO, "GlobalState::handle_event/test_result") + .entered(); + self.handle_cargo_test_msg(message); + // Coalesce many test result event into a single loop turn + while let Some(message) = + self.test_run_session.as_ref().and_then(|r| r.receiver().try_recv().ok()) + { + self.handle_cargo_test_msg(message); + } + } } let event_handling_duration = loop_start.elapsed(); @@ -367,7 +389,8 @@ impl GlobalState { let update_diagnostics = (!was_quiescent || state_changed || memdocs_added_or_removed) && self.config.publish_diagnostics(); if update_diagnostics { - self.update_diagnostics() + self.update_diagnostics(); + self.update_tests(); } } @@ -488,6 +511,55 @@ impl GlobalState { }); } + fn update_tests(&mut self) { + let db = self.analysis_host.raw_database(); + let subscriptions = self + .mem_docs + .iter() + .map(|path| self.vfs.read().0.file_id(path).unwrap()) + .filter(|&file_id| { + let source_root = db.file_source_root(file_id); + !db.source_root(source_root).is_library + }) + .collect::>(); + tracing::trace!("updating tests for {:?}", subscriptions); + + // Updating tests are triggered by the user typing + // so we run them on a latency sensitive thread. + self.task_pool.handle.spawn(ThreadIntent::LatencySensitive, { + let snapshot = self.snapshot(); + move || { + let tests = subscriptions + .into_iter() + .filter_map(|f| snapshot.analysis.crates_for(f).ok()) + .flatten() + .unique() + .filter_map(|c| snapshot.analysis.discover_tests_in_crate(c).ok()) + .flatten() + .collect::>(); + for t in &tests { + hack_recover_crate_name::insert_name(t.id.clone()); + } + let scope = tests + .iter() + .filter_map(|t| Some(t.id.split_once("::")?.0)) + .unique() + .map(|it| it.to_owned()) + .collect(); + Task::DiscoverTest(lsp_ext::DiscoverTestResults { + tests: tests + .into_iter() + .map(|t| { + let line_index = t.file.and_then(|f| snapshot.file_line_index(f).ok()); + to_proto::test_item(&snapshot, t, line_index.as_ref()) + }) + .collect(), + scope, + }) + } + }); + } + fn update_status_or_notify(&mut self) { let status = self.current_status(); if self.last_reported_status.as_ref() != Some(&status) { @@ -598,6 +670,9 @@ impl GlobalState { } } Task::BuildDepsHaveChanged => self.build_deps_changed = true, + Task::DiscoverTest(tests) => { + self.send_notification::(tests); + } } } @@ -666,7 +741,7 @@ impl GlobalState { let id = from_proto::file_id(&snap, &uri).expect("unable to get FileId"); if let Ok(crates) = &snap.analysis.crates_for(id) { if crates.is_empty() { - let params = ext::UnindexedProjectParams { + let params = lsp_ext::UnindexedProjectParams { text_documents: vec![lsp_types::TextDocumentIdentifier { uri }], }; sender.send(Task::ClientNotification(params)).unwrap(); @@ -698,6 +773,31 @@ impl GlobalState { } } + fn handle_cargo_test_msg(&mut self, message: flycheck::CargoTestMessage) { + match message { + flycheck::CargoTestMessage::Test { name, state } => { + let state = match state { + flycheck::TestState::Started => lsp_ext::TestState::Started, + flycheck::TestState::Ok => lsp_ext::TestState::Passed, + flycheck::TestState::Failed { stdout } => { + lsp_ext::TestState::Failed { message: stdout } + } + }; + let Some(test_id) = hack_recover_crate_name::lookup_name(name) else { + return; + }; + self.send_notification::( + lsp_ext::ChangeTestStateParams { test_id, state }, + ); + } + flycheck::CargoTestMessage::Suite => (), + flycheck::CargoTestMessage::Finished => { + self.send_notification::(()); + self.test_run_session = None; + } + } + } + fn handle_flycheck_msg(&mut self, message: flycheck::Message) { match message { flycheck::Message::AddDiagnostic { id, workspace_root, diagnostic } => { @@ -803,6 +903,7 @@ impl GlobalState { .on_sync_mut::(handlers::handle_proc_macros_rebuild) .on_sync_mut::(handlers::handle_memory_usage) .on_sync_mut::(handlers::handle_shuffle_crate_graph) + .on_sync_mut::(handlers::handle_run_test) // Request handlers which are related to the user typing // are run on the main thread to reduce latency: .on_sync::(handlers::handle_join_lines) @@ -843,6 +944,7 @@ impl GlobalState { .on::(handlers::handle_view_file_text) .on::(handlers::handle_view_crate_graph) .on::(handlers::handle_view_item_tree) + .on::(handlers::handle_discover_test) .on::(handlers::handle_expand_macro) .on::(handlers::handle_parent_module) .on::(handlers::handle_runnables) @@ -906,6 +1008,7 @@ impl GlobalState { .on_sync_mut::(handlers::handle_cancel_flycheck)? .on_sync_mut::(handlers::handle_clear_flycheck)? .on_sync_mut::(handlers::handle_run_flycheck)? + .on_sync_mut::(handlers::handle_abort_run_test)? .finish(); Ok(()) } diff --git a/crates/stdx/src/process.rs b/crates/stdx/src/process.rs index bca0cbc36d1a7..e6935f06b2ce1 100644 --- a/crates/stdx/src/process.rs +++ b/crates/stdx/src/process.rs @@ -15,6 +15,7 @@ pub fn streaming_output( err: ChildStderr, on_stdout_line: &mut dyn FnMut(&str), on_stderr_line: &mut dyn FnMut(&str), + on_eof: &mut dyn FnMut(), ) -> io::Result<(Vec, Vec)> { let mut stdout = Vec::new(); let mut stderr = Vec::new(); @@ -44,6 +45,9 @@ pub fn streaming_output( on_stderr_line(line); } } + if eof { + on_eof(); + } } })?; @@ -63,6 +67,7 @@ pub fn spawn_with_streaming_output( child.stderr.take().unwrap(), on_stdout_line, on_stderr_line, + &mut || (), )?; let status = child.wait()?; Ok(Output { status, stdout, stderr }) diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index f3100ee194e64..8d523d7baa3e5 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@