ronantakizawa/codereview-bench huggingface dataset:
Repository: launchbadge/sqlx
File: sqlx-core/src/postgres/types/ltree.rs (Rust)

Code before:
impl Type<Postgres> for PgLTree {
    fn type_info() -> PgTypeInfo {
        PgTypeInfo::with_name("ltree")
    }
}

impl Encode<'_, Postgres> for PgLTree {
    fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
        buf.extend(1i8.to_le_bytes());
        buf.extend_display(self);

        IsNull::No
    }
}

impl<'r> Decode<'r, Postgres> for PgLTree {
    fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
        match value.format() {
            PgValueFormat::Binary => {
                let bytes = value.as_bytes()?;
                let version = i8::from_le_bytes([bytes[0]; 1]);
                if version != 1 {
                    return Err(Box::new(Error::InvalidLtreeVersion));
                }
                Ok(Self::from_str(std::str::from_utf8(&bytes[1..])?)?)
            }
            PgValueFormat::Text => Ok(Self::from_str(value.as_str()?)?),
        }
    }
}


Review comment (suggestion):
I could see a `Deref<Target = [String]>` impl being useful here as well. I wouldn't implement `DerefMut` as that would allow the user to break the invariants of the type.

Code after:
    }
}

impl FromStr for PgLTree {
    type Err = PgLTreeParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self {
            labels: s.split('.').map(|s| s.to_owned()).collect(),
        })
    }
}

impl Display for PgLTree {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        let mut iter = self.labels.iter();
        if let Some(label) = iter.next() {
            write!(f, "{}", label)?;
            for label in iter {
                write!(f, ".{}", label)?;
            }
        }
        Ok(())
    }
}

impl Deref for PgLTree {
    type Target = [String];

    fn deref(&self) -> &Self::Target {
        &self.labels
    }
}

impl Type<Postgres> for PgLTree {
    fn type_info() -> PgTypeInfo {
        // Since `ltree` is enabled by an extension, it does not have a stable OID.
        PgTypeInfo::with_name("ltree")
    }
}

impl PgHasArrayType for PgLTree {
    fn array_type_info() -> PgTypeInfo {
        PgTypeInfo::with_name("_ltree")
    }
}

impl Encode<'_, Postgres> for PgLTree {
    fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
        buf.extend(1i8.to_le_bytes());
        write!(buf, "{}", self)
Repository: launchbadge/sqlx
File: sqlx-core/src/postgres/types/ltree.rs (Rust)

Code before:

impl IntoIterator for PgLTree {
    type Item = String;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.labels.into_iter()
    }
}

impl FromStr for PgLTree {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Error> {
        Ok(Self {
            labels: s.split('.').map(|s| s.to_owned()).collect(),
        })
    }
}

impl Display for PgLTree {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        let mut iter = self.labels.iter();
        if let Some(label) = iter.next() {
            write!(f, "{}", label)?;
            while let Some(label) = iter.next() {
                write!(f, ".{}", label)?;
            }
        }
        Ok(())
    }
}

impl Type<Postgres> for PgLTree {
    fn type_info() -> PgTypeInfo {
        PgTypeInfo::with_name("ltree")
    }
}

impl Encode<'_, Postgres> for PgLTree {
    fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
        buf.extend(1i8.to_le_bytes());
        buf.extend_display(self);

        IsNull::No
    }
}

impl<'r> Decode<'r, Postgres> for PgLTree {
    fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
        match value.format() {

Review comment (suggestion):
```suggestion
            for label in iter {
```

Code after:
        let mut ltree = Self::default();
        for label in labels {
            ltree.push(label.into())?;
        }
        Ok(ltree)
    }

    /// push a label to ltree
    pub fn push(&mut self, label: String) -> Result<(), PgLTreeParseError> {
        if label.len() <= 256
            && label
                .bytes()
                .all(|c| c.is_ascii_alphabetic() || c.is_ascii_digit() || c == b'_')
        {
            self.labels.push(label);
            Ok(())
        } else {
            Err(PgLTreeParseError::InvalidLtreeLabel)
        }
    }

    /// pop a label from ltree
    pub fn pop(&mut self) -> Option<String> {
        self.labels.pop()
    }
}

impl IntoIterator for PgLTree {
    type Item = String;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.labels.into_iter()
    }
}

impl FromStr for PgLTree {
    type Err = PgLTreeParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self {
            labels: s.split('.').map(|s| s.to_owned()).collect(),
        })
    }
}

impl Display for PgLTree {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        let mut iter = self.labels.iter();
        if let Some(label) = iter.next() {
            write!(f, "{}", label)?;
Repository: launchbadge/sqlx
File: sqlx-core/src/postgres/arguments.rs (Rust)

Code before:
        self.patches.push((offset, index, Box::new(callback)));
    }

    // Extends the inner buffer by enough space to have an OID
    // Remembers where the OID goes and type name for the OID
    pub(crate) fn patch_type_by_name(&mut self, type_name: &UStr) {
        let offset = self.len();

        self.extend_from_slice(&0_u32.to_be_bytes());
        self.type_holes.push((offset, type_name.clone()));
    }

    pub(crate) fn extend_display<T: fmt::Display>(&mut self, value: T) {
        struct VecFmt<'a>(&'a mut Vec<u8>);

        impl<'a> fmt::Write for VecFmt<'a> {
            fn write_char(&mut self, c: char) -> fmt::Result {
                self.write_str(c.encode_utf8(&mut [0u8; 4]))
            }

            fn write_str(&mut self, s: &str) -> fmt::Result {
                self.0.extend_from_slice(s.as_bytes());
                Ok(())
            }
        }

        write!(self.buffer, "{}", value)
            .expect("Display implementation panicked while writing to PgArgumentBuffer");
    }
}

impl Deref for PgArgumentBuffer {
    type Target = Vec<u8>;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.buffer
    }
}

impl DerefMut for PgArgumentBuffer {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.buffer
    }
}


Review comment (suggestion):
I didn't know of `write!` working with `Vec<u8>`. This is not needed anymore

```suggestion
```

Code after:

    // Extends the inner buffer by enough space to have an OID
    // Remembers where the OID goes and type name for the OID
    pub(crate) fn patch_type_by_name(&mut self, type_name: &UStr) {
        let offset = self.len();

        self.extend_from_slice(&0_u32.to_be_bytes());
        self.type_holes.push((offset, type_name.clone()));
    }
}

impl Deref for PgArgumentBuffer {
    type Target = Vec<u8>;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.buffer
    }
}

impl DerefMut for PgArgumentBuffer {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.buffer
    }
}
Repository: launchbadge/sqlx
File: tests/postgres/types.rs (Rust)

Code before:
        == PgInterval {
            months: 0,
            days: 0,
            microseconds: (3 * 3_600 + 10 * 60 + 20) * 1_000_000 + 116100
        },
));

test_prepared_type!(money<PgMoney>(Postgres, "123.45::money" == PgMoney(12345)));

test_prepared_type!(money_vec<Vec<PgMoney>>(Postgres,
    "array[123.45,420.00,666.66]::money[]" == vec![PgMoney(12345), PgMoney(42000), PgMoney(66666)],
));

test_type!(ltree<sqlx::postgres::types::PgLTree>(Postgres,
    "'Foo.Bar.Baz.Quux'::ltree" == sqlx::postgres::types::PgLTree::from_str("Foo.Bar.Baz.Quux").unwrap(),
    "'Alpha.Beta.Delta.Gamma'::ltree" == sqlx::postgres::types::PgLTree::from_iter(["Alpha", "Beta", "Delta", "Gamma"]).unwrap(),
));

test_type!(ltree_vec<Vec<sqlx::postgres::types::PgLTree>>(Postgres,
    "array['Foo.Bar.Baz.Quux', 'Alpha.Beta.Delta.Gamma']::ltree[]" ==
        vec![
            sqlx::postgres::types::PgLTree::from_str("Foo.Bar.Baz.Quux").unwrap(),
            sqlx::postgres::types::PgLTree::from_iter(["Alpha", "Beta", "Delta", "Gamma"]).unwrap()
        ]
));


Review comment (suggestion):
I didn't realize this until I checked but Gamma actually comes before Delta in the Greek alphabet. 

You don't need to change this, it's just an observation.

Code after:
        == PgInterval {
            months: 0,
            days: 0,
            microseconds: (3 * 3_600 + 10 * 60 + 20) * 1_000_000 + 116100
        },
));

test_prepared_type!(money<PgMoney>(Postgres, "123.45::money" == PgMoney(12345)));

test_prepared_type!(money_vec<Vec<PgMoney>>(Postgres,
    "array[123.45,420.00,666.66]::money[]" == vec![PgMoney(12345), PgMoney(42000), PgMoney(66666)],
));

// FIXME: needed to disable `ltree` tests in Postgres 9.6
// but `PgLTree` should just fall back to text format
#[cfg(postgres_14)]
test_type!(ltree<sqlx::postgres::types::PgLTree>(Postgres,
    "'Foo.Bar.Baz.Quux'::ltree" == sqlx::postgres::types::PgLTree::from_str("Foo.Bar.Baz.Quux").unwrap(),
    "'Alpha.Beta.Delta.Gamma'::ltree" == sqlx::postgres::types::PgLTree::from_iter(["Alpha", "Beta", "Delta", "Gamma"]).unwrap(),
));

// FIXME: needed to disable `ltree` tests in Postgres 9.6
// but `PgLTree` should just fall back to text format
#[cfg(postgres_14)]
test_type!(ltree_vec<Vec<sqlx::postgres::types::PgLTree>>(Postgres,
    "array['Foo.Bar.Baz.Quux', 'Alpha.Beta.Delta.Gamma']::ltree[]" ==
        vec![
            sqlx::postgres::types::PgLTree::from_str("Foo.Bar.Baz.Quux").unwrap(),
            sqlx::postgres::types::PgLTree::from_iter(["Alpha", "Beta", "Delta", "Gamma"]).unwrap()
        ]
));
Repository: launchbadge/sqlx
File: sqlx-core/src/postgres/types/mod.rs (Rust)

Code before:

#[cfg(feature = "bit-vec")]
mod bit_vec;

pub use array::PgHasArrayType;
pub use interval::PgInterval;
pub use lquery::PgLQuery;
pub use lquery::PgLQueryLevel;
pub use lquery::PgLQueryVariant;
pub use lquery::PgLQueryVariantFlag;
pub use ltree::PgLTree;
pub use ltree::PgLTreeLabel;
pub use ltree::PgLTreeParseError;
pub use money::PgMoney;
pub use range::PgRange;

#[cfg(any(feature = "chrono", feature = "time"))]
pub use time_tz::PgTimeTz;

// used in derive(Type) for `struct`
// but the interface is not considered part of the public API
#[doc(hidden)]
pub use record::{PgRecordDecoder, PgRecordEncoder};

// Type::compatible impl appropriate for arrays
fn array_compatible<E: Type<Postgres>>(ty: &PgTypeInfo) -> bool {
    // we require the declared type to be an _array_ with an
    // element type that is acceptable
    if let PgTypeKind::Array(element) = &ty.kind() {
        return E::compatible(&element);
    }

    false
}


Review comment (suggestion):
This is because `serde_json::RawValue` is unsized:

```rust
pub struct RawValue {
    json: str,
}
```

Code after:

#[cfg(feature = "bit-vec")]
mod bit_vec;

pub use array::PgHasArrayType;
pub use interval::PgInterval;
pub use lquery::PgLQuery;
pub use lquery::PgLQueryLevel;
pub use lquery::PgLQueryVariant;
pub use lquery::PgLQueryVariantFlag;
pub use ltree::PgLTree;
pub use ltree::PgLTreeLabel;
pub use ltree::PgLTreeParseError;
pub use money::PgMoney;
pub use range::PgRange;

#[cfg(any(feature = "chrono", feature = "time"))]
pub use time_tz::PgTimeTz;

// used in derive(Type) for `struct`
// but the interface is not considered part of the public API
#[doc(hidden)]
pub use record::{PgRecordDecoder, PgRecordEncoder};

// Type::compatible impl appropriate for arrays
fn array_compatible<E: Type<Postgres> + ?Sized>(ty: &PgTypeInfo) -> bool {
    // we require the declared type to be an _array_ with an
    // element type that is acceptable
    if let PgTypeKind::Array(element) = &ty.kind() {
        return E::compatible(&element);
    }

    false
}
Repository: launchbadge/sqlx
File: sqlx-core/src/postgres/types/ltree.rs (Rust)

Code before:
/// CREATE EXTENSION IF NOT EXISTS "ltree";
/// ```
#[derive(Clone, Debug, Default, PartialEq)]
pub struct PgLTree {
    labels: Vec<PgLTreeLabel>,
}

impl PgLTree {
    /// creates default/empty ltree
    pub fn new() -> Self {
        Self::default()
    }

    /// creates ltree from a [Vec<PgLTreeLabel>]
    pub fn from(labels: Vec<PgLTreeLabel>) -> Self {
        Self { labels }
    }

    /// creates ltree from an iterator with checking labels
    pub fn from_iter<I, S>(labels: I) -> Result<Self, PgLTreeParseError>
    where
        String: From<S>,
        I: IntoIterator<Item = S>,
    {
        let mut ltree = Self::default();
        for label in labels {
            ltree.push(String::from(label).parse()?);
        }
        Ok(ltree)
    }

    /// push a label to ltree
    pub fn push(&mut self, label: PgLTreeLabel) {
        self.labels.push(label);
    }

    /// pop a label from ltree
    pub fn pop(&mut self) -> Option<PgLTreeLabel> {
        self.labels.pop()
    }
}

impl IntoIterator for PgLTree {
    type Item = PgLTreeLabel;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.labels.into_iter()
    }
}


Review comment (suggestion):
Since you're calling `parse()` on it, we don't need to copy it to an owned string. I would make this `S: AsRef<str>` and then do `label.as_ref().parse()` in the `for` loop.

Code after:
/// ### Note: Extension Required
/// The `ltree` extension is not enabled by default in Postgres. You will need to do so explicitly:
///
/// ```ignore
/// CREATE EXTENSION IF NOT EXISTS "ltree";
/// ```
#[derive(Clone, Debug, Default, PartialEq)]
pub struct PgLTree {
    labels: Vec<PgLTreeLabel>,
}

impl PgLTree {
    /// creates default/empty ltree
    pub fn new() -> Self {
        Self::default()
    }

    /// creates ltree from a [Vec<PgLTreeLabel>]
    pub fn from(labels: Vec<PgLTreeLabel>) -> Self {
        Self { labels }
    }

    /// creates ltree from an iterator with checking labels
    pub fn from_iter<I, S>(labels: I) -> Result<Self, PgLTreeParseError>
    where
        String: From<S>,
        I: IntoIterator<Item = S>,
    {
        let mut ltree = Self::default();
        for label in labels {
            ltree.push(PgLTreeLabel::new(label)?);
        }
        Ok(ltree)
    }

    /// push a label to ltree
    pub fn push(&mut self, label: PgLTreeLabel) {
        self.labels.push(label);
    }

    /// pop a label from ltree
    pub fn pop(&mut self) -> Option<PgLTreeLabel> {
        self.labels.pop()
    }
}

impl IntoIterator for PgLTree {
    type Item = PgLTreeLabel;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
Repository: launchbadge/sqlx
File: sqlx-core/src/postgres/types/ltree.rs (Rust)

Code before:
    }

    /// creates ltree from a [Vec<PgLTreeLabel>]
    pub fn from(labels: Vec<PgLTreeLabel>) -> Self {
        Self { labels }
    }

    /// creates ltree from an iterator with checking labels
    pub fn from_iter<I, S>(labels: I) -> Result<Self, PgLTreeParseError>
    where
        String: From<S>,
        I: IntoIterator<Item = S>,
    {
        let mut ltree = Self::default();
        for label in labels {
            ltree.push(String::from(label).parse()?);
        }
        Ok(ltree)
    }

    /// push a label to ltree
    pub fn push(&mut self, label: PgLTreeLabel) {
        self.labels.push(label);
    }

    /// pop a label from ltree
    pub fn pop(&mut self) -> Option<PgLTreeLabel> {
        self.labels.pop()
    }
}

impl IntoIterator for PgLTree {
    type Item = PgLTreeLabel;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.labels.into_iter()
    }
}

impl FromStr for PgLTree {
    type Err = PgLTreeParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self {
            labels: s
                .split('.')
                .map(|s| PgLTreeLabel::new(s))
                .collect::<Result<Vec<_>, Self::Err>>()?,
        })
    }

Review comment (suggestion):
This is unfortunately a breaking change, though, and will need to wait for 0.6.0. I don't have an exact timeline on that right now but I expect it to be the next release we do, probably in a month or so.

Code after:
impl PgLTree {
    /// creates default/empty ltree
    pub fn new() -> Self {
        Self::default()
    }

    /// creates ltree from a [Vec<PgLTreeLabel>]
    pub fn from(labels: Vec<PgLTreeLabel>) -> Self {
        Self { labels }
    }

    /// creates ltree from an iterator with checking labels
    pub fn from_iter<I, S>(labels: I) -> Result<Self, PgLTreeParseError>
    where
        String: From<S>,
        I: IntoIterator<Item = S>,
    {
        let mut ltree = Self::default();
        for label in labels {
            ltree.push(PgLTreeLabel::new(label)?);
        }
        Ok(ltree)
    }

    /// push a label to ltree
    pub fn push(&mut self, label: PgLTreeLabel) {
        self.labels.push(label);
    }

    /// pop a label from ltree
    pub fn pop(&mut self) -> Option<PgLTreeLabel> {
        self.labels.pop()
    }
}

impl IntoIterator for PgLTree {
    type Item = PgLTreeLabel;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.labels.into_iter()
    }
}

impl FromStr for PgLTree {
    type Err = PgLTreeParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self {
            labels: s
                .split('.')
Repository: launchbadge/sqlx
File: sqlx-core/src/query_builder.rs (Rust)

Code before:
pub struct QueryBuilder<'a, DB>
where
    DB: Database,
{
    query: String,
    arguments: Option<<DB as HasArguments<'a>>::Arguments>,
    variable_count: u16,
}

impl<'a, DB: Database> QueryBuilder<'a, DB>
where
    DB: Database,
{
    pub fn new(init: impl Into<String>) -> Self
    where
        <DB as HasArguments<'a>>::Arguments: Default,
    {
        QueryBuilder {
            query: init.into(),
            arguments: Some(Default::default()),
            variable_count: 0,
        }
    }

    pub fn push(&mut self, sql: impl Display) -> &mut Self {
        self.query.push_str(&format!(" {}", sql));

        self
    }

    pub fn push_bind<A>(&mut self, value: A) -> &mut Self
    where
        A: 'a + Encode<'a, DB> + Send + Type<DB>,
    {
        match self.arguments {
            Some(ref mut arguments) => {
                arguments.add(value);
                self.variable_count += 1;
                self.query
                    .push_str(&arguments.place_holder(self.variable_count));
            }
            None => panic!("Arguments taken already"),
        }

        self
    }

    pub fn build(&mut self) -> Query<'_, DB, <DB as HasArguments<'a>>::Arguments> {
        Query {
            statement: Either::Left(&self.query),
            arguments: match self.arguments.take() {

Review comment (bug):
```suggestion
        // An error here is also highly unlikely but ignoring it is a code smell.
        write!(self.query, " {}", sql).expect("error formatting `sql`");
```

It is a bit weird to insert a space automatically, though. What if someone is trying to concatenate an identifier using this method, or is building a string literal where formatting matters? This violates the principle of least surprise.

Code after:

pub struct QueryBuilder<'a, DB>
where
    DB: Database,
{
    query: String,
    arguments: Option<<DB as HasArguments<'a>>::Arguments>,
}

impl<'a, DB: Database> QueryBuilder<'a, DB>
where
    DB: Database,
{
    pub fn new(init: impl Into<String>) -> Self
    where
        <DB as HasArguments<'a>>::Arguments: Default,
    {
        QueryBuilder {
            query: init.into(),
            arguments: Some(Default::default()),
        }
    }

    pub fn push(&mut self, sql: impl Display) -> &mut Self {
        if self.arguments.is_none() {
            panic!("QueryBuilder must be reset before reuse")
        }

        write!(self.query, "{}", sql).expect("error formatting `sql`");

        self
    }

    pub fn push_bind<A>(&mut self, value: A) -> &mut Self
    where
        A: 'a + Encode<'a, DB> + Send + Type<DB>,
    {
        match self.arguments {
            Some(ref mut arguments) => {
                arguments.add(value);

                arguments
                    .format_placeholder(&mut self.query)
                    .expect("error in format_placeholder");
            }
            None => panic!("Arguments taken already"),
        }

        self
    }
Repository: launchbadge/sqlx
File: sqlx-core/src/pool/inner.rs (Rust)

Code before:
        };

        let pool = Arc::new(pool);

        spawn_reaper(&pool);

        pool
    }

    pub(super) fn size(&self) -> u32 {
        self.size.load(Ordering::Acquire)
    }

    pub(super) fn num_idle(&self) -> usize {
        // NOTE: This is very expensive
        self.idle_conns.len()
    }

    pub(super) fn is_closed(&self) -> bool {
        self.is_closed.load(Ordering::Acquire)
    }

    pub fn options(&self) -> &PoolOptions<DB> {
        &self.options
    }

    pub fn connect_options(&self) -> &<DB::Connection as Connection>::Options {
        &self.connect_options
    }

    pub(super) async fn close(self: &Arc<Self>) {
        let already_closed = self.is_closed.swap(true, Ordering::AcqRel);

        if !already_closed {
            // if we were the one to mark this closed, release enough permits to wake all waiters
            // we can't just do `usize::MAX` because that would overflow
            // and we can't do this more than once cause that would _also_ overflow
            self.semaphore.release(WAKE_ALL_PERMITS);
            self.on_closed.notify(usize::MAX);
        }

        // wait for all permits to be released
        let _permits = self
            .semaphore
            .acquire(WAKE_ALL_PERMITS + (self.options.max_connections as usize))
            .await;

        while let Some(idle) = self.idle_conns.pop() {
            let _ = idle.live.float((*self).clone()).close().await;
        }
    }

Review comment (suggestion):
Adding these to `SharedPool` doesn't do anything. You need to add getters to `Pool` itself in `src/pool/mod.rs`

Code after:
        };

        let pool = Arc::new(pool);

        spawn_reaper(&pool);

        pool
    }

    pub(super) fn size(&self) -> u32 {
        self.size.load(Ordering::Acquire)
    }

    pub(super) fn num_idle(&self) -> usize {
        // NOTE: This is very expensive
        self.idle_conns.len()
    }

    pub(super) fn is_closed(&self) -> bool {
        self.is_closed.load(Ordering::Acquire)
    }

    pub(super) async fn close(self: &Arc<Self>) {
        let already_closed = self.is_closed.swap(true, Ordering::AcqRel);

        if !already_closed {
            // if we were the one to mark this closed, release enough permits to wake all waiters
            // we can't just do `usize::MAX` because that would overflow
            // and we can't do this more than once cause that would _also_ overflow
            self.semaphore.release(WAKE_ALL_PERMITS);
            self.on_closed.notify(usize::MAX);
        }

        // wait for all permits to be released
        let _permits = self
            .semaphore
            .acquire(WAKE_ALL_PERMITS + (self.options.max_connections as usize))
            .await;

        while let Some(idle) = self.idle_conns.pop() {
            let _ = idle.live.float((*self).clone()).close().await;
        }
    }

    #[inline]
    pub(super) fn try_acquire(self: &Arc<Self>) -> Option<Floating<DB, Idle<DB>>> {
        if self.is_closed() {
            return None;
        }

        let permit = self.semaphore.try_acquire(1)?;