Repository: rust-analyzer/rust-analyzer
Pull request #5800 (2020-08-18 15:21:57)

Speedup ty tests

bors r+
🤖


Patch:
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs
index 11c171fc2d..79574b9ac8 100644
--- a/crates/assists/src/assist_context.rs
+++ b/crates/assists/src/assist_context.rs
@@ -6,7 +6,6 @@ use algo::find_covering_element;
 use base_db::{FileId, FileRange};
 use hir::Semantics;
 use ide_db::{
-    label::Label,
     source_change::{SourceChange, SourceFileEdit},
     RootDatabase,
 };
@@ -158,9 +157,8 @@ impl Assists {
         if !self.is_allowed(&id) {
             return None;
         }
-        let label = Label::new(label.into());
-        let assist = Assist { id, label, group: None, target };
-        self.add_impl(assist, f)
+        let label = Assist::new(id, label.into(), None, target);
+        self.add_impl(label, f)
     }
 
     pub(crate) fn add_group(
@@ -174,12 +172,12 @@ impl Assists {
         if !self.is_allowed(&id) {
             return None;
         }
-        let label = Label::new(label.into());
-        let assist = Assist { id, label, group: Some(group.clone()), target };
-        self.add_impl(assist, f)
+
+        let label = Assist::new(id, label.into(), Some(group.clone()), target);
+        self.add_impl(label, f)
     }
 
-    fn add_impl(&mut self, assist: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> {
+    fn add_impl(&mut self, label: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> {
         let source_change = if self.resolve {
             let mut builder = AssistBuilder::new(self.file);
             f(&mut builder);
@@ -188,7 +186,7 @@ impl Assists {
             None
         };
 
-        self.buf.push((assist, source_change));
+        self.buf.push((label, source_change));
         Some(())
     }
 
diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs
index 14834480ac..c589b08dc4 100644
--- a/crates/assists/src/lib.rs
+++ b/crates/assists/src/lib.rs
@@ -19,7 +19,7 @@ pub mod ast_transform;
 
 use base_db::FileRange;
 use hir::Semantics;
-use ide_db::{label::Label, source_change::SourceChange, RootDatabase};
+use ide_db::{source_change::SourceChange, RootDatabase};
 use syntax::TextRange;
 
 pub(crate) use crate::assist_context::{AssistContext, Assists};
@@ -68,7 +68,7 @@ pub struct GroupLabel(pub String);
 pub struct Assist {
     pub id: AssistId,
     /// Short description of the assist, as shown in the UI.
-    pub label: Label,
+    label: String,
     pub group: Option<GroupLabel>,
     /// Target ranges are used to sort assists: the smaller the target range,
     /// the more specific assist is, and so it should be sorted first.
@@ -82,6 +82,11 @@ pub struct ResolvedAssist {
 }
 
 impl Assist {
+    fn new(id: AssistId, label: String, group: Option<GroupLabel>, target: TextRange) -> Assist {
+        assert!(label.starts_with(char::is_uppercase));
+        Assist { id, label, group, target }
+    }
+
     /// Return all the assists applicable at the given position.
     ///
     /// Assists are returned in the "unresolved" state, that is only labels are
@@ -113,6 +118,10 @@ impl Assist {
         });
         acc.finish_resolved()
     }
+
+    pub fn label(&self) -> &str {
+        self.label.as_str()
+    }
 }
 
 mod handlers {
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 3c36c0e15d..1f85805d22 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -19,7 +19,7 @@ use syntax::{
 };
 use text_edit::TextEdit;
 
-use crate::{FileId, Label, SourceChange, SourceFileEdit};
+use crate::{FileId, SourceChange, SourceFileEdit};
 
 use self::fixes::DiagnosticWithFix;
 
@@ -34,15 +34,20 @@ pub struct Diagnostic {
 
 #[derive(Debug)]
 pub struct Fix {
-    pub label: Label,
+    pub label: String,
     pub source_change: SourceChange,
     /// Allows to trigger the fix only when the caret is in the range given
     pub fix_trigger_range: TextRange,
 }
 
 impl Fix {
-    fn new(label: &str, source_change: SourceChange, fix_trigger_range: TextRange) -> Self {
-        let label = Label::new(label);
+    fn new(
+        label: impl Into<String>,
+        source_change: SourceChange,
+        fix_trigger_range: TextRange,
+    ) -> Self {
+        let label = label.into();
+        assert!(label.starts_with(char::is_uppercase) && !label.ends_with('.'));
         Self { label, source_change, fix_trigger_range }
     }
 }
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index e3af6d5bc9..f37119e28b 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -88,7 +88,6 @@ pub use base_db::{
 pub use hir::{Documentation, Semantics};
 pub use ide_db::{
     change::AnalysisChange,
-    label::Label,
     line_index::{LineCol, LineIndex},
     search::SearchScope,
     source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
diff --git a/crates/ide_db/src/label.rs b/crates/ide_db/src/label.rs
deleted file mode 100644
index c0e89e72f5..0000000000
--- a/crates/ide_db/src/label.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-//! See `Label`
-use std::fmt;
-
-/// A type to specify UI label, like an entry in the list of assists. Enforces
-/// proper casing:
-///
-///    Frobnicate bar
-///
-/// Note the upper-case first letter and the absence of `.` at the end.
-#[derive(Clone)]
-pub struct Label(String);
-
-impl PartialEq<str> for Label {
-    fn eq(&self, other: &str) -> bool {
-        self.0 == other
-    }
-}
-
-impl PartialEq<&'_ str> for Label {
-    fn eq(&self, other: &&str) -> bool {
-        self == *other
-    }
-}
-
-impl From<Label> for String {
-    fn from(label: Label) -> String {
-        label.0
-    }
-}
-
-impl Label {
-    pub fn new(label: impl Into<String>) -> Label {
-        let label = label.into();
-        assert!(label.starts_with(char::is_uppercase) && !label.ends_with('.'));
-        Label(label)
-    }
-}
-
-impl fmt::Display for Label {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.0, f)
-    }
-}
-
-impl fmt::Debug for Label {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(&self.0, f)
-    }
-}
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs
index 70ada02f31..fd474cd0f4 100644
--- a/crates/ide_db/src/lib.rs
+++ b/crates/ide_db/src/lib.rs
@@ -2,7 +2,6 @@
 //!
 //! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search.
 
-pub mod label;
 pub mod line_index;
 pub mod symbol_index;
 pub mod change;
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 33e60b500a..67ca9f0552 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -782,9 +782,10 @@ fn handle_fixes(
         .filter_map(|d| d.fix)
         .filter(|fix| fix.fix_trigger_range.intersect(range).is_some())
     {
+        let title = fix.label;
         let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?;
         let action = lsp_ext::CodeAction {
-            title: fix.label.to_string(),
+            title,
             id: None,
             group: None,
             kind: Some(CodeActionKind::QUICKFIX),
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 643dcb4fcb..535de2f71a 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -704,7 +704,7 @@ pub(crate) fn unresolved_code_action(
     index: usize,
 ) -> Result<lsp_ext::CodeAction> {
     let res = lsp_ext::CodeAction {
-        title: assist.label.to_string(),
+        title: assist.label().to_string(),
         id: Some(format!("{}:{}", assist.id.0, index.to_string())),
         group: assist.group.filter(|_| snap.config.client_caps.code_action_group).map(|gr| gr.0),
         kind: Some(code_action_kind(assist.id.1)),
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index 265d192883..5d60f02190 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -1,5 +1,8 @@
 //! Missing batteries for standard libraries.
-use std::time::Instant;
+use std::{
+    sync::atomic::{AtomicUsize, Ordering},
+    time::Instant,
+};
 
 mod macros;
 
@@ -134,6 +137,31 @@ where
     left
 }
 
+pub struct RacyFlag(AtomicUsize);
+
+impl RacyFlag {
+    pub const fn new() -> RacyFlag {
+        RacyFlag(AtomicUsize::new(0))
+    }
+
+    pub fn get(&self, init: impl FnMut() -> bool) -> bool {
+        let mut init = Some(init);
+        self.get_impl(&mut || init.take().map_or(false, |mut f| f()))
+    }
+
+    fn get_impl(&self, init: &mut dyn FnMut() -> bool) -> bool {
+        match self.0.load(Ordering::Relaxed) {
+            0 => false,
+            1 => true,
+            _ => {
+                let res = init();
+                self.0.store(if res { 1 } else { 0 }, Ordering::Relaxed);
+                res
+            }
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;


Test patch:
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index c953925ecb..91c9d38c52 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -8,7 +8,7 @@ mod method_resolution;
 mod macros;
 mod display_source_code;
 
-use std::sync::Arc;
+use std::{env, sync::Arc};
 
 use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt};
 use expect::Expect;
@@ -22,12 +22,14 @@ use hir_def::{
     AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId,
 };
 use hir_expand::{db::AstDatabase, InFile};
-use stdx::format_to;
+use stdx::{format_to, RacyFlag};
 use syntax::{
     algo,
     ast::{self, AstNode},
     SyntaxNode,
 };
+use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
+use tracing_tree::HierarchicalLayer;
 
 use crate::{
     db::HirDatabase, display::HirDisplay, infer::TypeMismatch, test_db::TestDB, InferenceResult, Ty,
@@ -37,9 +39,12 @@ use crate::{
 // against snapshots of the expected results using expect. Use
 // `env UPDATE_EXPECT=1 cargo test -p hir_ty` to update the snapshots.
 
-fn setup_tracing() -> tracing::subscriber::DefaultGuard {
-    use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
-    use tracing_tree::HierarchicalLayer;
+fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> {
+    static ENABLE: RacyFlag = RacyFlag::new();
+    if !ENABLE.get(|| env::var("CHALK_DEBUG").is_ok()) {
+        return None;
+    }
+
     let filter = EnvFilter::from_env("CHALK_DEBUG");
     let layer = HierarchicalLayer::default()
         .with_indent_lines(true)
@@ -47,7 +52,7 @@ fn setup_tracing() -> tracing::subscriber::DefaultGuard {
         .with_indent_amount(2)
         .with_writer(std::io::stderr);
     let subscriber = Registry::default().with(filter).with(layer);
-    tracing::subscriber::set_default(subscriber)
+    Some(tracing::subscriber::set_default(subscriber))
 }
 
 fn check_types(ra_fixture: &str) {