From f952dc61d108bef116657aa39f0ae043054e9bf5 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sat, 31 Jul 2021 18:25:45 +0300
Subject: [PATCH] internal: add API to check what are the max limits in
 practice

---
 crates/hir_expand/src/db.rs |  4 +++-
 crates/limit/Cargo.toml     |  4 +++-
 crates/limit/src/lib.rs     | 31 +++++++++++++++++++++++++++++--
 3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 7c83fcd639c..ee64564430e 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -22,7 +22,9 @@ use crate::{
 ///
 /// If an invocation produces more tokens than this limit, it will not be stored in the database and
 /// an error will be emitted.
-const TOKEN_LIMIT: Limit = Limit::new(524288);
+///
+/// Actual max for `analysis-stats .` at some point: 30672.
+static TOKEN_LIMIT: Limit = Limit::new(524_288);
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum TokenExpander {
diff --git a/crates/limit/Cargo.toml b/crates/limit/Cargo.toml
index 7676f3644b3..cb3ccbd73cf 100644
--- a/crates/limit/Cargo.toml
+++ b/crates/limit/Cargo.toml
@@ -6,4 +6,6 @@ license = "MIT OR Apache-2.0"
 authors = ["rust-analyzer developers"]
 edition = "2018"
 
-[dependencies]
+[features]
+tracking = []
+default = ["tracking"]
diff --git a/crates/limit/src/lib.rs b/crates/limit/src/lib.rs
index 8c96c748dbf..ace7ef7239b 100644
--- a/crates/limit/src/lib.rs
+++ b/crates/limit/src/lib.rs
@@ -1,15 +1,26 @@
 //! limit defines a struct to enforce limits.
 
+use std::sync::atomic::AtomicUsize;
+
 /// Represents a struct used to enforce a numerical limit.
 pub struct Limit {
     upper_bound: usize,
+    #[allow(unused)]
+    max: AtomicUsize,
 }
 
 impl Limit {
     /// Creates a new limit.
     #[inline]
     pub const fn new(upper_bound: usize) -> Self {
-        Self { upper_bound }
+        Self { upper_bound, max: AtomicUsize::new(0) }
+    }
+
+    /// Creates a new limit.
+    #[inline]
+    #[cfg(feature = "tracking")]
+    pub const fn new_tracking(upper_bound: usize) -> Self {
+        Self { upper_bound, max: AtomicUsize::new(1) }
     }
 
     /// Gets the underlying numeric limit.
@@ -21,10 +32,26 @@ impl Limit {
     /// Checks whether the given value is below the limit.
     /// Returns `Ok` when `other` is below `self`, and `Err` otherwise.
     #[inline]
-    pub const fn check(&self, other: usize) -> Result<(), ()> {
+    pub fn check(&self, other: usize) -> Result<(), ()> {
         if other > self.upper_bound {
             Err(())
         } else {
+            #[cfg(feature = "tracking")]
+            loop {
+                use std::sync::atomic::Ordering;
+                let old_max = self.max.load(Ordering::Relaxed);
+                if other <= old_max || old_max == 0 {
+                    break;
+                }
+                if self
+                    .max
+                    .compare_exchange(old_max, other, Ordering::Relaxed, Ordering::Relaxed)
+                    .is_ok()
+                {
+                    eprintln!("new max: {}", other);
+                }
+            }
+
             Ok(())
         }
     }