Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broken method resolution for arc-swap + diesel #127306

Open
weiznich opened this issue Jul 4, 2024 · 1 comment
Open

Broken method resolution for arc-swap + diesel #127306

weiznich opened this issue Jul 4, 2024 · 1 comment
Labels
C-bug Category: This is a bug. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@weiznich
Copy link
Contributor

weiznich commented Jul 4, 2024

I tried this code:

use arc_swap::ArcSwap; // arc-swap = "1.7.1"
use diesel_async::RunQueryDsl; // diesel-async = "0.4.1"
use std::sync::Arc;

fn issue(arc: ArcSwap<Arc<String>>) {
    let v = arc.load();
}

I expected to see this happen: Code compiles without error as ArcSwap::load() exists

Instead, this happened: Code fails to compile with the following error:

error[E0277]: the trait bound `ArcSwapAny<Arc<Arc<String>>>: diesel::query_builder::Query` is not satisfied
 --> src/main.rs:7:17
  |
7 |     let v = arc.load();
  |                 ^^^^ the trait `diesel::query_builder::Query` is not implemented for `ArcSwapAny<Arc<Arc<String>>>`, which is required by `ArcSwapAny<Arc<Arc<String>>>: LoadQuery<'_, _, _>`
  |
  = help: the following other types implement trait `diesel::query_builder::Query`:
            &'a T
            diesel::expression::sql_literal::SqlLiteral<ST, T>
            diesel::expression::sql_literal::UncheckedBind<Q, Value>
            diesel::query_builder::combination_clause::CombinationClause<Combinator, Rule, Source, Rhs>
            diesel::query_builder::delete_statement::DeleteStatement<T, U, diesel::query_builder::returning_clause::ReturningClause<Ret>>
            diesel::query_builder::insert_statement::InsertStatement<T, U, Op, diesel::query_builder::returning_clause::ReturningClause<Ret>>
            diesel::query_builder::select_statement::SelectStatement<F, S, D, W, O, LOf, G, H, LC>
            diesel::query_builder::select_statement::boxed::BoxedSelectStatement<'a, ST, QS, DB, GB>
          and 6 others
  = note: required for `ArcSwapAny<Arc<Arc<String>>>` to implement `diesel::query_builder::AsQuery`
  = note: required for `ArcSwapAny<Arc<Arc<String>>>` to implement `LoadQuery<'_, _, _>`

error[E0277]: the trait bound `ArcSwapAny<Arc<Arc<String>>>: diesel::query_builder::QueryFragment<_>` is not satisfied
 --> src/main.rs:7:17
  |
7 |     let v = arc.load();
  |                 ^^^^ the trait `diesel::query_builder::QueryFragment<_>` is not implemented for `ArcSwapAny<Arc<Arc<String>>>`, which is required by `ArcSwapAny<Arc<Arc<String>>>: LoadQuery<'_, _, _>`
  |
  = help: the following other types implement trait `diesel::query_builder::QueryFragment<DB, SP>`:
            <&'a T as diesel::query_builder::QueryFragment<DB>>
            <() as diesel::query_builder::QueryFragment<DB>>
            <(T0, T1) as diesel::query_builder::QueryFragment<__DB>>
            <(T0, T1, T2) as diesel::query_builder::QueryFragment<__DB>>
            <(T0, T1, T2, T3) as diesel::query_builder::QueryFragment<__DB>>
            <(T0, T1, T2, T3, T4) as diesel::query_builder::QueryFragment<__DB>>
            <(T0, T1, T2, T3, T4, T5) as diesel::query_builder::QueryFragment<__DB>>
            <(T0, T1, T2, T3, T4, T5, T6) as diesel::query_builder::QueryFragment<__DB>>
          and 160 others
  = note: required for `ArcSwapAny<Arc<Arc<String>>>` to implement `LoadQuery<'_, _, _>`

error[E0277]: the trait bound `ArcSwapAny<Arc<Arc<String>>>: diesel::query_builder::query_id::QueryId` is not satisfied
 --> src/main.rs:7:17
  |
7 |     let v = arc.load();
  |                 ^^^^ the trait `diesel::query_builder::query_id::QueryId` is not implemented for `ArcSwapAny<Arc<Arc<String>>>`, which is required by `ArcSwapAny<Arc<Arc<String>>>: LoadQuery<'_, _, _>`
  |
  = help: the following other types implement trait `diesel::query_builder::query_id::QueryId`:
            &'a T
            ()
            (T0, T1)
            (T0, T1, T2)
            (T0, T1, T2, T3)
            (T0, T1, T2, T3, T4)
            (T0, T1, T2, T3, T4, T5)
            (T0, T1, T2, T3, T4, T5, T6)
          and 148 others
  = note: required for `ArcSwapAny<Arc<Arc<String>>>` to implement `LoadQuery<'_, _, _>`

error[E0277]: the trait bound `ArcSwapAny<Arc<Arc<String>>>: LoadQuery<'_, _, _>` is not satisfied
   --> src/main.rs:7:17
    |
7   |     let v = arc.load();
    |                 ^^^^ the trait `diesel::query_builder::QueryFragment<_>` is not implemented for `ArcSwapAny<Arc<Arc<String>>>`, which is required by `ArcSwapAny<Arc<Arc<String>>>: LoadQuery<'_, _, _>`
    |
    = note: required for `ArcSwapAny<Arc<Arc<String>>>` to implement `LoadQuery<'_, _, _>`
note: required by a bound in `diesel_async::RunQueryDsl::load`
   --> /home/weiznich/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-async-0.4.1/src/run_query_dsl/mod.rs:338:15
    |
331 |     fn load<'query, 'conn, U>(
    |        ---- required by a bound in this associated function
...
338 |         Self: methods::LoadQuery<'query, Conn, U> + 'query,
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`

error[E0061]: this method takes 1 argument but 0 arguments were supplied
   --> src/main.rs:7:17
    |
7   |     let v = arc.load();
    |                 ^^^^-- an argument of type `&mut _` is missing
    |
note: method defined here
   --> /home/weiznich/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-async-0.4.1/src/run_query_dsl/mod.rs:331:8
    |
331 |     fn load<'query, 'conn, U>(
    |        ^^^^
help: provide the argument
    |
7   |     let v = arc.load(/* conn */);
    |                     ~~~~~~~~~~~~

warning: unused import: `arc_swap::access::Access`
 --> src/main.rs:1:5
  |
1 | use arc_swap::access::Access;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

The method provided by diesel does clearly not apply as:

  • It takes a different number of arguments
  • The trait bounds on the message are not fulfilled.

Meta

rustc --version --verbose:

rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: x86_64-unknown-linux-gnu
release: 1.79.0
LLVM version: 18.1.7

(Although the same behavior can be observed with the latest nightly compiler)

Backtrace

<backtrace>

@weiznich weiznich added the C-bug Category: This is a bug. label Jul 4, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jul 4, 2024
@saethlin saethlin added T-types Relevant to the types team, which will review and decide on the PR/issue. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jul 5, 2024
@theemathas
Copy link

Minimized reproduction:

trait Requirement {}

trait Extension {
    fn foo(self, x: i32)
    where
        Self: Requirement;
}

impl<T> Extension for T {
    fn foo(self)
    where
        Self: Requirement,
    {
    }
}

struct Thing;

impl Thing {
    fn foo(&self) {} // Note: &self, not self
}

fn what(x: Thing) {
    x.foo()
}
Error output
   Compiling playground v0.0.1 (/playground)
error[E0050]: method `foo` has 1 parameter but the declaration in trait `Extension::foo` has 2
  --> src/lib.rs:10:12
   |
4  |     fn foo(self, x: i32)
   |            ------------ trait requires 2 parameters
...
10 |     fn foo(self)
   |            ^^^^ expected 2 parameters, found 1

error[E0277]: the trait bound `Thing: Requirement` is not satisfied
  --> src/lib.rs:24:7
   |
24 |     x.foo()
   |       ^^^ the trait `Requirement` is not implemented for `Thing`
   |
help: this trait has no implementations, consider adding one
  --> src/lib.rs:1:1
   |
1  | trait Requirement {}
   | ^^^^^^^^^^^^^^^^^
note: required by a bound in `Extension::foo`
  --> src/lib.rs:6:15
   |
4  |     fn foo(self, x: i32)
   |        --- required by a bound in this associated function
5  |     where
6  |         Self: Requirement;
   |               ^^^^^^^^^^^ required by this bound in `Extension::foo`

error[E0061]: this method takes 1 argument but 0 arguments were supplied
  --> src/lib.rs:24:7
   |
24 |     x.foo()
   |       ^^^-- an argument of type `i32` is missing
   |
note: method defined here
  --> src/lib.rs:4:8
   |
4  |     fn foo(self, x: i32)
   |        ^^^
help: provide the argument
   |
24 |     x.foo(/* i32 */)
   |          ~~~~~~~~~~~

Some errors have detailed explanations: E0050, E0061, E0277.
For more information about an error, try `rustc --explain E0050`.
error: could not compile `playground` (lib) due to 3 previous errors

This happens because, when resolving the method call, rust checks calling the method on Thing before trying to call the method on &Thing. See the reference, which states that "This process does not take into account the mutability or lifetime of the receiver, or whether a method is unsafe." Is appears that this process also doesn't take into account the where bounds on the method.

This can be worked around by using the disambiguated function call syntax, e.g. Thing::foo(&x)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants